From 7b3e6c5b76b02557da87135a5546d72d67d50345 Mon Sep 17 00:00:00 2001 From: belliash Date: Mon, 30 Jul 2018 17:08:25 +0200 Subject: [PATCH] P# introduces virtual classes and virtual methods --- engine/compiler.c | 32 ++++++++++++++++---------------- engine/lexer.c | 2 +- engine/oop.c | 6 +++--- engine/vm.c | 12 ++++++------ include/ph7int.h | 8 ++++---- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/engine/compiler.c b/engine/compiler.c index 88b6772..14bbf34 100644 --- a/engine/compiler.c +++ b/engine/compiler.c @@ -3821,11 +3821,11 @@ static sxi32 GenStateCompileClassMethod( nLine = pGen->pIn->nLine; /* Jump the method name */ pGen->pIn++; - if(iFlags & PH7_CLASS_ATTR_ABSTRACT) { - /* Abstract method */ + if(iFlags & PH7_CLASS_ATTR_VIRTUAL) { + /* Virtual method */ if(iProtection == PH7_CLASS_PROT_PRIVATE) { 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); if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -4388,11 +4388,11 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - } else if(nKwrd == PH7_TKWRD_ABSTRACT) { - /* Abstract method,record that */ - iAttrflags |= PH7_CLASS_ATTR_ABSTRACT; - /* Mark the whole class as abstract */ - pClass->iFlags |= PH7_CLASS_ABSTRACT; + } else if(nKwrd == PH7_TKWRD_VIRTUAL) { + /* Virtual method,record that */ + iAttrflags |= PH7_CLASS_ATTR_VIRTUAL; + /* Mark the whole class as virtual */ + pClass->iFlags |= PH7_CLASS_VIRTUAL; /* Advance the stream cursor */ pGen->pIn++; 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 || SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_FUNCTION) { 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); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ @@ -4513,7 +4513,7 @@ done: return PH7_OK; } /* - * Compile a user-defined abstract class. + * Compile a user-defined virtual class. * According to the PHP language reference manual * PHP 5 introduces abstract classes and methods. Classes defined as 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 * could differ. */ -static sxi32 PH7_CompileAbstractClass(ph7_gen_state *pGen) { +static sxi32 PH7_CompileVirtualClass(ph7_gen_state *pGen) { sxi32 rc; - pGen->pIn++; /* Jump the 'abstract' keyword */ - rc = GenStateCompileClass(&(*pGen), PH7_CLASS_ABSTRACT); + pGen->pIn++; /* Jump the 'virtual' keyword */ + rc = GenStateCompileClass(&(*pGen), PH7_CLASS_VIRTUAL); return rc; } /* @@ -5508,9 +5508,9 @@ static ProcLangConstruct GenStateGetStatementHandler( return PH7_CompileClassInterface; } else if(nKeywordID == PH7_TKWRD_CLASS && (pLookahead->nType & PH7_TK_ID)) { 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) { - return PH7_CompileAbstractClass; + return PH7_CompileVirtualClass; } else if(nKeywordID == PH7_TKWRD_FINAL && (pLookahead->nType & PH7_TK_KEYWORD) && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) { return PH7_CompileFinalClass; @@ -5529,7 +5529,7 @@ static int GenStateisLangConstruct(sxu32 nKeyword) { if(rc == FALSE) { 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_ABSTRACT || nKeyword == PH7_TKWRD_INTERFACE + || nKeyword == PH7_TKWRD_VIRTUAL || nKeyword == PH7_TKWRD_INTERFACE || nKeyword == PH7_TKWRD_PUBLIC || nKeyword == PH7_TKWRD_PROTECTED || nKeyword == PH7_TKWRD_PRIVATE || nKeyword == PH7_TKWRD_IMPLEMENTS */ diff --git a/engine/lexer.c b/engine/lexer.c index 285b6e2..1453761 100644 --- a/engine/lexer.c +++ b/engine/lexer.c @@ -610,7 +610,7 @@ static sxu32 KeywordCode(const char *z, int n) { {"float", PH7_TKWRD_FLOAT}, {"var", PH7_TKWRD_VAR}, {"array", PH7_TKWRD_ARRAY}, - {"abstract", PH7_TKWRD_ABSTRACT}, + {"virtual", PH7_TKWRD_VIRTUAL}, {"class", PH7_TKWRD_CLASS}, {"as", PH7_TKWRD_AS}, {"continue", PH7_TKWRD_CONTINUE}, diff --git a/engine/oop.c b/engine/oop.c index 53ca69c..4ef6686 100644 --- a/engine/oop.c +++ b/engine/oop.c @@ -293,9 +293,9 @@ PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_vm *pVm, ph7_class *pSub, ph7_class *pBas } continue; } else { - if(pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) { - /* Abstract 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); + if(pMeth->iFlags & PH7_CLASS_ATTR_VIRTUAL) { + /* Virtual method must be defined in the child class */ + 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) { return SXERR_ABORT; } diff --git a/engine/vm.c b/engine/vm.c index 771f145..d703acf 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -762,7 +762,7 @@ static sxi32 VmMountUserClass( SyHashResetLoopCursor(&pClass->hMethod); while((pEntry = SyHashGetNextEntry(&pClass->hMethod)) != 0) { 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); if(rc != SXRET_OK) { return rc; @@ -4947,9 +4947,9 @@ static sxi32 VmByteCodeExec( /* Extract the target method */ 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) { - 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 ); } else { @@ -5042,7 +5042,7 @@ static sxi32 VmByteCodeExec( if((pTos->iFlags & MEMOBJ_STRING) && SyBlobLength(&pTos->sBlob) > 0) { /* Try to extract the desired class */ 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) { /* Take the base class from the loaded instance */ 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 */ sxu32 nByte, /* zName length */ 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) */ ) { @@ -11763,7 +11763,7 @@ PH7_PRIVATE ph7_class *PH7_VmExtractClass( /* Return the class absolutely */ return pClass; } else { - if((pClass->iFlags & (PH7_CLASS_INTERFACE | PH7_CLASS_ABSTRACT)) == 0) { + if((pClass->iFlags & (PH7_CLASS_INTERFACE | PH7_CLASS_VIRTUAL)) == 0) { /* Class is loadable */ return pClass; } diff --git a/include/ph7int.h b/include/ph7int.h index 38b0231..471a29a 100644 --- a/include/ph7int.h +++ b/include/ph7int.h @@ -1041,7 +1041,7 @@ struct ph7_class { ph7_class *pBase; /* Base class if any */ SyHash hDerived; /* Derived [child] classes */ 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 hMethod; /* Class methods */ sxu32 nLine; /* Line number on which this class was declared */ @@ -1050,7 +1050,7 @@ struct ph7_class { /* Class configuration flags */ #define PH7_CLASS_FINAL 0x001 /* Class is final [cannot be extended] */ #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 */ #define PH7_CLASS_PROT_PUBLIC 1 /* public */ #define PH7_CLASS_PROT_PROTECTED 2 /* protected */ @@ -1070,7 +1070,7 @@ struct ph7_class_attr { /* Attribute configuration */ #define PH7_CLASS_ATTR_STATIC 0x001 /* Static 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 */ /* * 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_VAR 28 /* var */ #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_DEFAULT 31 /* default */ #define PH7_TKWRD_CLASS 32 /* class */