diff --git a/cmdLine/rabbit.cpp b/cmdLine/rabbit.cpp index 0945ff9..5bba939 100644 --- a/cmdLine/rabbit.cpp +++ b/cmdLine/rabbit.cpp @@ -36,57 +36,57 @@ void PrintVersionInfos(); #if defined(_MSC_VER) && defined(_DEBUG) int MemAllocHook(int allocType, - void *userData, - size_t size, - int blockType, - long requestNumber, - const unsigned char *filename, - int lineNumber) { - //if(requestNumber==769)_asm int 3; - return 1; + void *userData, + size_t size, + int blockType, + long requestNumber, + const unsigned char *filename, + int lineNumber) { + //if(requestNumber==769)_asm int 3; + return 1; } #endif SQInteger quit(HRABBITVM v) { - int *done; - sq_getuserpointer(v,-1,(SQUserPointer*)&done); - *done=1; - return 0; + int *done; + sq_getuserpointer(v,-1,(SQUserPointer*)&done); + *done=1; + return 0; } void printfunc(HRABBITVM SQ_UNUSED_ARG(v),const SQChar *s,...) { - va_list vl; - va_start(vl, s); - scvprintf(stdout, s, vl); - va_end(vl); + va_list vl; + va_start(vl, s); + scvprintf(stdout, s, vl); + va_end(vl); } void errorfunc(HRABBITVM SQ_UNUSED_ARG(v),const SQChar *s,...) { - va_list vl; - va_start(vl, s); - scvprintf(stderr, s, vl); - va_end(vl); + va_list vl; + va_start(vl, s); + scvprintf(stderr, s, vl); + va_end(vl); } void PrintVersionInfos() { - scfprintf(stdout,_SC("%s %s (%d bits)\n"),RABBIT_VERSION,RABBIT_COPYRIGHT,((int)(sizeof(SQInteger)*8))); + scfprintf(stdout,_SC("%s %s (%d bits)\n"),RABBIT_VERSION,RABBIT_COPYRIGHT,((int)(sizeof(SQInteger)*8))); } void PrintUsage() { - scfprintf(stderr,_SC("usage: sq .\n") - _SC("Available options are:\n") - _SC(" -c compiles the file to bytecode(default output 'out.karrot')\n") - _SC(" -o specifies output file for the -c option\n") - _SC(" -c compiles only\n") - _SC(" -d generates debug infos\n") - _SC(" -v displays version infos\n") - _SC(" -h prints help\n")); + scfprintf(stderr,_SC("usage: sq .\n") + _SC("Available options are:\n") + _SC(" -c compiles the file to bytecode(default output 'out.karrot')\n") + _SC(" -o specifies output file for the -c option\n") + _SC(" -c compiles only\n") + _SC(" -d generates debug infos\n") + _SC(" -v displays version infos\n") + _SC(" -h prints help\n")); } #define _INTERACTIVE 0 @@ -95,265 +95,265 @@ void PrintUsage() //<> this func is a mess int getargs(HRABBITVM v,int argc, char* argv[],SQInteger *retval) { - int i; - int compiles_only = 0; + int i; + int compiles_only = 0; #ifdef SQUNICODE - static SQChar temp[500]; + static SQChar temp[500]; #endif - char * output = NULL; - *retval = 0; - if(argc>1) - { - int arg=1,exitloop=0; + char * output = NULL; + *retval = 0; + if(argc>1) + { + int arg=1,exitloop=0; - while(arg < argc && !exitloop) - { + while(arg < argc && !exitloop) + { - if(argv[arg][0]=='-') - { - switch(argv[arg][1]) - { - case 'd': - sq_enabledebuginfo(v,1); - break; - case 'c': - compiles_only = 1; - break; - case 'o': - if(arg < argc) { - arg++; - output = argv[arg]; - } - break; - case 'v': - PrintVersionInfos(); - return _DONE; + if(argv[arg][0]=='-') + { + switch(argv[arg][1]) + { + case 'd': + sq_enabledebuginfo(v,1); + break; + case 'c': + compiles_only = 1; + break; + case 'o': + if(arg < argc) { + arg++; + output = argv[arg]; + } + break; + case 'v': + PrintVersionInfos(); + return _DONE; - case 'h': - PrintVersionInfos(); - PrintUsage(); - return _DONE; - default: - PrintVersionInfos(); - scprintf(_SC("unknown prameter '-%c'\n"),argv[arg][1]); - PrintUsage(); - *retval = -1; - return _ERROR; - } - }else break; - arg++; - } + case 'h': + PrintVersionInfos(); + PrintUsage(); + return _DONE; + default: + PrintVersionInfos(); + scprintf(_SC("unknown prameter '-%c'\n"),argv[arg][1]); + PrintUsage(); + *retval = -1; + return _ERROR; + } + }else break; + arg++; + } - // src file + // src file - if(arg ")); - for(;;) { - int c; - if(done)return; - c = getchar(); - if (c == _SC('\n')) { - if (i>0 && buffer[i-1] == _SC('\\')) - { - buffer[i-1] = _SC('\n'); - } - else if(blocks==0)break; - buffer[i++] = _SC('\n'); - } - else if (c==_SC('}')) {blocks--; buffer[i++] = (SQChar)c;} - else if(c==_SC('{') && !string){ - blocks++; - buffer[i++] = (SQChar)c; - } - else if(c==_SC('"') || c==_SC('\'')){ - string=!string; - buffer[i++] = (SQChar)c; - } - else if (i >= MAXINPUT-1) { - scfprintf(stderr, _SC("sq : input line too long\n")); - break; - } - else{ - buffer[i++] = (SQChar)c; - } - } - buffer[i] = _SC('\0'); + while (!done) + { + SQInteger i = 0; + scprintf(_SC("\nrabbit> ")); + for(;;) { + int c; + if(done)return; + c = getchar(); + if (c == _SC('\n')) { + if (i>0 && buffer[i-1] == _SC('\\')) + { + buffer[i-1] = _SC('\n'); + } + else if(blocks==0)break; + buffer[i++] = _SC('\n'); + } + else if (c==_SC('}')) {blocks--; buffer[i++] = (SQChar)c;} + else if(c==_SC('{') && !string){ + blocks++; + buffer[i++] = (SQChar)c; + } + else if(c==_SC('"') || c==_SC('\'')){ + string=!string; + buffer[i++] = (SQChar)c; + } + else if (i >= MAXINPUT-1) { + scfprintf(stderr, _SC("sq : input line too long\n")); + break; + } + else{ + buffer[i++] = (SQChar)c; + } + } + buffer[i] = _SC('\0'); - if(buffer[0]==_SC('=')){ - scsprintf(sq_getscratchpad(v,MAXINPUT),(size_t)MAXINPUT,_SC("return (%s)"),&buffer[1]); - memcpy(buffer,sq_getscratchpad(v,-1),(scstrlen(sq_getscratchpad(v,-1))+1)*sizeof(SQChar)); - retval=1; - } - i=scstrlen(buffer); - if(i>0){ - SQInteger oldtop=sq_gettop(v); - if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,_SC("interactive console"),SQTrue))){ - sq_pushroottable(v); - if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) && retval){ - scprintf(_SC("\n")); - sq_pushroottable(v); - sq_pushstring(v,_SC("print"),-1); - sq_get(v,-2); - sq_pushroottable(v); - sq_push(v,-4); - sq_call(v,2,SQFalse,SQTrue); - retval=0; - scprintf(_SC("\n")); - } - } + if(buffer[0]==_SC('=')){ + scsprintf(sq_getscratchpad(v,MAXINPUT),(size_t)MAXINPUT,_SC("return (%s)"),&buffer[1]); + memcpy(buffer,sq_getscratchpad(v,-1),(scstrlen(sq_getscratchpad(v,-1))+1)*sizeof(SQChar)); + retval=1; + } + i=scstrlen(buffer); + if(i>0){ + SQInteger oldtop=sq_gettop(v); + if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,_SC("interactive console"),SQTrue))){ + sq_pushroottable(v); + if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) && retval){ + scprintf(_SC("\n")); + sq_pushroottable(v); + sq_pushstring(v,_SC("print"),-1); + sq_get(v,-2); + sq_pushroottable(v); + sq_push(v,-4); + sq_call(v,2,SQFalse,SQTrue); + retval=0; + scprintf(_SC("\n")); + } + } - sq_settop(v,oldtop); - } - } + sq_settop(v,oldtop); + } + } } int main(int argc, char* argv[]) { - HRABBITVM v; - SQInteger retval = 0; + HRABBITVM v; + SQInteger retval = 0; #if defined(_MSC_VER) && defined(_DEBUG) - _CrtSetAllocHook(MemAllocHook); + _CrtSetAllocHook(MemAllocHook); #endif - v=sq_open(1024); - sq_setprintfunc(v,printfunc,errorfunc); + v=sq_open(1024); + sq_setprintfunc(v,printfunc,errorfunc); - sq_pushroottable(v); + sq_pushroottable(v); - sqstd_register_bloblib(v); - sqstd_register_iolib(v); - sqstd_register_systemlib(v); - sqstd_register_mathlib(v); - sqstd_register_stringlib(v); + sqstd_register_bloblib(v); + sqstd_register_iolib(v); + sqstd_register_systemlib(v); + sqstd_register_mathlib(v); + sqstd_register_stringlib(v); - //aux library - //sets error handlers - sqstd_seterrorhandlers(v); + //aux library + //sets error handlers + sqstd_seterrorhandlers(v); - //gets arguments - switch(getargs(v,argc,argv,&retval)) - { - case _INTERACTIVE: - Interactive(v); - break; - case _DONE: - case _ERROR: - default: - break; - } + //gets arguments + switch(getargs(v,argc,argv,&retval)) + { + case _INTERACTIVE: + Interactive(v); + break; + case _DONE: + case _ERROR: + default: + break; + } - sq_close(v); + sq_close(v); #if defined(_MSC_VER) && defined(_DEBUG) - _getch(); - _CrtMemDumpAllObjectsSince( NULL ); + _getch(); + _CrtMemDumpAllObjectsSince( NULL ); #endif - return retval; + return retval; } diff --git a/doc/source/conf.py b/doc/source/conf.py index dc534ad..144f10e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -30,7 +30,7 @@ import time # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.pngmath', + 'sphinx.ext.pngmath', ] # Add any paths that contain templates here, relative to this directory. @@ -225,10 +225,10 @@ latex_elements = { # author, documentclass [howto, manual, or own class]). _stdauthor = r'Alberto Demichelis' latex_documents = [ - ('reference/index', 'reference.tex', - 'Squirrel Reference Manual', _stdauthor, 'manual'), - ('stdlib/index', 'stdlib.tex', - 'Squirrel Standard Library', _stdauthor, 'manual'), + ('reference/index', 'reference.tex', + 'Squirrel Reference Manual', _stdauthor, 'manual'), + ('stdlib/index', 'stdlib.tex', + 'Squirrel Standard Library', _stdauthor, 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -257,8 +257,8 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'Squirrel', u'Squirrel Documentation', - [author], 1) + (master_doc, 'Squirrel', u'Squirrel Documentation', + [author], 1) ] # If true, show URL addresses after external links. @@ -271,9 +271,9 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Squirrel', u'Squirrel Documentation', - author, 'Squirrel', 'The Programming Language.', - 'Miscellaneous'), + (master_doc, 'Squirrel', u'Squirrel Documentation', + author, 'Squirrel', 'The Programming Language.', + 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. diff --git a/etc/minimal.cpp b/etc/minimal.cpp index 0695768..1a77adc 100644 --- a/etc/minimal.cpp +++ b/etc/minimal.cpp @@ -20,59 +20,59 @@ void printfunc(HSQUIRRELVM v,const SQChar *s,...) { - va_list vl; - va_start(vl, s); - scvprintf(stdout, s, vl); - va_end(vl); + va_list vl; + va_start(vl, s); + scvprintf(stdout, s, vl); + va_end(vl); } void errorfunc(HSQUIRRELVM v,const SQChar *s,...) { - va_list vl; - va_start(vl, s); - scvprintf(stderr, s, vl); - va_end(vl); + va_list vl; + va_start(vl, s); + scvprintf(stderr, s, vl); + va_end(vl); } void call_foo(HSQUIRRELVM v, int n,float f,const SQChar *s) { - SQInteger top = sq_gettop(v); //saves the stack size before the call - sq_pushroottable(v); //pushes the global table - sq_pushstring(v,_SC("foo"),-1); - if(SQ_SUCCEEDED(sq_get(v,-2))) { //gets the field 'foo' from the global table - sq_pushroottable(v); //push the 'this' (in this case is the global table) - sq_pushinteger(v,n); - sq_pushfloat(v,f); - sq_pushstring(v,s,-1); - sq_call(v,4,SQFalse,SQTrue); //calls the function - } - sq_settop(v,top); //restores the original stack size + SQInteger top = sq_gettop(v); //saves the stack size before the call + sq_pushroottable(v); //pushes the global table + sq_pushstring(v,_SC("foo"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { //gets the field 'foo' from the global table + sq_pushroottable(v); //push the 'this' (in this case is the global table) + sq_pushinteger(v,n); + sq_pushfloat(v,f); + sq_pushstring(v,s,-1); + sq_call(v,4,SQFalse,SQTrue); //calls the function + } + sq_settop(v,top); //restores the original stack size } int main(int argc, char* argv[]) { - HSQUIRRELVM v; - v = sq_open(1024); // creates a VM with initial stack size 1024 + HSQUIRRELVM v; + v = sq_open(1024); // creates a VM with initial stack size 1024 - //REGISTRATION OF STDLIB - //sq_pushroottable(v); //push the root table where the std function will be registered - //sqstd_register_iolib(v); //registers a library - // ... call here other stdlibs string,math etc... - //sq_pop(v,1); //pops the root table - //END REGISTRATION OF STDLIB + //REGISTRATION OF STDLIB + //sq_pushroottable(v); //push the root table where the std function will be registered + //sqstd_register_iolib(v); //registers a library + // ... call here other stdlibs string,math etc... + //sq_pop(v,1); //pops the root table + //END REGISTRATION OF STDLIB - sqstd_seterrorhandlers(v); //registers the default error handlers + sqstd_seterrorhandlers(v); //registers the default error handlers - sq_setprintfunc(v, printfunc,errorfunc); //sets the print function + sq_setprintfunc(v, printfunc,errorfunc); //sets the print function - sq_pushroottable(v); //push the root table(were the globals of the script will be stored) - if(SQ_SUCCEEDED(sqstd_dofile(v, _SC("test.nut"), SQFalse, SQTrue))) // also prints syntax errors if any - { - call_foo(v,1,2.5,_SC("teststring")); - } + sq_pushroottable(v); //push the root table(were the globals of the script will be stored) + if(SQ_SUCCEEDED(sqstd_dofile(v, _SC("test.nut"), SQFalse, SQTrue))) // also prints syntax errors if any + { + call_foo(v,1,2.5,_SC("teststring")); + } - sq_pop(v,1); //pops the root table - sq_close(v); + sq_pop(v,1); //pops the root table + sq_close(v); - return 0; + return 0; } diff --git a/lutin_rabbit-core.py b/lutin_rabbit-core.py index 32a9d06..d430864 100644 --- a/lutin_rabbit-core.py +++ b/lutin_rabbit-core.py @@ -27,45 +27,45 @@ def get_version(): def configure(target, my_module): my_module.add_src_file([ - 'rabbit/sqmem.cpp', - 'rabbit/sqbaselib.cpp', - 'rabbit/sqapi.cpp', - 'rabbit/sqlexer.cpp', - 'rabbit/sqclass.cpp', - 'rabbit/sqvm.cpp', - 'rabbit/sqtable.cpp', - 'rabbit/sqstate.cpp', - 'rabbit/sqobject.cpp', - 'rabbit/sqcompiler.cpp', - 'rabbit/sqdebug.cpp', - 'rabbit/sqfuncstate.cpp', - ]) + 'rabbit/sqmem.cpp', + 'rabbit/sqbaselib.cpp', + 'rabbit/sqapi.cpp', + 'rabbit/sqlexer.cpp', + 'rabbit/sqclass.cpp', + 'rabbit/sqvm.cpp', + 'rabbit/sqtable.cpp', + 'rabbit/sqstate.cpp', + 'rabbit/sqobject.cpp', + 'rabbit/sqcompiler.cpp', + 'rabbit/sqdebug.cpp', + 'rabbit/sqfuncstate.cpp', + ]) my_module.compile_version("c++", 2011) my_module.add_depend([ - 'z', - 'm', - 'c' - ]) + 'z', + 'm', + 'c' + ]) my_module.add_header_file([ - 'rabbit/sqclass.hpp', - 'rabbit/sqvm.hpp', - 'rabbit/sqstate.hpp', - 'rabbit/rabbit.hpp', - 'rabbit/sqobject.hpp', - 'rabbit/sqopcodes.hpp', - 'rabbit/squserdata.hpp', - 'rabbit/squtils.hpp', - 'rabbit/sqpcheader.hpp', - 'rabbit/sqfuncproto.hpp', - 'rabbit/sqconfig.hpp', - 'rabbit/sqcompiler.hpp', - 'rabbit/sqarray.hpp', - 'rabbit/sqclosure.hpp', - 'rabbit/sqlexer.hpp', - 'rabbit/sqfuncstate.hpp', - 'rabbit/sqstring.hpp', - 'rabbit/sqtable.hpp', - ]) + 'rabbit/sqclass.hpp', + 'rabbit/sqvm.hpp', + 'rabbit/sqstate.hpp', + 'rabbit/rabbit.hpp', + 'rabbit/sqobject.hpp', + 'rabbit/sqopcodes.hpp', + 'rabbit/squserdata.hpp', + 'rabbit/squtils.hpp', + 'rabbit/sqpcheader.hpp', + 'rabbit/sqfuncproto.hpp', + 'rabbit/sqconfig.hpp', + 'rabbit/sqcompiler.hpp', + 'rabbit/sqarray.hpp', + 'rabbit/sqclosure.hpp', + 'rabbit/sqlexer.hpp', + 'rabbit/sqfuncstate.hpp', + 'rabbit/sqstring.hpp', + 'rabbit/sqtable.hpp', + ]) return True diff --git a/lutin_rabbit-std.py b/lutin_rabbit-std.py index cb5c2ec..be023e7 100644 --- a/lutin_rabbit-std.py +++ b/lutin_rabbit-std.py @@ -27,29 +27,29 @@ def get_version(): def configure(target, my_module): my_module.add_src_file([ - 'rabbit-std/sqstdaux.cpp', - 'rabbit-std/sqstdstream.cpp', - 'rabbit-std/sqstdrex.cpp', - 'rabbit-std/sqstdsystem.cpp', - 'rabbit-std/sqstdio.cpp', - 'rabbit-std/sqstdblob.cpp', - 'rabbit-std/sqstdmath.cpp', - 'rabbit-std/sqstdstring.cpp', - ]) + 'rabbit-std/sqstdaux.cpp', + 'rabbit-std/sqstdstream.cpp', + 'rabbit-std/sqstdrex.cpp', + 'rabbit-std/sqstdsystem.cpp', + 'rabbit-std/sqstdio.cpp', + 'rabbit-std/sqstdblob.cpp', + 'rabbit-std/sqstdmath.cpp', + 'rabbit-std/sqstdstring.cpp', + ]) my_module.compile_version("c++", 2011) my_module.add_depend([ - 'rabbit-core' - ]) + 'rabbit-core' + ]) my_module.add_header_file([ - 'rabbit-std/sqstdstring.hpp', - 'rabbit-std/sqstdmath.hpp', - 'rabbit-std/sqstdaux.hpp', - 'rabbit-std/sqstdsystem.hpp', - 'rabbit-std/sqstdblobimpl.hpp', - 'rabbit-std/sqstdstream.hpp', - 'rabbit-std/sqstdio.hpp', - 'rabbit-std/sqstdblob.hpp', - ]) + 'rabbit-std/sqstdstring.hpp', + 'rabbit-std/sqstdmath.hpp', + 'rabbit-std/sqstdaux.hpp', + 'rabbit-std/sqstdsystem.hpp', + 'rabbit-std/sqstdblobimpl.hpp', + 'rabbit-std/sqstdstream.hpp', + 'rabbit-std/sqstdio.hpp', + 'rabbit-std/sqstdblob.hpp', + ]) return True diff --git a/lutin_rabbit.py b/lutin_rabbit.py index bd48bf7..f843cc2 100644 --- a/lutin_rabbit.py +++ b/lutin_rabbit.py @@ -27,14 +27,14 @@ def get_version(): def configure(target, my_module): my_module.add_src_file([ - 'cmdLine/rabbit.cpp', - ]) + 'cmdLine/rabbit.cpp', + ]) my_module.compile_version("c++", 2011) my_module.add_depend([ - 'rabbit-core', - 'rabbit-std', - 'cxx', - ]) + 'rabbit-core', + 'rabbit-std', + 'cxx', + ]) return True diff --git a/rabbit-std/sqstdaux.cpp b/rabbit-std/sqstdaux.cpp index 88adcf2..9ffd92d 100644 --- a/rabbit-std/sqstdaux.cpp +++ b/rabbit-std/sqstdaux.cpp @@ -12,126 +12,126 @@ void sqstd_printcallstack(HRABBITVM v) { - SQPRINTFUNCTION pf = sq_geterrorfunc(v); - if(pf) { - SQStackInfos si; - SQInteger i; - SQFloat f; - const SQChar *s; - SQInteger level=1; //1 is to skip this function that is level 0 - const SQChar *name=0; - SQInteger seq=0; - pf(v,_SC("\nCALLSTACK\n")); - while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si))) - { - const SQChar *fn=_SC("unknown"); - const SQChar *src=_SC("unknown"); - if(si.funcname)fn=si.funcname; - if(si.source)src=si.source; - pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line); - level++; - } - level=0; - pf(v,_SC("\nLOCALS\n")); + SQPRINTFUNCTION pf = sq_geterrorfunc(v); + if(pf) { + SQStackInfos si; + SQInteger i; + SQFloat f; + const SQChar *s; + SQInteger level=1; //1 is to skip this function that is level 0 + const SQChar *name=0; + SQInteger seq=0; + pf(v,_SC("\nCALLSTACK\n")); + while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si))) + { + const SQChar *fn=_SC("unknown"); + const SQChar *src=_SC("unknown"); + if(si.funcname)fn=si.funcname; + if(si.source)src=si.source; + pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line); + level++; + } + level=0; + pf(v,_SC("\nLOCALS\n")); - for(level=0;level<10;level++){ - seq=0; - while((name = sq_getlocal(v,level,seq))) - { - seq++; - switch(sq_gettype(v,-1)) - { - case OT_NULL: - pf(v,_SC("[%s] NULL\n"),name); - break; - case OT_INTEGER: - sq_getinteger(v,-1,&i); - pf(v,_SC("[%s] %d\n"),name,i); - break; - case OT_FLOAT: - sq_getfloat(v,-1,&f); - pf(v,_SC("[%s] %.14g\n"),name,f); - break; - case OT_USERPOINTER: - pf(v,_SC("[%s] USERPOINTER\n"),name); - break; - case OT_STRING: - sq_getstring(v,-1,&s); - pf(v,_SC("[%s] \"%s\"\n"),name,s); - break; - case OT_TABLE: - pf(v,_SC("[%s] TABLE\n"),name); - break; - case OT_ARRAY: - pf(v,_SC("[%s] ARRAY\n"),name); - break; - case OT_CLOSURE: - pf(v,_SC("[%s] CLOSURE\n"),name); - break; - case OT_NATIVECLOSURE: - pf(v,_SC("[%s] NATIVECLOSURE\n"),name); - break; - case OT_GENERATOR: - pf(v,_SC("[%s] GENERATOR\n"),name); - break; - case OT_USERDATA: - pf(v,_SC("[%s] USERDATA\n"),name); - break; - case OT_THREAD: - pf(v,_SC("[%s] THREAD\n"),name); - break; - case OT_CLASS: - pf(v,_SC("[%s] CLASS\n"),name); - break; - case OT_INSTANCE: - pf(v,_SC("[%s] INSTANCE\n"),name); - break; - case OT_WEAKREF: - pf(v,_SC("[%s] WEAKREF\n"),name); - break; - case OT_BOOL:{ - SQBool bval; - sq_getbool(v,-1,&bval); - pf(v,_SC("[%s] %s\n"),name,bval == SQTrue ? _SC("true"):_SC("false")); - } - break; - default: assert(0); break; - } - sq_pop(v,1); - } - } - } + for(level=0;level<10;level++){ + seq=0; + while((name = sq_getlocal(v,level,seq))) + { + seq++; + switch(sq_gettype(v,-1)) + { + case OT_NULL: + pf(v,_SC("[%s] NULL\n"),name); + break; + case OT_INTEGER: + sq_getinteger(v,-1,&i); + pf(v,_SC("[%s] %d\n"),name,i); + break; + case OT_FLOAT: + sq_getfloat(v,-1,&f); + pf(v,_SC("[%s] %.14g\n"),name,f); + break; + case OT_USERPOINTER: + pf(v,_SC("[%s] USERPOINTER\n"),name); + break; + case OT_STRING: + sq_getstring(v,-1,&s); + pf(v,_SC("[%s] \"%s\"\n"),name,s); + break; + case OT_TABLE: + pf(v,_SC("[%s] TABLE\n"),name); + break; + case OT_ARRAY: + pf(v,_SC("[%s] ARRAY\n"),name); + break; + case OT_CLOSURE: + pf(v,_SC("[%s] CLOSURE\n"),name); + break; + case OT_NATIVECLOSURE: + pf(v,_SC("[%s] NATIVECLOSURE\n"),name); + break; + case OT_GENERATOR: + pf(v,_SC("[%s] GENERATOR\n"),name); + break; + case OT_USERDATA: + pf(v,_SC("[%s] USERDATA\n"),name); + break; + case OT_THREAD: + pf(v,_SC("[%s] THREAD\n"),name); + break; + case OT_CLASS: + pf(v,_SC("[%s] CLASS\n"),name); + break; + case OT_INSTANCE: + pf(v,_SC("[%s] INSTANCE\n"),name); + break; + case OT_WEAKREF: + pf(v,_SC("[%s] WEAKREF\n"),name); + break; + case OT_BOOL:{ + SQBool bval; + sq_getbool(v,-1,&bval); + pf(v,_SC("[%s] %s\n"),name,bval == SQTrue ? _SC("true"):_SC("false")); + } + break; + default: assert(0); break; + } + sq_pop(v,1); + } + } + } } static SQInteger _sqstd_aux_printerror(HRABBITVM v) { - SQPRINTFUNCTION pf = sq_geterrorfunc(v); - if(pf) { - const SQChar *sErr = 0; - if(sq_gettop(v)>=1) { - if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { - pf(v,_SC("\nAN ERROR HAS OCCURRED [%s]\n"),sErr); - } - else{ - pf(v,_SC("\nAN ERROR HAS OCCURRED [unknown]\n")); - } - sqstd_printcallstack(v); - } - } - return 0; + SQPRINTFUNCTION pf = sq_geterrorfunc(v); + if(pf) { + const SQChar *sErr = 0; + if(sq_gettop(v)>=1) { + if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { + pf(v,_SC("\nAN ERROR HAS OCCURRED [%s]\n"),sErr); + } + else{ + pf(v,_SC("\nAN ERROR HAS OCCURRED [unknown]\n")); + } + sqstd_printcallstack(v); + } + } + return 0; } void _sqstd_compiler_error(HRABBITVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column) { - SQPRINTFUNCTION pf = sq_geterrorfunc(v); - if(pf) { - pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr); - } + SQPRINTFUNCTION pf = sq_geterrorfunc(v); + if(pf) { + pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr); + } } void sqstd_seterrorhandlers(HRABBITVM v) { - sq_setcompilererrorhandler(v,_sqstd_compiler_error); - sq_newclosure(v,_sqstd_aux_printerror,0); - sq_seterrorhandler(v); + sq_setcompilererrorhandler(v,_sqstd_compiler_error); + sq_newclosure(v,_sqstd_aux_printerror,0); + sq_seterrorhandler(v); } diff --git a/rabbit-std/sqstdblob.cpp b/rabbit-std/sqstdblob.cpp index 8ed9bb0..7b45660 100644 --- a/rabbit-std/sqstdblob.cpp +++ b/rabbit-std/sqstdblob.cpp @@ -13,172 +13,172 @@ #define SETUP_BLOB(v) \ - SQBlob *self = NULL; \ - { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ - return sq_throwerror(v,_SC("invalid type tag")); } \ - if(!self || !self->IsValid()) \ - return sq_throwerror(v,_SC("the blob is invalid")); + SQBlob *self = NULL; \ + { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ + return sq_throwerror(v,_SC("invalid type tag")); } \ + if(!self || !self->IsValid()) \ + return sq_throwerror(v,_SC("the blob is invalid")); static SQInteger _blob_resize(HRABBITVM v) { - SETUP_BLOB(v); - SQInteger size; - sq_getinteger(v,2,&size); - if(!self->Resize(size)) - return sq_throwerror(v,_SC("resize failed")); - return 0; + SETUP_BLOB(v); + SQInteger size; + sq_getinteger(v,2,&size); + if(!self->Resize(size)) + return sq_throwerror(v,_SC("resize failed")); + return 0; } static void __swap_dword(unsigned int *n) { - *n=(unsigned int)(((*n&0xFF000000)>>24) | - ((*n&0x00FF0000)>>8) | - ((*n&0x0000FF00)<<8) | - ((*n&0x000000FF)<<24)); + *n=(unsigned int)(((*n&0xFF000000)>>24) | + ((*n&0x00FF0000)>>8) | + ((*n&0x0000FF00)<<8) | + ((*n&0x000000FF)<<24)); } static void __swap_word(unsigned short *n) { - *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00); + *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00); } static SQInteger _blob_swap4(HRABBITVM v) { - SETUP_BLOB(v); - SQInteger num=(self->Len()-(self->Len()%4))>>2; - unsigned int *t=(unsigned int *)self->GetBuf(); - for(SQInteger i = 0; i < num; i++) { - __swap_dword(&t[i]); - } - return 0; + SETUP_BLOB(v); + SQInteger num=(self->Len()-(self->Len()%4))>>2; + unsigned int *t=(unsigned int *)self->GetBuf(); + for(SQInteger i = 0; i < num; i++) { + __swap_dword(&t[i]); + } + return 0; } static SQInteger _blob_swap2(HRABBITVM v) { - SETUP_BLOB(v); - SQInteger num=(self->Len()-(self->Len()%2))>>1; - unsigned short *t = (unsigned short *)self->GetBuf(); - for(SQInteger i = 0; i < num; i++) { - __swap_word(&t[i]); - } - return 0; + SETUP_BLOB(v); + SQInteger num=(self->Len()-(self->Len()%2))>>1; + unsigned short *t = (unsigned short *)self->GetBuf(); + for(SQInteger i = 0; i < num; i++) { + __swap_word(&t[i]); + } + return 0; } static SQInteger _blob__set(HRABBITVM v) { - SETUP_BLOB(v); - SQInteger idx,val; - sq_getinteger(v,2,&idx); - sq_getinteger(v,3,&val); - if(idx < 0 || idx >= self->Len()) - return sq_throwerror(v,_SC("index out of range")); - ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val; - sq_push(v,3); - return 1; + SETUP_BLOB(v); + SQInteger idx,val; + sq_getinteger(v,2,&idx); + sq_getinteger(v,3,&val); + if(idx < 0 || idx >= self->Len()) + return sq_throwerror(v,_SC("index out of range")); + ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val; + sq_push(v,3); + return 1; } static SQInteger _blob__get(HRABBITVM v) { - SETUP_BLOB(v); - SQInteger idx; + SETUP_BLOB(v); + SQInteger idx; if ((sq_gettype(v, 2) & SQOBJECT_NUMERIC) == 0) { sq_pushnull(v); return sq_throwobject(v); } - sq_getinteger(v,2,&idx); - if(idx < 0 || idx >= self->Len()) - return sq_throwerror(v,_SC("index out of range")); - sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]); - return 1; + sq_getinteger(v,2,&idx); + if(idx < 0 || idx >= self->Len()) + return sq_throwerror(v,_SC("index out of range")); + sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]); + return 1; } static SQInteger _blob__nexti(HRABBITVM v) { - SETUP_BLOB(v); - if(sq_gettype(v,2) == OT_NULL) { - sq_pushinteger(v, 0); - return 1; - } - SQInteger idx; - if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) { - if(idx+1 < self->Len()) { - sq_pushinteger(v, idx+1); - return 1; - } - sq_pushnull(v); - return 1; - } - return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type")); + SETUP_BLOB(v); + if(sq_gettype(v,2) == OT_NULL) { + sq_pushinteger(v, 0); + return 1; + } + SQInteger idx; + if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) { + if(idx+1 < self->Len()) { + sq_pushinteger(v, idx+1); + return 1; + } + sq_pushnull(v); + return 1; + } + return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type")); } static SQInteger _blob__typeof(HRABBITVM v) { - sq_pushstring(v,_SC("blob"),-1); - return 1; + sq_pushstring(v,_SC("blob"),-1); + return 1; } static SQInteger _blob_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size)) { - SQBlob *self = (SQBlob*)p; - self->~SQBlob(); - sq_free(self,sizeof(SQBlob)); - return 1; + SQBlob *self = (SQBlob*)p; + self->~SQBlob(); + sq_free(self,sizeof(SQBlob)); + return 1; } static SQInteger _blob_constructor(HRABBITVM v) { - SQInteger nparam = sq_gettop(v); - SQInteger size = 0; - if(nparam == 2) { - sq_getinteger(v, 2, &size); - } - if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); - //SQBlob *b = new SQBlob(size); + SQInteger nparam = sq_gettop(v); + SQInteger size = 0; + if(nparam == 2) { + sq_getinteger(v, 2, &size); + } + if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); + //SQBlob *b = new SQBlob(size); - SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size); - if(SQ_FAILED(sq_setinstanceup(v,1,b))) { - b->~SQBlob(); - sq_free(b,sizeof(SQBlob)); - return sq_throwerror(v, _SC("cannot create blob")); - } - sq_setreleasehook(v,1,_blob_releasehook); - return 0; + SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size); + if(SQ_FAILED(sq_setinstanceup(v,1,b))) { + b->~SQBlob(); + sq_free(b,sizeof(SQBlob)); + return sq_throwerror(v, _SC("cannot create blob")); + } + sq_setreleasehook(v,1,_blob_releasehook); + return 0; } static SQInteger _blob__cloned(HRABBITVM v) { - SQBlob *other = NULL; - { - if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) - return SQ_ERROR; - } - //SQBlob *thisone = new SQBlob(other->Len()); - SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len()); - memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len()); - if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) { - thisone->~SQBlob(); - sq_free(thisone,sizeof(SQBlob)); - return sq_throwerror(v, _SC("cannot clone blob")); - } - sq_setreleasehook(v,1,_blob_releasehook); - return 0; + SQBlob *other = NULL; + { + if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + return SQ_ERROR; + } + //SQBlob *thisone = new SQBlob(other->Len()); + SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len()); + memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len()); + if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) { + thisone->~SQBlob(); + sq_free(thisone,sizeof(SQBlob)); + return sq_throwerror(v, _SC("cannot clone blob")); + } + sq_setreleasehook(v,1,_blob_releasehook); + return 0; } #define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck} static const SQRegFunction _blob_methods[] = { - _DECL_BLOB_FUNC(constructor,-1,_SC("xn")), - _DECL_BLOB_FUNC(resize,2,_SC("xn")), - _DECL_BLOB_FUNC(swap2,1,_SC("x")), - _DECL_BLOB_FUNC(swap4,1,_SC("x")), - _DECL_BLOB_FUNC(_set,3,_SC("xnn")), - _DECL_BLOB_FUNC(_get,2,_SC("x.")), - _DECL_BLOB_FUNC(_typeof,1,_SC("x")), - _DECL_BLOB_FUNC(_nexti,2,_SC("x")), - _DECL_BLOB_FUNC(_cloned,2,_SC("xx")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_BLOB_FUNC(constructor,-1,_SC("xn")), + _DECL_BLOB_FUNC(resize,2,_SC("xn")), + _DECL_BLOB_FUNC(swap2,1,_SC("x")), + _DECL_BLOB_FUNC(swap4,1,_SC("x")), + _DECL_BLOB_FUNC(_set,3,_SC("xnn")), + _DECL_BLOB_FUNC(_get,2,_SC("x.")), + _DECL_BLOB_FUNC(_typeof,1,_SC("x")), + _DECL_BLOB_FUNC(_nexti,2,_SC("x")), + _DECL_BLOB_FUNC(_cloned,2,_SC("xx")), + {NULL,(SQFUNCTION)0,0,NULL} }; @@ -187,97 +187,97 @@ static const SQRegFunction _blob_methods[] = { static SQInteger _g_blob_casti2f(HRABBITVM v) { - SQInteger i; - sq_getinteger(v,2,&i); - sq_pushfloat(v,*((const SQFloat *)&i)); - return 1; + SQInteger i; + sq_getinteger(v,2,&i); + sq_pushfloat(v,*((const SQFloat *)&i)); + return 1; } static SQInteger _g_blob_castf2i(HRABBITVM v) { - SQFloat f; - sq_getfloat(v,2,&f); - sq_pushinteger(v,*((const SQInteger *)&f)); - return 1; + SQFloat f; + sq_getfloat(v,2,&f); + sq_pushinteger(v,*((const SQInteger *)&f)); + return 1; } static SQInteger _g_blob_swap2(HRABBITVM v) { - SQInteger i; - sq_getinteger(v,2,&i); - short s=(short)i; - sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF)); - return 1; + SQInteger i; + sq_getinteger(v,2,&i); + short s=(short)i; + sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF)); + return 1; } static SQInteger _g_blob_swap4(HRABBITVM v) { - SQInteger i; - sq_getinteger(v,2,&i); - unsigned int t4 = (unsigned int)i; - __swap_dword(&t4); - sq_pushinteger(v,(SQInteger)t4); - return 1; + SQInteger i; + sq_getinteger(v,2,&i); + unsigned int t4 = (unsigned int)i; + __swap_dword(&t4); + sq_pushinteger(v,(SQInteger)t4); + return 1; } static SQInteger _g_blob_swapfloat(HRABBITVM v) { - SQFloat f; - sq_getfloat(v,2,&f); - __swap_dword((unsigned int *)&f); - sq_pushfloat(v,f); - return 1; + SQFloat f; + sq_getfloat(v,2,&f); + __swap_dword((unsigned int *)&f); + sq_pushfloat(v,f); + return 1; } #define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck} static const SQRegFunction bloblib_funcs[]={ - _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")), + {NULL,(SQFUNCTION)0,0,NULL} }; SQRESULT sqstd_getblob(HRABBITVM v,SQInteger idx,SQUserPointer *ptr) { - SQBlob *blob; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) - return -1; - *ptr = blob->GetBuf(); - return SQ_OK; + SQBlob *blob; + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + return -1; + *ptr = blob->GetBuf(); + return SQ_OK; } SQInteger sqstd_getblobsize(HRABBITVM v,SQInteger idx) { - SQBlob *blob; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) - return -1; - return blob->Len(); + SQBlob *blob; + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + return -1; + return blob->Len(); } SQUserPointer sqstd_createblob(HRABBITVM v, SQInteger size) { - SQInteger top = sq_gettop(v); - sq_pushregistrytable(v); - sq_pushstring(v,_SC("std_blob"),-1); - if(SQ_SUCCEEDED(sq_get(v,-2))) { - sq_remove(v,-2); //removes the registry - sq_push(v,1); // push the this - sq_pushinteger(v,size); //size - SQBlob *blob = NULL; - if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse)) - && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) { - sq_remove(v,-2); - return blob->GetBuf(); - } - } - sq_settop(v,top); - return NULL; + SQInteger top = sq_gettop(v); + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_blob"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { + sq_remove(v,-2); //removes the registry + sq_push(v,1); // push the this + sq_pushinteger(v,size); //size + SQBlob *blob = NULL; + if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse)) + && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) { + sq_remove(v,-2); + return blob->GetBuf(); + } + } + sq_settop(v,top); + return NULL; } SQRESULT sqstd_register_bloblib(HRABBITVM v) { - return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs); + return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs); } diff --git a/rabbit-std/sqstdblobimpl.hpp b/rabbit-std/sqstdblobimpl.hpp index 60c8cad..cb364e2 100644 --- a/rabbit-std/sqstdblobimpl.hpp +++ b/rabbit-std/sqstdblobimpl.hpp @@ -9,104 +9,104 @@ struct SQBlob : public SQStream { - SQBlob(SQInteger size) { - _size = size; - _allocated = size; - _buf = (unsigned char *)sq_malloc(size); - memset(_buf, 0, _size); - _ptr = 0; - _owns = true; - } - virtual ~SQBlob() { - sq_free(_buf, _allocated); - } - SQInteger Write(void *buffer, SQInteger size) { - if(!CanAdvance(size)) { - GrowBufOf(_ptr + size - _size); - } - memcpy(&_buf[_ptr], buffer, size); - _ptr += size; - return size; - } - SQInteger Read(void *buffer,SQInteger size) { - SQInteger n = size; - if(!CanAdvance(size)) { - if((_size - _ptr) > 0) - n = _size - _ptr; - else return 0; - } - memcpy(buffer, &_buf[_ptr], n); - _ptr += n; - return n; - } - bool Resize(SQInteger n) { - if(!_owns) return false; - if(n != _allocated) { - unsigned char *newbuf = (unsigned char *)sq_malloc(n); - memset(newbuf,0,n); - if(_size > n) - memcpy(newbuf,_buf,n); - else - memcpy(newbuf,_buf,_size); - sq_free(_buf,_allocated); - _buf=newbuf; - _allocated = n; - if(_size > _allocated) - _size = _allocated; - if(_ptr > _allocated) - _ptr = _allocated; - } - return true; - } - bool GrowBufOf(SQInteger n) - { - bool ret = true; - if(_size + n > _allocated) { - if(_size + n > _size * 2) - ret = Resize(_size + n); - else - ret = Resize(_size * 2); - } - _size = _size + n; - return ret; - } - bool CanAdvance(SQInteger n) { - if(_ptr+n>_size)return false; - return true; - } - SQInteger Seek(SQInteger offset, SQInteger origin) { - switch(origin) { - case SQ_SEEK_SET: - if(offset > _size || offset < 0) return -1; - _ptr = offset; - break; - case SQ_SEEK_CUR: - if(_ptr + offset > _size || _ptr + offset < 0) return -1; - _ptr += offset; - break; - case SQ_SEEK_END: - if(_size + offset > _size || _size + offset < 0) return -1; - _ptr = _size + offset; - break; - default: return -1; - } - return 0; - } - bool IsValid() { - return _size == 0 || _buf?true:false; - } - bool EOS() { - return _ptr == _size; - } - SQInteger Flush() { return 0; } - SQInteger Tell() { return _ptr; } - SQInteger Len() { return _size; } - SQUserPointer GetBuf(){ return _buf; } + SQBlob(SQInteger size) { + _size = size; + _allocated = size; + _buf = (unsigned char *)sq_malloc(size); + memset(_buf, 0, _size); + _ptr = 0; + _owns = true; + } + virtual ~SQBlob() { + sq_free(_buf, _allocated); + } + SQInteger Write(void *buffer, SQInteger size) { + if(!CanAdvance(size)) { + GrowBufOf(_ptr + size - _size); + } + memcpy(&_buf[_ptr], buffer, size); + _ptr += size; + return size; + } + SQInteger Read(void *buffer,SQInteger size) { + SQInteger n = size; + if(!CanAdvance(size)) { + if((_size - _ptr) > 0) + n = _size - _ptr; + else return 0; + } + memcpy(buffer, &_buf[_ptr], n); + _ptr += n; + return n; + } + bool Resize(SQInteger n) { + if(!_owns) return false; + if(n != _allocated) { + unsigned char *newbuf = (unsigned char *)sq_malloc(n); + memset(newbuf,0,n); + if(_size > n) + memcpy(newbuf,_buf,n); + else + memcpy(newbuf,_buf,_size); + sq_free(_buf,_allocated); + _buf=newbuf; + _allocated = n; + if(_size > _allocated) + _size = _allocated; + if(_ptr > _allocated) + _ptr = _allocated; + } + return true; + } + bool GrowBufOf(SQInteger n) + { + bool ret = true; + if(_size + n > _allocated) { + if(_size + n > _size * 2) + ret = Resize(_size + n); + else + ret = Resize(_size * 2); + } + _size = _size + n; + return ret; + } + bool CanAdvance(SQInteger n) { + if(_ptr+n>_size)return false; + return true; + } + SQInteger Seek(SQInteger offset, SQInteger origin) { + switch(origin) { + case SQ_SEEK_SET: + if(offset > _size || offset < 0) return -1; + _ptr = offset; + break; + case SQ_SEEK_CUR: + if(_ptr + offset > _size || _ptr + offset < 0) return -1; + _ptr += offset; + break; + case SQ_SEEK_END: + if(_size + offset > _size || _size + offset < 0) return -1; + _ptr = _size + offset; + break; + default: return -1; + } + return 0; + } + bool IsValid() { + return _size == 0 || _buf?true:false; + } + bool EOS() { + return _ptr == _size; + } + SQInteger Flush() { return 0; } + SQInteger Tell() { return _ptr; } + SQInteger Len() { return _size; } + SQUserPointer GetBuf(){ return _buf; } private: - SQInteger _size; - SQInteger _allocated; - SQInteger _ptr; - unsigned char *_buf; - bool _owns; + SQInteger _size; + SQInteger _allocated; + SQInteger _ptr; + unsigned char *_buf; + bool _owns; }; diff --git a/rabbit-std/sqstdio.cpp b/rabbit-std/sqstdio.cpp index 90cc9ab..354634c 100644 --- a/rabbit-std/sqstdio.cpp +++ b/rabbit-std/sqstdio.cpp @@ -17,480 +17,480 @@ SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode) { #ifndef SQUNICODE - return (SQFILE)fopen(filename,mode); + return (SQFILE)fopen(filename,mode); #else - return (SQFILE)_wfopen(filename,mode); + return (SQFILE)_wfopen(filename,mode); #endif } SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file) { - SQInteger ret = (SQInteger)fread(buffer,size,count,(FILE *)file); - return ret; + SQInteger ret = (SQInteger)fread(buffer,size,count,(FILE *)file); + return ret; } SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file) { - return (SQInteger)fwrite(buffer,size,count,(FILE *)file); + return (SQInteger)fwrite(buffer,size,count,(FILE *)file); } SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin) { - SQInteger realorigin; - switch(origin) { - case SQ_SEEK_CUR: realorigin = SEEK_CUR; break; - case SQ_SEEK_END: realorigin = SEEK_END; break; - case SQ_SEEK_SET: realorigin = SEEK_SET; break; - default: return -1; //failed - } - return fseek((FILE *)file,(long)offset,(int)realorigin); + SQInteger realorigin; + switch(origin) { + case SQ_SEEK_CUR: realorigin = SEEK_CUR; break; + case SQ_SEEK_END: realorigin = SEEK_END; break; + case SQ_SEEK_SET: realorigin = SEEK_SET; break; + default: return -1; //failed + } + return fseek((FILE *)file,(long)offset,(int)realorigin); } SQInteger sqstd_ftell(SQFILE file) { - return ftell((FILE *)file); + return ftell((FILE *)file); } SQInteger sqstd_fflush(SQFILE file) { - return fflush((FILE *)file); + return fflush((FILE *)file); } SQInteger sqstd_fclose(SQFILE file) { - return fclose((FILE *)file); + return fclose((FILE *)file); } SQInteger sqstd_feof(SQFILE file) { - return feof((FILE *)file); + return feof((FILE *)file); } //File struct SQFile : public SQStream { - SQFile() { _handle = NULL; _owns = false;} - SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;} - virtual ~SQFile() { Close(); } - bool Open(const SQChar *filename ,const SQChar *mode) { - Close(); - if( (_handle = sqstd_fopen(filename,mode)) ) { - _owns = true; - return true; - } - return false; - } - void Close() { - if(_handle && _owns) { - sqstd_fclose(_handle); - _handle = NULL; - _owns = false; - } - } - SQInteger Read(void *buffer,SQInteger size) { - return sqstd_fread(buffer,1,size,_handle); - } - SQInteger Write(void *buffer,SQInteger size) { - return sqstd_fwrite(buffer,1,size,_handle); - } - SQInteger Flush() { - return sqstd_fflush(_handle); - } - SQInteger Tell() { - return sqstd_ftell(_handle); - } - SQInteger Len() { - SQInteger prevpos=Tell(); - Seek(0,SQ_SEEK_END); - SQInteger size=Tell(); - Seek(prevpos,SQ_SEEK_SET); - return size; - } - SQInteger Seek(SQInteger offset, SQInteger origin) { - return sqstd_fseek(_handle,offset,origin); - } - bool IsValid() { return _handle?true:false; } - bool EOS() { return Tell()==Len()?true:false;} - SQFILE GetHandle() {return _handle;} + SQFile() { _handle = NULL; _owns = false;} + SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;} + virtual ~SQFile() { Close(); } + bool Open(const SQChar *filename ,const SQChar *mode) { + Close(); + if( (_handle = sqstd_fopen(filename,mode)) ) { + _owns = true; + return true; + } + return false; + } + void Close() { + if(_handle && _owns) { + sqstd_fclose(_handle); + _handle = NULL; + _owns = false; + } + } + SQInteger Read(void *buffer,SQInteger size) { + return sqstd_fread(buffer,1,size,_handle); + } + SQInteger Write(void *buffer,SQInteger size) { + return sqstd_fwrite(buffer,1,size,_handle); + } + SQInteger Flush() { + return sqstd_fflush(_handle); + } + SQInteger Tell() { + return sqstd_ftell(_handle); + } + SQInteger Len() { + SQInteger prevpos=Tell(); + Seek(0,SQ_SEEK_END); + SQInteger size=Tell(); + Seek(prevpos,SQ_SEEK_SET); + return size; + } + SQInteger Seek(SQInteger offset, SQInteger origin) { + return sqstd_fseek(_handle,offset,origin); + } + bool IsValid() { return _handle?true:false; } + bool EOS() { return Tell()==Len()?true:false;} + SQFILE GetHandle() {return _handle;} private: - SQFILE _handle; - bool _owns; + SQFILE _handle; + bool _owns; }; static SQInteger _file__typeof(HRABBITVM v) { - sq_pushstring(v,_SC("file"),-1); - return 1; + sq_pushstring(v,_SC("file"),-1); + return 1; } static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size)) { - SQFile *self = (SQFile*)p; - self->~SQFile(); - sq_free(self,sizeof(SQFile)); - return 1; + SQFile *self = (SQFile*)p; + self->~SQFile(); + sq_free(self,sizeof(SQFile)); + return 1; } static SQInteger _file_constructor(HRABBITVM v) { - const SQChar *filename,*mode; - bool owns = true; - SQFile *f; - SQFILE newf; - if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) { - sq_getstring(v, 2, &filename); - sq_getstring(v, 3, &mode); - newf = sqstd_fopen(filename, mode); - if(!newf) return sq_throwerror(v, _SC("cannot open file")); - } else if(sq_gettype(v,2) == OT_USERPOINTER) { - owns = !(sq_gettype(v,3) == OT_NULL); - sq_getuserpointer(v,2,&newf); - } else { - return sq_throwerror(v,_SC("wrong parameter")); - } + const SQChar *filename,*mode; + bool owns = true; + SQFile *f; + SQFILE newf; + if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) { + sq_getstring(v, 2, &filename); + sq_getstring(v, 3, &mode); + newf = sqstd_fopen(filename, mode); + if(!newf) return sq_throwerror(v, _SC("cannot open file")); + } else if(sq_gettype(v,2) == OT_USERPOINTER) { + owns = !(sq_gettype(v,3) == OT_NULL); + sq_getuserpointer(v,2,&newf); + } else { + return sq_throwerror(v,_SC("wrong parameter")); + } - f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns); - if(SQ_FAILED(sq_setinstanceup(v,1,f))) { - f->~SQFile(); - sq_free(f,sizeof(SQFile)); - return sq_throwerror(v, _SC("cannot create blob with negative size")); - } - sq_setreleasehook(v,1,_file_releasehook); - return 0; + f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns); + if(SQ_FAILED(sq_setinstanceup(v,1,f))) { + f->~SQFile(); + sq_free(f,sizeof(SQFile)); + return sq_throwerror(v, _SC("cannot create blob with negative size")); + } + sq_setreleasehook(v,1,_file_releasehook); + return 0; } static SQInteger _file_close(HRABBITVM v) { - SQFile *self = NULL; - if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG)) - && self != NULL) - { - self->Close(); - } - return 0; + SQFile *self = NULL; + if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG)) + && self != NULL) + { + self->Close(); + } + return 0; } //bindings #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck} static const SQRegFunction _file_methods[] = { - _DECL_FILE_FUNC(constructor,3,_SC("x")), - _DECL_FILE_FUNC(_typeof,1,_SC("x")), - _DECL_FILE_FUNC(close,1,_SC("x")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_FILE_FUNC(constructor,3,_SC("x")), + _DECL_FILE_FUNC(_typeof,1,_SC("x")), + _DECL_FILE_FUNC(close,1,_SC("x")), + {NULL,(SQFUNCTION)0,0,NULL} }; SQRESULT sqstd_createfile(HRABBITVM v, SQFILE file,SQBool own) { - SQInteger top = sq_gettop(v); - sq_pushregistrytable(v); - sq_pushstring(v,_SC("std_file"),-1); - if(SQ_SUCCEEDED(sq_get(v,-2))) { - sq_remove(v,-2); //removes the registry - sq_pushroottable(v); // push the this - sq_pushuserpointer(v,file); //file - if(own){ - sq_pushinteger(v,1); //true - } - else{ - sq_pushnull(v); //false - } - if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) { - sq_remove(v,-2); - return SQ_OK; - } - } - sq_settop(v,top); - return SQ_ERROR; + SQInteger top = sq_gettop(v); + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_file"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { + sq_remove(v,-2); //removes the registry + sq_pushroottable(v); // push the this + sq_pushuserpointer(v,file); //file + if(own){ + sq_pushinteger(v,1); //true + } + else{ + sq_pushnull(v); //false + } + if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) { + sq_remove(v,-2); + return SQ_OK; + } + } + sq_settop(v,top); + return SQ_ERROR; } SQRESULT sqstd_getfile(HRABBITVM v, SQInteger idx, SQFILE *file) { - SQFile *fileobj = NULL; - if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) { - *file = fileobj->GetHandle(); - return SQ_OK; - } - return sq_throwerror(v,_SC("not a file")); + SQFile *fileobj = NULL; + if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) { + *file = fileobj->GetHandle(); + return SQ_OK; + } + return sq_throwerror(v,_SC("not a file")); } #define IO_BUFFER_SIZE 2048 struct IOBuffer { - unsigned char buffer[IO_BUFFER_SIZE]; - SQInteger size; - SQInteger ptr; - SQFILE file; + unsigned char buffer[IO_BUFFER_SIZE]; + SQInteger size; + SQInteger ptr; + SQFILE file; }; SQInteger _read_byte(IOBuffer *iobuffer) { - if(iobuffer->ptr < iobuffer->size) { + if(iobuffer->ptr < iobuffer->size) { - SQInteger ret = iobuffer->buffer[iobuffer->ptr]; - iobuffer->ptr++; - return ret; - } - else { - if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 ) - { - SQInteger ret = iobuffer->buffer[0]; - iobuffer->ptr = 1; - return ret; - } - } + SQInteger ret = iobuffer->buffer[iobuffer->ptr]; + iobuffer->ptr++; + return ret; + } + else { + if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 ) + { + SQInteger ret = iobuffer->buffer[0]; + iobuffer->ptr = 1; + return ret; + } + } - return 0; + return 0; } SQInteger _read_two_bytes(IOBuffer *iobuffer) { - if(iobuffer->ptr < iobuffer->size) { - if(iobuffer->size < 2) return 0; - SQInteger ret = *((const wchar_t*)&iobuffer->buffer[iobuffer->ptr]); - iobuffer->ptr += 2; - return ret; - } - else { - if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 ) - { - if(iobuffer->size < 2) return 0; - SQInteger ret = *((const wchar_t*)&iobuffer->buffer[0]); - iobuffer->ptr = 2; - return ret; - } - } + if(iobuffer->ptr < iobuffer->size) { + if(iobuffer->size < 2) return 0; + SQInteger ret = *((const wchar_t*)&iobuffer->buffer[iobuffer->ptr]); + iobuffer->ptr += 2; + return ret; + } + else { + if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 ) + { + if(iobuffer->size < 2) return 0; + SQInteger ret = *((const wchar_t*)&iobuffer->buffer[0]); + iobuffer->ptr = 2; + return ret; + } + } - return 0; + return 0; } static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer iobuf) { - IOBuffer *iobuffer = (IOBuffer *)iobuf; - return _read_byte(iobuffer); + IOBuffer *iobuffer = (IOBuffer *)iobuf; + return _read_byte(iobuffer); } #ifdef SQUNICODE static SQInteger _io_file_lexfeed_UTF8(SQUserPointer iobuf) { - IOBuffer *iobuffer = (IOBuffer *)iobuf; + IOBuffer *iobuffer = (IOBuffer *)iobuf; #define READ(iobuf) \ - if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \ - return 0; + if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \ + return 0; - static const SQInteger utf8_lengths[16] = - { - 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */ - 0,0,0,0, /* 1000 to 1011 : not valid */ - 2,2, /* 1100, 1101 : 2 bytes */ - 3, /* 1110 : 3 bytes */ - 4 /* 1111 :4 bytes */ - }; - static const unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07}; - unsigned char inchar; - SQInteger c = 0; - READ(iobuffer); - c = inchar; - // - if(c >= 0x80) { - SQInteger tmp; - SQInteger codelen = utf8_lengths[c>>4]; - if(codelen == 0) - return 0; - //"invalid UTF-8 stream"; - tmp = c&byte_masks[codelen]; - for(SQInteger n = 0; n < codelen-1; n++) { - tmp<<=6; - READ(iobuffer); - tmp |= inchar & 0x3F; - } - c = tmp; - } - return c; + static const SQInteger utf8_lengths[16] = + { + 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */ + 0,0,0,0, /* 1000 to 1011 : not valid */ + 2,2, /* 1100, 1101 : 2 bytes */ + 3, /* 1110 : 3 bytes */ + 4 /* 1111 :4 bytes */ + }; + static const unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07}; + unsigned char inchar; + SQInteger c = 0; + READ(iobuffer); + c = inchar; + // + if(c >= 0x80) { + SQInteger tmp; + SQInteger codelen = utf8_lengths[c>>4]; + if(codelen == 0) + return 0; + //"invalid UTF-8 stream"; + tmp = c&byte_masks[codelen]; + for(SQInteger n = 0; n < codelen-1; n++) { + tmp<<=6; + READ(iobuffer); + tmp |= inchar & 0x3F; + } + c = tmp; + } + return c; } #endif static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer iobuf) { - SQInteger ret; - IOBuffer *iobuffer = (IOBuffer *)iobuf; - if( (ret = _read_two_bytes(iobuffer)) > 0 ) - return ret; - return 0; + SQInteger ret; + IOBuffer *iobuffer = (IOBuffer *)iobuf; + if( (ret = _read_two_bytes(iobuffer)) > 0 ) + return ret; + return 0; } static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer iobuf) { - SQInteger c; - IOBuffer *iobuffer = (IOBuffer *)iobuf; - if( (c = _read_two_bytes(iobuffer)) > 0 ) { - c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00); - return c; - } - return 0; + SQInteger c; + IOBuffer *iobuffer = (IOBuffer *)iobuf; + if( (c = _read_two_bytes(iobuffer)) > 0 ) { + c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00); + return c; + } + return 0; } SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size) { - SQInteger ret; - if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret; - return -1; + SQInteger ret; + if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret; + return -1; } SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size) { - return sqstd_fwrite(p,1,size,(SQFILE)file); + return sqstd_fwrite(p,1,size,(SQFILE)file); } SQRESULT sqstd_loadfile(HRABBITVM v,const SQChar *filename,SQBool printerror) { - SQFILE file = sqstd_fopen(filename,_SC("rb")); + SQFILE file = sqstd_fopen(filename,_SC("rb")); - SQInteger ret; - unsigned short us; - unsigned char uc; - SQLEXREADFUNC func = _io_file_lexfeed_PLAIN; - if(file){ - ret = sqstd_fread(&us,1,2,file); - if(ret != 2) { - //probably an empty file - us = 0; - } - if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE - sqstd_fseek(file,0,SQ_SEEK_SET); - if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) { - sqstd_fclose(file); - return SQ_OK; - } - } - else { //SCRIPT + SQInteger ret; + unsigned short us; + unsigned char uc; + SQLEXREADFUNC func = _io_file_lexfeed_PLAIN; + if(file){ + ret = sqstd_fread(&us,1,2,file); + if(ret != 2) { + //probably an empty file + us = 0; + } + if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE + sqstd_fseek(file,0,SQ_SEEK_SET); + if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) { + sqstd_fclose(file); + return SQ_OK; + } + } + else { //SCRIPT - switch(us) - { - //gotta swap the next 2 lines on BIG endian machines - case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian; - case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian; - case 0xBBEF: - if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { - sqstd_fclose(file); - return sq_throwerror(v,_SC("io error")); - } - if(uc != 0xBF) { - sqstd_fclose(file); - return sq_throwerror(v,_SC("Unrecognized encoding")); - } + switch(us) + { + //gotta swap the next 2 lines on BIG endian machines + case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian; + case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian; + case 0xBBEF: + if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { + sqstd_fclose(file); + return sq_throwerror(v,_SC("io error")); + } + if(uc != 0xBF) { + sqstd_fclose(file); + return sq_throwerror(v,_SC("Unrecognized encoding")); + } #ifdef SQUNICODE - func = _io_file_lexfeed_UTF8; + func = _io_file_lexfeed_UTF8; #else - func = _io_file_lexfeed_PLAIN; + func = _io_file_lexfeed_PLAIN; #endif - break;//UTF-8 ; - default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii - } - IOBuffer buffer; - buffer.ptr = 0; - buffer.size = 0; - buffer.file = file; - if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,filename,printerror))){ - sqstd_fclose(file); - return SQ_OK; - } - } - sqstd_fclose(file); - return SQ_ERROR; - } - return sq_throwerror(v,_SC("cannot open the file")); + break;//UTF-8 ; + default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii + } + IOBuffer buffer; + buffer.ptr = 0; + buffer.size = 0; + buffer.file = file; + if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,filename,printerror))){ + sqstd_fclose(file); + return SQ_OK; + } + } + sqstd_fclose(file); + return SQ_ERROR; + } + return sq_throwerror(v,_SC("cannot open the file")); } SQRESULT sqstd_dofile(HRABBITVM v,const SQChar *filename,SQBool retval,SQBool printerror) { - //at least one entry must exist in order for us to push it as the environment - if(sq_gettop(v) == 0) - return sq_throwerror(v,_SC("environment table expected")); + //at least one entry must exist in order for us to push it as the environment + if(sq_gettop(v) == 0) + return sq_throwerror(v,_SC("environment table expected")); - if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) { - sq_push(v,-2); - if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) { - sq_remove(v,retval?-2:-1); //removes the closure - return 1; - } - sq_pop(v,1); //removes the closure - } - return SQ_ERROR; + if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) { + sq_push(v,-2); + if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) { + sq_remove(v,retval?-2:-1); //removes the closure + return 1; + } + sq_pop(v,1); //removes the closure + } + return SQ_ERROR; } SQRESULT sqstd_writeclosuretofile(HRABBITVM v,const SQChar *filename) { - SQFILE file = sqstd_fopen(filename,_SC("wb+")); - if(!file) return sq_throwerror(v,_SC("cannot open the file")); - if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) { - sqstd_fclose(file); - return SQ_OK; - } - sqstd_fclose(file); - return SQ_ERROR; //forward the error + SQFILE file = sqstd_fopen(filename,_SC("wb+")); + if(!file) return sq_throwerror(v,_SC("cannot open the file")); + if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) { + sqstd_fclose(file); + return SQ_OK; + } + sqstd_fclose(file); + return SQ_ERROR; //forward the error } SQInteger _g_io_loadfile(HRABBITVM v) { - const SQChar *filename; - SQBool printerror = SQFalse; - sq_getstring(v,2,&filename); - if(sq_gettop(v) >= 3) { - sq_getbool(v,3,&printerror); - } - if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) - return 1; - return SQ_ERROR; //propagates the error + const SQChar *filename; + SQBool printerror = SQFalse; + sq_getstring(v,2,&filename); + if(sq_gettop(v) >= 3) { + sq_getbool(v,3,&printerror); + } + if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) + return 1; + return SQ_ERROR; //propagates the error } SQInteger _g_io_writeclosuretofile(HRABBITVM v) { - const SQChar *filename; - sq_getstring(v,2,&filename); - if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename))) - return 1; - return SQ_ERROR; //propagates the error + const SQChar *filename; + sq_getstring(v,2,&filename); + if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename))) + return 1; + return SQ_ERROR; //propagates the error } SQInteger _g_io_dofile(HRABBITVM v) { - const SQChar *filename; - SQBool printerror = SQFalse; - sq_getstring(v,2,&filename); - if(sq_gettop(v) >= 3) { - sq_getbool(v,3,&printerror); - } - sq_push(v,1); //repush the this - if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror))) - return 1; - return SQ_ERROR; //propagates the error + const SQChar *filename; + SQBool printerror = SQFalse; + sq_getstring(v,2,&filename); + if(sq_gettop(v) >= 3) { + sq_getbool(v,3,&printerror); + } + sq_push(v,1); //repush the this + if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror))) + return 1; + return SQ_ERROR; //propagates the error } #define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck} static const SQRegFunction iolib_funcs[]={ - _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")), - _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")), - _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")), + _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")), + _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")), + {NULL,(SQFUNCTION)0,0,NULL} }; SQRESULT sqstd_register_iolib(HRABBITVM v) { - SQInteger top = sq_gettop(v); - //create delegate - declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs); - sq_pushstring(v,_SC("stdout"),-1); - sqstd_createfile(v,stdout,SQFalse); - sq_newslot(v,-3,SQFalse); - sq_pushstring(v,_SC("stdin"),-1); - sqstd_createfile(v,stdin,SQFalse); - sq_newslot(v,-3,SQFalse); - sq_pushstring(v,_SC("stderr"),-1); - sqstd_createfile(v,stderr,SQFalse); - sq_newslot(v,-3,SQFalse); - sq_settop(v,top); - return SQ_OK; + SQInteger top = sq_gettop(v); + //create delegate + declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs); + sq_pushstring(v,_SC("stdout"),-1); + sqstd_createfile(v,stdout,SQFalse); + sq_newslot(v,-3,SQFalse); + sq_pushstring(v,_SC("stdin"),-1); + sqstd_createfile(v,stdin,SQFalse); + sq_newslot(v,-3,SQFalse); + sq_pushstring(v,_SC("stderr"),-1); + sqstd_createfile(v,stderr,SQFalse); + sq_newslot(v,-3,SQFalse); + sq_settop(v,top); + return SQ_OK; } diff --git a/rabbit-std/sqstdio.hpp b/rabbit-std/sqstdio.hpp index bd80b47..7d801a9 100644 --- a/rabbit-std/sqstdio.hpp +++ b/rabbit-std/sqstdio.hpp @@ -10,15 +10,15 @@ #define SQSTD_STREAM_TYPE_TAG 0x80000000 struct SQStream { - virtual ~SQStream() {} - virtual SQInteger Read(void *buffer, SQInteger size) = 0; - virtual SQInteger Write(void *buffer, SQInteger size) = 0; - virtual SQInteger Flush() = 0; - virtual SQInteger Tell() = 0; - virtual SQInteger Len() = 0; - virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0; - virtual bool IsValid() = 0; - virtual bool EOS() = 0; + virtual ~SQStream() {} + virtual SQInteger Read(void *buffer, SQInteger size) = 0; + virtual SQInteger Write(void *buffer, SQInteger size) = 0; + virtual SQInteger Flush() = 0; + virtual SQInteger Tell() = 0; + virtual SQInteger Len() = 0; + virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0; + virtual bool IsValid() = 0; + virtual bool EOS() = 0; }; #define SQ_SEEK_CUR 0 diff --git a/rabbit-std/sqstdmath.cpp b/rabbit-std/sqstdmath.cpp index 7fe68d3..68324e9 100644 --- a/rabbit-std/sqstdmath.cpp +++ b/rabbit-std/sqstdmath.cpp @@ -12,41 +12,41 @@ #include #define SINGLE_ARG_FUNC(_funcname) static SQInteger math_##_funcname(HRABBITVM v){ \ - SQFloat f; \ - sq_getfloat(v,2,&f); \ - sq_pushfloat(v,(SQFloat)_funcname(f)); \ - return 1; \ + SQFloat f; \ + sq_getfloat(v,2,&f); \ + sq_pushfloat(v,(SQFloat)_funcname(f)); \ + return 1; \ } #define TWO_ARGS_FUNC(_funcname) static SQInteger math_##_funcname(HRABBITVM v){ \ - SQFloat p1,p2; \ - sq_getfloat(v,2,&p1); \ - sq_getfloat(v,3,&p2); \ - sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \ - return 1; \ + SQFloat p1,p2; \ + sq_getfloat(v,2,&p1); \ + sq_getfloat(v,3,&p2); \ + sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \ + return 1; \ } static SQInteger math_srand(HRABBITVM v) { - SQInteger i; - if(SQ_FAILED(sq_getinteger(v,2,&i))) - return sq_throwerror(v,_SC("invalid param")); - srand((unsigned int)i); - return 0; + SQInteger i; + if(SQ_FAILED(sq_getinteger(v,2,&i))) + return sq_throwerror(v,_SC("invalid param")); + srand((unsigned int)i); + return 0; } static SQInteger math_rand(HRABBITVM v) { - sq_pushinteger(v,rand()); - return 1; + sq_pushinteger(v,rand()); + return 1; } static SQInteger math_abs(HRABBITVM v) { - SQInteger n; - sq_getinteger(v,2,&n); - sq_pushinteger(v,(SQInteger)abs((int)n)); - return 1; + SQInteger n; + sq_getinteger(v,2,&n); + sq_pushinteger(v,(SQInteger)abs((int)n)); + return 1; } SINGLE_ARG_FUNC(sqrt) @@ -67,25 +67,25 @@ SINGLE_ARG_FUNC(exp) #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck} static const SQRegFunction mathlib_funcs[] = { - _DECL_FUNC(sqrt,2,_SC(".n")), - _DECL_FUNC(sin,2,_SC(".n")), - _DECL_FUNC(cos,2,_SC(".n")), - _DECL_FUNC(asin,2,_SC(".n")), - _DECL_FUNC(acos,2,_SC(".n")), - _DECL_FUNC(log,2,_SC(".n")), - _DECL_FUNC(log10,2,_SC(".n")), - _DECL_FUNC(tan,2,_SC(".n")), - _DECL_FUNC(atan,2,_SC(".n")), - _DECL_FUNC(atan2,3,_SC(".nn")), - _DECL_FUNC(pow,3,_SC(".nn")), - _DECL_FUNC(floor,2,_SC(".n")), - _DECL_FUNC(ceil,2,_SC(".n")), - _DECL_FUNC(exp,2,_SC(".n")), - _DECL_FUNC(srand,2,_SC(".n")), - _DECL_FUNC(rand,1,NULL), - _DECL_FUNC(fabs,2,_SC(".n")), - _DECL_FUNC(abs,2,_SC(".n")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_FUNC(sqrt,2,_SC(".n")), + _DECL_FUNC(sin,2,_SC(".n")), + _DECL_FUNC(cos,2,_SC(".n")), + _DECL_FUNC(asin,2,_SC(".n")), + _DECL_FUNC(acos,2,_SC(".n")), + _DECL_FUNC(log,2,_SC(".n")), + _DECL_FUNC(log10,2,_SC(".n")), + _DECL_FUNC(tan,2,_SC(".n")), + _DECL_FUNC(atan,2,_SC(".n")), + _DECL_FUNC(atan2,3,_SC(".nn")), + _DECL_FUNC(pow,3,_SC(".nn")), + _DECL_FUNC(floor,2,_SC(".n")), + _DECL_FUNC(ceil,2,_SC(".n")), + _DECL_FUNC(exp,2,_SC(".n")), + _DECL_FUNC(srand,2,_SC(".n")), + _DECL_FUNC(rand,1,NULL), + _DECL_FUNC(fabs,2,_SC(".n")), + _DECL_FUNC(abs,2,_SC(".n")), + {NULL,(SQFUNCTION)0,0,NULL} }; #undef _DECL_FUNC @@ -95,20 +95,20 @@ static const SQRegFunction mathlib_funcs[] = { SQRESULT sqstd_register_mathlib(HRABBITVM v) { - SQInteger i=0; - while(mathlib_funcs[i].name!=0) { - sq_pushstring(v,mathlib_funcs[i].name,-1); - sq_newclosure(v,mathlib_funcs[i].f,0); - sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); - sq_setnativeclosurename(v,-1,mathlib_funcs[i].name); - sq_newslot(v,-3,SQFalse); - i++; - } - sq_pushstring(v,_SC("RAND_MAX"),-1); - sq_pushinteger(v,RAND_MAX); - sq_newslot(v,-3,SQFalse); - sq_pushstring(v,_SC("PI"),-1); - sq_pushfloat(v,(SQFloat)M_PI); - sq_newslot(v,-3,SQFalse); - return SQ_OK; + SQInteger i=0; + while(mathlib_funcs[i].name!=0) { + sq_pushstring(v,mathlib_funcs[i].name,-1); + sq_newclosure(v,mathlib_funcs[i].f,0); + sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,mathlib_funcs[i].name); + sq_newslot(v,-3,SQFalse); + i++; + } + sq_pushstring(v,_SC("RAND_MAX"),-1); + sq_pushinteger(v,RAND_MAX); + sq_newslot(v,-3,SQFalse); + sq_pushstring(v,_SC("PI"),-1); + sq_pushfloat(v,(SQFloat)M_PI); + sq_newslot(v,-3,SQFalse); + return SQ_OK; } diff --git a/rabbit-std/sqstdrex.cpp b/rabbit-std/sqstdrex.cpp index 9f8eb0d..2c8e29e 100644 --- a/rabbit-std/sqstdrex.cpp +++ b/rabbit-std/sqstdrex.cpp @@ -17,28 +17,28 @@ static const SQChar *g_nnames[] = { - _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), - _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), - _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), - _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_SC("OP_MB") + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_SC("OP_MB") }; #endif -#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} -#define OP_OR (MAX_CHAR+2) -#define OP_EXPR (MAX_CHAR+3) //parentesis () -#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) -#define OP_DOT (MAX_CHAR+5) -#define OP_CLASS (MAX_CHAR+6) -#define OP_CCLASS (MAX_CHAR+7) -#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ -#define OP_RANGE (MAX_CHAR+9) -#define OP_CHAR (MAX_CHAR+10) -#define OP_EOL (MAX_CHAR+11) -#define OP_BOL (MAX_CHAR+12) -#define OP_WB (MAX_CHAR+13) -#define OP_MB (MAX_CHAR+14) //match balanced +#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} +#define OP_OR (MAX_CHAR+2) +#define OP_EXPR (MAX_CHAR+3) //parentesis () +#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) +#define OP_DOT (MAX_CHAR+5) +#define OP_CLASS (MAX_CHAR+6) +#define OP_CCLASS (MAX_CHAR+7) +#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ +#define OP_RANGE (MAX_CHAR+9) +#define OP_CHAR (MAX_CHAR+10) +#define OP_EOL (MAX_CHAR+11) +#define OP_BOL (MAX_CHAR+12) +#define OP_WB (MAX_CHAR+13) +#define OP_MB (MAX_CHAR+14) //match balanced #define SQREX_SYMBOL_ANY_CHAR ('.') #define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') @@ -53,621 +53,621 @@ static const SQChar *g_nnames[] = typedef int SQRexNodeType; typedef struct tagSQRexNode{ - SQRexNodeType type; - SQInteger left; - SQInteger right; - SQInteger next; + SQRexNodeType type; + SQInteger left; + SQInteger right; + SQInteger next; }SQRexNode; struct SQRex{ - const SQChar *_eol; - const SQChar *_bol; - const SQChar *_p; - SQInteger _first; - SQInteger _op; - SQRexNode *_nodes; - SQInteger _nallocated; - SQInteger _nsize; - SQInteger _nsubexpr; - SQRexMatch *_matches; - SQInteger _currsubexp; - void *_jmpbuf; - const SQChar **_error; + const SQChar *_eol; + const SQChar *_bol; + const SQChar *_p; + SQInteger _first; + SQInteger _op; + SQRexNode *_nodes; + SQInteger _nallocated; + SQInteger _nsize; + SQInteger _nsubexpr; + SQRexMatch *_matches; + SQInteger _currsubexp; + void *_jmpbuf; + const SQChar **_error; }; static SQInteger sqstd_rex_list(SQRex *exp); static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type) { - SQRexNode n; - n.type = type; - n.next = n.right = n.left = -1; - if(type == OP_EXPR) - n.right = exp->_nsubexpr++; - if(exp->_nallocated < (exp->_nsize + 1)) { - SQInteger oldsize = exp->_nallocated; - exp->_nallocated *= 2; - exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode)); - } - exp->_nodes[exp->_nsize++] = n; - SQInteger newid = exp->_nsize - 1; - return (SQInteger)newid; + SQRexNode n; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + SQInteger oldsize = exp->_nallocated; + exp->_nallocated *= 2; + exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + SQInteger newid = exp->_nsize - 1; + return (SQInteger)newid; } static void sqstd_rex_error(SQRex *exp,const SQChar *error) { - if(exp->_error) *exp->_error = error; - longjmp(*((jmp_buf*)exp->_jmpbuf),-1); + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); } static void sqstd_rex_expect(SQRex *exp, SQInteger n){ - if((*exp->_p) != n) - sqstd_rex_error(exp, _SC("expected paren")); - exp->_p++; + if((*exp->_p) != n) + sqstd_rex_error(exp, _SC("expected paren")); + exp->_p++; } static SQChar sqstd_rex_escapechar(SQRex *exp) { - if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){ - exp->_p++; - switch(*exp->_p) { - case 'v': exp->_p++; return '\v'; - case 'n': exp->_p++; return '\n'; - case 't': exp->_p++; return '\t'; - case 'r': exp->_p++; return '\r'; - case 'f': exp->_p++; return '\f'; - default: return (*exp->_p++); - } - } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected")); - return (*exp->_p++); + if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected")); + return (*exp->_p++); } static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid) { - SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS); - exp->_nodes[n].left = classid; - return n; + SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; } static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass) { - SQChar t; - if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) { - exp->_p++; - switch(*exp->_p) { - case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n'); - case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t'); - case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r'); - case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f'); - case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v'); - case 'a': case 'A': case 'w': case 'W': case 's': case 'S': - case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': - case 'p': case 'P': case 'l': case 'u': - { - t = *exp->_p; exp->_p++; - return sqstd_rex_charclass(exp,t); - } - case 'm': - { - SQChar cb, ce; //cb = character begin match ce = character end match - cb = *++exp->_p; //skip 'm' - ce = *++exp->_p; - exp->_p++; //points to the next char to be parsed - if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected")); - if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same")); - SQInteger node = sqstd_rex_newnode(exp,OP_MB); - exp->_nodes[node].left = cb; - exp->_nodes[node].right = ce; - return node; - } - case 0: - sqstd_rex_error(exp,_SC("letter expected for argument of escape sequence")); - break; - case 'b': - case 'B': - if(!isclass) { - SQInteger node = sqstd_rex_newnode(exp,OP_WB); - exp->_nodes[node].left = *exp->_p; - exp->_p++; - return node; - } //else default - default: - t = *exp->_p; exp->_p++; - return sqstd_rex_newnode(exp,t); - } - } - else if(!scisprint(*exp->_p)) { + SQChar t; + if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n'); + case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t'); + case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r'); + case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f'); + case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + t = *exp->_p; exp->_p++; + return sqstd_rex_charclass(exp,t); + } + case 'm': + { + SQChar cb, ce; //cb = character begin match ce = character end match + cb = *++exp->_p; //skip 'm' + ce = *++exp->_p; + exp->_p++; //points to the next char to be parsed + if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected")); + if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same")); + SQInteger node = sqstd_rex_newnode(exp,OP_MB); + exp->_nodes[node].left = cb; + exp->_nodes[node].right = ce; + return node; + } + case 0: + sqstd_rex_error(exp,_SC("letter expected for argument of escape sequence")); + break; + case 'b': + case 'B': + if(!isclass) { + SQInteger node = sqstd_rex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + default: + t = *exp->_p; exp->_p++; + return sqstd_rex_newnode(exp,t); + } + } + else if(!scisprint(*exp->_p)) { - sqstd_rex_error(exp,_SC("letter expected")); - } - t = *exp->_p; exp->_p++; - return sqstd_rex_newnode(exp,t); + sqstd_rex_error(exp,_SC("letter expected")); + } + t = *exp->_p; exp->_p++; + return sqstd_rex_newnode(exp,t); } static SQInteger sqstd_rex_class(SQRex *exp) { - SQInteger ret = -1; - SQInteger first = -1,chain; - if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){ - ret = sqstd_rex_newnode(exp,OP_NCLASS); - exp->_p++; - }else ret = sqstd_rex_newnode(exp,OP_CLASS); + SQInteger ret = -1; + SQInteger first = -1,chain; + if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){ + ret = sqstd_rex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = sqstd_rex_newnode(exp,OP_CLASS); - if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class")); - chain = ret; - while(*exp->_p != ']' && exp->_p != exp->_eol) { - if(*exp->_p == '-' && first != -1){ - SQInteger r; - if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range")); - r = sqstd_rex_newnode(exp,OP_RANGE); - if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range")); - if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges")); - exp->_nodes[r].left = exp->_nodes[first].type; - SQInteger t = sqstd_rex_escapechar(exp); - exp->_nodes[r].right = t; - exp->_nodes[chain].next = r; - chain = r; - first = -1; - } - else{ - if(first!=-1){ - SQInteger c = first; - exp->_nodes[chain].next = c; - chain = c; - first = sqstd_rex_charnode(exp,SQTrue); - } - else{ - first = sqstd_rex_charnode(exp,SQTrue); - } - } - } - if(first!=-1){ - SQInteger c = first; - exp->_nodes[chain].next = c; - } - /* hack? */ - exp->_nodes[ret].left = exp->_nodes[ret].next; - exp->_nodes[ret].next = -1; - return ret; + if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + SQInteger r; + if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range")); + r = sqstd_rex_newnode(exp,OP_RANGE); + if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + SQInteger t = sqstd_rex_escapechar(exp); + exp->_nodes[r].right = t; + exp->_nodes[chain].next = r; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + SQInteger c = first; + exp->_nodes[chain].next = c; + chain = c; + first = sqstd_rex_charnode(exp,SQTrue); + } + else{ + first = sqstd_rex_charnode(exp,SQTrue); + } + } + } + if(first!=-1){ + SQInteger c = first; + exp->_nodes[chain].next = c; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; } static SQInteger sqstd_rex_parsenumber(SQRex *exp) { - SQInteger ret = *exp->_p-'0'; - SQInteger positions = 10; - exp->_p++; - while(isdigit(*exp->_p)) { - ret = ret*10+(*exp->_p++-'0'); - if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant")); - positions *= 10; - }; - return ret; + SQInteger ret = *exp->_p-'0'; + SQInteger positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; } static SQInteger sqstd_rex_element(SQRex *exp) { - SQInteger ret = -1; - switch(*exp->_p) - { - case '(': { - SQInteger expr; - exp->_p++; + SQInteger ret = -1; + switch(*exp->_p) + { + case '(': { + SQInteger expr; + exp->_p++; - if(*exp->_p =='?') { - exp->_p++; - sqstd_rex_expect(exp,':'); - expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR); - } - else - expr = sqstd_rex_newnode(exp,OP_EXPR); - SQInteger newn = sqstd_rex_list(exp); - exp->_nodes[expr].left = newn; - ret = expr; - sqstd_rex_expect(exp,')'); - } - break; - case '[': - exp->_p++; - ret = sqstd_rex_class(exp); - sqstd_rex_expect(exp,']'); - break; - case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break; - case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break; - default: - ret = sqstd_rex_charnode(exp,SQFalse); - break; - } + if(*exp->_p =='?') { + exp->_p++; + sqstd_rex_expect(exp,':'); + expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = sqstd_rex_newnode(exp,OP_EXPR); + SQInteger newn = sqstd_rex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + sqstd_rex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = sqstd_rex_class(exp); + sqstd_rex_expect(exp,']'); + break; + case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break; + case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break; + default: + ret = sqstd_rex_charnode(exp,SQFalse); + break; + } - SQBool isgreedy = SQFalse; - unsigned short p0 = 0, p1 = 0; - switch(*exp->_p){ - case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break; - case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break; - case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break; - case '{': - exp->_p++; - if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected")); - p0 = (unsigned short)sqstd_rex_parsenumber(exp); - /*******************************/ - switch(*exp->_p) { - case '}': - p1 = p0; exp->_p++; - break; - case ',': - exp->_p++; - p1 = 0xFFFF; - if(isdigit(*exp->_p)){ - p1 = (unsigned short)sqstd_rex_parsenumber(exp); - } - sqstd_rex_expect(exp,'}'); - break; - default: - sqstd_rex_error(exp,_SC(", or } expected")); - } - /*******************************/ - isgreedy = SQTrue; - break; + SQBool isgreedy = SQFalse; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break; + case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break; + case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break; + case '{': + exp->_p++; + if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected")); + p0 = (unsigned short)sqstd_rex_parsenumber(exp); + /*******************************/ + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit(*exp->_p)){ + p1 = (unsigned short)sqstd_rex_parsenumber(exp); + } + sqstd_rex_expect(exp,'}'); + break; + default: + sqstd_rex_error(exp,_SC(", or } expected")); + } + /*******************************/ + isgreedy = SQTrue; + break; - } - if(isgreedy) { - SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY); - exp->_nodes[nnode].left = ret; - exp->_nodes[nnode].right = ((p0)<<16)|p1; - ret = nnode; - } + } + if(isgreedy) { + SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY); + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } - if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { - SQInteger nnode = sqstd_rex_element(exp); - exp->_nodes[ret].next = nnode; - } + if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + SQInteger nnode = sqstd_rex_element(exp); + exp->_nodes[ret].next = nnode; + } - return ret; + return ret; } static SQInteger sqstd_rex_list(SQRex *exp) { - SQInteger ret=-1,e; - if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) { - exp->_p++; - ret = sqstd_rex_newnode(exp,OP_BOL); - } - e = sqstd_rex_element(exp); - if(ret != -1) { - exp->_nodes[ret].next = e; - } - else ret = e; + SQInteger ret=-1,e; + if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = sqstd_rex_newnode(exp,OP_BOL); + } + e = sqstd_rex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; - if(*exp->_p == SQREX_SYMBOL_BRANCH) { - SQInteger temp,tright; - exp->_p++; - temp = sqstd_rex_newnode(exp,OP_OR); - exp->_nodes[temp].left = ret; - tright = sqstd_rex_list(exp); - exp->_nodes[temp].right = tright; - ret = temp; - } - return ret; + if(*exp->_p == SQREX_SYMBOL_BRANCH) { + SQInteger temp,tright; + exp->_p++; + temp = sqstd_rex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + tright = sqstd_rex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; } static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c) { - switch(cclass) { - case 'a': return isalpha(c)?SQTrue:SQFalse; - case 'A': return !isalpha(c)?SQTrue:SQFalse; - case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse; - case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse; - case 's': return isspace(c)?SQTrue:SQFalse; - case 'S': return !isspace(c)?SQTrue:SQFalse; - case 'd': return isdigit(c)?SQTrue:SQFalse; - case 'D': return !isdigit(c)?SQTrue:SQFalse; - case 'x': return isxdigit(c)?SQTrue:SQFalse; - case 'X': return !isxdigit(c)?SQTrue:SQFalse; - case 'c': return iscntrl(c)?SQTrue:SQFalse; - case 'C': return !iscntrl(c)?SQTrue:SQFalse; - case 'p': return ispunct(c)?SQTrue:SQFalse; - case 'P': return !ispunct(c)?SQTrue:SQFalse; - case 'l': return islower(c)?SQTrue:SQFalse; - case 'u': return isupper(c)?SQTrue:SQFalse; - } - return SQFalse; /*cannot happen*/ + switch(cclass) { + case 'a': return isalpha(c)?SQTrue:SQFalse; + case 'A': return !isalpha(c)?SQTrue:SQFalse; + case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse; + case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse; + case 's': return isspace(c)?SQTrue:SQFalse; + case 'S': return !isspace(c)?SQTrue:SQFalse; + case 'd': return isdigit(c)?SQTrue:SQFalse; + case 'D': return !isdigit(c)?SQTrue:SQFalse; + case 'x': return isxdigit(c)?SQTrue:SQFalse; + case 'X': return !isxdigit(c)?SQTrue:SQFalse; + case 'c': return iscntrl(c)?SQTrue:SQFalse; + case 'C': return !iscntrl(c)?SQTrue:SQFalse; + case 'p': return ispunct(c)?SQTrue:SQFalse; + case 'P': return !ispunct(c)?SQTrue:SQFalse; + case 'l': return islower(c)?SQTrue:SQFalse; + case 'u': return isupper(c)?SQTrue:SQFalse; + } + return SQFalse; /*cannot happen*/ } static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c) { - do { - switch(node->type) { - case OP_RANGE: - if(c >= node->left && c <= node->right) return SQTrue; - break; - case OP_CCLASS: - if(sqstd_rex_matchcclass(node->left,c)) return SQTrue; - break; - default: - if(c == node->type)return SQTrue; - } - } while((node->next != -1) && (node = &exp->_nodes[node->next])); - return SQFalse; + do { + switch(node->type) { + case OP_RANGE: + if(c >= node->left && c <= node->right) return SQTrue; + break; + case OP_CCLASS: + if(sqstd_rex_matchcclass(node->left,c)) return SQTrue; + break; + default: + if(c == node->type)return SQTrue; + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return SQFalse; } static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next) { - SQRexNodeType type = node->type; - switch(type) { - case OP_GREEDY: { - //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; - SQRexNode *greedystop = NULL; - SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; - const SQChar *s=str, *good = str; + SQRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + SQRexNode *greedystop = NULL; + SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const SQChar *s=str, *good = str; - if(node->next != -1) { - greedystop = &exp->_nodes[node->next]; - } - else { - greedystop = next; - } + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } - while((nmaches == 0xFFFF || nmaches < p1)) { + while((nmaches == 0xFFFF || nmaches < p1)) { - const SQChar *stop; - if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) - break; - nmaches++; - good=s; - if(greedystop) { - //checks that 0 matches satisfy the expression(if so skips) - //if not would always stop(for instance if is a '?') - if(greedystop->type != OP_GREEDY || - (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) - { - SQRexNode *gnext = NULL; - if(greedystop->next != -1) { - gnext = &exp->_nodes[greedystop->next]; - }else if(next && next->next != -1){ - gnext = &exp->_nodes[next->next]; - } - stop = sqstd_rex_matchnode(exp,greedystop,s,gnext); - if(stop) { - //if satisfied stop it - if(p0 == p1 && p0 == nmaches) break; - else if(nmaches >= p0 && p1 == 0xFFFF) break; - else if(nmaches >= p0 && nmaches <= p1) break; - } - } - } + const SQChar *stop; + if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + SQRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = sqstd_rex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } - if(s >= exp->_eol) - break; - } - if(p0 == p1 && p0 == nmaches) return good; - else if(nmaches >= p0 && p1 == 0xFFFF) return good; - else if(nmaches >= p0 && nmaches <= p1) return good; - return NULL; - } - case OP_OR: { - const SQChar *asd = str; - SQRexNode *temp=&exp->_nodes[node->left]; - while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - asd = str; - temp = &exp->_nodes[node->right]; - while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - return NULL; - break; - } - case OP_EXPR: - case OP_NOCAPEXPR:{ - SQRexNode *n = &exp->_nodes[node->left]; - const SQChar *cur = str; - SQInteger capture = -1; - if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { - capture = exp->_currsubexp; - exp->_matches[capture].begin = cur; - exp->_currsubexp++; - } - SQInteger tempcap = exp->_currsubexp; - do { - SQRexNode *subnext = NULL; - if(n->next != -1) { - subnext = &exp->_nodes[n->next]; - }else { - subnext = next; - } - if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) { - if(capture != -1){ - exp->_matches[capture].begin = 0; - exp->_matches[capture].len = 0; - } - return NULL; - } - } while((n->next != -1) && (n = &exp->_nodes[n->next])); + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const SQChar *asd = str; + SQRexNode *temp=&exp->_nodes[node->left]; + while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + SQRexNode *n = &exp->_nodes[node->left]; + const SQChar *cur = str; + SQInteger capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + SQInteger tempcap = exp->_currsubexp; + do { + SQRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); - exp->_currsubexp = tempcap; - if(capture != -1) - exp->_matches[capture].len = cur - exp->_matches[capture].begin; - return cur; - } - case OP_WB: - if((str == exp->_bol && !isspace(*str)) - || (str == exp->_eol && !isspace(*(str-1))) - || (!isspace(*str) && isspace(*(str+1))) - || (isspace(*str) && !isspace(*(str+1))) ) { - return (node->left == 'b')?str:NULL; - } - return (node->left == 'b')?NULL:str; - case OP_BOL: - if(str == exp->_bol) return str; - return NULL; - case OP_EOL: - if(str == exp->_eol) return str; - return NULL; - case OP_DOT:{ - if (str == exp->_eol) return NULL; - str++; - } - return str; - case OP_NCLASS: - case OP_CLASS: - if (str == exp->_eol) return NULL; - if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { - str++; - return str; - } - return NULL; - case OP_CCLASS: - if (str == exp->_eol) return NULL; - if(sqstd_rex_matchcclass(node->left,*str)) { - str++; - return str; - } - return NULL; - case OP_MB: - { - SQInteger cb = node->left; //char that opens a balanced expression - if(*str != cb) return NULL; // string doesnt start with open char - SQInteger ce = node->right; //char that closes a balanced expression - SQInteger cont = 1; - const SQChar *streol = exp->_eol; - while (++str < streol) { - if (*str == ce) { - if (--cont == 0) { - return ++str; - } - } - else if (*str == cb) cont++; - } - } - return NULL; // string ends out of balance - default: /* char */ - if (str == exp->_eol) return NULL; - if(*str != node->type) return NULL; - str++; - return str; - } - return NULL; + exp->_currsubexp = tempcap; + if(capture != -1) + exp->_matches[capture].len = cur - exp->_matches[capture].begin; + return cur; + } + case OP_WB: + if((str == exp->_bol && !isspace(*str)) + || (str == exp->_eol && !isspace(*(str-1))) + || (!isspace(*str) && isspace(*(str+1))) + || (isspace(*str) && !isspace(*(str+1))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT:{ + if (str == exp->_eol) return NULL; + str++; + } + return str; + case OP_NCLASS: + case OP_CLASS: + if (str == exp->_eol) return NULL; + if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { + str++; + return str; + } + return NULL; + case OP_CCLASS: + if (str == exp->_eol) return NULL; + if(sqstd_rex_matchcclass(node->left,*str)) { + str++; + return str; + } + return NULL; + case OP_MB: + { + SQInteger cb = node->left; //char that opens a balanced expression + if(*str != cb) return NULL; // string doesnt start with open char + SQInteger ce = node->right; //char that closes a balanced expression + SQInteger cont = 1; + const SQChar *streol = exp->_eol; + while (++str < streol) { + if (*str == ce) { + if (--cont == 0) { + return ++str; + } + } + else if (*str == cb) cont++; + } + } + return NULL; // string ends out of balance + default: /* char */ + if (str == exp->_eol) return NULL; + if(*str != node->type) return NULL; + str++; + return str; + } + return NULL; } /* public api */ SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error) { - SQRex * volatile exp = (SQRex *)sq_malloc(sizeof(SQRex)); // "volatile" is needed for setjmp() - exp->_eol = exp->_bol = NULL; - exp->_p = pattern; - exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar); - exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode)); - exp->_nsize = 0; - exp->_matches = 0; - exp->_nsubexpr = 0; - exp->_first = sqstd_rex_newnode(exp,OP_EXPR); - exp->_error = error; - exp->_jmpbuf = sq_malloc(sizeof(jmp_buf)); - if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { - SQInteger res = sqstd_rex_list(exp); - exp->_nodes[exp->_first].left = res; - if(*exp->_p!='\0') - sqstd_rex_error(exp,_SC("unexpected character")); + SQRex * volatile exp = (SQRex *)sq_malloc(sizeof(SQRex)); // "volatile" is needed for setjmp() + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar); + exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = sqstd_rex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = sq_malloc(sizeof(jmp_buf)); + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + SQInteger res = sqstd_rex_list(exp); + exp->_nodes[exp->_first].left = res; + if(*exp->_p!='\0') + sqstd_rex_error(exp,_SC("unexpected character")); #ifdef _DEBUG - { - SQInteger nsize,i; - SQRexNode *t; - nsize = exp->_nsize; - t = &exp->_nodes[0]; - scprintf(_SC("\n")); - for(i = 0;i < nsize; i++) { - if(exp->_nodes[i].type>MAX_CHAR) - scprintf(_SC("[%02d] %10s "), (SQInt32)i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); - else - scprintf(_SC("[%02d] %10c "), (SQInt32)i,exp->_nodes[i].type); - scprintf(_SC("left %02d right %02d next %02d\n"), (SQInt32)exp->_nodes[i].left, (SQInt32)exp->_nodes[i].right, (SQInt32)exp->_nodes[i].next); - } - scprintf(_SC("\n")); - } + { + SQInteger nsize,i; + SQRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "), (SQInt32)i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "), (SQInt32)i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"), (SQInt32)exp->_nodes[i].left, (SQInt32)exp->_nodes[i].right, (SQInt32)exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } #endif - exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch)); - memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch)); - } - else{ - sqstd_rex_free(exp); - return NULL; - } - return exp; + exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch)); + } + else{ + sqstd_rex_free(exp); + return NULL; + } + return exp; } void sqstd_rex_free(SQRex *exp) { - if(exp) { - if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode)); - if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf)); - if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch)); - sq_free(exp,sizeof(SQRex)); - } + if(exp) { + if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode)); + if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf)); + if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch)); + sq_free(exp,sizeof(SQRex)); + } } SQBool sqstd_rex_match(SQRex* exp,const SQChar* text) { - const SQChar* res = NULL; - exp->_bol = text; - exp->_eol = text + scstrlen(text); - exp->_currsubexp = 0; - res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL); - if(res == NULL || res != exp->_eol) - return SQFalse; - return SQTrue; + const SQChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return SQFalse; + return SQTrue; } SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end) { - const SQChar *cur = NULL; - SQInteger node = exp->_first; - if(text_begin >= text_end) return SQFalse; - exp->_bol = text_begin; - exp->_eol = text_end; - do { - cur = text_begin; - while(node != -1) { - exp->_currsubexp = 0; - cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL); - if(!cur) - break; - node = exp->_nodes[node].next; - } - text_begin++; - } while(cur == NULL && text_begin != text_end); + const SQChar *cur = NULL; + SQInteger node = exp->_first; + if(text_begin >= text_end) return SQFalse; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + text_begin++; + } while(cur == NULL && text_begin != text_end); - if(cur == NULL) - return SQFalse; + if(cur == NULL) + return SQFalse; - --text_begin; + --text_begin; - if(out_begin) *out_begin = text_begin; - if(out_end) *out_end = cur; - return SQTrue; + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return SQTrue; } SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end) { - return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); + return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); } SQInteger sqstd_rex_getsubexpcount(SQRex* exp) { - return exp->_nsubexpr; + return exp->_nsubexpr; } SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp) { - if( n<0 || n >= exp->_nsubexpr) return SQFalse; - *subexp = exp->_matches[n]; - return SQTrue; + if( n<0 || n >= exp->_nsubexpr) return SQFalse; + *subexp = exp->_matches[n]; + return SQTrue; } diff --git a/rabbit-std/sqstdstream.cpp b/rabbit-std/sqstdstream.cpp index 9f49265..880b625 100644 --- a/rabbit-std/sqstdstream.cpp +++ b/rabbit-std/sqstdstream.cpp @@ -17,327 +17,327 @@ #include #define SETUP_STREAM(v) \ - SQStream *self = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG)))) \ - return sq_throwerror(v,_SC("invalid type tag")); \ - if(!self || !self->IsValid()) \ - return sq_throwerror(v,_SC("the stream is invalid")); + SQStream *self = NULL; \ + if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG)))) \ + return sq_throwerror(v,_SC("invalid type tag")); \ + if(!self || !self->IsValid()) \ + return sq_throwerror(v,_SC("the stream is invalid")); SQInteger _stream_readblob(HRABBITVM v) { - SETUP_STREAM(v); - SQUserPointer data,blobp; - SQInteger size,res; - sq_getinteger(v,2,&size); - if(size > self->Len()) { - size = self->Len(); - } - data = sq_getscratchpad(v,size); - res = self->Read(data,size); - if(res <= 0) - return sq_throwerror(v,_SC("no data left to read")); - blobp = sqstd_createblob(v,res); - memcpy(blobp,data,res); - return 1; + SETUP_STREAM(v); + SQUserPointer data,blobp; + SQInteger size,res; + sq_getinteger(v,2,&size); + if(size > self->Len()) { + size = self->Len(); + } + data = sq_getscratchpad(v,size); + res = self->Read(data,size); + if(res <= 0) + return sq_throwerror(v,_SC("no data left to read")); + blobp = sqstd_createblob(v,res); + memcpy(blobp,data,res); + return 1; } #define SAFE_READN(ptr,len) { \ - if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \ - } + if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \ + } SQInteger _stream_readn(HRABBITVM v) { - SETUP_STREAM(v); - SQInteger format; - sq_getinteger(v, 2, &format); - switch(format) { - case 'l': { - SQInteger i; - SAFE_READN(&i, sizeof(i)); - sq_pushinteger(v, i); - } - break; - case 'i': { - SQInt32 i; - SAFE_READN(&i, sizeof(i)); - sq_pushinteger(v, i); - } - break; - case 's': { - short s; - SAFE_READN(&s, sizeof(short)); - sq_pushinteger(v, s); - } - break; - case 'w': { - unsigned short w; - SAFE_READN(&w, sizeof(unsigned short)); - sq_pushinteger(v, w); - } - break; - case 'c': { - char c; - SAFE_READN(&c, sizeof(char)); - sq_pushinteger(v, c); - } - break; - case 'b': { - unsigned char c; - SAFE_READN(&c, sizeof(unsigned char)); - sq_pushinteger(v, c); - } - break; - case 'f': { - float f; - SAFE_READN(&f, sizeof(float)); - sq_pushfloat(v, f); - } - break; - case 'd': { - double d; - SAFE_READN(&d, sizeof(double)); - sq_pushfloat(v, (SQFloat)d); - } - break; - default: - return sq_throwerror(v, _SC("invalid format")); - } - return 1; + SETUP_STREAM(v); + SQInteger format; + sq_getinteger(v, 2, &format); + switch(format) { + case 'l': { + SQInteger i; + SAFE_READN(&i, sizeof(i)); + sq_pushinteger(v, i); + } + break; + case 'i': { + SQInt32 i; + SAFE_READN(&i, sizeof(i)); + sq_pushinteger(v, i); + } + break; + case 's': { + short s; + SAFE_READN(&s, sizeof(short)); + sq_pushinteger(v, s); + } + break; + case 'w': { + unsigned short w; + SAFE_READN(&w, sizeof(unsigned short)); + sq_pushinteger(v, w); + } + break; + case 'c': { + char c; + SAFE_READN(&c, sizeof(char)); + sq_pushinteger(v, c); + } + break; + case 'b': { + unsigned char c; + SAFE_READN(&c, sizeof(unsigned char)); + sq_pushinteger(v, c); + } + break; + case 'f': { + float f; + SAFE_READN(&f, sizeof(float)); + sq_pushfloat(v, f); + } + break; + case 'd': { + double d; + SAFE_READN(&d, sizeof(double)); + sq_pushfloat(v, (SQFloat)d); + } + break; + default: + return sq_throwerror(v, _SC("invalid format")); + } + return 1; } SQInteger _stream_writeblob(HRABBITVM v) { - SQUserPointer data; - SQInteger size; - SETUP_STREAM(v); - if(SQ_FAILED(sqstd_getblob(v,2,&data))) - return sq_throwerror(v,_SC("invalid parameter")); - size = sqstd_getblobsize(v,2); - if(self->Write(data,size) != size) - return sq_throwerror(v,_SC("io error")); - sq_pushinteger(v,size); - return 1; + SQUserPointer data; + SQInteger size; + SETUP_STREAM(v); + if(SQ_FAILED(sqstd_getblob(v,2,&data))) + return sq_throwerror(v,_SC("invalid parameter")); + size = sqstd_getblobsize(v,2); + if(self->Write(data,size) != size) + return sq_throwerror(v,_SC("io error")); + sq_pushinteger(v,size); + return 1; } SQInteger _stream_writen(HRABBITVM v) { - SETUP_STREAM(v); - SQInteger format, ti; - SQFloat tf; - sq_getinteger(v, 3, &format); - switch(format) { - case 'l': { - SQInteger i; - sq_getinteger(v, 2, &ti); - i = ti; - self->Write(&i, sizeof(SQInteger)); - } - break; - case 'i': { - SQInt32 i; - sq_getinteger(v, 2, &ti); - i = (SQInt32)ti; - self->Write(&i, sizeof(SQInt32)); - } - break; - case 's': { - short s; - sq_getinteger(v, 2, &ti); - s = (short)ti; - self->Write(&s, sizeof(short)); - } - break; - case 'w': { - unsigned short w; - sq_getinteger(v, 2, &ti); - w = (unsigned short)ti; - self->Write(&w, sizeof(unsigned short)); - } - break; - case 'c': { - char c; - sq_getinteger(v, 2, &ti); - c = (char)ti; - self->Write(&c, sizeof(char)); - } - break; - case 'b': { - unsigned char b; - sq_getinteger(v, 2, &ti); - b = (unsigned char)ti; - self->Write(&b, sizeof(unsigned char)); - } - break; - case 'f': { - float f; - sq_getfloat(v, 2, &tf); - f = (float)tf; - self->Write(&f, sizeof(float)); - } - break; - case 'd': { - double d; - sq_getfloat(v, 2, &tf); - d = tf; - self->Write(&d, sizeof(double)); - } - break; - default: - return sq_throwerror(v, _SC("invalid format")); - } - return 0; + SETUP_STREAM(v); + SQInteger format, ti; + SQFloat tf; + sq_getinteger(v, 3, &format); + switch(format) { + case 'l': { + SQInteger i; + sq_getinteger(v, 2, &ti); + i = ti; + self->Write(&i, sizeof(SQInteger)); + } + break; + case 'i': { + SQInt32 i; + sq_getinteger(v, 2, &ti); + i = (SQInt32)ti; + self->Write(&i, sizeof(SQInt32)); + } + break; + case 's': { + short s; + sq_getinteger(v, 2, &ti); + s = (short)ti; + self->Write(&s, sizeof(short)); + } + break; + case 'w': { + unsigned short w; + sq_getinteger(v, 2, &ti); + w = (unsigned short)ti; + self->Write(&w, sizeof(unsigned short)); + } + break; + case 'c': { + char c; + sq_getinteger(v, 2, &ti); + c = (char)ti; + self->Write(&c, sizeof(char)); + } + break; + case 'b': { + unsigned char b; + sq_getinteger(v, 2, &ti); + b = (unsigned char)ti; + self->Write(&b, sizeof(unsigned char)); + } + break; + case 'f': { + float f; + sq_getfloat(v, 2, &tf); + f = (float)tf; + self->Write(&f, sizeof(float)); + } + break; + case 'd': { + double d; + sq_getfloat(v, 2, &tf); + d = tf; + self->Write(&d, sizeof(double)); + } + break; + default: + return sq_throwerror(v, _SC("invalid format")); + } + return 0; } SQInteger _stream_seek(HRABBITVM v) { - SETUP_STREAM(v); - SQInteger offset, origin = SQ_SEEK_SET; - sq_getinteger(v, 2, &offset); - if(sq_gettop(v) > 2) { - SQInteger t; - sq_getinteger(v, 3, &t); - switch(t) { - case 'b': origin = SQ_SEEK_SET; break; - case 'c': origin = SQ_SEEK_CUR; break; - case 'e': origin = SQ_SEEK_END; break; - default: return sq_throwerror(v,_SC("invalid origin")); - } - } - sq_pushinteger(v, self->Seek(offset, origin)); - return 1; + SETUP_STREAM(v); + SQInteger offset, origin = SQ_SEEK_SET; + sq_getinteger(v, 2, &offset); + if(sq_gettop(v) > 2) { + SQInteger t; + sq_getinteger(v, 3, &t); + switch(t) { + case 'b': origin = SQ_SEEK_SET; break; + case 'c': origin = SQ_SEEK_CUR; break; + case 'e': origin = SQ_SEEK_END; break; + default: return sq_throwerror(v,_SC("invalid origin")); + } + } + sq_pushinteger(v, self->Seek(offset, origin)); + return 1; } SQInteger _stream_tell(HRABBITVM v) { - SETUP_STREAM(v); - sq_pushinteger(v, self->Tell()); - return 1; + SETUP_STREAM(v); + sq_pushinteger(v, self->Tell()); + return 1; } SQInteger _stream_len(HRABBITVM v) { - SETUP_STREAM(v); - sq_pushinteger(v, self->Len()); - return 1; + SETUP_STREAM(v); + sq_pushinteger(v, self->Len()); + return 1; } SQInteger _stream_flush(HRABBITVM v) { - SETUP_STREAM(v); - if(!self->Flush()) - sq_pushinteger(v, 1); - else - sq_pushnull(v); - return 1; + SETUP_STREAM(v); + if(!self->Flush()) + sq_pushinteger(v, 1); + else + sq_pushnull(v); + return 1; } SQInteger _stream_eos(HRABBITVM v) { - SETUP_STREAM(v); - if(self->EOS()) - sq_pushinteger(v, 1); - else - sq_pushnull(v); - return 1; + SETUP_STREAM(v); + if(self->EOS()) + sq_pushinteger(v, 1); + else + sq_pushnull(v); + return 1; } SQInteger _stream__cloned(HRABBITVM v) { - return sq_throwerror(v,_SC("this object cannot be cloned")); + return sq_throwerror(v,_SC("this object cannot be cloned")); } static const SQRegFunction _stream_methods[] = { - _DECL_STREAM_FUNC(readblob,2,_SC("xn")), - _DECL_STREAM_FUNC(readn,2,_SC("xn")), - _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")), - _DECL_STREAM_FUNC(writen,3,_SC("xnn")), - _DECL_STREAM_FUNC(seek,-2,_SC("xnn")), - _DECL_STREAM_FUNC(tell,1,_SC("x")), - _DECL_STREAM_FUNC(len,1,_SC("x")), - _DECL_STREAM_FUNC(eos,1,_SC("x")), - _DECL_STREAM_FUNC(flush,1,_SC("x")), - _DECL_STREAM_FUNC(_cloned,0,NULL), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_STREAM_FUNC(readblob,2,_SC("xn")), + _DECL_STREAM_FUNC(readn,2,_SC("xn")), + _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")), + _DECL_STREAM_FUNC(writen,3,_SC("xnn")), + _DECL_STREAM_FUNC(seek,-2,_SC("xnn")), + _DECL_STREAM_FUNC(tell,1,_SC("x")), + _DECL_STREAM_FUNC(len,1,_SC("x")), + _DECL_STREAM_FUNC(eos,1,_SC("x")), + _DECL_STREAM_FUNC(flush,1,_SC("x")), + _DECL_STREAM_FUNC(_cloned,0,NULL), + {NULL,(SQFUNCTION)0,0,NULL} }; void init_streamclass(HRABBITVM v) { - sq_pushregistrytable(v); - sq_pushstring(v,_SC("std_stream"),-1); - if(SQ_FAILED(sq_get(v,-2))) { - sq_pushstring(v,_SC("std_stream"),-1); - sq_newclass(v,SQFalse); - sq_settypetag(v,-1,(SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG)); - SQInteger i = 0; - while(_stream_methods[i].name != 0) { - const SQRegFunction &f = _stream_methods[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_newslot(v,-3,SQFalse); - i++; - } - sq_newslot(v,-3,SQFalse); - sq_pushroottable(v); - sq_pushstring(v,_SC("stream"),-1); - sq_pushstring(v,_SC("std_stream"),-1); - sq_get(v,-4); - sq_newslot(v,-3,SQFalse); - sq_pop(v,1); - } - else { - sq_pop(v,1); //result - } - sq_pop(v,1); + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_stream"),-1); + if(SQ_FAILED(sq_get(v,-2))) { + sq_pushstring(v,_SC("std_stream"),-1); + sq_newclass(v,SQFalse); + sq_settypetag(v,-1,(SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG)); + SQInteger i = 0; + while(_stream_methods[i].name != 0) { + const SQRegFunction &f = _stream_methods[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_newslot(v,-3,SQFalse); + i++; + } + sq_newslot(v,-3,SQFalse); + sq_pushroottable(v); + sq_pushstring(v,_SC("stream"),-1); + sq_pushstring(v,_SC("std_stream"),-1); + sq_get(v,-4); + sq_newslot(v,-3,SQFalse); + sq_pop(v,1); + } + else { + sq_pop(v,1); //result + } + sq_pop(v,1); } SQRESULT declare_stream(HRABBITVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,const SQRegFunction *methods,const SQRegFunction *globals) { - if(sq_gettype(v,-1) != OT_TABLE) - return sq_throwerror(v,_SC("table expected")); - SQInteger top = sq_gettop(v); - //create delegate - init_streamclass(v); - sq_pushregistrytable(v); - sq_pushstring(v,reg_name,-1); - sq_pushstring(v,_SC("std_stream"),-1); - if(SQ_SUCCEEDED(sq_get(v,-3))) { - sq_newclass(v,SQTrue); - sq_settypetag(v,-1,typetag); - SQInteger i = 0; - while(methods[i].name != 0) { - const SQRegFunction &f = methods[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_setnativeclosurename(v,-1,f.name); - sq_newslot(v,-3,SQFalse); - i++; - } - sq_newslot(v,-3,SQFalse); - sq_pop(v,1); + if(sq_gettype(v,-1) != OT_TABLE) + return sq_throwerror(v,_SC("table expected")); + SQInteger top = sq_gettop(v); + //create delegate + init_streamclass(v); + sq_pushregistrytable(v); + sq_pushstring(v,reg_name,-1); + sq_pushstring(v,_SC("std_stream"),-1); + if(SQ_SUCCEEDED(sq_get(v,-3))) { + sq_newclass(v,SQTrue); + sq_settypetag(v,-1,typetag); + SQInteger i = 0; + while(methods[i].name != 0) { + const SQRegFunction &f = methods[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_newslot(v,-3,SQFalse); + i++; + } + sq_newslot(v,-3,SQFalse); + sq_pop(v,1); - i = 0; - while(globals[i].name!=0) - { - const SQRegFunction &f = globals[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_setnativeclosurename(v,-1,f.name); - sq_newslot(v,-3,SQFalse); - i++; - } - //register the class in the target table - sq_pushstring(v,name,-1); - sq_pushregistrytable(v); - sq_pushstring(v,reg_name,-1); - sq_get(v,-2); - sq_remove(v,-2); - sq_newslot(v,-3,SQFalse); + i = 0; + while(globals[i].name!=0) + { + const SQRegFunction &f = globals[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_newslot(v,-3,SQFalse); + i++; + } + //register the class in the target table + sq_pushstring(v,name,-1); + sq_pushregistrytable(v); + sq_pushstring(v,reg_name,-1); + sq_get(v,-2); + sq_remove(v,-2); + sq_newslot(v,-3,SQFalse); - sq_settop(v,top); - return SQ_OK; - } - sq_settop(v,top); - return SQ_ERROR; + sq_settop(v,top); + return SQ_OK; + } + sq_settop(v,top); + return SQ_ERROR; } diff --git a/rabbit-std/sqstdstring.cpp b/rabbit-std/sqstdstring.cpp index 1cb703b..1736c74 100644 --- a/rabbit-std/sqstdstring.cpp +++ b/rabbit-std/sqstdstring.cpp @@ -20,506 +20,506 @@ static SQBool isfmtchr(SQChar ch) { - switch(ch) { - case '-': case '+': case ' ': case '#': case '0': return SQTrue; - } - return SQFalse; + switch(ch) { + case '-': case '+': case ' ': case '#': case '0': return SQTrue; + } + return SQFalse; } static SQInteger validate_format(HRABBITVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width) { - SQChar *dummy; - SQChar swidth[MAX_WFORMAT_LEN]; - SQInteger wc = 0; - SQInteger start = n; - fmt[0] = '%'; - while (isfmtchr(src[n])) n++; - while (scisdigit(src[n])) { - swidth[wc] = src[n]; - n++; - wc++; - if(wc>=MAX_WFORMAT_LEN) - return sq_throwerror(v,_SC("width format too long")); - } - swidth[wc] = '\0'; - if(wc > 0) { - width = scstrtol(swidth,&dummy,10); - } - else - width = 0; - if (src[n] == '.') { - n++; + SQChar *dummy; + SQChar swidth[MAX_WFORMAT_LEN]; + SQInteger wc = 0; + SQInteger start = n; + fmt[0] = '%'; + while (isfmtchr(src[n])) n++; + while (scisdigit(src[n])) { + swidth[wc] = src[n]; + n++; + wc++; + if(wc>=MAX_WFORMAT_LEN) + return sq_throwerror(v,_SC("width format too long")); + } + swidth[wc] = '\0'; + if(wc > 0) { + width = scstrtol(swidth,&dummy,10); + } + else + width = 0; + if (src[n] == '.') { + n++; - wc = 0; - while (scisdigit(src[n])) { - swidth[wc] = src[n]; - n++; - wc++; - if(wc>=MAX_WFORMAT_LEN) - return sq_throwerror(v,_SC("precision format too long")); - } - swidth[wc] = '\0'; - if(wc > 0) { - width += scstrtol(swidth,&dummy,10); + wc = 0; + while (scisdigit(src[n])) { + swidth[wc] = src[n]; + n++; + wc++; + if(wc>=MAX_WFORMAT_LEN) + return sq_throwerror(v,_SC("precision format too long")); + } + swidth[wc] = '\0'; + if(wc > 0) { + width += scstrtol(swidth,&dummy,10); - } - } - if (n-start > MAX_FORMAT_LEN ) - return sq_throwerror(v,_SC("format too long")); - memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar)); - fmt[(n-start)+2] = '\0'; - return n; + } + } + if (n-start > MAX_FORMAT_LEN ) + return sq_throwerror(v,_SC("format too long")); + memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar)); + fmt[(n-start)+2] = '\0'; + return n; } SQRESULT sqstd_format(HRABBITVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output) { - const SQChar *format; - SQChar *dest; - SQChar fmt[MAX_FORMAT_LEN]; - const SQRESULT res = sq_getstring(v,nformatstringidx,&format); - if (SQ_FAILED(res)) { - return res; // propagate the error - } - SQInteger format_size = sq_getsize(v,nformatstringidx); - SQInteger allocated = (format_size+2)*sizeof(SQChar); - dest = sq_getscratchpad(v,allocated); - SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0; - //while(format[n] != '\0') - while(n < format_size) - { - if(format[n] != '%') { - assert(i < allocated); - dest[i++] = format[n]; - n++; - } - else if(format[n+1] == '%') { //handles %% - dest[i++] = '%'; - n += 2; - } - else { - n++; - if( nparam > sq_gettop(v) ) - return sq_throwerror(v,_SC("not enough parameters for the given format string")); - n = validate_format(v,fmt,format,n,w); - if(n < 0) return -1; - SQInteger addlen = 0; - SQInteger valtype = 0; - const SQChar *ts = NULL; - SQInteger ti = 0; - SQFloat tf = 0; - switch(format[n]) { - case 's': - if(SQ_FAILED(sq_getstring(v,nparam,&ts))) - return sq_throwerror(v,_SC("string expected for the specified format")); - addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); - valtype = 's'; - break; - case 'i': case 'd': case 'o': case 'u': case 'x': case 'X': + const SQChar *format; + SQChar *dest; + SQChar fmt[MAX_FORMAT_LEN]; + const SQRESULT res = sq_getstring(v,nformatstringidx,&format); + if (SQ_FAILED(res)) { + return res; // propagate the error + } + SQInteger format_size = sq_getsize(v,nformatstringidx); + SQInteger allocated = (format_size+2)*sizeof(SQChar); + dest = sq_getscratchpad(v,allocated); + SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0; + //while(format[n] != '\0') + while(n < format_size) + { + if(format[n] != '%') { + assert(i < allocated); + dest[i++] = format[n]; + n++; + } + else if(format[n+1] == '%') { //handles %% + dest[i++] = '%'; + n += 2; + } + else { + n++; + if( nparam > sq_gettop(v) ) + return sq_throwerror(v,_SC("not enough parameters for the given format string")); + n = validate_format(v,fmt,format,n,w); + if(n < 0) return -1; + SQInteger addlen = 0; + SQInteger valtype = 0; + const SQChar *ts = NULL; + SQInteger ti = 0; + SQFloat tf = 0; + switch(format[n]) { + case 's': + if(SQ_FAILED(sq_getstring(v,nparam,&ts))) + return sq_throwerror(v,_SC("string expected for the specified format")); + addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); + valtype = 's'; + break; + case 'i': case 'd': case 'o': case 'u': case 'x': case 'X': #ifdef _SQ64 - { - size_t flen = scstrlen(fmt); - SQInteger fpos = flen - 1; - SQChar f = fmt[fpos]; - const SQChar *prec = (const SQChar *)_PRINT_INT_PREC; - while(*prec != _SC('\0')) { - fmt[fpos++] = *prec++; - } - fmt[fpos++] = f; - fmt[fpos++] = _SC('\0'); - } + { + size_t flen = scstrlen(fmt); + SQInteger fpos = flen - 1; + SQChar f = fmt[fpos]; + const SQChar *prec = (const SQChar *)_PRINT_INT_PREC; + while(*prec != _SC('\0')) { + fmt[fpos++] = *prec++; + } + fmt[fpos++] = f; + fmt[fpos++] = _SC('\0'); + } #endif - case 'c': - if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) - return sq_throwerror(v,_SC("integer expected for the specified format")); - addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); - valtype = 'i'; - break; - case 'f': case 'g': case 'G': case 'e': case 'E': - if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) - return sq_throwerror(v,_SC("float expected for the specified format")); - addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); - valtype = 'f'; - break; - default: - return sq_throwerror(v,_SC("invalid format")); - } - n++; - allocated += addlen + sizeof(SQChar); - dest = sq_getscratchpad(v,allocated); - switch(valtype) { - case 's': i += scsprintf(&dest[i],allocated,fmt,ts); break; - case 'i': i += scsprintf(&dest[i],allocated,fmt,ti); break; - case 'f': i += scsprintf(&dest[i],allocated,fmt,tf); break; - }; - nparam ++; - } - } - *outlen = i; - dest[i] = '\0'; - *output = dest; - return SQ_OK; + case 'c': + if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) + return sq_throwerror(v,_SC("integer expected for the specified format")); + addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); + valtype = 'i'; + break; + case 'f': case 'g': case 'G': case 'e': case 'E': + if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) + return sq_throwerror(v,_SC("float expected for the specified format")); + addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); + valtype = 'f'; + break; + default: + return sq_throwerror(v,_SC("invalid format")); + } + n++; + allocated += addlen + sizeof(SQChar); + dest = sq_getscratchpad(v,allocated); + switch(valtype) { + case 's': i += scsprintf(&dest[i],allocated,fmt,ts); break; + case 'i': i += scsprintf(&dest[i],allocated,fmt,ti); break; + case 'f': i += scsprintf(&dest[i],allocated,fmt,tf); break; + }; + nparam ++; + } + } + *outlen = i; + dest[i] = '\0'; + *output = dest; + return SQ_OK; } static SQInteger _string_printf(HRABBITVM v) { - SQChar *dest = NULL; - SQInteger length = 0; - if(SQ_FAILED(sqstd_format(v,2,&length,&dest))) - return -1; + SQChar *dest = NULL; + SQInteger length = 0; + if(SQ_FAILED(sqstd_format(v,2,&length,&dest))) + return -1; - SQPRINTFUNCTION printfunc = sq_getprintfunc(v); - if(printfunc) printfunc(v,dest); + SQPRINTFUNCTION printfunc = sq_getprintfunc(v); + if(printfunc) printfunc(v,dest); - return 0; + return 0; } static SQInteger _string_format(HRABBITVM v) { - SQChar *dest = NULL; - SQInteger length = 0; - if(SQ_FAILED(sqstd_format(v,2,&length,&dest))) - return -1; - sq_pushstring(v,dest,length); - return 1; + SQChar *dest = NULL; + SQInteger length = 0; + if(SQ_FAILED(sqstd_format(v,2,&length,&dest))) + return -1; + sq_pushstring(v,dest,length); + return 1; } static void __strip_l(const SQChar *str,const SQChar **start) { - const SQChar *t = str; - while(((*t) != '\0') && scisspace(*t)){ t++; } - *start = t; + const SQChar *t = str; + while(((*t) != '\0') && scisspace(*t)){ t++; } + *start = t; } static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end) { - if(len == 0) { - *end = str; - return; - } - const SQChar *t = &str[len-1]; - while(t >= str && scisspace(*t)) { t--; } - *end = t + 1; + if(len == 0) { + *end = str; + return; + } + const SQChar *t = &str[len-1]; + while(t >= str && scisspace(*t)) { t--; } + *end = t + 1; } static SQInteger _string_strip(HRABBITVM v) { - const SQChar *str,*start,*end; - sq_getstring(v,2,&str); - SQInteger len = sq_getsize(v,2); - __strip_l(str,&start); - __strip_r(str,len,&end); - sq_pushstring(v,start,end - start); - return 1; + const SQChar *str,*start,*end; + sq_getstring(v,2,&str); + SQInteger len = sq_getsize(v,2); + __strip_l(str,&start); + __strip_r(str,len,&end); + sq_pushstring(v,start,end - start); + return 1; } static SQInteger _string_lstrip(HRABBITVM v) { - const SQChar *str,*start; - sq_getstring(v,2,&str); - __strip_l(str,&start); - sq_pushstring(v,start,-1); - return 1; + const SQChar *str,*start; + sq_getstring(v,2,&str); + __strip_l(str,&start); + sq_pushstring(v,start,-1); + return 1; } static SQInteger _string_rstrip(HRABBITVM v) { - const SQChar *str,*end; - sq_getstring(v,2,&str); - SQInteger len = sq_getsize(v,2); - __strip_r(str,len,&end); - sq_pushstring(v,str,end - str); - return 1; + const SQChar *str,*end; + sq_getstring(v,2,&str); + SQInteger len = sq_getsize(v,2); + __strip_r(str,len,&end); + sq_pushstring(v,str,end - str); + return 1; } static SQInteger _string_split(HRABBITVM v) { - const SQChar *str,*seps; - SQChar *stemp; - sq_getstring(v,2,&str); - sq_getstring(v,3,&seps); - SQInteger sepsize = sq_getsize(v,3); - if(sepsize == 0) return sq_throwerror(v,_SC("empty separators string")); - SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar); - stemp = sq_getscratchpad(v,memsize); - memcpy(stemp,str,memsize); - SQChar *start = stemp; - SQChar *end = stemp; - sq_newarray(v,0); - while(*end != '\0') - { - SQChar cur = *end; - for(SQInteger i = 0; i < sepsize; i++) - { - if(cur == seps[i]) - { - *end = 0; - sq_pushstring(v,start,-1); - sq_arrayappend(v,-2); - start = end + 1; - break; - } - } - end++; - } - if(end != start) - { - sq_pushstring(v,start,-1); - sq_arrayappend(v,-2); - } - return 1; + const SQChar *str,*seps; + SQChar *stemp; + sq_getstring(v,2,&str); + sq_getstring(v,3,&seps); + SQInteger sepsize = sq_getsize(v,3); + if(sepsize == 0) return sq_throwerror(v,_SC("empty separators string")); + SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar); + stemp = sq_getscratchpad(v,memsize); + memcpy(stemp,str,memsize); + SQChar *start = stemp; + SQChar *end = stemp; + sq_newarray(v,0); + while(*end != '\0') + { + SQChar cur = *end; + for(SQInteger i = 0; i < sepsize; i++) + { + if(cur == seps[i]) + { + *end = 0; + sq_pushstring(v,start,-1); + sq_arrayappend(v,-2); + start = end + 1; + break; + } + } + end++; + } + if(end != start) + { + sq_pushstring(v,start,-1); + sq_arrayappend(v,-2); + } + return 1; } static SQInteger _string_escape(HRABBITVM v) { - const SQChar *str; - SQChar *dest,*resstr; - SQInteger size; - sq_getstring(v,2,&str); - size = sq_getsize(v,2); - if(size == 0) { - sq_push(v,2); - return 1; - } + const SQChar *str; + SQChar *dest,*resstr; + SQInteger size; + sq_getstring(v,2,&str); + size = sq_getsize(v,2); + if(size == 0) { + sq_push(v,2); + return 1; + } #ifdef SQUNICODE #if WCHAR_SIZE == 2 - const SQChar *escpat = _SC("\\x%04x"); - const SQInteger maxescsize = 6; + const SQChar *escpat = _SC("\\x%04x"); + const SQInteger maxescsize = 6; #else //WCHAR_SIZE == 4 - const SQChar *escpat = _SC("\\x%08x"); - const SQInteger maxescsize = 10; + const SQChar *escpat = _SC("\\x%08x"); + const SQInteger maxescsize = 10; #endif #else - const SQChar *escpat = _SC("\\x%02x"); - const SQInteger maxescsize = 4; + const SQChar *escpat = _SC("\\x%02x"); + const SQInteger maxescsize = 4; #endif - SQInteger destcharsize = (size * maxescsize); //assumes every char could be escaped - resstr = dest = (SQChar *)sq_getscratchpad(v,destcharsize * sizeof(SQChar)); - SQChar c; - SQChar escch; - SQInteger escaped = 0; - for(int n = 0; n < size; n++){ - c = *str++; - escch = 0; - if(scisprint(c) || c == 0) { - switch(c) { - case '\a': escch = 'a'; break; - case '\b': escch = 'b'; break; - case '\t': escch = 't'; break; - case '\n': escch = 'n'; break; - case '\v': escch = 'v'; break; - case '\f': escch = 'f'; break; - case '\r': escch = 'r'; break; - case '\\': escch = '\\'; break; - case '\"': escch = '\"'; break; - case '\'': escch = '\''; break; - case 0: escch = '0'; break; - } - if(escch) { - *dest++ = '\\'; - *dest++ = escch; - escaped++; - } - else { - *dest++ = c; - } - } - else { + SQInteger destcharsize = (size * maxescsize); //assumes every char could be escaped + resstr = dest = (SQChar *)sq_getscratchpad(v,destcharsize * sizeof(SQChar)); + SQChar c; + SQChar escch; + SQInteger escaped = 0; + for(int n = 0; n < size; n++){ + c = *str++; + escch = 0; + if(scisprint(c) || c == 0) { + switch(c) { + case '\a': escch = 'a'; break; + case '\b': escch = 'b'; break; + case '\t': escch = 't'; break; + case '\n': escch = 'n'; break; + case '\v': escch = 'v'; break; + case '\f': escch = 'f'; break; + case '\r': escch = 'r'; break; + case '\\': escch = '\\'; break; + case '\"': escch = '\"'; break; + case '\'': escch = '\''; break; + case 0: escch = '0'; break; + } + if(escch) { + *dest++ = '\\'; + *dest++ = escch; + escaped++; + } + else { + *dest++ = c; + } + } + else { - dest += scsprintf(dest, destcharsize, escpat, c); - escaped++; - } - } + dest += scsprintf(dest, destcharsize, escpat, c); + escaped++; + } + } - if(escaped) { - sq_pushstring(v,resstr,dest - resstr); - } - else { - sq_push(v,2); //nothing escaped - } - return 1; + if(escaped) { + sq_pushstring(v,resstr,dest - resstr); + } + else { + sq_push(v,2); //nothing escaped + } + return 1; } static SQInteger _string_startswith(HRABBITVM v) { - const SQChar *str,*cmp; - sq_getstring(v,2,&str); - sq_getstring(v,3,&cmp); - SQInteger len = sq_getsize(v,2); - SQInteger cmplen = sq_getsize(v,3); - SQBool ret = SQFalse; - if(cmplen <= len) { - ret = memcmp(str,cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse; - } - sq_pushbool(v,ret); - return 1; + const SQChar *str,*cmp; + sq_getstring(v,2,&str); + sq_getstring(v,3,&cmp); + SQInteger len = sq_getsize(v,2); + SQInteger cmplen = sq_getsize(v,3); + SQBool ret = SQFalse; + if(cmplen <= len) { + ret = memcmp(str,cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse; + } + sq_pushbool(v,ret); + return 1; } static SQInteger _string_endswith(HRABBITVM v) { - const SQChar *str,*cmp; - sq_getstring(v,2,&str); - sq_getstring(v,3,&cmp); - SQInteger len = sq_getsize(v,2); - SQInteger cmplen = sq_getsize(v,3); - SQBool ret = SQFalse; - if(cmplen <= len) { - ret = memcmp(&str[len - cmplen],cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse; - } - sq_pushbool(v,ret); - return 1; + const SQChar *str,*cmp; + sq_getstring(v,2,&str); + sq_getstring(v,3,&cmp); + SQInteger len = sq_getsize(v,2); + SQInteger cmplen = sq_getsize(v,3); + SQBool ret = SQFalse; + if(cmplen <= len) { + ret = memcmp(&str[len - cmplen],cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse; + } + sq_pushbool(v,ret); + return 1; } #define SETUP_REX(v) \ - SQRex *self = NULL; \ - sq_getinstanceup(v,1,(SQUserPointer *)&self,0); + SQRex *self = NULL; \ + sq_getinstanceup(v,1,(SQUserPointer *)&self,0); static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size)) { - SQRex *self = ((SQRex *)p); - sqstd_rex_free(self); - return 1; + SQRex *self = ((SQRex *)p); + sqstd_rex_free(self); + return 1; } static SQInteger _regexp_match(HRABBITVM v) { - SETUP_REX(v); - const SQChar *str; - sq_getstring(v,2,&str); - if(sqstd_rex_match(self,str) == SQTrue) - { - sq_pushbool(v,SQTrue); - return 1; - } - sq_pushbool(v,SQFalse); - return 1; + SETUP_REX(v); + const SQChar *str; + sq_getstring(v,2,&str); + if(sqstd_rex_match(self,str) == SQTrue) + { + sq_pushbool(v,SQTrue); + return 1; + } + sq_pushbool(v,SQFalse); + return 1; } static void _addrexmatch(HRABBITVM v,const SQChar *str,const SQChar *begin,const SQChar *end) { - sq_newtable(v); - sq_pushstring(v,_SC("begin"),-1); - sq_pushinteger(v,begin - str); - sq_rawset(v,-3); - sq_pushstring(v,_SC("end"),-1); - sq_pushinteger(v,end - str); - sq_rawset(v,-3); + sq_newtable(v); + sq_pushstring(v,_SC("begin"),-1); + sq_pushinteger(v,begin - str); + sq_rawset(v,-3); + sq_pushstring(v,_SC("end"),-1); + sq_pushinteger(v,end - str); + sq_rawset(v,-3); } static SQInteger _regexp_search(HRABBITVM v) { - SETUP_REX(v); - const SQChar *str,*begin,*end; - SQInteger start = 0; - sq_getstring(v,2,&str); - if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); - if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { - _addrexmatch(v,str,begin,end); - return 1; - } - return 0; + SETUP_REX(v); + const SQChar *str,*begin,*end; + SQInteger start = 0; + sq_getstring(v,2,&str); + if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); + if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { + _addrexmatch(v,str,begin,end); + return 1; + } + return 0; } static SQInteger _regexp_capture(HRABBITVM v) { - SETUP_REX(v); - const SQChar *str,*begin,*end; - SQInteger start = 0; - sq_getstring(v,2,&str); - if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); - if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { - SQInteger n = sqstd_rex_getsubexpcount(self); - SQRexMatch match; - sq_newarray(v,0); - for(SQInteger i = 0;i < n; i++) { - sqstd_rex_getsubexp(self,i,&match); - if(match.len > 0) - _addrexmatch(v,str,match.begin,match.begin+match.len); - else - _addrexmatch(v,str,str,str); //empty match - sq_arrayappend(v,-2); - } - return 1; - } - return 0; + SETUP_REX(v); + const SQChar *str,*begin,*end; + SQInteger start = 0; + sq_getstring(v,2,&str); + if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); + if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { + SQInteger n = sqstd_rex_getsubexpcount(self); + SQRexMatch match; + sq_newarray(v,0); + for(SQInteger i = 0;i < n; i++) { + sqstd_rex_getsubexp(self,i,&match); + if(match.len > 0) + _addrexmatch(v,str,match.begin,match.begin+match.len); + else + _addrexmatch(v,str,str,str); //empty match + sq_arrayappend(v,-2); + } + return 1; + } + return 0; } static SQInteger _regexp_subexpcount(HRABBITVM v) { - SETUP_REX(v); - sq_pushinteger(v,sqstd_rex_getsubexpcount(self)); - return 1; + SETUP_REX(v); + sq_pushinteger(v,sqstd_rex_getsubexpcount(self)); + return 1; } static SQInteger _regexp_constructor(HRABBITVM v) { - const SQChar *error,*pattern; - sq_getstring(v,2,&pattern); - SQRex *rex = sqstd_rex_compile(pattern,&error); - if(!rex) return sq_throwerror(v,error); - sq_setinstanceup(v,1,rex); - sq_setreleasehook(v,1,_rexobj_releasehook); - return 0; + const SQChar *error,*pattern; + sq_getstring(v,2,&pattern); + SQRex *rex = sqstd_rex_compile(pattern,&error); + if(!rex) return sq_throwerror(v,error); + sq_setinstanceup(v,1,rex); + sq_setreleasehook(v,1,_rexobj_releasehook); + return 0; } static SQInteger _regexp__typeof(HRABBITVM v) { - sq_pushstring(v,_SC("regexp"),-1); - return 1; + sq_pushstring(v,_SC("regexp"),-1); + return 1; } #define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask} static const SQRegFunction rexobj_funcs[]={ - _DECL_REX_FUNC(constructor,2,_SC(".s")), - _DECL_REX_FUNC(search,-2,_SC("xsn")), - _DECL_REX_FUNC(match,2,_SC("xs")), - _DECL_REX_FUNC(capture,-2,_SC("xsn")), - _DECL_REX_FUNC(subexpcount,1,_SC("x")), - _DECL_REX_FUNC(_typeof,1,_SC("x")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_REX_FUNC(constructor,2,_SC(".s")), + _DECL_REX_FUNC(search,-2,_SC("xsn")), + _DECL_REX_FUNC(match,2,_SC("xs")), + _DECL_REX_FUNC(capture,-2,_SC("xsn")), + _DECL_REX_FUNC(subexpcount,1,_SC("x")), + _DECL_REX_FUNC(_typeof,1,_SC("x")), + {NULL,(SQFUNCTION)0,0,NULL} }; #undef _DECL_REX_FUNC #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask} static const SQRegFunction stringlib_funcs[]={ - _DECL_FUNC(format,-2,_SC(".s")), - _DECL_FUNC(printf,-2,_SC(".s")), - _DECL_FUNC(strip,2,_SC(".s")), - _DECL_FUNC(lstrip,2,_SC(".s")), - _DECL_FUNC(rstrip,2,_SC(".s")), - _DECL_FUNC(split,3,_SC(".ss")), - _DECL_FUNC(escape,2,_SC(".s")), - _DECL_FUNC(startswith,3,_SC(".ss")), - _DECL_FUNC(endswith,3,_SC(".ss")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_FUNC(format,-2,_SC(".s")), + _DECL_FUNC(printf,-2,_SC(".s")), + _DECL_FUNC(strip,2,_SC(".s")), + _DECL_FUNC(lstrip,2,_SC(".s")), + _DECL_FUNC(rstrip,2,_SC(".s")), + _DECL_FUNC(split,3,_SC(".ss")), + _DECL_FUNC(escape,2,_SC(".s")), + _DECL_FUNC(startswith,3,_SC(".ss")), + _DECL_FUNC(endswith,3,_SC(".ss")), + {NULL,(SQFUNCTION)0,0,NULL} }; #undef _DECL_FUNC SQInteger sqstd_register_stringlib(HRABBITVM v) { - sq_pushstring(v,_SC("regexp"),-1); - sq_newclass(v,SQFalse); - SQInteger i = 0; - while(rexobj_funcs[i].name != 0) { - const SQRegFunction &f = rexobj_funcs[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_setnativeclosurename(v,-1,f.name); - sq_newslot(v,-3,SQFalse); - i++; - } - sq_newslot(v,-3,SQFalse); + sq_pushstring(v,_SC("regexp"),-1); + sq_newclass(v,SQFalse); + SQInteger i = 0; + while(rexobj_funcs[i].name != 0) { + const SQRegFunction &f = rexobj_funcs[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_newslot(v,-3,SQFalse); + i++; + } + sq_newslot(v,-3,SQFalse); - i = 0; - while(stringlib_funcs[i].name!=0) - { - sq_pushstring(v,stringlib_funcs[i].name,-1); - sq_newclosure(v,stringlib_funcs[i].f,0); - sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask); - sq_setnativeclosurename(v,-1,stringlib_funcs[i].name); - sq_newslot(v,-3,SQFalse); - i++; - } - return 1; + i = 0; + while(stringlib_funcs[i].name!=0) + { + sq_pushstring(v,stringlib_funcs[i].name,-1); + sq_newclosure(v,stringlib_funcs[i].f,0); + sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,stringlib_funcs[i].name); + sq_newslot(v,-3,SQFalse); + i++; + } + return 1; } diff --git a/rabbit-std/sqstdstring.hpp b/rabbit-std/sqstdstring.hpp index 4a2fc38..0343ea8 100644 --- a/rabbit-std/sqstdstring.hpp +++ b/rabbit-std/sqstdstring.hpp @@ -11,8 +11,8 @@ typedef unsigned int SQRexBool; typedef struct SQRex SQRex; typedef struct { - const SQChar *begin; - SQInteger len; + const SQChar *begin; + SQInteger len; } SQRexMatch; RABBIT_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error); diff --git a/rabbit-std/sqstdsystem.cpp b/rabbit-std/sqstdsystem.cpp index 2a05195..d59c78f 100644 --- a/rabbit-std/sqstdsystem.cpp +++ b/rabbit-std/sqstdsystem.cpp @@ -29,125 +29,125 @@ static SQInteger _system_getenv(HRABBITVM v) { - const SQChar *s; - if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ - sq_pushstring(v,scgetenv(s),-1); - return 1; - } - return 0; + const SQChar *s; + if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ + sq_pushstring(v,scgetenv(s),-1); + return 1; + } + return 0; } static SQInteger _system_system(HRABBITVM v) { - const SQChar *s; - if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ - sq_pushinteger(v,scsystem(s)); - return 1; - } - return sq_throwerror(v,_SC("wrong param")); + const SQChar *s; + if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ + sq_pushinteger(v,scsystem(s)); + return 1; + } + return sq_throwerror(v,_SC("wrong param")); } static SQInteger _system_clock(HRABBITVM v) { - sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); - return 1; + sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); + return 1; } static SQInteger _system_time(HRABBITVM v) { - SQInteger t = (SQInteger)time(NULL); - sq_pushinteger(v,t); - return 1; + SQInteger t = (SQInteger)time(NULL); + sq_pushinteger(v,t); + return 1; } static SQInteger _system_remove(HRABBITVM v) { - const SQChar *s; - sq_getstring(v,2,&s); - if(scremove(s)==-1) - return sq_throwerror(v,_SC("remove() failed")); - return 0; + const SQChar *s; + sq_getstring(v,2,&s); + if(scremove(s)==-1) + return sq_throwerror(v,_SC("remove() failed")); + return 0; } static SQInteger _system_rename(HRABBITVM v) { - const SQChar *oldn,*newn; - sq_getstring(v,2,&oldn); - sq_getstring(v,3,&newn); - if(screname(oldn,newn)==-1) - return sq_throwerror(v,_SC("rename() failed")); - return 0; + const SQChar *oldn,*newn; + sq_getstring(v,2,&oldn); + sq_getstring(v,3,&newn); + if(screname(oldn,newn)==-1) + return sq_throwerror(v,_SC("rename() failed")); + return 0; } static void _set_integer_slot(HRABBITVM v,const SQChar *name,SQInteger val) { - sq_pushstring(v,name,-1); - sq_pushinteger(v,val); - sq_rawset(v,-3); + sq_pushstring(v,name,-1); + sq_pushinteger(v,val); + sq_rawset(v,-3); } static SQInteger _system_date(HRABBITVM v) { - time_t t; - SQInteger it; - SQInteger format = 'l'; - if(sq_gettop(v) > 1) { - sq_getinteger(v,2,&it); - t = it; - if(sq_gettop(v) > 2) { - sq_getinteger(v,3,(SQInteger*)&format); - } - } - else { - time(&t); - } - tm *date; - if(format == 'u') - date = gmtime(&t); - else - date = localtime(&t); - if(!date) - return sq_throwerror(v,_SC("crt api failure")); - sq_newtable(v); - _set_integer_slot(v, _SC("sec"), date->tm_sec); - _set_integer_slot(v, _SC("min"), date->tm_min); - _set_integer_slot(v, _SC("hour"), date->tm_hour); - _set_integer_slot(v, _SC("day"), date->tm_mday); - _set_integer_slot(v, _SC("month"), date->tm_mon); - _set_integer_slot(v, _SC("year"), date->tm_year+1900); - _set_integer_slot(v, _SC("wday"), date->tm_wday); - _set_integer_slot(v, _SC("yday"), date->tm_yday); - return 1; + time_t t; + SQInteger it; + SQInteger format = 'l'; + if(sq_gettop(v) > 1) { + sq_getinteger(v,2,&it); + t = it; + if(sq_gettop(v) > 2) { + sq_getinteger(v,3,(SQInteger*)&format); + } + } + else { + time(&t); + } + tm *date; + if(format == 'u') + date = gmtime(&t); + else + date = localtime(&t); + if(!date) + return sq_throwerror(v,_SC("crt api failure")); + sq_newtable(v); + _set_integer_slot(v, _SC("sec"), date->tm_sec); + _set_integer_slot(v, _SC("min"), date->tm_min); + _set_integer_slot(v, _SC("hour"), date->tm_hour); + _set_integer_slot(v, _SC("day"), date->tm_mday); + _set_integer_slot(v, _SC("month"), date->tm_mon); + _set_integer_slot(v, _SC("year"), date->tm_year+1900); + _set_integer_slot(v, _SC("wday"), date->tm_wday); + _set_integer_slot(v, _SC("yday"), date->tm_yday); + return 1; } #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask} static const SQRegFunction systemlib_funcs[]={ - _DECL_FUNC(getenv,2,_SC(".s")), - _DECL_FUNC(system,2,_SC(".s")), - _DECL_FUNC(clock,0,NULL), - _DECL_FUNC(time,1,NULL), - _DECL_FUNC(date,-1,_SC(".nn")), - _DECL_FUNC(remove,2,_SC(".s")), - _DECL_FUNC(rename,3,_SC(".ss")), - {NULL,(SQFUNCTION)0,0,NULL} + _DECL_FUNC(getenv,2,_SC(".s")), + _DECL_FUNC(system,2,_SC(".s")), + _DECL_FUNC(clock,0,NULL), + _DECL_FUNC(time,1,NULL), + _DECL_FUNC(date,-1,_SC(".nn")), + _DECL_FUNC(remove,2,_SC(".s")), + _DECL_FUNC(rename,3,_SC(".ss")), + {NULL,(SQFUNCTION)0,0,NULL} }; #undef _DECL_FUNC SQInteger sqstd_register_systemlib(HRABBITVM v) { - SQInteger i=0; - while(systemlib_funcs[i].name!=0) - { - sq_pushstring(v,systemlib_funcs[i].name,-1); - sq_newclosure(v,systemlib_funcs[i].f,0); - sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); - sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); - sq_newslot(v,-3,SQFalse); - i++; - } - return 1; + SQInteger i=0; + while(systemlib_funcs[i].name!=0) + { + sq_pushstring(v,systemlib_funcs[i].name,-1); + sq_newclosure(v,systemlib_funcs[i].f,0); + sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); + sq_newslot(v,-3,SQFalse); + i++; + } + return 1; } diff --git a/rabbit/rabbit.hpp b/rabbit/rabbit.hpp index db025c5..97980d3 100644 --- a/rabbit/rabbit.hpp +++ b/rabbit/rabbit.hpp @@ -50,66 +50,66 @@ struct SQOuter; #include "sqconfig.hpp" -#define RABBIT_VERSION _SC("Rabbit 0.1 un-stable") +#define RABBIT_VERSION _SC("Rabbit 0.1 un-stable") #define RABBIT_COPYRIGHT _SC("Copyright (C) 2003-2017 Alberto Demichelis") -#define RABBIT_AUTHOR _SC("Edouard DUPIN") +#define RABBIT_AUTHOR _SC("Edouard DUPIN") #define RABBIT_VERSION_NUMBER 010 -#define SQ_VMSTATE_IDLE 0 -#define SQ_VMSTATE_RUNNING 1 -#define SQ_VMSTATE_SUSPENDED 2 +#define SQ_VMSTATE_IDLE 0 +#define SQ_VMSTATE_RUNNING 1 +#define SQ_VMSTATE_SUSPENDED 2 #define RABBIT_EOB 0 #define SQ_BYTECODE_STREAM_TAG 0xFAFA -#define SQOBJECT_REF_COUNTED 0x08000000 -#define SQOBJECT_NUMERIC 0x04000000 -#define SQOBJECT_DELEGABLE 0x02000000 -#define SQOBJECT_CANBEFALSE 0x01000000 +#define SQOBJECT_REF_COUNTED 0x08000000 +#define SQOBJECT_NUMERIC 0x04000000 +#define SQOBJECT_DELEGABLE 0x02000000 +#define SQOBJECT_CANBEFALSE 0x01000000 #define SQ_MATCHTYPEMASKSTRING (-99999) #define _RT_MASK 0x00FFFFFF #define _RAW_TYPE(type) (type&_RT_MASK) -#define _RT_NULL 0x00000001 -#define _RT_INTEGER 0x00000002 -#define _RT_FLOAT 0x00000004 -#define _RT_BOOL 0x00000008 -#define _RT_STRING 0x00000010 -#define _RT_TABLE 0x00000020 -#define _RT_ARRAY 0x00000040 -#define _RT_USERDATA 0x00000080 -#define _RT_CLOSURE 0x00000100 +#define _RT_NULL 0x00000001 +#define _RT_INTEGER 0x00000002 +#define _RT_FLOAT 0x00000004 +#define _RT_BOOL 0x00000008 +#define _RT_STRING 0x00000010 +#define _RT_TABLE 0x00000020 +#define _RT_ARRAY 0x00000040 +#define _RT_USERDATA 0x00000080 +#define _RT_CLOSURE 0x00000100 #define _RT_NATIVECLOSURE 0x00000200 -#define _RT_GENERATOR 0x00000400 -#define _RT_USERPOINTER 0x00000800 -#define _RT_THREAD 0x00001000 -#define _RT_FUNCPROTO 0x00002000 -#define _RT_CLASS 0x00004000 -#define _RT_INSTANCE 0x00008000 -#define _RT_WEAKREF 0x00010000 -#define _RT_OUTER 0x00020000 +#define _RT_GENERATOR 0x00000400 +#define _RT_USERPOINTER 0x00000800 +#define _RT_THREAD 0x00001000 +#define _RT_FUNCPROTO 0x00002000 +#define _RT_CLASS 0x00004000 +#define _RT_INSTANCE 0x00008000 +#define _RT_WEAKREF 0x00010000 +#define _RT_OUTER 0x00020000 typedef enum tagSQObjectType{ - OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), - OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), - OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), - OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE), - OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED), - OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED), - OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED), - OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED), - OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED), - OT_USERPOINTER = _RT_USERPOINTER, - OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) , - OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only - OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), - OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED), - OT_OUTER = (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only + OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), + OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), + OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), + OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE), + OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED), + OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED), + OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED), + OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED), + OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED), + OT_USERPOINTER = _RT_USERPOINTER, + OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) , + OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only + OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), + OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED), + OT_OUTER = (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only }SQObjectType; #define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED) @@ -117,43 +117,43 @@ typedef enum tagSQObjectType{ typedef union tagSQObjectValue { - struct SQTable *pTable; - struct SQArray *pArray; - struct SQClosure *pClosure; - struct SQOuter *pOuter; - struct SQGenerator *pGenerator; - struct SQNativeClosure *pNativeClosure; - struct SQString *pString; - struct SQUserData *pUserData; - SQInteger nInteger; - SQFloat fFloat; - SQUserPointer pUserPointer; - struct SQFunctionProto *pFunctionProto; - struct SQRefCounted *pRefCounted; - struct SQDelegable *pDelegable; - struct SQVM *pThread; - struct SQClass *pClass; - struct SQInstance *pInstance; - struct SQWeakRef *pWeakRef; - SQRawObjectVal raw; + struct SQTable *pTable; + struct SQArray *pArray; + struct SQClosure *pClosure; + struct SQOuter *pOuter; + struct SQGenerator *pGenerator; + struct SQNativeClosure *pNativeClosure; + struct SQString *pString; + struct SQUserData *pUserData; + SQInteger nInteger; + SQFloat fFloat; + SQUserPointer pUserPointer; + struct SQFunctionProto *pFunctionProto; + struct SQRefCounted *pRefCounted; + struct SQDelegable *pDelegable; + struct SQVM *pThread; + struct SQClass *pClass; + struct SQInstance *pInstance; + struct SQWeakRef *pWeakRef; + SQRawObjectVal raw; }SQObjectValue; typedef struct tagSQObject { - SQObjectType _type; - SQObjectValue _unVal; + SQObjectType _type; + SQObjectValue _unVal; }SQObject; typedef struct tagSQMemberHandle{ - SQBool _static; - SQInteger _index; + SQBool _static; + SQInteger _index; }SQMemberHandle; typedef struct tagSQStackInfos{ - const SQChar* funcname; - const SQChar* source; - SQInteger line; + const SQChar* funcname; + const SQChar* source; + SQInteger line; }SQStackInfos; typedef struct SQVM* HRABBITVM; @@ -170,17 +170,17 @@ typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger); typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer); typedef struct tagSQRegFunction{ - const SQChar *name; - SQFUNCTION f; - SQInteger nparamscheck; - const SQChar *typemask; + const SQChar *name; + SQFUNCTION f; + SQInteger nparamscheck; + const SQChar *typemask; }SQRegFunction; typedef struct tagSQFunctionInfo { - SQUserPointer funcid; - const SQChar *name; - const SQChar *source; - SQInteger line; + SQUserPointer funcid; + const SQChar *name; + const SQChar *source; + SQInteger line; }SQFunctionInfo; /*vm*/ diff --git a/rabbit/sqapi.cpp b/rabbit/sqapi.cpp index 9d79250..bcfb1cf 100644 --- a/rabbit/sqapi.cpp +++ b/rabbit/sqapi.cpp @@ -19,1171 +19,1171 @@ static bool sq_aux_gettypedarg(HRABBITVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o) { - *o = &stack_get(v,idx); - if(sq_type(**o) != type){ - SQObjectPtr oval = v->PrintObjVal(**o); - v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval)); - return false; - } - return true; + *o = &stack_get(v,idx); + if(sq_type(**o) != type){ + SQObjectPtr oval = v->PrintObjVal(**o); + v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval)); + return false; + } + return true; } #define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; } #define sq_aux_paramscheck(v,count) \ { \ - if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\ + if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\ } SQInteger sq_aux_invalidtype(HRABBITVM v,SQObjectType type) { - SQUnsignedInteger buf_size = 100 *sizeof(SQChar); - scsprintf(_ss(v)->GetScratchPad(buf_size), buf_size, _SC("unexpected type %s"), IdType2Name(type)); - return sq_throwerror(v, _ss(v)->GetScratchPad(-1)); + SQUnsignedInteger buf_size = 100 *sizeof(SQChar); + scsprintf(_ss(v)->GetScratchPad(buf_size), buf_size, _SC("unexpected type %s"), IdType2Name(type)); + return sq_throwerror(v, _ss(v)->GetScratchPad(-1)); } HRABBITVM sq_open(SQInteger initialstacksize) { - SQSharedState *ss; - SQVM *v; - sq_new(ss, SQSharedState); - ss->Init(); - v = (SQVM *)SQ_MALLOC(sizeof(SQVM)); - new (v) SQVM(ss); - ss->_root_vm = v; - if(v->Init(NULL, initialstacksize)) { - return v; - } else { - sq_delete(v, SQVM); - return NULL; - } - return v; + SQSharedState *ss; + SQVM *v; + sq_new(ss, SQSharedState); + ss->Init(); + v = (SQVM *)SQ_MALLOC(sizeof(SQVM)); + new (v) SQVM(ss); + ss->_root_vm = v; + if(v->Init(NULL, initialstacksize)) { + return v; + } else { + sq_delete(v, SQVM); + return NULL; + } + return v; } HRABBITVM sq_newthread(HRABBITVM friendvm, SQInteger initialstacksize) { - SQSharedState *ss; - SQVM *v; - ss=_ss(friendvm); + SQSharedState *ss; + SQVM *v; + ss=_ss(friendvm); - v= (SQVM *)SQ_MALLOC(sizeof(SQVM)); - new (v) SQVM(ss); + v= (SQVM *)SQ_MALLOC(sizeof(SQVM)); + new (v) SQVM(ss); - if(v->Init(friendvm, initialstacksize)) { - friendvm->Push(v); - return v; - } else { - sq_delete(v, SQVM); - return NULL; - } + if(v->Init(friendvm, initialstacksize)) { + friendvm->Push(v); + return v; + } else { + sq_delete(v, SQVM); + return NULL; + } } SQInteger sq_getvmstate(HRABBITVM v) { - if(v->_suspended) - return SQ_VMSTATE_SUSPENDED; - else { - if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING; - else return SQ_VMSTATE_IDLE; - } + if(v->_suspended) + return SQ_VMSTATE_SUSPENDED; + else { + if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING; + else return SQ_VMSTATE_IDLE; + } } void sq_seterrorhandler(HRABBITVM v) { - SQObject o = stack_get(v, -1); - if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { - v->_errorhandler = o; - v->Pop(); - } + SQObject o = stack_get(v, -1); + if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { + v->_errorhandler = o; + v->Pop(); + } } void sq_setnativedebughook(HRABBITVM v,SQDEBUGHOOK hook) { - v->_debughook_native = hook; - v->_debughook_closure.Null(); - v->_debughook = hook?true:false; + v->_debughook_native = hook; + v->_debughook_closure.Null(); + v->_debughook = hook?true:false; } void sq_setdebughook(HRABBITVM v) { - SQObject o = stack_get(v,-1); - if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { - v->_debughook_closure = o; - v->_debughook_native = NULL; - v->_debughook = !sq_isnull(o); - v->Pop(); - } + SQObject o = stack_get(v,-1); + if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { + v->_debughook_closure = o; + v->_debughook_native = NULL; + v->_debughook = !sq_isnull(o); + v->Pop(); + } } void sq_close(HRABBITVM v) { - SQSharedState *ss = _ss(v); - _thread(ss->_root_vm)->Finalize(); - sq_delete(ss, SQSharedState); + SQSharedState *ss = _ss(v); + _thread(ss->_root_vm)->Finalize(); + sq_delete(ss, SQSharedState); } SQInteger sq_getversion() { - return RABBIT_VERSION_NUMBER; + return RABBIT_VERSION_NUMBER; } SQRESULT sq_compile(HRABBITVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) { - SQObjectPtr o; + SQObjectPtr o; #ifndef NO_COMPILER - if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { - v->Push(SQClosure::Create(_ss(v), _funcproto(o), _table(v->_roottable)->GetWeakRef(OT_TABLE))); - return SQ_OK; - } - return SQ_ERROR; + if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { + v->Push(SQClosure::Create(_ss(v), _funcproto(o), _table(v->_roottable)->GetWeakRef(OT_TABLE))); + return SQ_OK; + } + return SQ_ERROR; #else - return sq_throwerror(v,_SC("this is a no compiler build")); + return sq_throwerror(v,_SC("this is a no compiler build")); #endif } void sq_enabledebuginfo(HRABBITVM v, SQBool enable) { - _ss(v)->_debuginfo = enable?true:false; + _ss(v)->_debuginfo = enable?true:false; } void sq_notifyallexceptions(HRABBITVM v, SQBool enable) { - _ss(v)->_notifyallexceptions = enable?true:false; + _ss(v)->_notifyallexceptions = enable?true:false; } void sq_addref(HRABBITVM v,HSQOBJECT *po) { - if(!ISREFCOUNTED(sq_type(*po))) return; - __AddRef(po->_type,po->_unVal); + if(!ISREFCOUNTED(sq_type(*po))) return; + __AddRef(po->_type,po->_unVal); } SQUnsignedInteger sq_getrefcount(HRABBITVM v,HSQOBJECT *po) { - if(!ISREFCOUNTED(sq_type(*po))) return 0; + if(!ISREFCOUNTED(sq_type(*po))) return 0; return po->_unVal.pRefCounted->_uiRef; } SQBool sq_release(HRABBITVM v,HSQOBJECT *po) { - if(!ISREFCOUNTED(sq_type(*po))) return SQTrue; - bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse; - __Release(po->_type,po->_unVal); - return ret; //the ret val doesn't work(and cannot be fixed) + if(!ISREFCOUNTED(sq_type(*po))) return SQTrue; + bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse; + __Release(po->_type,po->_unVal); + return ret; //the ret val doesn't work(and cannot be fixed) } SQUnsignedInteger sq_getvmrefcount(HRABBITVM SQ_UNUSED_ARG(v), const HSQOBJECT *po) { - if (!ISREFCOUNTED(sq_type(*po))) return 0; - return po->_unVal.pRefCounted->_uiRef; + if (!ISREFCOUNTED(sq_type(*po))) return 0; + return po->_unVal.pRefCounted->_uiRef; } const SQChar *sq_objtostring(const HSQOBJECT *o) { - if(sq_type(*o) == OT_STRING) { - return _stringval(*o); - } - return NULL; + if(sq_type(*o) == OT_STRING) { + return _stringval(*o); + } + return NULL; } SQInteger sq_objtointeger(const HSQOBJECT *o) { - if(sq_isnumeric(*o)) { - return tointeger(*o); - } - return 0; + if(sq_isnumeric(*o)) { + return tointeger(*o); + } + return 0; } SQFloat sq_objtofloat(const HSQOBJECT *o) { - if(sq_isnumeric(*o)) { - return tofloat(*o); - } - return 0; + if(sq_isnumeric(*o)) { + return tofloat(*o); + } + return 0; } SQBool sq_objtobool(const HSQOBJECT *o) { - if(sq_isbool(*o)) { - return _integer(*o); - } - return SQFalse; + if(sq_isbool(*o)) { + return _integer(*o); + } + return SQFalse; } SQUserPointer sq_objtouserpointer(const HSQOBJECT *o) { - if(sq_isuserpointer(*o)) { - return _userpointer(*o); - } - return 0; + if(sq_isuserpointer(*o)) { + return _userpointer(*o); + } + return 0; } void sq_pushnull(HRABBITVM v) { - v->PushNull(); + v->PushNull(); } void sq_pushstring(HRABBITVM v,const SQChar *s,SQInteger len) { - if(s) - v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); - else v->PushNull(); + if(s) + v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); + else v->PushNull(); } void sq_pushinteger(HRABBITVM v,SQInteger n) { - v->Push(n); + v->Push(n); } void sq_pushbool(HRABBITVM v,SQBool b) { - v->Push(b?true:false); + v->Push(b?true:false); } void sq_pushfloat(HRABBITVM v,SQFloat n) { - v->Push(n); + v->Push(n); } void sq_pushuserpointer(HRABBITVM v,SQUserPointer p) { - v->Push(p); + v->Push(p); } void sq_pushthread(HRABBITVM v, HRABBITVM thread) { - v->Push(thread); + v->Push(thread); } SQUserPointer sq_newuserdata(HRABBITVM v,SQUnsignedInteger size) { - SQUserData *ud = SQUserData::Create(_ss(v), size + SQ_ALIGNMENT); - v->Push(ud); - return (SQUserPointer)sq_aligning(ud + 1); + SQUserData *ud = SQUserData::Create(_ss(v), size + SQ_ALIGNMENT); + v->Push(ud); + return (SQUserPointer)sq_aligning(ud + 1); } void sq_newtable(HRABBITVM v) { - v->Push(SQTable::Create(_ss(v), 0)); + v->Push(SQTable::Create(_ss(v), 0)); } void sq_newtableex(HRABBITVM v,SQInteger initialcapacity) { - v->Push(SQTable::Create(_ss(v), initialcapacity)); + v->Push(SQTable::Create(_ss(v), initialcapacity)); } void sq_newarray(HRABBITVM v,SQInteger size) { - v->Push(SQArray::Create(_ss(v), size)); + v->Push(SQArray::Create(_ss(v), size)); } SQRESULT sq_newclass(HRABBITVM v,SQBool hasbase) { - SQClass *baseclass = NULL; - if(hasbase) { - SQObjectPtr &base = stack_get(v,-1); - if(sq_type(base) != OT_CLASS) - return sq_throwerror(v,_SC("invalid base type")); - baseclass = _class(base); - } - SQClass *newclass = SQClass::Create(_ss(v), baseclass); - if(baseclass) v->Pop(); - v->Push(newclass); - return SQ_OK; + SQClass *baseclass = NULL; + if(hasbase) { + SQObjectPtr &base = stack_get(v,-1); + if(sq_type(base) != OT_CLASS) + return sq_throwerror(v,_SC("invalid base type")); + baseclass = _class(base); + } + SQClass *newclass = SQClass::Create(_ss(v), baseclass); + if(baseclass) v->Pop(); + v->Push(newclass); + return SQ_OK; } SQBool sq_instanceof(HRABBITVM v) { - SQObjectPtr &inst = stack_get(v,-1); - SQObjectPtr &cl = stack_get(v,-2); - if(sq_type(inst) != OT_INSTANCE || sq_type(cl) != OT_CLASS) - return sq_throwerror(v,_SC("invalid param type")); - return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse; + SQObjectPtr &inst = stack_get(v,-1); + SQObjectPtr &cl = stack_get(v,-2); + if(sq_type(inst) != OT_INSTANCE || sq_type(cl) != OT_CLASS) + return sq_throwerror(v,_SC("invalid param type")); + return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse; } SQRESULT sq_arrayappend(HRABBITVM v,SQInteger idx) { - sq_aux_paramscheck(v,2); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - _array(*arr)->Append(v->GetUp(-1)); - v->Pop(); - return SQ_OK; + sq_aux_paramscheck(v,2); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + _array(*arr)->Append(v->GetUp(-1)); + v->Pop(); + return SQ_OK; } SQRESULT sq_arraypop(HRABBITVM v,SQInteger idx,SQBool pushval) { - sq_aux_paramscheck(v, 1); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - if(_array(*arr)->Size() > 0) { - if(pushval != 0){ v->Push(_array(*arr)->Top()); } - _array(*arr)->Pop(); - return SQ_OK; - } - return sq_throwerror(v, _SC("empty array")); + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + if(_array(*arr)->Size() > 0) { + if(pushval != 0){ v->Push(_array(*arr)->Top()); } + _array(*arr)->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("empty array")); } SQRESULT sq_arrayresize(HRABBITVM v,SQInteger idx,SQInteger newsize) { - sq_aux_paramscheck(v,1); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - if(newsize >= 0) { - _array(*arr)->Resize(newsize); - return SQ_OK; - } - return sq_throwerror(v,_SC("negative size")); + sq_aux_paramscheck(v,1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + if(newsize >= 0) { + _array(*arr)->Resize(newsize); + return SQ_OK; + } + return sq_throwerror(v,_SC("negative size")); } SQRESULT sq_arrayreverse(HRABBITVM v,SQInteger idx) { - sq_aux_paramscheck(v, 1); - SQObjectPtr *o; - _GETSAFE_OBJ(v, idx, OT_ARRAY,o); - SQArray *arr = _array(*o); - if(arr->Size() > 0) { - SQObjectPtr t; - SQInteger size = arr->Size(); - SQInteger n = size >> 1; size -= 1; - for(SQInteger i = 0; i < n; i++) { - t = arr->_values[i]; - arr->_values[i] = arr->_values[size-i]; - arr->_values[size-i] = t; - } - return SQ_OK; - } - return SQ_OK; + sq_aux_paramscheck(v, 1); + SQObjectPtr *o; + _GETSAFE_OBJ(v, idx, OT_ARRAY,o); + SQArray *arr = _array(*o); + if(arr->Size() > 0) { + SQObjectPtr t; + SQInteger size = arr->Size(); + SQInteger n = size >> 1; size -= 1; + for(SQInteger i = 0; i < n; i++) { + t = arr->_values[i]; + arr->_values[i] = arr->_values[size-i]; + arr->_values[size-i] = t; + } + return SQ_OK; + } + return SQ_OK; } SQRESULT sq_arrayremove(HRABBITVM v,SQInteger idx,SQInteger itemidx) { - sq_aux_paramscheck(v, 1); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); } SQRESULT sq_arrayinsert(HRABBITVM v,SQInteger idx,SQInteger destpos) { - sq_aux_paramscheck(v, 1); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); - v->Pop(); - return ret; + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); + v->Pop(); + return ret; } void sq_newclosure(HRABBITVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) { - SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars); - nc->_nparamscheck = 0; - for(SQUnsignedInteger i = 0; i < nfreevars; i++) { - nc->_outervalues[i] = v->Top(); - v->Pop(); - } - v->Push(SQObjectPtr(nc)); + SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars); + nc->_nparamscheck = 0; + for(SQUnsignedInteger i = 0; i < nfreevars; i++) { + nc->_outervalues[i] = v->Top(); + v->Pop(); + } + v->Push(SQObjectPtr(nc)); } SQRESULT sq_getclosureinfo(HRABBITVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars) { - SQObject o = stack_get(v, idx); - if(sq_type(o) == OT_CLOSURE) { - SQClosure *c = _closure(o); - SQFunctionProto *proto = c->_function; - *nparams = (SQUnsignedInteger)proto->_nparameters; - *nfreevars = (SQUnsignedInteger)proto->_noutervalues; - return SQ_OK; - } - else if(sq_type(o) == OT_NATIVECLOSURE) - { - SQNativeClosure *c = _nativeclosure(o); - *nparams = (SQUnsignedInteger)c->_nparamscheck; - *nfreevars = c->_noutervalues; - return SQ_OK; - } - return sq_throwerror(v,_SC("the object is not a closure")); + SQObject o = stack_get(v, idx); + if(sq_type(o) == OT_CLOSURE) { + SQClosure *c = _closure(o); + SQFunctionProto *proto = c->_function; + *nparams = (SQUnsignedInteger)proto->_nparameters; + *nfreevars = (SQUnsignedInteger)proto->_noutervalues; + return SQ_OK; + } + else if(sq_type(o) == OT_NATIVECLOSURE) + { + SQNativeClosure *c = _nativeclosure(o); + *nparams = (SQUnsignedInteger)c->_nparamscheck; + *nfreevars = c->_noutervalues; + return SQ_OK; + } + return sq_throwerror(v,_SC("the object is not a closure")); } SQRESULT sq_setnativeclosurename(HRABBITVM v,SQInteger idx,const SQChar *name) { - SQObject o = stack_get(v, idx); - if(sq_isnativeclosure(o)) { - SQNativeClosure *nc = _nativeclosure(o); - nc->_name = SQString::Create(_ss(v),name); - return SQ_OK; - } - return sq_throwerror(v,_SC("the object is not a nativeclosure")); + SQObject o = stack_get(v, idx); + if(sq_isnativeclosure(o)) { + SQNativeClosure *nc = _nativeclosure(o); + nc->_name = SQString::Create(_ss(v),name); + return SQ_OK; + } + return sq_throwerror(v,_SC("the object is not a nativeclosure")); } SQRESULT sq_setparamscheck(HRABBITVM v,SQInteger nparamscheck,const SQChar *typemask) { - SQObject o = stack_get(v, -1); - if(!sq_isnativeclosure(o)) - return sq_throwerror(v, _SC("native closure expected")); - SQNativeClosure *nc = _nativeclosure(o); - nc->_nparamscheck = nparamscheck; - if(typemask) { - SQIntVec res; - if(!CompileTypemask(res, typemask)) - return sq_throwerror(v, _SC("invalid typemask")); - nc->_typecheck.copy(res); - } - else { - nc->_typecheck.resize(0); - } - if(nparamscheck == SQ_MATCHTYPEMASKSTRING) { - nc->_nparamscheck = nc->_typecheck.size(); - } - return SQ_OK; + SQObject o = stack_get(v, -1); + if(!sq_isnativeclosure(o)) + return sq_throwerror(v, _SC("native closure expected")); + SQNativeClosure *nc = _nativeclosure(o); + nc->_nparamscheck = nparamscheck; + if(typemask) { + SQIntVec res; + if(!CompileTypemask(res, typemask)) + return sq_throwerror(v, _SC("invalid typemask")); + nc->_typecheck.copy(res); + } + else { + nc->_typecheck.resize(0); + } + if(nparamscheck == SQ_MATCHTYPEMASKSTRING) { + nc->_nparamscheck = nc->_typecheck.size(); + } + return SQ_OK; } SQRESULT sq_bindenv(HRABBITVM v,SQInteger idx) { - SQObjectPtr &o = stack_get(v,idx); - if(!sq_isnativeclosure(o) && - !sq_isclosure(o)) - return sq_throwerror(v,_SC("the target is not a closure")); - SQObjectPtr &env = stack_get(v,-1); - if(!sq_istable(env) && - !sq_isarray(env) && - !sq_isclass(env) && - !sq_isinstance(env)) - return sq_throwerror(v,_SC("invalid environment")); - SQWeakRef *w = _refcounted(env)->GetWeakRef(sq_type(env)); - SQObjectPtr ret; - if(sq_isclosure(o)) { - SQClosure *c = _closure(o)->Clone(); - __ObjRelease(c->_env); - c->_env = w; - __ObjAddRef(c->_env); - if(_closure(o)->_base) { - c->_base = _closure(o)->_base; - __ObjAddRef(c->_base); - } - ret = c; - } - else { //then must be a native closure - SQNativeClosure *c = _nativeclosure(o)->Clone(); - __ObjRelease(c->_env); - c->_env = w; - __ObjAddRef(c->_env); - ret = c; - } - v->Pop(); - v->Push(ret); - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if(!sq_isnativeclosure(o) && + !sq_isclosure(o)) + return sq_throwerror(v,_SC("the target is not a closure")); + SQObjectPtr &env = stack_get(v,-1); + if(!sq_istable(env) && + !sq_isarray(env) && + !sq_isclass(env) && + !sq_isinstance(env)) + return sq_throwerror(v,_SC("invalid environment")); + SQWeakRef *w = _refcounted(env)->GetWeakRef(sq_type(env)); + SQObjectPtr ret; + if(sq_isclosure(o)) { + SQClosure *c = _closure(o)->Clone(); + __ObjRelease(c->_env); + c->_env = w; + __ObjAddRef(c->_env); + if(_closure(o)->_base) { + c->_base = _closure(o)->_base; + __ObjAddRef(c->_base); + } + ret = c; + } + else { //then must be a native closure + SQNativeClosure *c = _nativeclosure(o)->Clone(); + __ObjRelease(c->_env); + c->_env = w; + __ObjAddRef(c->_env); + ret = c; + } + v->Pop(); + v->Push(ret); + return SQ_OK; } SQRESULT sq_getclosurename(HRABBITVM v,SQInteger idx) { - SQObjectPtr &o = stack_get(v,idx); - if(!sq_isnativeclosure(o) && - !sq_isclosure(o)) - return sq_throwerror(v,_SC("the target is not a closure")); - if(sq_isnativeclosure(o)) - { - v->Push(_nativeclosure(o)->_name); - } - else { //closure - v->Push(_closure(o)->_function->_name); - } - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if(!sq_isnativeclosure(o) && + !sq_isclosure(o)) + return sq_throwerror(v,_SC("the target is not a closure")); + if(sq_isnativeclosure(o)) + { + v->Push(_nativeclosure(o)->_name); + } + else { //closure + v->Push(_closure(o)->_function->_name); + } + return SQ_OK; } SQRESULT sq_setclosureroot(HRABBITVM v,SQInteger idx) { - SQObjectPtr &c = stack_get(v,idx); - SQObject o = stack_get(v, -1); - if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected")); - if(sq_istable(o)) { - _closure(c)->SetRoot(_table(o)->GetWeakRef(OT_TABLE)); - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v, _SC("invalid type")); + SQObjectPtr &c = stack_get(v,idx); + SQObject o = stack_get(v, -1); + if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected")); + if(sq_istable(o)) { + _closure(c)->SetRoot(_table(o)->GetWeakRef(OT_TABLE)); + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("invalid type")); } SQRESULT sq_getclosureroot(HRABBITVM v,SQInteger idx) { - SQObjectPtr &c = stack_get(v,idx); - if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected")); - v->Push(_closure(c)->_root->_obj); - return SQ_OK; + SQObjectPtr &c = stack_get(v,idx); + if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected")); + v->Push(_closure(c)->_root->_obj); + return SQ_OK; } SQRESULT sq_clear(HRABBITVM v,SQInteger idx) { - SQObject &o=stack_get(v,idx); - switch(sq_type(o)) { - case OT_TABLE: _table(o)->Clear(); break; - case OT_ARRAY: _array(o)->Resize(0); break; - default: - return sq_throwerror(v, _SC("clear only works on table and array")); - break; + SQObject &o=stack_get(v,idx); + switch(sq_type(o)) { + case OT_TABLE: _table(o)->Clear(); break; + case OT_ARRAY: _array(o)->Resize(0); break; + default: + return sq_throwerror(v, _SC("clear only works on table and array")); + break; - } - return SQ_OK; + } + return SQ_OK; } void sq_pushroottable(HRABBITVM v) { - v->Push(v->_roottable); + v->Push(v->_roottable); } void sq_pushregistrytable(HRABBITVM v) { - v->Push(_ss(v)->_registry); + v->Push(_ss(v)->_registry); } void sq_pushconsttable(HRABBITVM v) { - v->Push(_ss(v)->_consts); + v->Push(_ss(v)->_consts); } SQRESULT sq_setroottable(HRABBITVM v) { - SQObject o = stack_get(v, -1); - if(sq_istable(o) || sq_isnull(o)) { - v->_roottable = o; - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v, _SC("invalid type")); + SQObject o = stack_get(v, -1); + if(sq_istable(o) || sq_isnull(o)) { + v->_roottable = o; + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("invalid type")); } SQRESULT sq_setconsttable(HRABBITVM v) { - SQObject o = stack_get(v, -1); - if(sq_istable(o)) { - _ss(v)->_consts = o; - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v, _SC("invalid type, expected table")); + SQObject o = stack_get(v, -1); + if(sq_istable(o)) { + _ss(v)->_consts = o; + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("invalid type, expected table")); } void sq_setforeignptr(HRABBITVM v,SQUserPointer p) { - v->_foreignptr = p; + v->_foreignptr = p; } SQUserPointer sq_getforeignptr(HRABBITVM v) { - return v->_foreignptr; + return v->_foreignptr; } void sq_setsharedforeignptr(HRABBITVM v,SQUserPointer p) { - _ss(v)->_foreignptr = p; + _ss(v)->_foreignptr = p; } SQUserPointer sq_getsharedforeignptr(HRABBITVM v) { - return _ss(v)->_foreignptr; + return _ss(v)->_foreignptr; } void sq_setvmreleasehook(HRABBITVM v,SQRELEASEHOOK hook) { - v->_releasehook = hook; + v->_releasehook = hook; } SQRELEASEHOOK sq_getvmreleasehook(HRABBITVM v) { - return v->_releasehook; + return v->_releasehook; } void sq_setsharedreleasehook(HRABBITVM v,SQRELEASEHOOK hook) { - _ss(v)->_releasehook = hook; + _ss(v)->_releasehook = hook; } SQRELEASEHOOK sq_getsharedreleasehook(HRABBITVM v) { - return _ss(v)->_releasehook; + return _ss(v)->_releasehook; } void sq_push(HRABBITVM v,SQInteger idx) { - v->Push(stack_get(v, idx)); + v->Push(stack_get(v, idx)); } SQObjectType sq_gettype(HRABBITVM v,SQInteger idx) { - return sq_type(stack_get(v, idx)); + return sq_type(stack_get(v, idx)); } SQRESULT sq_typeof(HRABBITVM v,SQInteger idx) { - SQObjectPtr &o = stack_get(v, idx); - SQObjectPtr res; - if(!v->TypeOf(o,res)) { - return SQ_ERROR; - } - v->Push(res); - return SQ_OK; + SQObjectPtr &o = stack_get(v, idx); + SQObjectPtr res; + if(!v->TypeOf(o,res)) { + return SQ_ERROR; + } + v->Push(res); + return SQ_OK; } SQRESULT sq_tostring(HRABBITVM v,SQInteger idx) { - SQObjectPtr &o = stack_get(v, idx); - SQObjectPtr res; - if(!v->ToString(o,res)) { - return SQ_ERROR; - } - v->Push(res); - return SQ_OK; + SQObjectPtr &o = stack_get(v, idx); + SQObjectPtr res; + if(!v->ToString(o,res)) { + return SQ_ERROR; + } + v->Push(res); + return SQ_OK; } void sq_tobool(HRABBITVM v, SQInteger idx, SQBool *b) { - SQObjectPtr &o = stack_get(v, idx); - *b = SQVM::IsFalse(o)?SQFalse:SQTrue; + SQObjectPtr &o = stack_get(v, idx); + *b = SQVM::IsFalse(o)?SQFalse:SQTrue; } SQRESULT sq_getinteger(HRABBITVM v,SQInteger idx,SQInteger *i) { - SQObjectPtr &o = stack_get(v, idx); - if(sq_isnumeric(o)) { - *i = tointeger(o); - return SQ_OK; - } - if(sq_isbool(o)) { - *i = SQVM::IsFalse(o)?SQFalse:SQTrue; - return SQ_OK; - } - return SQ_ERROR; + SQObjectPtr &o = stack_get(v, idx); + if(sq_isnumeric(o)) { + *i = tointeger(o); + return SQ_OK; + } + if(sq_isbool(o)) { + *i = SQVM::IsFalse(o)?SQFalse:SQTrue; + return SQ_OK; + } + return SQ_ERROR; } SQRESULT sq_getfloat(HRABBITVM v,SQInteger idx,SQFloat *f) { - SQObjectPtr &o = stack_get(v, idx); - if(sq_isnumeric(o)) { - *f = tofloat(o); - return SQ_OK; - } - return SQ_ERROR; + SQObjectPtr &o = stack_get(v, idx); + if(sq_isnumeric(o)) { + *f = tofloat(o); + return SQ_OK; + } + return SQ_ERROR; } SQRESULT sq_getbool(HRABBITVM v,SQInteger idx,SQBool *b) { - SQObjectPtr &o = stack_get(v, idx); - if(sq_isbool(o)) { - *b = _integer(o); - return SQ_OK; - } - return SQ_ERROR; + SQObjectPtr &o = stack_get(v, idx); + if(sq_isbool(o)) { + *b = _integer(o); + return SQ_OK; + } + return SQ_ERROR; } SQRESULT sq_getstringandsize(HRABBITVM v,SQInteger idx,const SQChar **c,SQInteger *size) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_STRING,o); - *c = _stringval(*o); - *size = _string(*o)->_len; - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_STRING,o); + *c = _stringval(*o); + *size = _string(*o)->_len; + return SQ_OK; } SQRESULT sq_getstring(HRABBITVM v,SQInteger idx,const SQChar **c) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_STRING,o); - *c = _stringval(*o); - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_STRING,o); + *c = _stringval(*o); + return SQ_OK; } SQRESULT sq_getthread(HRABBITVM v,SQInteger idx,HRABBITVM *thread) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_THREAD,o); - *thread = _thread(*o); - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_THREAD,o); + *thread = _thread(*o); + return SQ_OK; } SQRESULT sq_clone(HRABBITVM v,SQInteger idx) { - SQObjectPtr &o = stack_get(v,idx); - v->PushNull(); - if(!v->Clone(o, stack_get(v, -1))){ - v->Pop(); - return SQ_ERROR; - } - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + v->PushNull(); + if(!v->Clone(o, stack_get(v, -1))){ + v->Pop(); + return SQ_ERROR; + } + return SQ_OK; } SQInteger sq_getsize(HRABBITVM v, SQInteger idx) { - SQObjectPtr &o = stack_get(v, idx); - SQObjectType type = sq_type(o); - switch(type) { - case OT_STRING: return _string(o)->_len; - case OT_TABLE: return _table(o)->CountUsed(); - case OT_ARRAY: return _array(o)->Size(); - case OT_USERDATA: return _userdata(o)->_size; - case OT_INSTANCE: return _instance(o)->_class->_udsize; - case OT_CLASS: return _class(o)->_udsize; - default: - return sq_aux_invalidtype(v, type); - } + SQObjectPtr &o = stack_get(v, idx); + SQObjectType type = sq_type(o); + switch(type) { + case OT_STRING: return _string(o)->_len; + case OT_TABLE: return _table(o)->CountUsed(); + case OT_ARRAY: return _array(o)->Size(); + case OT_USERDATA: return _userdata(o)->_size; + case OT_INSTANCE: return _instance(o)->_class->_udsize; + case OT_CLASS: return _class(o)->_udsize; + default: + return sq_aux_invalidtype(v, type); + } } SQHash sq_gethash(HRABBITVM v, SQInteger idx) { - SQObjectPtr &o = stack_get(v, idx); - return HashObj(o); + SQObjectPtr &o = stack_get(v, idx); + return HashObj(o); } SQRESULT sq_getuserdata(HRABBITVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_USERDATA,o); - (*p) = _userdataval(*o); - if(typetag) *typetag = _userdata(*o)->_typetag; - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_USERDATA,o); + (*p) = _userdataval(*o); + if(typetag) *typetag = _userdata(*o)->_typetag; + return SQ_OK; } SQRESULT sq_settypetag(HRABBITVM v,SQInteger idx,SQUserPointer typetag) { - SQObjectPtr &o = stack_get(v,idx); - switch(sq_type(o)) { - case OT_USERDATA: _userdata(o)->_typetag = typetag; break; - case OT_CLASS: _class(o)->_typetag = typetag; break; - default: return sq_throwerror(v,_SC("invalid object type")); - } - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + switch(sq_type(o)) { + case OT_USERDATA: _userdata(o)->_typetag = typetag; break; + case OT_CLASS: _class(o)->_typetag = typetag; break; + default: return sq_throwerror(v,_SC("invalid object type")); + } + return SQ_OK; } SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag) { switch(sq_type(*o)) { - case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; - case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break; - case OT_CLASS: *typetag = _class(*o)->_typetag; break; - default: return SQ_ERROR; + case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; + case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break; + case OT_CLASS: *typetag = _class(*o)->_typetag; break; + default: return SQ_ERROR; } return SQ_OK; } SQRESULT sq_gettypetag(HRABBITVM v,SQInteger idx,SQUserPointer *typetag) { - SQObjectPtr &o = stack_get(v,idx); - if (SQ_FAILED(sq_getobjtypetag(&o, typetag))) - return SQ_ERROR;// this is not an error it should be a bool but would break backward compatibility - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if (SQ_FAILED(sq_getobjtypetag(&o, typetag))) + return SQ_ERROR;// this is not an error it should be a bool but would break backward compatibility + return SQ_OK; } SQRESULT sq_getuserpointer(HRABBITVM v, SQInteger idx, SQUserPointer *p) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o); - (*p) = _userpointer(*o); - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o); + (*p) = _userpointer(*o); + return SQ_OK; } SQRESULT sq_setinstanceup(HRABBITVM v, SQInteger idx, SQUserPointer p) { - SQObjectPtr &o = stack_get(v,idx); - if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); - _instance(o)->_userpointer = p; - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); + _instance(o)->_userpointer = p; + return SQ_OK; } SQRESULT sq_setclassudsize(HRABBITVM v, SQInteger idx, SQInteger udsize) { - SQObjectPtr &o = stack_get(v,idx); - if(sq_type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class")); - if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked")); - _class(o)->_udsize = udsize; - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if(sq_type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class")); + if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked")); + _class(o)->_udsize = udsize; + return SQ_OK; } SQRESULT sq_getinstanceup(HRABBITVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag) { - SQObjectPtr &o = stack_get(v,idx); - if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); - (*p) = _instance(o)->_userpointer; - if(typetag != 0) { - SQClass *cl = _instance(o)->_class; - do{ - if(cl->_typetag == typetag) - return SQ_OK; - cl = cl->_base; - }while(cl != NULL); - return sq_throwerror(v,_SC("invalid type tag")); - } - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); + (*p) = _instance(o)->_userpointer; + if(typetag != 0) { + SQClass *cl = _instance(o)->_class; + do{ + if(cl->_typetag == typetag) + return SQ_OK; + cl = cl->_base; + }while(cl != NULL); + return sq_throwerror(v,_SC("invalid type tag")); + } + return SQ_OK; } SQInteger sq_gettop(HRABBITVM v) { - return (v->_top) - v->_stackbase; + return (v->_top) - v->_stackbase; } void sq_settop(HRABBITVM v, SQInteger newtop) { - SQInteger top = sq_gettop(v); - if(top > newtop) - sq_pop(v, top - newtop); - else - while(top++ < newtop) sq_pushnull(v); + SQInteger top = sq_gettop(v); + if(top > newtop) + sq_pop(v, top - newtop); + else + while(top++ < newtop) sq_pushnull(v); } void sq_pop(HRABBITVM v, SQInteger nelemstopop) { - assert(v->_top >= nelemstopop); - v->Pop(nelemstopop); + assert(v->_top >= nelemstopop); + v->Pop(nelemstopop); } void sq_poptop(HRABBITVM v) { - assert(v->_top >= 1); - v->Pop(); + assert(v->_top >= 1); + v->Pop(); } void sq_remove(HRABBITVM v, SQInteger idx) { - v->Remove(idx); + v->Remove(idx); } SQInteger sq_cmp(HRABBITVM v) { - SQInteger res; - v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res); - return res; + SQInteger res; + v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res); + return res; } SQRESULT sq_newslot(HRABBITVM v, SQInteger idx, SQBool bstatic) { - sq_aux_paramscheck(v, 3); - SQObjectPtr &self = stack_get(v, idx); - if(sq_type(self) == OT_TABLE || sq_type(self) == OT_CLASS) { - SQObjectPtr &key = v->GetUp(-2); - if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); - v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false); - v->Pop(2); - } - return SQ_OK; + sq_aux_paramscheck(v, 3); + SQObjectPtr &self = stack_get(v, idx); + if(sq_type(self) == OT_TABLE || sq_type(self) == OT_CLASS) { + SQObjectPtr &key = v->GetUp(-2); + if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false); + v->Pop(2); + } + return SQ_OK; } SQRESULT sq_deleteslot(HRABBITVM v,SQInteger idx,SQBool pushval) { - sq_aux_paramscheck(v, 2); - SQObjectPtr *self; - _GETSAFE_OBJ(v, idx, OT_TABLE,self); - SQObjectPtr &key = v->GetUp(-1); - if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); - SQObjectPtr res; - if(!v->DeleteSlot(*self, key, res)){ - v->Pop(); - return SQ_ERROR; - } - if(pushval) v->GetUp(-1) = res; - else v->Pop(); - return SQ_OK; + sq_aux_paramscheck(v, 2); + SQObjectPtr *self; + _GETSAFE_OBJ(v, idx, OT_TABLE,self); + SQObjectPtr &key = v->GetUp(-1); + if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + SQObjectPtr res; + if(!v->DeleteSlot(*self, key, res)){ + v->Pop(); + return SQ_ERROR; + } + if(pushval) v->GetUp(-1) = res; + else v->Pop(); + return SQ_OK; } SQRESULT sq_set(HRABBITVM v,SQInteger idx) { - SQObjectPtr &self = stack_get(v, idx); - if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) { - v->Pop(2); - return SQ_OK; - } - return SQ_ERROR; + SQObjectPtr &self = stack_get(v, idx); + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) { + v->Pop(2); + return SQ_OK; + } + return SQ_ERROR; } SQRESULT sq_rawset(HRABBITVM v,SQInteger idx) { - SQObjectPtr &self = stack_get(v, idx); - SQObjectPtr &key = v->GetUp(-2); - if(sq_type(key) == OT_NULL) { - v->Pop(2); - return sq_throwerror(v, _SC("null key")); - } - switch(sq_type(self)) { - case OT_TABLE: - _table(self)->NewSlot(key, v->GetUp(-1)); - v->Pop(2); - return SQ_OK; - break; - case OT_CLASS: - _class(self)->NewSlot(_ss(v), key, v->GetUp(-1),false); - v->Pop(2); - return SQ_OK; - break; - case OT_INSTANCE: - if(_instance(self)->Set(key, v->GetUp(-1))) { - v->Pop(2); - return SQ_OK; - } - break; - case OT_ARRAY: - if(v->Set(self, key, v->GetUp(-1),false)) { - v->Pop(2); - return SQ_OK; - } - break; - default: - v->Pop(2); - return sq_throwerror(v, _SC("rawset works only on array/table/class and instance")); - } - v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; + SQObjectPtr &self = stack_get(v, idx); + SQObjectPtr &key = v->GetUp(-2); + if(sq_type(key) == OT_NULL) { + v->Pop(2); + return sq_throwerror(v, _SC("null key")); + } + switch(sq_type(self)) { + case OT_TABLE: + _table(self)->NewSlot(key, v->GetUp(-1)); + v->Pop(2); + return SQ_OK; + break; + case OT_CLASS: + _class(self)->NewSlot(_ss(v), key, v->GetUp(-1),false); + v->Pop(2); + return SQ_OK; + break; + case OT_INSTANCE: + if(_instance(self)->Set(key, v->GetUp(-1))) { + v->Pop(2); + return SQ_OK; + } + break; + case OT_ARRAY: + if(v->Set(self, key, v->GetUp(-1),false)) { + v->Pop(2); + return SQ_OK; + } + break; + default: + v->Pop(2); + return sq_throwerror(v, _SC("rawset works only on array/table/class and instance")); + } + v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; } SQRESULT sq_newmember(HRABBITVM v,SQInteger idx,SQBool bstatic) { - SQObjectPtr &self = stack_get(v, idx); - if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); - SQObjectPtr &key = v->GetUp(-3); - if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key")); - if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false)) { - v->Pop(3); - return SQ_ERROR; - } - v->Pop(3); - return SQ_OK; + SQObjectPtr &self = stack_get(v, idx); + if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); + SQObjectPtr &key = v->GetUp(-3); + if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false)) { + v->Pop(3); + return SQ_ERROR; + } + v->Pop(3); + return SQ_OK; } SQRESULT sq_rawnewmember(HRABBITVM v,SQInteger idx,SQBool bstatic) { - SQObjectPtr &self = stack_get(v, idx); - if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); - SQObjectPtr &key = v->GetUp(-3); - if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key")); - if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true)) { - v->Pop(3); - return SQ_ERROR; - } - v->Pop(3); - return SQ_OK; + SQObjectPtr &self = stack_get(v, idx); + if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); + SQObjectPtr &key = v->GetUp(-3); + if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true)) { + v->Pop(3); + return SQ_ERROR; + } + v->Pop(3); + return SQ_OK; } SQRESULT sq_setdelegate(HRABBITVM v,SQInteger idx) { - SQObjectPtr &self = stack_get(v, idx); - SQObjectPtr &mt = v->GetUp(-1); - SQObjectType type = sq_type(self); - switch(type) { - case OT_TABLE: - if(sq_type(mt) == OT_TABLE) { - if(!_table(self)->SetDelegate(_table(mt))) { - return sq_throwerror(v, _SC("delagate cycle")); - } - v->Pop(); - } - else if(sq_type(mt)==OT_NULL) { - _table(self)->SetDelegate(NULL); v->Pop(); } - else return sq_aux_invalidtype(v,type); - break; - case OT_USERDATA: - if(sq_type(mt)==OT_TABLE) { - _userdata(self)->SetDelegate(_table(mt)); v->Pop(); } - else if(sq_type(mt)==OT_NULL) { - _userdata(self)->SetDelegate(NULL); v->Pop(); } - else return sq_aux_invalidtype(v, type); - break; - default: - return sq_aux_invalidtype(v, type); - break; - } - return SQ_OK; + SQObjectPtr &self = stack_get(v, idx); + SQObjectPtr &mt = v->GetUp(-1); + SQObjectType type = sq_type(self); + switch(type) { + case OT_TABLE: + if(sq_type(mt) == OT_TABLE) { + if(!_table(self)->SetDelegate(_table(mt))) { + return sq_throwerror(v, _SC("delagate cycle")); + } + v->Pop(); + } + else if(sq_type(mt)==OT_NULL) { + _table(self)->SetDelegate(NULL); v->Pop(); } + else return sq_aux_invalidtype(v,type); + break; + case OT_USERDATA: + if(sq_type(mt)==OT_TABLE) { + _userdata(self)->SetDelegate(_table(mt)); v->Pop(); } + else if(sq_type(mt)==OT_NULL) { + _userdata(self)->SetDelegate(NULL); v->Pop(); } + else return sq_aux_invalidtype(v, type); + break; + default: + return sq_aux_invalidtype(v, type); + break; + } + return SQ_OK; } SQRESULT sq_rawdeleteslot(HRABBITVM v,SQInteger idx,SQBool pushval) { - sq_aux_paramscheck(v, 2); - SQObjectPtr *self; - _GETSAFE_OBJ(v, idx, OT_TABLE,self); - SQObjectPtr &key = v->GetUp(-1); - SQObjectPtr t; - if(_table(*self)->Get(key,t)) { - _table(*self)->Remove(key); - } - if(pushval != 0) - v->GetUp(-1) = t; - else - v->Pop(); - return SQ_OK; + sq_aux_paramscheck(v, 2); + SQObjectPtr *self; + _GETSAFE_OBJ(v, idx, OT_TABLE,self); + SQObjectPtr &key = v->GetUp(-1); + SQObjectPtr t; + if(_table(*self)->Get(key,t)) { + _table(*self)->Remove(key); + } + if(pushval != 0) + v->GetUp(-1) = t; + else + v->Pop(); + return SQ_OK; } SQRESULT sq_getdelegate(HRABBITVM v,SQInteger idx) { - SQObjectPtr &self=stack_get(v,idx); - switch(sq_type(self)){ - case OT_TABLE: - case OT_USERDATA: - if(!_delegable(self)->_delegate){ - v->PushNull(); - break; - } - v->Push(SQObjectPtr(_delegable(self)->_delegate)); - break; - default: return sq_throwerror(v,_SC("wrong type")); break; - } - return SQ_OK; + SQObjectPtr &self=stack_get(v,idx); + switch(sq_type(self)){ + case OT_TABLE: + case OT_USERDATA: + if(!_delegable(self)->_delegate){ + v->PushNull(); + break; + } + v->Push(SQObjectPtr(_delegable(self)->_delegate)); + break; + default: return sq_throwerror(v,_SC("wrong type")); break; + } + return SQ_OK; } SQRESULT sq_get(HRABBITVM v,SQInteger idx) { - SQObjectPtr &self=stack_get(v,idx); - SQObjectPtr &obj = v->GetUp(-1); - if(v->Get(self,obj,obj,false,DONT_FALL_BACK)) - return SQ_OK; - v->Pop(); - return SQ_ERROR; + SQObjectPtr &self=stack_get(v,idx); + SQObjectPtr &obj = v->GetUp(-1); + if(v->Get(self,obj,obj,false,DONT_FALL_BACK)) + return SQ_OK; + v->Pop(); + return SQ_ERROR; } SQRESULT sq_rawget(HRABBITVM v,SQInteger idx) { - SQObjectPtr &self=stack_get(v,idx); - SQObjectPtr &obj = v->GetUp(-1); - switch(sq_type(self)) { - case OT_TABLE: - if(_table(self)->Get(obj,obj)) - return SQ_OK; - break; - case OT_CLASS: - if(_class(self)->Get(obj,obj)) - return SQ_OK; - break; - case OT_INSTANCE: - if(_instance(self)->Get(obj,obj)) - return SQ_OK; - break; - case OT_ARRAY:{ - if(sq_isnumeric(obj)){ - if(_array(self)->Get(tointeger(obj),obj)) { - return SQ_OK; - } - } - else { - v->Pop(); - return sq_throwerror(v,_SC("invalid index type for an array")); - } - } - break; - default: - v->Pop(); - return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); - } - v->Pop(); - return sq_throwerror(v,_SC("the index doesn't exist")); + SQObjectPtr &self=stack_get(v,idx); + SQObjectPtr &obj = v->GetUp(-1); + switch(sq_type(self)) { + case OT_TABLE: + if(_table(self)->Get(obj,obj)) + return SQ_OK; + break; + case OT_CLASS: + if(_class(self)->Get(obj,obj)) + return SQ_OK; + break; + case OT_INSTANCE: + if(_instance(self)->Get(obj,obj)) + return SQ_OK; + break; + case OT_ARRAY:{ + if(sq_isnumeric(obj)){ + if(_array(self)->Get(tointeger(obj),obj)) { + return SQ_OK; + } + } + else { + v->Pop(); + return sq_throwerror(v,_SC("invalid index type for an array")); + } + } + break; + default: + v->Pop(); + return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); + } + v->Pop(); + return sq_throwerror(v,_SC("the index doesn't exist")); } SQRESULT sq_getstackobj(HRABBITVM v,SQInteger idx,HSQOBJECT *po) { - *po=stack_get(v,idx); - return SQ_OK; + *po=stack_get(v,idx); + return SQ_OK; } const SQChar *sq_getlocal(HRABBITVM v,SQUnsignedInteger level,SQUnsignedInteger idx) { - SQUnsignedInteger cstksize=v->_callsstacksize; - SQUnsignedInteger lvl=(cstksize-level)-1; - SQInteger stackbase=v->_stackbase; - if(lvl_callsstack[(cstksize-i)-1]; - stackbase-=ci._prevstkbase; - } - SQVM::CallInfo &ci=v->_callsstack[lvl]; - if(sq_type(ci._closure)!=OT_CLOSURE) - return NULL; - SQClosure *c=_closure(ci._closure); - SQFunctionProto *func=c->_function; - if(func->_noutervalues > (SQInteger)idx) { - v->Push(*_outer(c->_outervalues[idx])->_valptr); - return _stringval(func->_outervalues[idx]._name); - } - idx -= func->_noutervalues; - return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1); - } - return NULL; + SQUnsignedInteger cstksize=v->_callsstacksize; + SQUnsignedInteger lvl=(cstksize-level)-1; + SQInteger stackbase=v->_stackbase; + if(lvl_callsstack[(cstksize-i)-1]; + stackbase-=ci._prevstkbase; + } + SQVM::CallInfo &ci=v->_callsstack[lvl]; + if(sq_type(ci._closure)!=OT_CLOSURE) + return NULL; + SQClosure *c=_closure(ci._closure); + SQFunctionProto *func=c->_function; + if(func->_noutervalues > (SQInteger)idx) { + v->Push(*_outer(c->_outervalues[idx])->_valptr); + return _stringval(func->_outervalues[idx]._name); + } + idx -= func->_noutervalues; + return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1); + } + return NULL; } void sq_pushobject(HRABBITVM v,HSQOBJECT obj) { - v->Push(SQObjectPtr(obj)); + v->Push(SQObjectPtr(obj)); } void sq_resetobject(HSQOBJECT *po) { - po->_unVal.pUserPointer=NULL;po->_type=OT_NULL; + po->_unVal.pUserPointer=NULL;po->_type=OT_NULL; } SQRESULT sq_throwerror(HRABBITVM v,const SQChar *err) { - v->_lasterror=SQString::Create(_ss(v),err); - return SQ_ERROR; + v->_lasterror=SQString::Create(_ss(v),err); + return SQ_ERROR; } SQRESULT sq_throwobject(HRABBITVM v) { - v->_lasterror = v->GetUp(-1); - v->Pop(); - return SQ_ERROR; + v->_lasterror = v->GetUp(-1); + v->Pop(); + return SQ_ERROR; } void sq_reseterror(HRABBITVM v) { - v->_lasterror.Null(); + v->_lasterror.Null(); } void sq_getlasterror(HRABBITVM v) { - v->Push(v->_lasterror); + v->Push(v->_lasterror); } SQRESULT sq_reservestack(HRABBITVM v,SQInteger nsize) { - if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { - if(v->_nmetamethodscall) { - return sq_throwerror(v,_SC("cannot resize stack while in a metamethod")); - } - v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); - } - return SQ_OK; + if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { + if(v->_nmetamethodscall) { + return sq_throwerror(v,_SC("cannot resize stack while in a metamethod")); + } + v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); + } + return SQ_OK; } SQRESULT sq_resume(HRABBITVM v,SQBool retval,SQBool raiseerror) { - if (sq_type(v->GetUp(-1)) == OT_GENERATOR) - { - v->PushNull(); //retval - if (!v->Execute(v->GetUp(-2), 0, v->_top, v->GetUp(-1), raiseerror, SQVM::ET_RESUME_GENERATOR)) - {v->Raise_Error(v->_lasterror); return SQ_ERROR;} - if(!retval) - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v,_SC("only generators can be resumed")); + if (sq_type(v->GetUp(-1)) == OT_GENERATOR) + { + v->PushNull(); //retval + if (!v->Execute(v->GetUp(-2), 0, v->_top, v->GetUp(-1), raiseerror, SQVM::ET_RESUME_GENERATOR)) + {v->Raise_Error(v->_lasterror); return SQ_ERROR;} + if(!retval) + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v,_SC("only generators can be resumed")); } SQRESULT sq_call(HRABBITVM v,SQInteger params,SQBool retval,SQBool raiseerror) { - SQObjectPtr res; - if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){ + SQObjectPtr res; + if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){ - if(!v->_suspended) { - v->Pop(params);//pop args - } - if(retval){ - v->Push(res); return SQ_OK; - } - return SQ_OK; - } - else { - v->Pop(params); - return SQ_ERROR; - } - if(!v->_suspended) - v->Pop(params); - return sq_throwerror(v,_SC("call failed")); + if(!v->_suspended) { + v->Pop(params);//pop args + } + if(retval){ + v->Push(res); return SQ_OK; + } + return SQ_OK; + } + else { + v->Pop(params); + return SQ_ERROR; + } + if(!v->_suspended) + v->Pop(params); + return sq_throwerror(v,_SC("call failed")); } SQRESULT sq_tailcall(HRABBITVM v, SQInteger nparams) @@ -1207,417 +1207,417 @@ SQRESULT sq_tailcall(HRABBITVM v, SQInteger nparams) SQRESULT sq_suspendvm(HRABBITVM v) { - return v->Suspend(); + return v->Suspend(); } SQRESULT sq_wakeupvm(HRABBITVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror,SQBool throwerror) { - SQObjectPtr ret; - if(!v->_suspended) - return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); - SQInteger target = v->_suspended_target; - if(wakeupret) { - if(target != -1) { - v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval - } - v->Pop(); - } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); } - SQObjectPtr dummy; - if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) { - return SQ_ERROR; - } - if(retval) - v->Push(ret); - return SQ_OK; + SQObjectPtr ret; + if(!v->_suspended) + return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); + SQInteger target = v->_suspended_target; + if(wakeupret) { + if(target != -1) { + v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + } + v->Pop(); + } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); } + SQObjectPtr dummy; + if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) { + return SQ_ERROR; + } + if(retval) + v->Push(ret); + return SQ_OK; } void sq_setreleasehook(HRABBITVM v,SQInteger idx,SQRELEASEHOOK hook) { - SQObjectPtr &ud=stack_get(v,idx); - switch(sq_type(ud) ) { - case OT_USERDATA: _userdata(ud)->_hook = hook; break; - case OT_INSTANCE: _instance(ud)->_hook = hook; break; - case OT_CLASS: _class(ud)->_hook = hook; break; - default: return; - } + SQObjectPtr &ud=stack_get(v,idx); + switch(sq_type(ud) ) { + case OT_USERDATA: _userdata(ud)->_hook = hook; break; + case OT_INSTANCE: _instance(ud)->_hook = hook; break; + case OT_CLASS: _class(ud)->_hook = hook; break; + default: return; + } } SQRELEASEHOOK sq_getreleasehook(HRABBITVM v,SQInteger idx) { - SQObjectPtr &ud=stack_get(v,idx); - switch(sq_type(ud) ) { - case OT_USERDATA: return _userdata(ud)->_hook; break; - case OT_INSTANCE: return _instance(ud)->_hook; break; - case OT_CLASS: return _class(ud)->_hook; break; - default: return NULL; - } + SQObjectPtr &ud=stack_get(v,idx); + switch(sq_type(ud) ) { + case OT_USERDATA: return _userdata(ud)->_hook; break; + case OT_INSTANCE: return _instance(ud)->_hook; break; + case OT_CLASS: return _class(ud)->_hook; break; + default: return NULL; + } } void sq_setcompilererrorhandler(HRABBITVM v,SQCOMPILERERROR f) { - _ss(v)->_compilererrorhandler = f; + _ss(v)->_compilererrorhandler = f; } SQRESULT sq_writeclosure(HRABBITVM v,SQWRITEFUNC w,SQUserPointer up) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); - unsigned short tag = SQ_BYTECODE_STREAM_TAG; - if(_closure(*o)->_function->_noutervalues) - return sq_throwerror(v,_SC("a closure with free variables bound cannot be serialized")); - if(w(up,&tag,2) != 2) - return sq_throwerror(v,_SC("io error")); - if(!_closure(*o)->Save(v,up,w)) - return SQ_ERROR; - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); + unsigned short tag = SQ_BYTECODE_STREAM_TAG; + if(_closure(*o)->_function->_noutervalues) + return sq_throwerror(v,_SC("a closure with free variables bound cannot be serialized")); + if(w(up,&tag,2) != 2) + return sq_throwerror(v,_SC("io error")); + if(!_closure(*o)->Save(v,up,w)) + return SQ_ERROR; + return SQ_OK; } SQRESULT sq_readclosure(HRABBITVM v,SQREADFUNC r,SQUserPointer up) { - SQObjectPtr closure; + SQObjectPtr closure; - unsigned short tag; - if(r(up,&tag,2) != 2) - return sq_throwerror(v,_SC("io error")); - if(tag != SQ_BYTECODE_STREAM_TAG) - return sq_throwerror(v,_SC("invalid stream")); - if(!SQClosure::Load(v,up,r,closure)) - return SQ_ERROR; - v->Push(closure); - return SQ_OK; + unsigned short tag; + if(r(up,&tag,2) != 2) + return sq_throwerror(v,_SC("io error")); + if(tag != SQ_BYTECODE_STREAM_TAG) + return sq_throwerror(v,_SC("invalid stream")); + if(!SQClosure::Load(v,up,r,closure)) + return SQ_ERROR; + v->Push(closure); + return SQ_OK; } SQChar *sq_getscratchpad(HRABBITVM v,SQInteger minsize) { - return _ss(v)->GetScratchPad(minsize); + return _ss(v)->GetScratchPad(minsize); } SQRESULT sq_resurrectunreachable(HRABBITVM v) { - return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build")); + return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build")); } // TODO: Remove this... SQInteger sq_collectgarbage(HRABBITVM v) { - return -1; + return -1; } SQRESULT sq_getcallee(HRABBITVM v) { - if(v->_callsstacksize > 1) - { - v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); - return SQ_OK; - } - return sq_throwerror(v,_SC("no closure in the calls stack")); + if(v->_callsstacksize > 1) + { + v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); + return SQ_OK; + } + return sq_throwerror(v,_SC("no closure in the calls stack")); } const SQChar *sq_getfreevariable(HRABBITVM v,SQInteger idx,SQUnsignedInteger nval) { - SQObjectPtr &self=stack_get(v,idx); - const SQChar *name = NULL; - switch(sq_type(self)) - { - case OT_CLOSURE:{ - SQClosure *clo = _closure(self); - SQFunctionProto *fp = clo->_function; - if(((SQUnsignedInteger)fp->_noutervalues) > nval) { - v->Push(*(_outer(clo->_outervalues[nval])->_valptr)); - SQOuterVar &ov = fp->_outervalues[nval]; - name = _stringval(ov._name); - } - } - break; - case OT_NATIVECLOSURE:{ - SQNativeClosure *clo = _nativeclosure(self); - if(clo->_noutervalues > nval) { - v->Push(clo->_outervalues[nval]); - name = _SC("@NATIVE"); - } - } - break; - default: break; //shutup compiler - } - return name; + SQObjectPtr &self=stack_get(v,idx); + const SQChar *name = NULL; + switch(sq_type(self)) + { + case OT_CLOSURE:{ + SQClosure *clo = _closure(self); + SQFunctionProto *fp = clo->_function; + if(((SQUnsignedInteger)fp->_noutervalues) > nval) { + v->Push(*(_outer(clo->_outervalues[nval])->_valptr)); + SQOuterVar &ov = fp->_outervalues[nval]; + name = _stringval(ov._name); + } + } + break; + case OT_NATIVECLOSURE:{ + SQNativeClosure *clo = _nativeclosure(self); + if(clo->_noutervalues > nval) { + v->Push(clo->_outervalues[nval]); + name = _SC("@NATIVE"); + } + } + break; + default: break; //shutup compiler + } + return name; } SQRESULT sq_setfreevariable(HRABBITVM v,SQInteger idx,SQUnsignedInteger nval) { - SQObjectPtr &self=stack_get(v,idx); - switch(sq_type(self)) - { - case OT_CLOSURE:{ - SQFunctionProto *fp = _closure(self)->_function; - if(((SQUnsignedInteger)fp->_noutervalues) > nval){ - *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1); - } - else return sq_throwerror(v,_SC("invalid free var index")); - } - break; - case OT_NATIVECLOSURE: - if(_nativeclosure(self)->_noutervalues > nval){ - _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1); - } - else return sq_throwerror(v,_SC("invalid free var index")); - break; - default: - return sq_aux_invalidtype(v, sq_type(self)); - } - v->Pop(); - return SQ_OK; + SQObjectPtr &self=stack_get(v,idx); + switch(sq_type(self)) + { + case OT_CLOSURE:{ + SQFunctionProto *fp = _closure(self)->_function; + if(((SQUnsignedInteger)fp->_noutervalues) > nval){ + *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1); + } + else return sq_throwerror(v,_SC("invalid free var index")); + } + break; + case OT_NATIVECLOSURE: + if(_nativeclosure(self)->_noutervalues > nval){ + _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1); + } + else return sq_throwerror(v,_SC("invalid free var index")); + break; + default: + return sq_aux_invalidtype(v, sq_type(self)); + } + v->Pop(); + return SQ_OK; } SQRESULT sq_setattributes(HRABBITVM v,SQInteger idx) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - SQObjectPtr &key = stack_get(v,-2); - SQObjectPtr &val = stack_get(v,-1); - SQObjectPtr attrs; - if(sq_type(key) == OT_NULL) { - attrs = _class(*o)->_attributes; - _class(*o)->_attributes = val; - v->Pop(2); - v->Push(attrs); - return SQ_OK; - }else if(_class(*o)->GetAttributes(key,attrs)) { - _class(*o)->SetAttributes(key,val); - v->Pop(2); - v->Push(attrs); - return SQ_OK; - } - return sq_throwerror(v,_SC("wrong index")); + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-2); + SQObjectPtr &val = stack_get(v,-1); + SQObjectPtr attrs; + if(sq_type(key) == OT_NULL) { + attrs = _class(*o)->_attributes; + _class(*o)->_attributes = val; + v->Pop(2); + v->Push(attrs); + return SQ_OK; + }else if(_class(*o)->GetAttributes(key,attrs)) { + _class(*o)->SetAttributes(key,val); + v->Pop(2); + v->Push(attrs); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); } SQRESULT sq_getattributes(HRABBITVM v,SQInteger idx) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - SQObjectPtr &key = stack_get(v,-1); - SQObjectPtr attrs; - if(sq_type(key) == OT_NULL) { - attrs = _class(*o)->_attributes; - v->Pop(); - v->Push(attrs); - return SQ_OK; - } - else if(_class(*o)->GetAttributes(key,attrs)) { - v->Pop(); - v->Push(attrs); - return SQ_OK; - } - return sq_throwerror(v,_SC("wrong index")); + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-1); + SQObjectPtr attrs; + if(sq_type(key) == OT_NULL) { + attrs = _class(*o)->_attributes; + v->Pop(); + v->Push(attrs); + return SQ_OK; + } + else if(_class(*o)->GetAttributes(key,attrs)) { + v->Pop(); + v->Push(attrs); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); } SQRESULT sq_getmemberhandle(HRABBITVM v,SQInteger idx,HSQMEMBERHANDLE *handle) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - SQObjectPtr &key = stack_get(v,-1); - SQTable *m = _class(*o)->_members; - SQObjectPtr val; - if(m->Get(key,val)) { - handle->_static = _isfield(val) ? SQFalse : SQTrue; - handle->_index = _member_idx(val); - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v,_SC("wrong index")); + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-1); + SQTable *m = _class(*o)->_members; + SQObjectPtr val; + if(m->Get(key,val)) { + handle->_static = _isfield(val) ? SQFalse : SQTrue; + handle->_index = _member_idx(val); + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); } SQRESULT _getmemberbyhandle(HRABBITVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val) { - switch(sq_type(self)) { - case OT_INSTANCE: { - SQInstance *i = _instance(self); - if(handle->_static) { - SQClass *c = i->_class; - val = &c->_methods[handle->_index].val; - } - else { - val = &i->_values[handle->_index]; + switch(sq_type(self)) { + case OT_INSTANCE: { + SQInstance *i = _instance(self); + if(handle->_static) { + SQClass *c = i->_class; + val = &c->_methods[handle->_index].val; + } + else { + val = &i->_values[handle->_index]; - } - } - break; - case OT_CLASS: { - SQClass *c = _class(self); - if(handle->_static) { - val = &c->_methods[handle->_index].val; - } - else { - val = &c->_defaultvalues[handle->_index].val; - } - } - break; - default: - return sq_throwerror(v,_SC("wrong type(expected class or instance)")); - } - return SQ_OK; + } + } + break; + case OT_CLASS: { + SQClass *c = _class(self); + if(handle->_static) { + val = &c->_methods[handle->_index].val; + } + else { + val = &c->_defaultvalues[handle->_index].val; + } + } + break; + default: + return sq_throwerror(v,_SC("wrong type(expected class or instance)")); + } + return SQ_OK; } SQRESULT sq_getbyhandle(HRABBITVM v,SQInteger idx,const HSQMEMBERHANDLE *handle) { - SQObjectPtr &self = stack_get(v,idx); - SQObjectPtr *val = NULL; - if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { - return SQ_ERROR; - } - v->Push(_realval(*val)); - return SQ_OK; + SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr *val = NULL; + if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { + return SQ_ERROR; + } + v->Push(_realval(*val)); + return SQ_OK; } SQRESULT sq_setbyhandle(HRABBITVM v,SQInteger idx,const HSQMEMBERHANDLE *handle) { - SQObjectPtr &self = stack_get(v,idx); - SQObjectPtr &newval = stack_get(v,-1); - SQObjectPtr *val = NULL; - if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { - return SQ_ERROR; - } - *val = newval; - v->Pop(); - return SQ_OK; + SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr &newval = stack_get(v,-1); + SQObjectPtr *val = NULL; + if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { + return SQ_ERROR; + } + *val = newval; + v->Pop(); + return SQ_OK; } SQRESULT sq_getbase(HRABBITVM v,SQInteger idx) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - if(_class(*o)->_base) - v->Push(SQObjectPtr(_class(*o)->_base)); - else - v->PushNull(); - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + if(_class(*o)->_base) + v->Push(SQObjectPtr(_class(*o)->_base)); + else + v->PushNull(); + return SQ_OK; } SQRESULT sq_getclass(HRABBITVM v,SQInteger idx) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_INSTANCE,o); - v->Push(SQObjectPtr(_instance(*o)->_class)); - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_INSTANCE,o); + v->Push(SQObjectPtr(_instance(*o)->_class)); + return SQ_OK; } SQRESULT sq_createinstance(HRABBITVM v,SQInteger idx) { - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - v->Push(_class(*o)->CreateInstance()); - return SQ_OK; + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + v->Push(_class(*o)->CreateInstance()); + return SQ_OK; } void sq_weakref(HRABBITVM v,SQInteger idx) { - SQObject &o=stack_get(v,idx); - if(ISREFCOUNTED(sq_type(o))) { - v->Push(_refcounted(o)->GetWeakRef(sq_type(o))); - return; - } - v->Push(o); + SQObject &o=stack_get(v,idx); + if(ISREFCOUNTED(sq_type(o))) { + v->Push(_refcounted(o)->GetWeakRef(sq_type(o))); + return; + } + v->Push(o); } SQRESULT sq_getweakrefval(HRABBITVM v,SQInteger idx) { - SQObjectPtr &o = stack_get(v,idx); - if(sq_type(o) != OT_WEAKREF) { - return sq_throwerror(v,_SC("the object must be a weakref")); - } - v->Push(_weakref(o)->_obj); - return SQ_OK; + SQObjectPtr &o = stack_get(v,idx); + if(sq_type(o) != OT_WEAKREF) { + return sq_throwerror(v,_SC("the object must be a weakref")); + } + v->Push(_weakref(o)->_obj); + return SQ_OK; } SQRESULT sq_getdefaultdelegate(HRABBITVM v,SQObjectType t) { - SQSharedState *ss = _ss(v); - switch(t) { - case OT_TABLE: v->Push(ss->_table_default_delegate); break; - case OT_ARRAY: v->Push(ss->_array_default_delegate); break; - case OT_STRING: v->Push(ss->_string_default_delegate); break; - case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break; - case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break; - case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break; - case OT_THREAD: v->Push(ss->_thread_default_delegate); break; - case OT_CLASS: v->Push(ss->_class_default_delegate); break; - case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break; - case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break; - default: return sq_throwerror(v,_SC("the type doesn't have a default delegate")); - } - return SQ_OK; + SQSharedState *ss = _ss(v); + switch(t) { + case OT_TABLE: v->Push(ss->_table_default_delegate); break; + case OT_ARRAY: v->Push(ss->_array_default_delegate); break; + case OT_STRING: v->Push(ss->_string_default_delegate); break; + case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break; + case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break; + case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break; + case OT_THREAD: v->Push(ss->_thread_default_delegate); break; + case OT_CLASS: v->Push(ss->_class_default_delegate); break; + case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break; + case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break; + default: return sq_throwerror(v,_SC("the type doesn't have a default delegate")); + } + return SQ_OK; } SQRESULT sq_next(HRABBITVM v,SQInteger idx) { - SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val; - if(sq_type(o) == OT_GENERATOR) { - return sq_throwerror(v,_SC("cannot iterate a generator")); - } - int faketojump; - if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump)) - return SQ_ERROR; - if(faketojump != 666) { - v->Push(realkey); - v->Push(val); - return SQ_OK; - } - return SQ_ERROR; + SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val; + if(sq_type(o) == OT_GENERATOR) { + return sq_throwerror(v,_SC("cannot iterate a generator")); + } + int faketojump; + if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump)) + return SQ_ERROR; + if(faketojump != 666) { + v->Push(realkey); + v->Push(val); + return SQ_OK; + } + return SQ_ERROR; } struct BufState{ - const SQChar *buf; - SQInteger ptr; - SQInteger size; + const SQChar *buf; + SQInteger ptr; + SQInteger size; }; SQInteger buf_lexfeed(SQUserPointer file) { - BufState *buf=(BufState*)file; - if(buf->size<(buf->ptr+1)) - return 0; - return buf->buf[buf->ptr++]; + BufState *buf=(BufState*)file; + if(buf->size<(buf->ptr+1)) + return 0; + return buf->buf[buf->ptr++]; } SQRESULT sq_compilebuffer(HRABBITVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) { - BufState buf; - buf.buf = s; - buf.size = size; - buf.ptr = 0; - return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror); + BufState buf; + buf.buf = s; + buf.size = size; + buf.ptr = 0; + return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror); } void sq_move(HRABBITVM dest,HRABBITVM src,SQInteger idx) { - dest->Push(stack_get(src,idx)); + dest->Push(stack_get(src,idx)); } void sq_setprintfunc(HRABBITVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc) { - _ss(v)->_printfunc = printfunc; - _ss(v)->_errorfunc = errfunc; + _ss(v)->_printfunc = printfunc; + _ss(v)->_errorfunc = errfunc; } SQPRINTFUNCTION sq_getprintfunc(HRABBITVM v) { - return _ss(v)->_printfunc; + return _ss(v)->_printfunc; } SQPRINTFUNCTION sq_geterrorfunc(HRABBITVM v) { - return _ss(v)->_errorfunc; + return _ss(v)->_errorfunc; } void *sq_malloc(SQUnsignedInteger size) { - return SQ_MALLOC(size); + return SQ_MALLOC(size); } void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize) { - return SQ_REALLOC(p,oldsize,newsize); + return SQ_REALLOC(p,oldsize,newsize); } void sq_free(void *p,SQUnsignedInteger size) { - SQ_FREE(p,size); + SQ_FREE(p,size); } diff --git a/rabbit/sqarray.hpp b/rabbit/sqarray.hpp index e4d0e11..99f6bc2 100644 --- a/rabbit/sqarray.hpp +++ b/rabbit/sqarray.hpp @@ -10,87 +10,87 @@ struct SQArray : public CHAINABLE_OBJ { private: - SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} - ~SQArray() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } + SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + ~SQArray() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } public: - static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){ - SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray)); - new (newarray) SQArray(ss,nInitialSize); - return newarray; - } - void Finalize(){ - _values.resize(0); - } - bool Get(const SQInteger nidx,SQObjectPtr &val) - { - if(nidx>=0 && nidx<(SQInteger)_values.size()){ - SQObjectPtr &o = _values[nidx]; - val = _realval(o); - return true; - } - else return false; - } - bool Set(const SQInteger nidx,const SQObjectPtr &val) - { - if(nidx>=0 && nidx<(SQInteger)_values.size()){ - _values[nidx]=val; - return true; - } - else return false; - } - SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval) - { - SQUnsignedInteger idx=TranslateIndex(refpos); - while(idx<_values.size()){ - //first found - outkey=(SQInteger)idx; - SQObjectPtr &o = _values[idx]; - outval = _realval(o); - //return idx for the next iteration - return ++idx; - } - //nothing to iterate anymore - return -1; - } - SQArray *Clone(){SQArray *anew=Create(NULL,0); anew->_values.copy(_values); return anew; } - SQInteger Size() const {return _values.size();} - void Resize(SQInteger size) - { - SQObjectPtr _null; - Resize(size,_null); - } - void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); } - void Reserve(SQInteger size) { _values.reserve(size); } - void Append(const SQObject &o){_values.push_back(o);} - void Extend(const SQArray *a); - SQObjectPtr &Top(){return _values.top();} - void Pop(){_values.pop_back(); ShrinkIfNeeded(); } - bool Insert(SQInteger idx,const SQObject &val){ - if(idx < 0 || idx > (SQInteger)_values.size()) - return false; - _values.insert(idx,val); - return true; - } - void ShrinkIfNeeded() { - if(_values.size() <= _values.capacity()>>2) //shrink the array - _values.shrinktofit(); - } - bool Remove(SQInteger idx){ - if(idx < 0 || idx >= (SQInteger)_values.size()) - return false; - _values.remove(idx); - ShrinkIfNeeded(); - return true; - } - void Release() - { - sq_delete(this,SQArray); - } + static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){ + SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray)); + new (newarray) SQArray(ss,nInitialSize); + return newarray; + } + void Finalize(){ + _values.resize(0); + } + bool Get(const SQInteger nidx,SQObjectPtr &val) + { + if(nidx>=0 && nidx<(SQInteger)_values.size()){ + SQObjectPtr &o = _values[nidx]; + val = _realval(o); + return true; + } + else return false; + } + bool Set(const SQInteger nidx,const SQObjectPtr &val) + { + if(nidx>=0 && nidx<(SQInteger)_values.size()){ + _values[nidx]=val; + return true; + } + else return false; + } + SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval) + { + SQUnsignedInteger idx=TranslateIndex(refpos); + while(idx<_values.size()){ + //first found + outkey=(SQInteger)idx; + SQObjectPtr &o = _values[idx]; + outval = _realval(o); + //return idx for the next iteration + return ++idx; + } + //nothing to iterate anymore + return -1; + } + SQArray *Clone(){SQArray *anew=Create(NULL,0); anew->_values.copy(_values); return anew; } + SQInteger Size() const {return _values.size();} + void Resize(SQInteger size) + { + SQObjectPtr _null; + Resize(size,_null); + } + void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); } + void Reserve(SQInteger size) { _values.reserve(size); } + void Append(const SQObject &o){_values.push_back(o);} + void Extend(const SQArray *a); + SQObjectPtr &Top(){return _values.top();} + void Pop(){_values.pop_back(); ShrinkIfNeeded(); } + bool Insert(SQInteger idx,const SQObject &val){ + if(idx < 0 || idx > (SQInteger)_values.size()) + return false; + _values.insert(idx,val); + return true; + } + void ShrinkIfNeeded() { + if(_values.size() <= _values.capacity()>>2) //shrink the array + _values.shrinktofit(); + } + bool Remove(SQInteger idx){ + if(idx < 0 || idx >= (SQInteger)_values.size()) + return false; + _values.remove(idx); + ShrinkIfNeeded(); + return true; + } + void Release() + { + sq_delete(this,SQArray); + } - SQObjectPtrVec _values; + SQObjectPtrVec _values; }; diff --git a/rabbit/sqbaselib.cpp b/rabbit/sqbaselib.cpp index ad9feef..955233f 100644 --- a/rabbit/sqbaselib.cpp +++ b/rabbit/sqbaselib.cpp @@ -19,397 +19,397 @@ static bool str2num(const SQChar *s,SQObjectPtr &res,SQInteger base) { - SQChar *end; - const SQChar *e = s; - bool iseintbase = base > 13; //to fix error converting hexadecimals with e like 56f0791e - bool isfloat = false; - SQChar c; - while((c = *e) != _SC('\0')) - { - if (c == _SC('.') || (!iseintbase && (c == _SC('E') || c == _SC('e')))) { //e and E is for scientific notation - isfloat = true; - break; - } - e++; - } - if(isfloat){ - SQFloat r = SQFloat(scstrtod(s,&end)); - if(s == end) return false; - res = r; - } - else{ - SQInteger r = SQInteger(scstrtol(s,&end,(int)base)); - if(s == end) return false; - res = r; - } - return true; + SQChar *end; + const SQChar *e = s; + bool iseintbase = base > 13; //to fix error converting hexadecimals with e like 56f0791e + bool isfloat = false; + SQChar c; + while((c = *e) != _SC('\0')) + { + if (c == _SC('.') || (!iseintbase && (c == _SC('E') || c == _SC('e')))) { //e and E is for scientific notation + isfloat = true; + break; + } + e++; + } + if(isfloat){ + SQFloat r = SQFloat(scstrtod(s,&end)); + if(s == end) return false; + res = r; + } + else{ + SQInteger r = SQInteger(scstrtol(s,&end,(int)base)); + if(s == end) return false; + res = r; + } + return true; } static SQInteger base_dummy(HRABBITVM SQ_UNUSED_ARG(v)) { - return 0; + return 0; } static SQInteger base_getroottable(HRABBITVM v) { - v->Push(v->_roottable); - return 1; + v->Push(v->_roottable); + return 1; } static SQInteger base_getconsttable(HRABBITVM v) { - v->Push(_ss(v)->_consts); - return 1; + v->Push(_ss(v)->_consts); + return 1; } static SQInteger base_setroottable(HRABBITVM v) { - SQObjectPtr o = v->_roottable; - if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; - v->Push(o); - return 1; + SQObjectPtr o = v->_roottable; + if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; + v->Push(o); + return 1; } static SQInteger base_setconsttable(HRABBITVM v) { - SQObjectPtr o = _ss(v)->_consts; - if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR; - v->Push(o); - return 1; + SQObjectPtr o = _ss(v)->_consts; + if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR; + v->Push(o); + return 1; } static SQInteger base_seterrorhandler(HRABBITVM v) { - sq_seterrorhandler(v); - return 0; + sq_seterrorhandler(v); + return 0; } static SQInteger base_setdebughook(HRABBITVM v) { - sq_setdebughook(v); - return 0; + sq_setdebughook(v); + return 0; } static SQInteger base_enabledebuginfo(HRABBITVM v) { - SQObjectPtr &o=stack_get(v,2); + SQObjectPtr &o=stack_get(v,2); - sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue); - return 0; + sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue); + return 0; } static SQInteger __getcallstackinfos(HRABBITVM v,SQInteger level) { - SQStackInfos si; - SQInteger seq = 0; - const SQChar *name = NULL; + SQStackInfos si; + SQInteger seq = 0; + const SQChar *name = NULL; - if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) - { - const SQChar *fn = _SC("unknown"); - const SQChar *src = _SC("unknown"); - if(si.funcname)fn = si.funcname; - if(si.source)src = si.source; - sq_newtable(v); - sq_pushstring(v, _SC("func"), -1); - sq_pushstring(v, fn, -1); - sq_newslot(v, -3, SQFalse); - sq_pushstring(v, _SC("src"), -1); - sq_pushstring(v, src, -1); - sq_newslot(v, -3, SQFalse); - sq_pushstring(v, _SC("line"), -1); - sq_pushinteger(v, si.line); - sq_newslot(v, -3, SQFalse); - sq_pushstring(v, _SC("locals"), -1); - sq_newtable(v); - seq=0; - while ((name = sq_getlocal(v, level, seq))) { - sq_pushstring(v, name, -1); - sq_push(v, -2); - sq_newslot(v, -4, SQFalse); - sq_pop(v, 1); - seq++; - } - sq_newslot(v, -3, SQFalse); - return 1; - } + if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) + { + const SQChar *fn = _SC("unknown"); + const SQChar *src = _SC("unknown"); + if(si.funcname)fn = si.funcname; + if(si.source)src = si.source; + sq_newtable(v); + sq_pushstring(v, _SC("func"), -1); + sq_pushstring(v, fn, -1); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("src"), -1); + sq_pushstring(v, src, -1); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("line"), -1); + sq_pushinteger(v, si.line); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("locals"), -1); + sq_newtable(v); + seq=0; + while ((name = sq_getlocal(v, level, seq))) { + sq_pushstring(v, name, -1); + sq_push(v, -2); + sq_newslot(v, -4, SQFalse); + sq_pop(v, 1); + seq++; + } + sq_newslot(v, -3, SQFalse); + return 1; + } - return 0; + return 0; } static SQInteger base_getstackinfos(HRABBITVM v) { - SQInteger level; - sq_getinteger(v, -1, &level); - return __getcallstackinfos(v,level); + SQInteger level; + sq_getinteger(v, -1, &level); + return __getcallstackinfos(v,level); } static SQInteger base_assert(HRABBITVM v) { - if(SQVM::IsFalse(stack_get(v,2))){ - SQInteger top = sq_gettop(v); - if (top>2 && SQ_SUCCEEDED(sq_tostring(v,3))) { - const SQChar *str = 0; - if (SQ_SUCCEEDED(sq_getstring(v,-1,&str))) { - return sq_throwerror(v, str); - } - } - return sq_throwerror(v, _SC("assertion failed")); - } - return 0; + if(SQVM::IsFalse(stack_get(v,2))){ + SQInteger top = sq_gettop(v); + if (top>2 && SQ_SUCCEEDED(sq_tostring(v,3))) { + const SQChar *str = 0; + if (SQ_SUCCEEDED(sq_getstring(v,-1,&str))) { + return sq_throwerror(v, str); + } + } + return sq_throwerror(v, _SC("assertion failed")); + } + return 0; } static SQInteger get_slice_params(HRABBITVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o) { - SQInteger top = sq_gettop(v); - sidx=0; - eidx=0; - o=stack_get(v,1); - if(top>1){ - SQObjectPtr &start=stack_get(v,2); - if(sq_type(start)!=OT_NULL && sq_isnumeric(start)){ - sidx=tointeger(start); - } - } - if(top>2){ - SQObjectPtr &end=stack_get(v,3); - if(sq_isnumeric(end)){ - eidx=tointeger(end); - } - } - else { - eidx = sq_getsize(v,1); - } - return 1; + SQInteger top = sq_gettop(v); + sidx=0; + eidx=0; + o=stack_get(v,1); + if(top>1){ + SQObjectPtr &start=stack_get(v,2); + if(sq_type(start)!=OT_NULL && sq_isnumeric(start)){ + sidx=tointeger(start); + } + } + if(top>2){ + SQObjectPtr &end=stack_get(v,3); + if(sq_isnumeric(end)){ + eidx=tointeger(end); + } + } + else { + eidx = sq_getsize(v,1); + } + return 1; } static SQInteger base_print(HRABBITVM v) { - const SQChar *str; - if(SQ_SUCCEEDED(sq_tostring(v,2))) - { - if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) { - if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str); - return 0; - } - } - return SQ_ERROR; + const SQChar *str; + if(SQ_SUCCEEDED(sq_tostring(v,2))) + { + if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) { + if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str); + return 0; + } + } + return SQ_ERROR; } static SQInteger base_error(HRABBITVM v) { - const SQChar *str; - if(SQ_SUCCEEDED(sq_tostring(v,2))) - { - if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) { - if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str); - return 0; - } - } - return SQ_ERROR; + const SQChar *str; + if(SQ_SUCCEEDED(sq_tostring(v,2))) + { + if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) { + if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str); + return 0; + } + } + return SQ_ERROR; } static SQInteger base_compilestring(HRABBITVM v) { - SQInteger nargs=sq_gettop(v); - const SQChar *src=NULL,*name=_SC("unnamedbuffer"); - SQInteger size; - sq_getstring(v,2,&src); - size=sq_getsize(v,2); - if(nargs>2){ - sq_getstring(v,3,&name); - } - if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse))) - return 1; - else - return SQ_ERROR; + SQInteger nargs=sq_gettop(v); + const SQChar *src=NULL,*name=_SC("unnamedbuffer"); + SQInteger size; + sq_getstring(v,2,&src); + size=sq_getsize(v,2); + if(nargs>2){ + sq_getstring(v,3,&name); + } + if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse))) + return 1; + else + return SQ_ERROR; } static SQInteger base_newthread(HRABBITVM v) { - SQObjectPtr &func = stack_get(v,2); - SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2; - HRABBITVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); - sq_move(newv,v,-2); - return 1; + SQObjectPtr &func = stack_get(v,2); + SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2; + HRABBITVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); + sq_move(newv,v,-2); + return 1; } static SQInteger base_suspend(HRABBITVM v) { - return sq_suspendvm(v); + return sq_suspendvm(v); } static SQInteger base_array(HRABBITVM v) { - SQArray *a; - SQObject &size = stack_get(v,2); - if(sq_gettop(v) > 2) { - a = SQArray::Create(_ss(v),0); - a->Resize(tointeger(size),stack_get(v,3)); - } - else { - a = SQArray::Create(_ss(v),tointeger(size)); - } - v->Push(a); - return 1; + SQArray *a; + SQObject &size = stack_get(v,2); + if(sq_gettop(v) > 2) { + a = SQArray::Create(_ss(v),0); + a->Resize(tointeger(size),stack_get(v,3)); + } + else { + a = SQArray::Create(_ss(v),tointeger(size)); + } + v->Push(a); + return 1; } static SQInteger base_type(HRABBITVM v) { - SQObjectPtr &o = stack_get(v,2); - v->Push(SQString::Create(_ss(v),GetTypeName(o),-1)); - return 1; + SQObjectPtr &o = stack_get(v,2); + v->Push(SQString::Create(_ss(v),GetTypeName(o),-1)); + return 1; } static SQInteger base_callee(HRABBITVM v) { - if(v->_callsstacksize > 1) - { - v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); - return 1; - } - return sq_throwerror(v,_SC("no closure in the calls stack")); + if(v->_callsstacksize > 1) + { + v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); + return 1; + } + return sq_throwerror(v,_SC("no closure in the calls stack")); } static const SQRegFunction base_funcs[]={ - //generic - {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, - {_SC("setdebughook"),base_setdebughook,2, NULL}, - {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL}, - {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")}, - {_SC("getroottable"),base_getroottable,1, NULL}, - {_SC("setroottable"),base_setroottable,2, NULL}, - {_SC("getconsttable"),base_getconsttable,1, NULL}, - {_SC("setconsttable"),base_setconsttable,2, NULL}, - {_SC("assert"),base_assert,-2, NULL}, - {_SC("print"),base_print,2, NULL}, - {_SC("error"),base_error,2, NULL}, - {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, - {_SC("newthread"),base_newthread,2, _SC(".c")}, - {_SC("suspend"),base_suspend,-1, NULL}, - {_SC("array"),base_array,-2, _SC(".n")}, - {_SC("type"),base_type,2, NULL}, - {_SC("callee"),base_callee,0,NULL}, - {_SC("dummy"),base_dummy,0,NULL}, - {NULL,(SQFUNCTION)0,0,NULL} + //generic + {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, + {_SC("setdebughook"),base_setdebughook,2, NULL}, + {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL}, + {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")}, + {_SC("getroottable"),base_getroottable,1, NULL}, + {_SC("setroottable"),base_setroottable,2, NULL}, + {_SC("getconsttable"),base_getconsttable,1, NULL}, + {_SC("setconsttable"),base_setconsttable,2, NULL}, + {_SC("assert"),base_assert,-2, NULL}, + {_SC("print"),base_print,2, NULL}, + {_SC("error"),base_error,2, NULL}, + {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, + {_SC("newthread"),base_newthread,2, _SC(".c")}, + {_SC("suspend"),base_suspend,-1, NULL}, + {_SC("array"),base_array,-2, _SC(".n")}, + {_SC("type"),base_type,2, NULL}, + {_SC("callee"),base_callee,0,NULL}, + {_SC("dummy"),base_dummy,0,NULL}, + {NULL,(SQFUNCTION)0,0,NULL} }; void sq_base_register(HRABBITVM v) { - SQInteger i=0; - sq_pushroottable(v); - while(base_funcs[i].name!=0) { - sq_pushstring(v,base_funcs[i].name,-1); - sq_newclosure(v,base_funcs[i].f,0); - sq_setnativeclosurename(v,-1,base_funcs[i].name); - sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); - sq_newslot(v,-3, SQFalse); - i++; - } + SQInteger i=0; + sq_pushroottable(v); + while(base_funcs[i].name!=0) { + sq_pushstring(v,base_funcs[i].name,-1); + sq_newclosure(v,base_funcs[i].f,0); + sq_setnativeclosurename(v,-1,base_funcs[i].name); + sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); + sq_newslot(v,-3, SQFalse); + i++; + } - sq_pushstring(v,_SC("_versionnumber_"),-1); - sq_pushinteger(v,RABBIT_VERSION_NUMBER); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("_version_"),-1); - sq_pushstring(v,RABBIT_VERSION,-1); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("_charsize_"),-1); - sq_pushinteger(v,sizeof(SQChar)); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("_intsize_"),-1); - sq_pushinteger(v,sizeof(SQInteger)); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("_floatsize_"),-1); - sq_pushinteger(v,sizeof(SQFloat)); - sq_newslot(v,-3, SQFalse); - sq_pop(v,1); + sq_pushstring(v,_SC("_versionnumber_"),-1); + sq_pushinteger(v,RABBIT_VERSION_NUMBER); + sq_newslot(v,-3, SQFalse); + sq_pushstring(v,_SC("_version_"),-1); + sq_pushstring(v,RABBIT_VERSION,-1); + sq_newslot(v,-3, SQFalse); + sq_pushstring(v,_SC("_charsize_"),-1); + sq_pushinteger(v,sizeof(SQChar)); + sq_newslot(v,-3, SQFalse); + sq_pushstring(v,_SC("_intsize_"),-1); + sq_pushinteger(v,sizeof(SQInteger)); + sq_newslot(v,-3, SQFalse); + sq_pushstring(v,_SC("_floatsize_"),-1); + sq_pushinteger(v,sizeof(SQFloat)); + sq_newslot(v,-3, SQFalse); + sq_pop(v,1); } static SQInteger default_delegate_len(HRABBITVM v) { - v->Push(SQInteger(sq_getsize(v,1))); - return 1; + v->Push(SQInteger(sq_getsize(v,1))); + return 1; } static SQInteger default_delegate_tofloat(HRABBITVM v) { - SQObjectPtr &o=stack_get(v,1); - switch(sq_type(o)){ - case OT_STRING:{ - SQObjectPtr res; - if(str2num(_stringval(o),res,10)){ - v->Push(SQObjectPtr(tofloat(res))); - break; - }} - return sq_throwerror(v, _SC("cannot convert the string")); - break; - case OT_INTEGER:case OT_FLOAT: - v->Push(SQObjectPtr(tofloat(o))); - break; - case OT_BOOL: - v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); - break; - default: - v->PushNull(); - break; - } - return 1; + SQObjectPtr &o=stack_get(v,1); + switch(sq_type(o)){ + case OT_STRING:{ + SQObjectPtr res; + if(str2num(_stringval(o),res,10)){ + v->Push(SQObjectPtr(tofloat(res))); + break; + }} + return sq_throwerror(v, _SC("cannot convert the string")); + break; + case OT_INTEGER:case OT_FLOAT: + v->Push(SQObjectPtr(tofloat(o))); + break; + case OT_BOOL: + v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); + break; + default: + v->PushNull(); + break; + } + return 1; } static SQInteger default_delegate_tointeger(HRABBITVM v) { - SQObjectPtr &o=stack_get(v,1); - SQInteger base = 10; - if(sq_gettop(v) > 1) { - sq_getinteger(v,2,&base); - } - switch(sq_type(o)){ - case OT_STRING:{ - SQObjectPtr res; - if(str2num(_stringval(o),res,base)){ - v->Push(SQObjectPtr(tointeger(res))); - break; - }} - return sq_throwerror(v, _SC("cannot convert the string")); - break; - case OT_INTEGER:case OT_FLOAT: - v->Push(SQObjectPtr(tointeger(o))); - break; - case OT_BOOL: - v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); - break; - default: - v->PushNull(); - break; - } - return 1; + SQObjectPtr &o=stack_get(v,1); + SQInteger base = 10; + if(sq_gettop(v) > 1) { + sq_getinteger(v,2,&base); + } + switch(sq_type(o)){ + case OT_STRING:{ + SQObjectPtr res; + if(str2num(_stringval(o),res,base)){ + v->Push(SQObjectPtr(tointeger(res))); + break; + }} + return sq_throwerror(v, _SC("cannot convert the string")); + break; + case OT_INTEGER:case OT_FLOAT: + v->Push(SQObjectPtr(tointeger(o))); + break; + case OT_BOOL: + v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); + break; + default: + v->PushNull(); + break; + } + return 1; } static SQInteger default_delegate_tostring(HRABBITVM v) { - if(SQ_FAILED(sq_tostring(v,1))) - return SQ_ERROR; - return 1; + if(SQ_FAILED(sq_tostring(v,1))) + return SQ_ERROR; + return 1; } static SQInteger obj_delegate_weakref(HRABBITVM v) { - sq_weakref(v,1); - return 1; + sq_weakref(v,1); + return 1; } static SQInteger obj_clear(HRABBITVM v) { - return SQ_SUCCEEDED(sq_clear(v,-1)) ? 1 : SQ_ERROR; + return SQ_SUCCEEDED(sq_clear(v,-1)) ? 1 : SQ_ERROR; } static SQInteger number_delegate_tochar(HRABBITVM v) { - SQObject &o=stack_get(v,1); - SQChar c = (SQChar)tointeger(o); - v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1)); - return 1; + SQObject &o=stack_get(v,1); + SQChar c = (SQChar)tointeger(o); + v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1)); + return 1; } @@ -419,467 +419,467 @@ static SQInteger number_delegate_tochar(HRABBITVM v) static SQInteger table_rawdelete(HRABBITVM v) { - if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue))) - return SQ_ERROR; - return 1; + if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue))) + return SQ_ERROR; + return 1; } static SQInteger container_rawexists(HRABBITVM v) { - if(SQ_SUCCEEDED(sq_rawget(v,-2))) { - sq_pushbool(v,SQTrue); - return 1; - } - sq_pushbool(v,SQFalse); - return 1; + if(SQ_SUCCEEDED(sq_rawget(v,-2))) { + sq_pushbool(v,SQTrue); + return 1; + } + sq_pushbool(v,SQFalse); + return 1; } static SQInteger container_rawset(HRABBITVM v) { - return SQ_SUCCEEDED(sq_rawset(v,-3)) ? 1 : SQ_ERROR; + return SQ_SUCCEEDED(sq_rawset(v,-3)) ? 1 : SQ_ERROR; } static SQInteger container_rawget(HRABBITVM v) { - return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; } static SQInteger table_setdelegate(HRABBITVM v) { - if(SQ_FAILED(sq_setdelegate(v,-2))) - return SQ_ERROR; - sq_push(v,-1); // -1 because sq_setdelegate pops 1 - return 1; + if(SQ_FAILED(sq_setdelegate(v,-2))) + return SQ_ERROR; + sq_push(v,-1); // -1 because sq_setdelegate pops 1 + return 1; } static SQInteger table_getdelegate(HRABBITVM v) { - return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR; } static SQInteger table_filter(HRABBITVM v) { - SQObject &o = stack_get(v,1); - SQTable *tbl = _table(o); - SQObjectPtr ret = SQTable::Create(_ss(v),0); + SQObject &o = stack_get(v,1); + SQTable *tbl = _table(o); + SQObjectPtr ret = SQTable::Create(_ss(v),0); - SQObjectPtr itr, key, val; - SQInteger nitr; - while((nitr = tbl->Next(false, itr, key, val)) != -1) { - itr = (SQInteger)nitr; + SQObjectPtr itr, key, val; + SQInteger nitr; + while((nitr = tbl->Next(false, itr, key, val)) != -1) { + itr = (SQInteger)nitr; - v->Push(o); - v->Push(key); - v->Push(val); - if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { - return SQ_ERROR; - } - if(!SQVM::IsFalse(v->GetUp(-1))) { - _table(ret)->NewSlot(key, val); - } - v->Pop(); - } + v->Push(o); + v->Push(key); + v->Push(val); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + if(!SQVM::IsFalse(v->GetUp(-1))) { + _table(ret)->NewSlot(key, val); + } + v->Pop(); + } - v->Push(ret); - return 1; + v->Push(ret); + return 1; } const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ - {_SC("len"),default_delegate_len,1, _SC("t")}, - {_SC("rawget"),container_rawget,2, _SC("t")}, - {_SC("rawset"),container_rawset,3, _SC("t")}, - {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, - {_SC("rawin"),container_rawexists,2, _SC("t")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("clear"),obj_clear,1, _SC(".")}, - {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")}, - {_SC("getdelegate"),table_getdelegate,1, _SC(".")}, - {_SC("filter"),table_filter,2, _SC("tc")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("len"),default_delegate_len,1, _SC("t")}, + {_SC("rawget"),container_rawget,2, _SC("t")}, + {_SC("rawset"),container_rawset,3, _SC("t")}, + {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, + {_SC("rawin"),container_rawexists,2, _SC("t")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("clear"),obj_clear,1, _SC(".")}, + {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")}, + {_SC("getdelegate"),table_getdelegate,1, _SC(".")}, + {_SC("filter"),table_filter,2, _SC("tc")}, + {NULL,(SQFUNCTION)0,0,NULL} }; //ARRAY DEFAULT DELEGATE/////////////////////////////////////// static SQInteger array_append(HRABBITVM v) { - return SQ_SUCCEEDED(sq_arrayappend(v,-2)) ? 1 : SQ_ERROR; + return SQ_SUCCEEDED(sq_arrayappend(v,-2)) ? 1 : SQ_ERROR; } static SQInteger array_extend(HRABBITVM v) { - _array(stack_get(v,1))->Extend(_array(stack_get(v,2))); - sq_pop(v,1); - return 1; + _array(stack_get(v,1))->Extend(_array(stack_get(v,2))); + sq_pop(v,1); + return 1; } static SQInteger array_reverse(HRABBITVM v) { - return SQ_SUCCEEDED(sq_arrayreverse(v,-1)) ? 1 : SQ_ERROR; + return SQ_SUCCEEDED(sq_arrayreverse(v,-1)) ? 1 : SQ_ERROR; } static SQInteger array_pop(HRABBITVM v) { - return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR; } static SQInteger array_top(HRABBITVM v) { - SQObject &o=stack_get(v,1); - if(_array(o)->Size()>0){ - v->Push(_array(o)->Top()); - return 1; - } - else return sq_throwerror(v,_SC("top() on a empty array")); + SQObject &o=stack_get(v,1); + if(_array(o)->Size()>0){ + v->Push(_array(o)->Top()); + return 1; + } + else return sq_throwerror(v,_SC("top() on a empty array")); } static SQInteger array_insert(HRABBITVM v) { - SQObject &o=stack_get(v,1); - SQObject &idx=stack_get(v,2); - SQObject &val=stack_get(v,3); - if(!_array(o)->Insert(tointeger(idx),val)) - return sq_throwerror(v,_SC("index out of range")); - sq_pop(v,2); - return 1; + SQObject &o=stack_get(v,1); + SQObject &idx=stack_get(v,2); + SQObject &val=stack_get(v,3); + if(!_array(o)->Insert(tointeger(idx),val)) + return sq_throwerror(v,_SC("index out of range")); + sq_pop(v,2); + return 1; } static SQInteger array_remove(HRABBITVM v) { - SQObject &o = stack_get(v, 1); - SQObject &idx = stack_get(v, 2); - if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type")); - SQObjectPtr val; - if(_array(o)->Get(tointeger(idx), val)) { - _array(o)->Remove(tointeger(idx)); - v->Push(val); - return 1; - } - return sq_throwerror(v, _SC("idx out of range")); + SQObject &o = stack_get(v, 1); + SQObject &idx = stack_get(v, 2); + if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type")); + SQObjectPtr val; + if(_array(o)->Get(tointeger(idx), val)) { + _array(o)->Remove(tointeger(idx)); + v->Push(val); + return 1; + } + return sq_throwerror(v, _SC("idx out of range")); } static SQInteger array_resize(HRABBITVM v) { - SQObject &o = stack_get(v, 1); - SQObject &nsize = stack_get(v, 2); - SQObjectPtr fill; - if(sq_isnumeric(nsize)) { - SQInteger sz = tointeger(nsize); - if (sz<0) - return sq_throwerror(v, _SC("resizing to negative length")); + SQObject &o = stack_get(v, 1); + SQObject &nsize = stack_get(v, 2); + SQObjectPtr fill; + if(sq_isnumeric(nsize)) { + SQInteger sz = tointeger(nsize); + if (sz<0) + return sq_throwerror(v, _SC("resizing to negative length")); - if(sq_gettop(v) > 2) - fill = stack_get(v, 3); - _array(o)->Resize(sz,fill); - sq_settop(v, 1); - return 1; - } - return sq_throwerror(v, _SC("size must be a number")); + if(sq_gettop(v) > 2) + fill = stack_get(v, 3); + _array(o)->Resize(sz,fill); + sq_settop(v, 1); + return 1; + } + return sq_throwerror(v, _SC("size must be a number")); } static SQInteger __map_array(SQArray *dest,SQArray *src,HRABBITVM v) { - SQObjectPtr temp; - SQInteger size = src->Size(); - for(SQInteger n = 0; n < size; n++) { - src->Get(n,temp); - v->Push(src); - v->Push(temp); - if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) { - return SQ_ERROR; - } - dest->Set(n,v->GetUp(-1)); - v->Pop(); - } - return 0; + SQObjectPtr temp; + SQInteger size = src->Size(); + for(SQInteger n = 0; n < size; n++) { + src->Get(n,temp); + v->Push(src); + v->Push(temp); + if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) { + return SQ_ERROR; + } + dest->Set(n,v->GetUp(-1)); + v->Pop(); + } + return 0; } static SQInteger array_map(HRABBITVM v) { - SQObject &o = stack_get(v,1); - SQInteger size = _array(o)->Size(); - SQObjectPtr ret = SQArray::Create(_ss(v),size); - if(SQ_FAILED(__map_array(_array(ret),_array(o),v))) - return SQ_ERROR; - v->Push(ret); - return 1; + SQObject &o = stack_get(v,1); + SQInteger size = _array(o)->Size(); + SQObjectPtr ret = SQArray::Create(_ss(v),size); + if(SQ_FAILED(__map_array(_array(ret),_array(o),v))) + return SQ_ERROR; + v->Push(ret); + return 1; } static SQInteger array_apply(HRABBITVM v) { - SQObject &o = stack_get(v,1); - if(SQ_FAILED(__map_array(_array(o),_array(o),v))) - return SQ_ERROR; - sq_pop(v,1); - return 1; + SQObject &o = stack_get(v,1); + if(SQ_FAILED(__map_array(_array(o),_array(o),v))) + return SQ_ERROR; + sq_pop(v,1); + return 1; } static SQInteger array_reduce(HRABBITVM v) { - SQObject &o = stack_get(v,1); - SQArray *a = _array(o); - SQInteger size = a->Size(); - if(size == 0) { - return 0; - } - SQObjectPtr res; - a->Get(0,res); - if(size > 1) { - SQObjectPtr other; - for(SQInteger n = 1; n < size; n++) { - a->Get(n,other); - v->Push(o); - v->Push(res); - v->Push(other); - if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { - return SQ_ERROR; - } - res = v->GetUp(-1); - v->Pop(); - } - } - v->Push(res); - return 1; + SQObject &o = stack_get(v,1); + SQArray *a = _array(o); + SQInteger size = a->Size(); + if(size == 0) { + return 0; + } + SQObjectPtr res; + a->Get(0,res); + if(size > 1) { + SQObjectPtr other; + for(SQInteger n = 1; n < size; n++) { + a->Get(n,other); + v->Push(o); + v->Push(res); + v->Push(other); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + res = v->GetUp(-1); + v->Pop(); + } + } + v->Push(res); + return 1; } static SQInteger array_filter(HRABBITVM v) { - SQObject &o = stack_get(v,1); - SQArray *a = _array(o); - SQObjectPtr ret = SQArray::Create(_ss(v),0); - SQInteger size = a->Size(); - SQObjectPtr val; - for(SQInteger n = 0; n < size; n++) { - a->Get(n,val); - v->Push(o); - v->Push(n); - v->Push(val); - if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { - return SQ_ERROR; - } - if(!SQVM::IsFalse(v->GetUp(-1))) { - _array(ret)->Append(val); - } - v->Pop(); - } - v->Push(ret); - return 1; + SQObject &o = stack_get(v,1); + SQArray *a = _array(o); + SQObjectPtr ret = SQArray::Create(_ss(v),0); + SQInteger size = a->Size(); + SQObjectPtr val; + for(SQInteger n = 0; n < size; n++) { + a->Get(n,val); + v->Push(o); + v->Push(n); + v->Push(val); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + if(!SQVM::IsFalse(v->GetUp(-1))) { + _array(ret)->Append(val); + } + v->Pop(); + } + v->Push(ret); + return 1; } static SQInteger array_find(HRABBITVM v) { - SQObject &o = stack_get(v,1); - SQObjectPtr &val = stack_get(v,2); - SQArray *a = _array(o); - SQInteger size = a->Size(); - SQObjectPtr temp; - for(SQInteger n = 0; n < size; n++) { - bool res = false; - a->Get(n,temp); - if(SQVM::IsEqual(temp,val,res) && res) { - v->Push(n); - return 1; - } - } - return 0; + SQObject &o = stack_get(v,1); + SQObjectPtr &val = stack_get(v,2); + SQArray *a = _array(o); + SQInteger size = a->Size(); + SQObjectPtr temp; + for(SQInteger n = 0; n < size; n++) { + bool res = false; + a->Get(n,temp); + if(SQVM::IsEqual(temp,val,res) && res) { + v->Push(n); + return 1; + } + } + return 0; } static bool _sort_compare(HRABBITVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) { - if(func < 0) { - if(!v->ObjCmp(a,b,ret)) return false; - } - else { - SQInteger top = sq_gettop(v); - sq_push(v, func); - sq_pushroottable(v); - v->Push(a); - v->Push(b); - if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { - if(!sq_isstring( v->_lasterror)) - v->Raise_Error(_SC("compare func failed")); - return false; - } - if(SQ_FAILED(sq_getinteger(v, -1, &ret))) { - v->Raise_Error(_SC("numeric value expected as return value of the compare function")); - return false; - } - sq_settop(v, top); - return true; - } - return true; + if(func < 0) { + if(!v->ObjCmp(a,b,ret)) return false; + } + else { + SQInteger top = sq_gettop(v); + sq_push(v, func); + sq_pushroottable(v); + v->Push(a); + v->Push(b); + if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { + if(!sq_isstring( v->_lasterror)) + v->Raise_Error(_SC("compare func failed")); + return false; + } + if(SQ_FAILED(sq_getinteger(v, -1, &ret))) { + v->Raise_Error(_SC("numeric value expected as return value of the compare function")); + return false; + } + sq_settop(v, top); + return true; + } + return true; } static bool _hsort_sift_down(HRABBITVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func) { - SQInteger maxChild; - SQInteger done = 0; - SQInteger ret; - SQInteger root2; - while (((root2 = root * 2) <= bottom) && (!done)) - { - if (root2 == bottom) { - maxChild = root2; - } - else { - if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret)) - return false; - if (ret > 0) { - maxChild = root2; - } - else { - maxChild = root2 + 1; - } - } + SQInteger maxChild; + SQInteger done = 0; + SQInteger ret; + SQInteger root2; + while (((root2 = root * 2) <= bottom) && (!done)) + { + if (root2 == bottom) { + maxChild = root2; + } + else { + if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret)) + return false; + if (ret > 0) { + maxChild = root2; + } + else { + maxChild = root2 + 1; + } + } - if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret)) - return false; - if (ret < 0) { - if (root == maxChild) { - v->Raise_Error(_SC("inconsistent compare function")); - return false; // We'd be swapping ourselve. The compare function is incorrect - } + if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret)) + return false; + if (ret < 0) { + if (root == maxChild) { + v->Raise_Error(_SC("inconsistent compare function")); + return false; // We'd be swapping ourselve. The compare function is incorrect + } - _Swap(arr->_values[root],arr->_values[maxChild]); - root = maxChild; - } - else { - done = 1; - } - } - return true; + _Swap(arr->_values[root],arr->_values[maxChild]); + root = maxChild; + } + else { + done = 1; + } + } + return true; } static bool _hsort(HRABBITVM v,SQObjectPtr &arr, SQInteger SQ_UNUSED_ARG(l), SQInteger SQ_UNUSED_ARG(r),SQInteger func) { - SQArray *a = _array(arr); - SQInteger i; - SQInteger array_size = a->Size(); - for (i = (array_size / 2); i >= 0; i--) { - if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false; - } + SQArray *a = _array(arr); + SQInteger i; + SQInteger array_size = a->Size(); + for (i = (array_size / 2); i >= 0; i--) { + if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false; + } - for (i = array_size-1; i >= 1; i--) - { - _Swap(a->_values[0],a->_values[i]); - if(!_hsort_sift_down(v,a, 0, i-1,func)) return false; - } - return true; + for (i = array_size-1; i >= 1; i--) + { + _Swap(a->_values[0],a->_values[i]); + if(!_hsort_sift_down(v,a, 0, i-1,func)) return false; + } + return true; } static SQInteger array_sort(HRABBITVM v) { - SQInteger func = -1; - SQObjectPtr &o = stack_get(v,1); - if(_array(o)->Size() > 1) { - if(sq_gettop(v) == 2) func = 2; - if(!_hsort(v, o, 0, _array(o)->Size()-1, func)) - return SQ_ERROR; + SQInteger func = -1; + SQObjectPtr &o = stack_get(v,1); + if(_array(o)->Size() > 1) { + if(sq_gettop(v) == 2) func = 2; + if(!_hsort(v, o, 0, _array(o)->Size()-1, func)) + return SQ_ERROR; - } - sq_settop(v,1); - return 1; + } + sq_settop(v,1); + return 1; } static SQInteger array_slice(HRABBITVM v) { - SQInteger sidx,eidx; - SQObjectPtr o; - if(get_slice_params(v,sidx,eidx,o)==-1)return -1; - SQInteger alen = _array(o)->Size(); - if(sidx < 0)sidx = alen + sidx; - if(eidx < 0)eidx = alen + eidx; - if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes")); - if(eidx > alen || sidx < 0)return sq_throwerror(v, _SC("slice out of range")); - SQArray *arr=SQArray::Create(_ss(v),eidx-sidx); - SQObjectPtr t; - SQInteger count=0; - for(SQInteger i=sidx;iGet(i,t); - arr->Set(count++,t); - } - v->Push(arr); - return 1; + SQInteger sidx,eidx; + SQObjectPtr o; + if(get_slice_params(v,sidx,eidx,o)==-1)return -1; + SQInteger alen = _array(o)->Size(); + if(sidx < 0)sidx = alen + sidx; + if(eidx < 0)eidx = alen + eidx; + if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes")); + if(eidx > alen || sidx < 0)return sq_throwerror(v, _SC("slice out of range")); + SQArray *arr=SQArray::Create(_ss(v),eidx-sidx); + SQObjectPtr t; + SQInteger count=0; + for(SQInteger i=sidx;iGet(i,t); + arr->Set(count++,t); + } + v->Push(arr); + return 1; } const SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ - {_SC("len"),default_delegate_len,1, _SC("a")}, - {_SC("append"),array_append,2, _SC("a")}, - {_SC("extend"),array_extend,2, _SC("aa")}, - {_SC("push"),array_append,2, _SC("a")}, - {_SC("pop"),array_pop,1, _SC("a")}, - {_SC("top"),array_top,1, _SC("a")}, - {_SC("insert"),array_insert,3, _SC("an")}, - {_SC("remove"),array_remove,2, _SC("an")}, - {_SC("resize"),array_resize,-2, _SC("an")}, - {_SC("reverse"),array_reverse,1, _SC("a")}, - {_SC("sort"),array_sort,-1, _SC("ac")}, - {_SC("slice"),array_slice,-1, _SC("ann")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("clear"),obj_clear,1, _SC(".")}, - {_SC("map"),array_map,2, _SC("ac")}, - {_SC("apply"),array_apply,2, _SC("ac")}, - {_SC("reduce"),array_reduce,2, _SC("ac")}, - {_SC("filter"),array_filter,2, _SC("ac")}, - {_SC("find"),array_find,2, _SC("a.")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("len"),default_delegate_len,1, _SC("a")}, + {_SC("append"),array_append,2, _SC("a")}, + {_SC("extend"),array_extend,2, _SC("aa")}, + {_SC("push"),array_append,2, _SC("a")}, + {_SC("pop"),array_pop,1, _SC("a")}, + {_SC("top"),array_top,1, _SC("a")}, + {_SC("insert"),array_insert,3, _SC("an")}, + {_SC("remove"),array_remove,2, _SC("an")}, + {_SC("resize"),array_resize,-2, _SC("an")}, + {_SC("reverse"),array_reverse,1, _SC("a")}, + {_SC("sort"),array_sort,-1, _SC("ac")}, + {_SC("slice"),array_slice,-1, _SC("ann")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("clear"),obj_clear,1, _SC(".")}, + {_SC("map"),array_map,2, _SC("ac")}, + {_SC("apply"),array_apply,2, _SC("ac")}, + {_SC("reduce"),array_reduce,2, _SC("ac")}, + {_SC("filter"),array_filter,2, _SC("ac")}, + {_SC("find"),array_find,2, _SC("a.")}, + {NULL,(SQFUNCTION)0,0,NULL} }; //STRING DEFAULT DELEGATE////////////////////////// static SQInteger string_slice(HRABBITVM v) { - SQInteger sidx,eidx; - SQObjectPtr o; - if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1; - SQInteger slen = _string(o)->_len; - if(sidx < 0)sidx = slen + sidx; - if(eidx < 0)eidx = slen + eidx; - if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes")); - if(eidx > slen || sidx < 0) return sq_throwerror(v, _SC("slice out of range")); - v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx)); - return 1; + SQInteger sidx,eidx; + SQObjectPtr o; + if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1; + SQInteger slen = _string(o)->_len; + if(sidx < 0)sidx = slen + sidx; + if(eidx < 0)eidx = slen + eidx; + if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes")); + if(eidx > slen || sidx < 0) return sq_throwerror(v, _SC("slice out of range")); + v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx)); + return 1; } static SQInteger string_find(HRABBITVM v) { - SQInteger top,start_idx=0; - const SQChar *str,*substr,*ret; - if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){ - if(top>2)sq_getinteger(v,3,&start_idx); - if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){ - ret=scstrstr(&str[start_idx],substr); - if(ret){ - sq_pushinteger(v,(SQInteger)(ret-str)); - return 1; - } - } - return 0; - } - return sq_throwerror(v,_SC("invalid param")); + SQInteger top,start_idx=0; + const SQChar *str,*substr,*ret; + if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){ + if(top>2)sq_getinteger(v,3,&start_idx); + if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){ + ret=scstrstr(&str[start_idx],substr); + if(ret){ + sq_pushinteger(v,(SQInteger)(ret-str)); + return 1; + } + } + return 0; + } + return sq_throwerror(v,_SC("invalid param")); } #define STRING_TOFUNCZ(func) static SQInteger string_##func(HRABBITVM v) \ {\ - SQInteger sidx,eidx; \ - SQObjectPtr str; \ - if(SQ_FAILED(get_slice_params(v,sidx,eidx,str)))return -1; \ - SQInteger slen = _string(str)->_len; \ - if(sidx < 0)sidx = slen + sidx; \ - if(eidx < 0)eidx = slen + eidx; \ - if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes")); \ - if(eidx > slen || sidx < 0) return sq_throwerror(v,_SC("slice out of range")); \ - SQInteger len=_string(str)->_len; \ - const SQChar *sthis=_stringval(str); \ - SQChar *snew=(_ss(v)->GetScratchPad(sq_rsl(len))); \ - memcpy(snew,sthis,sq_rsl(len));\ - for(SQInteger i=sidx;iPush(SQString::Create(_ss(v),snew,len)); \ - return 1; \ + SQInteger sidx,eidx; \ + SQObjectPtr str; \ + if(SQ_FAILED(get_slice_params(v,sidx,eidx,str)))return -1; \ + SQInteger slen = _string(str)->_len; \ + if(sidx < 0)sidx = slen + sidx; \ + if(eidx < 0)eidx = slen + eidx; \ + if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes")); \ + if(eidx > slen || sidx < 0) return sq_throwerror(v,_SC("slice out of range")); \ + SQInteger len=_string(str)->_len; \ + const SQChar *sthis=_stringval(str); \ + SQChar *snew=(_ss(v)->GetScratchPad(sq_rsl(len))); \ + memcpy(snew,sthis,sq_rsl(len));\ + for(SQInteger i=sidx;iPush(SQString::Create(_ss(v),snew,len)); \ + return 1; \ } @@ -887,32 +887,32 @@ STRING_TOFUNCZ(tolower) STRING_TOFUNCZ(toupper) const SQRegFunction SQSharedState::_string_default_delegate_funcz[]={ - {_SC("len"),default_delegate_len,1, _SC("s")}, - {_SC("tointeger"),default_delegate_tointeger,-1, _SC("sn")}, - {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")}, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("slice"),string_slice,-1, _SC("s n n")}, - {_SC("find"),string_find,-2, _SC("s s n")}, - {_SC("tolower"),string_tolower,-1, _SC("s n n")}, - {_SC("toupper"),string_toupper,-1, _SC("s n n")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("len"),default_delegate_len,1, _SC("s")}, + {_SC("tointeger"),default_delegate_tointeger,-1, _SC("sn")}, + {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")}, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("slice"),string_slice,-1, _SC("s n n")}, + {_SC("find"),string_find,-2, _SC("s s n")}, + {_SC("tolower"),string_tolower,-1, _SC("s n n")}, + {_SC("toupper"),string_toupper,-1, _SC("s n n")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {NULL,(SQFUNCTION)0,0,NULL} }; //INTEGER DEFAULT DELEGATE////////////////////////// const SQRegFunction SQSharedState::_number_default_delegate_funcz[]={ - {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")}, - {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")}, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")}, + {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")}, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {NULL,(SQFUNCTION)0,0,NULL} }; //CLOSURE DEFAULT DELEGATE////////////////////////// static SQInteger closure_pcall(HRABBITVM v) { - return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR; } static SQInteger closure_call(HRABBITVM v) @@ -927,377 +927,377 @@ static SQInteger closure_call(HRABBITVM v) static SQInteger _closure_acall(HRABBITVM v,SQBool raiseerror) { - SQArray *aparams=_array(stack_get(v,2)); - SQInteger nparams=aparams->Size(); - v->Push(stack_get(v,1)); - for(SQInteger i=0;iPush(aparams->_values[i]); - return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR; + SQArray *aparams=_array(stack_get(v,2)); + SQInteger nparams=aparams->Size(); + v->Push(stack_get(v,1)); + for(SQInteger i=0;iPush(aparams->_values[i]); + return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR; } static SQInteger closure_acall(HRABBITVM v) { - return _closure_acall(v,SQTrue); + return _closure_acall(v,SQTrue); } static SQInteger closure_pacall(HRABBITVM v) { - return _closure_acall(v,SQFalse); + return _closure_acall(v,SQFalse); } static SQInteger closure_bindenv(HRABBITVM v) { - if(SQ_FAILED(sq_bindenv(v,1))) - return SQ_ERROR; - return 1; + if(SQ_FAILED(sq_bindenv(v,1))) + return SQ_ERROR; + return 1; } static SQInteger closure_getroot(HRABBITVM v) { - if(SQ_FAILED(sq_getclosureroot(v,-1))) - return SQ_ERROR; - return 1; + if(SQ_FAILED(sq_getclosureroot(v,-1))) + return SQ_ERROR; + return 1; } static SQInteger closure_setroot(HRABBITVM v) { - if(SQ_FAILED(sq_setclosureroot(v,-2))) - return SQ_ERROR; - return 1; + if(SQ_FAILED(sq_setclosureroot(v,-2))) + return SQ_ERROR; + return 1; } static SQInteger closure_getinfos(HRABBITVM v) { - SQObject o = stack_get(v,1); - SQTable *res = SQTable::Create(_ss(v),4); - if(sq_type(o) == OT_CLOSURE) { - SQFunctionProto *f = _closure(o)->_function; - SQInteger nparams = f->_nparameters + (f->_varparams?1:0); - SQObjectPtr params = SQArray::Create(_ss(v),nparams); - SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams); - for(SQInteger n = 0; n_nparameters; n++) { - _array(params)->Set((SQInteger)n,f->_parameters[n]); - } - for(SQInteger j = 0; j_ndefaultparams; j++) { - _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]); - } - if(f->_varparams) { - _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1)); - } - res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false); - res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name); - res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename); - res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params); - res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams); - res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams); - } - else { //OT_NATIVECLOSURE - SQNativeClosure *nc = _nativeclosure(o); - res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true); - res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name); - res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck); - SQObjectPtr typecheck; - if(nc->_typecheck.size() > 0) { - typecheck = - SQArray::Create(_ss(v), nc->_typecheck.size()); - for(SQUnsignedInteger n = 0; n_typecheck.size(); n++) { - _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]); - } - } - res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck); - } - v->Push(res); - return 1; + SQObject o = stack_get(v,1); + SQTable *res = SQTable::Create(_ss(v),4); + if(sq_type(o) == OT_CLOSURE) { + SQFunctionProto *f = _closure(o)->_function; + SQInteger nparams = f->_nparameters + (f->_varparams?1:0); + SQObjectPtr params = SQArray::Create(_ss(v),nparams); + SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams); + for(SQInteger n = 0; n_nparameters; n++) { + _array(params)->Set((SQInteger)n,f->_parameters[n]); + } + for(SQInteger j = 0; j_ndefaultparams; j++) { + _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]); + } + if(f->_varparams) { + _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1)); + } + res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false); + res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name); + res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename); + res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params); + res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams); + res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams); + } + else { //OT_NATIVECLOSURE + SQNativeClosure *nc = _nativeclosure(o); + res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true); + res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name); + res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck); + SQObjectPtr typecheck; + if(nc->_typecheck.size() > 0) { + typecheck = + SQArray::Create(_ss(v), nc->_typecheck.size()); + for(SQUnsignedInteger n = 0; n_typecheck.size(); n++) { + _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]); + } + } + res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck); + } + v->Push(res); + return 1; } const SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={ - {_SC("call"),closure_call,-1, _SC("c")}, - {_SC("pcall"),closure_pcall,-1, _SC("c")}, - {_SC("acall"),closure_acall,2, _SC("ca")}, - {_SC("pacall"),closure_pacall,2, _SC("ca")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")}, - {_SC("getinfos"),closure_getinfos,1, _SC("c")}, - {_SC("getroot"),closure_getroot,1, _SC("c")}, - {_SC("setroot"),closure_setroot,2, _SC("ct")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("call"),closure_call,-1, _SC("c")}, + {_SC("pcall"),closure_pcall,-1, _SC("c")}, + {_SC("acall"),closure_acall,2, _SC("ca")}, + {_SC("pacall"),closure_pacall,2, _SC("ca")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")}, + {_SC("getinfos"),closure_getinfos,1, _SC("c")}, + {_SC("getroot"),closure_getroot,1, _SC("c")}, + {_SC("setroot"),closure_setroot,2, _SC("ct")}, + {NULL,(SQFUNCTION)0,0,NULL} }; //GENERATOR DEFAULT DELEGATE static SQInteger generator_getstatus(HRABBITVM v) { - SQObject &o=stack_get(v,1); - switch(_generator(o)->_state){ - case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break; - case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break; - case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break; - } - return 1; + SQObject &o=stack_get(v,1); + switch(_generator(o)->_state){ + case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break; + case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break; + case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break; + } + return 1; } const SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={ - {_SC("getstatus"),generator_getstatus,1, _SC("g")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("getstatus"),generator_getstatus,1, _SC("g")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {NULL,(SQFUNCTION)0,0,NULL} }; //THREAD DEFAULT DELEGATE static SQInteger thread_call(HRABBITVM v) { - SQObjectPtr o = stack_get(v,1); - if(sq_type(o) == OT_THREAD) { - SQInteger nparams = sq_gettop(v); - _thread(o)->Push(_thread(o)->_roottable); - for(SQInteger i = 2; i<(nparams+1); i++) - sq_move(_thread(o),v,i); - if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) { - sq_move(v,_thread(o),-1); - sq_pop(_thread(o),1); - return 1; - } - v->_lasterror = _thread(o)->_lasterror; - return SQ_ERROR; - } - return sq_throwerror(v,_SC("wrong parameter")); + SQObjectPtr o = stack_get(v,1); + if(sq_type(o) == OT_THREAD) { + SQInteger nparams = sq_gettop(v); + _thread(o)->Push(_thread(o)->_roottable); + for(SQInteger i = 2; i<(nparams+1); i++) + sq_move(_thread(o),v,i); + if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) { + sq_move(v,_thread(o),-1); + sq_pop(_thread(o),1); + return 1; + } + v->_lasterror = _thread(o)->_lasterror; + return SQ_ERROR; + } + return sq_throwerror(v,_SC("wrong parameter")); } static SQInteger thread_wakeup(HRABBITVM v) { - SQObjectPtr o = stack_get(v,1); - if(sq_type(o) == OT_THREAD) { - SQVM *thread = _thread(o); - SQInteger state = sq_getvmstate(thread); - if(state != SQ_VMSTATE_SUSPENDED) { - switch(state) { - case SQ_VMSTATE_IDLE: - return sq_throwerror(v,_SC("cannot wakeup a idle thread")); - break; - case SQ_VMSTATE_RUNNING: - return sq_throwerror(v,_SC("cannot wakeup a running thread")); - break; - } - } + SQObjectPtr o = stack_get(v,1); + if(sq_type(o) == OT_THREAD) { + SQVM *thread = _thread(o); + SQInteger state = sq_getvmstate(thread); + if(state != SQ_VMSTATE_SUSPENDED) { + switch(state) { + case SQ_VMSTATE_IDLE: + return sq_throwerror(v,_SC("cannot wakeup a idle thread")); + break; + case SQ_VMSTATE_RUNNING: + return sq_throwerror(v,_SC("cannot wakeup a running thread")); + break; + } + } - SQInteger wakeupret = sq_gettop(v)>1?SQTrue:SQFalse; - if(wakeupret) { - sq_move(thread,v,2); - } - if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) { - sq_move(v,thread,-1); - sq_pop(thread,1); //pop retval - if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { - sq_settop(thread,1); //pop roottable - } - return 1; - } - sq_settop(thread,1); - v->_lasterror = thread->_lasterror; - return SQ_ERROR; - } - return sq_throwerror(v,_SC("wrong parameter")); + SQInteger wakeupret = sq_gettop(v)>1?SQTrue:SQFalse; + if(wakeupret) { + sq_move(thread,v,2); + } + if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) { + sq_move(v,thread,-1); + sq_pop(thread,1); //pop retval + if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { + sq_settop(thread,1); //pop roottable + } + return 1; + } + sq_settop(thread,1); + v->_lasterror = thread->_lasterror; + return SQ_ERROR; + } + return sq_throwerror(v,_SC("wrong parameter")); } static SQInteger thread_wakeupthrow(HRABBITVM v) { - SQObjectPtr o = stack_get(v,1); - if(sq_type(o) == OT_THREAD) { - SQVM *thread = _thread(o); - SQInteger state = sq_getvmstate(thread); - if(state != SQ_VMSTATE_SUSPENDED) { - switch(state) { - case SQ_VMSTATE_IDLE: - return sq_throwerror(v,_SC("cannot wakeup a idle thread")); - break; - case SQ_VMSTATE_RUNNING: - return sq_throwerror(v,_SC("cannot wakeup a running thread")); - break; - } - } + SQObjectPtr o = stack_get(v,1); + if(sq_type(o) == OT_THREAD) { + SQVM *thread = _thread(o); + SQInteger state = sq_getvmstate(thread); + if(state != SQ_VMSTATE_SUSPENDED) { + switch(state) { + case SQ_VMSTATE_IDLE: + return sq_throwerror(v,_SC("cannot wakeup a idle thread")); + break; + case SQ_VMSTATE_RUNNING: + return sq_throwerror(v,_SC("cannot wakeup a running thread")); + break; + } + } - sq_move(thread,v,2); - sq_throwobject(thread); - SQBool rethrow_error = SQTrue; - if(sq_gettop(v) > 2) { - sq_getbool(v,3,&rethrow_error); - } - if(SQ_SUCCEEDED(sq_wakeupvm(thread,SQFalse,SQTrue,SQTrue,SQTrue))) { - sq_move(v,thread,-1); - sq_pop(thread,1); //pop retval - if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { - sq_settop(thread,1); //pop roottable - } - return 1; - } - sq_settop(thread,1); - if(rethrow_error) { - v->_lasterror = thread->_lasterror; - return SQ_ERROR; - } - return SQ_OK; - } - return sq_throwerror(v,_SC("wrong parameter")); + sq_move(thread,v,2); + sq_throwobject(thread); + SQBool rethrow_error = SQTrue; + if(sq_gettop(v) > 2) { + sq_getbool(v,3,&rethrow_error); + } + if(SQ_SUCCEEDED(sq_wakeupvm(thread,SQFalse,SQTrue,SQTrue,SQTrue))) { + sq_move(v,thread,-1); + sq_pop(thread,1); //pop retval + if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { + sq_settop(thread,1); //pop roottable + } + return 1; + } + sq_settop(thread,1); + if(rethrow_error) { + v->_lasterror = thread->_lasterror; + return SQ_ERROR; + } + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong parameter")); } static SQInteger thread_getstatus(HRABBITVM v) { - SQObjectPtr &o = stack_get(v,1); - switch(sq_getvmstate(_thread(o))) { - case SQ_VMSTATE_IDLE: - sq_pushstring(v,_SC("idle"),-1); - break; - case SQ_VMSTATE_RUNNING: - sq_pushstring(v,_SC("running"),-1); - break; - case SQ_VMSTATE_SUSPENDED: - sq_pushstring(v,_SC("suspended"),-1); - break; - default: - return sq_throwerror(v,_SC("internal VM error")); - } - return 1; + SQObjectPtr &o = stack_get(v,1); + switch(sq_getvmstate(_thread(o))) { + case SQ_VMSTATE_IDLE: + sq_pushstring(v,_SC("idle"),-1); + break; + case SQ_VMSTATE_RUNNING: + sq_pushstring(v,_SC("running"),-1); + break; + case SQ_VMSTATE_SUSPENDED: + sq_pushstring(v,_SC("suspended"),-1); + break; + default: + return sq_throwerror(v,_SC("internal VM error")); + } + return 1; } static SQInteger thread_getstackinfos(HRABBITVM v) { - SQObjectPtr o = stack_get(v,1); - if(sq_type(o) == OT_THREAD) { - SQVM *thread = _thread(o); - SQInteger threadtop = sq_gettop(thread); - SQInteger level; - sq_getinteger(v,-1,&level); - SQRESULT res = __getcallstackinfos(thread,level); - if(SQ_FAILED(res)) - { - sq_settop(thread,threadtop); - if(sq_type(thread->_lasterror) == OT_STRING) { - sq_throwerror(v,_stringval(thread->_lasterror)); - } - else { - sq_throwerror(v,_SC("unknown error")); - } - } - if(res > 0) { - //some result - sq_move(v,thread,-1); - sq_settop(thread,threadtop); - return 1; - } - //no result - sq_settop(thread,threadtop); - return 0; + SQObjectPtr o = stack_get(v,1); + if(sq_type(o) == OT_THREAD) { + SQVM *thread = _thread(o); + SQInteger threadtop = sq_gettop(thread); + SQInteger level; + sq_getinteger(v,-1,&level); + SQRESULT res = __getcallstackinfos(thread,level); + if(SQ_FAILED(res)) + { + sq_settop(thread,threadtop); + if(sq_type(thread->_lasterror) == OT_STRING) { + sq_throwerror(v,_stringval(thread->_lasterror)); + } + else { + sq_throwerror(v,_SC("unknown error")); + } + } + if(res > 0) { + //some result + sq_move(v,thread,-1); + sq_settop(thread,threadtop); + return 1; + } + //no result + sq_settop(thread,threadtop); + return 0; - } - return sq_throwerror(v,_SC("wrong parameter")); + } + return sq_throwerror(v,_SC("wrong parameter")); } const SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { - {_SC("call"), thread_call, -1, _SC("v")}, - {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, - {_SC("wakeupthrow"), thread_wakeupthrow, -2, _SC("v.b")}, - {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")}, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("call"), thread_call, -1, _SC("v")}, + {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, + {_SC("wakeupthrow"), thread_wakeupthrow, -2, _SC("v.b")}, + {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")}, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {NULL,(SQFUNCTION)0,0,NULL} }; static SQInteger class_getattributes(HRABBITVM v) { - return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR; } static SQInteger class_setattributes(HRABBITVM v) { - return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR; } static SQInteger class_instance(HRABBITVM v) { - return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR; } static SQInteger class_getbase(HRABBITVM v) { - return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR; + return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR; } static SQInteger class_newmember(HRABBITVM v) { - SQInteger top = sq_gettop(v); - SQBool bstatic = SQFalse; - if(top == 5) - { - sq_tobool(v,-1,&bstatic); - sq_pop(v,1); - } + SQInteger top = sq_gettop(v); + SQBool bstatic = SQFalse; + if(top == 5) + { + sq_tobool(v,-1,&bstatic); + sq_pop(v,1); + } - if(top < 4) { - sq_pushnull(v); - } - return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR; + if(top < 4) { + sq_pushnull(v); + } + return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR; } static SQInteger class_rawnewmember(HRABBITVM v) { - SQInteger top = sq_gettop(v); - SQBool bstatic = SQFalse; - if(top == 5) - { - sq_tobool(v,-1,&bstatic); - sq_pop(v,1); - } + SQInteger top = sq_gettop(v); + SQBool bstatic = SQFalse; + if(top == 5) + { + sq_tobool(v,-1,&bstatic); + sq_pop(v,1); + } - if(top < 4) { - sq_pushnull(v); - } - return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR; + if(top < 4) { + sq_pushnull(v); + } + return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR; } const SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { - {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, - {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, - {_SC("rawget"),container_rawget,2, _SC("y")}, - {_SC("rawset"),container_rawset,3, _SC("y")}, - {_SC("rawin"),container_rawexists,2, _SC("y")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("instance"),class_instance,1, _SC("y")}, - {_SC("getbase"),class_getbase,1, _SC("y")}, - {_SC("newmember"),class_newmember,-3, _SC("y")}, - {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, + {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, + {_SC("rawget"),container_rawget,2, _SC("y")}, + {_SC("rawset"),container_rawset,3, _SC("y")}, + {_SC("rawin"),container_rawexists,2, _SC("y")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("instance"),class_instance,1, _SC("y")}, + {_SC("getbase"),class_getbase,1, _SC("y")}, + {_SC("newmember"),class_newmember,-3, _SC("y")}, + {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")}, + {NULL,(SQFUNCTION)0,0,NULL} }; static SQInteger instance_getclass(HRABBITVM v) { - if(SQ_SUCCEEDED(sq_getclass(v,1))) - return 1; - return SQ_ERROR; + if(SQ_SUCCEEDED(sq_getclass(v,1))) + return 1; + return SQ_ERROR; } const SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { - {_SC("getclass"), instance_getclass, 1, _SC("x")}, - {_SC("rawget"),container_rawget,2, _SC("x")}, - {_SC("rawset"),container_rawset,3, _SC("x")}, - {_SC("rawin"),container_rawexists,2, _SC("x")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("getclass"), instance_getclass, 1, _SC("x")}, + {_SC("rawget"),container_rawget,2, _SC("x")}, + {_SC("rawset"),container_rawset,3, _SC("x")}, + {_SC("rawin"),container_rawexists,2, _SC("x")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {NULL,(SQFUNCTION)0,0,NULL} }; static SQInteger weakref_ref(HRABBITVM v) { - if(SQ_FAILED(sq_getweakrefval(v,1))) - return SQ_ERROR; - return 1; + if(SQ_FAILED(sq_getweakrefval(v,1))) + return SQ_ERROR; + return 1; } const SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { - {_SC("ref"),weakref_ref,1, _SC("r")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {NULL,(SQFUNCTION)0,0,NULL} + {_SC("ref"),weakref_ref,1, _SC("r")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {NULL,(SQFUNCTION)0,0,NULL} }; diff --git a/rabbit/sqclass.cpp b/rabbit/sqclass.cpp index c61d5fa..a850949 100644 --- a/rabbit/sqclass.cpp +++ b/rabbit/sqclass.cpp @@ -16,199 +16,199 @@ SQClass::SQClass(SQSharedState *ss,SQClass *base) { - _base = base; - _typetag = 0; - _hook = NULL; - _udsize = 0; - _locked = false; - _constructoridx = -1; - if(_base) { - _constructoridx = _base->_constructoridx; - _udsize = _base->_udsize; - _defaultvalues.copy(base->_defaultvalues); - _methods.copy(base->_methods); - _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST); - __ObjAddRef(_base); - } - _members = base?base->_members->Clone() : SQTable::Create(ss,0); - __ObjAddRef(_members); + _base = base; + _typetag = 0; + _hook = NULL; + _udsize = 0; + _locked = false; + _constructoridx = -1; + if(_base) { + _constructoridx = _base->_constructoridx; + _udsize = _base->_udsize; + _defaultvalues.copy(base->_defaultvalues); + _methods.copy(base->_methods); + _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST); + __ObjAddRef(_base); + } + _members = base?base->_members->Clone() : SQTable::Create(ss,0); + __ObjAddRef(_members); - INIT_CHAIN(); - ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); } void SQClass::Finalize() { - _attributes.Null(); - _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size()); - _methods.resize(0); - _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST); - __ObjRelease(_members); - if(_base) { - __ObjRelease(_base); - } + _attributes.Null(); + _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size()); + _methods.resize(0); + _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST); + __ObjRelease(_members); + if(_base) { + __ObjRelease(_base); + } } SQClass::~SQClass() { - REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); - Finalize(); + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + Finalize(); } bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) { - SQObjectPtr temp; - bool belongs_to_static_table = sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE || bstatic; - if(_locked && !belongs_to_static_table) - return false; //the class already has an instance so cannot be modified - if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value - { - _defaultvalues[_member_idx(temp)].val = val; - return true; - } - if(belongs_to_static_table) { - SQInteger mmidx; - if((sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE) && - (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { - _metamethods[mmidx] = val; - } - else { - SQObjectPtr theval = val; - if(_base && sq_type(val) == OT_CLOSURE) { - theval = _closure(val)->Clone(); - _closure(theval)->_base = _base; - __ObjAddRef(_base); //ref for the closure - } - if(sq_type(temp) == OT_NULL) { - bool isconstructor; - SQVM::IsEqual(ss->_constructoridx, key, isconstructor); - if(isconstructor) { - _constructoridx = (SQInteger)_methods.size(); - } - SQClassMember m; - m.val = theval; - _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); - _methods.push_back(m); - } - else { - _methods[_member_idx(temp)].val = theval; - } - } - return true; - } - SQClassMember m; - m.val = val; - _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size()))); - _defaultvalues.push_back(m); - return true; + SQObjectPtr temp; + bool belongs_to_static_table = sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE || bstatic; + if(_locked && !belongs_to_static_table) + return false; //the class already has an instance so cannot be modified + if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value + { + _defaultvalues[_member_idx(temp)].val = val; + return true; + } + if(belongs_to_static_table) { + SQInteger mmidx; + if((sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE) && + (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { + _metamethods[mmidx] = val; + } + else { + SQObjectPtr theval = val; + if(_base && sq_type(val) == OT_CLOSURE) { + theval = _closure(val)->Clone(); + _closure(theval)->_base = _base; + __ObjAddRef(_base); //ref for the closure + } + if(sq_type(temp) == OT_NULL) { + bool isconstructor; + SQVM::IsEqual(ss->_constructoridx, key, isconstructor); + if(isconstructor) { + _constructoridx = (SQInteger)_methods.size(); + } + SQClassMember m; + m.val = theval; + _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); + _methods.push_back(m); + } + else { + _methods[_member_idx(temp)].val = theval; + } + } + return true; + } + SQClassMember m; + m.val = val; + _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size()))); + _defaultvalues.push_back(m); + return true; } SQInstance *SQClass::CreateInstance() { - if(!_locked) Lock(); - return SQInstance::Create(NULL,this); + if(!_locked) Lock(); + return SQInstance::Create(NULL,this); } SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) { - SQObjectPtr oval; - SQInteger idx = _members->Next(false,refpos,outkey,oval); - if(idx != -1) { - if(_ismethod(oval)) { - outval = _methods[_member_idx(oval)].val; - } - else { - SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val; - outval = _realval(o); - } - } - return idx; + SQObjectPtr oval; + SQInteger idx = _members->Next(false,refpos,outkey,oval); + if(idx != -1) { + if(_ismethod(oval)) { + outval = _methods[_member_idx(oval)].val; + } + else { + SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val; + outval = _realval(o); + } + } + return idx; } bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val) { - SQObjectPtr idx; - if(_members->Get(key,idx)) { - if(_isfield(idx)) - _defaultvalues[_member_idx(idx)].attrs = val; - else - _methods[_member_idx(idx)].attrs = val; - return true; - } - return false; + SQObjectPtr idx; + if(_members->Get(key,idx)) { + if(_isfield(idx)) + _defaultvalues[_member_idx(idx)].attrs = val; + else + _methods[_member_idx(idx)].attrs = val; + return true; + } + return false; } bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval) { - SQObjectPtr idx; - if(_members->Get(key,idx)) { - outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs); - return true; - } - return false; + SQObjectPtr idx; + if(_members->Get(key,idx)) { + outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs); + return true; + } + return false; } /////////////////////////////////////////////////////////////////////// void SQInstance::Init(SQSharedState *ss) { - _userpointer = NULL; - _hook = NULL; - __ObjAddRef(_class); - _delegate = _class->_members; - INIT_CHAIN(); - ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); + _userpointer = NULL; + _hook = NULL; + __ObjAddRef(_class); + _delegate = _class->_members; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); } SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize) { - _memsize = memsize; - _class = c; - SQUnsignedInteger nvalues = _class->_defaultvalues.size(); - for(SQUnsignedInteger n = 0; n < nvalues; n++) { - new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val); - } - Init(ss); + _memsize = memsize; + _class = c; + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger n = 0; n < nvalues; n++) { + new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val); + } + Init(ss); } SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize) { - _memsize = memsize; - _class = i->_class; - SQUnsignedInteger nvalues = _class->_defaultvalues.size(); - for(SQUnsignedInteger n = 0; n < nvalues; n++) { - new (&_values[n]) SQObjectPtr(i->_values[n]); - } - Init(ss); + _memsize = memsize; + _class = i->_class; + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger n = 0; n < nvalues; n++) { + new (&_values[n]) SQObjectPtr(i->_values[n]); + } + Init(ss); } void SQInstance::Finalize() { - SQUnsignedInteger nvalues = _class->_defaultvalues.size(); - __ObjRelease(_class); - _NULL_SQOBJECT_VECTOR(_values,nvalues); + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + __ObjRelease(_class); + _NULL_SQOBJECT_VECTOR(_values,nvalues); } SQInstance::~SQInstance() { - REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); - if(_class){ Finalize(); } //if _class is null it was already finalized by the GC + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + if(_class){ Finalize(); } //if _class is null it was already finalized by the GC } bool SQInstance::GetMetaMethod(SQVM* SQ_UNUSED_ARG(v),SQMetaMethod mm,SQObjectPtr &res) { - if(sq_type(_class->_metamethods[mm]) != OT_NULL) { - res = _class->_metamethods[mm]; - return true; - } - return false; + if(sq_type(_class->_metamethods[mm]) != OT_NULL) { + res = _class->_metamethods[mm]; + return true; + } + return false; } bool SQInstance::InstanceOf(SQClass *trg) { - SQClass *parent = _class; - while(parent != NULL) { - if(parent == trg) - return true; - parent = parent->_base; - } - return false; + SQClass *parent = _class; + while(parent != NULL) { + if(parent == trg) + return true; + parent = parent->_base; + } + return false; } diff --git a/rabbit/sqclass.hpp b/rabbit/sqclass.hpp index caf2148..54c8795 100644 --- a/rabbit/sqclass.hpp +++ b/rabbit/sqclass.hpp @@ -10,12 +10,12 @@ struct SQInstance; struct SQClassMember { - SQObjectPtr val; - SQObjectPtr attrs; - void Null() { - val.Null(); - attrs.Null(); - } + SQObjectPtr val; + SQObjectPtr attrs; + void Null() { + val.Null(); + attrs.Null(); + } }; typedef sqvector SQClassMemberVec; @@ -32,127 +32,127 @@ typedef sqvector SQClassMemberVec; struct SQClass : public CHAINABLE_OBJ { - SQClass(SQSharedState *ss,SQClass *base); + SQClass(SQSharedState *ss,SQClass *base); public: - static SQClass* Create(SQSharedState *ss,SQClass *base) { - SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass)); - new (newclass) SQClass(ss, base); - return newclass; - } - ~SQClass(); - bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic); - bool Get(const SQObjectPtr &key,SQObjectPtr &val) { - if(_members->Get(key,val)) { - if(_isfield(val)) { - SQObjectPtr &o = _defaultvalues[_member_idx(val)].val; - val = _realval(o); - } - else { - val = _methods[_member_idx(val)].val; - } - return true; - } - return false; - } - bool GetConstructor(SQObjectPtr &ctor) - { - if(_constructoridx != -1) { - ctor = _methods[_constructoridx].val; - return true; - } - return false; - } - bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); - bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); - void Lock() { _locked = true; if(_base) _base->Lock(); } - void Release() { - if (_hook) { _hook(_typetag,0);} - sq_delete(this, SQClass); - } - void Finalize(); - SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); - SQInstance *CreateInstance(); - SQTable *_members; - SQClass *_base; - SQClassMemberVec _defaultvalues; - SQClassMemberVec _methods; - SQObjectPtr _metamethods[MT_LAST]; - SQObjectPtr _attributes; - SQUserPointer _typetag; - SQRELEASEHOOK _hook; - bool _locked; - SQInteger _constructoridx; - SQInteger _udsize; + static SQClass* Create(SQSharedState *ss,SQClass *base) { + SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass)); + new (newclass) SQClass(ss, base); + return newclass; + } + ~SQClass(); + bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic); + bool Get(const SQObjectPtr &key,SQObjectPtr &val) { + if(_members->Get(key,val)) { + if(_isfield(val)) { + SQObjectPtr &o = _defaultvalues[_member_idx(val)].val; + val = _realval(o); + } + else { + val = _methods[_member_idx(val)].val; + } + return true; + } + return false; + } + bool GetConstructor(SQObjectPtr &ctor) + { + if(_constructoridx != -1) { + ctor = _methods[_constructoridx].val; + return true; + } + return false; + } + bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); + bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); + void Lock() { _locked = true; if(_base) _base->Lock(); } + void Release() { + if (_hook) { _hook(_typetag,0);} + sq_delete(this, SQClass); + } + void Finalize(); + SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + SQInstance *CreateInstance(); + SQTable *_members; + SQClass *_base; + SQClassMemberVec _defaultvalues; + SQClassMemberVec _methods; + SQObjectPtr _metamethods[MT_LAST]; + SQObjectPtr _attributes; + SQUserPointer _typetag; + SQRELEASEHOOK _hook; + bool _locked; + SQInteger _constructoridx; + SQInteger _udsize; }; #define calcinstancesize(_theclass_) \ - (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))) + (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))) struct SQInstance : public SQDelegable { - void Init(SQSharedState *ss); - SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize); - SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize); + void Init(SQSharedState *ss); + SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize); + SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize); public: - static SQInstance* Create(SQSharedState *ss,SQClass *theclass) { + static SQInstance* Create(SQSharedState *ss,SQClass *theclass) { - SQInteger size = calcinstancesize(theclass); - SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); - new (newinst) SQInstance(ss, theclass,size); - if(theclass->_udsize) { - newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize); - } - return newinst; - } - SQInstance *Clone(SQSharedState *ss) - { - SQInteger size = calcinstancesize(_class); - SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); - new (newinst) SQInstance(ss, this,size); - if(_class->_udsize) { - newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize); - } - return newinst; - } - ~SQInstance(); - bool Get(const SQObjectPtr &key,SQObjectPtr &val) { - if(_class->_members->Get(key,val)) { - if(_isfield(val)) { - SQObjectPtr &o = _values[_member_idx(val)]; - val = _realval(o); - } - else { - val = _class->_methods[_member_idx(val)].val; - } - return true; - } - return false; - } - bool Set(const SQObjectPtr &key,const SQObjectPtr &val) { - SQObjectPtr idx; - if(_class->_members->Get(key,idx) && _isfield(idx)) { - _values[_member_idx(idx)] = val; - return true; - } - return false; - } - void Release() { - _uiRef++; - if (_hook) { _hook(_userpointer,0);} - _uiRef--; - if(_uiRef > 0) return; - SQInteger size = _memsize; - this->~SQInstance(); - SQ_FREE(this, size); - } - void Finalize(); - bool InstanceOf(SQClass *trg); - bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); + SQInteger size = calcinstancesize(theclass); + SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); + new (newinst) SQInstance(ss, theclass,size); + if(theclass->_udsize) { + newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize); + } + return newinst; + } + SQInstance *Clone(SQSharedState *ss) + { + SQInteger size = calcinstancesize(_class); + SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); + new (newinst) SQInstance(ss, this,size); + if(_class->_udsize) { + newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize); + } + return newinst; + } + ~SQInstance(); + bool Get(const SQObjectPtr &key,SQObjectPtr &val) { + if(_class->_members->Get(key,val)) { + if(_isfield(val)) { + SQObjectPtr &o = _values[_member_idx(val)]; + val = _realval(o); + } + else { + val = _class->_methods[_member_idx(val)].val; + } + return true; + } + return false; + } + bool Set(const SQObjectPtr &key,const SQObjectPtr &val) { + SQObjectPtr idx; + if(_class->_members->Get(key,idx) && _isfield(idx)) { + _values[_member_idx(idx)] = val; + return true; + } + return false; + } + void Release() { + _uiRef++; + if (_hook) { _hook(_userpointer,0);} + _uiRef--; + if(_uiRef > 0) return; + SQInteger size = _memsize; + this->~SQInstance(); + SQ_FREE(this, size); + } + void Finalize(); + bool InstanceOf(SQClass *trg); + bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); - SQClass *_class; - SQUserPointer _userpointer; - SQRELEASEHOOK _hook; - SQInteger _memsize; - SQObjectPtr _values[1]; + SQClass *_class; + SQUserPointer _userpointer; + SQRELEASEHOOK _hook; + SQInteger _memsize; + SQObjectPtr _values[1]; }; diff --git a/rabbit/sqclosure.hpp b/rabbit/sqclosure.hpp index dbc211b..8f46e02 100644 --- a/rabbit/sqclosure.hpp +++ b/rabbit/sqclosure.hpp @@ -14,55 +14,55 @@ struct SQClass; struct SQClosure : public CHAINABLE_OBJ { private: - SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL; _root=NULL;} + SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL; _root=NULL;} public: - static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func,SQWeakRef *root){ - SQInteger size = _CALC_CLOSURE_SIZE(func); - SQClosure *nc=(SQClosure*)SQ_MALLOC(size); - new (nc) SQClosure(ss,func); - nc->_outervalues = (SQObjectPtr *)(nc + 1); - nc->_defaultparams = &nc->_outervalues[func->_noutervalues]; - nc->_root = root; - __ObjAddRef(nc->_root); - _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues); - _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams); - return nc; - } - void Release(){ - SQFunctionProto *f = _function; - SQInteger size = _CALC_CLOSURE_SIZE(f); - _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues); - _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams); - __ObjRelease(_function); - this->~SQClosure(); - sq_vm_free(this,size); - } - void SetRoot(SQWeakRef *r) - { - __ObjRelease(_root); - _root = r; - __ObjAddRef(_root); - } - SQClosure *Clone() - { - SQFunctionProto *f = _function; - SQClosure * ret = SQClosure::Create(NULL,f,_root); - ret->_env = _env; - if(ret->_env) __ObjAddRef(ret->_env); - _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues); - _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams); - return ret; - } - ~SQClosure(); + static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func,SQWeakRef *root){ + SQInteger size = _CALC_CLOSURE_SIZE(func); + SQClosure *nc=(SQClosure*)SQ_MALLOC(size); + new (nc) SQClosure(ss,func); + nc->_outervalues = (SQObjectPtr *)(nc + 1); + nc->_defaultparams = &nc->_outervalues[func->_noutervalues]; + nc->_root = root; + __ObjAddRef(nc->_root); + _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues); + _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams); + return nc; + } + void Release(){ + SQFunctionProto *f = _function; + SQInteger size = _CALC_CLOSURE_SIZE(f); + _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues); + _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams); + __ObjRelease(_function); + this->~SQClosure(); + sq_vm_free(this,size); + } + void SetRoot(SQWeakRef *r) + { + __ObjRelease(_root); + _root = r; + __ObjAddRef(_root); + } + SQClosure *Clone() + { + SQFunctionProto *f = _function; + SQClosure * ret = SQClosure::Create(NULL,f,_root); + ret->_env = _env; + if(ret->_env) __ObjAddRef(ret->_env); + _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues); + _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams); + return ret; + } + ~SQClosure(); - bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); - static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); - SQWeakRef *_env; - SQWeakRef *_root; - SQClass *_base; - SQFunctionProto *_function; - SQObjectPtr *_outervalues; - SQObjectPtr *_defaultparams; + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); + static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); + SQWeakRef *_env; + SQWeakRef *_root; + SQClass *_base; + SQFunctionProto *_function; + SQObjectPtr *_outervalues; + SQObjectPtr *_defaultparams; }; ////////////////////////////////////////////// @@ -70,60 +70,60 @@ struct SQOuter : public CHAINABLE_OBJ { private: - SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } + SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } public: - static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer) - { - SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter)); - new (nc) SQOuter(ss, outer); - return nc; - } - ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } + static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer) + { + SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter)); + new (nc) SQOuter(ss, outer); + return nc; + } + ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } - void Release() - { - this->~SQOuter(); - sq_vm_free(this,sizeof(SQOuter)); - } + void Release() + { + this->~SQOuter(); + sq_vm_free(this,sizeof(SQOuter)); + } - SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */ - SQInteger _idx; /* idx in stack array, for relocation */ - SQObjectPtr _value; /* value of outer after stack frame is closed */ - SQOuter *_next; /* pointer to next outer when frame is open */ + SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */ + SQInteger _idx; /* idx in stack array, for relocation */ + SQObjectPtr _value; /* value of outer after stack frame is closed */ + SQOuter *_next; /* pointer to next outer when frame is open */ }; ////////////////////////////////////////////// struct SQGenerator : public CHAINABLE_OBJ { - enum SQGeneratorState{eRunning,eSuspended,eDead}; + enum SQGeneratorState{eRunning,eSuspended,eDead}; private: - SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} public: - static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ - SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); - new (nc) SQGenerator(ss,closure); - return nc; - } - ~SQGenerator() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } - void Kill(){ - _state=eDead; - _stack.resize(0); - _closure.Null();} - void Release(){ - sq_delete(this,SQGenerator); - } + static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ + SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); + new (nc) SQGenerator(ss,closure); + return nc; + } + ~SQGenerator() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + void Kill(){ + _state=eDead; + _stack.resize(0); + _closure.Null();} + void Release(){ + sq_delete(this,SQGenerator); + } - bool Yield(SQVM *v,SQInteger target); - bool Resume(SQVM *v,SQObjectPtr &dest); - SQObjectPtr _closure; - SQObjectPtrVec _stack; - SQVM::CallInfo _ci; - ExceptionsTraps _etraps; - SQGeneratorState _state; + bool Yield(SQVM *v,SQInteger target); + bool Resume(SQVM *v,SQObjectPtr &dest); + SQObjectPtr _closure; + SQObjectPtrVec _stack; + SQVM::CallInfo _ci; + ExceptionsTraps _etraps; + SQGeneratorState _state; }; #define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr))) @@ -131,48 +131,48 @@ public: struct SQNativeClosure : public CHAINABLE_OBJ { private: - SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} + SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} public: - static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters) - { - SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters); - SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size); - new (nc) SQNativeClosure(ss,func); - nc->_outervalues = (SQObjectPtr *)(nc + 1); - nc->_noutervalues = nouters; - _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues); - return nc; - } - SQNativeClosure *Clone() - { - SQNativeClosure * ret = SQNativeClosure::Create(NULL,_function,_noutervalues); - ret->_env = _env; - if(ret->_env) __ObjAddRef(ret->_env); - ret->_name = _name; - _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues); - ret->_typecheck.copy(_typecheck); - ret->_nparamscheck = _nparamscheck; - return ret; - } - ~SQNativeClosure() - { - __ObjRelease(_env); - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } - void Release(){ - SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues); - _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues); - this->~SQNativeClosure(); - sq_free(this,size); - } + static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters) + { + SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters); + SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size); + new (nc) SQNativeClosure(ss,func); + nc->_outervalues = (SQObjectPtr *)(nc + 1); + nc->_noutervalues = nouters; + _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues); + return nc; + } + SQNativeClosure *Clone() + { + SQNativeClosure * ret = SQNativeClosure::Create(NULL,_function,_noutervalues); + ret->_env = _env; + if(ret->_env) __ObjAddRef(ret->_env); + ret->_name = _name; + _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues); + ret->_typecheck.copy(_typecheck); + ret->_nparamscheck = _nparamscheck; + return ret; + } + ~SQNativeClosure() + { + __ObjRelease(_env); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + void Release(){ + SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues); + _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues); + this->~SQNativeClosure(); + sq_free(this,size); + } - SQInteger _nparamscheck; - SQIntVec _typecheck; - SQObjectPtr *_outervalues; - SQUnsignedInteger _noutervalues; - SQWeakRef *_env; - SQFUNCTION _function; - SQObjectPtr _name; + SQInteger _nparamscheck; + SQIntVec _typecheck; + SQObjectPtr *_outervalues; + SQUnsignedInteger _noutervalues; + SQWeakRef *_env; + SQFUNCTION _function; + SQObjectPtr _name; }; diff --git a/rabbit/sqcompiler.cpp b/rabbit/sqcompiler.cpp index 47a8442..8c3aaba 100644 --- a/rabbit/sqcompiler.cpp +++ b/rabbit/sqcompiler.cpp @@ -25,1567 +25,1567 @@ #define OUTER 5 struct SQExpState { - SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */ - SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */ - bool donot_get; /* signal not to deref the next value */ + SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */ + SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */ + bool donot_get; /* signal not to deref the next value */ }; #define MAX_COMPILER_ERROR_LEN 256 struct SQScope { - SQInteger outers; - SQInteger stacksize; + SQInteger outers; + SQInteger stacksize; }; #define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \ - _scope.outers = _fs->_outers; \ - _scope.stacksize = _fs->GetStackSize(); + _scope.outers = _fs->_outers; \ + _scope.stacksize = _fs->GetStackSize(); #define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \ - if(_fs->CountOuters(_scope.stacksize)) { \ - _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ - } \ - } + if(_fs->CountOuters(_scope.stacksize)) { \ + _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ + } \ + } #define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \ - _fs->SetStackSize(_scope.stacksize); \ - } \ - _scope = __oldscope__; \ - } + _fs->SetStackSize(_scope.stacksize); \ + } \ + _scope = __oldscope__; \ + } #define END_SCOPE() { SQInteger oldouters = _fs->_outers;\ - if(_fs->GetStackSize() != _scope.stacksize) { \ - _fs->SetStackSize(_scope.stacksize); \ - if(oldouters != _fs->_outers) { \ - _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ - } \ - } \ - _scope = __oldscope__; \ - } + if(_fs->GetStackSize() != _scope.stacksize) { \ + _fs->SetStackSize(_scope.stacksize); \ + if(oldouters != _fs->_outers) { \ + _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ + } \ + } \ + _scope = __oldscope__; \ + } #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \ - SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ - _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0); + SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ + _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0); #define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \ - __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \ - if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \ - if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \ - _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();} + __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \ + if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \ + if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \ + _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();} class SQCompiler { public: - SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) - { - _vm=v; - _lex.Init(_ss(v), rg, up,ThrowError,this); - _sourcename = SQString::Create(_ss(v), sourcename); - _lineinfo = lineinfo;_raiseerror = raiseerror; - _scope.outers = 0; - _scope.stacksize = 0; - _compilererror[0] = _SC('\0'); - } - static void ThrowError(void *ud, const SQChar *s) { - SQCompiler *c = (SQCompiler *)ud; - c->Error(s); - } - void Error(const SQChar *s, ...) - { - va_list vl; - va_start(vl, s); - scvsprintf(_compilererror, MAX_COMPILER_ERROR_LEN, s, vl); - va_end(vl); - longjmp(_errorjmp,1); - } - void Lex(){ _token = _lex.Lex();} - SQObject Expect(SQInteger tok) - { + SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) + { + _vm=v; + _lex.Init(_ss(v), rg, up,ThrowError,this); + _sourcename = SQString::Create(_ss(v), sourcename); + _lineinfo = lineinfo;_raiseerror = raiseerror; + _scope.outers = 0; + _scope.stacksize = 0; + _compilererror[0] = _SC('\0'); + } + static void ThrowError(void *ud, const SQChar *s) { + SQCompiler *c = (SQCompiler *)ud; + c->Error(s); + } + void Error(const SQChar *s, ...) + { + va_list vl; + va_start(vl, s); + scvsprintf(_compilererror, MAX_COMPILER_ERROR_LEN, s, vl); + va_end(vl); + longjmp(_errorjmp,1); + } + void Lex(){ _token = _lex.Lex();} + SQObject Expect(SQInteger tok) + { - if(_token != tok) { - if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { - //do nothing - } - else { - const SQChar *etypename; - if(tok > 255) { - switch(tok) - { - case TK_IDENTIFIER: - etypename = _SC("IDENTIFIER"); - break; - case TK_STRING_LITERAL: - etypename = _SC("STRING_LITERAL"); - break; - case TK_INTEGER: - etypename = _SC("INTEGER"); - break; - case TK_FLOAT: - etypename = _SC("FLOAT"); - break; - default: - etypename = _lex.Tok2Str(tok); - } - Error(_SC("expected '%s'"), etypename); - } - Error(_SC("expected '%c'"), tok); - } - } - SQObjectPtr ret; - switch(tok) - { - case TK_IDENTIFIER: - ret = _fs->CreateString(_lex._svalue); - break; - case TK_STRING_LITERAL: - ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); - break; - case TK_INTEGER: - ret = SQObjectPtr(_lex._nvalue); - break; - case TK_FLOAT: - ret = SQObjectPtr(_lex._fvalue); - break; - } - Lex(); - return ret; - } - bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == RABBIT_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); } - void OptionalSemicolon() - { - if(_token == _SC(';')) { Lex(); return; } - if(!IsEndOfStatement()) { - Error(_SC("end of statement expected (; or lf)")); - } - } - void MoveIfCurrentTargetIsLocal() { - SQInteger trg = _fs->TopTarget(); - if(_fs->IsLocal(trg)) { - trg = _fs->PopTarget(); //pops the target and moves it - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg); - } - } - bool Compile(SQObjectPtr &o) - { - _debugline = 1; - _debugop = 0; + if(_token != tok) { + if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { + //do nothing + } + else { + const SQChar *etypename; + if(tok > 255) { + switch(tok) + { + case TK_IDENTIFIER: + etypename = _SC("IDENTIFIER"); + break; + case TK_STRING_LITERAL: + etypename = _SC("STRING_LITERAL"); + break; + case TK_INTEGER: + etypename = _SC("INTEGER"); + break; + case TK_FLOAT: + etypename = _SC("FLOAT"); + break; + default: + etypename = _lex.Tok2Str(tok); + } + Error(_SC("expected '%s'"), etypename); + } + Error(_SC("expected '%c'"), tok); + } + } + SQObjectPtr ret; + switch(tok) + { + case TK_IDENTIFIER: + ret = _fs->CreateString(_lex._svalue); + break; + case TK_STRING_LITERAL: + ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); + break; + case TK_INTEGER: + ret = SQObjectPtr(_lex._nvalue); + break; + case TK_FLOAT: + ret = SQObjectPtr(_lex._fvalue); + break; + } + Lex(); + return ret; + } + bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == RABBIT_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); } + void OptionalSemicolon() + { + if(_token == _SC(';')) { Lex(); return; } + if(!IsEndOfStatement()) { + Error(_SC("end of statement expected (; or lf)")); + } + } + void MoveIfCurrentTargetIsLocal() { + SQInteger trg = _fs->TopTarget(); + if(_fs->IsLocal(trg)) { + trg = _fs->PopTarget(); //pops the target and moves it + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg); + } + } + bool Compile(SQObjectPtr &o) + { + _debugline = 1; + _debugop = 0; - SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this); - funcstate._name = SQString::Create(_ss(_vm), _SC("main")); - _fs = &funcstate; - _fs->AddParameter(_fs->CreateString(_SC("this"))); - _fs->AddParameter(_fs->CreateString(_SC("vargv"))); - _fs->_varparams = true; - _fs->_sourcename = _sourcename; - SQInteger stacksize = _fs->GetStackSize(); - if(setjmp(_errorjmp) == 0) { - Lex(); - while(_token > 0){ - Statement(); - if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); - } - _fs->SetStackSize(stacksize); - _fs->AddLineInfos(_lex._currentline, _lineinfo, true); - _fs->AddInstruction(_OP_RETURN, 0xFF); - _fs->SetStackSize(0); - o =_fs->BuildProto(); + SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this); + funcstate._name = SQString::Create(_ss(_vm), _SC("main")); + _fs = &funcstate; + _fs->AddParameter(_fs->CreateString(_SC("this"))); + _fs->AddParameter(_fs->CreateString(_SC("vargv"))); + _fs->_varparams = true; + _fs->_sourcename = _sourcename; + SQInteger stacksize = _fs->GetStackSize(); + if(setjmp(_errorjmp) == 0) { + Lex(); + while(_token > 0){ + Statement(); + if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); + } + _fs->SetStackSize(stacksize); + _fs->AddLineInfos(_lex._currentline, _lineinfo, true); + _fs->AddInstruction(_OP_RETURN, 0xFF); + _fs->SetStackSize(0); + o =_fs->BuildProto(); #ifdef _DEBUG_DUMP - _fs->Dump(_funcproto(o)); + _fs->Dump(_funcproto(o)); #endif - } - else { - if(_raiseerror && _ss(_vm)->_compilererrorhandler) { - _ss(_vm)->_compilererrorhandler(_vm, _compilererror, sq_type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"), - _lex._currentline, _lex._currentcolumn); - } - _vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1); - return false; - } - return true; - } - void Statements() - { - while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) { - Statement(); - if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); - } - } - void Statement(bool closeframe = true) - { - _fs->AddLineInfos(_lex._currentline, _lineinfo); - switch(_token){ - case _SC(';'): Lex(); break; - case TK_IF: IfStatement(); break; - case TK_WHILE: WhileStatement(); break; - case TK_DO: DoWhileStatement(); break; - case TK_FOR: ForStatement(); break; - case TK_FOREACH: ForEachStatement(); break; - case TK_SWITCH: SwitchStatement(); break; - case TK_LOCAL: LocalDeclStatement(); break; - case TK_RETURN: - case TK_YIELD: { - SQOpcode op; - if(_token == TK_RETURN) { - op = _OP_RETURN; - } - else { - op = _OP_YIELD; - _fs->_bgenerator = true; - } - Lex(); - if(!IsEndOfStatement()) { - SQInteger retexp = _fs->GetCurrentPos()+1; - CommaExpr(); - if(op == _OP_RETURN && _fs->_traps > 0) - _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); - _fs->_returnexp = retexp; - _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize()); - } - else{ - if(op == _OP_RETURN && _fs->_traps > 0) - _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); - _fs->_returnexp = -1; - _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); - } - break;} - case TK_BREAK: - if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block")); - if(_fs->_breaktargets.top() > 0){ - _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); - } - RESOLVE_OUTERS(); - _fs->AddInstruction(_OP_JMP, 0, -1234); - _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); - Lex(); - break; - case TK_CONTINUE: - if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block")); - if(_fs->_continuetargets.top() > 0) { - _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); - } - RESOLVE_OUTERS(); - _fs->AddInstruction(_OP_JMP, 0, -1234); - _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); - Lex(); - break; - case TK_FUNCTION: - FunctionStatement(); - break; - case TK_CLASS: - ClassStatement(); - break; - case TK_ENUM: - EnumStatement(); - break; - case _SC('{'):{ - BEGIN_SCOPE(); - Lex(); - Statements(); - Expect(_SC('}')); - if(closeframe) { - END_SCOPE(); - } - else { - END_SCOPE_NO_CLOSE(); - } - } - break; - case TK_TRY: - TryCatchStatement(); - break; - case TK_THROW: - Lex(); - CommaExpr(); - _fs->AddInstruction(_OP_THROW, _fs->PopTarget()); - break; - case TK_CONST: - { - Lex(); - SQObject id = Expect(TK_IDENTIFIER); - Expect('='); - SQObject val = ExpectScalar(); - OptionalSemicolon(); - SQTable *enums = _table(_ss(_vm)->_consts); - SQObjectPtr strongid = id; - enums->NewSlot(strongid,SQObjectPtr(val)); - strongid.Null(); - } - break; - default: - CommaExpr(); - _fs->DiscardTarget(); - //_fs->PopTarget(); - break; - } - _fs->SnoozeOpt(); - } - void EmitDerefOp(SQOpcode op) - { - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(op,_fs->PushTarget(),src,key,val); - } - void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0) - { - SQInteger p2 = _fs->PopTarget(); //src in OP_GET - SQInteger p1 = _fs->PopTarget(); //key in OP_GET - _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); - } - void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos) - { - /* Generate code depending on the expression type */ - switch(etype) { - case LOCAL:{ - SQInteger p2 = _fs->PopTarget(); //src in OP_GET - SQInteger p1 = _fs->PopTarget(); //key in OP_GET - _fs->PushTarget(p1); - //EmitCompArithLocal(tok, p1, p1, p2); - _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0); - _fs->SnoozeOpt(); - } - break; - case OBJECT: - case BASE: - { - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger src = _fs->PopTarget(); - /* _OP_COMPARITH mixes dest obj and source val in the arg1 */ - _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok)); - } - break; - case OUTER: - { - SQInteger val = _fs->TopTarget(); - SQInteger tmp = _fs->PushTarget(); - _fs->AddInstruction(_OP_GETOUTER, tmp, pos); - _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0); - _fs->PopTarget(); - _fs->PopTarget(); - _fs->AddInstruction(_OP_SETOUTER, _fs->PushTarget(), pos, tmp); - } - break; - } - } - void CommaExpr() - { - for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()); - } - void Expression() - { - SQExpState es = _es; - _es.etype = EXPR; - _es.epos = -1; - _es.donot_get = false; - LogicalOrExp(); - switch(_token) { - case _SC('='): - case TK_NEWSLOT: - case TK_MINUSEQ: - case TK_PLUSEQ: - case TK_MULEQ: - case TK_DIVEQ: - case TK_MODEQ:{ - SQInteger op = _token; - SQInteger ds = _es.etype; - SQInteger pos = _es.epos; - if(ds == EXPR) Error(_SC("can't assign expression")); - else if(ds == BASE) Error(_SC("'base' cannot be modified")); - Lex(); Expression(); + } + else { + if(_raiseerror && _ss(_vm)->_compilererrorhandler) { + _ss(_vm)->_compilererrorhandler(_vm, _compilererror, sq_type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"), + _lex._currentline, _lex._currentcolumn); + } + _vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1); + return false; + } + return true; + } + void Statements() + { + while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) { + Statement(); + if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); + } + } + void Statement(bool closeframe = true) + { + _fs->AddLineInfos(_lex._currentline, _lineinfo); + switch(_token){ + case _SC(';'): Lex(); break; + case TK_IF: IfStatement(); break; + case TK_WHILE: WhileStatement(); break; + case TK_DO: DoWhileStatement(); break; + case TK_FOR: ForStatement(); break; + case TK_FOREACH: ForEachStatement(); break; + case TK_SWITCH: SwitchStatement(); break; + case TK_LOCAL: LocalDeclStatement(); break; + case TK_RETURN: + case TK_YIELD: { + SQOpcode op; + if(_token == TK_RETURN) { + op = _OP_RETURN; + } + else { + op = _OP_YIELD; + _fs->_bgenerator = true; + } + Lex(); + if(!IsEndOfStatement()) { + SQInteger retexp = _fs->GetCurrentPos()+1; + CommaExpr(); + if(op == _OP_RETURN && _fs->_traps > 0) + _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); + _fs->_returnexp = retexp; + _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize()); + } + else{ + if(op == _OP_RETURN && _fs->_traps > 0) + _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); + _fs->_returnexp = -1; + _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); + } + break;} + case TK_BREAK: + if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block")); + if(_fs->_breaktargets.top() > 0){ + _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); + } + RESOLVE_OUTERS(); + _fs->AddInstruction(_OP_JMP, 0, -1234); + _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); + Lex(); + break; + case TK_CONTINUE: + if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block")); + if(_fs->_continuetargets.top() > 0) { + _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); + } + RESOLVE_OUTERS(); + _fs->AddInstruction(_OP_JMP, 0, -1234); + _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); + Lex(); + break; + case TK_FUNCTION: + FunctionStatement(); + break; + case TK_CLASS: + ClassStatement(); + break; + case TK_ENUM: + EnumStatement(); + break; + case _SC('{'):{ + BEGIN_SCOPE(); + Lex(); + Statements(); + Expect(_SC('}')); + if(closeframe) { + END_SCOPE(); + } + else { + END_SCOPE_NO_CLOSE(); + } + } + break; + case TK_TRY: + TryCatchStatement(); + break; + case TK_THROW: + Lex(); + CommaExpr(); + _fs->AddInstruction(_OP_THROW, _fs->PopTarget()); + break; + case TK_CONST: + { + Lex(); + SQObject id = Expect(TK_IDENTIFIER); + Expect('='); + SQObject val = ExpectScalar(); + OptionalSemicolon(); + SQTable *enums = _table(_ss(_vm)->_consts); + SQObjectPtr strongid = id; + enums->NewSlot(strongid,SQObjectPtr(val)); + strongid.Null(); + } + break; + default: + CommaExpr(); + _fs->DiscardTarget(); + //_fs->PopTarget(); + break; + } + _fs->SnoozeOpt(); + } + void EmitDerefOp(SQOpcode op) + { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(op,_fs->PushTarget(),src,key,val); + } + void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0) + { + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->PopTarget(); //key in OP_GET + _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); + } + void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos) + { + /* Generate code depending on the expression type */ + switch(etype) { + case LOCAL:{ + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->PopTarget(); //key in OP_GET + _fs->PushTarget(p1); + //EmitCompArithLocal(tok, p1, p1, p2); + _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0); + _fs->SnoozeOpt(); + } + break; + case OBJECT: + case BASE: + { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + /* _OP_COMPARITH mixes dest obj and source val in the arg1 */ + _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok)); + } + break; + case OUTER: + { + SQInteger val = _fs->TopTarget(); + SQInteger tmp = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp, pos); + _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0); + _fs->PopTarget(); + _fs->PopTarget(); + _fs->AddInstruction(_OP_SETOUTER, _fs->PushTarget(), pos, tmp); + } + break; + } + } + void CommaExpr() + { + for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()); + } + void Expression() + { + SQExpState es = _es; + _es.etype = EXPR; + _es.epos = -1; + _es.donot_get = false; + LogicalOrExp(); + switch(_token) { + case _SC('='): + case TK_NEWSLOT: + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ:{ + SQInteger op = _token; + SQInteger ds = _es.etype; + SQInteger pos = _es.epos; + if(ds == EXPR) Error(_SC("can't assign expression")); + else if(ds == BASE) Error(_SC("'base' cannot be modified")); + Lex(); Expression(); - switch(op){ - case TK_NEWSLOT: - if(ds == OBJECT || ds == BASE) - EmitDerefOp(_OP_NEWSLOT); - else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - Error(_SC("can't 'create' a local slot")); - break; - case _SC('='): //ASSIGN - switch(ds) { - case LOCAL: - { - SQInteger src = _fs->PopTarget(); - SQInteger dst = _fs->TopTarget(); - _fs->AddInstruction(_OP_MOVE, dst, src); - } - break; - case OBJECT: - case BASE: - EmitDerefOp(_OP_SET); - break; - case OUTER: - { - SQInteger src = _fs->PopTarget(); - SQInteger dst = _fs->PushTarget(); - _fs->AddInstruction(_OP_SETOUTER, dst, pos, src); - } - } - break; - case TK_MINUSEQ: - case TK_PLUSEQ: - case TK_MULEQ: - case TK_DIVEQ: - case TK_MODEQ: - EmitCompoundArith(op, ds, pos); - break; - } - } - break; - case _SC('?'): { - Lex(); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); - SQInteger jzpos = _fs->GetCurrentPos(); - SQInteger trg = _fs->PushTarget(); - Expression(); - SQInteger first_exp = _fs->PopTarget(); - if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); - SQInteger endfirstexp = _fs->GetCurrentPos(); - _fs->AddInstruction(_OP_JMP, 0, 0); - Expect(_SC(':')); - SQInteger jmppos = _fs->GetCurrentPos(); - Expression(); - SQInteger second_exp = _fs->PopTarget(); - if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); - _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); - _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1); - _fs->SnoozeOpt(); - } - break; - } - _es = es; - } - template void INVOKE_EXP(T f) - { - SQExpState es = _es; - _es.etype = EXPR; - _es.epos = -1; - _es.donot_get = false; - (this->*f)(); - _es = es; - } - template void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0) - { - Lex(); - INVOKE_EXP(f); - SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); - _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3); - _es.etype = EXPR; - } - void LogicalOrExp() - { - LogicalAndExp(); - for(;;) if(_token == TK_OR) { - SQInteger first_exp = _fs->PopTarget(); - SQInteger trg = _fs->PushTarget(); - _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0); - SQInteger jpos = _fs->GetCurrentPos(); - if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); - Lex(); INVOKE_EXP(&SQCompiler::LogicalOrExp); - _fs->SnoozeOpt(); - SQInteger second_exp = _fs->PopTarget(); - if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); - _fs->SnoozeOpt(); - _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); - _es.etype = EXPR; - break; - }else return; - } - void LogicalAndExp() - { - BitwiseOrExp(); - for(;;) switch(_token) { - case TK_AND: { - SQInteger first_exp = _fs->PopTarget(); - SQInteger trg = _fs->PushTarget(); - _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0); - SQInteger jpos = _fs->GetCurrentPos(); - if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); - Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp); - _fs->SnoozeOpt(); - SQInteger second_exp = _fs->PopTarget(); - if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); - _fs->SnoozeOpt(); - _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); - _es.etype = EXPR; - break; - } + switch(op){ + case TK_NEWSLOT: + if(ds == OBJECT || ds == BASE) + EmitDerefOp(_OP_NEWSLOT); + else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + Error(_SC("can't 'create' a local slot")); + break; + case _SC('='): //ASSIGN + switch(ds) { + case LOCAL: + { + SQInteger src = _fs->PopTarget(); + SQInteger dst = _fs->TopTarget(); + _fs->AddInstruction(_OP_MOVE, dst, src); + } + break; + case OBJECT: + case BASE: + EmitDerefOp(_OP_SET); + break; + case OUTER: + { + SQInteger src = _fs->PopTarget(); + SQInteger dst = _fs->PushTarget(); + _fs->AddInstruction(_OP_SETOUTER, dst, pos, src); + } + } + break; + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + EmitCompoundArith(op, ds, pos); + break; + } + } + break; + case _SC('?'): { + Lex(); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + SQInteger jzpos = _fs->GetCurrentPos(); + SQInteger trg = _fs->PushTarget(); + Expression(); + SQInteger first_exp = _fs->PopTarget(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + SQInteger endfirstexp = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_JMP, 0, 0); + Expect(_SC(':')); + SQInteger jmppos = _fs->GetCurrentPos(); + Expression(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); + _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1); + _fs->SnoozeOpt(); + } + break; + } + _es = es; + } + template void INVOKE_EXP(T f) + { + SQExpState es = _es; + _es.etype = EXPR; + _es.epos = -1; + _es.donot_get = false; + (this->*f)(); + _es = es; + } + template void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0) + { + Lex(); + INVOKE_EXP(f); + SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); + _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3); + _es.etype = EXPR; + } + void LogicalOrExp() + { + LogicalAndExp(); + for(;;) if(_token == TK_OR) { + SQInteger first_exp = _fs->PopTarget(); + SQInteger trg = _fs->PushTarget(); + _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0); + SQInteger jpos = _fs->GetCurrentPos(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + Lex(); INVOKE_EXP(&SQCompiler::LogicalOrExp); + _fs->SnoozeOpt(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SnoozeOpt(); + _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); + _es.etype = EXPR; + break; + }else return; + } + void LogicalAndExp() + { + BitwiseOrExp(); + for(;;) switch(_token) { + case TK_AND: { + SQInteger first_exp = _fs->PopTarget(); + SQInteger trg = _fs->PushTarget(); + _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0); + SQInteger jpos = _fs->GetCurrentPos(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp); + _fs->SnoozeOpt(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SnoozeOpt(); + _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); + _es.etype = EXPR; + break; + } - default: - return; - } - } - void BitwiseOrExp() - { - BitwiseXorExp(); - for(;;) if(_token == _SC('|')) - {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR); - }else return; - } - void BitwiseXorExp() - { - BitwiseAndExp(); - for(;;) if(_token == _SC('^')) - {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR); - }else return; - } - void BitwiseAndExp() - { - EqExp(); - for(;;) if(_token == _SC('&')) - {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND); - }else return; - } - void EqExp() - { - CompExp(); - for(;;) switch(_token) { - case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break; - case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break; - case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break; - default: return; - } - } - void CompExp() - { - ShiftExp(); - for(;;) switch(_token) { - case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; - case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; - case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; - case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; - case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break; - case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::ShiftExp); break; - default: return; - } - } - void ShiftExp() - { - PlusExp(); - for(;;) switch(_token) { - case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break; - case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break; - case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break; - default: return; - } - } - SQOpcode ChooseArithOpByToken(SQInteger tok) - { - switch(tok) { - case TK_PLUSEQ: case '+': return _OP_ADD; - case TK_MINUSEQ: case '-': return _OP_SUB; - case TK_MULEQ: case '*': return _OP_MUL; - case TK_DIVEQ: case '/': return _OP_DIV; - case TK_MODEQ: case '%': return _OP_MOD; - default: assert(0); - } - return _OP_ADD; - } - SQInteger ChooseCompArithCharByToken(SQInteger tok) - { - SQInteger oper; - switch(tok){ - case TK_MINUSEQ: oper = '-'; break; - case TK_PLUSEQ: oper = '+'; break; - case TK_MULEQ: oper = '*'; break; - case TK_DIVEQ: oper = '/'; break; - case TK_MODEQ: oper = '%'; break; - default: oper = 0; //shut up compiler - assert(0); break; - }; - return oper; - } - void PlusExp() - { - MultExp(); - for(;;) switch(_token) { - case _SC('+'): case _SC('-'): - BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break; - default: return; - } - } + default: + return; + } + } + void BitwiseOrExp() + { + BitwiseXorExp(); + for(;;) if(_token == _SC('|')) + {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR); + }else return; + } + void BitwiseXorExp() + { + BitwiseAndExp(); + for(;;) if(_token == _SC('^')) + {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR); + }else return; + } + void BitwiseAndExp() + { + EqExp(); + for(;;) if(_token == _SC('&')) + {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND); + }else return; + } + void EqExp() + { + CompExp(); + for(;;) switch(_token) { + case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break; + case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break; + case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break; + default: return; + } + } + void CompExp() + { + ShiftExp(); + for(;;) switch(_token) { + case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; + case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; + case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; + case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; + case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break; + case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::ShiftExp); break; + default: return; + } + } + void ShiftExp() + { + PlusExp(); + for(;;) switch(_token) { + case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break; + case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break; + case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break; + default: return; + } + } + SQOpcode ChooseArithOpByToken(SQInteger tok) + { + switch(tok) { + case TK_PLUSEQ: case '+': return _OP_ADD; + case TK_MINUSEQ: case '-': return _OP_SUB; + case TK_MULEQ: case '*': return _OP_MUL; + case TK_DIVEQ: case '/': return _OP_DIV; + case TK_MODEQ: case '%': return _OP_MOD; + default: assert(0); + } + return _OP_ADD; + } + SQInteger ChooseCompArithCharByToken(SQInteger tok) + { + SQInteger oper; + switch(tok){ + case TK_MINUSEQ: oper = '-'; break; + case TK_PLUSEQ: oper = '+'; break; + case TK_MULEQ: oper = '*'; break; + case TK_DIVEQ: oper = '/'; break; + case TK_MODEQ: oper = '%'; break; + default: oper = 0; //shut up compiler + assert(0); break; + }; + return oper; + } + void PlusExp() + { + MultExp(); + for(;;) switch(_token) { + case _SC('+'): case _SC('-'): + BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break; + default: return; + } + } - void MultExp() - { - PrefixedExpr(); - for(;;) switch(_token) { - case _SC('*'): case _SC('/'): case _SC('%'): - BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break; - default: return; - } - } - //if 'pos' != -1 the previous variable is a local variable - void PrefixedExpr() - { - SQInteger pos = Factor(); - for(;;) { - switch(_token) { - case _SC('.'): - pos = -1; - Lex(); + void MultExp() + { + PrefixedExpr(); + for(;;) switch(_token) { + case _SC('*'): case _SC('/'): case _SC('%'): + BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break; + default: return; + } + } + //if 'pos' != -1 the previous variable is a local variable + void PrefixedExpr() + { + SQInteger pos = Factor(); + for(;;) { + switch(_token) { + case _SC('.'): + pos = -1; + Lex(); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - if(_es.etype==BASE) { - Emit2ArgsOP(_OP_GET); - pos = _fs->TopTarget(); - _es.etype = EXPR; - _es.epos = pos; - } - else { - if(NeedGet()) { - Emit2ArgsOP(_OP_GET); - } - _es.etype = OBJECT; - } - break; - case _SC('['): - if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); - Lex(); Expression(); Expect(_SC(']')); - pos = -1; - if(_es.etype==BASE) { - Emit2ArgsOP(_OP_GET); - pos = _fs->TopTarget(); - _es.etype = EXPR; - _es.epos = pos; - } - else { - if(NeedGet()) { - Emit2ArgsOP(_OP_GET); - } - _es.etype = OBJECT; - } - break; - case TK_MINUSMINUS: - case TK_PLUSPLUS: - { - if(IsEndOfStatement()) return; - SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1; - Lex(); - switch(_es.etype) - { - case EXPR: Error(_SC("can't '++' or '--' an expression")); break; - case OBJECT: - case BASE: - if(_es.donot_get == true) { Error(_SC("can't '++' or '--' an expression")); break; } //mmh dor this make sense? - Emit2ArgsOP(_OP_PINC, diff); - break; - case LOCAL: { - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff); - } - break; - case OUTER: { - SQInteger tmp1 = _fs->PushTarget(); - SQInteger tmp2 = _fs->PushTarget(); - _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos); - _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff); - _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2); - _fs->PopTarget(); - } - } - } - return; - break; - case _SC('('): - switch(_es.etype) { - case OBJECT: { - SQInteger key = _fs->PopTarget(); /* location of the key */ - SQInteger table = _fs->PopTarget(); /* location of the object */ - SQInteger closure = _fs->PushTarget(); /* location for the closure */ - SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */ - _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); - } - break; - case BASE: - //Emit2ArgsOP(_OP_GET); - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - break; - case OUTER: - _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos); - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - break; - default: - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - } - _es.etype = EXPR; - Lex(); - FunctionCallArgs(); - break; - default: return; - } - } - } - SQInteger Factor() - { - //_es.etype = EXPR; - switch(_token) - { - case TK_STRING_LITERAL: - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); - Lex(); - break; - case TK_BASE: - Lex(); - _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget()); - _es.etype = BASE; - _es.epos = _fs->TopTarget(); - return (_es.epos); - break; - case TK_IDENTIFIER: - case TK_CONSTRUCTOR: - case TK_THIS:{ - SQObject id; - SQObject constant; + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + if(_es.etype==BASE) { + Emit2ArgsOP(_OP_GET); + pos = _fs->TopTarget(); + _es.etype = EXPR; + _es.epos = pos; + } + else { + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; + } + break; + case _SC('['): + if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); + Lex(); Expression(); Expect(_SC(']')); + pos = -1; + if(_es.etype==BASE) { + Emit2ArgsOP(_OP_GET); + pos = _fs->TopTarget(); + _es.etype = EXPR; + _es.epos = pos; + } + else { + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; + } + break; + case TK_MINUSMINUS: + case TK_PLUSPLUS: + { + if(IsEndOfStatement()) return; + SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1; + Lex(); + switch(_es.etype) + { + case EXPR: Error(_SC("can't '++' or '--' an expression")); break; + case OBJECT: + case BASE: + if(_es.donot_get == true) { Error(_SC("can't '++' or '--' an expression")); break; } //mmh dor this make sense? + Emit2ArgsOP(_OP_PINC, diff); + break; + case LOCAL: { + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff); + } + break; + case OUTER: { + SQInteger tmp1 = _fs->PushTarget(); + SQInteger tmp2 = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos); + _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff); + _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2); + _fs->PopTarget(); + } + } + } + return; + break; + case _SC('('): + switch(_es.etype) { + case OBJECT: { + SQInteger key = _fs->PopTarget(); /* location of the key */ + SQInteger table = _fs->PopTarget(); /* location of the object */ + SQInteger closure = _fs->PushTarget(); /* location for the closure */ + SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */ + _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); + } + break; + case BASE: + //Emit2ArgsOP(_OP_GET); + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + break; + case OUTER: + _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos); + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + break; + default: + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + } + _es.etype = EXPR; + Lex(); + FunctionCallArgs(); + break; + default: return; + } + } + } + SQInteger Factor() + { + //_es.etype = EXPR; + switch(_token) + { + case TK_STRING_LITERAL: + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); + Lex(); + break; + case TK_BASE: + Lex(); + _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget()); + _es.etype = BASE; + _es.epos = _fs->TopTarget(); + return (_es.epos); + break; + case TK_IDENTIFIER: + case TK_CONSTRUCTOR: + case TK_THIS:{ + SQObject id; + SQObject constant; - switch(_token) { - case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; - case TK_THIS: id = _fs->CreateString(_SC("this"),4); break; - case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor"),11); break; - } + switch(_token) { + case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; + case TK_THIS: id = _fs->CreateString(_SC("this"),4); break; + case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor"),11); break; + } - SQInteger pos = -1; - Lex(); - if((pos = _fs->GetLocalVariable(id)) != -1) { - /* Handle a local variable (includes 'this') */ - _fs->PushTarget(pos); - _es.etype = LOCAL; - _es.epos = pos; - } + SQInteger pos = -1; + Lex(); + if((pos = _fs->GetLocalVariable(id)) != -1) { + /* Handle a local variable (includes 'this') */ + _fs->PushTarget(pos); + _es.etype = LOCAL; + _es.epos = pos; + } - else if((pos = _fs->GetOuterVariable(id)) != -1) { - /* Handle a free var */ - if(NeedGet()) { - _es.epos = _fs->PushTarget(); - _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos); - /* _es.etype = EXPR; already default value */ - } - else { - _es.etype = OUTER; - _es.epos = pos; - } - } + else if((pos = _fs->GetOuterVariable(id)) != -1) { + /* Handle a free var */ + if(NeedGet()) { + _es.epos = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos); + /* _es.etype = EXPR; already default value */ + } + else { + _es.etype = OUTER; + _es.epos = pos; + } + } - else if(_fs->IsConstant(id, constant)) { - /* Handle named constant */ - SQObjectPtr constval; - SQObject constid; - if(sq_type(constant) == OT_TABLE) { - Expect('.'); - constid = Expect(TK_IDENTIFIER); - if(!_table(constant)->Get(constid, constval)) { - constval.Null(); - Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid)); - } - } - else { - constval = constant; - } - _es.epos = _fs->PushTarget(); + else if(_fs->IsConstant(id, constant)) { + /* Handle named constant */ + SQObjectPtr constval; + SQObject constid; + if(sq_type(constant) == OT_TABLE) { + Expect('.'); + constid = Expect(TK_IDENTIFIER); + if(!_table(constant)->Get(constid, constval)) { + constval.Null(); + Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid)); + } + } + else { + constval = constant; + } + _es.epos = _fs->PushTarget(); - /* generate direct or literal function depending on size */ - SQObjectType ctype = sq_type(constval); - switch(ctype) { - case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break; - case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break; - case OT_BOOL: _fs->AddInstruction(_OP_LOADBOOL, _es.epos, _integer(constval)); break; - default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break; - } - _es.etype = EXPR; - } - else { - /* Handle a non-local variable, aka a field. Push the 'this' pointer on - * the virtual stack (always found in offset 0, so no instruction needs to - * be generated), and push the key next. Generate an _OP_LOAD instruction - * for the latter. If we are not using the variable as a dref expr, generate - * the _OP_GET instruction. - */ - _fs->PushTarget(0); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(NeedGet()) { - Emit2ArgsOP(_OP_GET); - } - _es.etype = OBJECT; - } - return _es.epos; - } - break; - case TK_DOUBLE_COLON: // "::" - _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget()); - _es.etype = OBJECT; - _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/ - _es.epos = -1; - return _es.epos; - break; - case TK_NULL: - _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); - Lex(); - break; - case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break; - case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break; - case TK_TRUE: case TK_FALSE: - _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); - Lex(); - break; - case _SC('['): { - _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY); - SQInteger apos = _fs->GetCurrentPos(),key = 0; - Lex(); - while(_token != _SC(']')) { - Expression(); - if(_token == _SC(',')) Lex(); - SQInteger val = _fs->PopTarget(); - SQInteger array = _fs->TopTarget(); - _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK); - key++; - } - _fs->SetIntructionParam(apos, 1, key); - Lex(); - } - break; - case _SC('{'): - _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); - Lex();ParseTableOrClass(_SC(','),_SC('}')); - break; - case TK_FUNCTION: FunctionExp(_token);break; - case _SC('@'): FunctionExp(_token,true);break; - case TK_CLASS: Lex(); ClassExp();break; - case _SC('-'): - Lex(); - switch(_token) { - case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break; - case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break; - default: UnaryOP(_OP_NEG); - } - break; - case _SC('!'): Lex(); UnaryOP(_OP_NOT); break; - case _SC('~'): - Lex(); - if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; } - UnaryOP(_OP_BWNOT); - break; - case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break; - case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break; - case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break; - case TK_RAWCALL: Lex(); Expect('('); FunctionCallArgs(true); break; - case TK_MINUSMINUS : - case TK_PLUSPLUS :PrefixIncDec(_token); break; - case TK_DELETE : DeleteExpr(); break; - case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); - break; - case TK___LINE__: EmitLoadConstInt(_lex._currentline,-1); Lex(); break; - case TK___FILE__: _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_sourcename)); Lex(); break; - default: Error(_SC("expression expected")); - } - _es.etype = EXPR; - return -1; - } - void EmitLoadConstInt(SQInteger value,SQInteger target) - { - if(target < 0) { - target = _fs->PushTarget(); - } - if(value <= INT_MAX && value > INT_MIN) { //does it fit in 32 bits? - _fs->AddInstruction(_OP_LOADINT, target,value); - } - else { - _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); - } - } - void EmitLoadConstFloat(SQFloat value,SQInteger target) - { - if(target < 0) { - target = _fs->PushTarget(); - } - if(sizeof(SQFloat) == sizeof(SQInt32)) { - _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value)); - } - else { - _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); - } - } - void UnaryOP(SQOpcode op) - { - PrefixedExpr(); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(op, _fs->PushTarget(), src); - } - bool NeedGet() - { - switch(_token) { - case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ: - case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: - return false; - case TK_PLUSPLUS: case TK_MINUSMINUS: - if (!IsEndOfStatement()) { - return false; - } - break; - } - return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('[')))); - } - void FunctionCallArgs(bool rawcall = false) - { - SQInteger nargs = 1;//this - while(_token != _SC(')')) { - Expression(); - MoveIfCurrentTargetIsLocal(); - nargs++; - if(_token == _SC(',')){ - Lex(); - if(_token == ')') Error(_SC("expression expected, found ')'")); - } - } - Lex(); - if (rawcall) { - if (nargs < 3) Error(_SC("rawcall requires at least 2 parameters (callee and this)")); - nargs -= 2; //removes callee and this from count - } - for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget(); - SQInteger stackbase = _fs->PopTarget(); - SQInteger closure = _fs->PopTarget(); - _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); - } - void ParseTableOrClass(SQInteger separator,SQInteger terminator) - { - SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; - while(_token != terminator) { - bool hasattrs = false; - bool isstatic = false; - //check if is an attribute - if(separator == ';') { - if(_token == TK_ATTR_OPEN) { - _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex(); - ParseTableOrClass(',',TK_ATTR_CLOSE); - hasattrs = true; - } - if(_token == TK_STATIC) { - isstatic = true; - Lex(); - } - } - switch(_token) { - case TK_FUNCTION: - case TK_CONSTRUCTOR:{ - SQInteger tk = _token; - Lex(); - SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); - Expect(_SC('(')); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - CreateFunction(id); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - } - break; - case _SC('['): - Lex(); CommaExpr(); Expect(_SC(']')); - Expect(_SC('=')); Expression(); - break; - case TK_STRING_LITERAL: //JSON - if(separator == ',') { //only works for tables - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL))); - Expect(_SC(':')); Expression(); - break; - } - default : - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - Expect(_SC('=')); Expression(); - } - if(_token == separator) Lex();//optional comma/semicolon - nkeys++; - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger attrs = hasattrs ? _fs->PopTarget():-1; - ((void)attrs); - assert((hasattrs && (attrs == key-1)) || !hasattrs); - unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); - SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val); - } - else { - _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember - } - } - if(separator == _SC(',')) //hack recognizes a table from the separator - _fs->SetIntructionParam(tpos, 1, nkeys); - Lex(); - } - void LocalDeclStatement() - { - SQObject varname; - Lex(); - if( _token == TK_FUNCTION) { - Lex(); - varname = Expect(TK_IDENTIFIER); - Expect(_SC('(')); - CreateFunction(varname,false); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - _fs->PopTarget(); - _fs->PushLocalVariable(varname); - return; - } + /* generate direct or literal function depending on size */ + SQObjectType ctype = sq_type(constval); + switch(ctype) { + case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break; + case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break; + case OT_BOOL: _fs->AddInstruction(_OP_LOADBOOL, _es.epos, _integer(constval)); break; + default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break; + } + _es.etype = EXPR; + } + else { + /* Handle a non-local variable, aka a field. Push the 'this' pointer on + * the virtual stack (always found in offset 0, so no instruction needs to + * be generated), and push the key next. Generate an _OP_LOAD instruction + * for the latter. If we are not using the variable as a dref expr, generate + * the _OP_GET instruction. + */ + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; + } + return _es.epos; + } + break; + case TK_DOUBLE_COLON: // "::" + _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget()); + _es.etype = OBJECT; + _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/ + _es.epos = -1; + return _es.epos; + break; + case TK_NULL: + _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); + Lex(); + break; + case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break; + case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break; + case TK_TRUE: case TK_FALSE: + _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); + Lex(); + break; + case _SC('['): { + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY); + SQInteger apos = _fs->GetCurrentPos(),key = 0; + Lex(); + while(_token != _SC(']')) { + Expression(); + if(_token == _SC(',')) Lex(); + SQInteger val = _fs->PopTarget(); + SQInteger array = _fs->TopTarget(); + _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK); + key++; + } + _fs->SetIntructionParam(apos, 1, key); + Lex(); + } + break; + case _SC('{'): + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); + Lex();ParseTableOrClass(_SC(','),_SC('}')); + break; + case TK_FUNCTION: FunctionExp(_token);break; + case _SC('@'): FunctionExp(_token,true);break; + case TK_CLASS: Lex(); ClassExp();break; + case _SC('-'): + Lex(); + switch(_token) { + case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break; + case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break; + default: UnaryOP(_OP_NEG); + } + break; + case _SC('!'): Lex(); UnaryOP(_OP_NOT); break; + case _SC('~'): + Lex(); + if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; } + UnaryOP(_OP_BWNOT); + break; + case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break; + case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break; + case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break; + case TK_RAWCALL: Lex(); Expect('('); FunctionCallArgs(true); break; + case TK_MINUSMINUS : + case TK_PLUSPLUS :PrefixIncDec(_token); break; + case TK_DELETE : DeleteExpr(); break; + case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); + break; + case TK___LINE__: EmitLoadConstInt(_lex._currentline,-1); Lex(); break; + case TK___FILE__: _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_sourcename)); Lex(); break; + default: Error(_SC("expression expected")); + } + _es.etype = EXPR; + return -1; + } + void EmitLoadConstInt(SQInteger value,SQInteger target) + { + if(target < 0) { + target = _fs->PushTarget(); + } + if(value <= INT_MAX && value > INT_MIN) { //does it fit in 32 bits? + _fs->AddInstruction(_OP_LOADINT, target,value); + } + else { + _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); + } + } + void EmitLoadConstFloat(SQFloat value,SQInteger target) + { + if(target < 0) { + target = _fs->PushTarget(); + } + if(sizeof(SQFloat) == sizeof(SQInt32)) { + _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value)); + } + else { + _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); + } + } + void UnaryOP(SQOpcode op) + { + PrefixedExpr(); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(op, _fs->PushTarget(), src); + } + bool NeedGet() + { + switch(_token) { + case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ: + case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: + return false; + case TK_PLUSPLUS: case TK_MINUSMINUS: + if (!IsEndOfStatement()) { + return false; + } + break; + } + return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('[')))); + } + void FunctionCallArgs(bool rawcall = false) + { + SQInteger nargs = 1;//this + while(_token != _SC(')')) { + Expression(); + MoveIfCurrentTargetIsLocal(); + nargs++; + if(_token == _SC(',')){ + Lex(); + if(_token == ')') Error(_SC("expression expected, found ')'")); + } + } + Lex(); + if (rawcall) { + if (nargs < 3) Error(_SC("rawcall requires at least 2 parameters (callee and this)")); + nargs -= 2; //removes callee and this from count + } + for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget(); + SQInteger stackbase = _fs->PopTarget(); + SQInteger closure = _fs->PopTarget(); + _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); + } + void ParseTableOrClass(SQInteger separator,SQInteger terminator) + { + SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; + while(_token != terminator) { + bool hasattrs = false; + bool isstatic = false; + //check if is an attribute + if(separator == ';') { + if(_token == TK_ATTR_OPEN) { + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex(); + ParseTableOrClass(',',TK_ATTR_CLOSE); + hasattrs = true; + } + if(_token == TK_STATIC) { + isstatic = true; + Lex(); + } + } + switch(_token) { + case TK_FUNCTION: + case TK_CONSTRUCTOR:{ + SQInteger tk = _token; + Lex(); + SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); + Expect(_SC('(')); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + } + break; + case _SC('['): + Lex(); CommaExpr(); Expect(_SC(']')); + Expect(_SC('=')); Expression(); + break; + case TK_STRING_LITERAL: //JSON + if(separator == ',') { //only works for tables + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL))); + Expect(_SC(':')); Expression(); + break; + } + default : + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + Expect(_SC('=')); Expression(); + } + if(_token == separator) Lex();//optional comma/semicolon + nkeys++; + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger attrs = hasattrs ? _fs->PopTarget():-1; + ((void)attrs); + assert((hasattrs && (attrs == key-1)) || !hasattrs); + unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); + SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val); + } + else { + _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember + } + } + if(separator == _SC(',')) //hack recognizes a table from the separator + _fs->SetIntructionParam(tpos, 1, nkeys); + Lex(); + } + void LocalDeclStatement() + { + SQObject varname; + Lex(); + if( _token == TK_FUNCTION) { + Lex(); + varname = Expect(TK_IDENTIFIER); + Expect(_SC('(')); + CreateFunction(varname,false); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + _fs->PopTarget(); + _fs->PushLocalVariable(varname); + return; + } - do { - varname = Expect(TK_IDENTIFIER); - if(_token == _SC('=')) { - Lex(); Expression(); - SQInteger src = _fs->PopTarget(); - SQInteger dest = _fs->PushTarget(); - if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src); - } - else{ - _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); - } - _fs->PopTarget(); - _fs->PushLocalVariable(varname); - if(_token == _SC(',')) Lex(); else break; - } while(1); - } - void IfBlock() - { - if (_token == _SC('{')) - { - BEGIN_SCOPE(); - Lex(); - Statements(); - Expect(_SC('}')); - if (true) { - END_SCOPE(); - } - else { - END_SCOPE_NO_CLOSE(); - } - } - else { - //BEGIN_SCOPE(); - Statement(); - if (_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); - //END_SCOPE(); - } - } - void IfStatement() - { - SQInteger jmppos; - bool haselse = false; - Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); - SQInteger jnepos = _fs->GetCurrentPos(); + do { + varname = Expect(TK_IDENTIFIER); + if(_token == _SC('=')) { + Lex(); Expression(); + SQInteger src = _fs->PopTarget(); + SQInteger dest = _fs->PushTarget(); + if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src); + } + else{ + _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); + } + _fs->PopTarget(); + _fs->PushLocalVariable(varname); + if(_token == _SC(',')) Lex(); else break; + } while(1); + } + void IfBlock() + { + if (_token == _SC('{')) + { + BEGIN_SCOPE(); + Lex(); + Statements(); + Expect(_SC('}')); + if (true) { + END_SCOPE(); + } + else { + END_SCOPE_NO_CLOSE(); + } + } + else { + //BEGIN_SCOPE(); + Statement(); + if (_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); + //END_SCOPE(); + } + } + void IfStatement() + { + SQInteger jmppos; + bool haselse = false; + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + SQInteger jnepos = _fs->GetCurrentPos(); - IfBlock(); - // - /*static int n = 0; - if (_token != _SC('}') && _token != TK_ELSE) { - printf("IF %d-----------------------!!!!!!!!!\n", n); - if (n == 5) - { - printf("asd"); - } - n++; - //OptionalSemicolon(); - }*/ + IfBlock(); + // + /*static int n = 0; + if (_token != _SC('}') && _token != TK_ELSE) { + printf("IF %d-----------------------!!!!!!!!!\n", n); + if (n == 5) + { + printf("asd"); + } + n++; + //OptionalSemicolon(); + }*/ - SQInteger endifblock = _fs->GetCurrentPos(); - if(_token == TK_ELSE){ - haselse = true; - //BEGIN_SCOPE(); - _fs->AddInstruction(_OP_JMP); - jmppos = _fs->GetCurrentPos(); - Lex(); - //Statement(); if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); - IfBlock(); - //END_SCOPE(); - _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); - } - _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); - } - void WhileStatement() - { - SQInteger jzpos, jmppos; - jmppos = _fs->GetCurrentPos(); - Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + SQInteger endifblock = _fs->GetCurrentPos(); + if(_token == TK_ELSE){ + haselse = true; + //BEGIN_SCOPE(); + _fs->AddInstruction(_OP_JMP); + jmppos = _fs->GetCurrentPos(); + Lex(); + //Statement(); if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); + IfBlock(); + //END_SCOPE(); + _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); + } + _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); + } + void WhileStatement() + { + SQInteger jzpos, jmppos; + jmppos = _fs->GetCurrentPos(); + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - BEGIN_BREAKBLE_BLOCK(); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); - jzpos = _fs->GetCurrentPos(); - BEGIN_SCOPE(); + BEGIN_BREAKBLE_BLOCK(); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + jzpos = _fs->GetCurrentPos(); + BEGIN_SCOPE(); - Statement(); - - END_SCOPE(); - _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); - _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - - END_BREAKBLE_BLOCK(jmppos); - } - void DoWhileStatement() - { - Lex(); - SQInteger jmptrg = _fs->GetCurrentPos(); - BEGIN_BREAKBLE_BLOCK() - BEGIN_SCOPE(); - Statement(); - END_SCOPE(); - Expect(TK_WHILE); - SQInteger continuetrg = _fs->GetCurrentPos(); - Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1); - _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1); - END_BREAKBLE_BLOCK(continuetrg); - } - void ForStatement() - { - Lex(); - BEGIN_SCOPE(); - Expect(_SC('(')); - if(_token == TK_LOCAL) LocalDeclStatement(); - else if(_token != _SC(';')){ - CommaExpr(); - _fs->PopTarget(); - } - Expect(_SC(';')); - _fs->SnoozeOpt(); - SQInteger jmppos = _fs->GetCurrentPos(); - SQInteger jzpos = -1; - if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); } - Expect(_SC(';')); - _fs->SnoozeOpt(); - SQInteger expstart = _fs->GetCurrentPos() + 1; - if(_token != _SC(')')) { - CommaExpr(); - _fs->PopTarget(); - } - Expect(_SC(')')); - _fs->SnoozeOpt(); - SQInteger expend = _fs->GetCurrentPos(); - SQInteger expsize = (expend - expstart) + 1; - SQInstructionVec exp; - if(expsize > 0) { - for(SQInteger i = 0; i < expsize; i++) - exp.push_back(_fs->GetInstruction(expstart + i)); - _fs->PopInstructions(expsize); - } - BEGIN_BREAKBLE_BLOCK() - Statement(); - SQInteger continuetrg = _fs->GetCurrentPos(); - if(expsize > 0) { - for(SQInteger i = 0; i < expsize; i++) - _fs->AddInstruction(exp[i]); - } - _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); - if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - - END_BREAKBLE_BLOCK(continuetrg); + Statement(); END_SCOPE(); - } - void ForEachStatement() - { - SQObject idxname, valname; - Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER); - if(_token == _SC(',')) { - idxname = valname; - Lex(); valname = Expect(TK_IDENTIFIER); - } - else{ - idxname = _fs->CreateString(_SC("@INDEX@")); - } - Expect(TK_IN); + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); + _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - //save the stack size - BEGIN_SCOPE(); - //put the table in the stack(evaluate the table expression) - Expression(); Expect(_SC(')')); - SQInteger container = _fs->TopTarget(); - //push the index local var - SQInteger indexpos = _fs->PushLocalVariable(idxname); - _fs->AddInstruction(_OP_LOADNULLS, indexpos,1); - //push the value local var - SQInteger valuepos = _fs->PushLocalVariable(valname); - _fs->AddInstruction(_OP_LOADNULLS, valuepos,1); - //push reference index - SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible - _fs->AddInstruction(_OP_LOADNULLS, itrpos,1); - SQInteger jmppos = _fs->GetCurrentPos(); - _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos); - SQInteger foreachpos = _fs->GetCurrentPos(); - _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos); - //generate the statement code - BEGIN_BREAKBLE_BLOCK() - Statement(); - _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); - _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); - _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos); - END_BREAKBLE_BLOCK(foreachpos - 1); - //restore the local variable stack(remove index,val and ref idx) - _fs->PopTarget(); - END_SCOPE(); - } - void SwitchStatement() - { - Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - Expect(_SC('{')); - SQInteger expr = _fs->TopTarget(); - bool bfirst = true; - SQInteger tonextcondjmp = -1; - SQInteger skipcondjmp = -1; - SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); - _fs->_breaktargets.push_back(0); - while(_token == TK_CASE) { - if(!bfirst) { - _fs->AddInstruction(_OP_JMP, 0, 0); - skipcondjmp = _fs->GetCurrentPos(); - _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); - } - //condition - Lex(); Expression(); Expect(_SC(':')); - SQInteger trg = _fs->PopTarget(); - SQInteger eqtarget = trg; - bool local = _fs->IsLocal(trg); - if(local) { - eqtarget = _fs->PushTarget(); //we need to allocate a extra reg - } - _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr); - _fs->AddInstruction(_OP_JZ, eqtarget, 0); - if(local) { - _fs->PopTarget(); - } + END_BREAKBLE_BLOCK(jmppos); + } + void DoWhileStatement() + { + Lex(); + SQInteger jmptrg = _fs->GetCurrentPos(); + BEGIN_BREAKBLE_BLOCK() + BEGIN_SCOPE(); + Statement(); + END_SCOPE(); + Expect(TK_WHILE); + SQInteger continuetrg = _fs->GetCurrentPos(); + Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1); + _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1); + END_BREAKBLE_BLOCK(continuetrg); + } + void ForStatement() + { + Lex(); + BEGIN_SCOPE(); + Expect(_SC('(')); + if(_token == TK_LOCAL) LocalDeclStatement(); + else if(_token != _SC(';')){ + CommaExpr(); + _fs->PopTarget(); + } + Expect(_SC(';')); + _fs->SnoozeOpt(); + SQInteger jmppos = _fs->GetCurrentPos(); + SQInteger jzpos = -1; + if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); } + Expect(_SC(';')); + _fs->SnoozeOpt(); + SQInteger expstart = _fs->GetCurrentPos() + 1; + if(_token != _SC(')')) { + CommaExpr(); + _fs->PopTarget(); + } + Expect(_SC(')')); + _fs->SnoozeOpt(); + SQInteger expend = _fs->GetCurrentPos(); + SQInteger expsize = (expend - expstart) + 1; + SQInstructionVec exp; + if(expsize > 0) { + for(SQInteger i = 0; i < expsize; i++) + exp.push_back(_fs->GetInstruction(expstart + i)); + _fs->PopInstructions(expsize); + } + BEGIN_BREAKBLE_BLOCK() + Statement(); + SQInteger continuetrg = _fs->GetCurrentPos(); + if(expsize > 0) { + for(SQInteger i = 0; i < expsize; i++) + _fs->AddInstruction(exp[i]); + } + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); + if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); + + END_BREAKBLE_BLOCK(continuetrg); - //end condition - if(skipcondjmp != -1) { - _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); - } - tonextcondjmp = _fs->GetCurrentPos(); - BEGIN_SCOPE(); - Statements(); - END_SCOPE(); - bfirst = false; - } - if(tonextcondjmp != -1) - _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); - if(_token == TK_DEFAULT) { - Lex(); Expect(_SC(':')); - BEGIN_SCOPE(); - Statements(); - END_SCOPE(); - } - Expect(_SC('}')); - _fs->PopTarget(); - __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; - if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); - _fs->_breaktargets.pop_back(); - } - void FunctionStatement() - { - SQObject id; - Lex(); id = Expect(TK_IDENTIFIER); - _fs->PushTarget(0); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); + END_SCOPE(); + } + void ForEachStatement() + { + SQObject idxname, valname; + Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER); + if(_token == _SC(',')) { + idxname = valname; + Lex(); valname = Expect(TK_IDENTIFIER); + } + else{ + idxname = _fs->CreateString(_SC("@INDEX@")); + } + Expect(TK_IN); - while(_token == TK_DOUBLE_COLON) { - Lex(); - id = Expect(TK_IDENTIFIER); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); - } - Expect(_SC('(')); - CreateFunction(id); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - EmitDerefOp(_OP_NEWSLOT); - _fs->PopTarget(); - } - void ClassStatement() - { - SQExpState es; - Lex(); - es = _es; - _es.donot_get = true; - PrefixedExpr(); - if(_es.etype == EXPR) { - Error(_SC("invalid class name")); - } - else if(_es.etype == OBJECT || _es.etype == BASE) { - ClassExp(); - EmitDerefOp(_OP_NEWSLOT); - _fs->PopTarget(); - } - else { - Error(_SC("cannot create a class in a local with the syntax(class )")); - } - _es = es; - } - SQObject ExpectScalar() - { - SQObject val; - val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x - switch(_token) { - case TK_INTEGER: - val._type = OT_INTEGER; - val._unVal.nInteger = _lex._nvalue; - break; - case TK_FLOAT: - val._type = OT_FLOAT; - val._unVal.fFloat = _lex._fvalue; - break; - case TK_STRING_LITERAL: - val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); - break; - case TK_TRUE: - case TK_FALSE: - val._type = OT_BOOL; - val._unVal.nInteger = _token == TK_TRUE ? 1 : 0; - break; - case '-': - Lex(); - switch(_token) - { - case TK_INTEGER: - val._type = OT_INTEGER; - val._unVal.nInteger = -_lex._nvalue; - break; - case TK_FLOAT: - val._type = OT_FLOAT; - val._unVal.fFloat = -_lex._fvalue; - break; - default: - Error(_SC("scalar expected : integer, float")); - } - break; - default: - Error(_SC("scalar expected : integer, float, or string")); - } - Lex(); - return val; - } - void EnumStatement() - { - Lex(); - SQObject id = Expect(TK_IDENTIFIER); - Expect(_SC('{')); + //save the stack size + BEGIN_SCOPE(); + //put the table in the stack(evaluate the table expression) + Expression(); Expect(_SC(')')); + SQInteger container = _fs->TopTarget(); + //push the index local var + SQInteger indexpos = _fs->PushLocalVariable(idxname); + _fs->AddInstruction(_OP_LOADNULLS, indexpos,1); + //push the value local var + SQInteger valuepos = _fs->PushLocalVariable(valname); + _fs->AddInstruction(_OP_LOADNULLS, valuepos,1); + //push reference index + SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible + _fs->AddInstruction(_OP_LOADNULLS, itrpos,1); + SQInteger jmppos = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos); + SQInteger foreachpos = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos); + //generate the statement code + BEGIN_BREAKBLE_BLOCK() + Statement(); + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); + _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); + _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos); + END_BREAKBLE_BLOCK(foreachpos - 1); + //restore the local variable stack(remove index,val and ref idx) + _fs->PopTarget(); + END_SCOPE(); + } + void SwitchStatement() + { + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + Expect(_SC('{')); + SQInteger expr = _fs->TopTarget(); + bool bfirst = true; + SQInteger tonextcondjmp = -1; + SQInteger skipcondjmp = -1; + SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); + _fs->_breaktargets.push_back(0); + while(_token == TK_CASE) { + if(!bfirst) { + _fs->AddInstruction(_OP_JMP, 0, 0); + skipcondjmp = _fs->GetCurrentPos(); + _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); + } + //condition + Lex(); Expression(); Expect(_SC(':')); + SQInteger trg = _fs->PopTarget(); + SQInteger eqtarget = trg; + bool local = _fs->IsLocal(trg); + if(local) { + eqtarget = _fs->PushTarget(); //we need to allocate a extra reg + } + _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr); + _fs->AddInstruction(_OP_JZ, eqtarget, 0); + if(local) { + _fs->PopTarget(); + } - SQObject table = _fs->CreateTable(); - SQInteger nval = 0; - while(_token != _SC('}')) { - SQObject key = Expect(TK_IDENTIFIER); - SQObject val; - if(_token == _SC('=')) { - Lex(); - val = ExpectScalar(); - } - else { - val._type = OT_INTEGER; - val._unVal.nInteger = nval++; - } - _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val)); - if(_token == ',') Lex(); - } - SQTable *enums = _table(_ss(_vm)->_consts); - SQObjectPtr strongid = id; - enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table)); - strongid.Null(); - Lex(); - } - void TryCatchStatement() - { - SQObject exid; - Lex(); - _fs->AddInstruction(_OP_PUSHTRAP,0,0); - _fs->_traps++; - if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; - if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; - SQInteger trappos = _fs->GetCurrentPos(); - { - BEGIN_SCOPE(); - Statement(); - END_SCOPE(); - } - _fs->_traps--; - _fs->AddInstruction(_OP_POPTRAP, 1, 0); - if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; - if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--; - _fs->AddInstruction(_OP_JMP, 0, 0); - SQInteger jmppos = _fs->GetCurrentPos(); - _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); - Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); - { - BEGIN_SCOPE(); - SQInteger ex_target = _fs->PushLocalVariable(exid); - _fs->SetIntructionParam(trappos, 0, ex_target); - Statement(); - _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); - END_SCOPE(); - } - } - void FunctionExp(SQInteger ftype,bool lambda = false) - { - Lex(); Expect(_SC('(')); - SQObjectPtr dummy; - CreateFunction(dummy,lambda); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); - } - void ClassExp() - { - SQInteger base = -1; - SQInteger attrs = -1; - if(_token == TK_EXTENDS) { - Lex(); Expression(); - base = _fs->TopTarget(); - } - if(_token == TK_ATTR_OPEN) { - Lex(); - _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); - ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); - attrs = _fs->TopTarget(); - } - Expect(_SC('{')); - if(attrs != -1) _fs->PopTarget(); - if(base != -1) _fs->PopTarget(); - _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS); - ParseTableOrClass(_SC(';'),_SC('}')); - } - void DeleteExpr() - { - SQExpState es; - Lex(); - es = _es; - _es.donot_get = true; - PrefixedExpr(); - if(_es.etype==EXPR) Error(_SC("can't delete an expression")); - if(_es.etype==OBJECT || _es.etype==BASE) { - Emit2ArgsOP(_OP_DELETE); - } - else { - Error(_SC("cannot delete an (outer) local")); - } - _es = es; - } - void PrefixIncDec(SQInteger token) - { - SQExpState es; - SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1; - Lex(); - es = _es; - _es.donot_get = true; - PrefixedExpr(); - if(_es.etype==EXPR) { - Error(_SC("can't '++' or '--' an expression")); - } - else if(_es.etype==OBJECT || _es.etype==BASE) { - Emit2ArgsOP(_OP_INC, diff); - } - else if(_es.etype==LOCAL) { - SQInteger src = _fs->TopTarget(); - _fs->AddInstruction(_OP_INCL, src, src, 0, diff); + //end condition + if(skipcondjmp != -1) { + _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); + } + tonextcondjmp = _fs->GetCurrentPos(); + BEGIN_SCOPE(); + Statements(); + END_SCOPE(); + bfirst = false; + } + if(tonextcondjmp != -1) + _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); + if(_token == TK_DEFAULT) { + Lex(); Expect(_SC(':')); + BEGIN_SCOPE(); + Statements(); + END_SCOPE(); + } + Expect(_SC('}')); + _fs->PopTarget(); + __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; + if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); + _fs->_breaktargets.pop_back(); + } + void FunctionStatement() + { + SQObject id; + Lex(); id = Expect(TK_IDENTIFIER); + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); - } - else if(_es.etype==OUTER) { - SQInteger tmp = _fs->PushTarget(); - _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos); - _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff); - _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp); - } - _es = es; - } - void CreateFunction(SQObject &name,bool lambda = false) - { - SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); - funcstate->_name = name; - SQObject paramname; - funcstate->AddParameter(_fs->CreateString(_SC("this"))); - funcstate->_sourcename = _sourcename; - SQInteger defparams = 0; - while(_token!=_SC(')')) { - if(_token == TK_VARPARAMS) { - if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters")); - funcstate->AddParameter(_fs->CreateString(_SC("vargv"))); - funcstate->_varparams = true; - Lex(); - if(_token != _SC(')')) Error(_SC("expected ')'")); - break; - } - else { - paramname = Expect(TK_IDENTIFIER); - funcstate->AddParameter(paramname); - if(_token == _SC('=')) { - Lex(); - Expression(); - funcstate->AddDefaultParam(_fs->TopTarget()); - defparams++; - } - else { - if(defparams > 0) Error(_SC("expected '='")); - } - if(_token == _SC(',')) Lex(); - else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); - } - } - Expect(_SC(')')); - for(SQInteger n = 0; n < defparams; n++) { - _fs->PopTarget(); - } + while(_token == TK_DOUBLE_COLON) { + Lex(); + id = Expect(TK_IDENTIFIER); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); + } + Expect(_SC('(')); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + EmitDerefOp(_OP_NEWSLOT); + _fs->PopTarget(); + } + void ClassStatement() + { + SQExpState es; + Lex(); + es = _es; + _es.donot_get = true; + PrefixedExpr(); + if(_es.etype == EXPR) { + Error(_SC("invalid class name")); + } + else if(_es.etype == OBJECT || _es.etype == BASE) { + ClassExp(); + EmitDerefOp(_OP_NEWSLOT); + _fs->PopTarget(); + } + else { + Error(_SC("cannot create a class in a local with the syntax(class )")); + } + _es = es; + } + SQObject ExpectScalar() + { + SQObject val; + val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x + switch(_token) { + case TK_INTEGER: + val._type = OT_INTEGER; + val._unVal.nInteger = _lex._nvalue; + break; + case TK_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = _lex._fvalue; + break; + case TK_STRING_LITERAL: + val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); + break; + case TK_TRUE: + case TK_FALSE: + val._type = OT_BOOL; + val._unVal.nInteger = _token == TK_TRUE ? 1 : 0; + break; + case '-': + Lex(); + switch(_token) + { + case TK_INTEGER: + val._type = OT_INTEGER; + val._unVal.nInteger = -_lex._nvalue; + break; + case TK_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = -_lex._fvalue; + break; + default: + Error(_SC("scalar expected : integer, float")); + } + break; + default: + Error(_SC("scalar expected : integer, float, or string")); + } + Lex(); + return val; + } + void EnumStatement() + { + Lex(); + SQObject id = Expect(TK_IDENTIFIER); + Expect(_SC('{')); - SQFuncState *currchunk = _fs; - _fs = funcstate; - if(lambda) { - Expression(); - _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());} - else { - Statement(false); - } - funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); - funcstate->AddInstruction(_OP_RETURN, -1); - funcstate->SetStackSize(0); + SQObject table = _fs->CreateTable(); + SQInteger nval = 0; + while(_token != _SC('}')) { + SQObject key = Expect(TK_IDENTIFIER); + SQObject val; + if(_token == _SC('=')) { + Lex(); + val = ExpectScalar(); + } + else { + val._type = OT_INTEGER; + val._unVal.nInteger = nval++; + } + _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val)); + if(_token == ',') Lex(); + } + SQTable *enums = _table(_ss(_vm)->_consts); + SQObjectPtr strongid = id; + enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table)); + strongid.Null(); + Lex(); + } + void TryCatchStatement() + { + SQObject exid; + Lex(); + _fs->AddInstruction(_OP_PUSHTRAP,0,0); + _fs->_traps++; + if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; + if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; + SQInteger trappos = _fs->GetCurrentPos(); + { + BEGIN_SCOPE(); + Statement(); + END_SCOPE(); + } + _fs->_traps--; + _fs->AddInstruction(_OP_POPTRAP, 1, 0); + if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; + if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--; + _fs->AddInstruction(_OP_JMP, 0, 0); + SQInteger jmppos = _fs->GetCurrentPos(); + _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); + Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); + { + BEGIN_SCOPE(); + SQInteger ex_target = _fs->PushLocalVariable(exid); + _fs->SetIntructionParam(trappos, 0, ex_target); + Statement(); + _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); + END_SCOPE(); + } + } + void FunctionExp(SQInteger ftype,bool lambda = false) + { + Lex(); Expect(_SC('(')); + SQObjectPtr dummy; + CreateFunction(dummy,lambda); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); + } + void ClassExp() + { + SQInteger base = -1; + SQInteger attrs = -1; + if(_token == TK_EXTENDS) { + Lex(); Expression(); + base = _fs->TopTarget(); + } + if(_token == TK_ATTR_OPEN) { + Lex(); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); + ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); + attrs = _fs->TopTarget(); + } + Expect(_SC('{')); + if(attrs != -1) _fs->PopTarget(); + if(base != -1) _fs->PopTarget(); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS); + ParseTableOrClass(_SC(';'),_SC('}')); + } + void DeleteExpr() + { + SQExpState es; + Lex(); + es = _es; + _es.donot_get = true; + PrefixedExpr(); + if(_es.etype==EXPR) Error(_SC("can't delete an expression")); + if(_es.etype==OBJECT || _es.etype==BASE) { + Emit2ArgsOP(_OP_DELETE); + } + else { + Error(_SC("cannot delete an (outer) local")); + } + _es = es; + } + void PrefixIncDec(SQInteger token) + { + SQExpState es; + SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1; + Lex(); + es = _es; + _es.donot_get = true; + PrefixedExpr(); + if(_es.etype==EXPR) { + Error(_SC("can't '++' or '--' an expression")); + } + else if(_es.etype==OBJECT || _es.etype==BASE) { + Emit2ArgsOP(_OP_INC, diff); + } + else if(_es.etype==LOCAL) { + SQInteger src = _fs->TopTarget(); + _fs->AddInstruction(_OP_INCL, src, src, 0, diff); - SQFunctionProto *func = funcstate->BuildProto(); + } + else if(_es.etype==OUTER) { + SQInteger tmp = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos); + _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff); + _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp); + } + _es = es; + } + void CreateFunction(SQObject &name,bool lambda = false) + { + SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); + funcstate->_name = name; + SQObject paramname; + funcstate->AddParameter(_fs->CreateString(_SC("this"))); + funcstate->_sourcename = _sourcename; + SQInteger defparams = 0; + while(_token!=_SC(')')) { + if(_token == TK_VARPARAMS) { + if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters")); + funcstate->AddParameter(_fs->CreateString(_SC("vargv"))); + funcstate->_varparams = true; + Lex(); + if(_token != _SC(')')) Error(_SC("expected ')'")); + break; + } + else { + paramname = Expect(TK_IDENTIFIER); + funcstate->AddParameter(paramname); + if(_token == _SC('=')) { + Lex(); + Expression(); + funcstate->AddDefaultParam(_fs->TopTarget()); + defparams++; + } + else { + if(defparams > 0) Error(_SC("expected '='")); + } + if(_token == _SC(',')) Lex(); + else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); + } + } + Expect(_SC(')')); + for(SQInteger n = 0; n < defparams; n++) { + _fs->PopTarget(); + } + + SQFuncState *currchunk = _fs; + _fs = funcstate; + if(lambda) { + Expression(); + _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());} + else { + Statement(false); + } + funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); + funcstate->AddInstruction(_OP_RETURN, -1); + funcstate->SetStackSize(0); + + SQFunctionProto *func = funcstate->BuildProto(); #ifdef _DEBUG_DUMP - funcstate->Dump(func); + funcstate->Dump(func); #endif - _fs = currchunk; - _fs->_functions.push_back(func); - _fs->PopChildState(); - } - void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) - { - while(ntoresolve > 0) { - SQInteger pos = funcstate->_unresolvedbreaks.back(); - funcstate->_unresolvedbreaks.pop_back(); - //set the jmp instruction - funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0); - ntoresolve--; - } - } - void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos) - { - while(ntoresolve > 0) { - SQInteger pos = funcstate->_unresolvedcontinues.back(); - funcstate->_unresolvedcontinues.pop_back(); - //set the jmp instruction - funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0); - ntoresolve--; - } - } + _fs = currchunk; + _fs->_functions.push_back(func); + _fs->PopChildState(); + } + void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) + { + while(ntoresolve > 0) { + SQInteger pos = funcstate->_unresolvedbreaks.back(); + funcstate->_unresolvedbreaks.pop_back(); + //set the jmp instruction + funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0); + ntoresolve--; + } + } + void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos) + { + while(ntoresolve > 0) { + SQInteger pos = funcstate->_unresolvedcontinues.back(); + funcstate->_unresolvedcontinues.pop_back(); + //set the jmp instruction + funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0); + ntoresolve--; + } + } private: - SQInteger _token; - SQFuncState *_fs; - SQObjectPtr _sourcename; - SQLexer _lex; - bool _lineinfo; - bool _raiseerror; - SQInteger _debugline; - SQInteger _debugop; - SQExpState _es; - SQScope _scope; - SQChar _compilererror[MAX_COMPILER_ERROR_LEN]; - jmp_buf _errorjmp; - SQVM *_vm; + SQInteger _token; + SQFuncState *_fs; + SQObjectPtr _sourcename; + SQLexer _lex; + bool _lineinfo; + bool _raiseerror; + SQInteger _debugline; + SQInteger _debugop; + SQExpState _es; + SQScope _scope; + SQChar _compilererror[MAX_COMPILER_ERROR_LEN]; + jmp_buf _errorjmp; + SQVM *_vm; }; bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo) { - SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo); - return p.Compile(out); + SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo); + return p.Compile(out); } #endif diff --git a/rabbit/sqcompiler.hpp b/rabbit/sqcompiler.hpp index 380d8f1..b63d825 100644 --- a/rabbit/sqcompiler.hpp +++ b/rabbit/sqcompiler.hpp @@ -12,7 +12,7 @@ struct SQVM; #define TK_IDENTIFIER 258 #define TK_STRING_LITERAL 259 #define TK_INTEGER 260 -#define TK_FLOAT 261 +#define TK_FLOAT 261 #define TK_BASE 262 #define TK_DELETE 263 #define TK_EQ 264 @@ -20,13 +20,13 @@ struct SQVM; #define TK_LE 266 #define TK_GE 267 #define TK_SWITCH 268 -#define TK_ARROW 269 +#define TK_ARROW 269 #define TK_AND 270 #define TK_OR 271 #define TK_IF 272 #define TK_ELSE 273 -#define TK_WHILE 274 -#define TK_BREAK 275 +#define TK_WHILE 274 +#define TK_BREAK 275 #define TK_FOR 276 #define TK_DO 277 #define TK_NULL 278 @@ -34,8 +34,8 @@ struct SQVM; #define TK_IN 280 #define TK_NEWSLOT 281 #define TK_MODULO 282 -#define TK_LOCAL 283 -#define TK_CLONE 284 +#define TK_LOCAL 283 +#define TK_CLONE 284 #define TK_FUNCTION 285 #define TK_RETURN 286 #define TK_TYPEOF 287 diff --git a/rabbit/sqconfig.hpp b/rabbit/sqconfig.hpp index baaee56..22b37d0 100644 --- a/rabbit/sqconfig.hpp +++ b/rabbit/sqconfig.hpp @@ -67,23 +67,23 @@ typedef SQInteger SQRESULT; typedef wchar_t SQChar; -#define scstrcmp wcscmp +#define scstrcmp wcscmp #ifdef _WIN32 #define scsprintf _snwprintf #else #define scsprintf swprintf #endif -#define scstrlen wcslen -#define scstrtod wcstod +#define scstrlen wcslen +#define scstrtod wcstod #ifdef _SQ64 -#define scstrtol wcstoll +#define scstrtol wcstoll #else -#define scstrtol wcstol +#define scstrtol wcstol #endif #define scstrtoul wcstoul #define scvsprintf vswprintf -#define scstrstr wcsstr -#define scprintf wprintf +#define scstrstr wcsstr +#define scprintf wprintf #ifdef _WIN32 #define WCHAR_SIZE 2 @@ -112,26 +112,26 @@ typedef wchar_t SQChar; #else typedef char SQChar; #define _SC(a) a -#define scstrcmp strcmp +#define scstrcmp strcmp #ifdef _MSC_VER #define scsprintf _snprintf #else #define scsprintf snprintf #endif -#define scstrlen strlen -#define scstrtod strtod +#define scstrlen strlen +#define scstrtod strtod #ifdef _SQ64 #ifdef _MSC_VER -#define scstrtol _strtoi64 +#define scstrtol _strtoi64 #else -#define scstrtol strtoll +#define scstrtol strtoll #endif #else -#define scstrtol strtol +#define scstrtol strtol #endif #define scstrtoul strtoul #define scvsprintf vsnprintf -#define scstrstr strstr +#define scstrstr strstr #define scisspace isspace #define scisdigit isdigit #define scisprint isprint @@ -139,7 +139,7 @@ typedef char SQChar; #define sciscntrl iscntrl #define scisalpha isalpha #define scisalnum isalnum -#define scprintf printf +#define scprintf printf #define MAX_CHAR 0xFF #define sq_rsl(l) (l) diff --git a/rabbit/sqdebug.cpp b/rabbit/sqdebug.cpp index 6b70387..25bfc28 100644 --- a/rabbit/sqdebug.cpp +++ b/rabbit/sqdebug.cpp @@ -15,109 +15,109 @@ SQRESULT sq_getfunctioninfo(HRABBITVM v,SQInteger level,SQFunctionInfo *fi) { - SQInteger cssize = v->_callsstacksize; - if (cssize > level) { - SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; - if(sq_isclosure(ci._closure)) { - SQClosure *c = _closure(ci._closure); - SQFunctionProto *proto = c->_function; - fi->funcid = proto; - fi->name = sq_type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown"); - fi->source = sq_type(proto->_sourcename) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown"); - fi->line = proto->_lineinfos[0]._line; - return SQ_OK; - } - } - return sq_throwerror(v,_SC("the object is not a closure")); + SQInteger cssize = v->_callsstacksize; + if (cssize > level) { + SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; + if(sq_isclosure(ci._closure)) { + SQClosure *c = _closure(ci._closure); + SQFunctionProto *proto = c->_function; + fi->funcid = proto; + fi->name = sq_type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown"); + fi->source = sq_type(proto->_sourcename) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown"); + fi->line = proto->_lineinfos[0]._line; + return SQ_OK; + } + } + return sq_throwerror(v,_SC("the object is not a closure")); } SQRESULT sq_stackinfos(HRABBITVM v, SQInteger level, SQStackInfos *si) { - SQInteger cssize = v->_callsstacksize; - if (cssize > level) { - memset(si, 0, sizeof(SQStackInfos)); - SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; - switch (sq_type(ci._closure)) { - case OT_CLOSURE:{ - SQFunctionProto *func = _closure(ci._closure)->_function; - if (sq_type(func->_name) == OT_STRING) - si->funcname = _stringval(func->_name); - if (sq_type(func->_sourcename) == OT_STRING) - si->source = _stringval(func->_sourcename); - si->line = func->GetLine(ci._ip); - } - break; - case OT_NATIVECLOSURE: - si->source = _SC("NATIVE"); - si->funcname = _SC("unknown"); - if(sq_type(_nativeclosure(ci._closure)->_name) == OT_STRING) - si->funcname = _stringval(_nativeclosure(ci._closure)->_name); - si->line = -1; - break; - default: break; //shutup compiler - } - return SQ_OK; - } - return SQ_ERROR; + SQInteger cssize = v->_callsstacksize; + if (cssize > level) { + memset(si, 0, sizeof(SQStackInfos)); + SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; + switch (sq_type(ci._closure)) { + case OT_CLOSURE:{ + SQFunctionProto *func = _closure(ci._closure)->_function; + if (sq_type(func->_name) == OT_STRING) + si->funcname = _stringval(func->_name); + if (sq_type(func->_sourcename) == OT_STRING) + si->source = _stringval(func->_sourcename); + si->line = func->GetLine(ci._ip); + } + break; + case OT_NATIVECLOSURE: + si->source = _SC("NATIVE"); + si->funcname = _SC("unknown"); + if(sq_type(_nativeclosure(ci._closure)->_name) == OT_STRING) + si->funcname = _stringval(_nativeclosure(ci._closure)->_name); + si->line = -1; + break; + default: break; //shutup compiler + } + return SQ_OK; + } + return SQ_ERROR; } void SQVM::Raise_Error(const SQChar *s, ...) { - va_list vl; - va_start(vl, s); - SQInteger buffersize = (SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2); - scvsprintf(_sp(sq_rsl(buffersize)),buffersize, s, vl); - va_end(vl); - _lasterror = SQString::Create(_ss(this),_spval,-1); + va_list vl; + va_start(vl, s); + SQInteger buffersize = (SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2); + scvsprintf(_sp(sq_rsl(buffersize)),buffersize, s, vl); + va_end(vl); + _lasterror = SQString::Create(_ss(this),_spval,-1); } void SQVM::Raise_Error(const SQObjectPtr &desc) { - _lasterror = desc; + _lasterror = desc; } SQString *SQVM::PrintObjVal(const SQObjectPtr &o) { - switch(sq_type(o)) { - case OT_STRING: return _string(o); - case OT_INTEGER: - scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR), _PRINT_INT_FMT, _integer(o)); - return SQString::Create(_ss(this), _spval); - break; - case OT_FLOAT: - scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)), sq_rsl(NUMBER_MAX_CHAR), _SC("%.14g"), _float(o)); - return SQString::Create(_ss(this), _spval); - break; - default: - return SQString::Create(_ss(this), GetTypeName(o)); - } + switch(sq_type(o)) { + case OT_STRING: return _string(o); + case OT_INTEGER: + scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR), _PRINT_INT_FMT, _integer(o)); + return SQString::Create(_ss(this), _spval); + break; + case OT_FLOAT: + scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)), sq_rsl(NUMBER_MAX_CHAR), _SC("%.14g"), _float(o)); + return SQString::Create(_ss(this), _spval); + break; + default: + return SQString::Create(_ss(this), GetTypeName(o)); + } } void SQVM::Raise_IdxError(const SQObjectPtr &o) { - SQObjectPtr oval = PrintObjVal(o); - Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); + SQObjectPtr oval = PrintObjVal(o); + Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); } void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2) { - SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); - Raise_Error(_SC("comparison between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); + SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); + Raise_Error(_SC("comparison between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); } void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type) { - SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1); - SQInteger found = 0; - for(SQInteger i=0; i<16; i++) - { - SQInteger mask = ((SQInteger)1) << i; - if(typemask & (mask)) { - if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes); - found ++; - StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes); - } - } - Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)); + SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1); + SQInteger found = 0; + for(SQInteger i=0; i<16; i++) + { + SQInteger mask = ((SQInteger)1) << i; + if(typemask & (mask)) { + if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes); + found ++; + StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes); + } + } + Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)); } diff --git a/rabbit/sqfuncproto.hpp b/rabbit/sqfuncproto.hpp index 079d6ff..0790863 100644 --- a/rabbit/sqfuncproto.hpp +++ b/rabbit/sqfuncproto.hpp @@ -10,45 +10,45 @@ #include enum SQOuterType { - otLOCAL = 0, - otOUTER = 1 + otLOCAL = 0, + otOUTER = 1 }; struct SQOuterVar { - SQOuterVar(){} - SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t) - { - _name = name; - _src=src; - _type=t; - } - SQOuterVar(const SQOuterVar &ov) - { - _type=ov._type; - _src=ov._src; - _name=ov._name; - } - SQOuterType _type; - SQObjectPtr _name; - SQObjectPtr _src; + SQOuterVar(){} + SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t) + { + _name = name; + _src=src; + _type=t; + } + SQOuterVar(const SQOuterVar &ov) + { + _type=ov._type; + _src=ov._src; + _name=ov._name; + } + SQOuterType _type; + SQObjectPtr _name; + SQObjectPtr _src; }; struct SQLocalVarInfo { - SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){} - SQLocalVarInfo(const SQLocalVarInfo &lvi) - { - _name=lvi._name; - _start_op=lvi._start_op; - _end_op=lvi._end_op; - _pos=lvi._pos; - } - SQObjectPtr _name; - SQUnsignedInteger _start_op; - SQUnsignedInteger _end_op; - SQUnsignedInteger _pos; + SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){} + SQLocalVarInfo(const SQLocalVarInfo &lvi) + { + _name=lvi._name; + _start_op=lvi._start_op; + _end_op=lvi._end_op; + _pos=lvi._pos; + } + SQObjectPtr _name; + SQUnsignedInteger _start_op; + SQUnsignedInteger _end_op; + SQUnsignedInteger _pos; }; struct SQLineInfo { SQInteger _line;SQInteger _op; }; @@ -58,95 +58,95 @@ typedef sqvector SQLocalVarInfoVec; typedef sqvector SQLineInfoVec; #define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \ - +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \ - +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \ - +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \ - +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger))) + +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \ + +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \ + +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \ + +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger))) struct SQFunctionProto : public CHAINABLE_OBJ { private: - SQFunctionProto(SQSharedState *ss); - ~SQFunctionProto(); + SQFunctionProto(SQSharedState *ss); + ~SQFunctionProto(); public: - static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions, - SQInteger nliterals,SQInteger nparameters, - SQInteger nfunctions,SQInteger noutervalues, - SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams) - { - SQFunctionProto *f; - //I compact the whole class and members in a single memory allocation - f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams)); - new (f) SQFunctionProto(ss); - f->_ninstructions = ninstructions; - f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions]; - f->_nliterals = nliterals; - f->_parameters = (SQObjectPtr*)&f->_literals[nliterals]; - f->_nparameters = nparameters; - f->_functions = (SQObjectPtr*)&f->_parameters[nparameters]; - f->_nfunctions = nfunctions; - f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions]; - f->_noutervalues = noutervalues; - f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues]; - f->_nlineinfos = nlineinfos; - f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos]; - f->_nlocalvarinfos = nlocalvarinfos; - f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos]; - f->_ndefaultparams = ndefaultparams; + static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions, + SQInteger nliterals,SQInteger nparameters, + SQInteger nfunctions,SQInteger noutervalues, + SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams) + { + SQFunctionProto *f; + //I compact the whole class and members in a single memory allocation + f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams)); + new (f) SQFunctionProto(ss); + f->_ninstructions = ninstructions; + f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions]; + f->_nliterals = nliterals; + f->_parameters = (SQObjectPtr*)&f->_literals[nliterals]; + f->_nparameters = nparameters; + f->_functions = (SQObjectPtr*)&f->_parameters[nparameters]; + f->_nfunctions = nfunctions; + f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions]; + f->_noutervalues = noutervalues; + f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues]; + f->_nlineinfos = nlineinfos; + f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos]; + f->_nlocalvarinfos = nlocalvarinfos; + f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos]; + f->_ndefaultparams = ndefaultparams; - _CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals); - _CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters); - _CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions); - _CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues); - //_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers - _CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos); - return f; - } - void Release(){ - _DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals); - _DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters); - _DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions); - _DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues); - //_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers - _DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos); - SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams); - this->~SQFunctionProto(); - sq_vm_free(this,size); - } + _CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals); + _CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters); + _CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions); + _CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues); + //_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers + _CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos); + return f; + } + void Release(){ + _DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals); + _DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters); + _DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions); + _DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues); + //_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers + _DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos); + SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams); + this->~SQFunctionProto(); + sq_vm_free(this,size); + } - const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); - SQInteger GetLine(SQInstruction *curr); - bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); - static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); - SQObjectPtr _sourcename; - SQObjectPtr _name; - SQInteger _stacksize; - bool _bgenerator; - SQInteger _varparams; + const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); + SQInteger GetLine(SQInstruction *curr); + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); + static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); + SQObjectPtr _sourcename; + SQObjectPtr _name; + SQInteger _stacksize; + bool _bgenerator; + SQInteger _varparams; - SQInteger _nlocalvarinfos; - SQLocalVarInfo *_localvarinfos; + SQInteger _nlocalvarinfos; + SQLocalVarInfo *_localvarinfos; - SQInteger _nlineinfos; - SQLineInfo *_lineinfos; + SQInteger _nlineinfos; + SQLineInfo *_lineinfos; - SQInteger _nliterals; - SQObjectPtr *_literals; + SQInteger _nliterals; + SQObjectPtr *_literals; - SQInteger _nparameters; - SQObjectPtr *_parameters; + SQInteger _nparameters; + SQObjectPtr *_parameters; - SQInteger _nfunctions; - SQObjectPtr *_functions; + SQInteger _nfunctions; + SQObjectPtr *_functions; - SQInteger _noutervalues; - SQOuterVar *_outervalues; + SQInteger _noutervalues; + SQOuterVar *_outervalues; - SQInteger _ndefaultparams; - SQInteger *_defaultparams; + SQInteger _ndefaultparams; + SQInteger *_defaultparams; - SQInteger _ninstructions; - SQInstruction _instructions[1]; + SQInteger _ninstructions; + SQInstruction _instructions[1]; }; diff --git a/rabbit/sqfuncstate.cpp b/rabbit/sqfuncstate.cpp index fe24734..c1b3ff0 100644 --- a/rabbit/sqfuncstate.cpp +++ b/rabbit/sqfuncstate.cpp @@ -17,642 +17,642 @@ #ifdef _DEBUG_DUMP SQInstructionDesc g_InstrDesc[]={ - {_SC("_OP_LINE")}, - {_SC("_OP_LOAD")}, - {_SC("_OP_LOADINT")}, - {_SC("_OP_LOADFLOAT")}, - {_SC("_OP_DLOAD")}, - {_SC("_OP_TAILCALL")}, - {_SC("_OP_CALL")}, - {_SC("_OP_PREPCALL")}, - {_SC("_OP_PREPCALLK")}, - {_SC("_OP_GETK")}, - {_SC("_OP_MOVE")}, - {_SC("_OP_NEWSLOT")}, - {_SC("_OP_DELETE")}, - {_SC("_OP_SET")}, - {_SC("_OP_GET")}, - {_SC("_OP_EQ")}, - {_SC("_OP_NE")}, - {_SC("_OP_ADD")}, - {_SC("_OP_SUB")}, - {_SC("_OP_MUL")}, - {_SC("_OP_DIV")}, - {_SC("_OP_MOD")}, - {_SC("_OP_BITW")}, - {_SC("_OP_RETURN")}, - {_SC("_OP_LOADNULLS")}, - {_SC("_OP_LOADROOT")}, - {_SC("_OP_LOADBOOL")}, - {_SC("_OP_DMOVE")}, - {_SC("_OP_JMP")}, - {_SC("_OP_JCMP")}, - {_SC("_OP_JZ")}, - {_SC("_OP_SETOUTER")}, - {_SC("_OP_GETOUTER")}, - {_SC("_OP_NEWOBJ")}, - {_SC("_OP_APPENDARRAY")}, - {_SC("_OP_COMPARITH")}, - {_SC("_OP_INC")}, - {_SC("_OP_INCL")}, - {_SC("_OP_PINC")}, - {_SC("_OP_PINCL")}, - {_SC("_OP_CMP")}, - {_SC("_OP_EXISTS")}, - {_SC("_OP_INSTANCEOF")}, - {_SC("_OP_AND")}, - {_SC("_OP_OR")}, - {_SC("_OP_NEG")}, - {_SC("_OP_NOT")}, - {_SC("_OP_BWNOT")}, - {_SC("_OP_CLOSURE")}, - {_SC("_OP_YIELD")}, - {_SC("_OP_RESUME")}, - {_SC("_OP_FOREACH")}, - {_SC("_OP_POSTFOREACH")}, - {_SC("_OP_CLONE")}, - {_SC("_OP_TYPEOF")}, - {_SC("_OP_PUSHTRAP")}, - {_SC("_OP_POPTRAP")}, - {_SC("_OP_THROW")}, - {_SC("_OP_NEWSLOTA")}, - {_SC("_OP_GETBASE")}, - {_SC("_OP_CLOSE")}, + {_SC("_OP_LINE")}, + {_SC("_OP_LOAD")}, + {_SC("_OP_LOADINT")}, + {_SC("_OP_LOADFLOAT")}, + {_SC("_OP_DLOAD")}, + {_SC("_OP_TAILCALL")}, + {_SC("_OP_CALL")}, + {_SC("_OP_PREPCALL")}, + {_SC("_OP_PREPCALLK")}, + {_SC("_OP_GETK")}, + {_SC("_OP_MOVE")}, + {_SC("_OP_NEWSLOT")}, + {_SC("_OP_DELETE")}, + {_SC("_OP_SET")}, + {_SC("_OP_GET")}, + {_SC("_OP_EQ")}, + {_SC("_OP_NE")}, + {_SC("_OP_ADD")}, + {_SC("_OP_SUB")}, + {_SC("_OP_MUL")}, + {_SC("_OP_DIV")}, + {_SC("_OP_MOD")}, + {_SC("_OP_BITW")}, + {_SC("_OP_RETURN")}, + {_SC("_OP_LOADNULLS")}, + {_SC("_OP_LOADROOT")}, + {_SC("_OP_LOADBOOL")}, + {_SC("_OP_DMOVE")}, + {_SC("_OP_JMP")}, + {_SC("_OP_JCMP")}, + {_SC("_OP_JZ")}, + {_SC("_OP_SETOUTER")}, + {_SC("_OP_GETOUTER")}, + {_SC("_OP_NEWOBJ")}, + {_SC("_OP_APPENDARRAY")}, + {_SC("_OP_COMPARITH")}, + {_SC("_OP_INC")}, + {_SC("_OP_INCL")}, + {_SC("_OP_PINC")}, + {_SC("_OP_PINCL")}, + {_SC("_OP_CMP")}, + {_SC("_OP_EXISTS")}, + {_SC("_OP_INSTANCEOF")}, + {_SC("_OP_AND")}, + {_SC("_OP_OR")}, + {_SC("_OP_NEG")}, + {_SC("_OP_NOT")}, + {_SC("_OP_BWNOT")}, + {_SC("_OP_CLOSURE")}, + {_SC("_OP_YIELD")}, + {_SC("_OP_RESUME")}, + {_SC("_OP_FOREACH")}, + {_SC("_OP_POSTFOREACH")}, + {_SC("_OP_CLONE")}, + {_SC("_OP_TYPEOF")}, + {_SC("_OP_PUSHTRAP")}, + {_SC("_OP_POPTRAP")}, + {_SC("_OP_THROW")}, + {_SC("_OP_NEWSLOTA")}, + {_SC("_OP_GETBASE")}, + {_SC("_OP_CLOSE")}, }; #endif void DumpLiteral(SQObjectPtr &o) { - switch(sq_type(o)){ - case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break; - case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break; - case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break; - case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break; - default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler - } + switch(sq_type(o)){ + case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break; + case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break; + case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break; + case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break; + default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler + } } SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed) { - _nliterals = 0; - _literals = SQTable::Create(ss,0); - _strings = SQTable::Create(ss,0); - _sharedstate = ss; - _lastline = 0; - _optimization = true; - _parent = parent; - _stacksize = 0; - _traps = 0; - _returnexp = 0; - _varparams = false; - _errfunc = efunc; - _errtarget = ed; - _bgenerator = false; - _outers = 0; - _ss = ss; + _nliterals = 0; + _literals = SQTable::Create(ss,0); + _strings = SQTable::Create(ss,0); + _sharedstate = ss; + _lastline = 0; + _optimization = true; + _parent = parent; + _stacksize = 0; + _traps = 0; + _returnexp = 0; + _varparams = false; + _errfunc = efunc; + _errtarget = ed; + _bgenerator = false; + _outers = 0; + _ss = ss; } void SQFuncState::Error(const SQChar *err) { - _errfunc(_errtarget,err); + _errfunc(_errtarget,err); } #ifdef _DEBUG_DUMP void SQFuncState::Dump(SQFunctionProto *func) { - SQUnsignedInteger n=0,i; - SQInteger si; - scprintf(_SC("SQInstruction sizeof %d\n"),(SQInt32)sizeof(SQInstruction)); - scprintf(_SC("SQObject sizeof %d\n"), (SQInt32)sizeof(SQObject)); - scprintf(_SC("--------------------------------------------------------------------\n")); - scprintf(_SC("*****FUNCTION [%s]\n"),sq_type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown")); - scprintf(_SC("-----LITERALS\n")); - SQObjectPtr refidx,key,val; - SQInteger idx; - SQObjectPtrVec templiterals; - templiterals.resize(_nliterals); - while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { - refidx=idx; - templiterals[_integer(val)]=key; - } - for(i=0;i>\n")); - n=0; - for(i=0;i<_parameters.size();i++){ - scprintf(_SC("[%d] "), (SQInt32)n); - DumpLiteral(_parameters[i]); - scprintf(_SC("\n")); - n++; - } - scprintf(_SC("-----LOCALS\n")); - for(si=0;si_nlocalvarinfos;si++){ - SQLocalVarInfo lvi=func->_localvarinfos[si]; - scprintf(_SC("[%d] %s \t%d %d\n"), (SQInt32)lvi._pos,_stringval(lvi._name), (SQInt32)lvi._start_op, (SQInt32)lvi._end_op); - n++; - } - scprintf(_SC("-----LINE INFO\n")); - for(i=0;i<_lineinfos.size();i++){ - SQLineInfo li=_lineinfos[i]; - scprintf(_SC("op [%d] line [%d] \n"), (SQInt32)li._op, (SQInt32)li._line); - n++; - } - scprintf(_SC("-----dump\n")); - n=0; - for(i=0;i<_instructions.size();i++){ - SQInstruction &inst=_instructions[i]; - if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){ + SQUnsignedInteger n=0,i; + SQInteger si; + scprintf(_SC("SQInstruction sizeof %d\n"),(SQInt32)sizeof(SQInstruction)); + scprintf(_SC("SQObject sizeof %d\n"), (SQInt32)sizeof(SQObject)); + scprintf(_SC("--------------------------------------------------------------------\n")); + scprintf(_SC("*****FUNCTION [%s]\n"),sq_type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown")); + scprintf(_SC("-----LITERALS\n")); + SQObjectPtr refidx,key,val; + SQInteger idx; + SQObjectPtrVec templiterals; + templiterals.resize(_nliterals); + while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { + refidx=idx; + templiterals[_integer(val)]=key; + } + for(i=0;i>\n")); + n=0; + for(i=0;i<_parameters.size();i++){ + scprintf(_SC("[%d] "), (SQInt32)n); + DumpLiteral(_parameters[i]); + scprintf(_SC("\n")); + n++; + } + scprintf(_SC("-----LOCALS\n")); + for(si=0;si_nlocalvarinfos;si++){ + SQLocalVarInfo lvi=func->_localvarinfos[si]; + scprintf(_SC("[%d] %s \t%d %d\n"), (SQInt32)lvi._pos,_stringval(lvi._name), (SQInt32)lvi._start_op, (SQInt32)lvi._end_op); + n++; + } + scprintf(_SC("-----LINE INFO\n")); + for(i=0;i<_lineinfos.size();i++){ + SQLineInfo li=_lineinfos[i]; + scprintf(_SC("op [%d] line [%d] \n"), (SQInt32)li._op, (SQInt32)li._line); + n++; + } + scprintf(_SC("-----dump\n")); + n=0; + for(i=0;i<_instructions.size();i++){ + SQInstruction &inst=_instructions[i]; + if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){ - SQInteger lidx = inst._arg1; - scprintf(_SC("[%03d] %15s %d "), (SQInt32)n,g_InstrDesc[inst.op].name,inst._arg0); - if(lidx >= 0xFFFFFFFF) - scprintf(_SC("null")); - else { - SQInteger refidx; - SQObjectPtr val,key,refo; - while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { - refo = refidx; - } - DumpLiteral(key); - } - if(inst.op != _OP_DLOAD) { - scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3); - } - else { - scprintf(_SC(" %d "),inst._arg2); - lidx = inst._arg3; - if(lidx >= 0xFFFFFFFF) - scprintf(_SC("null")); - else { - SQInteger refidx; - SQObjectPtr val,key,refo; - while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { - refo = refidx; - } - DumpLiteral(key); - scprintf(_SC("\n")); - } - } - } - else if(inst.op==_OP_LOADFLOAT) { - scprintf(_SC("[%03d] %15s %d %f %d %d\n"), (SQInt32)n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3); - } - /* else if(inst.op==_OP_ARITH){ - scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); - }*/ - else { - scprintf(_SC("[%03d] %15s %d %d %d %d\n"), (SQInt32)n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); - } - n++; - } - scprintf(_SC("-----\n")); - scprintf(_SC("stack size[%d]\n"), (SQInt32)func->_stacksize); - scprintf(_SC("--------------------------------------------------------------------\n\n")); + SQInteger lidx = inst._arg1; + scprintf(_SC("[%03d] %15s %d "), (SQInt32)n,g_InstrDesc[inst.op].name,inst._arg0); + if(lidx >= 0xFFFFFFFF) + scprintf(_SC("null")); + else { + SQInteger refidx; + SQObjectPtr val,key,refo; + while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { + refo = refidx; + } + DumpLiteral(key); + } + if(inst.op != _OP_DLOAD) { + scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3); + } + else { + scprintf(_SC(" %d "),inst._arg2); + lidx = inst._arg3; + if(lidx >= 0xFFFFFFFF) + scprintf(_SC("null")); + else { + SQInteger refidx; + SQObjectPtr val,key,refo; + while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { + refo = refidx; + } + DumpLiteral(key); + scprintf(_SC("\n")); + } + } + } + else if(inst.op==_OP_LOADFLOAT) { + scprintf(_SC("[%03d] %15s %d %f %d %d\n"), (SQInt32)n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3); + } + /* else if(inst.op==_OP_ARITH){ + scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + }*/ + else { + scprintf(_SC("[%03d] %15s %d %d %d %d\n"), (SQInt32)n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + } + n++; + } + scprintf(_SC("-----\n")); + scprintf(_SC("stack size[%d]\n"), (SQInt32)func->_stacksize); + scprintf(_SC("--------------------------------------------------------------------\n\n")); } #endif SQInteger SQFuncState::GetNumericConstant(const SQInteger cons) { - return GetConstant(SQObjectPtr(cons)); + return GetConstant(SQObjectPtr(cons)); } SQInteger SQFuncState::GetNumericConstant(const SQFloat cons) { - return GetConstant(SQObjectPtr(cons)); + return GetConstant(SQObjectPtr(cons)); } SQInteger SQFuncState::GetConstant(const SQObject &cons) { - SQObjectPtr val; - if(!_table(_literals)->Get(cons,val)) - { - val = _nliterals; - _table(_literals)->NewSlot(cons,val); - _nliterals++; - if(_nliterals > MAX_LITERALS) { - val.Null(); - Error(_SC("internal compiler error: too many literals")); - } - } - return _integer(val); + SQObjectPtr val; + if(!_table(_literals)->Get(cons,val)) + { + val = _nliterals; + _table(_literals)->NewSlot(cons,val); + _nliterals++; + if(_nliterals > MAX_LITERALS) { + val.Null(); + Error(_SC("internal compiler error: too many literals")); + } + } + return _integer(val); } void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3) { - _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0); - _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1); - _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2); - _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3); + _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0); + _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1); + _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2); + _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3); } void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val) { - switch(arg){ - case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break; - case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break; - case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break; - case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break; - }; + switch(arg){ + case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break; + case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break; + case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break; + case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break; + }; } SQInteger SQFuncState::AllocStackPos() { - SQInteger npos=_vlocals.size(); - _vlocals.push_back(SQLocalVarInfo()); - if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) { - if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals")); - _stacksize=_vlocals.size(); - } - return npos; + SQInteger npos=_vlocals.size(); + _vlocals.push_back(SQLocalVarInfo()); + if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) { + if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals")); + _stacksize=_vlocals.size(); + } + return npos; } SQInteger SQFuncState::PushTarget(SQInteger n) { - if(n!=-1){ - _targetstack.push_back(n); - return n; - } - n=AllocStackPos(); - _targetstack.push_back(n); - return n; + if(n!=-1){ + _targetstack.push_back(n); + return n; + } + n=AllocStackPos(); + _targetstack.push_back(n); + return n; } SQInteger SQFuncState::GetUpTarget(SQInteger n){ - return _targetstack[((_targetstack.size()-1)-n)]; + return _targetstack[((_targetstack.size()-1)-n)]; } SQInteger SQFuncState::TopTarget(){ - return _targetstack.back(); + return _targetstack.back(); } SQInteger SQFuncState::PopTarget() { - SQUnsignedInteger npos=_targetstack.back(); - assert(npos < _vlocals.size()); - SQLocalVarInfo &t = _vlocals[npos]; - if(sq_type(t._name)==OT_NULL){ - _vlocals.pop_back(); - } - _targetstack.pop_back(); - return npos; + SQUnsignedInteger npos=_targetstack.back(); + assert(npos < _vlocals.size()); + SQLocalVarInfo &t = _vlocals[npos]; + if(sq_type(t._name)==OT_NULL){ + _vlocals.pop_back(); + } + _targetstack.pop_back(); + return npos; } SQInteger SQFuncState::GetStackSize() { - return _vlocals.size(); + return _vlocals.size(); } SQInteger SQFuncState::CountOuters(SQInteger stacksize) { - SQInteger outers = 0; - SQInteger k = _vlocals.size() - 1; - while(k >= stacksize) { - SQLocalVarInfo &lvi = _vlocals[k]; - k--; - if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer - outers++; - } - } - return outers; + SQInteger outers = 0; + SQInteger k = _vlocals.size() - 1; + while(k >= stacksize) { + SQLocalVarInfo &lvi = _vlocals[k]; + k--; + if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer + outers++; + } + } + return outers; } void SQFuncState::SetStackSize(SQInteger n) { - SQInteger size=_vlocals.size(); - while(size>n){ - size--; - SQLocalVarInfo lvi = _vlocals.back(); - if(sq_type(lvi._name)!=OT_NULL){ - if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer - _outers--; - } - lvi._end_op = GetCurrentPos(); - _localvarinfos.push_back(lvi); - } - _vlocals.pop_back(); - } + SQInteger size=_vlocals.size(); + while(size>n){ + size--; + SQLocalVarInfo lvi = _vlocals.back(); + if(sq_type(lvi._name)!=OT_NULL){ + if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer + _outers--; + } + lvi._end_op = GetCurrentPos(); + _localvarinfos.push_back(lvi); + } + _vlocals.pop_back(); + } } bool SQFuncState::IsConstant(const SQObject &name,SQObject &e) { - SQObjectPtr val; - if(_table(_sharedstate->_consts)->Get(name,val)) { - e = val; - return true; - } - return false; + SQObjectPtr val; + if(_table(_sharedstate->_consts)->Get(name,val)) { + e = val; + return true; + } + return false; } bool SQFuncState::IsLocal(SQUnsignedInteger stkpos) { - if(stkpos>=_vlocals.size())return false; - else if(sq_type(_vlocals[stkpos]._name)!=OT_NULL)return true; - return false; + if(stkpos>=_vlocals.size())return false; + else if(sq_type(_vlocals[stkpos]._name)!=OT_NULL)return true; + return false; } SQInteger SQFuncState::PushLocalVariable(const SQObject &name) { - SQInteger pos=_vlocals.size(); - SQLocalVarInfo lvi; - lvi._name=name; - lvi._start_op=GetCurrentPos()+1; - lvi._pos=_vlocals.size(); - _vlocals.push_back(lvi); - if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); - return pos; + SQInteger pos=_vlocals.size(); + SQLocalVarInfo lvi; + lvi._name=name; + lvi._start_op=GetCurrentPos()+1; + lvi._pos=_vlocals.size(); + _vlocals.push_back(lvi); + if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); + return pos; } SQInteger SQFuncState::GetLocalVariable(const SQObject &name) { - SQInteger locals=_vlocals.size(); - while(locals>=1){ - SQLocalVarInfo &lvi = _vlocals[locals-1]; - if(sq_type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){ - return locals-1; - } - locals--; - } - return -1; + SQInteger locals=_vlocals.size(); + while(locals>=1){ + SQLocalVarInfo &lvi = _vlocals[locals-1]; + if(sq_type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){ + return locals-1; + } + locals--; + } + return -1; } void SQFuncState::MarkLocalAsOuter(SQInteger pos) { - SQLocalVarInfo &lvi = _vlocals[pos]; - lvi._end_op = UINT_MINUS_ONE; - _outers++; + SQLocalVarInfo &lvi = _vlocals[pos]; + lvi._end_op = UINT_MINUS_ONE; + _outers++; } SQInteger SQFuncState::GetOuterVariable(const SQObject &name) { - SQInteger outers = _outervalues.size(); - for(SQInteger i = 0; iGetLocalVariable(name); - if(pos == -1) { - pos = _parent->GetOuterVariable(name); - if(pos != -1) { - _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local - return _outervalues.size() - 1; - } - } - else { - _parent->MarkLocalAsOuter(pos); - _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local - return _outervalues.size() - 1; + SQInteger outers = _outervalues.size(); + for(SQInteger i = 0; iGetLocalVariable(name); + if(pos == -1) { + pos = _parent->GetOuterVariable(name); + if(pos != -1) { + _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local + return _outervalues.size() - 1; + } + } + else { + _parent->MarkLocalAsOuter(pos); + _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local + return _outervalues.size() - 1; - } - } - return -1; + } + } + return -1; } void SQFuncState::AddParameter(const SQObject &name) { - PushLocalVariable(name); - _parameters.push_back(name); + PushLocalVariable(name); + _parameters.push_back(name); } void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force) { - if(_lastline!=line || force){ - SQLineInfo li; - li._line=line;li._op=(GetCurrentPos()+1); - if(lineop)AddInstruction(_OP_LINE,0,line); - if(_lastline!=line) { - _lineinfos.push_back(li); - } - _lastline=line; - } + if(_lastline!=line || force){ + SQLineInfo li; + li._line=line;li._op=(GetCurrentPos()+1); + if(lineop)AddInstruction(_OP_LINE,0,line); + if(_lastline!=line) { + _lineinfos.push_back(li); + } + _lastline=line; + } } void SQFuncState::DiscardTarget() { - SQInteger discardedtarget = PopTarget(); - SQInteger size = _instructions.size(); - if(size > 0 && _optimization){ - SQInstruction &pi = _instructions[size-1];//previous instruction - switch(pi.op) { - case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL: - if(pi._arg0 == discardedtarget) { - pi._arg0 = 0xFF; - } - } - } + SQInteger discardedtarget = PopTarget(); + SQInteger size = _instructions.size(); + if(size > 0 && _optimization){ + SQInstruction &pi = _instructions[size-1];//previous instruction + switch(pi.op) { + case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL: + if(pi._arg0 == discardedtarget) { + pi._arg0 = 0xFF; + } + } + } } void SQFuncState::AddInstruction(SQInstruction &i) { - SQInteger size = _instructions.size(); - if(size > 0 && _optimization){ //simple optimizer - SQInstruction &pi = _instructions[size-1];//previous instruction - switch(i.op) { - case _OP_JZ: - if( pi.op == _OP_CMP && pi._arg1 < 0xFF) { - pi.op = _OP_JCMP; - pi._arg0 = (unsigned char)pi._arg1; - pi._arg1 = i._arg1; - return; - } - break; - case _OP_SET: - case _OP_NEWSLOT: - if(i._arg0 == i._arg3) { - i._arg0 = 0xFF; - } - break; - case _OP_SETOUTER: - if(i._arg0 == i._arg2) { - i._arg0 = 0xFF; - } - break; - case _OP_RETURN: - if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { - pi.op = _OP_TAILCALL; - } else if(pi.op == _OP_CLOSE){ - pi = i; - return; - } - break; - case _OP_GET: - if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){ - pi._arg1 = pi._arg1; - pi._arg2 = (unsigned char)i._arg1; - pi.op = _OP_GETK; - pi._arg0 = i._arg0; + SQInteger size = _instructions.size(); + if(size > 0 && _optimization){ //simple optimizer + SQInstruction &pi = _instructions[size-1];//previous instruction + switch(i.op) { + case _OP_JZ: + if( pi.op == _OP_CMP && pi._arg1 < 0xFF) { + pi.op = _OP_JCMP; + pi._arg0 = (unsigned char)pi._arg1; + pi._arg1 = i._arg1; + return; + } + break; + case _OP_SET: + case _OP_NEWSLOT: + if(i._arg0 == i._arg3) { + i._arg0 = 0xFF; + } + break; + case _OP_SETOUTER: + if(i._arg0 == i._arg2) { + i._arg0 = 0xFF; + } + break; + case _OP_RETURN: + if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { + pi.op = _OP_TAILCALL; + } else if(pi.op == _OP_CLOSE){ + pi = i; + return; + } + break; + case _OP_GET: + if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){ + pi._arg1 = pi._arg1; + pi._arg2 = (unsigned char)i._arg1; + pi.op = _OP_GETK; + pi._arg0 = i._arg0; - return; - } - break; - case _OP_PREPCALL: - if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ - pi.op = _OP_PREPCALLK; - pi._arg0 = i._arg0; - pi._arg1 = pi._arg1; - pi._arg2 = i._arg2; - pi._arg3 = i._arg3; - return; - } - break; - case _OP_APPENDARRAY: { - SQInteger aat = -1; - switch(pi.op) { - case _OP_LOAD: aat = AAT_LITERAL; break; - case _OP_LOADINT: aat = AAT_INT; break; - case _OP_LOADBOOL: aat = AAT_BOOL; break; - case _OP_LOADFLOAT: aat = AAT_FLOAT; break; - default: break; - } - if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ - pi.op = _OP_APPENDARRAY; - pi._arg0 = i._arg0; - pi._arg1 = pi._arg1; - pi._arg2 = (unsigned char)aat; - pi._arg3 = MAX_FUNC_STACKSIZE; - return; - } - } - break; - case _OP_MOVE: - switch(pi.op) { - case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW: - case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD: + return; + } + break; + case _OP_PREPCALL: + if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + pi.op = _OP_PREPCALLK; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = i._arg2; + pi._arg3 = i._arg3; + return; + } + break; + case _OP_APPENDARRAY: { + SQInteger aat = -1; + switch(pi.op) { + case _OP_LOAD: aat = AAT_LITERAL; break; + case _OP_LOADINT: aat = AAT_INT; break; + case _OP_LOADBOOL: aat = AAT_BOOL; break; + case _OP_LOADFLOAT: aat = AAT_FLOAT; break; + default: break; + } + if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + pi.op = _OP_APPENDARRAY; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = (unsigned char)aat; + pi._arg3 = MAX_FUNC_STACKSIZE; + return; + } + } + break; + case _OP_MOVE: + switch(pi.op) { + case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW: + case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD: - if(pi._arg0 == i._arg1) - { - pi._arg0 = i._arg0; - _optimization = false; - //_result_elimination = false; - return; - } - } + if(pi._arg0 == i._arg1) + { + pi._arg0 = i._arg0; + _optimization = false; + //_result_elimination = false; + return; + } + } - if(pi.op == _OP_MOVE) - { - pi.op = _OP_DMOVE; - pi._arg2 = i._arg0; - pi._arg3 = (unsigned char)i._arg1; - return; - } - break; - case _OP_LOAD: - if(pi.op == _OP_LOAD && i._arg1 < 256) { - pi.op = _OP_DLOAD; - pi._arg2 = i._arg0; - pi._arg3 = (unsigned char)i._arg1; - return; - } - break; - case _OP_EQ:case _OP_NE: - if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) )) - { - pi.op = i.op; - pi._arg0 = i._arg0; - pi._arg1 = pi._arg1; - pi._arg2 = i._arg2; - pi._arg3 = MAX_FUNC_STACKSIZE; - return; - } - break; - case _OP_LOADNULLS: - if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) { + if(pi.op == _OP_MOVE) + { + pi.op = _OP_DMOVE; + pi._arg2 = i._arg0; + pi._arg3 = (unsigned char)i._arg1; + return; + } + break; + case _OP_LOAD: + if(pi.op == _OP_LOAD && i._arg1 < 256) { + pi.op = _OP_DLOAD; + pi._arg2 = i._arg0; + pi._arg3 = (unsigned char)i._arg1; + return; + } + break; + case _OP_EQ:case _OP_NE: + if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) )) + { + pi.op = i.op; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = i._arg2; + pi._arg3 = MAX_FUNC_STACKSIZE; + return; + } + break; + case _OP_LOADNULLS: + if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) { - pi._arg1 = pi._arg1 + 1; - pi.op = _OP_LOADNULLS; - return; - } - break; - case _OP_LINE: - if(pi.op == _OP_LINE) { - _instructions.pop_back(); - _lineinfos.pop_back(); - } - break; - } - } - _optimization = true; - _instructions.push_back(i); + pi._arg1 = pi._arg1 + 1; + pi.op = _OP_LOADNULLS; + return; + } + break; + case _OP_LINE: + if(pi.op == _OP_LINE) { + _instructions.pop_back(); + _lineinfos.pop_back(); + } + break; + } + } + _optimization = true; + _instructions.push_back(i); } SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len) { - SQObjectPtr ns(SQString::Create(_sharedstate,s,len)); - _table(_strings)->NewSlot(ns,(SQInteger)1); - return ns; + SQObjectPtr ns(SQString::Create(_sharedstate,s,len)); + _table(_strings)->NewSlot(ns,(SQInteger)1); + return ns; } SQObject SQFuncState::CreateTable() { - SQObjectPtr nt(SQTable::Create(_sharedstate,0)); - _table(_strings)->NewSlot(nt,(SQInteger)1); - return nt; + SQObjectPtr nt(SQTable::Create(_sharedstate,0)); + _table(_strings)->NewSlot(nt,(SQInteger)1); + return nt; } SQFunctionProto *SQFuncState::BuildProto() { - SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(), - _nliterals,_parameters.size(),_functions.size(),_outervalues.size(), - _lineinfos.size(),_localvarinfos.size(),_defaultparams.size()); + SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(), + _nliterals,_parameters.size(),_functions.size(),_outervalues.size(), + _lineinfos.size(),_localvarinfos.size(),_defaultparams.size()); - SQObjectPtr refidx,key,val; - SQInteger idx; + SQObjectPtr refidx,key,val; + SQInteger idx; - f->_stacksize = _stacksize; - f->_sourcename = _sourcename; - f->_bgenerator = _bgenerator; - f->_name = _name; + f->_stacksize = _stacksize; + f->_sourcename = _sourcename; + f->_bgenerator = _bgenerator; + f->_name = _name; - while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { - f->_literals[_integer(val)]=key; - refidx=idx; - } + while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { + f->_literals[_integer(val)]=key; + refidx=idx; + } - for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf]; - for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np]; - for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no]; - for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl]; - for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni]; - for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd]; + for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf]; + for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np]; + for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no]; + for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl]; + for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni]; + for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd]; - memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction)); + memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction)); - f->_varparams = _varparams; + f->_varparams = _varparams; - return f; + return f; } SQFuncState *SQFuncState::PushChildState(SQSharedState *ss) { - SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState)); - new (child) SQFuncState(ss,this,_errfunc,_errtarget); - _childstates.push_back(child); - return child; + SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState)); + new (child) SQFuncState(ss,this,_errfunc,_errtarget); + _childstates.push_back(child); + return child; } void SQFuncState::PopChildState() { - SQFuncState *child = _childstates.back(); - sq_delete(child,SQFuncState); - _childstates.pop_back(); + SQFuncState *child = _childstates.back(); + sq_delete(child,SQFuncState); + _childstates.pop_back(); } SQFuncState::~SQFuncState() { - while(_childstates.size() > 0) - { - PopChildState(); - } + while(_childstates.size() > 0) + { + PopChildState(); + } } #endif diff --git a/rabbit/sqfuncstate.hpp b/rabbit/sqfuncstate.hpp index 99e899c..513cfb1 100644 --- a/rabbit/sqfuncstate.hpp +++ b/rabbit/sqfuncstate.hpp @@ -11,84 +11,84 @@ struct SQFuncState { - SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed); - ~SQFuncState(); + SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed); + ~SQFuncState(); #ifdef _DEBUG_DUMP - void Dump(SQFunctionProto *func); + void Dump(SQFunctionProto *func); #endif - void Error(const SQChar *err); - SQFuncState *PushChildState(SQSharedState *ss); - void PopChildState(); - void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);} - void AddInstruction(SQInstruction &i); - void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0); - void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val); - SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];} - void PopInstructions(SQInteger size){for(SQInteger i=0;i _childstates; - SQInteger GetConstant(const SQObject &cons); + void Error(const SQChar *err); + SQFuncState *PushChildState(SQSharedState *ss); + void PopChildState(); + void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);} + void AddInstruction(SQInstruction &i); + void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0); + void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val); + SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];} + void PopInstructions(SQInteger size){for(SQInteger i=0;i _childstates; + SQInteger GetConstant(const SQObject &cons); private: - CompilerErrorFunc _errfunc; - void *_errtarget; - SQSharedState *_ss; + CompilerErrorFunc _errfunc; + void *_errtarget; + SQSharedState *_ss; }; diff --git a/rabbit/sqlexer.cpp b/rabbit/sqlexer.cpp index 0c653af..b81da7d 100644 --- a/rabbit/sqlexer.cpp +++ b/rabbit/sqlexer.cpp @@ -26,456 +26,456 @@ SQLexer::SQLexer(){} SQLexer::~SQLexer() { - _keywords->Release(); + _keywords->Release(); } void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed) { - _errfunc = efunc; - _errtarget = ed; - _sharedstate = ss; - _keywords = SQTable::Create(ss, 37); - ADD_KEYWORD(while, TK_WHILE); - ADD_KEYWORD(do, TK_DO); - ADD_KEYWORD(if, TK_IF); - ADD_KEYWORD(else, TK_ELSE); - ADD_KEYWORD(break, TK_BREAK); - ADD_KEYWORD(continue, TK_CONTINUE); - ADD_KEYWORD(return, TK_RETURN); - ADD_KEYWORD(null, TK_NULL); - ADD_KEYWORD(function, TK_FUNCTION); - ADD_KEYWORD(local, TK_LOCAL); - ADD_KEYWORD(for, TK_FOR); - ADD_KEYWORD(foreach, TK_FOREACH); - ADD_KEYWORD(in, TK_IN); - ADD_KEYWORD(typeof, TK_TYPEOF); - ADD_KEYWORD(base, TK_BASE); - ADD_KEYWORD(delete, TK_DELETE); - ADD_KEYWORD(try, TK_TRY); - ADD_KEYWORD(catch, TK_CATCH); - ADD_KEYWORD(throw, TK_THROW); - ADD_KEYWORD(clone, TK_CLONE); - ADD_KEYWORD(yield, TK_YIELD); - ADD_KEYWORD(resume, TK_RESUME); - ADD_KEYWORD(switch, TK_SWITCH); - ADD_KEYWORD(case, TK_CASE); - ADD_KEYWORD(default, TK_DEFAULT); - ADD_KEYWORD(this, TK_THIS); - ADD_KEYWORD(class,TK_CLASS); - ADD_KEYWORD(extends,TK_EXTENDS); - ADD_KEYWORD(constructor,TK_CONSTRUCTOR); - ADD_KEYWORD(instanceof,TK_INSTANCEOF); - ADD_KEYWORD(true,TK_TRUE); - ADD_KEYWORD(false,TK_FALSE); - ADD_KEYWORD(static,TK_STATIC); - ADD_KEYWORD(enum,TK_ENUM); - ADD_KEYWORD(const,TK_CONST); - ADD_KEYWORD(__LINE__,TK___LINE__); - ADD_KEYWORD(__FILE__,TK___FILE__); - ADD_KEYWORD(rawcall, TK_RAWCALL); + _errfunc = efunc; + _errtarget = ed; + _sharedstate = ss; + _keywords = SQTable::Create(ss, 37); + ADD_KEYWORD(while, TK_WHILE); + ADD_KEYWORD(do, TK_DO); + ADD_KEYWORD(if, TK_IF); + ADD_KEYWORD(else, TK_ELSE); + ADD_KEYWORD(break, TK_BREAK); + ADD_KEYWORD(continue, TK_CONTINUE); + ADD_KEYWORD(return, TK_RETURN); + ADD_KEYWORD(null, TK_NULL); + ADD_KEYWORD(function, TK_FUNCTION); + ADD_KEYWORD(local, TK_LOCAL); + ADD_KEYWORD(for, TK_FOR); + ADD_KEYWORD(foreach, TK_FOREACH); + ADD_KEYWORD(in, TK_IN); + ADD_KEYWORD(typeof, TK_TYPEOF); + ADD_KEYWORD(base, TK_BASE); + ADD_KEYWORD(delete, TK_DELETE); + ADD_KEYWORD(try, TK_TRY); + ADD_KEYWORD(catch, TK_CATCH); + ADD_KEYWORD(throw, TK_THROW); + ADD_KEYWORD(clone, TK_CLONE); + ADD_KEYWORD(yield, TK_YIELD); + ADD_KEYWORD(resume, TK_RESUME); + ADD_KEYWORD(switch, TK_SWITCH); + ADD_KEYWORD(case, TK_CASE); + ADD_KEYWORD(default, TK_DEFAULT); + ADD_KEYWORD(this, TK_THIS); + ADD_KEYWORD(class,TK_CLASS); + ADD_KEYWORD(extends,TK_EXTENDS); + ADD_KEYWORD(constructor,TK_CONSTRUCTOR); + ADD_KEYWORD(instanceof,TK_INSTANCEOF); + ADD_KEYWORD(true,TK_TRUE); + ADD_KEYWORD(false,TK_FALSE); + ADD_KEYWORD(static,TK_STATIC); + ADD_KEYWORD(enum,TK_ENUM); + ADD_KEYWORD(const,TK_CONST); + ADD_KEYWORD(__LINE__,TK___LINE__); + ADD_KEYWORD(__FILE__,TK___FILE__); + ADD_KEYWORD(rawcall, TK_RAWCALL); - _readf = rg; - _up = up; - _lasttokenline = _currentline = 1; - _currentcolumn = 0; - _prevtoken = -1; - _reached_eof = SQFalse; - Next(); + _readf = rg; + _up = up; + _lasttokenline = _currentline = 1; + _currentcolumn = 0; + _prevtoken = -1; + _reached_eof = SQFalse; + Next(); } void SQLexer::Error(const SQChar *err) { - _errfunc(_errtarget,err); + _errfunc(_errtarget,err); } void SQLexer::Next() { - SQInteger t = _readf(_up); - if(t > MAX_CHAR) Error(_SC("Invalid character")); - if(t != 0) { - _currdata = (LexChar)t; - return; - } - _currdata = RABBIT_EOB; - _reached_eof = SQTrue; + SQInteger t = _readf(_up); + if(t > MAX_CHAR) Error(_SC("Invalid character")); + if(t != 0) { + _currdata = (LexChar)t; + return; + } + _currdata = RABBIT_EOB; + _reached_eof = SQTrue; } const SQChar *SQLexer::Tok2Str(SQInteger tok) { - SQObjectPtr itr, key, val; - SQInteger nitr; - while((nitr = _keywords->Next(false,itr, key, val)) != -1) { - itr = (SQInteger)nitr; - if(((SQInteger)_integer(val)) == tok) - return _stringval(key); - } - return NULL; + SQObjectPtr itr, key, val; + SQInteger nitr; + while((nitr = _keywords->Next(false,itr, key, val)) != -1) { + itr = (SQInteger)nitr; + if(((SQInteger)_integer(val)) == tok) + return _stringval(key); + } + return NULL; } void SQLexer::LexBlockComment() { - bool done = false; - while(!done) { - switch(CUR_CHAR) { - case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue; - case _SC('\n'): _currentline++; NEXT(); continue; - case RABBIT_EOB: Error(_SC("missing \"*/\" in comment")); - default: NEXT(); - } - } + bool done = false; + while(!done) { + switch(CUR_CHAR) { + case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue; + case _SC('\n'): _currentline++; NEXT(); continue; + case RABBIT_EOB: Error(_SC("missing \"*/\" in comment")); + default: NEXT(); + } + } } void SQLexer::LexLineComment() { - do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); + do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); } SQInteger SQLexer::Lex() { - _lasttokenline = _currentline; - while(CUR_CHAR != RABBIT_EOB) { - switch(CUR_CHAR){ - case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue; - case _SC('\n'): - _currentline++; - _prevtoken=_curtoken; - _curtoken=_SC('\n'); - NEXT(); - _currentcolumn=1; - continue; - case _SC('#'): LexLineComment(); continue; - case _SC('/'): - NEXT(); - switch(CUR_CHAR){ - case _SC('*'): - NEXT(); - LexBlockComment(); - continue; - case _SC('/'): - LexLineComment(); - continue; - case _SC('='): - NEXT(); - RETURN_TOKEN(TK_DIVEQ); - continue; - case _SC('>'): - NEXT(); - RETURN_TOKEN(TK_ATTR_CLOSE); - continue; - default: - RETURN_TOKEN('/'); - } - case _SC('='): - NEXT(); - if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') } - else { NEXT(); RETURN_TOKEN(TK_EQ); } - case _SC('<'): - NEXT(); - switch(CUR_CHAR) { - case _SC('='): - NEXT(); - if(CUR_CHAR == _SC('>')) { - NEXT(); - RETURN_TOKEN(TK_3WAYSCMP); - } - RETURN_TOKEN(TK_LE) - break; - case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break; - case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break; - case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break; - } - RETURN_TOKEN('<'); - case _SC('>'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} - else if(CUR_CHAR == _SC('>')){ - NEXT(); - if(CUR_CHAR == _SC('>')){ - NEXT(); - RETURN_TOKEN(TK_USHIFTR); - } - RETURN_TOKEN(TK_SHIFTR); - } - else { RETURN_TOKEN('>') } - case _SC('!'): - NEXT(); - if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')} - else { NEXT(); RETURN_TOKEN(TK_NE); } - case _SC('@'): { - SQInteger stype; - NEXT(); - if(CUR_CHAR != _SC('"')) { - RETURN_TOKEN('@'); - } - if((stype=ReadString('"',true))!=-1) { - RETURN_TOKEN(stype); - } - Error(_SC("error parsing the string")); - } - case _SC('"'): - case _SC('\''): { - SQInteger stype; - if((stype=ReadString(CUR_CHAR,false))!=-1){ - RETURN_TOKEN(stype); - } - Error(_SC("error parsing the string")); - } - case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'): - case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'): - {SQInteger ret = CUR_CHAR; - NEXT(); RETURN_TOKEN(ret); } - case _SC('.'): - NEXT(); - if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') } - NEXT(); - if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); } - NEXT(); - RETURN_TOKEN(TK_VARPARAMS); - case _SC('&'): - NEXT(); - if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') } - else { NEXT(); RETURN_TOKEN(TK_AND); } - case _SC('|'): - NEXT(); - if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') } - else { NEXT(); RETURN_TOKEN(TK_OR); } - case _SC(':'): - NEXT(); - if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') } - else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); } - case _SC('*'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);} - else RETURN_TOKEN('*'); - case _SC('%'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);} - else RETURN_TOKEN('%'); - case _SC('-'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);} - else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);} - else RETURN_TOKEN('-'); - case _SC('+'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);} - else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);} - else RETURN_TOKEN('+'); - case RABBIT_EOB: - return 0; - default:{ - if (scisdigit(CUR_CHAR)) { - SQInteger ret = ReadNumber(); - RETURN_TOKEN(ret); - } - else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) { - SQInteger t = ReadID(); - RETURN_TOKEN(t); - } - else { - SQInteger c = CUR_CHAR; - if (sciscntrl((int)c)) Error(_SC("unexpected character(control)")); - NEXT(); - RETURN_TOKEN(c); - } - RETURN_TOKEN(0); - } - } - } - return 0; + _lasttokenline = _currentline; + while(CUR_CHAR != RABBIT_EOB) { + switch(CUR_CHAR){ + case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue; + case _SC('\n'): + _currentline++; + _prevtoken=_curtoken; + _curtoken=_SC('\n'); + NEXT(); + _currentcolumn=1; + continue; + case _SC('#'): LexLineComment(); continue; + case _SC('/'): + NEXT(); + switch(CUR_CHAR){ + case _SC('*'): + NEXT(); + LexBlockComment(); + continue; + case _SC('/'): + LexLineComment(); + continue; + case _SC('='): + NEXT(); + RETURN_TOKEN(TK_DIVEQ); + continue; + case _SC('>'): + NEXT(); + RETURN_TOKEN(TK_ATTR_CLOSE); + continue; + default: + RETURN_TOKEN('/'); + } + case _SC('='): + NEXT(); + if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') } + else { NEXT(); RETURN_TOKEN(TK_EQ); } + case _SC('<'): + NEXT(); + switch(CUR_CHAR) { + case _SC('='): + NEXT(); + if(CUR_CHAR == _SC('>')) { + NEXT(); + RETURN_TOKEN(TK_3WAYSCMP); + } + RETURN_TOKEN(TK_LE) + break; + case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break; + case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break; + case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break; + } + RETURN_TOKEN('<'); + case _SC('>'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} + else if(CUR_CHAR == _SC('>')){ + NEXT(); + if(CUR_CHAR == _SC('>')){ + NEXT(); + RETURN_TOKEN(TK_USHIFTR); + } + RETURN_TOKEN(TK_SHIFTR); + } + else { RETURN_TOKEN('>') } + case _SC('!'): + NEXT(); + if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')} + else { NEXT(); RETURN_TOKEN(TK_NE); } + case _SC('@'): { + SQInteger stype; + NEXT(); + if(CUR_CHAR != _SC('"')) { + RETURN_TOKEN('@'); + } + if((stype=ReadString('"',true))!=-1) { + RETURN_TOKEN(stype); + } + Error(_SC("error parsing the string")); + } + case _SC('"'): + case _SC('\''): { + SQInteger stype; + if((stype=ReadString(CUR_CHAR,false))!=-1){ + RETURN_TOKEN(stype); + } + Error(_SC("error parsing the string")); + } + case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'): + case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'): + {SQInteger ret = CUR_CHAR; + NEXT(); RETURN_TOKEN(ret); } + case _SC('.'): + NEXT(); + if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') } + NEXT(); + if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); } + NEXT(); + RETURN_TOKEN(TK_VARPARAMS); + case _SC('&'): + NEXT(); + if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') } + else { NEXT(); RETURN_TOKEN(TK_AND); } + case _SC('|'): + NEXT(); + if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') } + else { NEXT(); RETURN_TOKEN(TK_OR); } + case _SC(':'): + NEXT(); + if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') } + else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); } + case _SC('*'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);} + else RETURN_TOKEN('*'); + case _SC('%'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);} + else RETURN_TOKEN('%'); + case _SC('-'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);} + else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);} + else RETURN_TOKEN('-'); + case _SC('+'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);} + else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);} + else RETURN_TOKEN('+'); + case RABBIT_EOB: + return 0; + default:{ + if (scisdigit(CUR_CHAR)) { + SQInteger ret = ReadNumber(); + RETURN_TOKEN(ret); + } + else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) { + SQInteger t = ReadID(); + RETURN_TOKEN(t); + } + else { + SQInteger c = CUR_CHAR; + if (sciscntrl((int)c)) Error(_SC("unexpected character(control)")); + NEXT(); + RETURN_TOKEN(c); + } + RETURN_TOKEN(0); + } + } + } + return 0; } SQInteger SQLexer::GetIDType(const SQChar *s,SQInteger len) { - SQObjectPtr t; - if(_keywords->GetStr(s,len, t)) { - return SQInteger(_integer(t)); - } - return TK_IDENTIFIER; + SQObjectPtr t; + if(_keywords->GetStr(s,len, t)) { + return SQInteger(_integer(t)); + } + return TK_IDENTIFIER; } #ifdef SQUNICODE #if WCHAR_SIZE == 2 SQInteger SQLexer::AddUTF16(SQUnsignedInteger ch) { - if (ch >= 0x10000) - { - SQUnsignedInteger code = (ch - 0x10000); - APPEND_CHAR((SQChar)(0xD800 | (code >> 10))); - APPEND_CHAR((SQChar)(0xDC00 | (code & 0x3FF))); - return 2; - } - else { - APPEND_CHAR((SQChar)ch); - return 1; - } + if (ch >= 0x10000) + { + SQUnsignedInteger code = (ch - 0x10000); + APPEND_CHAR((SQChar)(0xD800 | (code >> 10))); + APPEND_CHAR((SQChar)(0xDC00 | (code & 0x3FF))); + return 2; + } + else { + APPEND_CHAR((SQChar)ch); + return 1; + } } #endif #else SQInteger SQLexer::AddUTF8(SQUnsignedInteger ch) { - if (ch < 0x80) { - APPEND_CHAR((char)ch); - return 1; - } - if (ch < 0x800) { - APPEND_CHAR((SQChar)((ch >> 6) | 0xC0)); - APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80)); - return 2; - } - if (ch < 0x10000) { - APPEND_CHAR((SQChar)((ch >> 12) | 0xE0)); - APPEND_CHAR((SQChar)(((ch >> 6) & 0x3F) | 0x80)); - APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80)); - return 3; - } - if (ch < 0x110000) { - APPEND_CHAR((SQChar)((ch >> 18) | 0xF0)); - APPEND_CHAR((SQChar)(((ch >> 12) & 0x3F) | 0x80)); - APPEND_CHAR((SQChar)(((ch >> 6) & 0x3F) | 0x80)); - APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80)); - return 4; - } - return 0; + if (ch < 0x80) { + APPEND_CHAR((char)ch); + return 1; + } + if (ch < 0x800) { + APPEND_CHAR((SQChar)((ch >> 6) | 0xC0)); + APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80)); + return 2; + } + if (ch < 0x10000) { + APPEND_CHAR((SQChar)((ch >> 12) | 0xE0)); + APPEND_CHAR((SQChar)(((ch >> 6) & 0x3F) | 0x80)); + APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80)); + return 3; + } + if (ch < 0x110000) { + APPEND_CHAR((SQChar)((ch >> 18) | 0xF0)); + APPEND_CHAR((SQChar)(((ch >> 12) & 0x3F) | 0x80)); + APPEND_CHAR((SQChar)(((ch >> 6) & 0x3F) | 0x80)); + APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80)); + return 4; + } + return 0; } #endif SQInteger SQLexer::ProcessStringHexEscape(SQChar *dest, SQInteger maxdigits) { - NEXT(); - if (!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); - SQInteger n = 0; - while (isxdigit(CUR_CHAR) && n < maxdigits) { - dest[n] = CUR_CHAR; - n++; - NEXT(); - } - dest[n] = 0; - return n; + NEXT(); + if (!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); + SQInteger n = 0; + while (isxdigit(CUR_CHAR) && n < maxdigits) { + dest[n] = CUR_CHAR; + n++; + NEXT(); + } + dest[n] = 0; + return n; } SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim) { - INIT_TEMP_STRING(); - NEXT(); - if(IS_EOB()) return -1; - for(;;) { - while(CUR_CHAR != ndelim) { - SQInteger x = CUR_CHAR; - switch (x) { - case RABBIT_EOB: - Error(_SC("unfinished string")); - return -1; - case _SC('\n'): - if(!verbatim) Error(_SC("newline in a constant")); - APPEND_CHAR(CUR_CHAR); NEXT(); - _currentline++; - break; - case _SC('\\'): - if(verbatim) { - APPEND_CHAR('\\'); NEXT(); - } - else { - NEXT(); - switch(CUR_CHAR) { - case _SC('x'): { - const SQInteger maxdigits = sizeof(SQChar) * 2; - SQChar temp[maxdigits + 1]; - ProcessStringHexEscape(temp, maxdigits); - SQChar *stemp; - APPEND_CHAR((SQChar)scstrtoul(temp, &stemp, 16)); - } - break; - case _SC('U'): - case _SC('u'): { - const SQInteger maxdigits = CUR_CHAR == 'u' ? 4 : 8; - SQChar temp[8 + 1]; - ProcessStringHexEscape(temp, maxdigits); - SQChar *stemp; + INIT_TEMP_STRING(); + NEXT(); + if(IS_EOB()) return -1; + for(;;) { + while(CUR_CHAR != ndelim) { + SQInteger x = CUR_CHAR; + switch (x) { + case RABBIT_EOB: + Error(_SC("unfinished string")); + return -1; + case _SC('\n'): + if(!verbatim) Error(_SC("newline in a constant")); + APPEND_CHAR(CUR_CHAR); NEXT(); + _currentline++; + break; + case _SC('\\'): + if(verbatim) { + APPEND_CHAR('\\'); NEXT(); + } + else { + NEXT(); + switch(CUR_CHAR) { + case _SC('x'): { + const SQInteger maxdigits = sizeof(SQChar) * 2; + SQChar temp[maxdigits + 1]; + ProcessStringHexEscape(temp, maxdigits); + SQChar *stemp; + APPEND_CHAR((SQChar)scstrtoul(temp, &stemp, 16)); + } + break; + case _SC('U'): + case _SC('u'): { + const SQInteger maxdigits = CUR_CHAR == 'u' ? 4 : 8; + SQChar temp[8 + 1]; + ProcessStringHexEscape(temp, maxdigits); + SQChar *stemp; #ifdef SQUNICODE #if WCHAR_SIZE == 2 - AddUTF16(scstrtoul(temp, &stemp, 16)); + AddUTF16(scstrtoul(temp, &stemp, 16)); #else - APPEND_CHAR((SQChar)scstrtoul(temp, &stemp, 16)); + APPEND_CHAR((SQChar)scstrtoul(temp, &stemp, 16)); #endif #else - AddUTF8(scstrtoul(temp, &stemp, 16)); + AddUTF8(scstrtoul(temp, &stemp, 16)); #endif - } - break; - case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break; - case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break; - case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break; - case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break; - case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break; - case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break; - case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break; - case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break; - case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break; - case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break; - case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break; - default: - Error(_SC("unrecognised escaper char")); - break; - } - } - break; - default: - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - } - NEXT(); - if(verbatim && CUR_CHAR == '"') { //double quotation - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - else { - break; - } - } - TERMINATE_BUFFER(); - SQInteger len = _longstr.size()-1; - if(ndelim == _SC('\'')) { - if(len == 0) Error(_SC("empty constant")); - if(len > 1) Error(_SC("constant too long")); - _nvalue = _longstr[0]; - return TK_INTEGER; - } - _svalue = &_longstr[0]; - return TK_STRING_LITERAL; + } + break; + case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break; + case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break; + case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break; + case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break; + case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break; + case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break; + case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break; + case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break; + case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break; + case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break; + case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break; + default: + Error(_SC("unrecognised escaper char")); + break; + } + } + break; + default: + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + } + NEXT(); + if(verbatim && CUR_CHAR == '"') { //double quotation + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + else { + break; + } + } + TERMINATE_BUFFER(); + SQInteger len = _longstr.size()-1; + if(ndelim == _SC('\'')) { + if(len == 0) Error(_SC("empty constant")); + if(len > 1) Error(_SC("constant too long")); + _nvalue = _longstr[0]; + return TK_INTEGER; + } + _svalue = &_longstr[0]; + return TK_STRING_LITERAL; } void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res) { - *res = 0; - while(*s != 0) - { - if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0'); - else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10); - else { assert(0); } - } + *res = 0; + while(*s != 0) + { + if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0'); + else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10); + else { assert(0); } + } } void LexInteger(const SQChar *s,SQUnsignedInteger *res) { - *res = 0; - while(*s != 0) - { - *res = (*res)*10+((*s++)-'0'); - } + *res = 0; + while(*s != 0) + { + *res = (*res)*10+((*s++)-'0'); + } } SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); } void LexOctal(const SQChar *s,SQUnsignedInteger *res) { - *res = 0; - while(*s != 0) - { - if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0'); - else { assert(0); } - } + *res = 0; + while(*s != 0) + { + if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0'); + else { assert(0); } + } } SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; } @@ -489,80 +489,80 @@ SQInteger SQLexer::ReadNumber() #define THEX 3 #define TSCIENTIFIC 4 #define TOCTAL 5 - SQInteger type = TINT, firstchar = CUR_CHAR; - SQChar *sTemp; - INIT_TEMP_STRING(); - NEXT(); - if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) { - if(scisodigit(CUR_CHAR)) { - type = TOCTAL; - while(scisodigit(CUR_CHAR)) { - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number")); - } - else { - NEXT(); - type = THEX; - while(isxdigit(CUR_CHAR)) { - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number")); - } - } - else { - APPEND_CHAR((int)firstchar); - while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) { - if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) type = TFLOAT; - if(isexponent(CUR_CHAR)) { - if(type != TFLOAT) Error(_SC("invalid numeric format")); - type = TSCIENTIFIC; - APPEND_CHAR(CUR_CHAR); - NEXT(); - if(CUR_CHAR == '+' || CUR_CHAR == '-'){ - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected")); - } + SQInteger type = TINT, firstchar = CUR_CHAR; + SQChar *sTemp; + INIT_TEMP_STRING(); + NEXT(); + if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) { + if(scisodigit(CUR_CHAR)) { + type = TOCTAL; + while(scisodigit(CUR_CHAR)) { + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number")); + } + else { + NEXT(); + type = THEX; + while(isxdigit(CUR_CHAR)) { + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number")); + } + } + else { + APPEND_CHAR((int)firstchar); + while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) { + if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) type = TFLOAT; + if(isexponent(CUR_CHAR)) { + if(type != TFLOAT) Error(_SC("invalid numeric format")); + type = TSCIENTIFIC; + APPEND_CHAR(CUR_CHAR); + NEXT(); + if(CUR_CHAR == '+' || CUR_CHAR == '-'){ + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected")); + } - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - } - TERMINATE_BUFFER(); - switch(type) { - case TSCIENTIFIC: - case TFLOAT: - _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp); - return TK_FLOAT; - case TINT: - LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue); - return TK_INTEGER; - case THEX: - LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); - return TK_INTEGER; - case TOCTAL: - LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); - return TK_INTEGER; - } - return 0; + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + } + TERMINATE_BUFFER(); + switch(type) { + case TSCIENTIFIC: + case TFLOAT: + _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp); + return TK_FLOAT; + case TINT: + LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue); + return TK_INTEGER; + case THEX: + LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); + return TK_INTEGER; + case TOCTAL: + LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); + return TK_INTEGER; + } + return 0; } SQInteger SQLexer::ReadID() { - SQInteger res; - INIT_TEMP_STRING(); - do { - APPEND_CHAR(CUR_CHAR); - NEXT(); - } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_')); - TERMINATE_BUFFER(); - res = GetIDType(&_longstr[0],_longstr.size() - 1); - if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) { - _svalue = &_longstr[0]; - } - return res; + SQInteger res; + INIT_TEMP_STRING(); + do { + APPEND_CHAR(CUR_CHAR); + NEXT(); + } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_')); + TERMINATE_BUFFER(); + res = GetIDType(&_longstr[0],_longstr.size() - 1); + if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) { + _svalue = &_longstr[0]; + } + return res; } diff --git a/rabbit/sqlexer.hpp b/rabbit/sqlexer.hpp index d2f223f..722c932 100644 --- a/rabbit/sqlexer.hpp +++ b/rabbit/sqlexer.hpp @@ -15,45 +15,45 @@ typedef unsigned char LexChar; struct SQLexer { - SQLexer(); - ~SQLexer(); - void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed); - void Error(const SQChar *err); - SQInteger Lex(); - const SQChar *Tok2Str(SQInteger tok); + SQLexer(); + ~SQLexer(); + void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed); + void Error(const SQChar *err); + SQInteger Lex(); + const SQChar *Tok2Str(SQInteger tok); private: - SQInteger GetIDType(const SQChar *s,SQInteger len); - SQInteger ReadString(SQInteger ndelim,bool verbatim); - SQInteger ReadNumber(); - void LexBlockComment(); - void LexLineComment(); - SQInteger ReadID(); - void Next(); + SQInteger GetIDType(const SQChar *s,SQInteger len); + SQInteger ReadString(SQInteger ndelim,bool verbatim); + SQInteger ReadNumber(); + void LexBlockComment(); + void LexLineComment(); + SQInteger ReadID(); + void Next(); #ifdef SQUNICODE #if WCHAR_SIZE == 2 - SQInteger AddUTF16(SQUnsignedInteger ch); + SQInteger AddUTF16(SQUnsignedInteger ch); #endif #else - SQInteger AddUTF8(SQUnsignedInteger ch); + SQInteger AddUTF8(SQUnsignedInteger ch); #endif - SQInteger ProcessStringHexEscape(SQChar *dest, SQInteger maxdigits); - SQInteger _curtoken; - SQTable *_keywords; - SQBool _reached_eof; + SQInteger ProcessStringHexEscape(SQChar *dest, SQInteger maxdigits); + SQInteger _curtoken; + SQTable *_keywords; + SQBool _reached_eof; public: - SQInteger _prevtoken; - SQInteger _currentline; - SQInteger _lasttokenline; - SQInteger _currentcolumn; - const SQChar *_svalue; - SQInteger _nvalue; - SQFloat _fvalue; - SQLEXREADFUNC _readf; - SQUserPointer _up; - LexChar _currdata; - SQSharedState *_sharedstate; - sqvector _longstr; - CompilerErrorFunc _errfunc; - void *_errtarget; + SQInteger _prevtoken; + SQInteger _currentline; + SQInteger _lasttokenline; + SQInteger _currentcolumn; + const SQChar *_svalue; + SQInteger _nvalue; + SQFloat _fvalue; + SQLEXREADFUNC _readf; + SQUserPointer _up; + LexChar _currdata; + SQSharedState *_sharedstate; + sqvector _longstr; + CompilerErrorFunc _errfunc; + void *_errtarget; }; diff --git a/rabbit/sqobject.cpp b/rabbit/sqobject.cpp index c6564ce..67de71a 100644 --- a/rabbit/sqobject.cpp +++ b/rabbit/sqobject.cpp @@ -18,539 +18,539 @@ const SQChar *IdType2Name(SQObjectType type) { - switch(_RAW_TYPE(type)) - { - case _RT_NULL:return _SC("null"); - case _RT_INTEGER:return _SC("integer"); - case _RT_FLOAT:return _SC("float"); - case _RT_BOOL:return _SC("bool"); - case _RT_STRING:return _SC("string"); - case _RT_TABLE:return _SC("table"); - case _RT_ARRAY:return _SC("array"); - case _RT_GENERATOR:return _SC("generator"); - case _RT_CLOSURE: - case _RT_NATIVECLOSURE: - return _SC("function"); - case _RT_USERDATA: - case _RT_USERPOINTER: - return _SC("userdata"); - case _RT_THREAD: return _SC("thread"); - case _RT_FUNCPROTO: return _SC("function"); - case _RT_CLASS: return _SC("class"); - case _RT_INSTANCE: return _SC("instance"); - case _RT_WEAKREF: return _SC("weakref"); - case _RT_OUTER: return _SC("outer"); - default: - return NULL; - } + switch(_RAW_TYPE(type)) + { + case _RT_NULL:return _SC("null"); + case _RT_INTEGER:return _SC("integer"); + case _RT_FLOAT:return _SC("float"); + case _RT_BOOL:return _SC("bool"); + case _RT_STRING:return _SC("string"); + case _RT_TABLE:return _SC("table"); + case _RT_ARRAY:return _SC("array"); + case _RT_GENERATOR:return _SC("generator"); + case _RT_CLOSURE: + case _RT_NATIVECLOSURE: + return _SC("function"); + case _RT_USERDATA: + case _RT_USERPOINTER: + return _SC("userdata"); + case _RT_THREAD: return _SC("thread"); + case _RT_FUNCPROTO: return _SC("function"); + case _RT_CLASS: return _SC("class"); + case _RT_INSTANCE: return _SC("instance"); + case _RT_WEAKREF: return _SC("weakref"); + case _RT_OUTER: return _SC("outer"); + default: + return NULL; + } } const SQChar *GetTypeName(const SQObjectPtr &obj1) { - return IdType2Name(sq_type(obj1)); + return IdType2Name(sq_type(obj1)); } SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len) { - SQString *str=ADD_STRING(ss,s,len); - return str; + SQString *str=ADD_STRING(ss,s,len); + return str; } void SQString::Release() { - REMOVE_STRING(_sharedstate,this); + REMOVE_STRING(_sharedstate,this); } SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) { - SQInteger idx = (SQInteger)TranslateIndex(refpos); - while(idx < _len){ - outkey = (SQInteger)idx; - outval = (SQInteger)((SQUnsignedInteger)_val[idx]); - //return idx for the next iteration - return ++idx; - } - //nothing to iterate anymore - return -1; + SQInteger idx = (SQInteger)TranslateIndex(refpos); + while(idx < _len){ + outkey = (SQInteger)idx; + outval = (SQInteger)((SQUnsignedInteger)_val[idx]); + //return idx for the next iteration + return ++idx; + } + //nothing to iterate anymore + return -1; } SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx) { - switch(sq_type(idx)){ - case OT_NULL: - return 0; - case OT_INTEGER: - return (SQUnsignedInteger)_integer(idx); - default: assert(0); break; - } - return 0; + switch(sq_type(idx)){ + case OT_NULL: + return 0; + case OT_INTEGER: + return (SQUnsignedInteger)_integer(idx); + default: assert(0); break; + } + return 0; } SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type) { - if(!_weakref) { - sq_new(_weakref,SQWeakRef); + if(!_weakref) { + sq_new(_weakref,SQWeakRef); #if defined(SQUSEDOUBLE) && !defined(_SQ64) - _weakref->_obj._unVal.raw = 0; //clean the whole union on 32 bits with double + _weakref->_obj._unVal.raw = 0; //clean the whole union on 32 bits with double #endif - _weakref->_obj._type = type; - _weakref->_obj._unVal.pRefCounted = this; - } - return _weakref; + _weakref->_obj._type = type; + _weakref->_obj._unVal.pRefCounted = this; + } + return _weakref; } SQRefCounted::~SQRefCounted() { - if(_weakref) { - _weakref->_obj._type = OT_NULL; - _weakref->_obj._unVal.pRefCounted = NULL; - } + if(_weakref) { + _weakref->_obj._type = OT_NULL; + _weakref->_obj._unVal.pRefCounted = NULL; + } } void SQWeakRef::Release() { - if(ISREFCOUNTED(_obj._type)) { - _obj._unVal.pRefCounted->_weakref = NULL; - } - sq_delete(this,SQWeakRef); + if(ISREFCOUNTED(_obj._type)) { + _obj._unVal.pRefCounted->_weakref = NULL; + } + sq_delete(this,SQWeakRef); } bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) { - if(_delegate) { - return _delegate->Get((*_ss(v)->_metamethods)[mm],res); - } - return false; + if(_delegate) { + return _delegate->Get((*_ss(v)->_metamethods)[mm],res); + } + return false; } bool SQDelegable::SetDelegate(SQTable *mt) { - SQTable *temp = mt; - if(temp == this) return false; - while (temp) { - if (temp->_delegate == this) return false; //cycle detected - temp = temp->_delegate; - } - if (mt) __ObjAddRef(mt); - __ObjRelease(_delegate); - _delegate = mt; - return true; + SQTable *temp = mt; + if(temp == this) return false; + while (temp) { + if (temp->_delegate == this) return false; //cycle detected + temp = temp->_delegate; + } + if (mt) __ObjAddRef(mt); + __ObjRelease(_delegate); + _delegate = mt; + return true; } bool SQGenerator::Yield(SQVM *v,SQInteger target) { - if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} - if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } - SQInteger size = v->_top-v->_stackbase; + if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} + if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } + SQInteger size = v->_top-v->_stackbase; - _stack.resize(size); - SQObject _this = v->_stack[v->_stackbase]; - _stack._vals[0] = ISREFCOUNTED(sq_type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(sq_type(_this))) : _this; - for(SQInteger n =1; n_stack[v->_stackbase+n]; - } - for(SQInteger j =0; j < size; j++) - { - v->_stack[v->_stackbase+j].Null(); - } + _stack.resize(size); + SQObject _this = v->_stack[v->_stackbase]; + _stack._vals[0] = ISREFCOUNTED(sq_type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(sq_type(_this))) : _this; + for(SQInteger n =1; n_stack[v->_stackbase+n]; + } + for(SQInteger j =0; j < size; j++) + { + v->_stack[v->_stackbase+j].Null(); + } - _ci = *v->ci; - _ci._generator=NULL; - for(SQInteger i=0;i<_ci._etraps;i++) { - _etraps.push_back(v->_etraps.top()); - v->_etraps.pop_back(); - // store relative stack base and size in case of resume to other _top - SQExceptionTrap &et = _etraps.back(); - et._stackbase -= v->_stackbase; - et._stacksize -= v->_stackbase; - } - _state=eSuspended; - return true; + _ci = *v->ci; + _ci._generator=NULL; + for(SQInteger i=0;i<_ci._etraps;i++) { + _etraps.push_back(v->_etraps.top()); + v->_etraps.pop_back(); + // store relative stack base and size in case of resume to other _top + SQExceptionTrap &et = _etraps.back(); + et._stackbase -= v->_stackbase; + et._stacksize -= v->_stackbase; + } + _state=eSuspended; + return true; } bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest) { - if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } - if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } - SQInteger size = _stack.size(); - SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]); - assert(target>=0 && target<=255); - SQInteger newbase = v->_top; - if(!v->EnterFrame(v->_top, v->_top + size, false)) - return false; - v->ci->_generator = this; - v->ci->_target = (SQInt32)target; - v->ci->_closure = _ci._closure; - v->ci->_ip = _ci._ip; - v->ci->_literals = _ci._literals; - v->ci->_ncalls = _ci._ncalls; - v->ci->_etraps = _ci._etraps; - v->ci->_root = _ci._root; + if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } + if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } + SQInteger size = _stack.size(); + SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]); + assert(target>=0 && target<=255); + SQInteger newbase = v->_top; + if(!v->EnterFrame(v->_top, v->_top + size, false)) + return false; + v->ci->_generator = this; + v->ci->_target = (SQInt32)target; + v->ci->_closure = _ci._closure; + v->ci->_ip = _ci._ip; + v->ci->_literals = _ci._literals; + v->ci->_ncalls = _ci._ncalls; + v->ci->_etraps = _ci._etraps; + v->ci->_root = _ci._root; - for(SQInteger i=0;i<_ci._etraps;i++) { - v->_etraps.push_back(_etraps.top()); - _etraps.pop_back(); - SQExceptionTrap &et = v->_etraps.back(); - // restore absolute stack base and size - et._stackbase += newbase; - et._stacksize += newbase; - } - SQObject _this = _stack._vals[0]; - v->_stack[v->_stackbase] = sq_type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this; + for(SQInteger i=0;i<_ci._etraps;i++) { + v->_etraps.push_back(_etraps.top()); + _etraps.pop_back(); + SQExceptionTrap &et = v->_etraps.back(); + // restore absolute stack base and size + et._stackbase += newbase; + et._stacksize += newbase; + } + SQObject _this = _stack._vals[0]; + v->_stack[v->_stackbase] = sq_type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this; - for(SQInteger n = 1; n_stack[v->_stackbase+n] = _stack._vals[n]; - _stack._vals[n].Null(); - } + for(SQInteger n = 1; n_stack[v->_stackbase+n] = _stack._vals[n]; + _stack._vals[n].Null(); + } - _state=eRunning; - if (v->_debughook) - v->CallDebugHook(_SC('c')); + _state=eRunning; + if (v->_debughook) + v->CallDebugHook(_SC('c')); - return true; + return true; } void SQArray::Extend(const SQArray *a){ - SQInteger xlen; - if((xlen=a->Size())) - for(SQInteger i=0;i_values[i]); + SQInteger xlen; + if((xlen=a->Size())) + for(SQInteger i=0;i_values[i]); } const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop) { - SQUnsignedInteger nvars=_nlocalvarinfos; - const SQChar *res=NULL; - if(nvars>=nseq){ - for(SQUnsignedInteger i=0;i=nop) - { - if(nseq==0){ - vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]); - res=_stringval(_localvarinfos[i]._name); - break; - } - nseq--; - } - } - } - return res; + SQUnsignedInteger nvars=_nlocalvarinfos; + const SQChar *res=NULL; + if(nvars>=nseq){ + for(SQUnsignedInteger i=0;i=nop) + { + if(nseq==0){ + vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]); + res=_stringval(_localvarinfos[i]._name); + break; + } + nseq--; + } + } + } + return res; } SQInteger SQFunctionProto::GetLine(SQInstruction *curr) { - SQInteger op = (SQInteger)(curr-_instructions); - SQInteger line=_lineinfos[0]._line; - SQInteger low = 0; - SQInteger high = _nlineinfos - 1; - SQInteger mid = 0; - while(low <= high) - { - mid = low + ((high - low) >> 1); - SQInteger curop = _lineinfos[mid]._op; - if(curop > op) - { - high = mid - 1; - } - else if(curop < op) { - if(mid < (_nlineinfos - 1) - && _lineinfos[mid + 1]._op >= op) { - break; - } - low = mid + 1; - } - else { //equal - break; - } - } + SQInteger op = (SQInteger)(curr-_instructions); + SQInteger line=_lineinfos[0]._line; + SQInteger low = 0; + SQInteger high = _nlineinfos - 1; + SQInteger mid = 0; + while(low <= high) + { + mid = low + ((high - low) >> 1); + SQInteger curop = _lineinfos[mid]._op; + if(curop > op) + { + high = mid - 1; + } + else if(curop < op) { + if(mid < (_nlineinfos - 1) + && _lineinfos[mid + 1]._op >= op) { + break; + } + low = mid + 1; + } + else { //equal + break; + } + } - while(mid > 0 && _lineinfos[mid]._op >= op) mid--; + while(mid > 0 && _lineinfos[mid]._op >= op) mid--; - line = _lineinfos[mid]._line; + line = _lineinfos[mid]._line; - return line; + return line; } SQClosure::~SQClosure() { - __ObjRelease(_root); - __ObjRelease(_env); - __ObjRelease(_base); - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + __ObjRelease(_root); + __ObjRelease(_env); + __ObjRelease(_base); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } #define _CHECK_IO(exp) { if(!exp)return false; } bool SafeWrite(HRABBITVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size) { - if(write(up,dest,size) != size) { - v->Raise_Error(_SC("io error (write function failure)")); - return false; - } - return true; + if(write(up,dest,size) != size) { + v->Raise_Error(_SC("io error (write function failure)")); + return false; + } + return true; } bool SafeRead(HRABBITVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size) { - if(size && read(up,dest,size) != size) { - v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated")); - return false; - } - return true; + if(size && read(up,dest,size) != size) { + v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated")); + return false; + } + return true; } bool WriteTag(HRABBITVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag) { - return SafeWrite(v,write,up,&tag,sizeof(tag)); + return SafeWrite(v,write,up,&tag,sizeof(tag)); } bool CheckTag(HRABBITVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag) { - SQUnsignedInteger32 t; - _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); - if(t != tag){ - v->Raise_Error(_SC("invalid or corrupted closure stream")); - return false; - } - return true; + SQUnsignedInteger32 t; + _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); + if(t != tag){ + v->Raise_Error(_SC("invalid or corrupted closure stream")); + return false; + } + return true; } bool WriteObject(HRABBITVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o) { - SQUnsignedInteger32 _type = (SQUnsignedInteger32)sq_type(o); - _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type))); - switch(sq_type(o)){ - case OT_STRING: - _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); - _CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len))); - break; - case OT_BOOL: - case OT_INTEGER: - _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break; - case OT_FLOAT: - _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break; - case OT_NULL: - break; - default: - v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o)); - return false; - } - return true; + SQUnsignedInteger32 _type = (SQUnsignedInteger32)sq_type(o); + _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type))); + switch(sq_type(o)){ + case OT_STRING: + _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); + _CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len))); + break; + case OT_BOOL: + case OT_INTEGER: + _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break; + case OT_FLOAT: + _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break; + case OT_NULL: + break; + default: + v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o)); + return false; + } + return true; } bool ReadObject(HRABBITVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) { - SQUnsignedInteger32 _type; - _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type))); - SQObjectType t = (SQObjectType)_type; - switch(t){ - case OT_STRING:{ - SQInteger len; - _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger))); - _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(sq_rsl(len)),sq_rsl(len))); - o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len); - } - break; - case OT_INTEGER:{ - SQInteger i; - _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break; - } - case OT_BOOL:{ - SQInteger i; - _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break; - } - case OT_FLOAT:{ - SQFloat f; - _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; - } - case OT_NULL: - o.Null(); - break; - default: - v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); - return false; - } - return true; + SQUnsignedInteger32 _type; + _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type))); + SQObjectType t = (SQObjectType)_type; + switch(t){ + case OT_STRING:{ + SQInteger len; + _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger))); + _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(sq_rsl(len)),sq_rsl(len))); + o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len); + } + break; + case OT_INTEGER:{ + SQInteger i; + _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break; + } + case OT_BOOL:{ + SQInteger i; + _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break; + } + case OT_FLOAT:{ + SQFloat f; + _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; + } + case OT_NULL: + o.Null(); + break; + default: + v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); + return false; + } + return true; } bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) { - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); - _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); - _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger))); - _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat))); - _CHECK_IO(_function->Save(v,up,write)); - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); - return true; + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger))); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat))); + _CHECK_IO(_function->Save(v,up,write)); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); + return true; } bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) { - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); - _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); - _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger))); - _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat))); - SQObjectPtr func; - _CHECK_IO(SQFunctionProto::Load(v,up,read,func)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); - ret = SQClosure::Create(_ss(v),_funcproto(func),_table(v->_roottable)->GetWeakRef(OT_TABLE)); - //FIXME: load an root for this closure - return true; + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger))); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat))); + SQObjectPtr func; + _CHECK_IO(SQFunctionProto::Load(v,up,read,func)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); + ret = SQClosure::Create(_ss(v),_funcproto(func),_table(v->_roottable)->GetWeakRef(OT_TABLE)); + //FIXME: load an root for this closure + return true; } SQFunctionProto::SQFunctionProto(SQSharedState *ss) { - _stacksize=0; - _bgenerator=false; - INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); + _stacksize=0; + _bgenerator=false; + INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } SQFunctionProto::~SQFunctionProto() { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) { - SQInteger i,nliterals = _nliterals,nparameters = _nparameters; - SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos; - SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions; - SQInteger ndefaultparams = _ndefaultparams; - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(WriteObject(v,up,write,_sourcename)); - _CHECK_IO(WriteObject(v,up,write,_name)); - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals))); - _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters))); - _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues))); - _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos))); - _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos))); - _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams))); - _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions))); - _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions))); - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); - for(i=0;iSave(v,up,write)); - } - _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize))); - _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator))); - _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams))); - return true; + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); + for(i=0;iSave(v,up,write)); + } + _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize))); + _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator))); + _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams))); + return true; } bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) { - SQInteger i, nliterals,nparameters; - SQInteger noutervalues ,nlocalvarinfos ; - SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ; - SQObjectPtr sourcename, name; - SQObjectPtr o; - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(ReadObject(v, up, read, sourcename)); - _CHECK_IO(ReadObject(v, up, read, name)); + SQInteger i, nliterals,nparameters; + SQInteger noutervalues ,nlocalvarinfos ; + SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ; + SQObjectPtr sourcename, name; + SQObjectPtr o; + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(ReadObject(v, up, read, sourcename)); + _CHECK_IO(ReadObject(v, up, read, name)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals))); - _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters))); - _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues))); - _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos))); - _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos))); - _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams))); - _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions))); - _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions))); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals))); + _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters))); + _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues))); + _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos))); + _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos))); + _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams))); + _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions))); + _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions))); - SQFunctionProto *f = SQFunctionProto::Create(NULL,ninstructions,nliterals,nparameters, - nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams); - SQObjectPtr proto = f; //gets a ref in case of failure - f->_sourcename = sourcename; - f->_name = name; + SQFunctionProto *f = SQFunctionProto::Create(NULL,ninstructions,nliterals,nparameters, + nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams); + SQObjectPtr proto = f; //gets a ref in case of failure + f->_sourcename = sourcename; + f->_name = name; - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - for(i = 0;i < nliterals; i++){ - _CHECK_IO(ReadObject(v, up, read, o)); - f->_literals[i] = o; - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + for(i = 0;i < nliterals; i++){ + _CHECK_IO(ReadObject(v, up, read, o)); + f->_literals[i] = o; + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - for(i = 0; i < nparameters; i++){ - _CHECK_IO(ReadObject(v, up, read, o)); - f->_parameters[i] = o; - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + for(i = 0; i < nparameters; i++){ + _CHECK_IO(ReadObject(v, up, read, o)); + f->_parameters[i] = o; + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - for(i = 0; i < noutervalues; i++){ - SQUnsignedInteger type; - SQObjectPtr name; - _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); - _CHECK_IO(ReadObject(v, up, read, o)); - _CHECK_IO(ReadObject(v, up, read, name)); - f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type); - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + for(i = 0; i < noutervalues; i++){ + SQUnsignedInteger type; + SQObjectPtr name; + _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); + _CHECK_IO(ReadObject(v, up, read, o)); + _CHECK_IO(ReadObject(v, up, read, name)); + f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type); + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - for(i = 0; i < nlocalvarinfos; i++){ - SQLocalVarInfo lvi; - _CHECK_IO(ReadObject(v, up, read, lvi._name)); - _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger))); - _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger))); - _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger))); - f->_localvarinfos[i] = lvi; - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos)); + for(i = 0; i < nlocalvarinfos; i++){ + SQLocalVarInfo lvi; + _CHECK_IO(ReadObject(v, up, read, lvi._name)); + _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger))); + _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger))); + _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger))); + f->_localvarinfos[i] = lvi; + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - for(i = 0; i < nfunctions; i++){ - _CHECK_IO(_funcproto(o)->Load(v, up, read, o)); - f->_functions[i] = o; - } - _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize))); - _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator))); - _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams))); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + for(i = 0; i < nfunctions; i++){ + _CHECK_IO(_funcproto(o)->Load(v, up, read, o)); + f->_functions[i] = o; + } + _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize))); + _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator))); + _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams))); - ret = f; - return true; + ret = f; + return true; } diff --git a/rabbit/sqobject.hpp b/rabbit/sqobject.hpp index c4f160b..8c0f8f8 100644 --- a/rabbit/sqobject.hpp +++ b/rabbit/sqobject.hpp @@ -22,39 +22,39 @@ struct SQSharedState; enum SQMetaMethod{ - MT_ADD=0, - MT_SUB=1, - MT_MUL=2, - MT_DIV=3, - MT_UNM=4, - MT_MODULO=5, - MT_SET=6, - MT_GET=7, - MT_TYPEOF=8, - MT_NEXTI=9, - MT_CMP=10, - MT_CALL=11, - MT_CLONED=12, - MT_NEWSLOT=13, - MT_DELSLOT=14, - MT_TOSTRING=15, - MT_NEWMEMBER=16, - MT_INHERITED=17, - MT_LAST = 18 + MT_ADD=0, + MT_SUB=1, + MT_MUL=2, + MT_DIV=3, + MT_UNM=4, + MT_MODULO=5, + MT_SET=6, + MT_GET=7, + MT_TYPEOF=8, + MT_NEXTI=9, + MT_CMP=10, + MT_CALL=11, + MT_CLONED=12, + MT_NEWSLOT=13, + MT_DELSLOT=14, + MT_TOSTRING=15, + MT_NEWMEMBER=16, + MT_INHERITED=17, + MT_LAST = 18 }; -#define MM_ADD _SC("_add") -#define MM_SUB _SC("_sub") -#define MM_MUL _SC("_mul") -#define MM_DIV _SC("_div") -#define MM_UNM _SC("_unm") +#define MM_ADD _SC("_add") +#define MM_SUB _SC("_sub") +#define MM_MUL _SC("_mul") +#define MM_DIV _SC("_div") +#define MM_UNM _SC("_unm") #define MM_MODULO _SC("_modulo") -#define MM_SET _SC("_set") -#define MM_GET _SC("_get") +#define MM_SET _SC("_set") +#define MM_GET _SC("_get") #define MM_TYPEOF _SC("_typeof") -#define MM_NEXTI _SC("_nexti") -#define MM_CMP _SC("_cmp") -#define MM_CALL _SC("_call") +#define MM_NEXTI _SC("_nexti") +#define MM_CMP _SC("_cmp") +#define MM_CALL _SC("_call") #define MM_CLONED _SC("_cloned") #define MM_NEWSLOT _SC("_newslot") #define MM_DELSLOT _SC("_delslot") @@ -64,46 +64,46 @@ enum SQMetaMethod{ #define _CONSTRUCT_VECTOR(type,size,ptr) { \ - for(SQInteger n = 0; n < ((SQInteger)size); n++) { \ - new (&ptr[n]) type(); \ - } \ + for(SQInteger n = 0; n < ((SQInteger)size); n++) { \ + new (&ptr[n]) type(); \ + } \ } #define _DESTRUCT_VECTOR(type,size,ptr) { \ - for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \ - ptr[nl].~type(); \ - } \ + for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \ + ptr[nl].~type(); \ + } \ } #define _COPY_VECTOR(dest,src,size) { \ - for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ - dest[_n_] = src[_n_]; \ - } \ + for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ + dest[_n_] = src[_n_]; \ + } \ } #define _NULL_SQOBJECT_VECTOR(vec,size) { \ - for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ - vec[_n_].Null(); \ - } \ + for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ + vec[_n_].Null(); \ + } \ } #define MINPOWER2 4 struct SQRefCounted { - SQUnsignedInteger _uiRef; - struct SQWeakRef *_weakref; - SQRefCounted() { _uiRef = 0; _weakref = NULL; } - virtual ~SQRefCounted(); - SQWeakRef *GetWeakRef(SQObjectType type); - virtual void Release()=0; + SQUnsignedInteger _uiRef; + struct SQWeakRef *_weakref; + SQRefCounted() { _uiRef = 0; _weakref = NULL; } + virtual ~SQRefCounted(); + SQWeakRef *GetWeakRef(SQObjectType type); + virtual void Release()=0; }; struct SQWeakRef : SQRefCounted { - void Release(); - SQObject _obj; + void Release(); + SQObject _obj; }; #define _realval(o) (sq_type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj) @@ -111,26 +111,26 @@ struct SQWeakRef : SQRefCounted struct SQObjectPtr; #define __AddRef(type,unval) if(ISREFCOUNTED(type)) \ - { \ - unval.pRefCounted->_uiRef++; \ - } + { \ + unval.pRefCounted->_uiRef++; \ + } #define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0)) \ - { \ - unval.pRefCounted->Release(); \ - } + { \ + unval.pRefCounted->Release(); \ + } #define __ObjRelease(obj) { \ - if((obj)) { \ - (obj)->_uiRef--; \ - if((obj)->_uiRef == 0) \ - (obj)->Release(); \ - (obj) = NULL; \ - } \ + if((obj)) { \ + (obj)->_uiRef--; \ + if((obj)->_uiRef == 0) \ + (obj)->Release(); \ + (obj) = NULL; \ + } \ } #define __ObjAddRef(obj) { \ - (obj)->_uiRef++; \ + (obj)->_uiRef++; \ } #define is_delegable(t) (sq_type(t)&SQOBJECT_DELEGABLE) @@ -170,146 +170,146 @@ struct SQObjectPtr; #endif #define _REF_TYPE_DECL(type,_class,sym) \ - SQObjectPtr(_class * x) \ - { \ - SQ_OBJECT_RAWINIT() \ - _type=type; \ - _unVal.sym = x; \ - assert(_unVal.pTable); \ - _unVal.pRefCounted->_uiRef++; \ - } \ - inline SQObjectPtr& operator=(_class *x) \ - { \ - SQObjectType tOldType; \ - SQObjectValue unOldVal; \ - tOldType=_type; \ - unOldVal=_unVal; \ - _type = type; \ - SQ_REFOBJECT_INIT() \ - _unVal.sym = x; \ - _unVal.pRefCounted->_uiRef++; \ - __Release(tOldType,unOldVal); \ - return *this; \ - } + SQObjectPtr(_class * x) \ + { \ + SQ_OBJECT_RAWINIT() \ + _type=type; \ + _unVal.sym = x; \ + assert(_unVal.pTable); \ + _unVal.pRefCounted->_uiRef++; \ + } \ + inline SQObjectPtr& operator=(_class *x) \ + { \ + SQObjectType tOldType; \ + SQObjectValue unOldVal; \ + tOldType=_type; \ + unOldVal=_unVal; \ + _type = type; \ + SQ_REFOBJECT_INIT() \ + _unVal.sym = x; \ + _unVal.pRefCounted->_uiRef++; \ + __Release(tOldType,unOldVal); \ + return *this; \ + } #define _SCALAR_TYPE_DECL(type,_class,sym) \ - SQObjectPtr(_class x) \ - { \ - SQ_OBJECT_RAWINIT() \ - _type=type; \ - _unVal.sym = x; \ - } \ - inline SQObjectPtr& operator=(_class x) \ - { \ - __Release(_type,_unVal); \ - _type = type; \ - SQ_OBJECT_RAWINIT() \ - _unVal.sym = x; \ - return *this; \ - } + SQObjectPtr(_class x) \ + { \ + SQ_OBJECT_RAWINIT() \ + _type=type; \ + _unVal.sym = x; \ + } \ + inline SQObjectPtr& operator=(_class x) \ + { \ + __Release(_type,_unVal); \ + _type = type; \ + SQ_OBJECT_RAWINIT() \ + _unVal.sym = x; \ + return *this; \ + } struct SQObjectPtr : public SQObject { - SQObjectPtr() - { - SQ_OBJECT_RAWINIT() - _type=OT_NULL; - _unVal.pUserPointer=NULL; - } - SQObjectPtr(const SQObjectPtr &o) - { - _type = o._type; - _unVal = o._unVal; - __AddRef(_type,_unVal); - } - SQObjectPtr(const SQObject &o) - { - _type = o._type; - _unVal = o._unVal; - __AddRef(_type,_unVal); - } - _REF_TYPE_DECL(OT_TABLE,SQTable,pTable) - _REF_TYPE_DECL(OT_CLASS,SQClass,pClass) - _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance) - _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray) - _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure) - _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure) - _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter) - _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator) - _REF_TYPE_DECL(OT_STRING,SQString,pString) - _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData) - _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef) - _REF_TYPE_DECL(OT_THREAD,SQVM,pThread) - _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto) + SQObjectPtr() + { + SQ_OBJECT_RAWINIT() + _type=OT_NULL; + _unVal.pUserPointer=NULL; + } + SQObjectPtr(const SQObjectPtr &o) + { + _type = o._type; + _unVal = o._unVal; + __AddRef(_type,_unVal); + } + SQObjectPtr(const SQObject &o) + { + _type = o._type; + _unVal = o._unVal; + __AddRef(_type,_unVal); + } + _REF_TYPE_DECL(OT_TABLE,SQTable,pTable) + _REF_TYPE_DECL(OT_CLASS,SQClass,pClass) + _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance) + _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray) + _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure) + _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure) + _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter) + _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator) + _REF_TYPE_DECL(OT_STRING,SQString,pString) + _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData) + _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef) + _REF_TYPE_DECL(OT_THREAD,SQVM,pThread) + _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto) - _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger) - _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat) - _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer) + _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger) + _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat) + _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer) - SQObjectPtr(bool bBool) - { - SQ_OBJECT_RAWINIT() - _type = OT_BOOL; - _unVal.nInteger = bBool?1:0; - } - inline SQObjectPtr& operator=(bool b) - { - __Release(_type,_unVal); - SQ_OBJECT_RAWINIT() - _type = OT_BOOL; - _unVal.nInteger = b?1:0; - return *this; - } + SQObjectPtr(bool bBool) + { + SQ_OBJECT_RAWINIT() + _type = OT_BOOL; + _unVal.nInteger = bBool?1:0; + } + inline SQObjectPtr& operator=(bool b) + { + __Release(_type,_unVal); + SQ_OBJECT_RAWINIT() + _type = OT_BOOL; + _unVal.nInteger = b?1:0; + return *this; + } - ~SQObjectPtr() - { - __Release(_type,_unVal); - } + ~SQObjectPtr() + { + __Release(_type,_unVal); + } - inline SQObjectPtr& operator=(const SQObjectPtr& obj) - { - SQObjectType tOldType; - SQObjectValue unOldVal; - tOldType=_type; - unOldVal=_unVal; - _unVal = obj._unVal; - _type = obj._type; - __AddRef(_type,_unVal); - __Release(tOldType,unOldVal); - return *this; - } - inline SQObjectPtr& operator=(const SQObject& obj) - { - SQObjectType tOldType; - SQObjectValue unOldVal; - tOldType=_type; - unOldVal=_unVal; - _unVal = obj._unVal; - _type = obj._type; - __AddRef(_type,_unVal); - __Release(tOldType,unOldVal); - return *this; - } - inline void Null() - { - SQObjectType tOldType = _type; - SQObjectValue unOldVal = _unVal; - _type = OT_NULL; - _unVal.raw = (SQRawObjectVal)NULL; - __Release(tOldType ,unOldVal); - } - private: - SQObjectPtr(const SQChar *){} //safety + inline SQObjectPtr& operator=(const SQObjectPtr& obj) + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType=_type; + unOldVal=_unVal; + _unVal = obj._unVal; + _type = obj._type; + __AddRef(_type,_unVal); + __Release(tOldType,unOldVal); + return *this; + } + inline SQObjectPtr& operator=(const SQObject& obj) + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType=_type; + unOldVal=_unVal; + _unVal = obj._unVal; + _type = obj._type; + __AddRef(_type,_unVal); + __Release(tOldType,unOldVal); + return *this; + } + inline void Null() + { + SQObjectType tOldType = _type; + SQObjectValue unOldVal = _unVal; + _type = OT_NULL; + _unVal.raw = (SQRawObjectVal)NULL; + __Release(tOldType ,unOldVal); + } + private: + SQObjectPtr(const SQChar *){} //safety }; inline void _Swap(SQObject &a,SQObject &b) { - SQObjectType tOldType = a._type; - SQObjectValue unOldVal = a._unVal; - a._type = b._type; - a._unVal = b._unVal; - b._type = tOldType; - b._unVal = unOldVal; + SQObjectType tOldType = a._type; + SQObjectValue unOldVal = a._unVal; + a._type = b._type; + a._unVal = b._unVal; + b._type = tOldType; + b._unVal = unOldVal; } #define ADD_TO_CHAIN(chain,obj) ((void)0) @@ -318,9 +318,9 @@ inline void _Swap(SQObject &a,SQObject &b) #define INIT_CHAIN() ((void)0) struct SQDelegable : public CHAINABLE_OBJ { - bool SetDelegate(SQTable *m); - virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); - SQTable *_delegate; + bool SetDelegate(SQTable *m); + virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); + SQTable *_delegate; }; SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx); diff --git a/rabbit/sqopcodes.hpp b/rabbit/sqopcodes.hpp index 33102ff..d4accdd 100644 --- a/rabbit/sqopcodes.hpp +++ b/rabbit/sqopcodes.hpp @@ -11,126 +11,126 @@ #define MAX_LITERALS ((SQInteger)0x7FFFFFFF) enum BitWiseOP { - BW_AND = 0, - BW_OR = 2, - BW_XOR = 3, - BW_SHIFTL = 4, - BW_SHIFTR = 5, - BW_USHIFTR = 6 + BW_AND = 0, + BW_OR = 2, + BW_XOR = 3, + BW_SHIFTL = 4, + BW_SHIFTR = 5, + BW_USHIFTR = 6 }; enum CmpOP { - CMP_G = 0, - CMP_GE = 2, - CMP_L = 3, - CMP_LE = 4, - CMP_3W = 5 + CMP_G = 0, + CMP_GE = 2, + CMP_L = 3, + CMP_LE = 4, + CMP_3W = 5 }; enum NewObjectType { - NOT_TABLE = 0, - NOT_ARRAY = 1, - NOT_CLASS = 2 + NOT_TABLE = 0, + NOT_ARRAY = 1, + NOT_CLASS = 2 }; enum AppendArrayType { - AAT_STACK = 0, - AAT_LITERAL = 1, - AAT_INT = 2, - AAT_FLOAT = 3, - AAT_BOOL = 4 + AAT_STACK = 0, + AAT_LITERAL = 1, + AAT_INT = 2, + AAT_FLOAT = 3, + AAT_BOOL = 4 }; enum SQOpcode { - _OP_LINE= 0x00, - _OP_LOAD= 0x01, - _OP_LOADINT= 0x02, - _OP_LOADFLOAT= 0x03, - _OP_DLOAD= 0x04, - _OP_TAILCALL= 0x05, - _OP_CALL= 0x06, - _OP_PREPCALL= 0x07, - _OP_PREPCALLK= 0x08, - _OP_GETK= 0x09, - _OP_MOVE= 0x0A, - _OP_NEWSLOT= 0x0B, - _OP_DELETE= 0x0C, - _OP_SET= 0x0D, - _OP_GET= 0x0E, - _OP_EQ= 0x0F, - _OP_NE= 0x10, - _OP_ADD= 0x11, - _OP_SUB= 0x12, - _OP_MUL= 0x13, - _OP_DIV= 0x14, - _OP_MOD= 0x15, - _OP_BITW= 0x16, - _OP_RETURN= 0x17, - _OP_LOADNULLS= 0x18, - _OP_LOADROOT= 0x19, - _OP_LOADBOOL= 0x1A, - _OP_DMOVE= 0x1B, - _OP_JMP= 0x1C, - //_OP_JNZ= 0x1D, - _OP_JCMP= 0x1D, - _OP_JZ= 0x1E, - _OP_SETOUTER= 0x1F, - _OP_GETOUTER= 0x20, - _OP_NEWOBJ= 0x21, - _OP_APPENDARRAY= 0x22, - _OP_COMPARITH= 0x23, - _OP_INC= 0x24, - _OP_INCL= 0x25, - _OP_PINC= 0x26, - _OP_PINCL= 0x27, - _OP_CMP= 0x28, - _OP_EXISTS= 0x29, - _OP_INSTANCEOF= 0x2A, - _OP_AND= 0x2B, - _OP_OR= 0x2C, - _OP_NEG= 0x2D, - _OP_NOT= 0x2E, - _OP_BWNOT= 0x2F, - _OP_CLOSURE= 0x30, - _OP_YIELD= 0x31, - _OP_RESUME= 0x32, - _OP_FOREACH= 0x33, - _OP_POSTFOREACH= 0x34, - _OP_CLONE= 0x35, - _OP_TYPEOF= 0x36, - _OP_PUSHTRAP= 0x37, - _OP_POPTRAP= 0x38, - _OP_THROW= 0x39, - _OP_NEWSLOTA= 0x3A, - _OP_GETBASE= 0x3B, - _OP_CLOSE= 0x3C + _OP_LINE= 0x00, + _OP_LOAD= 0x01, + _OP_LOADINT= 0x02, + _OP_LOADFLOAT= 0x03, + _OP_DLOAD= 0x04, + _OP_TAILCALL= 0x05, + _OP_CALL= 0x06, + _OP_PREPCALL= 0x07, + _OP_PREPCALLK= 0x08, + _OP_GETK= 0x09, + _OP_MOVE= 0x0A, + _OP_NEWSLOT= 0x0B, + _OP_DELETE= 0x0C, + _OP_SET= 0x0D, + _OP_GET= 0x0E, + _OP_EQ= 0x0F, + _OP_NE= 0x10, + _OP_ADD= 0x11, + _OP_SUB= 0x12, + _OP_MUL= 0x13, + _OP_DIV= 0x14, + _OP_MOD= 0x15, + _OP_BITW= 0x16, + _OP_RETURN= 0x17, + _OP_LOADNULLS= 0x18, + _OP_LOADROOT= 0x19, + _OP_LOADBOOL= 0x1A, + _OP_DMOVE= 0x1B, + _OP_JMP= 0x1C, + //_OP_JNZ= 0x1D, + _OP_JCMP= 0x1D, + _OP_JZ= 0x1E, + _OP_SETOUTER= 0x1F, + _OP_GETOUTER= 0x20, + _OP_NEWOBJ= 0x21, + _OP_APPENDARRAY= 0x22, + _OP_COMPARITH= 0x23, + _OP_INC= 0x24, + _OP_INCL= 0x25, + _OP_PINC= 0x26, + _OP_PINCL= 0x27, + _OP_CMP= 0x28, + _OP_EXISTS= 0x29, + _OP_INSTANCEOF= 0x2A, + _OP_AND= 0x2B, + _OP_OR= 0x2C, + _OP_NEG= 0x2D, + _OP_NOT= 0x2E, + _OP_BWNOT= 0x2F, + _OP_CLOSURE= 0x30, + _OP_YIELD= 0x31, + _OP_RESUME= 0x32, + _OP_FOREACH= 0x33, + _OP_POSTFOREACH= 0x34, + _OP_CLONE= 0x35, + _OP_TYPEOF= 0x36, + _OP_PUSHTRAP= 0x37, + _OP_POPTRAP= 0x38, + _OP_THROW= 0x39, + _OP_NEWSLOTA= 0x3A, + _OP_GETBASE= 0x3B, + _OP_CLOSE= 0x3C }; struct SQInstructionDesc { - const SQChar *name; + const SQChar *name; }; struct SQInstruction { - SQInstruction(){}; - SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0) - { op = (unsigned char)_op; - _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1; - _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3; - } + SQInstruction(){}; + SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0) + { op = (unsigned char)_op; + _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1; + _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3; + } - SQInt32 _arg1; - unsigned char op; - unsigned char _arg0; - unsigned char _arg2; - unsigned char _arg3; + SQInt32 _arg1; + unsigned char op; + unsigned char _arg0; + unsigned char _arg2; + unsigned char _arg3; }; #include typedef sqvector SQInstructionVec; -#define NEW_SLOT_ATTRIBUTES_FLAG 0x01 -#define NEW_SLOT_STATIC_FLAG 0x02 +#define NEW_SLOT_ATTRIBUTES_FLAG 0x01 +#define NEW_SLOT_STATIC_FLAG 0x02 diff --git a/rabbit/sqstate.cpp b/rabbit/sqstate.cpp index 4e49326..fd2e862 100644 --- a/rabbit/sqstate.cpp +++ b/rabbit/sqstate.cpp @@ -18,356 +18,356 @@ SQSharedState::SQSharedState() { - _compilererrorhandler = NULL; - _printfunc = NULL; - _errorfunc = NULL; - _debuginfo = false; - _notifyallexceptions = false; - _foreignptr = NULL; - _releasehook = NULL; + _compilererrorhandler = NULL; + _printfunc = NULL; + _errorfunc = NULL; + _debuginfo = false; + _notifyallexceptions = false; + _foreignptr = NULL; + _releasehook = NULL; } #define newsysstring(s) { \ - _systemstrings->push_back(SQString::Create(this,s)); \ - } + _systemstrings->push_back(SQString::Create(this,s)); \ + } #define newmetamethod(s) { \ - _metamethods->push_back(SQString::Create(this,s)); \ - _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ - } + _metamethods->push_back(SQString::Create(this,s)); \ + _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ + } bool CompileTypemask(SQIntVec &res,const SQChar *typemask) { - SQInteger i = 0; - SQInteger mask = 0; - while(typemask[i] != 0) { - switch(typemask[i]) { - case 'o': mask |= _RT_NULL; break; - case 'i': mask |= _RT_INTEGER; break; - case 'f': mask |= _RT_FLOAT; break; - case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break; - case 's': mask |= _RT_STRING; break; - case 't': mask |= _RT_TABLE; break; - case 'a': mask |= _RT_ARRAY; break; - case 'u': mask |= _RT_USERDATA; break; - case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break; - case 'b': mask |= _RT_BOOL; break; - case 'g': mask |= _RT_GENERATOR; break; - case 'p': mask |= _RT_USERPOINTER; break; - case 'v': mask |= _RT_THREAD; break; - case 'x': mask |= _RT_INSTANCE; break; - case 'y': mask |= _RT_CLASS; break; - case 'r': mask |= _RT_WEAKREF; break; - case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue; - case ' ': i++; continue; //ignores spaces - default: - return false; - } - i++; - if(typemask[i] == '|') { - i++; - if(typemask[i] == 0) - return false; - continue; - } - res.push_back(mask); - mask = 0; + SQInteger i = 0; + SQInteger mask = 0; + while(typemask[i] != 0) { + switch(typemask[i]) { + case 'o': mask |= _RT_NULL; break; + case 'i': mask |= _RT_INTEGER; break; + case 'f': mask |= _RT_FLOAT; break; + case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break; + case 's': mask |= _RT_STRING; break; + case 't': mask |= _RT_TABLE; break; + case 'a': mask |= _RT_ARRAY; break; + case 'u': mask |= _RT_USERDATA; break; + case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break; + case 'b': mask |= _RT_BOOL; break; + case 'g': mask |= _RT_GENERATOR; break; + case 'p': mask |= _RT_USERPOINTER; break; + case 'v': mask |= _RT_THREAD; break; + case 'x': mask |= _RT_INSTANCE; break; + case 'y': mask |= _RT_CLASS; break; + case 'r': mask |= _RT_WEAKREF; break; + case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue; + case ' ': i++; continue; //ignores spaces + default: + return false; + } + i++; + if(typemask[i] == '|') { + i++; + if(typemask[i] == 0) + return false; + continue; + } + res.push_back(mask); + mask = 0; - } - return true; + } + return true; } SQTable *CreateDefaultDelegate(SQSharedState *ss,const SQRegFunction *funcz) { - SQInteger i=0; - SQTable *t=SQTable::Create(ss,0); - while(funcz[i].name!=0){ - SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0); - nc->_nparamscheck = funcz[i].nparamscheck; - nc->_name = SQString::Create(ss,funcz[i].name); - if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) - return NULL; - t->NewSlot(SQString::Create(ss,funcz[i].name),nc); - i++; - } - return t; + SQInteger i=0; + SQTable *t=SQTable::Create(ss,0); + while(funcz[i].name!=0){ + SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0); + nc->_nparamscheck = funcz[i].nparamscheck; + nc->_name = SQString::Create(ss,funcz[i].name); + if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) + return NULL; + t->NewSlot(SQString::Create(ss,funcz[i].name),nc); + i++; + } + return t; } void SQSharedState::Init() { - _scratchpad=NULL; - _scratchpadsize=0; - _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable)); - new (_stringtable) SQStringTable(this); - sq_new(_metamethods,SQObjectPtrVec); - sq_new(_systemstrings,SQObjectPtrVec); - sq_new(_types,SQObjectPtrVec); - _metamethodsmap = SQTable::Create(this,MT_LAST-1); - //adding type strings to avoid memory trashing - //types names - newsysstring(_SC("null")); - newsysstring(_SC("table")); - newsysstring(_SC("array")); - newsysstring(_SC("closure")); - newsysstring(_SC("string")); - newsysstring(_SC("userdata")); - newsysstring(_SC("integer")); - newsysstring(_SC("float")); - newsysstring(_SC("userpointer")); - newsysstring(_SC("function")); - newsysstring(_SC("generator")); - newsysstring(_SC("thread")); - newsysstring(_SC("class")); - newsysstring(_SC("instance")); - newsysstring(_SC("bool")); - //meta methods - newmetamethod(MM_ADD); - newmetamethod(MM_SUB); - newmetamethod(MM_MUL); - newmetamethod(MM_DIV); - newmetamethod(MM_UNM); - newmetamethod(MM_MODULO); - newmetamethod(MM_SET); - newmetamethod(MM_GET); - newmetamethod(MM_TYPEOF); - newmetamethod(MM_NEXTI); - newmetamethod(MM_CMP); - newmetamethod(MM_CALL); - newmetamethod(MM_CLONED); - newmetamethod(MM_NEWSLOT); - newmetamethod(MM_DELSLOT); - newmetamethod(MM_TOSTRING); - newmetamethod(MM_NEWMEMBER); - newmetamethod(MM_INHERITED); + _scratchpad=NULL; + _scratchpadsize=0; + _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable)); + new (_stringtable) SQStringTable(this); + sq_new(_metamethods,SQObjectPtrVec); + sq_new(_systemstrings,SQObjectPtrVec); + sq_new(_types,SQObjectPtrVec); + _metamethodsmap = SQTable::Create(this,MT_LAST-1); + //adding type strings to avoid memory trashing + //types names + newsysstring(_SC("null")); + newsysstring(_SC("table")); + newsysstring(_SC("array")); + newsysstring(_SC("closure")); + newsysstring(_SC("string")); + newsysstring(_SC("userdata")); + newsysstring(_SC("integer")); + newsysstring(_SC("float")); + newsysstring(_SC("userpointer")); + newsysstring(_SC("function")); + newsysstring(_SC("generator")); + newsysstring(_SC("thread")); + newsysstring(_SC("class")); + newsysstring(_SC("instance")); + newsysstring(_SC("bool")); + //meta methods + newmetamethod(MM_ADD); + newmetamethod(MM_SUB); + newmetamethod(MM_MUL); + newmetamethod(MM_DIV); + newmetamethod(MM_UNM); + newmetamethod(MM_MODULO); + newmetamethod(MM_SET); + newmetamethod(MM_GET); + newmetamethod(MM_TYPEOF); + newmetamethod(MM_NEXTI); + newmetamethod(MM_CMP); + newmetamethod(MM_CALL); + newmetamethod(MM_CLONED); + newmetamethod(MM_NEWSLOT); + newmetamethod(MM_DELSLOT); + newmetamethod(MM_TOSTRING); + newmetamethod(MM_NEWMEMBER); + newmetamethod(MM_INHERITED); - _constructoridx = SQString::Create(this,_SC("constructor")); - _registry = SQTable::Create(this,0); - _consts = SQTable::Create(this,0); - _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz); - _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz); - _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz); - _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz); - _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz); - _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz); - _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz); - _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz); - _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz); - _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz); + _constructoridx = SQString::Create(this,_SC("constructor")); + _registry = SQTable::Create(this,0); + _consts = SQTable::Create(this,0); + _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz); + _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz); + _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz); + _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz); + _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz); + _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz); + _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz); + _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz); + _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz); + _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz); } SQSharedState::~SQSharedState() { - if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; } - _constructoridx.Null(); - _table(_registry)->Finalize(); - _table(_consts)->Finalize(); - _table(_metamethodsmap)->Finalize(); - _registry.Null(); - _consts.Null(); - _metamethodsmap.Null(); - while(!_systemstrings->empty()) { - _systemstrings->back().Null(); - _systemstrings->pop_back(); - } - _thread(_root_vm)->Finalize(); - _root_vm.Null(); - _table_default_delegate.Null(); - _array_default_delegate.Null(); - _string_default_delegate.Null(); - _number_default_delegate.Null(); - _closure_default_delegate.Null(); - _generator_default_delegate.Null(); - _thread_default_delegate.Null(); - _class_default_delegate.Null(); - _instance_default_delegate.Null(); - _weakref_default_delegate.Null(); - _refs_table.Finalize(); + if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; } + _constructoridx.Null(); + _table(_registry)->Finalize(); + _table(_consts)->Finalize(); + _table(_metamethodsmap)->Finalize(); + _registry.Null(); + _consts.Null(); + _metamethodsmap.Null(); + while(!_systemstrings->empty()) { + _systemstrings->back().Null(); + _systemstrings->pop_back(); + } + _thread(_root_vm)->Finalize(); + _root_vm.Null(); + _table_default_delegate.Null(); + _array_default_delegate.Null(); + _string_default_delegate.Null(); + _number_default_delegate.Null(); + _closure_default_delegate.Null(); + _generator_default_delegate.Null(); + _thread_default_delegate.Null(); + _class_default_delegate.Null(); + _instance_default_delegate.Null(); + _weakref_default_delegate.Null(); + _refs_table.Finalize(); - sq_delete(_types,SQObjectPtrVec); - sq_delete(_systemstrings,SQObjectPtrVec); - sq_delete(_metamethods,SQObjectPtrVec); - sq_delete(_stringtable,SQStringTable); - if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize); + sq_delete(_types,SQObjectPtrVec); + sq_delete(_systemstrings,SQObjectPtrVec); + sq_delete(_metamethods,SQObjectPtrVec); + sq_delete(_stringtable,SQStringTable); + if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize); } SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name) { - if(sq_type(name) != OT_STRING) - return -1; - SQObjectPtr ret; - if(_table(_metamethodsmap)->Get(name,ret)) { - return _integer(ret); - } - return -1; + if(sq_type(name) != OT_STRING) + return -1; + SQObjectPtr ret; + if(_table(_metamethodsmap)->Get(name,ret)) { + return _integer(ret); + } + return -1; } SQChar* SQSharedState::GetScratchPad(SQInteger size) { - SQInteger newsize; - if(size>0) { - if(_scratchpadsize < size) { - newsize = size + (size>>1); - _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); - _scratchpadsize = newsize; + SQInteger newsize; + if(size>0) { + if(_scratchpadsize < size) { + newsize = size + (size>>1); + _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize = newsize; - }else if(_scratchpadsize >= (size<<5)) { - newsize = _scratchpadsize >> 1; - _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); - _scratchpadsize = newsize; - } - } - return _scratchpad; + }else if(_scratchpadsize >= (size<<5)) { + newsize = _scratchpadsize >> 1; + _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize = newsize; + } + } + return _scratchpad; } RefTable::RefTable() { - AllocNodes(4); + AllocNodes(4); } void RefTable::Finalize() { - RefNode *nodes = _nodes; - for(SQUnsignedInteger n = 0; n < _numofslots; n++) { - nodes->obj.Null(); - nodes++; - } + RefNode *nodes = _nodes; + for(SQUnsignedInteger n = 0; n < _numofslots; n++) { + nodes->obj.Null(); + nodes++; + } } RefTable::~RefTable() { - SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode))); + SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode))); } void RefTable::AddRef(SQObject &obj) { - SQHash mainpos; - RefNode *prev; - RefNode *ref = Get(obj,mainpos,&prev,true); - ref->refs++; + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + ref->refs++; } SQUnsignedInteger RefTable::GetRefCount(SQObject &obj) { - SQHash mainpos; - RefNode *prev; - RefNode *ref = Get(obj,mainpos,&prev,true); - return ref->refs; + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + return ref->refs; } SQBool RefTable::Release(SQObject &obj) { - SQHash mainpos; - RefNode *prev; - RefNode *ref = Get(obj,mainpos,&prev,false); - if(ref) { - if(--ref->refs == 0) { - SQObjectPtr o = ref->obj; - if(prev) { - prev->next = ref->next; - } - else { - _buckets[mainpos] = ref->next; - } - ref->next = _freelist; - _freelist = ref; - _slotused--; - ref->obj.Null(); - //<>test for shrink? - return SQTrue; - } - } - else { - assert(0); - } - return SQFalse; + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,false); + if(ref) { + if(--ref->refs == 0) { + SQObjectPtr o = ref->obj; + if(prev) { + prev->next = ref->next; + } + else { + _buckets[mainpos] = ref->next; + } + ref->next = _freelist; + _freelist = ref; + _slotused--; + ref->obj.Null(); + //<>test for shrink? + return SQTrue; + } + } + else { + assert(0); + } + return SQFalse; } void RefTable::Resize(SQUnsignedInteger size) { - RefNode **oldbucks = _buckets; - RefNode *t = _nodes; - SQUnsignedInteger oldnumofslots = _numofslots; - AllocNodes(size); - //rehash - SQUnsignedInteger nfound = 0; - for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { - if(sq_type(t->obj) != OT_NULL) { - //add back; - assert(t->refs != 0); - RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj); - nn->refs = t->refs; - t->obj.Null(); - nfound++; - } - t++; - } - assert(nfound == oldnumofslots); - SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode))); + RefNode **oldbucks = _buckets; + RefNode *t = _nodes; + SQUnsignedInteger oldnumofslots = _numofslots; + AllocNodes(size); + //rehash + SQUnsignedInteger nfound = 0; + for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { + if(sq_type(t->obj) != OT_NULL) { + //add back; + assert(t->refs != 0); + RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj); + nn->refs = t->refs; + t->obj.Null(); + nfound++; + } + t++; + } + assert(nfound == oldnumofslots); + SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode))); } RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj) { - RefNode *t = _buckets[mainpos]; - RefNode *newnode = _freelist; - newnode->obj = obj; - _buckets[mainpos] = newnode; - _freelist = _freelist->next; - newnode->next = t; - assert(newnode->refs == 0); - _slotused++; - return newnode; + RefNode *t = _buckets[mainpos]; + RefNode *newnode = _freelist; + newnode->obj = obj; + _buckets[mainpos] = newnode; + _freelist = _freelist->next; + newnode->next = t; + assert(newnode->refs == 0); + _slotused++; + return newnode; } RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add) { - RefNode *ref; - mainpos = ::HashObj(obj)&(_numofslots-1); - *prev = NULL; - for (ref = _buckets[mainpos]; ref; ) { - if(_rawval(ref->obj) == _rawval(obj) && sq_type(ref->obj) == sq_type(obj)) - break; - *prev = ref; - ref = ref->next; - } - if(ref == NULL && add) { - if(_numofslots == _slotused) { - assert(_freelist == 0); - Resize(_numofslots*2); - mainpos = ::HashObj(obj)&(_numofslots-1); - } - ref = Add(mainpos,obj); - } - return ref; + RefNode *ref; + mainpos = ::HashObj(obj)&(_numofslots-1); + *prev = NULL; + for (ref = _buckets[mainpos]; ref; ) { + if(_rawval(ref->obj) == _rawval(obj) && sq_type(ref->obj) == sq_type(obj)) + break; + *prev = ref; + ref = ref->next; + } + if(ref == NULL && add) { + if(_numofslots == _slotused) { + assert(_freelist == 0); + Resize(_numofslots*2); + mainpos = ::HashObj(obj)&(_numofslots-1); + } + ref = Add(mainpos,obj); + } + return ref; } void RefTable::AllocNodes(SQUnsignedInteger size) { - RefNode **bucks; - RefNode *nodes; - bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode))); - nodes = (RefNode *)&bucks[size]; - RefNode *temp = nodes; - SQUnsignedInteger n; - for(n = 0; n < size - 1; n++) { - bucks[n] = NULL; - temp->refs = 0; - new (&temp->obj) SQObjectPtr; - temp->next = temp+1; - temp++; - } - bucks[n] = NULL; - temp->refs = 0; - new (&temp->obj) SQObjectPtr; - temp->next = NULL; - _freelist = nodes; - _nodes = nodes; - _buckets = bucks; - _slotused = 0; - _numofslots = size; + RefNode **bucks; + RefNode *nodes; + bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode))); + nodes = (RefNode *)&bucks[size]; + RefNode *temp = nodes; + SQUnsignedInteger n; + for(n = 0; n < size - 1; n++) { + bucks[n] = NULL; + temp->refs = 0; + new (&temp->obj) SQObjectPtr; + temp->next = temp+1; + temp++; + } + bucks[n] = NULL; + temp->refs = 0; + new (&temp->obj) SQObjectPtr; + temp->next = NULL; + _freelist = nodes; + _nodes = nodes; + _buckets = bucks; + _slotused = 0; + _numofslots = size; } ////////////////////////////////////////////////////////////////////////// //SQStringTable @@ -379,89 +379,89 @@ void RefTable::AllocNodes(SQUnsignedInteger size) SQStringTable::SQStringTable(SQSharedState *ss) { - _sharedstate = ss; - AllocNodes(4); - _slotused = 0; + _sharedstate = ss; + AllocNodes(4); + _slotused = 0; } SQStringTable::~SQStringTable() { - SQ_FREE(_strings,sizeof(SQString*)*_numofslots); - _strings = NULL; + SQ_FREE(_strings,sizeof(SQString*)*_numofslots); + _strings = NULL; } void SQStringTable::AllocNodes(SQInteger size) { - _numofslots = size; - _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots); - memset(_strings,0,sizeof(SQString*)*_numofslots); + _numofslots = size; + _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots); + memset(_strings,0,sizeof(SQString*)*_numofslots); } SQString *SQStringTable::Add(const SQChar *news,SQInteger len) { - if(len<0) - len = (SQInteger)scstrlen(news); - SQHash newhash = ::_hashstr(news,len); - SQHash h = newhash&(_numofslots-1); - SQString *s; - for (s = _strings[h]; s; s = s->_next){ - if(s->_len == len && (!memcmp(news,s->_val,sq_rsl(len)))) - return s; //found - } + if(len<0) + len = (SQInteger)scstrlen(news); + SQHash newhash = ::_hashstr(news,len); + SQHash h = newhash&(_numofslots-1); + SQString *s; + for (s = _strings[h]; s; s = s->_next){ + if(s->_len == len && (!memcmp(news,s->_val,sq_rsl(len)))) + return s; //found + } - SQString *t = (SQString *)SQ_MALLOC(sq_rsl(len)+sizeof(SQString)); - new (t) SQString; - t->_sharedstate = _sharedstate; - memcpy(t->_val,news,sq_rsl(len)); - t->_val[len] = _SC('\0'); - t->_len = len; - t->_hash = newhash; - t->_next = _strings[h]; - _strings[h] = t; - _slotused++; - if (_slotused > _numofslots) /* too crowded? */ - Resize(_numofslots*2); - return t; + SQString *t = (SQString *)SQ_MALLOC(sq_rsl(len)+sizeof(SQString)); + new (t) SQString; + t->_sharedstate = _sharedstate; + memcpy(t->_val,news,sq_rsl(len)); + t->_val[len] = _SC('\0'); + t->_len = len; + t->_hash = newhash; + t->_next = _strings[h]; + _strings[h] = t; + _slotused++; + if (_slotused > _numofslots) /* too crowded? */ + Resize(_numofslots*2); + return t; } void SQStringTable::Resize(SQInteger size) { - SQInteger oldsize=_numofslots; - SQString **oldtable=_strings; - AllocNodes(size); - for (SQInteger i=0; i_next; - SQHash h = p->_hash&(_numofslots-1); - p->_next = _strings[h]; - _strings[h] = p; - p = next; - } - } - SQ_FREE(oldtable,oldsize*sizeof(SQString*)); + SQInteger oldsize=_numofslots; + SQString **oldtable=_strings; + AllocNodes(size); + for (SQInteger i=0; i_next; + SQHash h = p->_hash&(_numofslots-1); + p->_next = _strings[h]; + _strings[h] = p; + p = next; + } + } + SQ_FREE(oldtable,oldsize*sizeof(SQString*)); } void SQStringTable::Remove(SQString *bs) { - SQString *s; - SQString *prev=NULL; - SQHash h = bs->_hash&(_numofslots - 1); + SQString *s; + SQString *prev=NULL; + SQHash h = bs->_hash&(_numofslots - 1); - for (s = _strings[h]; s; ){ - if(s == bs){ - if(prev) - prev->_next = s->_next; - else - _strings[h] = s->_next; - _slotused--; - SQInteger slen = s->_len; - s->~SQString(); - SQ_FREE(s,sizeof(SQString) + sq_rsl(slen)); - return; - } - prev = s; - s = s->_next; - } - assert(0);//if this fail something is wrong + for (s = _strings[h]; s; ){ + if(s == bs){ + if(prev) + prev->_next = s->_next; + else + _strings[h] = s->_next; + _slotused--; + SQInteger slen = s->_len; + s->~SQString(); + SQ_FREE(s,sizeof(SQString) + sq_rsl(slen)); + return; + } + prev = s; + s = s->_next; + } + assert(0);//if this fail something is wrong } diff --git a/rabbit/sqstate.hpp b/rabbit/sqstate.hpp index de9ff65..43f84b2 100644 --- a/rabbit/sqstate.hpp +++ b/rabbit/sqstate.hpp @@ -16,41 +16,41 @@ struct SQTable; struct SQStringTable { - SQStringTable(SQSharedState*ss); - ~SQStringTable(); - SQString *Add(const SQChar *,SQInteger len); - void Remove(SQString *); + SQStringTable(SQSharedState*ss); + ~SQStringTable(); + SQString *Add(const SQChar *,SQInteger len); + void Remove(SQString *); private: - void Resize(SQInteger size); - void AllocNodes(SQInteger size); - SQString **_strings; - SQUnsignedInteger _numofslots; - SQUnsignedInteger _slotused; - SQSharedState *_sharedstate; + void Resize(SQInteger size); + void AllocNodes(SQInteger size); + SQString **_strings; + SQUnsignedInteger _numofslots; + SQUnsignedInteger _slotused; + SQSharedState *_sharedstate; }; struct RefTable { - struct RefNode { - SQObjectPtr obj; - SQUnsignedInteger refs; - struct RefNode *next; - }; - RefTable(); - ~RefTable(); - void AddRef(SQObject &obj); - SQBool Release(SQObject &obj); - SQUnsignedInteger GetRefCount(SQObject &obj); - void Finalize(); + struct RefNode { + SQObjectPtr obj; + SQUnsignedInteger refs; + struct RefNode *next; + }; + RefTable(); + ~RefTable(); + void AddRef(SQObject &obj); + SQBool Release(SQObject &obj); + SQUnsignedInteger GetRefCount(SQObject &obj); + void Finalize(); private: - RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add); - RefNode *Add(SQHash mainpos,SQObject &obj); - void Resize(SQUnsignedInteger size); - void AllocNodes(SQUnsignedInteger size); - SQUnsignedInteger _numofslots; - SQUnsignedInteger _slotused; - RefNode *_nodes; - RefNode *_freelist; - RefNode **_buckets; + RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add); + RefNode *Add(SQHash mainpos,SQObject &obj); + void Resize(SQUnsignedInteger size); + void AllocNodes(SQUnsignedInteger size); + SQUnsignedInteger _numofslots; + SQUnsignedInteger _slotused; + RefNode *_nodes; + RefNode *_freelist; + RefNode **_buckets; }; #define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len) @@ -60,66 +60,66 @@ struct SQObjectPtr; struct SQSharedState { - SQSharedState(); - ~SQSharedState(); - void Init(); + SQSharedState(); + ~SQSharedState(); + void Init(); public: - SQChar* GetScratchPad(SQInteger size); - SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); - SQObjectPtrVec *_metamethods; - SQObjectPtr _metamethodsmap; - SQObjectPtrVec *_systemstrings; - SQObjectPtrVec *_types; - SQStringTable *_stringtable; - RefTable _refs_table; - SQObjectPtr _registry; - SQObjectPtr _consts; - SQObjectPtr _constructoridx; - SQObjectPtr _root_vm; - SQObjectPtr _table_default_delegate; - static const SQRegFunction _table_default_delegate_funcz[]; - SQObjectPtr _array_default_delegate; - static const SQRegFunction _array_default_delegate_funcz[]; - SQObjectPtr _string_default_delegate; - static const SQRegFunction _string_default_delegate_funcz[]; - SQObjectPtr _number_default_delegate; - static const SQRegFunction _number_default_delegate_funcz[]; - SQObjectPtr _generator_default_delegate; - static const SQRegFunction _generator_default_delegate_funcz[]; - SQObjectPtr _closure_default_delegate; - static const SQRegFunction _closure_default_delegate_funcz[]; - SQObjectPtr _thread_default_delegate; - static const SQRegFunction _thread_default_delegate_funcz[]; - SQObjectPtr _class_default_delegate; - static const SQRegFunction _class_default_delegate_funcz[]; - SQObjectPtr _instance_default_delegate; - static const SQRegFunction _instance_default_delegate_funcz[]; - SQObjectPtr _weakref_default_delegate; - static const SQRegFunction _weakref_default_delegate_funcz[]; + SQChar* GetScratchPad(SQInteger size); + SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); + SQObjectPtrVec *_metamethods; + SQObjectPtr _metamethodsmap; + SQObjectPtrVec *_systemstrings; + SQObjectPtrVec *_types; + SQStringTable *_stringtable; + RefTable _refs_table; + SQObjectPtr _registry; + SQObjectPtr _consts; + SQObjectPtr _constructoridx; + SQObjectPtr _root_vm; + SQObjectPtr _table_default_delegate; + static const SQRegFunction _table_default_delegate_funcz[]; + SQObjectPtr _array_default_delegate; + static const SQRegFunction _array_default_delegate_funcz[]; + SQObjectPtr _string_default_delegate; + static const SQRegFunction _string_default_delegate_funcz[]; + SQObjectPtr _number_default_delegate; + static const SQRegFunction _number_default_delegate_funcz[]; + SQObjectPtr _generator_default_delegate; + static const SQRegFunction _generator_default_delegate_funcz[]; + SQObjectPtr _closure_default_delegate; + static const SQRegFunction _closure_default_delegate_funcz[]; + SQObjectPtr _thread_default_delegate; + static const SQRegFunction _thread_default_delegate_funcz[]; + SQObjectPtr _class_default_delegate; + static const SQRegFunction _class_default_delegate_funcz[]; + SQObjectPtr _instance_default_delegate; + static const SQRegFunction _instance_default_delegate_funcz[]; + SQObjectPtr _weakref_default_delegate; + static const SQRegFunction _weakref_default_delegate_funcz[]; - SQCOMPILERERROR _compilererrorhandler; - SQPRINTFUNCTION _printfunc; - SQPRINTFUNCTION _errorfunc; - bool _debuginfo; - bool _notifyallexceptions; - SQUserPointer _foreignptr; - SQRELEASEHOOK _releasehook; + SQCOMPILERERROR _compilererrorhandler; + SQPRINTFUNCTION _printfunc; + SQPRINTFUNCTION _errorfunc; + bool _debuginfo; + bool _notifyallexceptions; + SQUserPointer _foreignptr; + SQRELEASEHOOK _releasehook; private: - SQChar *_scratchpad; - SQInteger _scratchpadsize; + SQChar *_scratchpad; + SQInteger _scratchpadsize; }; #define _sp(s) (_sharedstate->GetScratchPad(s)) #define _spval (_sharedstate->GetScratchPad(-1)) -#define _table_ddel _table(_sharedstate->_table_default_delegate) -#define _array_ddel _table(_sharedstate->_array_default_delegate) -#define _string_ddel _table(_sharedstate->_string_default_delegate) -#define _number_ddel _table(_sharedstate->_number_default_delegate) +#define _table_ddel _table(_sharedstate->_table_default_delegate) +#define _array_ddel _table(_sharedstate->_array_default_delegate) +#define _string_ddel _table(_sharedstate->_string_default_delegate) +#define _number_ddel _table(_sharedstate->_number_default_delegate) #define _generator_ddel _table(_sharedstate->_generator_default_delegate) #define _closure_ddel _table(_sharedstate->_closure_default_delegate) -#define _thread_ddel _table(_sharedstate->_thread_default_delegate) -#define _class_ddel _table(_sharedstate->_class_default_delegate) +#define _thread_ddel _table(_sharedstate->_thread_default_delegate) +#define _class_ddel _table(_sharedstate->_class_default_delegate) #define _instance_ddel _table(_sharedstate->_instance_default_delegate) #define _weakref_ddel _table(_sharedstate->_weakref_default_delegate) diff --git a/rabbit/sqstring.hpp b/rabbit/sqstring.hpp index 5575d6b..fc9bfa9 100644 --- a/rabbit/sqstring.hpp +++ b/rabbit/sqstring.hpp @@ -9,26 +9,26 @@ inline SQHash _hashstr (const SQChar *s, size_t l) { - SQHash h = (SQHash)l; /* seed */ - size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ - for (; l>=step; l-=step) - h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++)); - return h; + SQHash h = (SQHash)l; /* seed */ + size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ + for (; l>=step; l-=step) + h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++)); + return h; } struct SQString : public SQRefCounted { - SQString(){} - ~SQString(){} + SQString(){} + ~SQString(){} public: - static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 ); - SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); - void Release(); - SQSharedState *_sharedstate; - SQString *_next; //chain for the string table - SQInteger _len; - SQHash _hash; - SQChar _val[1]; + static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 ); + SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + void Release(); + SQSharedState *_sharedstate; + SQString *_next; //chain for the string table + SQInteger _len; + SQHash _hash; + SQChar _val[1]; }; diff --git a/rabbit/sqtable.cpp b/rabbit/sqtable.cpp index 8fba98f..389fd40 100644 --- a/rabbit/sqtable.cpp +++ b/rabbit/sqtable.cpp @@ -14,213 +14,213 @@ SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize) { - SQInteger pow2size=MINPOWER2; - while(nInitialSize>pow2size)pow2size=pow2size<<1; - AllocNodes(pow2size); - _usednodes = 0; - _delegate = NULL; - INIT_CHAIN(); - ADD_TO_CHAIN(&_sharedstate->_gc_chain,this); + SQInteger pow2size=MINPOWER2; + while(nInitialSize>pow2size)pow2size=pow2size<<1; + AllocNodes(pow2size); + _usednodes = 0; + _delegate = NULL; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain,this); } void SQTable::Remove(const SQObjectPtr &key) { - _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); - if (n) { - n->val.Null(); - n->key.Null(); - _usednodes--; - Rehash(false); - } + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + n->val.Null(); + n->key.Null(); + _usednodes--; + Rehash(false); + } } void SQTable::AllocNodes(SQInteger nSize) { - _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); - for(SQInteger i=0;i= oldsize-oldsize/4) /* using more than 3/4? */ - AllocNodes(oldsize*2); - else if (nelems <= oldsize/4 && /* less than 1/4? */ - oldsize > MINPOWER2) - AllocNodes(oldsize/2); - else if(force) - AllocNodes(oldsize); - else - return; - _usednodes = 0; - for (SQInteger i=0; ikey) != OT_NULL) - NewSlot(old->key,old->val); - } - for(SQInteger k=0;k= oldsize-oldsize/4) /* using more than 3/4? */ + AllocNodes(oldsize*2); + else if (nelems <= oldsize/4 && /* less than 1/4? */ + oldsize > MINPOWER2) + AllocNodes(oldsize/2); + else if(force) + AllocNodes(oldsize); + else + return; + _usednodes = 0; + for (SQInteger i=0; ikey) != OT_NULL) + NewSlot(old->key,old->val); + } + for(SQInteger k=0;k_nodes; - _HashNode *src = _nodes; - _HashNode *dst = nt->_nodes; - SQInteger n = 0; - for(n = 0; n < _numofnodes; n++) { - dst->key = src->key; - dst->val = src->val; - if(src->next) { - assert(src->next > basesrc); - dst->next = basedst + (src->next - basesrc); - assert(dst != dst->next); - } - dst++; - src++; - } - assert(_firstfree > basesrc); - assert(_firstfree != NULL); - nt->_firstfree = basedst + (_firstfree - basesrc); - nt->_usednodes = _usednodes; + _HashNode *basesrc = _nodes; + _HashNode *basedst = nt->_nodes; + _HashNode *src = _nodes; + _HashNode *dst = nt->_nodes; + SQInteger n = 0; + for(n = 0; n < _numofnodes; n++) { + dst->key = src->key; + dst->val = src->val; + if(src->next) { + assert(src->next > basesrc); + dst->next = basedst + (src->next - basesrc); + assert(dst != dst->next); + } + dst++; + src++; + } + assert(_firstfree > basesrc); + assert(_firstfree != NULL); + nt->_firstfree = basedst + (_firstfree - basesrc); + nt->_usednodes = _usednodes; #else - SQInteger ridx=0; - SQObjectPtr key,val; - while((ridx=Next(true,ridx,key,val))!=-1){ - nt->NewSlot(key,val); - } + SQInteger ridx=0; + SQObjectPtr key,val; + while((ridx=Next(true,ridx,key,val))!=-1){ + nt->NewSlot(key,val); + } #endif - nt->SetDelegate(_delegate); - return nt; + nt->SetDelegate(_delegate); + return nt; } bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val) { - if(sq_type(key) == OT_NULL) - return false; - _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); - if (n) { - val = _realval(n->val); - return true; - } - return false; + if(sq_type(key) == OT_NULL) + return false; + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + val = _realval(n->val); + return true; + } + return false; } bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) { - assert(sq_type(key) != OT_NULL); - SQHash h = HashObj(key) & (_numofnodes - 1); - _HashNode *n = _Get(key, h); - if (n) { - n->val = val; - return false; - } - _HashNode *mp = &_nodes[h]; - n = mp; + assert(sq_type(key) != OT_NULL); + SQHash h = HashObj(key) & (_numofnodes - 1); + _HashNode *n = _Get(key, h); + if (n) { + n->val = val; + return false; + } + _HashNode *mp = &_nodes[h]; + n = mp; - //key not found I'll insert it - //main pos is not free + //key not found I'll insert it + //main pos is not free - if(sq_type(mp->key) != OT_NULL) { - n = _firstfree; /* get a free place */ - SQHash mph = HashObj(mp->key) & (_numofnodes - 1); - _HashNode *othern; /* main position of colliding node */ + if(sq_type(mp->key) != OT_NULL) { + n = _firstfree; /* get a free place */ + SQHash mph = HashObj(mp->key) & (_numofnodes - 1); + _HashNode *othern; /* main position of colliding node */ - if (mp > n && (othern = &_nodes[mph]) != mp){ - /* yes; move colliding node into free position */ - while (othern->next != mp){ - assert(othern->next != NULL); - othern = othern->next; /* find previous */ - } - othern->next = n; /* redo the chain with `n' in place of `mp' */ - n->key = mp->key; - n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ - n->next = mp->next; - mp->key.Null(); - mp->val.Null(); - mp->next = NULL; /* now `mp' is free */ - } - else{ - /* new node will go into free position */ - n->next = mp->next; /* chain new position */ - mp->next = n; - mp = n; - } - } - mp->key = key; + if (mp > n && (othern = &_nodes[mph]) != mp){ + /* yes; move colliding node into free position */ + while (othern->next != mp){ + assert(othern->next != NULL); + othern = othern->next; /* find previous */ + } + othern->next = n; /* redo the chain with `n' in place of `mp' */ + n->key = mp->key; + n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ + n->next = mp->next; + mp->key.Null(); + mp->val.Null(); + mp->next = NULL; /* now `mp' is free */ + } + else{ + /* new node will go into free position */ + n->next = mp->next; /* chain new position */ + mp->next = n; + mp = n; + } + } + mp->key = key; - for (;;) { /* correct `firstfree' */ - if (sq_type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) { - mp->val = val; - _usednodes++; - return true; /* OK; table still has a free place */ - } - else if (_firstfree == _nodes) break; /* cannot decrement from here */ - else (_firstfree)--; - } - Rehash(true); - return NewSlot(key, val); + for (;;) { /* correct `firstfree' */ + if (sq_type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) { + mp->val = val; + _usednodes++; + return true; /* OK; table still has a free place */ + } + else if (_firstfree == _nodes) break; /* cannot decrement from here */ + else (_firstfree)--; + } + Rehash(true); + return NewSlot(key, val); } SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) { - SQInteger idx = (SQInteger)TranslateIndex(refpos); - while (idx < _numofnodes) { - if(sq_type(_nodes[idx].key) != OT_NULL) { - //first found - _HashNode &n = _nodes[idx]; - outkey = n.key; - outval = getweakrefs?(SQObject)n.val:_realval(n.val); - //return idx for the next iteration - return ++idx; - } - ++idx; - } - //nothing to iterate anymore - return -1; + SQInteger idx = (SQInteger)TranslateIndex(refpos); + while (idx < _numofnodes) { + if(sq_type(_nodes[idx].key) != OT_NULL) { + //first found + _HashNode &n = _nodes[idx]; + outkey = n.key; + outval = getweakrefs?(SQObject)n.val:_realval(n.val); + //return idx for the next iteration + return ++idx; + } + ++idx; + } + //nothing to iterate anymore + return -1; } bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val) { - _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); - if (n) { - n->val = val; - return true; - } - return false; + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + n->val = val; + return true; + } + return false; } void SQTable::_ClearNodes() { - for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); } + for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); } } void SQTable::Finalize() { - _ClearNodes(); - SetDelegate(NULL); + _ClearNodes(); + SetDelegate(NULL); } void SQTable::Clear() { - _ClearNodes(); - _usednodes = 0; - Rehash(true); + _ClearNodes(); + _usednodes = 0; + Rehash(true); } diff --git a/rabbit/sqtable.hpp b/rabbit/sqtable.hpp index a6af102..6c8b3d7 100644 --- a/rabbit/sqtable.hpp +++ b/rabbit/sqtable.hpp @@ -20,92 +20,92 @@ inline SQHash HashObj(const SQObjectPtr &key) { - switch(sq_type(key)) { - case OT_STRING: return _string(key)->_hash; - case OT_FLOAT: return (SQHash)((SQInteger)_float(key)); - case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key)); - default: return hashptr(key._unVal.pRefCounted); - } + switch(sq_type(key)) { + case OT_STRING: return _string(key)->_hash; + case OT_FLOAT: return (SQHash)((SQInteger)_float(key)); + case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key)); + default: return hashptr(key._unVal.pRefCounted); + } } struct SQTable : public SQDelegable { private: - struct _HashNode - { - _HashNode() { next = NULL; } - SQObjectPtr val; - SQObjectPtr key; - _HashNode *next; - }; - _HashNode *_firstfree; - _HashNode *_nodes; - SQInteger _numofnodes; - SQInteger _usednodes; + struct _HashNode + { + _HashNode() { next = NULL; } + SQObjectPtr val; + SQObjectPtr key; + _HashNode *next; + }; + _HashNode *_firstfree; + _HashNode *_nodes; + SQInteger _numofnodes; + SQInteger _usednodes; /////////////////////////// - void AllocNodes(SQInteger nSize); - void Rehash(bool force); - SQTable(SQSharedState *ss, SQInteger nInitialSize); - void _ClearNodes(); + void AllocNodes(SQInteger nSize); + void Rehash(bool force); + SQTable(SQSharedState *ss, SQInteger nInitialSize); + void _ClearNodes(); public: - static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize) - { - SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable)); - new (newtable) SQTable(ss, nInitialSize); - newtable->_delegate = NULL; - return newtable; - } - void Finalize(); - SQTable *Clone(); - ~SQTable() - { - SetDelegate(NULL); - REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); - for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode(); - SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode)); - } - inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) - { - _HashNode *n = &_nodes[hash]; - do{ - if(_rawval(n->key) == _rawval(key) && sq_type(n->key) == sq_type(key)){ - return n; - } - }while((n = n->next)); - return NULL; - } - //for compiler use - inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val) - { - SQHash hash = _hashstr(key,keylen); - _HashNode *n = &_nodes[hash & (_numofnodes - 1)]; - _HashNode *res = NULL; - do{ - if(sq_type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){ - res = n; - break; - } - }while((n = n->next)); - if (res) { - val = _realval(res->val); - return true; - } - return false; - } - bool Get(const SQObjectPtr &key,SQObjectPtr &val); - void Remove(const SQObjectPtr &key); - bool Set(const SQObjectPtr &key, const SQObjectPtr &val); - //returns true if a new slot has been created false if it was already present - bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val); - SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize) + { + SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable)); + new (newtable) SQTable(ss, nInitialSize); + newtable->_delegate = NULL; + return newtable; + } + void Finalize(); + SQTable *Clone(); + ~SQTable() + { + SetDelegate(NULL); + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode(); + SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode)); + } + inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) + { + _HashNode *n = &_nodes[hash]; + do{ + if(_rawval(n->key) == _rawval(key) && sq_type(n->key) == sq_type(key)){ + return n; + } + }while((n = n->next)); + return NULL; + } + //for compiler use + inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val) + { + SQHash hash = _hashstr(key,keylen); + _HashNode *n = &_nodes[hash & (_numofnodes - 1)]; + _HashNode *res = NULL; + do{ + if(sq_type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){ + res = n; + break; + } + }while((n = n->next)); + if (res) { + val = _realval(res->val); + return true; + } + return false; + } + bool Get(const SQObjectPtr &key,SQObjectPtr &val); + void Remove(const SQObjectPtr &key); + bool Set(const SQObjectPtr &key, const SQObjectPtr &val); + //returns true if a new slot has been created false if it was already present + bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val); + SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); - SQInteger CountUsed(){ return _usednodes;} - void Clear(); - void Release() - { - sq_delete(this, SQTable); - } + SQInteger CountUsed(){ return _usednodes;} + void Clear(); + void Release() + { + sq_delete(this, SQTable); + } }; diff --git a/rabbit/squserdata.hpp b/rabbit/squserdata.hpp index 789ae75..3dbff66 100644 --- a/rabbit/squserdata.hpp +++ b/rabbit/squserdata.hpp @@ -9,31 +9,31 @@ struct SQUserData : SQDelegable { - SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); } - ~SQUserData() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this); - SetDelegate(NULL); - } - static SQUserData* Create(SQSharedState *ss, SQInteger size) - { - SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size); - new (ud) SQUserData(ss); - ud->_size = size; - ud->_typetag = 0; - return ud; - } - void Release() { - if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size); - SQInteger tsize = _size; - this->~SQUserData(); - SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize); - } + SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); } + ~SQUserData() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this); + SetDelegate(NULL); + } + static SQUserData* Create(SQSharedState *ss, SQInteger size) + { + SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size); + new (ud) SQUserData(ss); + ud->_size = size; + ud->_typetag = 0; + return ud; + } + void Release() { + if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size); + SQInteger tsize = _size; + this->~SQUserData(); + SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize); + } - SQInteger _size; - SQRELEASEHOOK _hook; - SQUserPointer _typetag; - //SQChar _val[1]; + SQInteger _size; + SQRELEASEHOOK _hook; + SQUserPointer _typetag; + //SQChar _val[1]; }; diff --git a/rabbit/squtils.hpp b/rabbit/squtils.hpp index e42da59..0971674 100644 --- a/rabbit/squtils.hpp +++ b/rabbit/squtils.hpp @@ -23,98 +23,98 @@ void sq_vm_free(void *p,SQUnsignedInteger size); template class sqvector { public: - sqvector() - { - _vals = NULL; - _size = 0; - _allocated = 0; - } - sqvector(const sqvector& v) - { - copy(v); - } - void copy(const sqvector& v) - { - if(_size) { - resize(0); //destroys all previous stuff - } - //resize(v._size); - if(v._size > _allocated) { - _realloc(v._size); - } - for(SQUnsignedInteger i = 0; i < v._size; i++) { - new ((void *)&_vals[i]) T(v._vals[i]); - } - _size = v._size; - } - ~sqvector() - { - if(_allocated) { - for(SQUnsignedInteger i = 0; i < _size; i++) - _vals[i].~T(); - SQ_FREE(_vals, (_allocated * sizeof(T))); - } - } - void reserve(SQUnsignedInteger newsize) { _realloc(newsize); } - void resize(SQUnsignedInteger newsize, const T& fill = T()) - { - if(newsize > _allocated) - _realloc(newsize); - if(newsize > _size) { - while(_size < newsize) { - new ((void *)&_vals[_size]) T(fill); - _size++; - } - } - else{ - for(SQUnsignedInteger i = newsize; i < _size; i++) { - _vals[i].~T(); - } - _size = newsize; - } - } - void shrinktofit() { if(_size > 4) { _realloc(_size); } } - T& top() const { return _vals[_size - 1]; } - inline SQUnsignedInteger size() const { return _size; } - bool empty() const { return (_size <= 0); } - inline T &push_back(const T& val = T()) - { - if(_allocated <= _size) - _realloc(_size * 2); - return *(new ((void *)&_vals[_size++]) T(val)); - } - inline void pop_back() - { - _size--; _vals[_size].~T(); - } - void insert(SQUnsignedInteger idx, const T& val) - { - resize(_size + 1); - for(SQUnsignedInteger i = _size - 1; i > idx; i--) { - _vals[i] = _vals[i - 1]; - } - _vals[idx] = val; - } - void remove(SQUnsignedInteger idx) - { - _vals[idx].~T(); - if(idx < (_size - 1)) { - memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1)); - } - _size--; - } - SQUnsignedInteger capacity() { return _allocated; } - inline T &back() const { return _vals[_size - 1]; } - inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; } - T* _vals; + sqvector() + { + _vals = NULL; + _size = 0; + _allocated = 0; + } + sqvector(const sqvector& v) + { + copy(v); + } + void copy(const sqvector& v) + { + if(_size) { + resize(0); //destroys all previous stuff + } + //resize(v._size); + if(v._size > _allocated) { + _realloc(v._size); + } + for(SQUnsignedInteger i = 0; i < v._size; i++) { + new ((void *)&_vals[i]) T(v._vals[i]); + } + _size = v._size; + } + ~sqvector() + { + if(_allocated) { + for(SQUnsignedInteger i = 0; i < _size; i++) + _vals[i].~T(); + SQ_FREE(_vals, (_allocated * sizeof(T))); + } + } + void reserve(SQUnsignedInteger newsize) { _realloc(newsize); } + void resize(SQUnsignedInteger newsize, const T& fill = T()) + { + if(newsize > _allocated) + _realloc(newsize); + if(newsize > _size) { + while(_size < newsize) { + new ((void *)&_vals[_size]) T(fill); + _size++; + } + } + else{ + for(SQUnsignedInteger i = newsize; i < _size; i++) { + _vals[i].~T(); + } + _size = newsize; + } + } + void shrinktofit() { if(_size > 4) { _realloc(_size); } } + T& top() const { return _vals[_size - 1]; } + inline SQUnsignedInteger size() const { return _size; } + bool empty() const { return (_size <= 0); } + inline T &push_back(const T& val = T()) + { + if(_allocated <= _size) + _realloc(_size * 2); + return *(new ((void *)&_vals[_size++]) T(val)); + } + inline void pop_back() + { + _size--; _vals[_size].~T(); + } + void insert(SQUnsignedInteger idx, const T& val) + { + resize(_size + 1); + for(SQUnsignedInteger i = _size - 1; i > idx; i--) { + _vals[i] = _vals[i - 1]; + } + _vals[idx] = val; + } + void remove(SQUnsignedInteger idx) + { + _vals[idx].~T(); + if(idx < (_size - 1)) { + memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1)); + } + _size--; + } + SQUnsignedInteger capacity() { return _allocated; } + inline T &back() const { return _vals[_size - 1]; } + inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; } + T* _vals; private: - void _realloc(SQUnsignedInteger newsize) - { - newsize = (newsize > 0)?newsize:4; - _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T)); - _allocated = newsize; - } - SQUnsignedInteger _size; - SQUnsignedInteger _allocated; + void _realloc(SQUnsignedInteger newsize) + { + newsize = (newsize > 0)?newsize:4; + _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T)); + _allocated = newsize; + } + SQUnsignedInteger _size; + SQUnsignedInteger _allocated; }; diff --git a/rabbit/sqvm.cpp b/rabbit/sqvm.cpp index 8db107a..3fc2aa8 100644 --- a/rabbit/sqvm.cpp +++ b/rabbit/sqvm.cpp @@ -24,480 +24,480 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) { - SQInteger res; - if((sq_type(o1)| sq_type(o2)) == OT_INTEGER) - { - SQInteger i1 = _integer(o1), i2 = _integer(o2); - switch(op) { - case BW_AND: res = i1 & i2; break; - case BW_OR: res = i1 | i2; break; - case BW_XOR: res = i1 ^ i2; break; - case BW_SHIFTL: res = i1 << i2; break; - case BW_SHIFTR: res = i1 >> i2; break; - case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; - default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } - } - } - else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} - trg = res; - return true; + SQInteger res; + if((sq_type(o1)| sq_type(o2)) == OT_INTEGER) + { + SQInteger i1 = _integer(o1), i2 = _integer(o2); + switch(op) { + case BW_AND: res = i1 & i2; break; + case BW_OR: res = i1 | i2; break; + case BW_XOR: res = i1 ^ i2; break; + case BW_SHIFTL: res = i1 << i2; break; + case BW_SHIFTR: res = i1 >> i2; break; + case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; + default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } + } + } + else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} + trg = res; + return true; } #define _ARITH_(op,trg,o1,o2) \ { \ - SQInteger tmask = sq_type(o1)|sq_type(o2); \ - switch(tmask) { \ - case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \ - case (OT_FLOAT|OT_INTEGER): \ - case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ - default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ - } \ + SQInteger tmask = sq_type(o1)|sq_type(o2); \ + switch(tmask) { \ + case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \ + case (OT_FLOAT|OT_INTEGER): \ + case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ + default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ + } \ } #define _ARITH_NOZERO(op,trg,o1,o2,err) \ { \ - SQInteger tmask = sq_type(o1)|sq_type(o2); \ - switch(tmask) { \ - case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\ - case (OT_FLOAT|OT_INTEGER): \ - case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ - default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ - } \ + SQInteger tmask = sq_type(o1)|sq_type(o2); \ + switch(tmask) { \ + case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\ + case (OT_FLOAT|OT_INTEGER): \ + case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ + default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ + } \ } bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) { - SQInteger tmask = sq_type(o1)| sq_type(o2); - switch(tmask) { - case OT_INTEGER:{ - SQInteger res, i1 = _integer(o1), i2 = _integer(o2); - switch(op) { - case '+': res = i1 + i2; break; - case '-': res = i1 - i2; break; - case '/': if (i2 == 0) { Raise_Error(_SC("division by zero")); return false; } - else if (i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); return false; } - res = i1 / i2; - break; - case '*': res = i1 * i2; break; - case '%': if (i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } - else if (i2 == -1 && i1 == INT_MIN) { res = 0; break; } - res = i1 % i2; - break; - default: res = 0xDEADBEEF; - } - trg = res; } - break; - case (OT_FLOAT|OT_INTEGER): - case (OT_FLOAT):{ - SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); - switch(op) { - case '+': res = f1 + f2; break; - case '-': res = f1 - f2; break; - case '/': res = f1 / f2; break; - case '*': res = f1 * f2; break; - case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; - default: res = 0x0f; - } - trg = res; } - break; - default: - if(op == '+' && (tmask & _RT_STRING)){ - if(!StringCat(o1, o2, trg)) return false; - } - else if(!ArithMetaMethod(op,o1,o2,trg)) { - return false; - } - } - return true; + SQInteger tmask = sq_type(o1)| sq_type(o2); + switch(tmask) { + case OT_INTEGER:{ + SQInteger res, i1 = _integer(o1), i2 = _integer(o2); + switch(op) { + case '+': res = i1 + i2; break; + case '-': res = i1 - i2; break; + case '/': if (i2 == 0) { Raise_Error(_SC("division by zero")); return false; } + else if (i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); return false; } + res = i1 / i2; + break; + case '*': res = i1 * i2; break; + case '%': if (i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } + else if (i2 == -1 && i1 == INT_MIN) { res = 0; break; } + res = i1 % i2; + break; + default: res = 0xDEADBEEF; + } + trg = res; } + break; + case (OT_FLOAT|OT_INTEGER): + case (OT_FLOAT):{ + SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); + switch(op) { + case '+': res = f1 + f2; break; + case '-': res = f1 - f2; break; + case '/': res = f1 / f2; break; + case '*': res = f1 * f2; break; + case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; + default: res = 0x0f; + } + trg = res; } + break; + default: + if(op == '+' && (tmask & _RT_STRING)){ + if(!StringCat(o1, o2, trg)) return false; + } + else if(!ArithMetaMethod(op,o1,o2,trg)) { + return false; + } + } + return true; } SQVM::SQVM(SQSharedState *ss) { - _sharedstate=ss; - _suspended = SQFalse; - _suspended_target = -1; - _suspended_root = SQFalse; - _suspended_traps = -1; - _foreignptr = NULL; - _nnativecalls = 0; - _nmetamethodscall = 0; - _lasterror.Null(); - _errorhandler.Null(); - _debughook = false; - _debughook_native = NULL; - _debughook_closure.Null(); - _openouters = NULL; - ci = NULL; - _releasehook = NULL; - INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); + _sharedstate=ss; + _suspended = SQFalse; + _suspended_target = -1; + _suspended_root = SQFalse; + _suspended_traps = -1; + _foreignptr = NULL; + _nnativecalls = 0; + _nmetamethodscall = 0; + _lasterror.Null(); + _errorhandler.Null(); + _debughook = false; + _debughook_native = NULL; + _debughook_closure.Null(); + _openouters = NULL; + ci = NULL; + _releasehook = NULL; + INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } void SQVM::Finalize() { - if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; } - if(_openouters) CloseOuters(&_stack._vals[0]); - _roottable.Null(); - _lasterror.Null(); - _errorhandler.Null(); - _debughook = false; - _debughook_native = NULL; - _debughook_closure.Null(); - temp_reg.Null(); - _callstackdata.resize(0); - SQInteger size=_stack.size(); - for(SQInteger i=0;i_gc_chain,this); + Finalize(); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest) { - SQMetaMethod mm; - switch(op){ - case _SC('+'): mm=MT_ADD; break; - case _SC('-'): mm=MT_SUB; break; - case _SC('/'): mm=MT_DIV; break; - case _SC('*'): mm=MT_MUL; break; - case _SC('%'): mm=MT_MODULO; break; - default: mm = MT_ADD; assert(0); break; //shutup compiler - } - if(is_delegable(o1) && _delegable(o1)->_delegate) { + SQMetaMethod mm; + switch(op){ + case _SC('+'): mm=MT_ADD; break; + case _SC('-'): mm=MT_SUB; break; + case _SC('/'): mm=MT_DIV; break; + case _SC('*'): mm=MT_MUL; break; + case _SC('%'): mm=MT_MODULO; break; + default: mm = MT_ADD; assert(0); break; //shutup compiler + } + if(is_delegable(o1) && _delegable(o1)->_delegate) { - SQObjectPtr closure; - if(_delegable(o1)->GetMetaMethod(this, mm, closure)) { - Push(o1);Push(o2); - return CallMetaMethod(closure,mm,2,dest); - } - } - Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); - return false; + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, mm, closure)) { + Push(o1);Push(o2); + return CallMetaMethod(closure,mm,2,dest); + } + } + Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); + return false; } bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) { - switch(sq_type(o)) { - case OT_INTEGER: - trg = -_integer(o); - return true; - case OT_FLOAT: - trg = -_float(o); - return true; - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o)->_delegate) { - SQObjectPtr closure; - if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) { - Push(o); - if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false; - _Swap(trg,temp_reg); - return true; + switch(sq_type(o)) { + case OT_INTEGER: + trg = -_integer(o); + return true; + case OT_FLOAT: + trg = -_float(o); + return true; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o)->_delegate) { + SQObjectPtr closure; + if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) { + Push(o); + if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false; + _Swap(trg,temp_reg); + return true; - } - } - default:break; //shutup compiler - } - Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); - return false; + } + } + default:break; //shutup compiler + } + Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); + return false; } #define _RET_SUCCEED(exp) { result = (exp); return true; } bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) { - SQObjectType t1 = sq_type(o1), t2 = sq_type(o2); - if(t1 == t2) { - if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0); - SQObjectPtr res; - switch(t1){ - case OT_STRING: - _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); - case OT_INTEGER: - _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1); - case OT_FLOAT: - _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o1)->_delegate) { - SQObjectPtr closure; - if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) { - Push(o1);Push(o2); - if(CallMetaMethod(closure,MT_CMP,2,res)) { - if(sq_type(res) != OT_INTEGER) { - Raise_Error(_SC("_cmp must return an integer")); - return false; - } - _RET_SUCCEED(_integer(res)) - } - return false; - } - } - //continues through (no break needed) - default: - _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); - } - assert(0); - //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } - // _RET_SUCCEED(_integer(res)); + SQObjectType t1 = sq_type(o1), t2 = sq_type(o2); + if(t1 == t2) { + if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0); + SQObjectPtr res; + switch(t1){ + case OT_STRING: + _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); + case OT_INTEGER: + _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1); + case OT_FLOAT: + _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o1)->_delegate) { + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) { + Push(o1);Push(o2); + if(CallMetaMethod(closure,MT_CMP,2,res)) { + if(sq_type(res) != OT_INTEGER) { + Raise_Error(_SC("_cmp must return an integer")); + return false; + } + _RET_SUCCEED(_integer(res)) + } + return false; + } + } + //continues through (no break needed) + default: + _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); + } + assert(0); + //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } + // _RET_SUCCEED(_integer(res)); - } - else{ - if(sq_isnumeric(o1) && sq_isnumeric(o2)){ - if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { - if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } - else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } - _RET_SUCCEED(1); - } - else{ - if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } - else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } - _RET_SUCCEED(1); - } - } - else if(t1==OT_NULL) {_RET_SUCCEED(-1);} - else if(t2==OT_NULL) {_RET_SUCCEED(1);} - else { Raise_CompareError(o1,o2); return false; } + } + else{ + if(sq_isnumeric(o1) && sq_isnumeric(o2)){ + if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { + if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } + else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } + _RET_SUCCEED(1); + } + else{ + if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } + else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } + _RET_SUCCEED(1); + } + } + else if(t1==OT_NULL) {_RET_SUCCEED(-1);} + else if(t2==OT_NULL) {_RET_SUCCEED(1);} + else { Raise_CompareError(o1,o2); return false; } - } - assert(0); - _RET_SUCCEED(0); //cannot happen + } + assert(0); + _RET_SUCCEED(0); //cannot happen } bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res) { - SQInteger r; - if(ObjCmp(o1,o2,r)) { - switch(op) { - case CMP_G: res = (r > 0); return true; - case CMP_GE: res = (r >= 0); return true; - case CMP_L: res = (r < 0); return true; - case CMP_LE: res = (r <= 0); return true; - case CMP_3W: res = r; return true; - } - assert(0); - } - return false; + SQInteger r; + if(ObjCmp(o1,o2,r)) { + switch(op) { + case CMP_G: res = (r > 0); return true; + case CMP_GE: res = (r >= 0); return true; + case CMP_L: res = (r < 0); return true; + case CMP_LE: res = (r <= 0); return true; + case CMP_3W: res = r; return true; + } + assert(0); + } + return false; } bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) { - switch(sq_type(o)) { - case OT_STRING: - res = o; - return true; - case OT_FLOAT: - scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_SC("%g"),_float(o)); - break; - case OT_INTEGER: - scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_PRINT_INT_FMT,_integer(o)); - break; - case OT_BOOL: - scsprintf(_sp(sq_rsl(6)),sq_rsl(6),_integer(o)?_SC("true"):_SC("false")); - break; - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o)->_delegate) { - SQObjectPtr closure; - if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) { - Push(o); - if(CallMetaMethod(closure,MT_TOSTRING,1,res)) { - if(sq_type(res) == OT_STRING) - return true; - } - else { - return false; - } - } - } - default: - scsprintf(_sp(sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR)),sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); - } - res = SQString::Create(_ss(this),_spval); - return true; + switch(sq_type(o)) { + case OT_STRING: + res = o; + return true; + case OT_FLOAT: + scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_SC("%g"),_float(o)); + break; + case OT_INTEGER: + scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_PRINT_INT_FMT,_integer(o)); + break; + case OT_BOOL: + scsprintf(_sp(sq_rsl(6)),sq_rsl(6),_integer(o)?_SC("true"):_SC("false")); + break; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o)->_delegate) { + SQObjectPtr closure; + if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) { + Push(o); + if(CallMetaMethod(closure,MT_TOSTRING,1,res)) { + if(sq_type(res) == OT_STRING) + return true; + } + else { + return false; + } + } + } + default: + scsprintf(_sp(sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR)),sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); + } + res = SQString::Create(_ss(this),_spval); + return true; } bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) { - SQObjectPtr a, b; - if(!ToString(str, a)) return false; - if(!ToString(obj, b)) return false; - SQInteger l = _string(a)->_len , ol = _string(b)->_len; - SQChar *s = _sp(sq_rsl(l + ol + 1)); - memcpy(s, _stringval(a), sq_rsl(l)); - memcpy(s + l, _stringval(b), sq_rsl(ol)); - dest = SQString::Create(_ss(this), _spval, l + ol); - return true; + SQObjectPtr a, b; + if(!ToString(str, a)) return false; + if(!ToString(obj, b)) return false; + SQInteger l = _string(a)->_len , ol = _string(b)->_len; + SQChar *s = _sp(sq_rsl(l + ol + 1)); + memcpy(s, _stringval(a), sq_rsl(l)); + memcpy(s + l, _stringval(b), sq_rsl(ol)); + dest = SQString::Create(_ss(this), _spval, l + ol); + return true; } bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) { - if(is_delegable(obj1) && _delegable(obj1)->_delegate) { - SQObjectPtr closure; - if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) { - Push(obj1); - return CallMetaMethod(closure,MT_TYPEOF,1,dest); - } - } - dest = SQString::Create(_ss(this),GetTypeName(obj1)); - return true; + if(is_delegable(obj1) && _delegable(obj1)->_delegate) { + SQObjectPtr closure; + if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) { + Push(obj1); + return CallMetaMethod(closure,MT_TYPEOF,1,dest); + } + } + dest = SQString::Create(_ss(this),GetTypeName(obj1)); + return true; } bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) { - _stack.resize(stacksize); - _alloccallsstacksize = 4; - _callstackdata.resize(_alloccallsstacksize); - _callsstacksize = 0; - _callsstack = &_callstackdata[0]; - _stackbase = 0; - _top = 0; - if(!friendvm) { - _roottable = SQTable::Create(_ss(this), 0); - sq_base_register(this); - } - else { - _roottable = friendvm->_roottable; - _errorhandler = friendvm->_errorhandler; - _debughook = friendvm->_debughook; - _debughook_native = friendvm->_debughook_native; - _debughook_closure = friendvm->_debughook_closure; - } + _stack.resize(stacksize); + _alloccallsstacksize = 4; + _callstackdata.resize(_alloccallsstacksize); + _callsstacksize = 0; + _callsstack = &_callstackdata[0]; + _stackbase = 0; + _top = 0; + if(!friendvm) { + _roottable = SQTable::Create(_ss(this), 0); + sq_base_register(this); + } + else { + _roottable = friendvm->_roottable; + _errorhandler = friendvm->_errorhandler; + _debughook = friendvm->_debughook; + _debughook_native = friendvm->_debughook_native; + _debughook_closure = friendvm->_debughook_closure; + } - return true; + return true; } bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall) { - SQFunctionProto *func = closure->_function; + SQFunctionProto *func = closure->_function; - SQInteger paramssize = func->_nparameters; - const SQInteger newtop = stackbase + func->_stacksize; - SQInteger nargs = args; - if(func->_varparams) - { - paramssize--; - if (nargs < paramssize) { - Raise_Error(_SC("wrong number of parameters")); - return false; - } + SQInteger paramssize = func->_nparameters; + const SQInteger newtop = stackbase + func->_stacksize; + SQInteger nargs = args; + if(func->_varparams) + { + paramssize--; + if (nargs < paramssize) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } - //dumpstack(stackbase); - SQInteger nvargs = nargs - paramssize; - SQArray *arr = SQArray::Create(_ss(this),nvargs); - SQInteger pbase = stackbase+paramssize; - for(SQInteger n = 0; n < nvargs; n++) { - arr->_values[n] = _stack._vals[pbase]; - _stack._vals[pbase].Null(); - pbase++; + //dumpstack(stackbase); + SQInteger nvargs = nargs - paramssize; + SQArray *arr = SQArray::Create(_ss(this),nvargs); + SQInteger pbase = stackbase+paramssize; + for(SQInteger n = 0; n < nvargs; n++) { + arr->_values[n] = _stack._vals[pbase]; + _stack._vals[pbase].Null(); + pbase++; - } - _stack._vals[stackbase+paramssize] = arr; - //dumpstack(stackbase); - } - else if (paramssize != nargs) { - SQInteger ndef = func->_ndefaultparams; - SQInteger diff; - if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) { - for(SQInteger n = ndef - diff; n < ndef; n++) { - _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; - } - } - else { - Raise_Error(_SC("wrong number of parameters")); - return false; - } - } + } + _stack._vals[stackbase+paramssize] = arr; + //dumpstack(stackbase); + } + else if (paramssize != nargs) { + SQInteger ndef = func->_ndefaultparams; + SQInteger diff; + if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) { + for(SQInteger n = ndef - diff; n < ndef; n++) { + _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; + } + } + else { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + } - if(closure->_env) { - _stack._vals[stackbase] = closure->_env->_obj; - } + if(closure->_env) { + _stack._vals[stackbase] = closure->_env->_obj; + } - if(!EnterFrame(stackbase, newtop, tailcall)) return false; + if(!EnterFrame(stackbase, newtop, tailcall)) return false; - ci->_closure = closure; - ci->_literals = func->_literals; - ci->_ip = func->_instructions; - ci->_target = (SQInt32)target; + ci->_closure = closure; + ci->_literals = func->_literals; + ci->_ip = func->_instructions; + ci->_target = (SQInt32)target; - if (_debughook) { - CallDebugHook(_SC('c')); - } + if (_debughook) { + CallDebugHook(_SC('c')); + } - if (closure->_function->_bgenerator) { - SQFunctionProto *f = closure->_function; - SQGenerator *gen = SQGenerator::Create(_ss(this), closure); - if(!gen->Yield(this,f->_stacksize)) - return false; - SQObjectPtr temp; - Return(1, target, temp); - STK(target) = gen; - } + if (closure->_function->_bgenerator) { + SQFunctionProto *f = closure->_function; + SQGenerator *gen = SQGenerator::Create(_ss(this), closure); + if(!gen->Yield(this,f->_stacksize)) + return false; + SQObjectPtr temp; + Return(1, target, temp); + STK(target) = gen; + } - return true; + return true; } bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) { - SQBool _isroot = ci->_root; - SQInteger callerbase = _stackbase - ci->_prevstkbase; + SQBool _isroot = ci->_root; + SQInteger callerbase = _stackbase - ci->_prevstkbase; - if (_debughook) { - for(SQInteger i=0; i_ncalls; i++) { - CallDebugHook(_SC('r')); - } - } + if (_debughook) { + for(SQInteger i=0; i_ncalls; i++) { + CallDebugHook(_SC('r')); + } + } - SQObjectPtr *dest; - if (_isroot) { - dest = &(retval); - } else if (ci->_target == -1) { - dest = NULL; - } else { - dest = &_stack._vals[callerbase + ci->_target]; - } - if (dest) { - if(_arg0 != 0xFF) { - *dest = _stack._vals[_stackbase+_arg1]; - } - else { - dest->Null(); - } - //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_; - } - LeaveFrame(); - return _isroot ? true : false; + SQObjectPtr *dest; + if (_isroot) { + dest = &(retval); + } else if (ci->_target == -1) { + dest = NULL; + } else { + dest = &_stack._vals[callerbase + ci->_target]; + } + if (dest) { + if(_arg0 != 0xFF) { + *dest = _stack._vals[_stackbase+_arg1]; + } + else { + dest->Null(); + } + //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_; + } + LeaveFrame(); + return _isroot ? true : false; } #define _RET_ON_FAIL(exp) { if(!exp) return false; } bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) { - SQObjectPtr trg; - _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); - target = a; - a = trg; - return true; + SQObjectPtr trg; + _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); + target = a; + a = trg; + return true; } bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx) { - SQObjectPtr tmp, tself = self, tkey = key; - if (!Get(tself, tkey, tmp, 0, selfidx)) { return false; } - _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) - if (!Set(tself, tkey, target,selfidx)) { return false; } - if (postfix) target = tmp; - return true; + SQObjectPtr tmp, tself = self, tkey = key; + if (!Get(tself, tkey, tmp, 0, selfidx)) { return false; } + _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) + if (!Set(tself, tkey, target,selfidx)) { return false; } + if (postfix) target = tmp; + return true; } #define arg0 (_i_._arg0) @@ -510,11 +510,11 @@ bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjec SQRESULT SQVM::Suspend() { - if (_suspended) - return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); - if (_nnativecalls!=2) - return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); - return SQ_SUSPEND_FLAG; + if (_suspended) + return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); + if (_nnativecalls!=2) + return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); + return SQ_SUSPEND_FLAG; } @@ -522,61 +522,61 @@ SQRESULT SQVM::Suspend() bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger SQ_UNUSED_ARG(arg_2),int exitpos,int &jump) { - SQInteger nrefidx; - switch(sq_type(o1)) { - case OT_TABLE: - if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos); - o4 = (SQInteger)nrefidx; _FINISH(1); - case OT_ARRAY: - if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos); - o4 = (SQInteger) nrefidx; _FINISH(1); - case OT_STRING: - if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); - o4 = (SQInteger)nrefidx; _FINISH(1); - case OT_CLASS: - if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); - o4 = (SQInteger)nrefidx; _FINISH(1); - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o1)->_delegate) { - SQObjectPtr itr; - SQObjectPtr closure; - if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) { - Push(o1); - Push(o4); - if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) { - o4 = o2 = itr; - if(sq_type(itr) == OT_NULL) _FINISH(exitpos); - if(!Get(o1, itr, o3, 0, DONT_FALL_BACK)) { - Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed - return false; - } - _FINISH(1); - } - else { - return false; - } - } - Raise_Error(_SC("_nexti failed")); - return false; - } - break; - case OT_GENERATOR: - if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos); - if(_generator(o1)->_state == SQGenerator::eSuspended) { - SQInteger idx = 0; - if(sq_type(o4) == OT_INTEGER) { - idx = _integer(o4) + 1; - } - o2 = idx; - o4 = idx; - _generator(o1)->Resume(this, o3); - _FINISH(0); - } - default: - Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); - } - return false; //cannot be hit(just to avoid warnings) + SQInteger nrefidx; + switch(sq_type(o1)) { + case OT_TABLE: + if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos); + o4 = (SQInteger)nrefidx; _FINISH(1); + case OT_ARRAY: + if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos); + o4 = (SQInteger) nrefidx; _FINISH(1); + case OT_STRING: + if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); + o4 = (SQInteger)nrefidx; _FINISH(1); + case OT_CLASS: + if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); + o4 = (SQInteger)nrefidx; _FINISH(1); + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o1)->_delegate) { + SQObjectPtr itr; + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) { + Push(o1); + Push(o4); + if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) { + o4 = o2 = itr; + if(sq_type(itr) == OT_NULL) _FINISH(exitpos); + if(!Get(o1, itr, o3, 0, DONT_FALL_BACK)) { + Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed + return false; + } + _FINISH(1); + } + else { + return false; + } + } + Raise_Error(_SC("_nexti failed")); + return false; + } + break; + case OT_GENERATOR: + if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos); + if(_generator(o1)->_state == SQGenerator::eSuspended) { + SQInteger idx = 0; + if(sq_type(o4) == OT_INTEGER) { + idx = _integer(o4) + 1; + } + o2 = idx; + o4 = idx; + _generator(o1)->Resume(this, o3); + _FINISH(0); + } + default: + Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); + } + return false; //cannot be hit(just to avoid warnings) } #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1)) @@ -587,630 +587,630 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) { - SQInteger nouters; - SQClosure *closure = SQClosure::Create(_ss(this), func,_table(_roottable)->GetWeakRef(OT_TABLE)); - if((nouters = func->_noutervalues)) { - for(SQInteger i = 0; i_outervalues[i]; - switch(v._type){ - case otLOCAL: - FindOuter(closure->_outervalues[i], &STK(_integer(v._src))); - break; - case otOUTER: - closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)]; - break; - } - } - } - SQInteger ndefparams; - if((ndefparams = func->_ndefaultparams)) { - for(SQInteger i = 0; i < ndefparams; i++) { - SQInteger spos = func->_defaultparams[i]; - closure->_defaultparams[i] = _stack._vals[_stackbase + spos]; - } - } - target = closure; - return true; + SQInteger nouters; + SQClosure *closure = SQClosure::Create(_ss(this), func,_table(_roottable)->GetWeakRef(OT_TABLE)); + if((nouters = func->_noutervalues)) { + for(SQInteger i = 0; i_outervalues[i]; + switch(v._type){ + case otLOCAL: + FindOuter(closure->_outervalues[i], &STK(_integer(v._src))); + break; + case otOUTER: + closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)]; + break; + } + } + } + SQInteger ndefparams; + if((ndefparams = func->_ndefaultparams)) { + for(SQInteger i = 0; i < ndefparams; i++) { + SQInteger spos = func->_defaultparams[i]; + closure->_defaultparams[i] = _stack._vals[_stackbase + spos]; + } + } + target = closure; + return true; } bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) { - SQClass *base = NULL; - SQObjectPtr attrs; - if(baseclass != -1) { - if(sq_type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } - base = _class(_stack._vals[_stackbase + baseclass]); - } - if(attributes != MAX_FUNC_STACKSIZE) { - attrs = _stack._vals[_stackbase+attributes]; - } - target = SQClass::Create(_ss(this),base); - if(sq_type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { - int nparams = 2; - SQObjectPtr ret; - Push(target); Push(attrs); - if(!Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false)) { - Pop(nparams); - return false; - } - Pop(nparams); - } - _class(target)->_attributes = attrs; - return true; + SQClass *base = NULL; + SQObjectPtr attrs; + if(baseclass != -1) { + if(sq_type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } + base = _class(_stack._vals[_stackbase + baseclass]); + } + if(attributes != MAX_FUNC_STACKSIZE) { + attrs = _stack._vals[_stackbase+attributes]; + } + target = SQClass::Create(_ss(this),base); + if(sq_type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { + int nparams = 2; + SQObjectPtr ret; + Push(target); Push(attrs); + if(!Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false)) { + Pop(nparams); + return false; + } + Pop(nparams); + } + _class(target)->_attributes = attrs; + return true; } bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res) { - if(sq_type(o1) == sq_type(o2)) { - res = (_rawval(o1) == _rawval(o2)); - } - else { - if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - res = (tofloat(o1) == tofloat(o2)); - } - else { - res = false; - } - } - return true; + if(sq_type(o1) == sq_type(o2)) { + res = (_rawval(o1) == _rawval(o2)); + } + else { + if(sq_isnumeric(o1) && sq_isnumeric(o2)) { + res = (tofloat(o1) == tofloat(o2)); + } + else { + res = false; + } + } + return true; } bool SQVM::IsFalse(SQObjectPtr &o) { - if(((sq_type(o) & SQOBJECT_CANBEFALSE) - && ( ((sq_type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )) + if(((sq_type(o) & SQOBJECT_CANBEFALSE) + && ( ((sq_type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )) #if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64)) - || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL + || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL #else - || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL + || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL #endif - { - return true; - } - return false; + { + return true; + } + return false; } extern SQInstructionDesc g_InstrDesc[]; bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) { - if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } - _nnativecalls++; - AutoDec ad(&_nnativecalls); - SQInteger traps = 0; - CallInfo *prevci = ci; + if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } + _nnativecalls++; + AutoDec ad(&_nnativecalls); + SQInteger traps = 0; + CallInfo *prevci = ci; - switch(et) { - case ET_CALL: { - temp_reg = closure; - if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { - //call the handler if there are no calls in the stack, if not relies on the previous node - if(ci == NULL) CallErrorHandler(_lasterror); - return false; - } - if(ci == prevci) { - outres = STK(_top-nargs); - return true; - } - ci->_root = SQTrue; - } - break; - case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break; - case ET_RESUME_VM: - case ET_RESUME_THROW_VM: - traps = _suspended_traps; - ci->_root = _suspended_root; - _suspended = SQFalse; - if(et == ET_RESUME_THROW_VM) { SQ_THROW(); } - break; - } + switch(et) { + case ET_CALL: { + temp_reg = closure; + if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { + //call the handler if there are no calls in the stack, if not relies on the previous node + if(ci == NULL) CallErrorHandler(_lasterror); + return false; + } + if(ci == prevci) { + outres = STK(_top-nargs); + return true; + } + ci->_root = SQTrue; + } + break; + case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break; + case ET_RESUME_VM: + case ET_RESUME_THROW_VM: + traps = _suspended_traps; + ci->_root = _suspended_root; + _suspended = SQFalse; + if(et == ET_RESUME_THROW_VM) { SQ_THROW(); } + break; + } exception_restore: - // - { - for(;;) - { - const SQInstruction &_i_ = *ci->_ip++; - //dumpstack(_stackbase); - //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-_closure(ci->_closure)->_function->_instructions,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); - switch(_i_.op) - { - case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue; - case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; - case _OP_LOADINT: + // + { + for(;;) + { + const SQInstruction &_i_ = *ci->_ip++; + //dumpstack(_stackbase); + //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-_closure(ci->_closure)->_function->_instructions,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); + switch(_i_.op) + { + case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue; + case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; + case _OP_LOADINT: #ifndef _SQ64 - TARGET = (SQInteger)arg1; continue; + TARGET = (SQInteger)arg1; continue; #else - TARGET = (SQInteger)((SQInt32)arg1); continue; + TARGET = (SQInteger)((SQInt32)arg1); continue; #endif - case _OP_LOADFLOAT: TARGET = *((const SQFloat *)&arg1); continue; - case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; - case _OP_TAILCALL:{ - SQObjectPtr &t = STK(arg1); - if (sq_type(t) == OT_CLOSURE - && (!_closure(t)->_function->_bgenerator)){ - SQObjectPtr clo = t; - SQInteger last_top = _top; - if(_openouters) CloseOuters(&(_stack._vals[_stackbase])); - for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); - _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true)); - if (last_top >= _top) { - _top = last_top; - } - continue; - } - } - case _OP_CALL: { - SQObjectPtr clo = STK(arg1); - switch (sq_type(clo)) { - case OT_CLOSURE: - _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false)); - continue; - case OT_NATIVECLOSURE: { - bool suspend; + case _OP_LOADFLOAT: TARGET = *((const SQFloat *)&arg1); continue; + case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; + case _OP_TAILCALL:{ + SQObjectPtr &t = STK(arg1); + if (sq_type(t) == OT_CLOSURE + && (!_closure(t)->_function->_bgenerator)){ + SQObjectPtr clo = t; + SQInteger last_top = _top; + if(_openouters) CloseOuters(&(_stack._vals[_stackbase])); + for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); + _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true)); + if (last_top >= _top) { + _top = last_top; + } + continue; + } + } + case _OP_CALL: { + SQObjectPtr clo = STK(arg1); + switch (sq_type(clo)) { + case OT_CLOSURE: + _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false)); + continue; + case OT_NATIVECLOSURE: { + bool suspend; bool tailcall; - _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo, (SQInt32)sarg0, suspend, tailcall)); - if(suspend){ - _suspended = SQTrue; - _suspended_target = sarg0; - _suspended_root = ci->_root; - _suspended_traps = traps; - outres = clo; - return true; - } - if(sarg0 != -1 && !tailcall) { - STK(arg0) = clo; - } - } - continue; - case OT_CLASS:{ - SQObjectPtr inst; - _GUARD(CreateClassInstance(_class(clo),inst,clo)); - if(sarg0 != -1) { - STK(arg0) = inst; - } - SQInteger stkbase; - switch(sq_type(clo)) { - case OT_CLOSURE: - stkbase = _stackbase+arg2; - _stack._vals[stkbase] = inst; - _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false)); - break; - case OT_NATIVECLOSURE: - bool dummy; - stkbase = _stackbase+arg2; - _stack._vals[stkbase] = inst; - _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo, -1, dummy, dummy)); - break; - default: break; //shutup GCC 4.x - } - } - break; - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE:{ - SQObjectPtr closure; - if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) { - Push(clo); - for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); - if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW(); - if(sarg0 != -1) { - STK(arg0) = clo; - } - break; - } + _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo, (SQInt32)sarg0, suspend, tailcall)); + if(suspend){ + _suspended = SQTrue; + _suspended_target = sarg0; + _suspended_root = ci->_root; + _suspended_traps = traps; + outres = clo; + return true; + } + if(sarg0 != -1 && !tailcall) { + STK(arg0) = clo; + } + } + continue; + case OT_CLASS:{ + SQObjectPtr inst; + _GUARD(CreateClassInstance(_class(clo),inst,clo)); + if(sarg0 != -1) { + STK(arg0) = inst; + } + SQInteger stkbase; + switch(sq_type(clo)) { + case OT_CLOSURE: + stkbase = _stackbase+arg2; + _stack._vals[stkbase] = inst; + _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false)); + break; + case OT_NATIVECLOSURE: + bool dummy; + stkbase = _stackbase+arg2; + _stack._vals[stkbase] = inst; + _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo, -1, dummy, dummy)); + break; + default: break; //shutup GCC 4.x + } + } + break; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE:{ + SQObjectPtr closure; + if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) { + Push(clo); + for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); + if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW(); + if(sarg0 != -1) { + STK(arg0) = clo; + } + break; + } - //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); - //SQ_THROW(); - } - default: - Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); - SQ_THROW(); - } - } - continue; - case _OP_PREPCALL: - case _OP_PREPCALLK: { - SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); - SQObjectPtr &o = STK(arg2); - if (!Get(o, key, temp_reg,0,arg2)) { - SQ_THROW(); - } - STK(arg3) = o; - _Swap(TARGET,temp_reg);//TARGET = temp_reg; - } - continue; - case _OP_GETK: - if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, 0,arg2)) { SQ_THROW();} - _Swap(TARGET,temp_reg);//TARGET = temp_reg; - continue; - case _OP_MOVE: TARGET = STK(arg1); continue; - case _OP_NEWSLOT: - _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); - if(arg0 != 0xFF) TARGET = STK(arg3); - continue; - case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; - case _OP_SET: - if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); } - if (arg0 != 0xFF) TARGET = STK(arg3); - continue; - case _OP_GET: - if (!Get(STK(arg1), STK(arg2), temp_reg, 0,arg1)) { SQ_THROW(); } - _Swap(TARGET,temp_reg);//TARGET = temp_reg; - continue; - case _OP_EQ:{ - bool res; - if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = res?true:false; - }continue; - case _OP_NE:{ - bool res; - if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = (!res)?true:false; - } continue; - case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue; - case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue; - case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue; - case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue; - case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue; - case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; - case _OP_RETURN: - if((ci)->_generator) { - (ci)->_generator->Kill(); - } - if(Return(arg0, arg1, temp_reg)){ - assert(traps==0); - //outres = temp_reg; - _Swap(outres,temp_reg); - return true; - } - continue; - case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue; - case _OP_LOADROOT: { - SQWeakRef *w = _closure(ci->_closure)->_root; - if(sq_type(w->_obj) != OT_NULL) { - TARGET = w->_obj; - } else { - TARGET = _roottable; //shoud this be like this? or null - } - } - continue; - case _OP_LOADBOOL: TARGET = arg1?true:false; continue; - case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; - case _OP_JMP: ci->_ip += (sarg1); continue; - //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; - case _OP_JCMP: - _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg)); - if(IsFalse(temp_reg)) ci->_ip+=(sarg1); - continue; - case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; - case _OP_GETOUTER: { - SQClosure *cur_cls = _closure(ci->_closure); - SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); - TARGET = *(otr->_valptr); - } - continue; - case _OP_SETOUTER: { - SQClosure *cur_cls = _closure(ci->_closure); - SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); - *(otr->_valptr) = STK(arg2); - if(arg0 != 0xFF) { - TARGET = STK(arg2); - } - } - continue; - case _OP_NEWOBJ: - switch(arg3) { - case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; - case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; - case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; - default: assert(0); continue; - } - case _OP_APPENDARRAY: - { - SQObject val; - val._unVal.raw = 0; - switch(arg2) { - case AAT_STACK: - val = STK(arg1); break; - case AAT_LITERAL: - val = ci->_literals[arg1]; break; - case AAT_INT: - val._type = OT_INTEGER; + //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); + //SQ_THROW(); + } + default: + Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); + SQ_THROW(); + } + } + continue; + case _OP_PREPCALL: + case _OP_PREPCALLK: { + SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); + SQObjectPtr &o = STK(arg2); + if (!Get(o, key, temp_reg,0,arg2)) { + SQ_THROW(); + } + STK(arg3) = o; + _Swap(TARGET,temp_reg);//TARGET = temp_reg; + } + continue; + case _OP_GETK: + if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, 0,arg2)) { SQ_THROW();} + _Swap(TARGET,temp_reg);//TARGET = temp_reg; + continue; + case _OP_MOVE: TARGET = STK(arg1); continue; + case _OP_NEWSLOT: + _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); + if(arg0 != 0xFF) TARGET = STK(arg3); + continue; + case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; + case _OP_SET: + if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); } + if (arg0 != 0xFF) TARGET = STK(arg3); + continue; + case _OP_GET: + if (!Get(STK(arg1), STK(arg2), temp_reg, 0,arg1)) { SQ_THROW(); } + _Swap(TARGET,temp_reg);//TARGET = temp_reg; + continue; + case _OP_EQ:{ + bool res; + if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } + TARGET = res?true:false; + }continue; + case _OP_NE:{ + bool res; + if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } + TARGET = (!res)?true:false; + } continue; + case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue; + case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue; + case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; + case _OP_RETURN: + if((ci)->_generator) { + (ci)->_generator->Kill(); + } + if(Return(arg0, arg1, temp_reg)){ + assert(traps==0); + //outres = temp_reg; + _Swap(outres,temp_reg); + return true; + } + continue; + case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue; + case _OP_LOADROOT: { + SQWeakRef *w = _closure(ci->_closure)->_root; + if(sq_type(w->_obj) != OT_NULL) { + TARGET = w->_obj; + } else { + TARGET = _roottable; //shoud this be like this? or null + } + } + continue; + case _OP_LOADBOOL: TARGET = arg1?true:false; continue; + case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; + case _OP_JMP: ci->_ip += (sarg1); continue; + //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_JCMP: + _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg)); + if(IsFalse(temp_reg)) ci->_ip+=(sarg1); + continue; + case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_GETOUTER: { + SQClosure *cur_cls = _closure(ci->_closure); + SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); + TARGET = *(otr->_valptr); + } + continue; + case _OP_SETOUTER: { + SQClosure *cur_cls = _closure(ci->_closure); + SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); + *(otr->_valptr) = STK(arg2); + if(arg0 != 0xFF) { + TARGET = STK(arg2); + } + } + continue; + case _OP_NEWOBJ: + switch(arg3) { + case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; + case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; + case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; + default: assert(0); continue; + } + case _OP_APPENDARRAY: + { + SQObject val; + val._unVal.raw = 0; + switch(arg2) { + case AAT_STACK: + val = STK(arg1); break; + case AAT_LITERAL: + val = ci->_literals[arg1]; break; + case AAT_INT: + val._type = OT_INTEGER; #ifndef _SQ64 - val._unVal.nInteger = (SQInteger)arg1; + val._unVal.nInteger = (SQInteger)arg1; #else - val._unVal.nInteger = (SQInteger)((SQInt32)arg1); + val._unVal.nInteger = (SQInteger)((SQInt32)arg1); #endif - break; - case AAT_FLOAT: - val._type = OT_FLOAT; - val._unVal.fFloat = *((const SQFloat *)&arg1); - break; - case AAT_BOOL: - val._type = OT_BOOL; - val._unVal.nInteger = arg1; - break; - default: val._type = OT_INTEGER; assert(0); break; + break; + case AAT_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = *((const SQFloat *)&arg1); + break; + case AAT_BOOL: + val._type = OT_BOOL; + val._unVal.nInteger = arg1; + break; + default: val._type = OT_INTEGER; assert(0); break; - } - _array(STK(arg0))->Append(val); continue; - } - case _OP_COMPARITH: { - SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16); - _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); - } - continue; - case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue; - case _OP_INCL: { - SQObjectPtr &a = STK(arg1); - if(sq_type(a) == OT_INTEGER) { - a._unVal.nInteger = _integer(a) + sarg3; - } - else { - SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o)); - _ARITH_(+,a,a,o); - } - } continue; - case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue; - case _OP_PINCL: { - SQObjectPtr &a = STK(arg1); - if(sq_type(a) == OT_INTEGER) { - TARGET = a; - a._unVal.nInteger = _integer(a) + sarg3; - } - else { - SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o)); - } + } + _array(STK(arg0))->Append(val); continue; + } + case _OP_COMPARITH: { + SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16); + _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); + } + continue; + case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue; + case _OP_INCL: { + SQObjectPtr &a = STK(arg1); + if(sq_type(a) == OT_INTEGER) { + a._unVal.nInteger = _integer(a) + sarg3; + } + else { + SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o)); + _ARITH_(+,a,a,o); + } + } continue; + case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue; + case _OP_PINCL: { + SQObjectPtr &a = STK(arg1); + if(sq_type(a) == OT_INTEGER) { + TARGET = a; + a._unVal.nInteger = _integer(a) + sarg3; + } + else { + SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o)); + } - } continue; - case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; - case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | GET_FLAG_RAW, DONT_FALL_BACK) ? true : false; continue; - case _OP_INSTANCEOF: - if(sq_type(STK(arg1)) != OT_CLASS) - {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} - TARGET = (sq_type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false; - continue; - case _OP_AND: - if(IsFalse(STK(arg2))) { - TARGET = STK(arg2); - ci->_ip += (sarg1); - } - continue; - case _OP_OR: - if(!IsFalse(STK(arg2))) { - TARGET = STK(arg2); - ci->_ip += (sarg1); - } - continue; - case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; - case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue; - case _OP_BWNOT: - if(sq_type(STK(arg1)) == OT_INTEGER) { - SQInteger t = _integer(STK(arg1)); - TARGET = SQInteger(~t); - continue; - } - Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); - SQ_THROW(); - case _OP_CLOSURE: { - SQClosure *c = ci->_closure._unVal.pClosure; - SQFunctionProto *fp = c->_function; - if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } - continue; - } - case _OP_YIELD:{ - if(ci->_generator) { - if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); - _GUARD(ci->_generator->Yield(this,arg2)); - traps -= ci->_etraps; - if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg; - } - else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} - if(Return(arg0, arg1, temp_reg)){ - assert(traps == 0); - outres = temp_reg; - return true; - } + } continue; + case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; + case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | GET_FLAG_RAW, DONT_FALL_BACK) ? true : false; continue; + case _OP_INSTANCEOF: + if(sq_type(STK(arg1)) != OT_CLASS) + {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} + TARGET = (sq_type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false; + continue; + case _OP_AND: + if(IsFalse(STK(arg2))) { + TARGET = STK(arg2); + ci->_ip += (sarg1); + } + continue; + case _OP_OR: + if(!IsFalse(STK(arg2))) { + TARGET = STK(arg2); + ci->_ip += (sarg1); + } + continue; + case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; + case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue; + case _OP_BWNOT: + if(sq_type(STK(arg1)) == OT_INTEGER) { + SQInteger t = _integer(STK(arg1)); + TARGET = SQInteger(~t); + continue; + } + Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); + SQ_THROW(); + case _OP_CLOSURE: { + SQClosure *c = ci->_closure._unVal.pClosure; + SQFunctionProto *fp = c->_function; + if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } + continue; + } + case _OP_YIELD:{ + if(ci->_generator) { + if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); + _GUARD(ci->_generator->Yield(this,arg2)); + traps -= ci->_etraps; + if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg; + } + else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} + if(Return(arg0, arg1, temp_reg)){ + assert(traps == 0); + outres = temp_reg; + return true; + } - } - continue; - case _OP_RESUME: - if(sq_type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} - _GUARD(_generator(STK(arg1))->Resume(this, TARGET)); - traps += ci->_etraps; - continue; - case _OP_FOREACH:{ int tojump; - _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump)); - ci->_ip += tojump; } - continue; - case _OP_POSTFOREACH: - assert(sq_type(STK(arg0)) == OT_GENERATOR); - if(_generator(STK(arg0))->_state == SQGenerator::eDead) - ci->_ip += (sarg1 - 1); - continue; - case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue; - case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue; - case _OP_PUSHTRAP:{ - SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions; - _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; - ci->_etraps++; - } - continue; - case _OP_POPTRAP: { - for(SQInteger i = 0; i < arg0; i++) { - _etraps.pop_back(); traps--; - ci->_etraps--; - } - } - continue; - case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; - case _OP_NEWSLOTA: - _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false)); - continue; - case _OP_GETBASE:{ - SQClosure *clo = _closure(ci->_closure); - if(clo->_base) { - TARGET = clo->_base; - } - else { - TARGET.Null(); - } - continue; - } - case _OP_CLOSE: - if(_openouters) CloseOuters(&(STK(arg1))); - continue; - } + } + continue; + case _OP_RESUME: + if(sq_type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} + _GUARD(_generator(STK(arg1))->Resume(this, TARGET)); + traps += ci->_etraps; + continue; + case _OP_FOREACH:{ int tojump; + _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump)); + ci->_ip += tojump; } + continue; + case _OP_POSTFOREACH: + assert(sq_type(STK(arg0)) == OT_GENERATOR); + if(_generator(STK(arg0))->_state == SQGenerator::eDead) + ci->_ip += (sarg1 - 1); + continue; + case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue; + case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue; + case _OP_PUSHTRAP:{ + SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions; + _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; + ci->_etraps++; + } + continue; + case _OP_POPTRAP: { + for(SQInteger i = 0; i < arg0; i++) { + _etraps.pop_back(); traps--; + ci->_etraps--; + } + } + continue; + case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; + case _OP_NEWSLOTA: + _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false)); + continue; + case _OP_GETBASE:{ + SQClosure *clo = _closure(ci->_closure); + if(clo->_base) { + TARGET = clo->_base; + } + else { + TARGET.Null(); + } + continue; + } + case _OP_CLOSE: + if(_openouters) CloseOuters(&(STK(arg1))); + continue; + } - } - } + } + } exception_trap: - { - SQObjectPtr currerror = _lasterror; -// dumpstack(_stackbase); -// SQInteger n = 0; - SQInteger last_top = _top; + { + SQObjectPtr currerror = _lasterror; +// dumpstack(_stackbase); +// SQInteger n = 0; + SQInteger last_top = _top; - if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror); + if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror); - while( ci ) { - if(ci->_etraps > 0) { - SQExceptionTrap &et = _etraps.top(); - ci->_ip = et._ip; - _top = et._stacksize; - _stackbase = et._stackbase; - _stack._vals[_stackbase + et._extarget] = currerror; - _etraps.pop_back(); traps--; ci->_etraps--; - while(last_top >= _top) _stack._vals[last_top--].Null(); - goto exception_restore; - } - else if (_debughook) { - //notify debugger of a "return" - //even if it really an exception unwinding the stack - for(SQInteger i = 0; i < ci->_ncalls; i++) { - CallDebugHook(_SC('r')); - } - } - if(ci->_generator) ci->_generator->Kill(); - bool mustbreak = ci && ci->_root; - LeaveFrame(); - if(mustbreak) break; - } + while( ci ) { + if(ci->_etraps > 0) { + SQExceptionTrap &et = _etraps.top(); + ci->_ip = et._ip; + _top = et._stacksize; + _stackbase = et._stackbase; + _stack._vals[_stackbase + et._extarget] = currerror; + _etraps.pop_back(); traps--; ci->_etraps--; + while(last_top >= _top) _stack._vals[last_top--].Null(); + goto exception_restore; + } + else if (_debughook) { + //notify debugger of a "return" + //even if it really an exception unwinding the stack + for(SQInteger i = 0; i < ci->_ncalls; i++) { + CallDebugHook(_SC('r')); + } + } + if(ci->_generator) ci->_generator->Kill(); + bool mustbreak = ci && ci->_root; + LeaveFrame(); + if(mustbreak) break; + } - _lasterror = currerror; - return false; - } - assert(0); + _lasterror = currerror; + return false; + } + assert(0); } bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) { - inst = theclass->CreateInstance(); - if(!theclass->GetConstructor(constructor)) { - constructor.Null(); - } - return true; + inst = theclass->CreateInstance(); + if(!theclass->GetConstructor(constructor)) { + constructor.Null(); + } + return true; } void SQVM::CallErrorHandler(SQObjectPtr &error) { - if(sq_type(_errorhandler) != OT_NULL) { - SQObjectPtr out; - Push(_roottable); Push(error); - Call(_errorhandler, 2, _top-2, out,SQFalse); - Pop(2); - } + if(sq_type(_errorhandler) != OT_NULL) { + SQObjectPtr out; + Push(_roottable); Push(error); + Call(_errorhandler, 2, _top-2, out,SQFalse); + Pop(2); + } } void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) { - _debughook = false; - SQFunctionProto *func=_closure(ci->_closure)->_function; - if(_debughook_native) { - const SQChar *src = sq_type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL; - const SQChar *fname = sq_type(func->_name) == OT_STRING?_stringval(func->_name):NULL; - SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip); - _debughook_native(this,type,src,line,fname); - } - else { - SQObjectPtr temp_reg; - SQInteger nparams=5; - Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); - Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse); - Pop(nparams); - } - _debughook = true; + _debughook = false; + SQFunctionProto *func=_closure(ci->_closure)->_function; + if(_debughook_native) { + const SQChar *src = sq_type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL; + const SQChar *fname = sq_type(func->_name) == OT_STRING?_stringval(func->_name):NULL; + SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip); + _debughook_native(this,type,src,line,fname); + } + else { + SQObjectPtr temp_reg; + SQInteger nparams=5; + Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); + Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse); + Pop(nparams); + } + _debughook = true; } bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, SQInt32 target,bool &suspend, bool &tailcall) { - SQInteger nparamscheck = nclosure->_nparamscheck; - SQInteger newtop = newbase + nargs + nclosure->_noutervalues; + SQInteger nparamscheck = nclosure->_nparamscheck; + SQInteger newtop = newbase + nargs + nclosure->_noutervalues; - if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { - Raise_Error(_SC("Native stack overflow")); - return false; - } + if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { + Raise_Error(_SC("Native stack overflow")); + return false; + } - if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) || - ((nparamscheck < 0) && (nargs < (-nparamscheck))))) - { - Raise_Error(_SC("wrong number of parameters")); - return false; - } + if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) || + ((nparamscheck < 0) && (nargs < (-nparamscheck))))) + { + Raise_Error(_SC("wrong number of parameters")); + return false; + } - SQInteger tcs; - SQIntVec &tc = nclosure->_typecheck; - if((tcs = tc.size())) { - for(SQInteger i = 0; i < nargs && i < tcs; i++) { - if((tc._vals[i] != -1) && !(sq_type(_stack._vals[newbase+i]) & tc._vals[i])) { - Raise_ParamTypeError(i,tc._vals[i], sq_type(_stack._vals[newbase+i])); - return false; - } - } - } + SQInteger tcs; + SQIntVec &tc = nclosure->_typecheck; + if((tcs = tc.size())) { + for(SQInteger i = 0; i < nargs && i < tcs; i++) { + if((tc._vals[i] != -1) && !(sq_type(_stack._vals[newbase+i]) & tc._vals[i])) { + Raise_ParamTypeError(i,tc._vals[i], sq_type(_stack._vals[newbase+i])); + return false; + } + } + } - if(!EnterFrame(newbase, newtop, false)) return false; - ci->_closure = nclosure; + if(!EnterFrame(newbase, newtop, false)) return false; + ci->_closure = nclosure; ci->_target = target; - SQInteger outers = nclosure->_noutervalues; - for (SQInteger i = 0; i < outers; i++) { - _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i]; - } - if(nclosure->_env) { - _stack._vals[newbase] = nclosure->_env->_obj; - } + SQInteger outers = nclosure->_noutervalues; + for (SQInteger i = 0; i < outers; i++) { + _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i]; + } + if(nclosure->_env) { + _stack._vals[newbase] = nclosure->_env->_obj; + } - _nnativecalls++; - SQInteger ret = (nclosure->_function)(this); - _nnativecalls--; + _nnativecalls++; + SQInteger ret = (nclosure->_function)(this); + _nnativecalls--; - suspend = false; + suspend = false; tailcall = false; if (ret == SQ_TAILCALL_FLAG) { tailcall = true; return true; } - else if (ret == SQ_SUSPEND_FLAG) { - suspend = true; - } - else if (ret < 0) { - LeaveFrame(); - Raise_Error(_lasterror); - return false; - } - if(ret) { - retval = _stack._vals[_top-1]; - } - else { - retval.Null(); - } - //retval = ret ? _stack._vals[_top-1] : _null_; - LeaveFrame(); - return true; + else if (ret == SQ_SUSPEND_FLAG) { + suspend = true; + } + else if (ret < 0) { + LeaveFrame(); + Raise_Error(_lasterror); + return false; + } + if(ret) { + retval = _stack._vals[_top-1]; + } + else { + retval.Null(); + } + //retval = ret ? _stack._vals[_top-1] : _null_; + LeaveFrame(); + return true; } bool SQVM::TailCall(SQClosure *closure, SQInteger parambase,SQInteger nparams) @@ -1230,343 +1230,343 @@ bool SQVM::TailCall(SQClosure *closure, SQInteger parambase,SQInteger nparams) return ret; } -#define FALLBACK_OK 0 +#define FALLBACK_OK 0 #define FALLBACK_NO_MATCH 1 -#define FALLBACK_ERROR 2 +#define FALLBACK_ERROR 2 bool SQVM::Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx) { - switch(sq_type(self)){ - case OT_TABLE: - if(_table(self)->Get(key,dest))return true; - break; - case OT_ARRAY: - if (sq_isnumeric(key)) { if (_array(self)->Get(tointeger(key), dest)) { return true; } if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); return false; } - break; - case OT_INSTANCE: - if(_instance(self)->Get(key,dest)) return true; - break; - case OT_CLASS: - if(_class(self)->Get(key,dest)) return true; - break; - case OT_STRING: - if(sq_isnumeric(key)){ - SQInteger n = tointeger(key); - SQInteger len = _string(self)->_len; - if (n < 0) { n += len; } - if (n >= 0 && n < len) { - dest = SQInteger(_stringval(self)[n]); - return true; - } - if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); - return false; - } - break; - default:break; //shut up compiler - } - if ((getflags & GET_FLAG_RAW) == 0) { - switch(FallBackGet(self,key,dest)) { - case FALLBACK_OK: return true; //okie - case FALLBACK_NO_MATCH: break; //keep falling back - case FALLBACK_ERROR: return false; // the metamethod failed - } - if(InvokeDefaultDelegate(self,key,dest)) { - return true; - } - } + switch(sq_type(self)){ + case OT_TABLE: + if(_table(self)->Get(key,dest))return true; + break; + case OT_ARRAY: + if (sq_isnumeric(key)) { if (_array(self)->Get(tointeger(key), dest)) { return true; } if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); return false; } + break; + case OT_INSTANCE: + if(_instance(self)->Get(key,dest)) return true; + break; + case OT_CLASS: + if(_class(self)->Get(key,dest)) return true; + break; + case OT_STRING: + if(sq_isnumeric(key)){ + SQInteger n = tointeger(key); + SQInteger len = _string(self)->_len; + if (n < 0) { n += len; } + if (n >= 0 && n < len) { + dest = SQInteger(_stringval(self)[n]); + return true; + } + if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); + return false; + } + break; + default:break; //shut up compiler + } + if ((getflags & GET_FLAG_RAW) == 0) { + switch(FallBackGet(self,key,dest)) { + case FALLBACK_OK: return true; //okie + case FALLBACK_NO_MATCH: break; //keep falling back + case FALLBACK_ERROR: return false; // the metamethod failed + } + if(InvokeDefaultDelegate(self,key,dest)) { + return true; + } + } //#ifdef ROOT_FALLBACK - if(selfidx == 0) { - SQWeakRef *w = _closure(ci->_closure)->_root; - if(sq_type(w->_obj) != OT_NULL) - { - if(Get(*((const SQObjectPtr *)&w->_obj),key,dest,0,DONT_FALL_BACK)) return true; - } + if(selfidx == 0) { + SQWeakRef *w = _closure(ci->_closure)->_root; + if(sq_type(w->_obj) != OT_NULL) + { + if(Get(*((const SQObjectPtr *)&w->_obj),key,dest,0,DONT_FALL_BACK)) return true; + } - } + } //#endif - if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); - return false; + if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); + return false; } bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) { - SQTable *ddel = NULL; - switch(sq_type(self)) { - case OT_CLASS: ddel = _class_ddel; break; - case OT_TABLE: ddel = _table_ddel; break; - case OT_ARRAY: ddel = _array_ddel; break; - case OT_STRING: ddel = _string_ddel; break; - case OT_INSTANCE: ddel = _instance_ddel; break; - case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break; - case OT_GENERATOR: ddel = _generator_ddel; break; - case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break; - case OT_THREAD: ddel = _thread_ddel; break; - case OT_WEAKREF: ddel = _weakref_ddel; break; - default: return false; - } - return ddel->Get(key,dest); + SQTable *ddel = NULL; + switch(sq_type(self)) { + case OT_CLASS: ddel = _class_ddel; break; + case OT_TABLE: ddel = _table_ddel; break; + case OT_ARRAY: ddel = _array_ddel; break; + case OT_STRING: ddel = _string_ddel; break; + case OT_INSTANCE: ddel = _instance_ddel; break; + case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break; + case OT_GENERATOR: ddel = _generator_ddel; break; + case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break; + case OT_THREAD: ddel = _thread_ddel; break; + case OT_WEAKREF: ddel = _weakref_ddel; break; + default: return false; + } + return ddel->Get(key,dest); } SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) { - switch(sq_type(self)){ - case OT_TABLE: - case OT_USERDATA: - //delegation - if(_delegable(self)->_delegate) { - if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,0,DONT_FALL_BACK)) return FALLBACK_OK; - } - else { - return FALLBACK_NO_MATCH; - } - //go through - case OT_INSTANCE: { - SQObjectPtr closure; - if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) { - Push(self);Push(key); - _nmetamethodscall++; - AutoDec ad(&_nmetamethodscall); - if(Call(closure, 2, _top - 2, dest, SQFalse)) { - Pop(2); - return FALLBACK_OK; - } - else { - Pop(2); - if(sq_type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) - return FALLBACK_ERROR; - } - } - } - } - break; - default: break;//shutup GCC 4.x - } - // no metamethod or no fallback type - return FALLBACK_NO_MATCH; + switch(sq_type(self)){ + case OT_TABLE: + case OT_USERDATA: + //delegation + if(_delegable(self)->_delegate) { + if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,0,DONT_FALL_BACK)) return FALLBACK_OK; + } + else { + return FALLBACK_NO_MATCH; + } + //go through + case OT_INSTANCE: { + SQObjectPtr closure; + if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) { + Push(self);Push(key); + _nmetamethodscall++; + AutoDec ad(&_nmetamethodscall); + if(Call(closure, 2, _top - 2, dest, SQFalse)) { + Pop(2); + return FALLBACK_OK; + } + else { + Pop(2); + if(sq_type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) + return FALLBACK_ERROR; + } + } + } + } + break; + default: break;//shutup GCC 4.x + } + // no metamethod or no fallback type + return FALLBACK_NO_MATCH; } bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx) { - switch(sq_type(self)){ - case OT_TABLE: - if(_table(self)->Set(key,val)) return true; - break; - case OT_INSTANCE: - if(_instance(self)->Set(key,val)) return true; - break; - case OT_ARRAY: - if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } - if(!_array(self)->Set(tointeger(key),val)) { - Raise_IdxError(key); - return false; - } - return true; - case OT_USERDATA: break; // must fall back - default: - Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); - return false; - } + switch(sq_type(self)){ + case OT_TABLE: + if(_table(self)->Set(key,val)) return true; + break; + case OT_INSTANCE: + if(_instance(self)->Set(key,val)) return true; + break; + case OT_ARRAY: + if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } + if(!_array(self)->Set(tointeger(key),val)) { + Raise_IdxError(key); + return false; + } + return true; + case OT_USERDATA: break; // must fall back + default: + Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); + return false; + } - switch(FallBackSet(self,key,val)) { - case FALLBACK_OK: return true; //okie - case FALLBACK_NO_MATCH: break; //keep falling back - case FALLBACK_ERROR: return false; // the metamethod failed - } - if(selfidx == 0) { - if(_table(_roottable)->Set(key,val)) - return true; - } - Raise_IdxError(key); - return false; + switch(FallBackSet(self,key,val)) { + case FALLBACK_OK: return true; //okie + case FALLBACK_NO_MATCH: break; //keep falling back + case FALLBACK_ERROR: return false; // the metamethod failed + } + if(selfidx == 0) { + if(_table(_roottable)->Set(key,val)) + return true; + } + Raise_IdxError(key); + return false; } SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val) { - switch(sq_type(self)) { - case OT_TABLE: - if(_table(self)->_delegate) { - if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK; - } - //keps on going - case OT_INSTANCE: - case OT_USERDATA:{ - SQObjectPtr closure; - SQObjectPtr t; - if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) { - Push(self);Push(key);Push(val); - _nmetamethodscall++; - AutoDec ad(&_nmetamethodscall); - if(Call(closure, 3, _top - 3, t, SQFalse)) { - Pop(3); - return FALLBACK_OK; - } - else { - Pop(3); - if(sq_type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) - return FALLBACK_ERROR; - } - } - } - } - break; - default: break;//shutup GCC 4.x - } - // no metamethod or no fallback type - return FALLBACK_NO_MATCH; + switch(sq_type(self)) { + case OT_TABLE: + if(_table(self)->_delegate) { + if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK; + } + //keps on going + case OT_INSTANCE: + case OT_USERDATA:{ + SQObjectPtr closure; + SQObjectPtr t; + if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) { + Push(self);Push(key);Push(val); + _nmetamethodscall++; + AutoDec ad(&_nmetamethodscall); + if(Call(closure, 3, _top - 3, t, SQFalse)) { + Pop(3); + return FALLBACK_OK; + } + else { + Pop(3); + if(sq_type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) + return FALLBACK_ERROR; + } + } + } + } + break; + default: break;//shutup GCC 4.x + } + // no metamethod or no fallback type + return FALLBACK_NO_MATCH; } bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) { - SQObjectPtr temp_reg; - SQObjectPtr newobj; - switch(sq_type(self)){ - case OT_TABLE: - newobj = _table(self)->Clone(); - goto cloned_mt; - case OT_INSTANCE: { - newobj = _instance(self)->Clone(_ss(this)); + SQObjectPtr temp_reg; + SQObjectPtr newobj; + switch(sq_type(self)){ + case OT_TABLE: + newobj = _table(self)->Clone(); + goto cloned_mt; + case OT_INSTANCE: { + newobj = _instance(self)->Clone(_ss(this)); cloned_mt: - SQObjectPtr closure; - if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) { - Push(newobj); - Push(self); - if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg)) - return false; - } - } - target = newobj; - return true; - case OT_ARRAY: - target = _array(self)->Clone(); - return true; - default: - Raise_Error(_SC("cloning a %s"), GetTypeName(self)); - return false; - } + SQObjectPtr closure; + if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) { + Push(newobj); + Push(self); + if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg)) + return false; + } + } + target = newobj; + return true; + case OT_ARRAY: + target = _array(self)->Clone(); + return true; + default: + Raise_Error(_SC("cloning a %s"), GetTypeName(self)); + return false; + } } bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw) { - if(sq_type(self) != OT_CLASS) { - Raise_Error(_SC("object must be a class")); - return false; - } - SQClass *c = _class(self); - if(!raw) { - SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; - if(sq_type(mm) != OT_NULL ) { - Push(self); Push(key); Push(val); - Push(attrs); - Push(bstatic); - return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg); - } - } - if(!NewSlot(self, key, val,bstatic)) - return false; - if(sq_type(attrs) != OT_NULL) { - c->SetAttributes(key,attrs); - } - return true; + if(sq_type(self) != OT_CLASS) { + Raise_Error(_SC("object must be a class")); + return false; + } + SQClass *c = _class(self); + if(!raw) { + SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; + if(sq_type(mm) != OT_NULL ) { + Push(self); Push(key); Push(val); + Push(attrs); + Push(bstatic); + return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg); + } + } + if(!NewSlot(self, key, val,bstatic)) + return false; + if(sq_type(attrs) != OT_NULL) { + c->SetAttributes(key,attrs); + } + return true; } bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) { - if(sq_type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } - switch(sq_type(self)) { - case OT_TABLE: { - bool rawcall = true; - if(_table(self)->_delegate) { - SQObjectPtr res; - if(!_table(self)->Get(key,res)) { - SQObjectPtr closure; - if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { - Push(self);Push(key);Push(val); - if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { - return false; - } - rawcall = false; - } - else { - rawcall = true; - } - } - } - if(rawcall) _table(self)->NewSlot(key,val); //cannot fail + if(sq_type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } + switch(sq_type(self)) { + case OT_TABLE: { + bool rawcall = true; + if(_table(self)->_delegate) { + SQObjectPtr res; + if(!_table(self)->Get(key,res)) { + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { + Push(self);Push(key);Push(val); + if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { + return false; + } + rawcall = false; + } + else { + rawcall = true; + } + } + } + if(rawcall) _table(self)->NewSlot(key,val); //cannot fail - break;} - case OT_INSTANCE: { - SQObjectPtr res; - SQObjectPtr closure; - if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { - Push(self);Push(key);Push(val); - if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { - return false; - } - break; - } - Raise_Error(_SC("class instances do not support the new slot operator")); - return false; - break;} - case OT_CLASS: - if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { - if(_class(self)->_locked) { - Raise_Error(_SC("trying to modify a class that has already been instantiated")); - return false; - } - else { - SQObjectPtr oval = PrintObjVal(key); - Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); - return false; - } - } - break; - default: - Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); - return false; - break; - } - return true; + break;} + case OT_INSTANCE: { + SQObjectPtr res; + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { + Push(self);Push(key);Push(val); + if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { + return false; + } + break; + } + Raise_Error(_SC("class instances do not support the new slot operator")); + return false; + break;} + case OT_CLASS: + if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { + if(_class(self)->_locked) { + Raise_Error(_SC("trying to modify a class that has already been instantiated")); + return false; + } + else { + SQObjectPtr oval = PrintObjVal(key); + Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); + return false; + } + } + break; + default: + Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); + return false; + break; + } + return true; } bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) { - switch(sq_type(self)) { - case OT_TABLE: - case OT_INSTANCE: - case OT_USERDATA: { - SQObjectPtr t; - //bool handled = false; - SQObjectPtr closure; - if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) { - Push(self);Push(key); - return CallMetaMethod(closure,MT_DELSLOT,2,res); - } - else { - if(sq_type(self) == OT_TABLE) { - if(_table(self)->Get(key,t)) { - _table(self)->Remove(key); - } - else { - Raise_IdxError((const SQObject &)key); - return false; - } - } - else { - Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); - return false; - } - } - res = t; - } - break; - default: - Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); - return false; - } - return true; + switch(sq_type(self)) { + case OT_TABLE: + case OT_INSTANCE: + case OT_USERDATA: { + SQObjectPtr t; + //bool handled = false; + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) { + Push(self);Push(key); + return CallMetaMethod(closure,MT_DELSLOT,2,res); + } + else { + if(sq_type(self) == OT_TABLE) { + if(_table(self)->Get(key,t)) { + _table(self)->Remove(key); + } + else { + Raise_IdxError((const SQObject &)key); + return false; + } + } + else { + Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); + return false; + } + } + res = t; + } + break; + default: + Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); + return false; + } + return true; } bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror) @@ -1574,160 +1574,160 @@ bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObj #ifdef _DEBUG SQInteger prevstackbase = _stackbase; #endif - switch(sq_type(closure)) { - case OT_CLOSURE: - return Execute(closure, nparams, stackbase, outres, raiseerror); - break; - case OT_NATIVECLOSURE:{ - bool dummy; - return CallNative(_nativeclosure(closure), nparams, stackbase, outres, -1, dummy, dummy); + switch(sq_type(closure)) { + case OT_CLOSURE: + return Execute(closure, nparams, stackbase, outres, raiseerror); + break; + case OT_NATIVECLOSURE:{ + bool dummy; + return CallNative(_nativeclosure(closure), nparams, stackbase, outres, -1, dummy, dummy); - } - break; - case OT_CLASS: { - SQObjectPtr constr; - SQObjectPtr temp; - CreateClassInstance(_class(closure),outres,constr); - SQObjectType ctype = sq_type(constr); - if (ctype == OT_NATIVECLOSURE || ctype == OT_CLOSURE) { - _stack[stackbase] = outres; - return Call(constr,nparams,stackbase,temp,raiseerror); - } - return true; - } - break; - default: - return false; - } + } + break; + case OT_CLASS: { + SQObjectPtr constr; + SQObjectPtr temp; + CreateClassInstance(_class(closure),outres,constr); + SQObjectType ctype = sq_type(constr); + if (ctype == OT_NATIVECLOSURE || ctype == OT_CLOSURE) { + _stack[stackbase] = outres; + return Call(constr,nparams,stackbase,temp,raiseerror); + } + return true; + } + break; + default: + return false; + } #ifdef _DEBUG - if(!_suspended) { - assert(_stackbase == prevstackbase); - } + if(!_suspended) { + assert(_stackbase == prevstackbase); + } #endif - return true; + return true; } bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod SQ_UNUSED_ARG(mm),SQInteger nparams,SQObjectPtr &outres) { - //SQObjectPtr closure; + //SQObjectPtr closure; - _nmetamethodscall++; - if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { - _nmetamethodscall--; - Pop(nparams); - return true; - } - _nmetamethodscall--; - //} - Pop(nparams); - return false; + _nmetamethodscall++; + if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { + _nmetamethodscall--; + Pop(nparams); + return true; + } + _nmetamethodscall--; + //} + Pop(nparams); + return false; } void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex) { - SQOuter **pp = &_openouters; - SQOuter *p; - SQOuter *otr; + SQOuter **pp = &_openouters; + SQOuter *p; + SQOuter *otr; - while ((p = *pp) != NULL && p->_valptr >= stackindex) { - if (p->_valptr == stackindex) { - target = SQObjectPtr(p); - return; - } - pp = &p->_next; - } - otr = SQOuter::Create(_ss(this), stackindex); - otr->_next = *pp; - otr->_idx = (stackindex - _stack._vals); - __ObjAddRef(otr); - *pp = otr; - target = SQObjectPtr(otr); + while ((p = *pp) != NULL && p->_valptr >= stackindex) { + if (p->_valptr == stackindex) { + target = SQObjectPtr(p); + return; + } + pp = &p->_next; + } + otr = SQOuter::Create(_ss(this), stackindex); + otr->_next = *pp; + otr->_idx = (stackindex - _stack._vals); + __ObjAddRef(otr); + *pp = otr; + target = SQObjectPtr(otr); } bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall) { - if( !tailcall ) { - if( _callsstacksize == _alloccallsstacksize ) { - GrowCallStack(); - } - ci = &_callsstack[_callsstacksize++]; - ci->_prevstkbase = (SQInt32)(newbase - _stackbase); - ci->_prevtop = (SQInt32)(_top - _stackbase); - ci->_etraps = 0; - ci->_ncalls = 1; - ci->_generator = NULL; - ci->_root = SQFalse; - } - else { - ci->_ncalls++; - } + if( !tailcall ) { + if( _callsstacksize == _alloccallsstacksize ) { + GrowCallStack(); + } + ci = &_callsstack[_callsstacksize++]; + ci->_prevstkbase = (SQInt32)(newbase - _stackbase); + ci->_prevtop = (SQInt32)(_top - _stackbase); + ci->_etraps = 0; + ci->_ncalls = 1; + ci->_generator = NULL; + ci->_root = SQFalse; + } + else { + ci->_ncalls++; + } - _stackbase = newbase; - _top = newtop; - if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) { - if(_nmetamethodscall) { - Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod")); - return false; - } - _stack.resize(newtop + (MIN_STACK_OVERHEAD << 2)); - RelocateOuters(); - } - return true; + _stackbase = newbase; + _top = newtop; + if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) { + if(_nmetamethodscall) { + Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod")); + return false; + } + _stack.resize(newtop + (MIN_STACK_OVERHEAD << 2)); + RelocateOuters(); + } + return true; } void SQVM::LeaveFrame() { - SQInteger last_top = _top; - SQInteger last_stackbase = _stackbase; - SQInteger css = --_callsstacksize; + SQInteger last_top = _top; + SQInteger last_stackbase = _stackbase; + SQInteger css = --_callsstacksize; - /* First clean out the call stack frame */ - ci->_closure.Null(); - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - ci = (css) ? &_callsstack[css-1] : NULL; + /* First clean out the call stack frame */ + ci->_closure.Null(); + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + ci = (css) ? &_callsstack[css-1] : NULL; - if(_openouters) CloseOuters(&(_stack._vals[last_stackbase])); - while (last_top >= _top) { - _stack._vals[last_top--].Null(); - } + if(_openouters) CloseOuters(&(_stack._vals[last_stackbase])); + while (last_top >= _top) { + _stack._vals[last_top--].Null(); + } } void SQVM::RelocateOuters() { - SQOuter *p = _openouters; - while (p) { - p->_valptr = _stack._vals + p->_idx; - p = p->_next; - } + SQOuter *p = _openouters; + while (p) { + p->_valptr = _stack._vals + p->_idx; + p = p->_next; + } } void SQVM::CloseOuters(SQObjectPtr *stackindex) { SQOuter *p; while ((p = _openouters) != NULL && p->_valptr >= stackindex) { - p->_value = *(p->_valptr); - p->_valptr = &p->_value; - _openouters = p->_next; - __ObjRelease(p); + p->_value = *(p->_valptr); + p->_valptr = &p->_value; + _openouters = p->_next; + __ObjRelease(p); } } void SQVM::Remove(SQInteger n) { - n = (n >= 0)?n + _stackbase - 1:_top + n; - for(SQInteger i = n; i < _top; i++){ - _stack[i] = _stack[i+1]; - } - _stack[_top].Null(); - _top--; + n = (n >= 0)?n + _stackbase - 1:_top + n; + for(SQInteger i = n; i < _top; i++){ + _stack[i] = _stack[i+1]; + } + _stack[_top].Null(); + _top--; } void SQVM::Pop() { - _stack[--_top].Null(); + _stack[--_top].Null(); } void SQVM::Pop(SQInteger n) { - for(SQInteger i = 0; i < n; i++){ - _stack[--_top].Null(); - } + for(SQInteger i = 0; i < n; i++){ + _stack[--_top].Null(); + } } void SQVM::PushNull() { _stack[_top++].Null(); } @@ -1740,41 +1740,41 @@ SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; } #ifdef _DEBUG_DUMP void SQVM::dumpstack(SQInteger stackbase,bool dumpall) { - SQInteger size=dumpall?_stack.size():_top; - SQInteger n=0; - scprintf(_SC("\n>>>>stack dump<<<<\n")); - CallInfo &ci=_callsstack[_callsstacksize-1]; - scprintf(_SC("IP: %p\n"),ci._ip); - scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); - scprintf(_SC("prev top: %d\n"),ci._prevtop); - for(SQInteger i=0;i"));else scprintf(_SC(" ")); - scprintf(_SC("[" _PRINT_INT_FMT "]:"),n); - switch(sq_type(obj)){ - case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break; - case OT_INTEGER: scprintf(_SC("INTEGER " _PRINT_INT_FMT),_integer(obj));break; - case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break; - case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break; - case OT_NULL: scprintf(_SC("NULL")); break; - case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break; - case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break; - case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break; - case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break; - case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break; - case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break; - case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break; - case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break; - case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break; - case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break; - case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break; - default: - assert(0); - break; - }; - scprintf(_SC("\n")); - ++n; - } + SQInteger size=dumpall?_stack.size():_top; + SQInteger n=0; + scprintf(_SC("\n>>>>stack dump<<<<\n")); + CallInfo &ci=_callsstack[_callsstacksize-1]; + scprintf(_SC("IP: %p\n"),ci._ip); + scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); + scprintf(_SC("prev top: %d\n"),ci._prevtop); + for(SQInteger i=0;i"));else scprintf(_SC(" ")); + scprintf(_SC("[" _PRINT_INT_FMT "]:"),n); + switch(sq_type(obj)){ + case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break; + case OT_INTEGER: scprintf(_SC("INTEGER " _PRINT_INT_FMT),_integer(obj));break; + case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break; + case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break; + case OT_NULL: scprintf(_SC("NULL")); break; + case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break; + case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break; + case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break; + case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break; + case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break; + case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break; + case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break; + case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break; + case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break; + case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break; + case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break; + default: + assert(0); + break; + }; + scprintf(_SC("\n")); + ++n; + } } diff --git a/rabbit/sqvm.hpp b/rabbit/sqvm.hpp index c7c196f..e5246f6 100644 --- a/rabbit/sqvm.hpp +++ b/rabbit/sqvm.hpp @@ -18,19 +18,19 @@ #define DONT_FALL_BACK 666 //#define EXISTS_FALL_BACK -1 -#define GET_FLAG_RAW 0x00000001 +#define GET_FLAG_RAW 0x00000001 #define GET_FLAG_DO_NOT_RAISE_ERROR 0x00000002 //base lib void sq_base_register(HRABBITVM v); struct SQExceptionTrap{ - SQExceptionTrap() {} - SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;} - SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; } - SQInteger _stackbase; - SQInteger _stacksize; - SQInstruction *_ip; - SQInteger _extarget; + SQExceptionTrap() {} + SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;} + SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; } + SQInteger _stackbase; + SQInteger _stacksize; + SQInstruction *_ip; + SQInteger _extarget; }; #define _INLINE @@ -39,152 +39,152 @@ typedef sqvector ExceptionsTraps; struct SQVM : public CHAINABLE_OBJ { - struct CallInfo{ - //CallInfo() { _generator = NULL;} - SQInstruction *_ip; - SQObjectPtr *_literals; - SQObjectPtr _closure; - SQGenerator *_generator; - SQInt32 _etraps; - SQInt32 _prevstkbase; - SQInt32 _prevtop; - SQInt32 _target; - SQInt32 _ncalls; - SQBool _root; - }; + struct CallInfo{ + //CallInfo() { _generator = NULL;} + SQInstruction *_ip; + SQObjectPtr *_literals; + SQObjectPtr _closure; + SQGenerator *_generator; + SQInt32 _etraps; + SQInt32 _prevstkbase; + SQInt32 _prevtop; + SQInt32 _target; + SQInt32 _ncalls; + SQBool _root; + }; typedef sqvector CallInfoVec; public: - void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); - static void _DebugHookProxy(HRABBITVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); - enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM }; - SQVM(SQSharedState *ss); - ~SQVM(); - bool Init(SQVM *friendvm, SQInteger stacksize); - bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); - //starts a native call return when the NATIVE closure returns - bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, SQInt32 target, bool &suspend,bool &tailcall); + void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); + static void _DebugHookProxy(HRABBITVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); + enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM }; + SQVM(SQSharedState *ss); + ~SQVM(); + bool Init(SQVM *friendvm, SQInteger stacksize); + bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); + //starts a native call return when the NATIVE closure returns + bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, SQInt32 target, bool &suspend,bool &tailcall); bool TailCall(SQClosure *closure, SQInteger firstparam, SQInteger nparams); - //starts a RABBIT call in the same "Execution loop" - bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); - bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); - //call a generic closure pure RABBIT or NATIVE - bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror); - SQRESULT Suspend(); + //starts a RABBIT call in the same "Execution loop" + bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); + bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); + //call a generic closure pure RABBIT or NATIVE + bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror); + SQRESULT Suspend(); - void CallDebugHook(SQInteger type,SQInteger forcedline=0); - void CallErrorHandler(SQObjectPtr &e); - bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx); - SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); - bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); - bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx); - SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val); - bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); - bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw); - bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); - bool Clone(const SQObjectPtr &self, SQObjectPtr &target); - bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); - bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); - static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res); - bool ToString(const SQObjectPtr &o,SQObjectPtr &res); - SQString *PrintObjVal(const SQObjectPtr &o); + void CallDebugHook(SQInteger type,SQInteger forcedline=0); + void CallErrorHandler(SQObjectPtr &e); + bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx); + SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); + bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); + bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx); + SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val); + bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); + bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw); + bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); + bool Clone(const SQObjectPtr &self, SQObjectPtr &target); + bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); + bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); + static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res); + bool ToString(const SQObjectPtr &o,SQObjectPtr &res); + SQString *PrintObjVal(const SQObjectPtr &o); - void Raise_Error(const SQChar *s, ...); - void Raise_Error(const SQObjectPtr &desc); - void Raise_IdxError(const SQObjectPtr &o); - void Raise_CompareError(const SQObject &o1, const SQObject &o2); - void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); + void Raise_Error(const SQChar *s, ...); + void Raise_Error(const SQObjectPtr &desc); + void Raise_IdxError(const SQObjectPtr &o); + void Raise_CompareError(const SQObject &o1, const SQObject &o2); + void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); - void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex); - void RelocateOuters(); - void CloseOuters(SQObjectPtr *stackindex); + void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex); + void RelocateOuters(); + void CloseOuters(SQObjectPtr *stackindex); - bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); - bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); - bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); - bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); - //new stuff - _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); - _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); - _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); - _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); - bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); - bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); - //return true if the loop is finished - bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump); - //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); - _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); - _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0); + bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); + bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); + bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); + bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); + //new stuff + bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); + bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); + bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); + bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); + bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); + bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); + //return true if the loop is finished + bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump); + //bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0); #ifdef _DEBUG_DUMP - void dumpstack(SQInteger stackbase=-1, bool dumpall = false); + void dumpstack(SQInteger stackbase=-1, bool dumpall = false); #endif - void Finalize(); - void GrowCallStack() { - SQInteger newsize = _alloccallsstacksize*2; - _callstackdata.resize(newsize); - _callsstack = &_callstackdata[0]; - _alloccallsstacksize = newsize; - } - bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall); - void LeaveFrame(); - void Release(){ sq_delete(this,SQVM); } + void Finalize(); + void GrowCallStack() { + SQInteger newsize = _alloccallsstacksize*2; + _callstackdata.resize(newsize); + _callsstack = &_callstackdata[0]; + _alloccallsstacksize = newsize; + } + bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall); + void LeaveFrame(); + void Release(){ sq_delete(this,SQVM); } //////////////////////////////////////////////////////////////////////////// - //stack functions for the api - void Remove(SQInteger n); + //stack functions for the api + void Remove(SQInteger n); - static bool IsFalse(SQObjectPtr &o); + static bool IsFalse(SQObjectPtr &o); - void Pop(); - void Pop(SQInteger n); - void Push(const SQObjectPtr &o); - void PushNull(); - SQObjectPtr &Top(); - SQObjectPtr &PopGet(); - SQObjectPtr &GetUp(SQInteger n); - SQObjectPtr &GetAt(SQInteger n); + void Pop(); + void Pop(SQInteger n); + void Push(const SQObjectPtr &o); + void PushNull(); + SQObjectPtr &Top(); + SQObjectPtr &PopGet(); + SQObjectPtr &GetUp(SQInteger n); + SQObjectPtr &GetAt(SQInteger n); - SQObjectPtrVec _stack; + SQObjectPtrVec _stack; - SQInteger _top; - SQInteger _stackbase; - SQOuter *_openouters; - SQObjectPtr _roottable; - SQObjectPtr _lasterror; - SQObjectPtr _errorhandler; + SQInteger _top; + SQInteger _stackbase; + SQOuter *_openouters; + SQObjectPtr _roottable; + SQObjectPtr _lasterror; + SQObjectPtr _errorhandler; - bool _debughook; - SQDEBUGHOOK _debughook_native; - SQObjectPtr _debughook_closure; + bool _debughook; + SQDEBUGHOOK _debughook_native; + SQObjectPtr _debughook_closure; - SQObjectPtr temp_reg; + SQObjectPtr temp_reg; - CallInfo* _callsstack; - SQInteger _callsstacksize; - SQInteger _alloccallsstacksize; - sqvector _callstackdata; + CallInfo* _callsstack; + SQInteger _callsstacksize; + SQInteger _alloccallsstacksize; + sqvector _callstackdata; - ExceptionsTraps _etraps; - CallInfo *ci; - SQUserPointer _foreignptr; - //VMs sharing the same state - SQSharedState *_sharedstate; - SQInteger _nnativecalls; - SQInteger _nmetamethodscall; - SQRELEASEHOOK _releasehook; - //suspend infos - SQBool _suspended; - SQBool _suspended_root; - SQInteger _suspended_target; - SQInteger _suspended_traps; + ExceptionsTraps _etraps; + CallInfo *ci; + SQUserPointer _foreignptr; + //VMs sharing the same state + SQSharedState *_sharedstate; + SQInteger _nnativecalls; + SQInteger _nmetamethodscall; + SQRELEASEHOOK _releasehook; + //suspend infos + SQBool _suspended; + SQBool _suspended_root; + SQInteger _suspended_target; + SQInteger _suspended_traps; }; struct AutoDec{ - AutoDec(SQInteger *n) { _n = n; } - ~AutoDec() { (*_n)--; } - SQInteger *_n; + AutoDec(SQInteger *n) { _n = n; } + ~AutoDec() { (*_n)--; } + SQInteger *_n; }; inline SQObjectPtr &stack_get(HRABBITVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));} @@ -192,17 +192,17 @@ inline SQObjectPtr &stack_get(HRABBITVM v,SQInteger idx){return ((idx>=0)?(v->Ge #define _ss(_vm_) (_vm_)->_sharedstate #define PUSH_CALLINFO(v,nci){ \ - SQInteger css = v->_callsstacksize; \ - if(css == v->_alloccallsstacksize) { \ - v->GrowCallStack(); \ - } \ - v->ci = &v->_callsstack[css]; \ - *(v->ci) = nci; \ - v->_callsstacksize++; \ + SQInteger css = v->_callsstacksize; \ + if(css == v->_alloccallsstacksize) { \ + v->GrowCallStack(); \ + } \ + v->ci = &v->_callsstack[css]; \ + *(v->ci) = nci; \ + v->_callsstacksize++; \ } #define POP_CALLINFO(v){ \ - SQInteger css = --v->_callsstacksize; \ - v->ci->_closure.Null(); \ - v->ci = css?&v->_callsstack[css-1]:NULL; \ + SQInteger css = --v->_callsstacksize; \ + v->ci->_closure.Null(); \ + v->ci = css?&v->_callsstack[css-1]:NULL; \ }