Test and temporary version of compiler emiting PH7_OP_CLASS_INIT instruction.

However it works on ph7_class and thus passes whole class into the VM, what causes memory overhead,
as finally we have to find this class on the VM's stack. Instead, we could pass some ph7_class_info
structure containing a name of class to look for and information about its inheritances.
This commit is contained in:
Rafal Kupiec 2018-07-27 08:24:53 +02:00
parent c24a9bc251
commit b040886b97
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
4 changed files with 91 additions and 70 deletions

View File

@ -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,10 +4258,11 @@ 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 */
for(;;) {
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) { if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
/* Syntax error */ /* Syntax error */
rc = PH7_GenCompileError(pGen, E_ERROR, nLine, rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
@ -4273,33 +4276,24 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
return SXRET_OK; return SXRET_OK;
} }
/* Extract base class name */ /* Extract base class name */
pBaseName = &pGen->pIn->sData; char *pName = malloc(pGen->pIn->sData.nByte);
// /* Perform the query */ SyStrncpy(pName, pGen->pIn->sData.zString, pGen->pIn->sData.nByte);
// pBase = PH7_VmExtractClass(pGen->pVm, pBaseName->zString, pBaseName->nByte, FALSE, 0); SyStringInitFromBuf(&pBaseName, pName, SyStrlen(pName));
// /* Interface is not allowed */ /* Register inherited class */
// if(pBase == 0 || (pBase->iFlags & PH7_CLASS_INTERFACE)) { SySetPut(&pClass->sExtends, (const void *)&pBaseName);
// /* 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 */ /* Advance the stream cursor */
pGen->pIn++; pGen->pIn++;
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_COMMA) == 0) {
break;
}
/* Jump the comma operator */
pGen->pIn++;
}
iP1 = 1;
} }
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;

View File

@ -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;

View File

@ -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;

View File

@ -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 */