Implement a fix also for interface. This commit also adds initial and partial support for multiple inheritance.
This commit is contained in:
parent
a6a43b5f3b
commit
bdf053a205
|
@ -4006,12 +4006,27 @@ Synchronize:
|
||||||
static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||||
sxu32 nLine = pGen->pIn->nLine;
|
sxu32 nLine = pGen->pIn->nLine;
|
||||||
ph7_class *pClass, *pBase;
|
ph7_class *pClass, *pBase;
|
||||||
|
ph7_class_info *pClassInfo;
|
||||||
SyToken *pEnd, *pTmp;
|
SyToken *pEnd, *pTmp;
|
||||||
SyString *pName;
|
SyString *pName;
|
||||||
sxi32 nKwrd;
|
sxi32 nKwrd;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
|
sxi32 iP1 = 0;
|
||||||
/* Jump the 'interface' keyword */
|
/* Jump the 'interface' keyword */
|
||||||
pGen->pIn++;
|
pGen->pIn++;
|
||||||
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||||
|
/* Syntax error */
|
||||||
|
rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid interface name");
|
||||||
|
if(rc == SXERR_ABORT) {
|
||||||
|
/* Error count limit reached,abort immediately */
|
||||||
|
return SXERR_ABORT;
|
||||||
|
}
|
||||||
|
/* Synchronize with the first semi-colon or curly braces */
|
||||||
|
while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_OCB/*'{'*/ | PH7_TK_SEMI/*';'*/)) == 0) {
|
||||||
|
pGen->pIn++;
|
||||||
|
}
|
||||||
|
return SXRET_OK;
|
||||||
|
}
|
||||||
/* Extract interface name */
|
/* Extract interface name */
|
||||||
pName = &pGen->pIn->sData;
|
pName = &pGen->pIn->sData;
|
||||||
/* Advance the stream cursor */
|
/* Advance the stream cursor */
|
||||||
|
@ -4022,41 +4037,49 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||||
PH7_GenCompileError(pGen, E_ERROR, nLine, "Fatal, PH7 is running out of memory");
|
PH7_GenCompileError(pGen, E_ERROR, nLine, "Fatal, PH7 is running out of memory");
|
||||||
return SXERR_ABORT;
|
return SXERR_ABORT;
|
||||||
}
|
}
|
||||||
|
/* Obtain a raw class inheritance storage */
|
||||||
|
pClassInfo = PH7_NewClassInfo(pGen->pVm, pName);
|
||||||
|
if(pClassInfo == 0) {
|
||||||
|
PH7_GenCompileError(pGen, E_ERROR, nLine, "Fatal, PH7 is running out of memory");
|
||||||
|
return SXERR_ABORT;
|
||||||
|
}
|
||||||
/* Mark as an interface */
|
/* Mark as an interface */
|
||||||
pClass->iFlags = PH7_CLASS_INTERFACE;
|
pClass->iFlags = PH7_CLASS_INTERFACE;
|
||||||
/* Assume no base class is given */
|
/* Assume no base class is given */
|
||||||
pBase = 0;
|
pBase = 0;
|
||||||
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) {
|
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) {
|
||||||
|
SyString pBaseName;
|
||||||
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
|
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
|
||||||
if(nKwrd == PH7_TKWRD_EXTENDS /* interface b extends a */) {
|
if(nKwrd == PH7_TKWRD_EXTENDS /* interface b extends a */) {
|
||||||
SyString *pBaseName;
|
|
||||||
/* Extract base interface */
|
/* Extract base interface */
|
||||||
pGen->pIn++;
|
pGen->pIn++;
|
||||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
for(;;) {
|
||||||
/* Syntax error */
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||||
rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
|
/* Syntax error */
|
||||||
"Expected 'interface_name' after 'extends' keyword inside interface '%z'",
|
rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
|
||||||
pName);
|
"Expected 'interface_name' after 'extends' keyword inside interface '%z'",
|
||||||
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pClass);
|
pName);
|
||||||
if(rc == SXERR_ABORT) {
|
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pClass);
|
||||||
/* Error count limit reached,abort immediately */
|
if(rc == SXERR_ABORT) {
|
||||||
return SXERR_ABORT;
|
/* Error count limit reached,abort immediately */
|
||||||
|
return SXERR_ABORT;
|
||||||
|
}
|
||||||
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
return SXRET_OK;
|
/* Extract base class name */
|
||||||
}
|
char *sName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pGen->pIn->sData.zString, pGen->pIn->sData.nByte);
|
||||||
pBaseName = &pGen->pIn->sData;
|
SyStringInitFromBuf(&pBaseName, sName, SyStrlen(sName));
|
||||||
pBase = PH7_VmExtractClass(pGen->pVm, pBaseName->zString, pBaseName->nByte, FALSE, 0);
|
/* Register inherited class */
|
||||||
/* Only interface is allowed */
|
SySetPut(&pClassInfo->sExtends, (const void *)&pBaseName);
|
||||||
if(pBase == 0 || (pBase->iFlags & PH7_CLASS_INTERFACE) == 0) {
|
/* Advance the stream cursor */
|
||||||
/* Inexistant interface */
|
pGen->pIn++;
|
||||||
rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Inexistant base interface '%z'", pBaseName);
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_COMMA) == 0) {
|
||||||
if(rc == SXERR_ABORT) {
|
break;
|
||||||
/* Error count limit reached,abort immediately */
|
|
||||||
return SXERR_ABORT;
|
|
||||||
}
|
}
|
||||||
|
/* Jump the comma operator */
|
||||||
|
pGen->pIn++;
|
||||||
}
|
}
|
||||||
/* Advance the stream cursor */
|
iP1 = 1;
|
||||||
pGen->pIn++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_OCB /*'{'*/) == 0) {
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_OCB /*'{'*/) == 0) {
|
||||||
|
@ -4188,9 +4211,9 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||||
}
|
}
|
||||||
/* Install the interface */
|
/* Install the interface */
|
||||||
rc = PH7_VmInstallClass(pGen->pVm, pClass);
|
rc = PH7_VmInstallClass(pGen->pVm, pClass);
|
||||||
if(rc == SXRET_OK && pBase) {
|
if(iP1) {
|
||||||
/* Inherit from the base interface */
|
/* Emit the INTERFACE_INIT instruction only if there is such a need */
|
||||||
rc = PH7_ClassInterfaceInherit(pClass, pBase);
|
PH7_VmEmitInstr(pGen->pVm, PH7_OP_INTERFACE_INIT, iP1, 0, pClassInfo, 0);
|
||||||
}
|
}
|
||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
PH7_GenCompileError(pGen, E_ERROR, nLine, "Fatal, PH7 is running out of memory");
|
PH7_GenCompileError(pGen, E_ERROR, nLine, "Fatal, PH7 is running out of memory");
|
||||||
|
|
23
engine/vm.c
23
engine/vm.c
|
@ -4560,12 +4560,33 @@ static sxi32 VmByteCodeExec(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* OP_INTERFACE_INIT * * P3
|
* OP_INTERFACE_INIT P1 * P3
|
||||||
* Perform additional interface initialization, by adding base interfaces
|
* Perform additional interface initialization, by adding base interfaces
|
||||||
* to its definition.
|
* to its definition.
|
||||||
*/
|
*/
|
||||||
case PH7_OP_INTERFACE_INIT:
|
case PH7_OP_INTERFACE_INIT:
|
||||||
{
|
{
|
||||||
|
ph7_class_info *pClassInfo = (ph7_class_info *)pInstr->p3;
|
||||||
|
ph7_class *pClass = PH7_VmExtractClass(pVm, pClassInfo->sName.zString, pClassInfo->sName.nByte, FALSE, 0);
|
||||||
|
ph7_class *pBase = 0;
|
||||||
|
if(pInstr->iP1) {
|
||||||
|
/* This interface inherits from other interface */
|
||||||
|
SyString *apExtends;
|
||||||
|
while(SySetGetNextEntry(&pClassInfo->sExtends, (void **)&apExtends) == SXRET_OK) {
|
||||||
|
pBase = PH7_VmExtractClass(pVm, apExtends->zString, apExtends->nByte, FALSE, 0);
|
||||||
|
if(pBase == 0) {
|
||||||
|
/* Non-existent base interface */
|
||||||
|
VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Call to non-existent base interface '%z'", &apExtends->zString);
|
||||||
|
} else if((pBase->iFlags & PH7_CLASS_INTERFACE) == 0) {
|
||||||
|
/* Trying to inherit from class */
|
||||||
|
VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Interface '%z' cannot inherit from class '%z'", &pClass->sName.zString, &apExtends->zString);
|
||||||
|
}
|
||||||
|
rc = PH7_ClassInterfaceInherit(pClass, pBase);
|
||||||
|
if(rc != SXRET_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue