Fix #5: Included files content is unavailable during compilation #21
@ -4226,6 +4226,8 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
|||||||
SyString *pName;
|
SyString *pName;
|
||||||
sxi32 nKwrd;
|
sxi32 nKwrd;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
|
sxi32 iP1 = 0;
|
||||||
|
sxu32 iP2 = 0;
|
||||||
/* Jump the 'class' keyword */
|
/* Jump the 'class' keyword */
|
||||||
pGen->pIn++;
|
pGen->pIn++;
|
||||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||||
@ -4256,50 +4258,42 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
|||||||
/* Assume a standalone class */
|
/* Assume a standalone class */
|
||||||
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;
|
SyString pBaseName;
|
||||||
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
|
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
|
||||||
if(nKwrd == PH7_TKWRD_EXTENDS /* class b extends a */) {
|
if(nKwrd == PH7_TKWRD_EXTENDS /* class b extends a */) {
|
||||||
pGen->pIn++; /* Advance the stream cursor */
|
pGen->pIn++; /* Advance the stream cursor */
|
||||||
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 'class_name' after 'extends' keyword inside class '%z'",
|
rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
|
||||||
pName);
|
"Expected 'class_name' after 'extends' keyword inside class '%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 *pName = malloc(pGen->pIn->sData.nByte);
|
||||||
|
SyStrncpy(pName, pGen->pIn->sData.zString, pGen->pIn->sData.nByte);
|
||||||
|
SyStringInitFromBuf(&pBaseName, pName, SyStrlen(pName));
|
||||||
|
/* Register inherited class */
|
||||||
|
SySetPut(&pClass->sExtends, (const void *)&pBaseName);
|
||||||
|
/* Advance the stream cursor */
|
||||||
|
pGen->pIn++;
|
||||||
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_COMMA) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Jump the comma operator */
|
||||||
|
pGen->pIn++;
|
||||||
}
|
}
|
||||||
/* Extract base class name */
|
iP1 = 1;
|
||||||
pBaseName = &pGen->pIn->sData;
|
|
||||||
// /* Perform the query */
|
|
||||||
// pBase = PH7_VmExtractClass(pGen->pVm, pBaseName->zString, pBaseName->nByte, FALSE, 0);
|
|
||||||
// /* Interface is not allowed */
|
|
||||||
// if(pBase == 0 || (pBase->iFlags & PH7_CLASS_INTERFACE)) {
|
|
||||||
// /* Inexistant base class */
|
|
||||||
// rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Inexistant base class '%z'", pBaseName);
|
|
||||||
// if(rc == SXERR_ABORT) {
|
|
||||||
// /* Error count limit reached,abort immediately */
|
|
||||||
// return SXERR_ABORT;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if(pBase->iFlags & PH7_CLASS_FINAL) {
|
|
||||||
// rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
|
|
||||||
// "Class '%z' may not inherit from final class '%z'", pName, &pBase->sName);
|
|
||||||
// if(rc == SXERR_ABORT) {
|
|
||||||
// /* Error count limit reached,abort immediately */
|
|
||||||
// return SXERR_ABORT;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
/* Advance the stream cursor */
|
|
||||||
pGen->pIn++;
|
|
||||||
}
|
}
|
||||||
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_TKWRD_IMPLEMENTS) {
|
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_TKWRD_IMPLEMENTS) {
|
||||||
ph7_class *pInterface;
|
ph7_class *pInterface;
|
||||||
SyString *pIntName;
|
SyString pIntName;
|
||||||
/* Interface implementation */
|
/* Interface implementation */
|
||||||
pGen->pIn++; /* Advance the stream cursor */
|
pGen->pIn++; /* Advance the stream cursor */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -4308,35 +4302,28 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
|||||||
rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
|
rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
|
||||||
"Expected 'interface_name' after 'implements' keyword inside class '%z' declaration",
|
"Expected 'interface_name' after 'implements' keyword inside class '%z' declaration",
|
||||||
pName);
|
pName);
|
||||||
|
SyMemBackendPoolFree(&pGen->pVm->sAllocator, pClass);
|
||||||
if(rc == SXERR_ABORT) {
|
if(rc == SXERR_ABORT) {
|
||||||
/* Error count limit reached,abort immediately */
|
/* Error count limit reached,abort immediately */
|
||||||
return SXERR_ABORT;
|
return SXERR_ABORT;
|
||||||
}
|
}
|
||||||
break;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
/* Extract interface name */
|
/* Extract interface name */
|
||||||
pIntName = &pGen->pIn->sData;
|
char *pName = malloc(pGen->pIn->sData.nByte);
|
||||||
/* Make sure the interface is already defined */
|
SyStrncpy(pName, pGen->pIn->sData.zString, pGen->pIn->sData.nByte);
|
||||||
pInterface = PH7_VmExtractClass(pGen->pVm, pIntName->zString, pIntName->nByte, FALSE, 0);
|
SyStringInitFromBuf(&pIntName, pName, SyStrlen(pName));
|
||||||
/* Only interfaces are allowed */
|
/* Register inherited class */
|
||||||
if(pInterface == 0 || (pInterface->iFlags & PH7_CLASS_INTERFACE) == 0) {
|
SySetPut(&pClass->sImplements, (const void *)&pIntName);
|
||||||
/* Inexistant interface */
|
|
||||||
rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Inexistant base interface '%z'", pIntName);
|
|
||||||
if(rc == SXERR_ABORT) {
|
|
||||||
/* Error count limit reached,abort immediately */
|
|
||||||
return SXERR_ABORT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Register interface */
|
|
||||||
SySetPut(&aInterfaces, (const void *)&pInterface);
|
|
||||||
}
|
|
||||||
/* Advance the stream cursor */
|
/* Advance the stream cursor */
|
||||||
pGen->pIn++;
|
pGen->pIn++;
|
||||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_COMMA) == 0) {
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_COMMA) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pGen->pIn++;/* Jump the comma */
|
/* Jump the comma */
|
||||||
|
pGen->pIn++;
|
||||||
}
|
}
|
||||||
|
iP2 = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_OCB /*'{'*/) == 0) {
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_OCB /*'{'*/) == 0) {
|
||||||
@ -4576,23 +4563,10 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
|
|||||||
}
|
}
|
||||||
/* Install the class */
|
/* Install the class */
|
||||||
rc = PH7_VmInstallClass(pGen->pVm, pClass);
|
rc = PH7_VmInstallClass(pGen->pVm, pClass);
|
||||||
// if(rc == SXRET_OK) {
|
if(iP1 || iP2) {
|
||||||
// ph7_class **apInterface;
|
/* Emit the CLASS_INIT instruction only if there is such a need */
|
||||||
// sxu32 n;
|
PH7_VmEmitInstr(pGen->pVm, PH7_OP_CLASS_INIT, iP1, iP2, pClass, 0);
|
||||||
// if(pBase) {
|
}
|
||||||
// /* Inherit from base class and mark as a subclass */
|
|
||||||
// rc = PH7_ClassInherit(&(*pGen), pClass, pBase);
|
|
||||||
// }
|
|
||||||
// apInterface = (ph7_class **)SySetBasePtr(&aInterfaces);
|
|
||||||
// for(n = 0 ; n < SySetUsed(&aInterfaces) ; n++) {
|
|
||||||
// /* Implements one or more interface */
|
|
||||||
// rc = PH7_ClassImplement(pClass, apInterface[n]);
|
|
||||||
// if(rc != SXRET_OK) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
SySetRelease(&aInterfaces);
|
|
||||||
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");
|
||||||
return SXERR_ABORT;
|
return SXERR_ABORT;
|
||||||
|
@ -41,6 +41,8 @@ PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32
|
|||||||
SyHashInit(&pClass->hAttr, &pVm->sAllocator, 0, 0);
|
SyHashInit(&pClass->hAttr, &pVm->sAllocator, 0, 0);
|
||||||
SyHashInit(&pClass->hDerived, &pVm->sAllocator, 0, 0);
|
SyHashInit(&pClass->hDerived, &pVm->sAllocator, 0, 0);
|
||||||
SySetInit(&pClass->aInterface, &pVm->sAllocator, sizeof(ph7_class *));
|
SySetInit(&pClass->aInterface, &pVm->sAllocator, sizeof(ph7_class *));
|
||||||
|
SySetInit(&pClass->sExtends, &pVm->sAllocator, sizeof(SyString));
|
||||||
|
SySetInit(&pClass->sImplements, &pVm->sAllocator, sizeof(SyString));
|
||||||
pClass->nLine = nLine;
|
pClass->nLine = nLine;
|
||||||
/* All done */
|
/* All done */
|
||||||
return pClass;
|
return pClass;
|
||||||
|
41
engine/vm.c
41
engine/vm.c
@ -4508,6 +4508,41 @@ static sxi32 VmByteCodeExec(
|
|||||||
pc = nJump - 1;
|
pc = nJump - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* OP_CLASS_INIT P1 P2 P3
|
||||||
|
* Perform additional class initialization, by adding base classes
|
||||||
|
* and interfaces to its definition.
|
||||||
|
*/
|
||||||
|
case PH7_OP_CLASS_INIT:
|
||||||
|
{
|
||||||
|
ph7_class *pClass = (ph7_class *)pInstr->p3;
|
||||||
|
printf("Called by class: '%s'\n", pClass->sName);
|
||||||
|
if(pInstr->iP1) {
|
||||||
|
/* This class inherits from other classes */
|
||||||
|
SyString *apExtends;
|
||||||
|
while(SySetGetNextEntry(&pClass->sExtends, (void **)&apExtends) == SXRET_OK) {
|
||||||
|
printf("Class '%s' inherits from '%s'\n", pClass->sName.zString, apExtends->zString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pInstr->iP2) {
|
||||||
|
/* This class implements some interfaces */
|
||||||
|
SyString *apImplements;
|
||||||
|
while(SySetGetNextEntry(&pClass->sImplements, (void **)&apImplements) == SXRET_OK) {
|
||||||
|
printf("Class '%s' implements '%s'\n", pClass->sName.zString, apImplements->zString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SyStringInitFromBuf(&pClass->sName, "DUPA", 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* OP_INTERFACE_INIT * * P3
|
||||||
|
* Perform additional interface initialization, by adding base interfaces
|
||||||
|
* to its definition.
|
||||||
|
*/
|
||||||
|
case PH7_OP_INTERFACE_INIT:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* OP_FOREACH_INIT * P2 P3
|
* OP_FOREACH_INIT * P2 P3
|
||||||
* Prepare a foreach step.
|
* Prepare a foreach step.
|
||||||
@ -6025,6 +6060,12 @@ static const char *VmInstrToString(sxi32 nOp) {
|
|||||||
case PH7_OP_THROW:
|
case PH7_OP_THROW:
|
||||||
zOp = "THROW ";
|
zOp = "THROW ";
|
||||||
break;
|
break;
|
||||||
|
case PH7_OP_CLASS_INIT:
|
||||||
|
zOp = "CLASS_INIT ";
|
||||||
|
break;
|
||||||
|
case PH7_OP_INTERFACE_INIT:
|
||||||
|
zOp = "INTER_INIT ";
|
||||||
|
break;
|
||||||
case PH7_OP_FOREACH_INIT:
|
case PH7_OP_FOREACH_INIT:
|
||||||
zOp = "4EACH_INIT ";
|
zOp = "4EACH_INIT ";
|
||||||
break;
|
break;
|
||||||
|
@ -1035,6 +1035,8 @@ struct ph7_class {
|
|||||||
SyHash hMethod; /* Class methods */
|
SyHash hMethod; /* Class methods */
|
||||||
sxu32 nLine; /* Line number on which this class was declared */
|
sxu32 nLine; /* Line number on which this class was declared */
|
||||||
SySet aInterface; /* Implemented interface container */
|
SySet aInterface; /* Implemented interface container */
|
||||||
|
SySet sExtends; /* List of inherited classes / interfaces */
|
||||||
|
SySet sImplements; /* List of implemented interfaces */
|
||||||
};
|
};
|
||||||
/* Class configuration flags */
|
/* Class configuration flags */
|
||||||
#define PH7_CLASS_FINAL 0x001 /* Class is final [cannot be extended] */
|
#define PH7_CLASS_FINAL 0x001 /* Class is final [cannot be extended] */
|
||||||
@ -1360,6 +1362,8 @@ enum ph7_vm_op {
|
|||||||
PH7_OP_CVT_NULL, /* NULL cast */
|
PH7_OP_CVT_NULL, /* NULL cast */
|
||||||
PH7_OP_CVT_ARRAY, /* Array cast */
|
PH7_OP_CVT_ARRAY, /* Array cast */
|
||||||
PH7_OP_CVT_OBJ, /* Object cast */
|
PH7_OP_CVT_OBJ, /* Object cast */
|
||||||
|
PH7_OP_CLASS_INIT, /* Class init */
|
||||||
|
PH7_OP_INTERFACE_INIT,/* Interface init */
|
||||||
PH7_OP_FOREACH_INIT, /* For each init */
|
PH7_OP_FOREACH_INIT, /* For each init */
|
||||||
PH7_OP_FOREACH_STEP, /* For each step */
|
PH7_OP_FOREACH_STEP, /* For each step */
|
||||||
PH7_OP_IS_A, /* Instanceof */
|
PH7_OP_IS_A, /* Instanceof */
|
||||||
|
Loading…
Reference in New Issue
Block a user