Implement nominal class and interface types across declarations and calls
Build / AerScript (push) Successful in 37s
Build / AerScript (push) Successful in 37s
This commit is contained in:
+72
-25
@@ -981,6 +981,36 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) {
|
||||
/* Node successfully compiled */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Names, not class pointers, survive forward declarations and arena growth. */
|
||||
static sxu32 GenStateNamedType(ph7_gen_state *pGen, SyString *pName) {
|
||||
SyString sName;
|
||||
sxu32 i;
|
||||
char *zName;
|
||||
for(i = 0; i < SySetUsed(&pGen->pVm->aTypeNames); i++) {
|
||||
if(SyStringCmp(pName, (SyString *)SySetAt(&pGen->pVm->aTypeNames, i), SyMemcmp) == 0) {
|
||||
return ((i + 1) << 12) | MEMOBJ_OBJ;
|
||||
}
|
||||
}
|
||||
zName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pName->zString, pName->nByte);
|
||||
if(zName == 0 || i >= (MEMOBJ_NAMED >> 12)) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "PH7 engine is running out-of-memory");
|
||||
}
|
||||
SyStringInitFromBuf(&sName, zName, pName->nByte);
|
||||
if(SySetPut(&pGen->pVm->aTypeNames, &sName) != SXRET_OK) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "PH7 engine is running out-of-memory");
|
||||
}
|
||||
return ((i + 1) << 12) | MEMOBJ_OBJ;
|
||||
}
|
||||
static sxi32 GenStateIsNamedDeclaration(SyToken *pIn, SyToken *pEnd) {
|
||||
if(pIn >= pEnd || (pIn->nType & PH7_TK_ID) == 0 || (pIn->nType & PH7_TK_OP)) {
|
||||
return FALSE;
|
||||
}
|
||||
pIn++;
|
||||
if(pIn < pEnd && &pIn[1] < pEnd && (pIn->nType & PH7_TK_OSB) && (pIn[1].nType & PH7_TK_CSB)) {
|
||||
pIn += 2;
|
||||
}
|
||||
return pIn < pEnd && (pIn->nType & PH7_TK_DOLLAR);
|
||||
}
|
||||
/*
|
||||
* Compile a closure (anonymous function).
|
||||
* Closures (also known as anonymous functions), allow the creation of functions
|
||||
@@ -1010,7 +1040,9 @@ PH7_PRIVATE sxi32 PH7_CompileClosure(ph7_gen_state *pGen, sxi32 iCompileFlag) {
|
||||
sxu32 nType = 0;
|
||||
SXUNUSED(iCompileFlag);
|
||||
sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
if(nKey & PH7_KEYWORD_BOOL) {
|
||||
if(pGen->pIn->nType & PH7_TK_ID) {
|
||||
nType = GenStateNamedType(pGen, &pGen->pIn->sData);
|
||||
} else if(nKey & PH7_KEYWORD_BOOL) {
|
||||
nType = MEMOBJ_BOOL;
|
||||
} else if(nKey & PH7_KEYWORD_CALLBACK) {
|
||||
nType = MEMOBJ_CALL;
|
||||
@@ -2057,7 +2089,7 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
|
||||
pTmp = pGen->pEnd;
|
||||
pGen->pEnd = pEnd;
|
||||
sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
if(nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) {
|
||||
if((nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) || GenStateIsNamedDeclaration(pGen->pIn, pGen->pEnd)) {
|
||||
/* Compile variable */
|
||||
PH7_CompileVar(&(*pGen));
|
||||
}
|
||||
@@ -2243,14 +2275,18 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
||||
pTmp = pGen->pEnd;
|
||||
pGen->pEnd = pCur;
|
||||
nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
if(nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) {
|
||||
if((nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) || GenStateIsNamedDeclaration(pGen->pIn, pGen->pEnd)) {
|
||||
SyToken *pDeclName = &pGen->pIn[2];
|
||||
if(pGen->pIn[1].nType & PH7_TK_OSB) {
|
||||
pDeclName += 2;
|
||||
}
|
||||
/* Hack to compile variable */
|
||||
pGen->pEnd->nType = PH7_TK_SEMI;
|
||||
if(pGen->pIn[3].nType != PH7_TK_SEMI) {
|
||||
if(pDeclName + 1 != pGen->pEnd) {
|
||||
PH7_GenCompileError(&(*pGen), E_ERROR, pGen->pIn->nLine, "foreach: Improper key declaration");
|
||||
}
|
||||
/* Extract variable name */
|
||||
zName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pGen->pIn[2].sData.zString, pGen->pIn[2].sData.nByte);
|
||||
zName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pDeclName->sData.zString, pDeclName->sData.nByte);
|
||||
/* Compile variable declaration */
|
||||
PH7_CompileVar(&(*pGen));
|
||||
/* Record key name */
|
||||
@@ -2292,14 +2328,18 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
||||
pTmp = pGen->pEnd;
|
||||
pGen->pEnd = pCur;
|
||||
nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
if(nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) {
|
||||
if((nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) || GenStateIsNamedDeclaration(pGen->pIn, pGen->pEnd)) {
|
||||
SyToken *pDeclName = &pGen->pIn[2];
|
||||
if(pGen->pIn[1].nType & PH7_TK_OSB) {
|
||||
pDeclName += 2;
|
||||
}
|
||||
/* Hack to compile variable */
|
||||
pGen->pEnd->nType = PH7_TK_SEMI;
|
||||
if(pGen->pIn[3].nType != PH7_TK_SEMI) {
|
||||
if(pDeclName + 1 != pGen->pEnd) {
|
||||
PH7_GenCompileError(&(*pGen), E_ERROR, pGen->pIn->nLine, "foreach: Improper value declaration");
|
||||
}
|
||||
/* Extract variable name */
|
||||
zName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pGen->pIn[2].sData.zString, pGen->pIn[2].sData.nByte);
|
||||
zName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pDeclName->sData.zString, pDeclName->sData.nByte);
|
||||
/* Compile variable declaration */
|
||||
PH7_CompileVar(&(*pGen));
|
||||
/* Record value name */
|
||||
@@ -2564,7 +2604,9 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) {
|
||||
pGen->pIn++;
|
||||
nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
}
|
||||
if(nKey & PH7_KEYWORD_BOOL) {
|
||||
if(pGen->pIn->nType & PH7_TK_ID) {
|
||||
nType = GenStateNamedType(pGen, &pGen->pIn->sData);
|
||||
} else if(nKey & PH7_KEYWORD_BOOL) {
|
||||
nType = MEMOBJ_BOOL;
|
||||
} else if(nKey & PH7_KEYWORD_CALLBACK) {
|
||||
nType = MEMOBJ_CALL;
|
||||
@@ -3088,11 +3130,10 @@ static sxi32 PH7_GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen
|
||||
/* Argument must be a class instance, record that*/
|
||||
zDup = SyMemBackendStrDup(&pGen->pVm->sAllocator, pName->zString, pName->nByte);
|
||||
if(zDup) {
|
||||
sArg.nType = SXU32_HIGH; /* 0xFFFFFFFF as sentinel */
|
||||
sArg.nType = GenStateNamedType(pGen, pName);
|
||||
SyStringInitFromBuf(&sArg.sClass, zDup, pName->nByte);
|
||||
} else {
|
||||
/* This should not happen, but fallback to object anyway */
|
||||
sArg.nType = MEMOBJ_OBJ;
|
||||
PH7_GenCompileError(pGen, E_ERROR, pIn->nLine, "PH7 engine is running out-of-memory");
|
||||
}
|
||||
}
|
||||
pIn++;
|
||||
@@ -3855,7 +3896,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||
/* End of interface body */
|
||||
break;
|
||||
}
|
||||
if((pGen->pIn->nType & PH7_TK_KEYWORD) == 0) {
|
||||
if((pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z'. Expecting method signature or constant declaration inside interface '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
@@ -3870,7 +3911,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||
if(nKwrd == PH7_KEYWORD_PUBLIC) {
|
||||
/* Advance the stream cursor */
|
||||
pGen->pIn++;
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0) {
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Expecting method signature inside interface '%z'", pName);
|
||||
}
|
||||
@@ -3892,14 +3933,16 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||
"Cannot declare a static method in an interface '%z'",
|
||||
pName);
|
||||
}
|
||||
if((nKwrd & PH7_KEYWORD_TYPEDEF) == 0) {
|
||||
if((nKwrd & PH7_KEYWORD_TYPEDEF) == 0 && (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z', expecting data type for method signature inside interface '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
}
|
||||
sxu32 nType = 0;
|
||||
sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
if(nKey & PH7_KEYWORD_BOOL) {
|
||||
if(pGen->pIn->nType & PH7_TK_ID) {
|
||||
nType = GenStateNamedType(pGen, &pGen->pIn->sData);
|
||||
} else if(nKey & PH7_KEYWORD_BOOL) {
|
||||
nType = MEMOBJ_BOOL;
|
||||
} else if(nKey & PH7_KEYWORD_CALLBACK) {
|
||||
nType = MEMOBJ_CALL;
|
||||
@@ -4089,7 +4132,7 @@ static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
||||
/* End of class body */
|
||||
break;
|
||||
}
|
||||
if((pGen->pIn->nType & PH7_TK_KEYWORD) == 0) {
|
||||
if((pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z'. Expecting attribute or method declaration inside class '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
@@ -4102,7 +4145,7 @@ static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
||||
if(nKwrd == PH7_KEYWORD_PUBLIC || nKwrd == PH7_KEYWORD_PRIVATE || nKwrd == PH7_KEYWORD_PROTECTED) {
|
||||
iProtection = nKwrd;
|
||||
pGen->pIn++; /* Jump the visibility token */
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0) {
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z'. Expecting attribute or method declaration inside class '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
@@ -4124,7 +4167,7 @@ static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
||||
/* Static method or attribute,record that */
|
||||
iAttrflags |= PH7_CLASS_ATTR_STATIC;
|
||||
pGen->pIn++; /* Jump the static keyword */
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0) {
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z',Expecting attribute or method declaration inside class '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
@@ -4156,8 +4199,8 @@ static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
||||
pGen->pIn++; /* Jump the static keyword */
|
||||
}
|
||||
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 ||
|
||||
((nKwrd & PH7_KEYWORD_TYPEDEF) == 0 && pGen->pIn[2].nType != PH7_TK_LPAREN)) {
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0 ||
|
||||
((nKwrd & PH7_KEYWORD_TYPEDEF) == 0 && (pGen->pIn->nType & PH7_TK_ID) == 0 && pGen->pIn[2].nType != PH7_TK_LPAREN)) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z', expecting method declaration after 'virtual' keyword inside class '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
@@ -4181,21 +4224,23 @@ static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
||||
pGen->pIn++; /* Jump the static keyword */
|
||||
}
|
||||
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 ||
|
||||
((nKwrd & PH7_KEYWORD_TYPEDEF) == 0 && pGen->pIn[2].nType != PH7_TK_LPAREN)) {
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0 ||
|
||||
((nKwrd & PH7_KEYWORD_TYPEDEF) == 0 && (pGen->pIn->nType & PH7_TK_ID) == 0 && pGen->pIn[2].nType != PH7_TK_LPAREN)) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z', expecting method declaration after 'final' keyword inside class '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
}
|
||||
}
|
||||
if((nKwrd & PH7_KEYWORD_TYPEDEF) == 0) {
|
||||
if((nKwrd & PH7_KEYWORD_TYPEDEF) == 0 && (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
|
||||
"Unexpected token '%z', expecting data type for attribute or method declaration inside class '%z'",
|
||||
&pGen->pIn->sData, pName);
|
||||
}
|
||||
sxu32 nType = 0;
|
||||
sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||
if(nKey & PH7_KEYWORD_BOOL) {
|
||||
if(pGen->pIn->nType & PH7_TK_ID) {
|
||||
nType = GenStateNamedType(pGen, &pGen->pIn->sData);
|
||||
} else if(nKey & PH7_KEYWORD_BOOL) {
|
||||
nType = MEMOBJ_BOOL;
|
||||
} else if(nKey & PH7_KEYWORD_CALLBACK) {
|
||||
nType = MEMOBJ_CALL;
|
||||
@@ -5384,6 +5429,8 @@ static sxi32 PH7_GenStateCompileChunk(
|
||||
"Syntax error: Unexpected keyword '%z'",
|
||||
&pGen->pIn->sData);
|
||||
}
|
||||
} else if(GenStateIsNamedDeclaration(pGen->pIn, pGen->pEnd)) {
|
||||
xCons = PH7_CompileVar;
|
||||
} else if((pGen->pIn->nType & PH7_TK_ID) && (&pGen->pIn[1] < pGen->pEnd) && (pGen->pIn[1].nType & PH7_TK_COLON /*':'*/)) {
|
||||
/* Label found [i.e: Out: ],point to the routine responsible of compiling it */
|
||||
xCons = PH7_CompileLabel;
|
||||
|
||||
Reference in New Issue
Block a user