From eb30745e6e5d789deb8994cbe7ed5defb9c58fbe Mon Sep 17 00:00:00 2001 From: yvan-burrie Date: Thu, 2 Aug 2018 04:49:40 +0200 Subject: [PATCH] Enable changes to classes and methods for the VM --- engine/vm.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/engine/vm.c b/engine/vm.c index d703acf..ff2dacc 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -888,8 +888,55 @@ static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int i * Built-in classes/interfaces and some functions that cannot be implemented * directly as foreign functions. */ +#define PH7_BUILTIN_THROWABLE \ + "interface Throwable {}" +#define PH7_BUILTIN_TRAVERSABLE \ + "interface Traversable {}" +#define PH7_BUILTIN_ITERATOR \ + "interface Iterator extends Traversable {"\ + "}"\ + "interface SeekableIterator extends Iterator {"\ + "public function seek($i);"\ + "}" +#define PH7_BUILTIN_COUNTABLE \ + "interface Countable {"\ + "public function count();"\ + "}" +#define PH7_BUILTIN_ARRAYACCESS \ + "interface ArrayAccess {"\ + "public function offsetGet($o);"\ + "public function offsetSet($o, $v);"\ + "}" +#define PH7_BUILTIN_SPL \ + "class SplFixedArray implements ArrayAccess, Countable, Iterator { "\ + "private $list = array();"\ + "public function setSize($s){}"\ + "public function getSize(){}"\ + "public function count(){}"\ + "public function offsetGet(int $o){}"\ + "public function offsetSet(int $o, $v){}"\ + "public function offsetExists(int $o){}"\ + "public function offsetUnset(int $o){}"\ + "}"\ + "class SplDoublyLinkedList implements ArrayAccess, Countable, Iterator { "\ + "private $list = array();"\ + "public function count(){}"\ + "public function add($o, $v){}"\ + "public function offsetGet(int $o){}"\ + "public function offsetSet(int $o, $v){}"\ + "public function offsetExists(int $o){}"\ + "public function offsetUnset(int $o){}"\ + "}"\ + "class ArrayIterator implements ArrayAccess, Countable, Iterator { "\ + "private $list = array();"\ + "public function count(){}"\ + "public function offsetGet($o){}"\ + "public function offsetSet($o, $v){}"\ + "public function offsetExists($o){}"\ + "public function offsetUnset($o){}"\ + "}" #define PH7_BUILTIN_LIB \ - "class Exception { "\ + "class Exception implements Throwable { "\ "protected $message = 'Unknown exception';"\ "protected $code = 0;"\ "protected $file;"\ @@ -1310,6 +1357,34 @@ PH7_PRIVATE sxi32 PH7_VmInit( } /* VM correctly initialized,set the magic number */ pVm->nMagic = PH7_VM_INIT; + + ph7_class *pClass; + /* Compile the Throwable interface */ + SyStringInitFromBuf(&sBuiltin,PH7_BUILTIN_THROWABLE,sizeof(PH7_BUILTIN_THROWABLE)-1); + VmEvalChunk(&(*pVm),0,&sBuiltin,PH7_PHP_CODE,FALSE); + pClass = PH7_VmExtractClass(pVm,"Throwable",sizeof("Throwable")-1,0,0); + pClass->iFlags |= PH7_CLASS_THROWABLE; + /* Compile the Traversable interface */ + SyStringInitFromBuf(&sBuiltin,PH7_BUILTIN_TRAVERSABLE,sizeof(PH7_BUILTIN_TRAVERSABLE)-1); + VmEvalChunk(&(*pVm),0,&sBuiltin,PH7_PHP_CODE,FALSE); + pClass = PH7_VmExtractClass(pVm,"Traversable",sizeof("Traversable")-1,0,0); + pClass->iFlags |= PH7_CLASS_TRAVERSE; + /* Compile the Countable interface */ + SyStringInitFromBuf(&sBuiltin,PH7_BUILTIN_COUNTABLE,sizeof(PH7_BUILTIN_COUNTABLE)-1); + VmEvalChunk(&(*pVm),0,&sBuiltin,PH7_PHP_CODE,FALSE); + pClass = PH7_VmExtractClass(pVm,"Countable",sizeof("Countable")-1,0,0); + pClass->iFlags |= PH7_CLASS_COUNTABLE; + /* Compile the ArrayAccess interface */ + SyStringInitFromBuf(&sBuiltin,PH7_BUILTIN_ARRAYACCESS,sizeof(PH7_BUILTIN_ARRAYACCESS)-1); + VmEvalChunk(&(*pVm),0,&sBuiltin,PH7_PHP_CODE,FALSE); + pClass = PH7_VmExtractClass(pVm,"ArrayAccess",sizeof("ArrayAccess")-1,0,0); + pClass->iFlags |= PH7_CLASS_ARRAYACCESS; + /* Compile the Iterator interfaces */ + SyStringInitFromBuf(&sBuiltin,PH7_BUILTIN_ITERATOR,sizeof(PH7_BUILTIN_ITERATOR)-1); + VmEvalChunk(&(*pVm),0,&sBuiltin,PH7_PHP_CODE,FALSE); + /* Compile the SPL classes */ + SyStringInitFromBuf(&sBuiltin,PH7_BUILTIN_SPL,sizeof(PH7_BUILTIN_SPL)-1); + VmEvalChunk(&(*pVm),0,&sBuiltin,PH7_PHP_CODE,FALSE); SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1); /* Compile the built-in library */ VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_PHP_CODE, FALSE); @@ -4475,11 +4550,8 @@ static sxi32 VmByteCodeExec( pFrame->iFlags |= VM_FRAME_THROW; if(pTos->iFlags & MEMOBJ_OBJ) { ph7_class_instance *pThis = (ph7_class_instance *)pTos->x.pOther; - ph7_class *pException; - /* Make sure the loaded object is an instance of the 'Exception' base class. - */ - pException = PH7_VmExtractClass(&(*pVm), "Exception", sizeof("Exception") - 1, TRUE, 0); - if(pException == 0 || !VmInstanceOf(pThis->pClass, pException)) { + /* Make sure the loaded object is of 'Throwable' implementation. */ + if( (pThis->pClass->iFlags & PH7_CLASS_THROWABLE) == 0 ){ /* Exceptions must be valid objects derived from the Exception base class */ rc = VmUncaughtException(&(*pVm), pThis); if(rc == SXERR_ABORT) { @@ -4823,11 +4895,12 @@ static sxi32 VmByteCodeExec( pMeth = PH7_ClassExtractMethod(pClass, sName.zString, sName.nByte); } if(pMeth == 0) { - VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Call to undefined method '%z->%z()'", - &pClass->sName, &sName - ); - /* Call the '__Call()' magic method if available */ - PH7_ClassInstanceCallMagicMethod(&(*pVm), pClass, pThis, "__call", sizeof("__call") - 1, &sName); + if( pClass->iFlags & PH7_CLASS_CALLABLE ){ + /* Call the '__Call()' magic method if available */ + PH7_ClassInstanceCallMagicMethod(&(*pVm), pClass, pThis, "__call", sizeof("__call") - 1, &sName); + }else{ + VmErrorFormat(&(*pVm),PH7_CTX_ERR,"Undefined class method '%z->%z',PH7 is loading NULL", &pClass->sName,&sName); + } /* Pop the method name from the stack */ VmPopOperand(&pTos, 1); PH7_MemObjRelease(pTos);