Browse Source

Get rid of array() & list() for the new syntax.

pull/50/head
Rafal Kupiec 3 years ago
parent
commit
65b178932a
Signed by: belliash GPG Key ID: 4E829243E0CFE6B4
  1. 63
      engine/compiler.c
  2. 6
      engine/lexer.c
  3. 43
      engine/parser.c
  4. 70
      engine/vm.c
  5. 1
      include/compiler.h
  6. 5
      include/ph7int.h

63
engine/compiler.c

@ -798,14 +798,8 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) {
sxi32 nPair = 0;
sxi32 iNest;
sxi32 rc;
if(pGen->pIn->nType & PH7_TK_OCB) {
/* Jump the opening curly bracket */
pGen->pIn++;
} else {
/* Jump the 'array' keyword,the leading left parenthesis */
pGen->pIn += 2;
}
/* Jump the trailing parenthesis. */
/* Jump the opening and the trailing parenthesis. */
pGen->pIn++;
pGen->pEnd--;
xValidator = 0;
SXUNUSED(iCompileFlag); /* cc warning */
@ -930,49 +924,6 @@ static sxi32 PH7_GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *p
}
return rc;
}
/*
* Compile the 'list' language construct.
* list(): Assign variables as if they were an array.
* list() is used to assign a list of variables in one operation.
* Description
* array list (mixed $varname [, mixed $... ] )
* Like array(), this is not really a function, but a language construct.
* list() is used to assign a list of variables in one operation.
* Parameters
* $varname: A variable.
* Return Values
* The assigned array.
*/
PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag) {
SyToken *pNext;
sxi32 nExpr;
sxi32 rc;
nExpr = 0;
/* Jump the 'list' keyword,the leading left parenthesis and the trailing parenthesis */
pGen->pIn += 2;
pGen->pEnd--;
SXUNUSED(iCompileFlag); /* cc warning */
while(SXRET_OK == PH7_GetNextExpr(pGen->pIn, pGen->pEnd, &pNext)) {
if(pGen->pIn < pNext) {
/* Compile the expression holding the variable */
rc = PH7_GenStateCompileArrayEntry(&(*pGen), pGen->pIn, pNext, EXPR_FLAG_LOAD_IDX_STORE, PH7_GenStateListNodeValidator);
if(rc != SXRET_OK) {
/* Do not bother compiling this expression, it's broken anyway */
return SXRET_OK;
}
} else {
/* Empty entry,load NULL */
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_LOADC, 0, 0/* NULL index */, 0, 0);
}
nExpr++;
/* Advance the stream cursor */
pGen->pIn = &pNext[1];
}
/* Emit the LOAD_LIST instruction */
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_LOAD_LIST, nExpr, 0, 0, 0);
/* Node successfully compiled */
return SXRET_OK;
}
/*
* Compile a closure (anonymous function).
* Closures (also known as anonymous functions), allow the creation of functions
@ -5107,10 +5058,7 @@ static sxi32 PH7_GenStateEmitExprCode(
if(iVmOp == PH7_OP_STORE) {
pInstr = PH7_VmPeekInstr(pGen->pVm);
if(pInstr) {
if(pInstr->iOp == PH7_OP_LOAD_LIST) {
/* Hide the STORE instruction */
iVmOp = 0;
} else if(pInstr->iOp == PH7_OP_MEMBER) {
if(pInstr->iOp == PH7_OP_MEMBER) {
/* Perform a member store operation [i.e: $this->x = 50] */
iP2 = 1;
} else {
@ -5378,9 +5326,8 @@ static ProcLangConstruct PH7_GenStateGetStatementHandler(
static int PH7_IsLangConstruct(sxu32 nKeywordID) {
if(nKeywordID == PH7_KEYWORD_IMPORT || nKeywordID == PH7_KEYWORD_INCLUDE || nKeywordID == PH7_KEYWORD_REQUIRE
|| nKeywordID == PH7_KEYWORD_ISSET || nKeywordID == PH7_KEYWORD_EVAL || nKeywordID == PH7_KEYWORD_EMPTY
|| nKeywordID == PH7_KEYWORD_ARRAY || nKeywordID == PH7_KEYWORD_LIST || nKeywordID == PH7_KEYWORD_SELF
|| nKeywordID == PH7_KEYWORD_PARENT || nKeywordID == PH7_KEYWORD_STATIC || nKeywordID == PH7_KEYWORD_NEW
|| nKeywordID == PH7_KEYWORD_CLONE) {
|| nKeywordID == PH7_KEYWORD_SELF || nKeywordID == PH7_KEYWORD_PARENT || nKeywordID == PH7_KEYWORD_STATIC
|| nKeywordID == PH7_KEYWORD_NEW || nKeywordID == PH7_KEYWORD_CLONE) {
return TRUE;
}
/* Not a language construct */

6
engine/lexer.c

@ -225,7 +225,7 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
pTmp = (SyToken *)SySetPeek(pTokSet);
if(pTmp->nType & PH7_TK_KEYWORD) {
sxi32 nID = SX_PTR_TO_INT(pTmp->pUserData);
if((sxu32)nID & (PH7_KEYWORD_ARRAY | PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_CHAR | PH7_KEYWORD_CALLBACK | PH7_KEYWORD_RESOURCE | PH7_KEYWORD_VOID)) {
if((sxu32)nID & (PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_CHAR | PH7_KEYWORD_CALLBACK | PH7_KEYWORD_RESOURCE | PH7_KEYWORD_VOID)) {
pTmp = (SyToken *)SySetAt(pTokSet, pTokSet->nUsed - 2);
if(pTmp->nType & PH7_TK_LPAREN) {
/* Merge the three tokens '(' 'TYPE' ')' into a single one */
@ -238,8 +238,6 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
zTypeCast = "(char)";
} else if(nID & PH7_KEYWORD_STRING) {
zTypeCast = "(string)";
} else if(nID & PH7_KEYWORD_ARRAY) {
zTypeCast = "(array)";
} else if(nID & PH7_KEYWORD_OBJECT) {
zTypeCast = "(object)";
} else if(nID & PH7_KEYWORD_CALLBACK) {
@ -635,11 +633,9 @@ static sxu32 KeywordCode(const char *z, int n) {
{"import", PH7_KEYWORD_IMPORT},
{"include", PH7_KEYWORD_INCLUDE},
{"isset", PH7_KEYWORD_ISSET},
{"list", PH7_KEYWORD_LIST},
{"require", PH7_KEYWORD_REQUIRE},
{"return", PH7_KEYWORD_RETURN},
/* Other keywords */
{"array", PH7_KEYWORD_ARRAY},
{"function", PH7_KEYWORD_FUNCTION},
{"var", PH7_KEYWORD_VAR}
};

43
engine/parser.c

@ -181,7 +181,6 @@ static const ph7_expr_op aOpTable[] = {
{ {"(char)", sizeof("(char)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_CHAR },
{ {"(string)", sizeof("(string)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_STR },
{ {"(float)", sizeof("(float)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_REAL },
{ {"(array)", sizeof("(array)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_ARRAY},
{ {"(object)", sizeof("(object)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_OBJ },
{ {"(callback)", sizeof("(callback)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_CALL},
{ {"(resource)", sizeof("(resource)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_RES},
@ -611,7 +610,7 @@ Synchronize:
* An expression node can be a variable [i.e: $var],an operator [i.e: ++]
* an anonymous function [i.e: function(){ return "Hello"; }, a double/single
* quoted string, a literal [i.e: PHP_EOL],a namespace path
* [i.e: namespaces\path\to..],a array/list [i.e: array(4,5,6)] and so on.
* [i.e: namespaces\path\to..],an array [i.e: {4,5,6}] and so on.
*/
static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) {
ph7_expr_node *pNode;
@ -680,43 +679,7 @@ static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) {
pNode->xCode = PH7_CompileArray;
} else if(pCur->nType & PH7_TK_KEYWORD) {
sxu32 nKeyword = (sxu32)SX_PTR_TO_INT(pCur->pUserData);
if(nKeyword == PH7_KEYWORD_ARRAY || nKeyword == PH7_KEYWORD_LIST) {
/* List/Array node */
if(&pCur[1] >= pGen->pEnd || (pCur[1].nType & PH7_TK_LPAREN) == 0) {
/* Assume a literal */
ExprAssembleLiteral(&pCur, pGen->pEnd);
pNode->xCode = PH7_CompileLiteral;
} else {
pCur += 2;
/* Collect array/list tokens */
PH7_DelimitNestedTokens(pCur, pGen->pEnd, PH7_TK_LPAREN /* '(' */, PH7_TK_RPAREN /* ')' */, &pCur);
if(pCur < pGen->pEnd) {
pCur++;
} else {
/* Syntax error */
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine,
"%s: Missing closing parenthesis ')'", nKeyword == PH7_KEYWORD_LIST ? "list" : "array");
if(rc != SXERR_ABORT) {
rc = SXERR_SYNTAX;
}
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pNode);
return rc;
}
pNode->xCode = (nKeyword == PH7_KEYWORD_LIST) ? PH7_CompileList : PH7_CompileArray;
if(pNode->xCode == PH7_CompileList) {
ph7_expr_op *pOp = (pCur < pGen->pEnd) ? (ph7_expr_op *)pCur->pUserData : 0;
if(pCur >= pGen->pEnd || (pCur->nType & PH7_TK_OP) == 0 || pOp == 0 || pOp->iVmOp != PH7_OP_STORE /*'='*/) {
/* Syntax error */
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine, "list(): expecting '=' after construct");
if(rc != SXERR_ABORT) {
rc = SXERR_SYNTAX;
}
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pNode);
return rc;
}
}
}
} else if(pCur[1].nType & PH7_TK_LPAREN && (nKeyword & PH7_KEYWORD_TYPEDEF)) {
if(pCur[1].nType & PH7_TK_LPAREN && (nKeyword & PH7_KEYWORD_TYPEDEF)) {
/* Anonymous function */
if(&pCur[1] >= pGen->pEnd) {
/* Assume a literal */
@ -1468,7 +1431,7 @@ static sxi32 ExprMakeTree(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32 nTo
return rc;
}
if(ExprIsModifiableValue(apNode[iLeft], FALSE) == FALSE) {
if(pNode->pOp->iVmOp != PH7_OP_STORE || apNode[iLeft]->xCode != PH7_CompileList) {
if(pNode->pOp->iVmOp != PH7_OP_STORE) {
/* Left operand must be a modifiable l-value */
rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine,
"'%z': Left operand must be a modifiable l-value", &pNode->pOp->sOp);

70
engine/vm.c

@ -2261,24 +2261,6 @@ static sxi32 VmByteCodeExec(
/* Force a numeric cast */
PH7_MemObjToNumeric(pTos);
break;
/*
* CVT_ARRAY: * * *
*
* Force the top of the stack to be a hashmap aka 'array'.
*/
case PH7_OP_CVT_ARRAY:
#ifdef UNTRUST
if(pTos < pStack) {
goto Abort;
}
#endif
/* Force a hashmap cast */
rc = PH7_MemObjToHashmap(pTos);
if(rc != SXRET_OK) {
/* OOM, emit an error message */
PH7_VmMemoryError(&(*pVm));
}
break;
/*
* CVT_OBJ: * * *
*
@ -2539,52 +2521,6 @@ static sxi32 VmByteCodeExec(
MemObjSetType(pTos, MEMOBJ_HASHMAP | iFlags);
break;
}
/*
* LOAD_LIST: P1 * *
*
* Assign hashmap entries values to the top P1 entries.
* This is the VM implementation of the list() PHP construct.
* Caveats:
* This implementation support only a single nesting level.
*/
case PH7_OP_LOAD_LIST: {
ph7_value *pEntry;
if(pInstr->iP1 <= 0) {
/* Empty list,break immediately */
break;
}
pEntry = &pTos[-pInstr->iP1 + 1];
#ifdef UNTRUST
if(&pEntry[-1] < pStack) {
goto Abort;
}
#endif
if(pEntry[-1].iFlags & MEMOBJ_HASHMAP) {
ph7_hashmap *pMap = (ph7_hashmap *)pEntry[-1].x.pOther;
ph7_hashmap_node *pNode;
ph7_value sKey, *pObj;
/* Start Copying */
PH7_MemObjInitFromInt(&(*pVm), &sKey, 0);
while(pEntry <= pTos) {
if(pEntry->nIdx != SXU32_HIGH /* Variable not constant */) {
rc = PH7_HashmapLookup(pMap, &sKey, &pNode);
if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pEntry->nIdx)) != 0) {
if(rc == SXRET_OK) {
/* Store node value */
PH7_HashmapExtractNodeValue(pNode, pObj, TRUE);
} else {
/* Nullify the variable */
PH7_MemObjRelease(pObj);
}
}
}
sKey.x.iVal++; /* Next numeric index */
pEntry++;
}
}
VmPopOperand(&pTos, pInstr->iP1);
break;
}
/*
* LOAD_IDX: P1 P2 *
*
@ -5592,9 +5528,6 @@ static const char *VmInstrToString(sxi32 nOp) {
case PH7_OP_LOAD_MAP:
zOp = "LOAD_MAP";
break;
case PH7_OP_LOAD_LIST:
zOp = "LOAD_LIST";
break;
case PH7_OP_LOAD_IDX:
zOp = "LOAD_IDX";
break;
@ -5727,9 +5660,6 @@ static const char *VmInstrToString(sxi32 nOp) {
case PH7_OP_CVT_NULL:
zOp = "CVT_NULL";
break;
case PH7_OP_CVT_ARRAY:
zOp = "CVT_ARRAY";
break;
case PH7_OP_CVT_OBJ:
zOp = "CVT_OBJ";
break;

1
include/compiler.h

@ -96,7 +96,6 @@ static sxi32 PH7_GenStateCompileArrayEntry(ph7_gen_state *pGen, SyToken *pIn, Sy
static sxi32 PH7_GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag);

5
include/ph7int.h

@ -1393,7 +1393,6 @@ enum ph7_vm_op {
PH7_OP_LOADC, /* Load constant */
PH7_OP_LOAD_IDX, /* Load array entry */
PH7_OP_LOAD_MAP, /* Load hashmap('array') */
PH7_OP_LOAD_LIST, /* Load list */
PH7_OP_LOAD_CLOSURE, /* Load closure */
PH7_OP_NOOP, /* NOOP */
PH7_OP_JMP, /* Unconditional jump */
@ -1457,7 +1456,6 @@ enum ph7_vm_op {
PH7_OP_STORE_REF, /* Store a reference to a variable*/
PH7_OP_MEMBER, /* Class member run-time access */
PH7_OP_CVT_NULL, /* NULL cast */
PH7_OP_CVT_ARRAY, /* Array cast */
PH7_OP_CVT_OBJ, /* Object cast */
PH7_OP_CVT_CALL, /* Callback cast */
PH7_OP_CVT_RES, /* Resource cast */
@ -1576,7 +1574,6 @@ enum ph7_expr_id {
#define PH7_KEYWORD_ELSE 0x8000000 /* else: MUST BE A POWER OF TWO */
#define PH7_KEYWORD_IF 13 /* if */
#define PH7_KEYWORD_FINAL 14 /* final */
#define PH7_KEYWORD_LIST 15 /* list */
#define PH7_KEYWORD_STATIC 16 /* static */
#define PH7_KEYWORD_CASE 17 /* case */
#define PH7_KEYWORD_SELF 18 /* self */
@ -1590,7 +1587,6 @@ enum ph7_expr_id {
#define PH7_KEYWORD_WHILE 26 /* while */
#define PH7_KEYWORD_EVAL 27 /* eval */
#define PH7_KEYWORD_VAR 28 /* var */
#define PH7_KEYWORD_ARRAY 0x200 /* array: MUST BE A POWER OF TWO */
#define PH7_KEYWORD_VIRTUAL 29 /* virtual */
#define PH7_KEYWORD_TRY 30 /* try */
#define PH7_KEYWORD_DEFAULT 31 /* default */
@ -1734,7 +1730,6 @@ PH7_PRIVATE sxi32 PH7_CompileLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileClosure(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);

Loading…
Cancel
Save