Implement 'define' statement for defining constants globally.
The build was successful. Details

This commit is contained in:
Rafal Kupiec 2019-05-04 17:08:09 +02:00
parent ab8bf48485
commit b36510943d
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
4 changed files with 68 additions and 1 deletions

View File

@ -964,6 +964,67 @@ PH7_PRIVATE sxi32 PH7_CompileClosure(ph7_gen_state *pGen, sxi32 iCompileFlag) {
/* Node successfully compiled */
return SXRET_OK;
}
/*
* Expression tree validator callback used by the 'define' statement.
*/
static sxi32 GenStateDefineNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) {
if(pRoot->xCode != PH7_CompileArray && pRoot->xCode != PH7_CompileLiteral && pRoot->xCode != PH7_CompileNumLiteral &&
pRoot->xCode != PH7_CompileSimpleString && pRoot->xCode != PH7_CompileString) {
/* Unexpected expression */
PH7_GenCompileError(&(*pGen), E_ERROR, pRoot->pStart ? pRoot->pStart->nLine : 0,
"Define: Expecting a constant simple value, not expression");
}
return SXRET_OK;
}
/*
* Compile a global 'define' construct.
* A global constant, defined in global scope can be accessible from any place.
*/
PH7_PRIVATE sxi32 PH7_CompileDefine(ph7_gen_state *pGen, sxi32 iFlags) {
SySet *pConsCode, *pInstrContainer;
SyString *pName;
sxi32 rc;
/* Jump the 'define' keyword */
pGen->pIn++;
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_ID | PH7_TK_KEYWORD)) == 0) {
/* Invalid variable name */
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Invalid constant name");
}
/* Extract constant name */
pName = &pGen->pIn->sData;
if(PH7_GenStateIsReservedConstant(pName)) {
/* Reserved constant */
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "define: Cannot redeclare a reserved constant '%z'", pName);
}
/* Advance the stream cursor */
pGen->pIn++;
/* Allocate a new constant value container */
pConsCode = (SySet *)SyMemBackendPoolAlloc(&pGen->pVm->sAllocator, sizeof(SySet));
if(pConsCode == 0) {
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "PH7 engine is running out-of-memory");
}
SySetInit(pConsCode, &pGen->pVm->sAllocator, sizeof(VmInstr));
/* Swap bytecode container */
pInstrContainer = PH7_VmGetByteCodeContainer(pGen->pVm);
PH7_VmSetByteCodeContainer(pGen->pVm, pConsCode);
/* Compile constant value */
rc = PH7_CompileExpr(&(*pGen), 0, GenStateDefineNodeValidator);
/* Emit the done instruction */
PH7_VmEmitInstr(pGen->pVm, pGen->pIn->nLine, PH7_OP_DONE, (rc != SXERR_EMPTY ? 1 : 0), 1, 0, 0);
PH7_VmSetByteCodeContainer(pGen->pVm, pInstrContainer);
if(rc == SXERR_ABORT) {
/* Don't worry about freeing memory, everything will be released shortly */
return SXERR_ABORT;
}
SySetSetUserData(pConsCode, pGen->pVm);
/* Register the global constant */
rc = PH7_VmRegisterConstant(pGen->pVm, pName, PH7_VmExpandConstantValue, pConsCode, TRUE);
if(rc != SXRET_OK) {
SySetRelease(pConsCode);
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pConsCode);
}
return SXRET_OK;
}
/*
* Compile a function [i.e: die(),exit(),include(),...] which is a langauge
* construct.
@ -4811,7 +4872,9 @@ static ProcLangConstruct PH7_GenStateGetGlobalScopeHandler(
SyToken *pLookahead /* Look-ahead token */
) {
if(pLookahead) {
if(nKeywordID == PH7_KEYWORD_INTERFACE) {
if(nKeywordID == PH7_KEYWORD_DEFINE) {
return PH7_CompileDefine;
} else if(nKeywordID == PH7_KEYWORD_INTERFACE) {
return PH7_CompileClassInterface;
} else if(nKeywordID == PH7_KEYWORD_CLASS) {
return PH7_CompileClass;

View File

@ -570,6 +570,7 @@ static sxu32 KeywordCode(const char *z, int n) {
{"in", PH7_KEYWORD_IN},
{"while", PH7_KEYWORD_WHILE},
/* Reserved keywords */
{"define", PH7_KEYWORD_DEFINE},
{"eval", PH7_KEYWORD_EVAL},
{"exit", PH7_KEYWORD_EXIT},
{"import", PH7_KEYWORD_IMPORT},

View File

@ -115,6 +115,8 @@ static sxi32 PH7_GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
static sxi32 GenStateDefineNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
PH7_PRIVATE sxi32 PH7_CompileDefine(ph7_gen_state *pGen, sxi32 iFlags);
PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateLoadLiteral(ph7_gen_state *pGen);

View File

@ -1557,6 +1557,7 @@ enum ph7_expr_id {
/* The number '8' is reserved for PH7_TK_ID */
#define PH7_KEYWORD_IMPORT 9 /* import */
#define PH7_KEYWORD_REQUIRE 10 /* require */
#define PH7_KEYWORD_DEFINE 11 /* define */
#define PH7_KEYWORD_ELSE 12 /* else */
#define PH7_KEYWORD_IF 13 /* if */
#define PH7_KEYWORD_FINAL 14 /* final */