P# introduces virtual classes and virtual methods

This commit is contained in:
Rafal Kupiec 2018-07-30 17:08:25 +02:00
parent b7792dfc3d
commit 7b3e6c5b76
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
5 changed files with 30 additions and 30 deletions

View File

@ -3821,11 +3821,11 @@ static sxi32 GenStateCompileClassMethod(
nLine = pGen->pIn->nLine; nLine = pGen->pIn->nLine;
/* Jump the method name */ /* Jump the method name */
pGen->pIn++; pGen->pIn++;
if(iFlags & PH7_CLASS_ATTR_ABSTRACT) { if(iFlags & PH7_CLASS_ATTR_VIRTUAL) {
/* Abstract method */ /* Virtual method */
if(iProtection == PH7_CLASS_PROT_PRIVATE) { if(iProtection == PH7_CLASS_PROT_PRIVATE) {
rc = PH7_GenCompileError(pGen, E_ERROR, nLine, rc = PH7_GenCompileError(pGen, E_ERROR, nLine,
"Access type for abstract method '%z::%z' cannot be 'private'", "Access type for virtual method '%z::%z' cannot be 'private'",
&pClass->sName, pName); &pClass->sName, pName);
if(rc == SXERR_ABORT) { if(rc == SXERR_ABORT) {
return SXERR_ABORT; return SXERR_ABORT;
@ -4388,11 +4388,11 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
} }
/* Extract the keyword */ /* Extract the keyword */
nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData);
} else if(nKwrd == PH7_TKWRD_ABSTRACT) { } else if(nKwrd == PH7_TKWRD_VIRTUAL) {
/* Abstract method,record that */ /* Virtual method,record that */
iAttrflags |= PH7_CLASS_ATTR_ABSTRACT; iAttrflags |= PH7_CLASS_ATTR_VIRTUAL;
/* Mark the whole class as abstract */ /* Mark the whole class as virtual */
pClass->iFlags |= PH7_CLASS_ABSTRACT; pClass->iFlags |= PH7_CLASS_VIRTUAL;
/* Advance the stream cursor */ /* Advance the stream cursor */
pGen->pIn++; pGen->pIn++;
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) { if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) {
@ -4411,7 +4411,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) {
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 || if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 ||
SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_FUNCTION) { SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_FUNCTION) {
rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
"Unexpected token '%z',Expecting method declaration after 'abstract' keyword inside class '%z'", "Unexpected token '%z',Expecting method declaration after 'virtual' keyword inside class '%z'",
&pGen->pIn->sData, pName); &pGen->pIn->sData, pName);
if(rc == SXERR_ABORT) { if(rc == SXERR_ABORT) {
/* Error count limit reached,abort immediately */ /* Error count limit reached,abort immediately */
@ -4513,7 +4513,7 @@ done:
return PH7_OK; return PH7_OK;
} }
/* /*
* Compile a user-defined abstract class. * Compile a user-defined virtual class.
* According to the PHP language reference manual * According to the PHP language reference manual
* PHP 5 introduces abstract classes and methods. Classes defined as abstract * PHP 5 introduces abstract classes and methods. Classes defined as abstract
* may not be instantiated, and any class that contains at least one abstract * may not be instantiated, and any class that contains at least one abstract
@ -4528,10 +4528,10 @@ done:
* This also applies to constructors as of PHP 5.4. Before 5.4 constructor signatures * This also applies to constructors as of PHP 5.4. Before 5.4 constructor signatures
* could differ. * could differ.
*/ */
static sxi32 PH7_CompileAbstractClass(ph7_gen_state *pGen) { static sxi32 PH7_CompileVirtualClass(ph7_gen_state *pGen) {
sxi32 rc; sxi32 rc;
pGen->pIn++; /* Jump the 'abstract' keyword */ pGen->pIn++; /* Jump the 'virtual' keyword */
rc = GenStateCompileClass(&(*pGen), PH7_CLASS_ABSTRACT); rc = GenStateCompileClass(&(*pGen), PH7_CLASS_VIRTUAL);
return rc; return rc;
} }
/* /*
@ -5508,9 +5508,9 @@ static ProcLangConstruct GenStateGetStatementHandler(
return PH7_CompileClassInterface; return PH7_CompileClassInterface;
} else if(nKeywordID == PH7_TKWRD_CLASS && (pLookahead->nType & PH7_TK_ID)) { } else if(nKeywordID == PH7_TKWRD_CLASS && (pLookahead->nType & PH7_TK_ID)) {
return PH7_CompileClass; return PH7_CompileClass;
} else if(nKeywordID == PH7_TKWRD_ABSTRACT && (pLookahead->nType & PH7_TK_KEYWORD) } else if(nKeywordID == PH7_TKWRD_VIRTUAL && (pLookahead->nType & PH7_TK_KEYWORD)
&& SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) { && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) {
return PH7_CompileAbstractClass; return PH7_CompileVirtualClass;
} else if(nKeywordID == PH7_TKWRD_FINAL && (pLookahead->nType & PH7_TK_KEYWORD) } else if(nKeywordID == PH7_TKWRD_FINAL && (pLookahead->nType & PH7_TK_KEYWORD)
&& SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) { && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) {
return PH7_CompileFinalClass; return PH7_CompileFinalClass;
@ -5529,7 +5529,7 @@ static int GenStateisLangConstruct(sxu32 nKeyword) {
if(rc == FALSE) { if(rc == FALSE) {
if(nKeyword == PH7_TKWRD_SELF || nKeyword == PH7_TKWRD_PARENT || nKeyword == PH7_TKWRD_STATIC if(nKeyword == PH7_TKWRD_SELF || nKeyword == PH7_TKWRD_PARENT || nKeyword == PH7_TKWRD_STATIC
/*|| nKeyword == PH7_TKWRD_CLASS || nKeyword == PH7_TKWRD_FINAL || nKeyword == PH7_TKWRD_EXTENDS /*|| nKeyword == PH7_TKWRD_CLASS || nKeyword == PH7_TKWRD_FINAL || nKeyword == PH7_TKWRD_EXTENDS
|| nKeyword == PH7_TKWRD_ABSTRACT || nKeyword == PH7_TKWRD_INTERFACE || nKeyword == PH7_TKWRD_VIRTUAL || nKeyword == PH7_TKWRD_INTERFACE
|| nKeyword == PH7_TKWRD_PUBLIC || nKeyword == PH7_TKWRD_PROTECTED || nKeyword == PH7_TKWRD_PUBLIC || nKeyword == PH7_TKWRD_PROTECTED
|| nKeyword == PH7_TKWRD_PRIVATE || nKeyword == PH7_TKWRD_IMPLEMENTS || nKeyword == PH7_TKWRD_PRIVATE || nKeyword == PH7_TKWRD_IMPLEMENTS
*/ */

View File

@ -610,7 +610,7 @@ static sxu32 KeywordCode(const char *z, int n) {
{"float", PH7_TKWRD_FLOAT}, {"float", PH7_TKWRD_FLOAT},
{"var", PH7_TKWRD_VAR}, {"var", PH7_TKWRD_VAR},
{"array", PH7_TKWRD_ARRAY}, {"array", PH7_TKWRD_ARRAY},
{"abstract", PH7_TKWRD_ABSTRACT}, {"virtual", PH7_TKWRD_VIRTUAL},
{"class", PH7_TKWRD_CLASS}, {"class", PH7_TKWRD_CLASS},
{"as", PH7_TKWRD_AS}, {"as", PH7_TKWRD_AS},
{"continue", PH7_TKWRD_CONTINUE}, {"continue", PH7_TKWRD_CONTINUE},

View File

@ -293,9 +293,9 @@ PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_vm *pVm, ph7_class *pSub, ph7_class *pBas
} }
continue; continue;
} else { } else {
if(pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) { if(pMeth->iFlags & PH7_CLASS_ATTR_VIRTUAL) {
/* Abstract method must be defined in the child class */ /* Virtual method must be defined in the child class */
rc = VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Abstract method '%z:%z()' must be defined inside child class '%z'", &pBase->sName, pName, &pSub->sName); rc = VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Virtual method '%z:%z()' must be defined inside child class '%z'", &pBase->sName, pName, &pSub->sName);
if(rc == SXERR_ABORT) { if(rc == SXERR_ABORT) {
return SXERR_ABORT; return SXERR_ABORT;
} }

View File

@ -762,7 +762,7 @@ static sxi32 VmMountUserClass(
SyHashResetLoopCursor(&pClass->hMethod); SyHashResetLoopCursor(&pClass->hMethod);
while((pEntry = SyHashGetNextEntry(&pClass->hMethod)) != 0) { while((pEntry = SyHashGetNextEntry(&pClass->hMethod)) != 0) {
pMeth = (ph7_class_method *)pEntry->pUserData; pMeth = (ph7_class_method *)pEntry->pUserData;
if((pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) == 0) { if((pMeth->iFlags & PH7_CLASS_ATTR_VIRTUAL) == 0) {
rc = PH7_VmInstallUserFunction(&(*pVm), &pMeth->sFunc, &pMeth->sVmName); rc = PH7_VmInstallUserFunction(&(*pVm), &pMeth->sFunc, &pMeth->sVmName);
if(rc != SXRET_OK) { if(rc != SXRET_OK) {
return rc; return rc;
@ -4947,9 +4947,9 @@ static sxi32 VmByteCodeExec(
/* Extract the target method */ /* Extract the target method */
pMeth = PH7_ClassExtractMethod(pClass, sName.zString, sName.nByte); pMeth = PH7_ClassExtractMethod(pClass, sName.zString, sName.nByte);
} }
if(pMeth == 0 || (pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT)) { if(pMeth == 0 || (pMeth->iFlags & PH7_CLASS_ATTR_VIRTUAL)) {
if(pMeth) { if(pMeth) {
VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Cannot call abstract method '%z:%z',PH7 is loading NULL", VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Cannot call virtual method '%z:%z',PH7 is loading NULL",
&pClass->sName, &sName &pClass->sName, &sName
); );
} else { } else {
@ -5042,7 +5042,7 @@ static sxi32 VmByteCodeExec(
if((pTos->iFlags & MEMOBJ_STRING) && SyBlobLength(&pTos->sBlob) > 0) { if((pTos->iFlags & MEMOBJ_STRING) && SyBlobLength(&pTos->sBlob) > 0) {
/* Try to extract the desired class */ /* Try to extract the desired class */
pClass = PH7_VmExtractClass(&(*pVm), (const char *)SyBlobData(&pTos->sBlob), pClass = PH7_VmExtractClass(&(*pVm), (const char *)SyBlobData(&pTos->sBlob),
SyBlobLength(&pTos->sBlob), TRUE /* Only loadable class but not 'interface' or 'abstract' class*/, 0); SyBlobLength(&pTos->sBlob), TRUE /* Only loadable class but not 'interface' or 'virtual' class*/, 0);
} else if(pTos->iFlags & MEMOBJ_OBJ) { } else if(pTos->iFlags & MEMOBJ_OBJ) {
/* Take the base class from the loaded instance */ /* Take the base class from the loaded instance */
pClass = ((ph7_class_instance *)pTos->x.pOther)->pClass; pClass = ((ph7_class_instance *)pTos->x.pOther)->pClass;
@ -11718,7 +11718,7 @@ PH7_PRIVATE ph7_class *PH7_VmExtractClass(
const char *zName, /* Name of the target class */ const char *zName, /* Name of the target class */
sxu32 nByte, /* zName length */ sxu32 nByte, /* zName length */
sxi32 iLoadable, /* TRUE to return only loadable class sxi32 iLoadable, /* TRUE to return only loadable class
* [i.e: no abstract classes or interfaces] * [i.e: no virtual classes or interfaces]
*/ */
sxi32 iNest /* Nesting level (Not used) */ sxi32 iNest /* Nesting level (Not used) */
) { ) {
@ -11763,7 +11763,7 @@ PH7_PRIVATE ph7_class *PH7_VmExtractClass(
/* Return the class absolutely */ /* Return the class absolutely */
return pClass; return pClass;
} else { } else {
if((pClass->iFlags & (PH7_CLASS_INTERFACE | PH7_CLASS_ABSTRACT)) == 0) { if((pClass->iFlags & (PH7_CLASS_INTERFACE | PH7_CLASS_VIRTUAL)) == 0) {
/* Class is loadable */ /* Class is loadable */
return pClass; return pClass;
} }

View File

@ -1041,7 +1041,7 @@ struct ph7_class {
ph7_class *pBase; /* Base class if any */ ph7_class *pBase; /* Base class if any */
SyHash hDerived; /* Derived [child] classes */ SyHash hDerived; /* Derived [child] classes */
SyString sName; /* Class full qualified name */ SyString sName; /* Class full qualified name */
sxi32 iFlags; /* Class configuration flags [i.e: final, interface, abstract, etc.] */ sxi32 iFlags; /* Class configuration flags [i.e: final, interface, virtual, etc.] */
SyHash hAttr; /* Class attributes [i.e: variables and constants] */ SyHash hAttr; /* Class attributes [i.e: variables and constants] */
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 */
@ -1050,7 +1050,7 @@ struct ph7_class {
/* 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] */
#define PH7_CLASS_INTERFACE 0x002 /* Class is interface */ #define PH7_CLASS_INTERFACE 0x002 /* Class is interface */
#define PH7_CLASS_ABSTRACT 0x004 /* Class is abstract */ #define PH7_CLASS_VIRTUAL 0x004 /* Class is virtual */
/* Class attribute/methods/constants protection levels */ /* Class attribute/methods/constants protection levels */
#define PH7_CLASS_PROT_PUBLIC 1 /* public */ #define PH7_CLASS_PROT_PUBLIC 1 /* public */
#define PH7_CLASS_PROT_PROTECTED 2 /* protected */ #define PH7_CLASS_PROT_PROTECTED 2 /* protected */
@ -1070,7 +1070,7 @@ struct ph7_class_attr {
/* Attribute configuration */ /* Attribute configuration */
#define PH7_CLASS_ATTR_STATIC 0x001 /* Static attribute */ #define PH7_CLASS_ATTR_STATIC 0x001 /* Static attribute */
#define PH7_CLASS_ATTR_CONSTANT 0x002 /* Constant attribute */ #define PH7_CLASS_ATTR_CONSTANT 0x002 /* Constant attribute */
#define PH7_CLASS_ATTR_ABSTRACT 0x004 /* Abstract method */ #define PH7_CLASS_ATTR_VIRTUAL 0x004 /* Virtual method */
#define PH7_CLASS_ATTR_FINAL 0x008 /* Final method */ #define PH7_CLASS_ATTR_FINAL 0x008 /* Final method */
/* /*
* Each class method is parsed out and stored in an instance of the following * Each class method is parsed out and stored in an instance of the following
@ -1503,7 +1503,7 @@ enum ph7_expr_id {
#define PH7_TKWRD_EVAL 27 /* eval */ #define PH7_TKWRD_EVAL 27 /* eval */
#define PH7_TKWRD_VAR 28 /* var */ #define PH7_TKWRD_VAR 28 /* var */
#define PH7_TKWRD_ARRAY 0x200 /* array: MUST BE A POWER OF TWO */ #define PH7_TKWRD_ARRAY 0x200 /* array: MUST BE A POWER OF TWO */
#define PH7_TKWRD_ABSTRACT 29 /* abstract */ #define PH7_TKWRD_VIRTUAL 29 /* virtual */
#define PH7_TKWRD_TRY 30 /* try */ #define PH7_TKWRD_TRY 30 /* try */
#define PH7_TKWRD_DEFAULT 31 /* default */ #define PH7_TKWRD_DEFAULT 31 /* default */
#define PH7_TKWRD_CLASS 32 /* class */ #define PH7_TKWRD_CLASS 32 /* class */