--- /dev/null
+Copyright (c) 2003-2007 Alberto Demichelis\r
+\r
+This software is provided 'as-is', without any \r
+express or implied warranty. In no event will the \r
+authors be held liable for any damages arising from \r
+the use of this software.\r
+\r
+Permission is granted to anyone to use this software \r
+for any purpose, including commercial applications, \r
+and to alter it and redistribute it freely, subject \r
+to the following restrictions:\r
+\r
+ 1. The origin of this software must not be \r
+ misrepresented; you must not claim that \r
+ you wrote the original software. If you \r
+ use this software in a product, an \r
+ acknowledgment in the product \r
+ documentation would be appreciated but is \r
+ not required.\r
+\r
+ 2. Altered source versions must be plainly \r
+ marked as such, and must not be \r
+ misrepresented as being the original \r
+ software.\r
+\r
+ 3. This notice may not be removed or \r
+ altered from any source distribution.\r
+-----------------------------------------------------\r
+END OF COPYRIGHT
\ No newline at end of file
--- /dev/null
+***version 2.1.2 stable***\r
+-new behaviour for generators iteration using foreach\r
+now when a generator is iterated by foreach the value returned by a 'return val' statement\r
+will terminate the iteration but will not be returned as foreach iteration\r
+-added sq_setclassudsize()\r
+-added sq_clear()\r
+-added table.clear(), array.clear()\r
+-fixed sq_cmp() (thx jyuill)\r
+-fixed minor bugs\r
+\r
+***2006-08-21 ***\r
+***version 2.1.1 stable***\r
+-vm refactoring\r
+-optimized internal function memory layout\r
+-new global symbol _version_ (is the version string)\r
+-code size optimization for float literals(on 32bits float builts)\r
+-now the raw ref API(sq_addref etc...) is fully reentrant.\r
+-fixed a bug in sq_getdelegate() now pushes null if the object doesn't have a delegate(thx MatzeB)\r
+-improved C reference performances in NO_GARBAGE_COLLECTOR builds\r
+-sq_getlocal() now enumerates also outer values.\r
+-fixed regexp library for GCC users.\r
+\r
+***2006-03-19 ***\r
+***version 2.1 stable***\r
+-added static class fields, new keyword static\r
+-added 64bits architecture support\r
+-added global slot _intsize_ int the base lib to recognize 32bits and 64bits builds\r
+-added functions with fixed environment, closure.bindenv() built-in function\r
+-all types except userdata and null implement the tostring() method\r
+-string concatenation now invokes metamethod _tostring\r
+-new metamethods for class objects _newmember and _inherited\r
+-sq_call() sq_resume() sq_wakeupvm() have a new signature\r
+-new C referencing implementation(scales more with the amount of references)\r
+-refactored hash table\r
+-new api functions sq_newslot(),sq_tobool(),sq_getbase(), sq_instanceof(), sq_bindenv()\r
+-the api func sq_createslot was deprecated but still supported in form of C macro on top of sq_newslot\r
+-sq_setreleasehook() now also works for classes\r
+-stream.readstr() and stream.writestr() have been deprecated(this affects file and blob)\r
+-fixed squirrel.h undeclared api calls\r
+-fixed few minor bugs\r
+-SQChar is now defined as wchar_t\r
+-removed warning when building with -Wall -pedantic for GCC users\r
+-added new std io function writeclosuretofile()\r
+-added new std string functions strip(),rstrip(),lstrip() and split()\r
+-regular expressions operators (+,*) now have more POSIX greedyness behaviour\r
+-class constructors are now invoked as normal functions\r
+\r
+***2005-10-02 ***\r
+***version 2.0.5 stable***\r
+-fixed some 64bits incompatibilities (thx sarge)\r
+-fixed minor bug in the stdlib format() function (thx Rick)\r
+-fixed a bug in dofile() that was preventing to compile empty files\r
+-added new API sq_poptop() & sq_getfreevariable()\r
+-some performance improvements\r
+\r
+***2005-08-14 ***\r
+***version 2.0.4 stable***\r
+-weak references and related API calls\r
+-added sq_objtobool()\r
+-class instances memory policies improved(1 mem allocation for the whole instance)\r
+-typetags are now declared as SQUserPointer instead of unsigned int\r
+-first pass for 64bits compatibility\r
+-fixed minor bug in the stdio stream\r
+-fixed a bug in format()\r
+-fixed bug in string.tointeger() and string.tofloat()\r
+\r
+***2005-06-24 ***\r
+***version 2.0.3 stable***\r
+-dofile() and loadfile() in the iolib now can decode ASCII, UTF8 files UCS2 big-endian and little-endian\r
+-sq_setparamscheck() : now typemesk can check for null\r
+-added string escape sequence \xhhhh\r
+-fixed some C++ standard incompatibilities\r
+\r
+***2005-05-15 ***\r
+***version 2.0.2 stable***\r
+-performances improvements (expecially for GCC users)\r
+-removed all dependencies from C++ exception handling\r
+-various bugfixes\r
+\r
+***2005-04-12 ***\r
+***version 2.0.1 stable***\r
+-various bugfixes\r
+-sq_setparamscheck() now allows spaces in the typemask\r
+\r
+***2005-04-03 ***\r
+***version 2.0 stable***\r
+-added API sq_gettypetag()\r
+-added built-in function to the bool type(tointeger, tostring etc...)\r
+\r
+***2005-02-27 ***\r
+***version 2.0 release candidate 1(RC 1)***\r
+-added API sq_reseterror()\r
+-modified sq_release()\r
+-now class instances can be cloned\r
+-various bufixes\r
+\r
+***2005-01-26 ***\r
+***version 2.0 beta 1***\r
+-added bool type\r
+-class properties can be redefined in a derived class\r
+-added ops *= /= and %=\r
+-new syntax for class attributes declaration </ and /> instead of ( and )\r
+-increased the max number of literals per function from 65535 to 16777215\r
+-now free variables have proper lexical scoping\r
+-added API sq_createinstance(), sq_pushbool(), sq_getbool()\r
+-added built-in function type()\r
+-added built-in function obj.rawin(key) in table,class and instance\r
+-sq_rawget() and sq_rawset() now work also on classes and instances\r
+-the VM no longer uses C++ exception handling (more suitable for embedded devices)\r
+-various bufixes\r
+\r
+***2004-12-21 ***\r
+***version 2.0 alpha 2***\r
+-globals scoping changed, now if :: is omitted the VM automatically falls back on the root table\r
+-various bufixes\r
+-added class level attributes\r
+\r
+***2004-12-12 ***\r
+***version 2.0 alpha 1***\r
+-codebase branch from version 1.x\r
+-added classes\r
+-added functions with variable number of parameters(vargc & vargv and the ...)\r
+-0 and 0.0 are now considered 'false' by all conditional statements(if,while,for,?,do-while)\r
+-added new api functions sq_newclass() sq_setinstanceup() sq_getinstanceup() sq_getattributes() sq_setattributes()\r
+-modified api sq_settypetag()\r
+\r
+***2004-11-01 ***\r
+***version 1.0 stable***\r
+-fixed some minor bug\r
+-improoved operator 'delete' performances\r
+-added scientific notation for float numbers( eg. 2.e16 or 2.e-2)\r
+\r
+***2004-08-30 ***\r
+***version 1.0 release candidate 2(RC 2)***\r
+-fixed bug in the vm(thx Pierre Renaux)\r
+-fixed bug in the optimizer(thx Pierre Renaux)\r
+-fixed some bug in the documentation(thx JD)\r
+-added new api functions for raw object handling\r
+-removed nested multiline comments\r
+-reduced memory footprint in C references\r
+\r
+***2004-08-23 ***\r
+***version 1.0 release candidate 1(RC 1)***\r
+-fixed division by zero\r
+-the 'in' operator and obj.rawget() do not query the default delegate anymore\r
+-added function sq_getprintfunc()\r
+-added new standard library 'auxlib'(implements default error handlers)\r
+\r
+***2004-07-12 ***\r
+***version 1.0 beta 4***\r
+-fixed a bug in the integer.tochar() built-in method\r
+-fixed unary minus operator\r
+-fixed bug in dofile()\r
+-fixed inconsistency between != and == operators(on float/integer comparison)\r
+-added javascript style unsigned right shift operator '>>>'\r
+-added array(size) constructor built-in function\r
+-array.resize(size,[fill]) built-in function accepts an optional 'fill' value\r
+-improved debug API, added sq_getclosureinfo() and sq_setnativeclosurename()\r
+\r
+***2004-05-23 ***\r
+***version 1.0 beta 3***\r
+-minor vm bug fixes\r
+-string allocation is now faster\r
+-tables and array memory usage is now less conservative(they shrink)\r
+-added regular expression routines in the standard library\r
+-The 'c' expression now accepts only 1 character(thx irbrian)\r
+-multiline strings <[ ]> have been substituted with C# style verbatim strings (eg. @"string")\r
+-added new keyword 'parent' for accessing the delegate of tables and unserdata\r
+-The metamethod '_clone' has been renamed '_cloned'\r
+-the _delslot metamethod's behaviour and prototype have been changed\r
+-new default function in the integer and float object 'tochar()'\r
+-the built-in function chcode2string has been removed\r
+-the default method [table].getdelegate() has been removed\r
+-new api sq_rawdeleteslot()\r
+-new table built-in method rawdelete(key)\r
+-the dynamic mudule loading has been removed from the standard distribution\r
+-some optimizations in the VM\r
+\r
+***2004-04-21 ***\r
+***version 1.0 beta 2***\r
+-minor compiler/parser bug fixes\r
+-sq_newclosure has a different prototype, the "paramscheck" of paramter has been moved to the new function sq_setparamscheck()\r
+-sq_setparamscheck allows to add automatic parameters type checking in native closures\r
+-sq_compile() lost the lineinfo parameter\r
+-new api sq_enabledebuginfo() globally sets compiler's debug info generation\r
+-added consistency check on bytecode serialization\r
+-fixed += operator, now works on strings like +\r
+-added global slot in the base lib _charsize_ to recognize unicode builds from ascii builds runtime\r
+-added registry table\r
+-new api call sq_pushregistrytable()\r
+-added type tag to the userdata type sq_settypetag()\r
+-sq_getuserdata now queries the userdata typetag\r
+-the built in function collect_garbage() as been renamed collectgarbage() for consistency reasons\r
+-new standard libraries(sqlibs are now obsolete)\r
+\r
+***2004-02-20 ***\r
+***version 1.0 beta 1***\r
+-fixed a bug in the compiler (thanks Martin Kofler)\r
+-fixed bug in the switch case statement\r
+-fixed the _unm metamethod\r
+-fixed minor bugs in the API\r
+-fixed automatic stack resizing\r
+-first beta version \r
+ first pass code clean up in the VM and base lib\r
+ first pass code coverege test has been done on VM and built-in lib\r
+-new VM creation API sq_open() sq_close() (sq_newvm and sq_releasevm are now obsolete)\r
+-new api allows to specifiy a "print" function to output text(sq_printfunc)\r
+-added some small optimizations\r
+-new cooperative multi-threading capabilities in the base library(coroutines), VMs are now a built in type("thread")\r
+-new built in functions have been added for manipulating the new "thread" type\r
+-friend virtual machines share the same root table, error handler and debug hook by default\r
+-new compile time options\r
+\r
+***2004-01-19 ***\r
+***version 0.9 alpha***\r
+-fixed a garbage collection bug\r
+-fixed some API bugs(thanks to Joshua Jensen)\r
+-fixed tail calls (in the version 0.8 the tail call optimization was erroneously disabled)\r
+-new function parameters semantic, now passing a wrong number of parameters generates an exception\r
+-native closures have now a built in parameter number checking\r
+-sq_rawget and sq_rawset now work also on arrays\r
+-sq_getsize now woks also on userdata\r
+-the userdata release hook prototype is changed(now passes the size of the userdata)\r
+-the lexer reader function now returns an integer instead of a char that allows better error checking on the input(thx Joshua Jensen)\r
+-faster compiler\r
+-try/catch blocks do not cause any runtime memory allocation anymore\r
+\r
+***2003-12-06 ***\r
+***version 0.8 alpha***\r
+-fixed a bug that was preventing to have callable userdata throught the metamethod _call\r
+-fixed a garbage collection bug\r
+-fixed == operator now can compare correctly different types\r
+-new built in method getstackinfos(level)\r
+-improoved line informations precision for the debug hook\r
+-new api call sq_compilebuffer()\r
+-new built-in api function compilestring()\r
+-new syntactic sugar for function declarations inside tables\r
+-the debug API has been finalized\r
+\r
+***2003-11-17 ***\r
+***version 0.7 alpha***\r
+-fixed critical bug SQInteger the tail call system\r
+-fixed bug in the continue statement code generation\r
+-fixed func call param issue(thanks to Rewoonenco Andrew)\r
+-added _delslot metamethod(thanks to Rewoonenco Andrew)\r
+-new multiline string expression ( delimited by <[ and ]> )\r
+-normal strings ("") do not allow embedded new line anymore\r
+-reduced vm memory footprint(C refs are shared between friend VMs)\r
+-new api method sq_deleteslot()\r
+-new debug hook event 'r' is triggered when a function returns\r
+\r
+***2003-11-04 ***\r
+***version 0.6 alpha***\r
+-fixed switch statement(was executing the default case after a break)\r
+-sq_call() doesn't pop the closure (just the params)\r
+-the vm execution can be suspended from the C API anytime (micro-threads)\r
+-new api calls sq_suspendvm() sq_wakeupvm() sq_getvmstate() and sq_reservestack()\r
+\r
+***2003-10-13 ***\r
+***version 0.5 alpha***\r
+-fixed some minor bug\r
+-tested with non ASCII identifiers in unicode mode(I've tried chinese chars)\r
+-added built-in function string.find()\r
+-the built-in function array.sort() optionally accepts a cmp(a,b) function\r
+-the debug hook function now has a new prototype debug_hook(event_type,sourcefile,line,functionname)\r
+-fixed some debug info imprecision\r
+\r
+***2003-10-01 ***\r
+***version 0.4 alpha***\r
+-faster VM\r
+-sq_call will pop arguments and closure also in case of failure\r
+-fixed a bug in sq_remove\r
+-now the VM detects delegation cycles(and throws an exception)\r
+-new operators ++ and --\r
+-new operator ',' comma operator\r
+-fixed some expression precedence issue\r
+-fixed bug in sq_arraypop\r
+\r
+***2003-09-15 ***\r
+***version 0.3 alpha***\r
+-fixed a bug in array::insert()\r
+-optional Unicode core(define SQUNICODE or _UNICODE on Win32)\r
+-sq_compiler uses a new reader function SQLEXREADFUNC\r
+-the debug hook passes 'l' instead of 'line' for line callbacks\r
+ and 'c' instead of 'call' for call callbacks\r
+-new array.extend() bulit-in function\r
+-new API sq_clone()\r
+\r
+***2003-09-10 ***\r
+***version 0.2 pre-alpha***\r
+-new completely reentrant VM (sq_open and sq_close are now obsolete)\r
+-sq_newvm() has a new prototype\r
+-allocators are now global and linked in the VM\r
+-_newslot meta method added\r
+-rawset creates a slot if doesn't exists\r
+-the compiler error callback pass the vm handle(thanks Pierre Renaux)\r
+-sq_setforeignptr() sq_getforeingptr() are now public\r
+-sq_resume() now is possible to resume generators from C\r
+-sq_getlasterror() retrieve the last thrown error\r
+-improved docs\r
+\r
+***2003-09-06 ***\r
+***version 0.1 pre-alpha***\r
+first release\r
-~~~~~~~~
-Squirrel
-~~~~~~~~
-
-This directory contains the SQUIRREL programming language as found on
-http://www.squirrel-lang.org with some minor fixes to make it compile warning
-free on 64bit architectures.
-
-Squirrel Copyright:
-Copyright (c) 2003-2006 Alberto Demichelis
-
-This software is provided 'as-is', without any
-express or implied warranty. In no event will the
-authors be held liable for any damages arising from
-the use of this software.
-
-Permission is granted to anyone to use this software
-for any purpose, including commercial applications,
-and to alter it and redistribute it freely, subject
-to the following restrictions:
-
- 1. The origin of this software must not be
- misrepresented; you must not claim that
- you wrote the original software. If you
- use this software in a product, an
- acknowledgment in the product
- documentation would be appreciated but is
- not required.
-
- 2. Altered source versions must be plainly
- marked as such, and must not be
- misrepresented as being the original
- software.
-
- 3. This notice may not be removed or
- altered from any source distribution.
------------------------------------------------------
-END OF COPYRIGHT
-
-
-~~~~~~~~~~~~~~~~~~~~~~~~
-Squirrel Remote Debugger
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-The subdirectory sqdbg contains the sqdbg library by Alberto Demichelis.
-
-SQDBG License:
-
-This software is provided 'as-is', without any express or implied warranty. In
-no event will the authors be held liable for any damages arising from the use
-of this software.
-
-Permission is granted to anyone to use this software for any purpose, including
-commercial applications, and to alter it and redistribute it freely, subject to
-the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim
-that you wrote the original software. If you use this software in a product, an
-acknowledgment in the product documentation would be appreciated but is not
-required.
-
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source distribution.
-
+The programming language SQUIRREL 2.1.2 stable\r
+\r
+--------------------------------------------------\r
+The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and\r
+Linux(Slackware 9.0 on Intel x86, Fedora Core 4 on AMD x64).\r
+\r
+Has been tested with the following compilers:\r
+ MS Visual C++ 6.0,7.0,7.1 and 8.0 (32 and 64bits)\r
+ MinGW gcc 3.2 (mingw special 20020817-1)\r
+ Cygnus gcc 3.2\r
+ Linux gcc 3.2.3\r
+ Linux gcc 4.0.0 (x86 64bits)\r
+ \r
+\r
+Feedback and suggestions are appreciated \r
+project page - http://www.squirrel-lang.org\r
+community forums - http://www.squirrel-lang.org/Forums\r
+wiki - http://wiki.squirrel-lang.org\r
+author - alberto@ademichelis.com\r
+\r
+END OF README\r
+\r
#endif
#endif /*_SQSTDBLOB_H_*/
+
#define SQSTD_STREAM_TYPE_TAG 0x80000000
struct SQStream {
+
+ // [SuperTux] Added virtual destructor to avoid compiler warnings
virtual ~SQStream() { };
+
virtual SQInteger Read(void *buffer, SQInteger size) = 0;
virtual SQInteger Write(void *buffer, SQInteger size) = 0;
virtual SQInteger Flush() = 0;
#endif
#endif /*_SQSTDIO_H_*/
+
extern "C" {
#endif
-//#define SQRex_True 1
-//#define SQRex_False 0
-
typedef unsigned int SQRexBool;
typedef struct SQRex SQRex;
/*
-Copyright (c) 2003-2006 Alberto Demichelis
+Copyright (c) 2003-2007 Alberto Demichelis
-This software is provided 'as-is', without any
-express or implied warranty. In no event will the
-authors be held liable for any damages arising from
+This software is provided 'as-is', without any
+express or implied warranty. In no event will the
+authors be held liable for any damages arising from
the use of this software.
-Permission is granted to anyone to use this software
-for any purpose, including commercial applications,
-and to alter it and redistribute it freely, subject
+Permission is granted to anyone to use this software
+for any purpose, including commercial applications,
+and to alter it and redistribute it freely, subject
to the following restrictions:
- 1. The origin of this software must not be
- misrepresented; you must not claim that
- you wrote the original software. If you
- use this software in a product, an
- acknowledgment in the product
- documentation would be appreciated but is
+ 1. The origin of this software must not be
+ misrepresented; you must not claim that
+ you wrote the original software. If you
+ use this software in a product, an
+ acknowledgment in the product
+ documentation would be appreciated but is
not required.
- 2. Altered source versions must be plainly
- marked as such, and must not be
- misrepresented as being the original
+ 2. Altered source versions must be plainly
+ marked as such, and must not be
+ misrepresented as being the original
software.
- 3. This notice may not be removed or
+ 3. This notice may not be removed or
altered from any source distribution.
*/
typedef unsigned long SQUnsignedInteger;
typedef unsigned long SQHash; /*should be the same size of a pointer*/
#endif
-typedef int SQInt32;
-#else
+typedef int SQInt32;
+#else
typedef int SQInteger;
typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/
typedef unsigned int SQUnsignedInteger;
#endif
#ifdef SQUNICODE
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8
+
#if defined(wchar_t) //this is if the compiler considers wchar_t as native type
#define wchar_t unsigned short
#endif
+
+#else
+typedef unsigned short wchar_t;
+#endif
+
typedef wchar_t SQChar;
#define _SC(a) L##a
#define scstrcmp wcscmp
#define MAX_CHAR 0xFF
#endif
-#define SQUIRREL_VERSION _SC("Squirrel 2.1 stable")
-#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2006 Alberto Demichelis")
+#define SQUIRREL_VERSION _SC("Squirrel 2.1.2 stable")
+#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2007 Alberto Demichelis")
#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
#define SQ_VMSTATE_IDLE 0
typedef struct tagSQObject
{
- SQObjectValue _unVal;
SQObjectType _type;
+ SQObjectValue _unVal;
}SQObject;
typedef struct tagSQStackInfos{
SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
-/*SQUIRREL_API SQRESULT sq_createslot(HSQUIRRELVM v,SQInteger idx);*/
-SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
+SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
-SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
-SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
+SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
/*calls*/
SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
SQFloat f;
const SQChar *s;
SQInteger level=1; //1 is to skip this function that is level 0
- const SQChar *name=0;
+ const SQChar *name=0;
SQInteger seq=0;
pf(v,_SC("\nCALLSTACK\n"));
while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
pf(v,_SC("[%s] INSTANCE\n"),name);
break;
case OT_WEAKREF:
- pf(v,_SC("[%s] INSTANCE\n"),name);
+ pf(v,_SC("[%s] WEAKREF\n"),name);
break;
case OT_BOOL:{
sq_getinteger(v,-1,&i);
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);
- sq_remove(v,-2);
return blob->GetBuf();
}
}
{
return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
}
+
return false;
}
void Close() {
- if(_handle && _owns) {
+ if(_handle && _owns) {
sqstd_fclose(_handle);
_handle = NULL;
_owns = false;
if(c >= 0x80) {
SQInteger tmp;
SQInteger codelen = utf8_lengths[c>>4];
- if(codelen == 0)
+ if(codelen == 0)
return 0;
//"invalid UTF-8 stream";
tmp = c&byte_masks[codelen];
//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"));
+ 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("Unrecognozed ecoding"));
+ if(uc != 0xBF) {
+ sqstd_fclose(file);
+ return sq_throwerror(v,_SC("Unrecognozed ecoding"));
}
func = _io_file_lexfeed_UTF8;
break;//UTF-8 ;
{
SQInteger n;
sq_getinteger(v,2,&n);
- sq_pushinteger(v,(SQInteger)abs((int)n));
- return 1;
+ sq_pushinteger(v,(SQInteger)abs((int)n));
+ return 1;
}
SINGLE_ARG_FUNC(sqrt)
#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 SQREX_SYMBOL_ANY_CHAR '.'
-#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+'
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*'
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?'
-#define SQREX_SYMBOL_BRANCH '|'
-#define SQREX_SYMBOL_END_OF_STRING '$'
-#define SQREX_SYMBOL_BEGINNING_OF_STRING '^'
-#define SQREX_SYMBOL_ESCAPE_CHAR '\\'
+#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 SQREX_SYMBOL_ANY_CHAR ('.')
+#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
+#define SQREX_SYMBOL_BRANCH ('|')
+#define SQREX_SYMBOL_END_OF_STRING ('$')
+#define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
+#define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
typedef int SQRexNodeType;
exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
}
exp->_nodes[exp->_nsize++] = n;
- return (SQInteger)exp->_nsize - 1;
+ SQInteger newid = exp->_nsize - 1;
+ return (SQInteger)newid;
}
static void sqstd_rex_error(SQRex *exp,const SQChar *error)
}
static void sqstd_rex_expect(SQRex *exp, SQInteger n){
- if((*exp->_p) != n)
+ if((*exp->_p) != n)
sqstd_rex_error(exp, _SC("expected paren"));
exp->_p++;
}
-/*static SQBool sqstd_rex_ischar(SQChar c)
-{
- switch(c) {
- case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE:
- case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE:
- case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING:
- case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}':
- return SQFalse;
- }
- return SQTrue;
-}*/
-
static SQChar sqstd_rex_escapechar(SQRex *exp)
{
if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
{
+ SQChar t;
if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
exp->_p++;
switch(*exp->_p) {
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':
+ 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':
{
- SQChar t = *exp->_p;
- exp->_p++;
+ t = *exp->_p; exp->_p++;
return sqstd_rex_charclass(exp,t);
}
- case 'b':
+ case 'b':
case 'B':
if(!isclass) {
SQInteger node = sqstd_rex_newnode(exp,OP_WB);
exp->_nodes[node].left = *exp->_p;
- exp->_p++;
+ exp->_p++;
return node;
} //else default
- default: return sqstd_rex_newnode(exp,(*exp->_p++));
+ default:
+ t = *exp->_p; exp->_p++;
+ return sqstd_rex_newnode(exp,t);
}
}
else if(!scisprint(*exp->_p)) {
-
+
sqstd_rex_error(exp,_SC("letter expected"));
}
- return sqstd_rex_newnode(exp,*exp->_p++);
+ t = *exp->_p; exp->_p++;
+ return sqstd_rex_newnode(exp,t);
}
static SQInteger sqstd_rex_class(SQRex *exp)
{
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){
+ 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(first>*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;
- exp->_nodes[r].right = sqstd_rex_escapechar(exp);
+ SQInteger t = sqstd_rex_escapechar(exp);
+ exp->_nodes[r].right = t;
exp->_nodes[chain].next = r;
chain = r;
first = -1;
static SQInteger sqstd_rex_element(SQRex *exp)
{
- SQInteger ret;
+ SQInteger ret = -1;
switch(*exp->_p)
{
case '(': {
}
else
expr = sqstd_rex_newnode(exp,OP_EXPR);
- exp->_nodes[expr].left = sqstd_rex_list(exp);
+ SQInteger newn = sqstd_rex_list(exp);
+ exp->_nodes[expr].left = newn;
ret = expr;
sqstd_rex_expect(exp,')');
- }
- break;
+ }
+ break;
case '[':
exp->_p++;
ret = sqstd_rex_class(exp);
ret = sqstd_rex_charnode(exp,SQFalse);
break;
}
- /* scope block */
- {
- SQInteger op;
- unsigned short p0 = 0, p1 = 0;
- switch(*exp->_p){
- case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end;
- case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end;
- case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end;
- case '{':{
+
+
+ SQInteger op;
+ 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++;
- goto __end;
- case ',':
- exp->_p++;
- p1 = 0xFFFF;
- if(isdigit(*exp->_p)){
- p1 = (unsigned short)sqstd_rex_parsenumber(exp);
- }
- sqstd_rex_expect(exp,'}');
- goto __end;
- default:
- sqstd_rex_error(exp,_SC(", or } expected"));
+ case '}':
+ p1 = p0; exp->_p++;
+ break;
+ case ',':
+ exp->_p++;
+ p1 = 0xFFFF;
+ if(isdigit(*exp->_p)){
+ p1 = (unsigned short)sqstd_rex_parsenumber(exp);
}
- }
- __end: {
- SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
- op = OP_GREEDY;
- exp->_nodes[nnode].left = ret;
- exp->_nodes[nnode].right = ((p0)<<16)|p1;
- ret = nnode;
+ sqstd_rex_expect(exp,'}');
+ break;
+ default:
+ sqstd_rex_error(exp,_SC(", or } expected"));
}
- }
+ /*******************************/
+ isgreedy = SQTrue;
+ break;
+
}
- 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')
- exp->_nodes[ret].next = sqstd_rex_element(exp);
+ if(isgreedy) {
+ SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
+ op = 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;
+ }
+
return ret;
}
else ret = e;
if(*exp->_p == SQREX_SYMBOL_BRANCH) {
- SQInteger temp;
+ SQInteger temp,tright;
exp->_p++;
temp = sqstd_rex_newnode(exp,OP_OR);
exp->_nodes[temp].left = ret;
- exp->_nodes[temp].right = sqstd_rex_list(exp);
+ tright = sqstd_rex_list(exp);
+ exp->_nodes[temp].right = tright;
ret = temp;
}
return ret;
static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
{
-
+
SQRexNodeType type = node->type;
switch(type) {
case OP_GREEDY: {
}
}
}
-
+
if(s >= exp->_eol)
break;
}
exp->_matches[capture].begin = cur;
exp->_currsubexp++;
}
-
+
do {
SQRexNode *subnext = NULL;
if(n->next != -1) {
}
} while((n->next != -1) && (n = &exp->_nodes[n->next]));
- if(capture != -1)
+ 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)))
exp->_error = error;
exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
- exp->_nodes[exp->_first].left=sqstd_rex_list(exp);
+ 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
*subexp = exp->_matches[n];
return SQTrue;
}
+
case 'f': {
float f;
sq_getfloat(v, 2, &tf);
- f = tf;
+ f = (float)tf;
self->Write(&f, sizeof(float));
}
break;
}
sq_createslot(v,-3);
sq_pop(v,1);
-
+
i = 0;
while(globals[i].name!=0)
{
width = 0;
if (src[n] == '.') {
n++;
-
+
wc = 0;
while (scisdigit(src[n])) {
swidth[wc] = src[n];
}
else if(format[n+1] == '%') { //handles %%
dest[i++] = '%';
- n += 2;
+ n += 2;
}
else {
n++;
SQFloat tf;
switch(format[n]) {
case 's':
- if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
+ 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 'c':case 'o': case 'u': case 'x': case 'X':
- if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
+ 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)))
+ 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';
#define SETUP_REX(v) \
SQRex *self = NULL; \
- sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
+ sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)
{
#define sq_aux_paramscheck(v,count) \
{ \
if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
-}
+}
SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)
{
SQSharedState *ss;
SQVM *v;
ss=_ss(friendvm);
-
+
v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
new (v) SQVM(ss);
-
+
if(v->Init(friendvm, initialstacksize)) {
friendvm->Push(v);
return v;
{
if(v->_suspended)
return SQ_VMSTATE_SUSPENDED;
- else {
- if(v->_callsstack.size() != 0) return SQ_VMSTATE_RUNNING;
+ else {
+ if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;
else return SQ_VMSTATE_IDLE;
}
}
void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
{
if(!ISREFCOUNTED(type(*po))) return;
+#ifdef NO_GARBAGE_COLLECTOR
+ __AddRef(po->_type,po->_unVal);
+#else
_ss(v)->_refs_table.AddRef(*po);
+#endif
}
SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
{
if(!ISREFCOUNTED(type(*po))) return SQTrue;
+#ifdef NO_GARBAGE_COLLECTOR
+ __Release(po->_type,po->_unVal);
+ return SQFalse; //the ret val doesn't work(and cannot be fixed)
+#else
return _ss(v)->_refs_table.Release(*po);
+#endif
}
-const SQChar *sq_objtostring(HSQOBJECT *o)
+const SQChar *sq_objtostring(HSQOBJECT *o)
{
if(sq_type(*o) == OT_STRING) {
return _stringval(*o);
return NULL;
}
-SQInteger sq_objtointeger(HSQOBJECT *o)
+SQInteger sq_objtointeger(HSQOBJECT *o)
{
if(sq_isnumeric(*o)) {
return tointeger(*o);
return 0;
}
-SQFloat sq_objtofloat(HSQOBJECT *o)
+SQFloat sq_objtofloat(HSQOBJECT *o)
{
if(sq_isnumeric(*o)) {
return tofloat(*o);
return 0;
}
-SQBool sq_objtobool(HSQOBJECT *o)
+SQBool sq_objtobool(HSQOBJECT *o)
{
if(sq_isbool(*o)) {
return _integer(*o);
void sq_newtable(HSQUIRRELVM v)
{
- v->Push(SQTable::Create(_ss(v), 0));
+ v->Push(SQTable::Create(_ss(v), 0));
}
void sq_newarray(HSQUIRRELVM v,SQInteger size)
{
- v->Push(SQArray::Create(_ss(v), size));
+ v->Push(SQArray::Create(_ss(v), size));
}
SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)
}
SQClass *newclass = SQClass::Create(_ss(v), baseclass);
if(baseclass) v->Pop();
- v->Push(newclass);
+ v->Push(newclass);
return SQ_OK;
}
return SQ_OK;
}
+
SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)
{
sq_aux_paramscheck(v, 1);
nc->_outervalues.push_back(v->Top());
v->Pop();
}
- v->Push(SQObjectPtr(nc));
+ v->Push(SQObjectPtr(nc));
}
SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)
if(sq_isclosure(o)) {
SQClosure *c = _closure(o);
SQFunctionProto *proto = _funcproto(c->_function);
- *nparams = (SQUnsignedInteger)proto->_parameters.size();
+ *nparams = (SQUnsignedInteger)proto->_nparameters;
*nfreevars = (SQUnsignedInteger)c->_outervalues.size();
return SQ_OK;
}
return SQ_OK;
}
+SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)
+{
+ SQObject &o=stack_get(v,idx);
+ switch(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;
+}
+
void sq_pushroottable(HSQUIRRELVM v)
{
v->Push(v->_roottable);
return type(stack_get(v, idx));
}
+
void sq_tostring(HSQUIRRELVM v,SQInteger idx)
{
SQObjectPtr &o = stack_get(v, idx);
return SQ_OK;
}
+SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
+{
+ SQObjectPtr &o = stack_get(v,idx);
+ if(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(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag)
{
SQObjectPtr &o = stack_get(v,idx);
return SQ_OK;
}
-/*SQRESULT sq_createslot(HSQUIRRELVM v, SQInteger idx)
-{
- sq_aux_paramscheck(v, 3);
- SQObjectPtr &self = stack_get(v, idx);
- if(type(self) == OT_TABLE || type(self) == OT_CLASS) {
- SQObjectPtr &key = v->GetUp(-2);
- if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
- v->NewSlot(self, key, v->GetUp(-1));
- v->Pop(2);
- }
- return SQ_OK;
-}*/
-
SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
{
sq_aux_paramscheck(v, 2);
break;
default:
v->Pop(2);
- return sq_throwerror(v, _SC("rawset works only on array/table/calsse and instance"));
+ 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);
switch(type(self)){
case OT_TABLE:
- if(!_table(self)->_delegate)break;
- v->Push(SQObjectPtr(_table(self)->_delegate));
- break;
case OT_USERDATA:
- if(!_userdata(self)->_delegate)break;
- v->Push(SQObjectPtr(_userdata(self)->_delegate));
+ if(!_delegable(self)->_delegate){
+ v->Push(_null_);
+ break;
+ }
+ v->Push(SQObjectPtr(_delegable(self)->_delegate));
break;
default: return sq_throwerror(v,_SC("wrong type")); break;
}
return SQ_OK;
-
+
}
SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)
default:
v->Pop(1);
return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));
- }
+ }
v->Pop(1);
return sq_throwerror(v,_SC("the index doesn't exist"));
}
const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
{
- SQUnsignedInteger cstksize=v->_callsstack.size();
+ SQUnsignedInteger cstksize=v->_callsstacksize;
SQUnsignedInteger lvl=(cstksize-level)-1;
SQInteger stackbase=v->_stackbase;
if(lvl<cstksize){
return NULL;
SQClosure *c=_closure(ci._closure);
SQFunctionProto *func=_funcproto(c->_function);
- return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions._vals)-1);
+ if(func->_noutervalues > (SQInteger)idx) {
+ v->Push(c->_outervalues[idx]);
+ return _stringval(func->_outervalues[idx]._name);
+ }
+ idx -= func->_noutervalues;
+ return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);
}
return NULL;
}
SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
{
- SQObjectPtr func=SQFunctionProto::Create();
- SQObjectPtr closure=SQClosure::Create(_ss(v),_funcproto(func));
+ 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(!_closure(closure)->Load(v,up,r))
+ if(!SQClosure::Load(v,up,r,closure))
return SQ_ERROR;
v->Push(closure);
return SQ_OK;
if(type(key) == OT_NULL) {
attrs = _class(*o)->_attributes;
v->Pop();
- v->Push(attrs);
+ v->Push(attrs);
return SQ_OK;
}
else if(_class(*o)->GetAttributes(key,attrs)) {
if(type(o) == OT_GENERATOR) {
return sq_throwerror(v,_SC("cannot iterate a generator"));
}
- bool finished;
- if(!v->FOREACH_OP(o,realkey,val,refpos,0,finished))
+ int faketojump;
+ if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
return SQ_ERROR;
- if(!finished) {
+ if(faketojump != 666) {
v->Push(realkey);
v->Push(val);
return SQ_OK;
{
return SQ_REALLOC(p,oldsize,newsize);
}
+
void sq_free(void *p,SQUnsignedInteger size)
{
SQ_FREE(p,size);
}
}
+static SQInteger base_dummy(HSQUIRRELVM v)
+{
+ return 0;
+}
+
#ifndef NO_GARBAGE_COLLECTOR
static SQInteger base_collectgarbage(HSQUIRRELVM v)
{
{_SC("suspend"),base_suspend,-1, NULL},
{_SC("array"),base_array,-2, _SC(".n")},
{_SC("type"),base_type,2, NULL},
+ {_SC("dummy"),base_dummy,0,NULL},
#ifndef NO_GARBAGE_COLLECTOR
{_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},
#endif
sq_createslot(v,-3);
i++;
}
+ sq_pushstring(v,_SC("_version_"),-1);
+ sq_pushstring(v,SQUIRREL_VERSION,-1);
+ sq_createslot(v,-3);
sq_pushstring(v,_SC("_charsize_"),-1);
sq_pushinteger(v,sizeof(SQChar));
sq_createslot(v,-3);
return 1;
}
+static SQInteger obj_clear(HSQUIRRELVM v)
+{
+ return sq_clear(v,-1);
+}
+
+
static SQInteger number_delegate_tochar(HSQUIRRELVM v)
{
SQObject &o=stack_get(v,1);
return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
}
+
SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
{_SC("len"),default_delegate_len,1, _SC("t")},
{_SC("rawget"),table_rawget,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(".")},
{0,0}
};
i = l; j = r+1;
while(1){
SQInteger ret;
- do {
- ++i;
+ do {
+ ++i;
if(i > r) break;
if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))
return false;
} while( ret <= 0);
do {
- --j;
+ --j;
if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))
return false;
}
if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
if(sidx<0)sidx=_array(o)->Size()+sidx;
if(eidx<0)eidx=_array(o)->Size()+eidx;
- if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes"));
+ if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));
SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
SQObjectPtr t;
SQInteger count=0;
}
v->Push(arr);
return 1;
-
+
}
SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
{_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(".")},
{0,0}
};
SQTable *res = SQTable::Create(_ss(v),4);
if(type(o) == OT_CLOSURE) {
SQFunctionProto *f = _funcproto(_closure(o)->_function);
- SQInteger nparams = f->_parameters.size() + (f->_varparams?1:0);
+ SQInteger nparams = f->_nparameters + (f->_varparams?1:0);
SQObjectPtr params = SQArray::Create(_ss(v),nparams);
- for(SQUnsignedInteger n = 0; n<f->_parameters.size(); n++) {
+ for(SQInteger n = 0; n<f->_nparameters; n++) {
_array(params)->Set((SQInteger)n,f->_parameters[n]);
}
if(f->_varparams) {
res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);
res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);
}
- else { //OT_NATIVECLOSURE
+ 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);
break;
}
}
-
+
SQInteger wakeupret = sq_gettop(v)>1?1:0;
if(wakeupret) {
sq_move(thread,v,2);
{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
{0,0}
};
+
+
_base = base;
_typetag = 0;
_hook = NULL;
+ _udsize = 0;
_metamethods.resize(MT_LAST); //size it to max size
if(_base) {
_defaultvalues.copy(base->_defaultvalues);
ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
}
-void SQClass::Finalize() {
+void SQClass::Finalize() {
_attributes = _null_;
_defaultvalues.resize(0);
_methods.resize(0);
bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
{
SQObjectPtr temp;
- if(_locked)
+ if(_locked)
return false; //the class already has an instance so cannot be modified
if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
{
}
if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) {
SQInteger mmidx;
- if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
+ if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
(mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
_metamethods[mmidx] = val;
- }
+ }
else {
if(type(temp) == OT_NULL) {
- SQClassMemeber m;
+ SQClassMember m;
m.val = val;
_members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
_methods.push_back(m);
}
return true;
}
- SQClassMemeber m;
+ SQClassMember m;
m.val = val;
_members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
_defaultvalues.push_back(m);
{
_memsize = memsize;
_class = c;
- _nvalues = _class->_defaultvalues.size();
- for(SQUnsignedInteger n = 0; n < _nvalues; n++) {
+ 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 = i->_class;
- _nvalues = _class->_defaultvalues.size();
- for(SQUnsignedInteger n = 0; n < _nvalues; n++) {
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+ for(SQUnsignedInteger n = 0; n < nvalues; n++) {
new (&_values[n]) SQObjectPtr(i->_values[n]);
}
Init(ss);
}
-void SQInstance::Finalize()
+void SQInstance::Finalize()
{
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();
__ObjRelease(_class);
- for(SQUnsignedInteger i = 0; i < _nvalues; i++) {
+ for(SQUnsignedInteger i = 0; i < nvalues; i++) {
_values[i] = _null_;
}
}
SQInstance::~SQInstance()
{
REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
- Finalize();
+ if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
}
bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res)
struct SQInstance;
-struct SQClassMemeber {
- SQClassMemeber(){}
- SQClassMemeber(const SQClassMemeber &o) {
+struct SQClassMember {
+ SQClassMember(){}
+ SQClassMember(const SQClassMember &o) {
val = o.val;
attrs = o.attrs;
}
SQObjectPtr attrs;
};
-typedef sqvector<SQClassMemeber> SQClassMemeberVec;
+typedef sqvector<SQClassMember> SQClassMemberVec;
#define MEMBER_TYPE_METHOD 0x01000000
#define MEMBER_TYPE_FIELD 0x02000000
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() {
+ void Release() {
if (_hook) { _hook(_typetag,0);}
- sq_delete(this, SQClass);
+ sq_delete(this, SQClass);
}
void Finalize();
#ifndef NO_GARBAGE_COLLECTOR
SQInstance *CreateInstance();
SQTable *_members;
SQClass *_base;
- SQClassMemeberVec _defaultvalues;
- SQClassMemeberVec _methods;
+ SQClassMemberVec _defaultvalues;
+ SQClassMemberVec _methods;
SQObjectPtrVec _metamethods;
SQObjectPtr _attributes;
SQUserPointer _typetag;
SQRELEASEHOOK _hook;
bool _locked;
+ SQInteger _udsize;
};
#define calcinstancesize(_theclass_) \
- (sizeof(SQInstance)+(sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))
-struct SQInstance : public SQDelegable
+ (_theclass_->_udsize + 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);
public:
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();
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();
-#ifndef NO_GARBAGE_COLLECTOR
+#ifndef NO_GARBAGE_COLLECTOR
void Mark(SQCollectable ** );
#endif
bool InstanceOf(SQClass *trg);
SQClass *_class;
SQUserPointer _userpointer;
SQRELEASEHOOK _hook;
- SQUnsignedInteger _nvalues;
SQInteger _memsize;
SQObjectPtr _values[1];
};
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
}
bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
- bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);
+ static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
#ifndef NO_GARBAGE_COLLECTOR
void Mark(SQCollectable **chain);
void Finalize(){_outervalues.resize(0); }
SQObjectPtrVec _outervalues;
};
//////////////////////////////////////////////
-struct SQGenerator : public CHAINABLE_OBJ
+struct SQGenerator : public CHAINABLE_OBJ
{
enum SQGeneratorState{eRunning,eSuspended,eDead};
private:
ret->_env = _env;
ret->_name = _name;
ret->_outervalues.copy(_outervalues);
- ret->_typecheck = _typecheck;
+ ret->_typecheck.copy(_typecheck);
ret->_nparamscheck = _nparamscheck;
return ret;
}
void Mark(SQCollectable **chain);
void Finalize(){_outervalues.resize(0);}
#endif
+ SQInteger _nparamscheck;
+ SQIntVec _typecheck;
+ SQObjectPtrVec _outervalues;
SQObjectPtr _env;
SQFUNCTION _function;
SQObjectPtr _name;
- SQObjectPtrVec _outervalues;
- SQIntVec _typecheck;
- SQInteger _nparamscheck;
};
}
SQObject Expect(SQInteger tok)
{
-
+
if(_token != tok) {
if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
//ret = SQString::Create(_ss(_vm),_SC("constructor"));
SQOpcode op;
if(_token == TK_RETURN) {
op = _OP_RETURN;
-
+
}
else {
op = _OP_YIELD;
_fs->_returnexp = retexp;
_fs->AddInstruction(op, 1, _fs->PopTarget());
}
- else{
+ else{
if(op == _OP_RETURN && _fs->_traps > 0)
_fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
_fs->_returnexp = -1;
- _fs->AddInstruction(op, 0xFF);
+ _fs->AddInstruction(op, 0xFF);
}
break;}
case TK_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_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;
- default: return;
+ default: return;
}
}
void ShiftExp()
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;
+ default: return;
}
}
void PlusExp()
default: return;
}
}
-
+
void MultExp()
{
PrefixedExpr();
switch(_token) {
case _SC('.'): {
pos = -1;
- Lex();
+ Lex();
if(_token == TK_PARENT) {
Lex();
if(!NeedGet())
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(']'));
+ Lex(); Expression(); Expect(_SC(']'));
pos = -1;
if(NeedGet()) Emit2ArgsOP(_OP_GET);
_exst._deref = DEREF_FIELD;
break;
case TK_MINUSMINUS:
case TK_PLUSPLUS:
- if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
+ if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
SQInteger tok = _token; Lex();
if(pos < 0)
Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);
SQInteger src = _fs->PopTarget();
_fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);
}
-
+
}
return;
- break;
- case _SC('('):
+ break;
+ case _SC('('):
{
if(_exst._deref != DEREF_NO_DEREF) {
if(pos<0) {
case TK_STRING_LITERAL: {
//SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
- Lex();
+ Lex();
}
break;
case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;
//checks if is a free variable
if((pos = _fs->GetOuterVariable(id)) != -1) {
_exst._deref = _fs->PushTarget();
- _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
+ _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
_exst._freevar = true;
} else {
_fs->PushTarget(0);
_token = _SC('.'); //hack
return -1;
break;
- case TK_NULL:
+ case TK_NULL:
_fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
Lex();
break;
}
break;
case TK_FLOAT:
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
+ if(sizeof(SQFloat) == sizeof(SQInt32)) {
+ _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));
+ }
+ else {
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
+ }
Lex();
break;
case TK_TRUE: case TK_FALSE:
SQInteger apos = _fs->GetCurrentPos(),key = 0;
Lex();
while(_token != _SC(']')) {
- Expression();
+ Expression();
if(_token == _SC(',')) Lex();
SQInteger val = _fs->PopTarget();
SQInteger array = _fs->TopTarget();
case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;
case TK_RESUME : UnaryOP(_OP_RESUME); break;
case TK_CLONE : UnaryOP(_OP_CLONE); break;
- case TK_MINUSMINUS :
+ case TK_MINUSMINUS :
case TK_PLUSPLUS :PrefixIncDec(_token); break;
case TK_DELETE : DeleteExpr(); break;
case TK_DELEGATE : DelegateExpr(); break;
}
return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));
}
-
+
void FunctionCallArgs()
{
SQInteger nargs = 1;//this
while(_token != _SC(')')) {
Expression(true);
MoveIfCurrentTargetIsLocal();
- nargs++;
- if(_token == _SC(',')){
- Lex();
+ nargs++;
+ if(_token == _SC(',')){
+ Lex();
if(_token == ')') Error(_SC("expression expected, found ')'"));
}
}
void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')
{
SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
-
+
while(_token != terminator) {
bool hasattrs = false;
bool isstatic = false;
}
_fs->PopTarget();
_fs->PushLocalVariable(varname);
-
+
} while(_token == _SC(','));
}
void IfStatement()
_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
SQInteger jnepos = _fs->GetCurrentPos();
SQInteger stacksize = _fs->GetStackSize();
-
+
Statement();
//
if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
-
+
CleanStack(stacksize);
SQInteger endifblock = _fs->GetCurrentPos();
if(_token == TK_ELSE){
SQInteger stacksize = _fs->GetStackSize();
jmppos = _fs->GetCurrentPos();
Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
-
+
BEGIN_BREAKBLE_BLOCK();
_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
jzpos = _fs->GetCurrentPos();
stacksize = _fs->GetStackSize();
-
+
Statement();
-
+
CleanStack(stacksize);
_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
_fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
-
+
END_BREAKBLE_BLOCK(jmppos);
}
void DoWhileStatement()
_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
CleanStack(stacksize);
-
+
END_BREAKBLE_BLOCK(continuetrg);
}
void ForEachStatement()
idxname = _fs->CreateString(_SC("@INDEX@"));
}
Expect(TK_IN);
-
+
//save the stack size
SQInteger stacksize = _fs->GetStackSize();
//put the table in the stack(evaluate the table expression)
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);
//restore the local variable stack(remove index,val and ref idx)
CleanStack(stacksize);
END_BREAKBLE_BLOCK(foreachpos - 1);
__nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
_fs->_breaktargets.pop_back();
-
+
}
void FunctionStatement()
{
_fs->PushTarget(0);
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
-
+
while(_token == TK_DOUBLE_COLON) {
Lex();
id = Expect(TK_IDENTIFIER);
}
void CreateFunction(SQObject &name)
{
-
+
SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
funcstate->_name = name;
SQObject paramname;
}
Lex();
}
-
+
SQFuncState *currchunk = _fs;
_fs = funcstate;
Statement();
SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
{
- SQInteger cssize = v->_callsstack.size();
+ SQInteger cssize = v->_callsstacksize;
if (cssize > level) {
memset(si, 0, sizeof(SQStackInfos));
SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type)
{
SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);
- SQInteger found = 0;
+ SQInteger found = 0;
for(SQInteger i=0; i<16; i++)
{
SQInteger mask = 0x00000001 << i;
struct SQOuterVar
{
-
+
SQOuterVar(){}
SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
{
typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
typedef sqvector<SQLineInfo> SQLineInfoVec;
+#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf) (sizeof(SQFunctionProto) \
+ +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
+ +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \
+ +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
+ +(localinf*sizeof(SQLocalVarInfo)))
+
+#define _CONSTRUCT_VECTOR(type,size,ptr) { \
+ for(SQInteger n = 0; n < size; n++) { \
+ new (&ptr[n]) type(); \
+ } \
+}
+
+#define _DESTRUCT_VECTOR(type,size,ptr) { \
+ for(SQInteger nl = 0; nl < size; nl++) { \
+ ptr[nl].~type(); \
+ } \
+}
struct SQFunctionProto : public SQRefCounted
{
private:
_stacksize=0;
_bgenerator=false;}
public:
- static SQFunctionProto *Create()
+ static SQFunctionProto *Create(SQInteger ninstructions,
+ SQInteger nliterals,SQInteger nparameters,
+ SQInteger nfunctions,SQInteger noutervalues,
+ SQInteger nlineinfos,SQInteger nlocalvarinfos)
{
SQFunctionProto *f;
- sq_new(f,SQFunctionProto);
+ //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));
+ new (f) SQFunctionProto;
+ 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;
+
+ _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(){ sq_delete(this,SQFunctionProto);}
+ 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);
+ 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);
- bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);
- SQObjectPtrVec _literals;
- SQObjectPtrVec _functions;
- SQObjectPtrVec _parameters;
- SQOuterVarVec _outervalues;
- SQInstructionVec _instructions;
+ static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
+
SQObjectPtr _sourcename;
SQObjectPtr _name;
- SQLocalVarInfoVec _localvarinfos;
- SQLineInfoVec _lineinfos;
SQInteger _stacksize;
bool _bgenerator;
bool _varparams;
+
+ SQInteger _nlocalvarinfos;
+ SQLocalVarInfo *_localvarinfos;
+
+ SQInteger _nlineinfos;
+ SQLineInfo *_lineinfos;
+
+ SQInteger _nliterals;
+ SQObjectPtr *_literals;
+
+ SQInteger _nparameters;
+ SQObjectPtr *_parameters;
+
+ SQInteger _nfunctions;
+ SQObjectPtr *_functions;
+
+ SQInteger _noutervalues;
+ SQOuterVar *_outervalues;
+
+ SQInteger _ninstructions;
+ SQInstruction _instructions[1];
};
#endif //_SQFUNCTION_H_
{_SC("_OP_LINE")},
{_SC("_OP_LOAD")},
{_SC("_OP_LOADINT")},
+ {_SC("_OP_LOADFLOAT")},
{_SC("_OP_DLOAD")},
{_SC("_OP_TAILCALL")},
{_SC("_OP_CALL")},
{_SC("_OP_YIELD")},
{_SC("_OP_RESUME")},
{_SC("_OP_FOREACH")},
+ {_SC("_OP_POSTFOREACH")},
{_SC("_OP_DELEGATE")},
{_SC("_OP_CLONE")},
{_SC("_OP_TYPEOF")},
void SQFuncState::Dump(SQFunctionProto *func)
{
SQUnsignedInteger n=0,i;
+ SQInteger si;
scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
scprintf(_SC("--------------------------------------------------------------------\n"));
n++;
}
scprintf(_SC("-----LOCALS\n"));
- for(i=0;i<func->_localvarinfos.size();i++){
- SQLocalVarInfo lvi=func->_localvarinfos[i];
+ for(si=0;si<func->_nlocalvarinfos;si++){
+ SQLocalVarInfo lvi=func->_localvarinfos[si];
scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
n++;
}
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 "),n,g_InstrDesc[inst.op].name,inst._arg0);
if(lidx >= 0xFFFFFFFF)
SQInteger refidx;
SQObjectPtr val,key,refo;
while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
- refo = refidx;
+ refo = refidx;
}
DumpLiteral(key);
}
SQInteger refidx;
SQObjectPtr val,key,refo;
while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
- refo = refidx;
+ refo = refidx;
}
DumpLiteral(key);
scprintf(_SC("\n"));
}
}
}
+ else if(inst.op==_OP_LOADFLOAT) {
+ scprintf(_SC("[%03d] %15s %d %f %d %d\n"),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
+ else
scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
n++;
}
lvi._pos=_vlocals.size();
_vlocals.push_back(lvi);
if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
-
+
return pos;
}
void SQFuncState::AddOuterValue(const SQObject &name)
{
SQInteger pos=-1;
- if(_parent) {
+ if(_parent) {
pos = _parent->GetLocalVariable(name);
if(pos == -1) {
pos = _parent->GetOuterVariable(name);
_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
return;
}
- }
+ }
_outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
}
pi._arg2 = (unsigned char)i._arg1;
pi.op = _OP_GETK;
pi._arg0 = i._arg0;
-
+
return;
}
break;
return;
}
break;
- case _OP_MOVE:
+ case _OP_MOVE:
if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
{
pi._arg0 = i._arg0;
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;
SQFunctionProto *SQFuncState::BuildProto()
{
- SQFunctionProto *f=SQFunctionProto::Create();
- f->_literals.resize(_nliterals);
+ SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
+ _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
+ _lineinfos.size(),_localvarinfos.size());
+
SQObjectPtr refidx,key,val;
SQInteger idx;
refidx=idx;
}
- f->_functions.resize(_functions.size());
- f->_functions.copy(_functions);
- f->_parameters.resize(_parameters.size());
- f->_parameters.copy(_parameters);
- f->_outervalues.resize(_outervalues.size());
- f->_outervalues.copy(_outervalues);
- f->_instructions.resize(_instructions.size());
- f->_instructions.copy(_instructions);
- f->_localvarinfos.resize(_localvarinfos.size());
- f->_localvarinfos.copy(_localvarinfos);
- f->_lineinfos.resize(_lineinfos.size());
- f->_lineinfos.copy(_lineinfos);
+ 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 no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];
+ for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
+
+ memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
+
f->_varparams = _varparams;
return f;
#endif //_SQFUNCSTATE_H_
+
case _SC('*'):
NEXT();
LexBlockComment();
- continue;
+ continue;
case _SC('/'):
do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
continue;
case _SC('>'):
NEXT();
if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
- else if(CUR_CHAR == _SC('>')){
- NEXT();
+ else if(CUR_CHAR == _SC('>')){
+ NEXT();
if(CUR_CHAR == _SC('>')){
NEXT();
RETURN_TOKEN(TK_USHIFTR);
else { NEXT(); RETURN_TOKEN(TK_NE); }
case _SC('@'): {
SQInteger stype;
- NEXT();
+ NEXT();
if(CUR_CHAR != _SC('"'))
Error(_SC("string expected"));
if((stype=ReadString('"',true))!=-1) {
SQInteger c = CUR_CHAR;
if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
NEXT();
- RETURN_TOKEN(c);
+ RETURN_TOKEN(c);
}
RETURN_TOKEN(0);
}
}
}
- return 0;
+ return 0;
}
-
+
SQInteger SQLexer::GetIDType(SQChar *s)
{
SQObjectPtr t;
case SQUIRREL_EOB:
Error(_SC("unfinished string"));
return -1;
- case _SC('\n'):
- if(!verbatim) Error(_SC("newline in a constant"));
- APPEND_CHAR(CUR_CHAR); NEXT();
+ 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();
+ APPEND_CHAR('\\'); NEXT();
}
else {
NEXT();
switch(CUR_CHAR) {
case _SC('x'): NEXT(); {
- if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
+ if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
const SQInteger maxdigits = 4;
SQChar temp[maxdigits+1];
SQInteger n = 0;
}
if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));
}
-
+
APPEND_CHAR(CUR_CHAR);
NEXT();
}
}
}
-void SQWeakRef::Release() {
- if(ISREFCOUNTED(_obj._type)) {
+void SQWeakRef::Release() {
+ if(ISREFCOUNTED(_obj._type)) {
_obj._unVal.pRefCounted->_weakref = NULL;
- }
+ }
sq_delete(this,SQWeakRef);
}
SQInteger prevtop=v->_top-v->_stackbase;
PUSH_CALLINFO(v,_ci);
SQInteger oldstackbase=v->_stackbase;
- v->_stackbase=v->_top;
- v->ci->_target=target;
- v->ci->_generator=SQObjectPtr(this);
- v->ci->_vargs.size = _vargsstack.size();
-
+ v->_stackbase = v->_top;
+ v->ci->_target = (SQInt32)target;
+ v->ci->_generator = SQObjectPtr(this);
+ v->ci->_vargs.size = (unsigned short)_vargsstack.size();
+
for(SQInteger i=0;i<_ci._etraps;i++) {
v->_etraps.push_back(_etraps.top());
_etraps.pop_back();
v->_vargsstack.push_back(_vargsstack.back());
_vargsstack.pop_back();
}
- v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;
+ v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);
v->_top=v->_stackbase+size;
- v->ci->_prevtop=prevtop;
- v->ci->_prevstkbase=v->_stackbase-oldstackbase;
+ v->ci->_prevtop = (SQInt32)prevtop;
+ v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);
_state=eRunning;
return true;
}
const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
{
- SQUnsignedInteger nvars=_localvarinfos.size();
- const SQChar *res=NULL;
+ SQUnsignedInteger nvars=_nlocalvarinfos;
+ const SQChar *res=NULL;
if(nvars>=nseq){
for(SQUnsignedInteger i=0;i<nvars;i++){
if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
SQInteger SQFunctionProto::GetLine(SQInstruction *curr)
{
- SQInteger op = (SQInteger)(curr-_instructions._vals);
+ SQInteger op = (SQInteger)(curr-_instructions);
SQInteger line=_lineinfos[0]._line;
- for(SQUnsignedInteger i=1;i<_lineinfos.size();i++){
+ for(SQInteger i=1;i<_nlineinfos;i++){
if(_lineinfos[i]._op>=op)
return line;
line=_lineinfos[i]._line;
return line;
}
-//#define _ERROR_TRAP() error_trap:
#define _CHECK_IO(exp) { if(!exp)return false; }
bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)
{
return true;
}
-bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
+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(_funcproto(_function)->Load(v,up,read));
+ 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));
return true;
}
bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
{
- SQInteger i,nsize=_literals.size();
+ SQInteger i,nliterals = _nliterals,nparameters = _nparameters;
+ SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
+ SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
_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,&nsize,sizeof(nsize)));
- for(i=0;i<nsize;i++){
+ _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,&ninstructions,sizeof(ninstructions)));
+ _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ for(i=0;i<nliterals;i++){
_CHECK_IO(WriteObject(v,up,write,_literals[i]));
}
+
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- nsize=_parameters.size();
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
- for(i=0;i<nsize;i++){
+ for(i=0;i<nparameters;i++){
_CHECK_IO(WriteObject(v,up,write,_parameters[i]));
}
+
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- nsize=_outervalues.size();
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
- for(i=0;i<nsize;i++){
+ for(i=0;i<noutervalues;i++){
_CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
}
+
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- nsize=_localvarinfos.size();
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
- for(i=0;i<nsize;i++){
+ for(i=0;i<nlocalvarinfos;i++){
SQLocalVarInfo &lvi=_localvarinfos[i];
_CHECK_IO(WriteObject(v,up,write,lvi._name));
_CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));
_CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));
_CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));
}
+
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- nsize=_lineinfos.size();
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
- _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));
+ _CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
+
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- nsize=_instructions.size();
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
- _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));
+ _CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
+
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- nsize=_functions.size();
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
- for(i=0;i<nsize;i++){
+ for(i=0;i<nfunctions;i++){
_CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
}
_CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
return true;
}
-bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
+bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
{
- SQInteger i, nsize = _literals.size();
+ SQInteger i, nliterals,nparameters;
+ SQInteger noutervalues ,nlocalvarinfos ;
+ SQInteger nlineinfos,ninstructions ,nfunctions ;
+ 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(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, &nsize, sizeof(nsize)));
- for(i = 0;i < nsize; i++){
+ _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, &ninstructions, sizeof(ninstructions)));
+ _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
+
+ SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos);
+ 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));
+
+ for(i = 0;i < nliterals; i++){
_CHECK_IO(ReadObject(v, up, read, o));
- _literals.push_back(o);
+ f->_literals[i] = o;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
- for(i = 0; i < nsize; i++){
+
+ for(i = 0; i < nparameters; i++){
_CHECK_IO(ReadObject(v, up, read, o));
- _parameters.push_back(o);
+ f->_parameters[i] = o;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));
- for(i = 0; i < nsize; i++){
+
+ 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));
- _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));
+ f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));
- for(i = 0; i < nsize; i++){
+
+ 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)));
- _localvarinfos.push_back(lvi);
+ f->_localvarinfos[i] = lvi;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));
- _lineinfos.resize(nsize);
- _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));
+ _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, &nsize, sizeof(nsize)));
- _instructions.resize(nsize);
- _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));
+ _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, &nsize, sizeof(nsize)));
- for(i = 0; i < nsize; i++){
- o = SQFunctionProto::Create();
- _CHECK_IO(_funcproto(o)->Load(v, up, read));
- _functions.push_back(o);
+ 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, &_stacksize, sizeof(_stacksize)));
- _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));
- _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));
+ _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;
}
{
START_MARK()
_class->Mark(chain);
- for(SQUnsignedInteger i =0; i< _nvalues; i++) {
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+ for(SQUnsignedInteger i =0; i< nvalues; i++) {
SQSharedState::MarkObject(_values[i], chain);
}
END_MARK()
void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
#endif
+
#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \
{ \
unval.pRefCounted->_uiRef++; \
- }
+ }
#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \
{ \
}
inline void Null()
{
+ SQObjectType tOldType;
+ SQObjectValue unOldVal;
+ tOldType = _type;
+ unOldVal = _unVal;
+ _type = OT_NULL;
+ _unVal.pUserPointer = NULL;
+ __Release(tOldType,unOldVal);
+ }
+ inline SQObjectPtr& operator=(SQInteger i)
+ {
__Release(_type,_unVal);
- _type=OT_NULL;
- _unVal.pUserPointer=NULL;
+ _unVal.nInteger = i;
+ _type = OT_INTEGER;
+ return *this;
+ }
+ inline SQObjectPtr& operator=(SQFloat f)
+ {
+ __Release(_type,_unVal);
+ _unVal.fFloat = f;
+ _type = OT_FLOAT;
+ return *this;
}
inline SQObjectPtr& operator=(const SQObjectPtr& obj)
- {
+ {
SQObjectType tOldType;
SQObjectValue unOldVal;
tOldType=_type;
return *this;
}
inline SQObjectPtr& operator=(const SQObject& obj)
- {
+ {
SQObjectType tOldType;
SQObjectValue unOldVal;
tOldType=_type;
enum BitWiseOP {
BW_AND = 0,
- BW_OR = 2, //like ADD
+ BW_OR = 2,
BW_XOR = 3,
BW_SHIFTL = 4,
BW_SHIFTR = 5,
enum CmpOP {
CMP_G = 0,
- CMP_GE = 2, //like ADD
+ CMP_GE = 2,
CMP_L = 3,
CMP_LE = 4
};
enum SQOpcode
{
- _OP_LINE= 0x00,
+ _OP_LINE= 0x00,
_OP_LOAD= 0x01,
_OP_LOADINT= 0x02,
- _OP_DLOAD= 0x03,
- _OP_TAILCALL= 0x04,
- _OP_CALL= 0x05,
- _OP_PREPCALL= 0x06,
- _OP_PREPCALLK= 0x07,
- _OP_GETK= 0x08,
- _OP_MOVE= 0x09,
- _OP_NEWSLOT= 0x0A,
- _OP_DELETE= 0x0B,
- _OP_SET= 0x0C,
- _OP_GET= 0x0D,
- _OP_EQ= 0x0E,
- _OP_NE= 0x0F,
- _OP_ARITH= 0x10,
- _OP_BITW= 0x11,
- _OP_RETURN= 0x12,
- _OP_LOADNULLS= 0x13,
- _OP_LOADROOTTABLE= 0x14,
- _OP_LOADBOOL= 0x15,
- _OP_DMOVE= 0x16,
- _OP_JMP= 0x17,
- _OP_JNZ= 0x18,
- _OP_JZ= 0x19,
- _OP_LOADFREEVAR= 0x1A,
- _OP_VARGC= 0x1B,
- _OP_GETVARGV= 0x1C,
- _OP_NEWTABLE= 0x1D,
- _OP_NEWARRAY= 0x1E,
- _OP_APPENDARRAY= 0x1F,
- _OP_GETPARENT= 0x20,
- _OP_COMPARITH= 0x21,
- _OP_COMPARITHL= 0x22,
- _OP_INC= 0x23,
- _OP_INCL= 0x24,
- _OP_PINC= 0x25,
- _OP_PINCL= 0x26,
- _OP_CMP= 0x27,
- _OP_EXISTS= 0x28,
- _OP_INSTANCEOF= 0x29,
- _OP_AND= 0x2A,
- _OP_OR= 0x2B,
- _OP_NEG= 0x2C,
- _OP_NOT= 0x2D,
- _OP_BWNOT= 0x2E,
- _OP_CLOSURE= 0x2F,
- _OP_YIELD= 0x30,
- _OP_RESUME= 0x31,
- _OP_FOREACH= 0x32,
- _OP_DELEGATE= 0x33,
- _OP_CLONE= 0x34,
- _OP_TYPEOF= 0x35,
- _OP_PUSHTRAP= 0x36,
- _OP_POPTRAP= 0x37,
- _OP_THROW= 0x38,
- _OP_CLASS= 0x39,
- _OP_NEWSLOTA= 0x3A
-};
+ _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_ARITH= 0x11,
+ _OP_BITW= 0x12,
+ _OP_RETURN= 0x13,
+ _OP_LOADNULLS= 0x14,
+ _OP_LOADROOTTABLE= 0x15,
+ _OP_LOADBOOL= 0x16,
+ _OP_DMOVE= 0x17,
+ _OP_JMP= 0x18,
+ _OP_JNZ= 0x19,
+ _OP_JZ= 0x1A,
+ _OP_LOADFREEVAR= 0x1B,
+ _OP_VARGC= 0x1C,
+ _OP_GETVARGV= 0x1D,
+ _OP_NEWTABLE= 0x1E,
+ _OP_NEWARRAY= 0x1F,
+ _OP_APPENDARRAY= 0x20,
+ _OP_GETPARENT= 0x21,
+ _OP_COMPARITH= 0x22,
+ _OP_COMPARITHL= 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_DELEGATE= 0x35,
+ _OP_CLONE= 0x36,
+ _OP_TYPEOF= 0x37,
+ _OP_PUSHTRAP= 0x38,
+ _OP_POPTRAP= 0x39,
+ _OP_THROW= 0x3A,
+ _OP_CLASS= 0x3B,
+ _OP_NEWSLOTA= 0x3C,
+};
-struct SQInstructionDesc {
- const SQChar *name;
-};
+struct SQInstructionDesc {
+ const SQChar *name;
+};
-struct SQInstruction
+struct SQInstruction
{
SQInstruction(){};
SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0)
_arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1;
_arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;
}
-
-
+
+
SQInt32 _arg1;
unsigned char op;
unsigned char _arg0;
#if defined(_MSC_VER) && defined(_DEBUG)
#include <crtdbg.h>
-#endif
+#endif
#include <stdio.h>
#include <stdlib.h>
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;
return false;
}
i++;
- if(typemask[i] == '|') {
- i++;
+ if(typemask[i] == '|') {
+ i++;
if(typemask[i] == 0)
return false;
- continue;
+ continue;
}
res.push_back(mask);
mask = 0;
-
+
}
return true;
}
}
void SQSharedState::Init()
-{
+{
_scratchpad=NULL;
_scratchpadsize=0;
#ifndef NO_GARBAGE_COLLECTOR
_refs_table.Finalize();
_table(_registry)->Finalize();
_table(_metamethodsmap)->Finalize();
-// _refs_table = _null_;
_registry = _null_;
_metamethodsmap = _null_;
- while(!_systemstrings->empty()){
+ while(!_systemstrings->empty()) {
_systemstrings->back()=_null_;
_systemstrings->pop_back();
}
_class_default_delegate=_null_;
_instance_default_delegate=_null_;
_weakref_default_delegate=_null_;
-
+
#ifndef NO_GARBAGE_COLLECTOR
-
-
SQCollectable *t=_gc_chain;
SQCollectable *nx=NULL;
- while(t){
+ while(t) {
t->_uiRef++;
t->Finalize();
nx=t->_next;
- if(--t->_uiRef==0)
+ if(--t->_uiRef == 0)
t->Release();
t=nx;
}
_gc_chain->Release();
}
#endif
+
sq_delete(_types,SQObjectPtrVec);
sq_delete(_systemstrings,SQObjectPtrVec);
sq_delete(_metamethods,SQObjectPtrVec);
{
SQInteger n=0;
SQCollectable *tchain=NULL;
- SQVM *vms=_thread(_root_vm);
-
+ SQVM *vms = _thread(_root_vm);
+
vms->Mark(&tchain);
SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();
_refs_table.Mark(&tchain);
MarkObject(_class_default_delegate,&tchain);
MarkObject(_instance_default_delegate,&tchain);
MarkObject(_weakref_default_delegate,&tchain);
-
- SQCollectable *t=_gc_chain;
- SQCollectable *nx=NULL;
- while(t){
+
+ SQCollectable *t = _gc_chain;
+ SQCollectable *nx = NULL;
+ while(t) {
t->_uiRef++;
t->Finalize();
- nx=t->_next;
- if(--t->_uiRef==0)
+ nx = t->_next;
+ if(--t->_uiRef == 0)
t->Release();
- t=nx;
+ t = nx;
n++;
}
- t=tchain;
- while(t){
+ t = tchain;
+ while(t) {
t->UnMark();
- t=t->_next;
+ t = t->_next;
}
- _gc_chain=tchain;
+ _gc_chain = tchain;
SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();
assert(z == x);
return n;
#ifndef NO_GARBAGE_COLLECTOR
void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
{
- c->_prev=NULL;
- c->_next=*chain;
- if(*chain) (*chain)->_prev=c;
- *chain=c;
+ c->_prev = NULL;
+ c->_next = *chain;
+ if(*chain) (*chain)->_prev = c;
+ *chain = c;
}
void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
{
- if(c->_prev) c->_prev->_next=c->_next;
- else *chain=c->_next;
+ if(c->_prev) c->_prev->_next = c->_next;
+ else *chain = c->_next;
if(c->_next)
- c->_next->_prev=c->_prev;
- c->_next=NULL;
- c->_prev=NULL;
+ c->_next->_prev = c->_prev;
+ c->_next = NULL;
+ c->_prev = NULL;
}
#endif
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;
-
- }else if(_scratchpadsize>=(size<<5)){
- newsize=_scratchpadsize>>1;
- _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
- _scratchpadsize=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;
void RefTable::Finalize()
{
- RefNode *nodes = (RefNode *)&_buckets[_numofslots];
+ RefNode *nodes = _nodes;
for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
nodes->obj = _null_;
nodes++;
RefTable::~RefTable()
{
- SQ_FREE(_buckets,_buffersize);
+ SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
}
+
#ifndef NO_GARBAGE_COLLECTOR
void RefTable::Mark(SQCollectable **chain)
{
- RefNode *nodes = (RefNode *)&_buckets[_numofslots];
+ RefNode *nodes = (RefNode *)_nodes;
for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
if(type(nodes->obj) != OT_NULL) {
SQSharedState::MarkObject(nodes->obj,chain);
}
}
#endif
+
void RefTable::AddRef(SQObject &obj)
{
SQHash mainpos;
RefNode *ref = Get(obj,mainpos,&prev,false);
if(ref) {
if(--ref->refs == 0) {
- ref->obj = _null_;
+ SQObjectPtr o = ref->obj;
if(prev) {
prev->next = ref->next;
}
ref->next = _freelist;
_freelist = ref;
_slotused--;
+ ref->obj = _null_;
//<<FIXME>>test for shrink?
return SQTrue;
}
}
+ else {
+ assert(0);
+ }
return SQFalse;
}
void RefTable::Resize(SQUnsignedInteger size)
{
- RefNode **oldbuffer = _buckets;
- RefNode *oldnodes = (RefNode *)&_buckets[_numofslots];
+ RefNode **oldbucks = _buckets;
+ RefNode *t = _nodes;
SQUnsignedInteger oldnumofslots = _numofslots;
- SQUnsignedInteger oldbuffersize = _buffersize;
AllocNodes(size);
//rehash
+ SQUnsignedInteger nfound = 0;
for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
- if(type(oldnodes->obj) != OT_NULL) {
+ if(type(t->obj) != OT_NULL) {
//add back;
- assert(oldnodes->refs != 0);
- RefNode *nn = Add(::HashObj(oldnodes->obj)&(_numofslots-1),oldnodes->obj);
- nn->refs = oldnodes->refs;
- oldnodes->obj = _null_;
+ assert(t->refs != 0);
+ RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
+ nn->refs = t->refs;
+ t->obj = _null_;
+ nfound++;
}
- oldnodes++;
+ t++;
}
- SQ_FREE(oldbuffer,oldbuffersize);
+ assert(nfound == oldnumofslots);
+ SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
}
RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
}
if(ref == NULL && add) {
if(_numofslots == _slotused) {
+ assert(_freelist == 0);
Resize(_numofslots*2);
+ mainpos = ::HashObj(obj)&(_numofslots-1);
}
ref = Add(mainpos,obj);
}
void RefTable::AllocNodes(SQUnsignedInteger size)
{
RefNode **bucks;
- RefNode *firstnode;
- _buffersize = size * sizeof(RefNode *) + size * sizeof(RefNode);
- bucks = (RefNode **)SQ_MALLOC(_buffersize);
- firstnode = (RefNode *)&bucks[size];
- RefNode *temp = firstnode;
+ 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 = NULL;
- _freelist = firstnode;
+ _freelist = nodes;
+ _nodes = nodes;
_buckets = bucks;
_slotused = 0;
_numofslots = size;
StringTable::~StringTable()
{
SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
- _strings=NULL;
+ _strings = NULL;
}
void StringTable::AllocNodes(SQInteger size)
{
- _numofslots=size;
- //_slotused=0;
- _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
+ _numofslots = size;
+ _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
memset(_strings,0,sizeof(SQString*)*_numofslots);
}
SQString *s;
SQString *prev=NULL;
SQHash h = bs->_hash&(_numofslots - 1);
-
+
for (s = _strings[h]; s; ){
if(s == bs){
if(prev)
void AllocNodes(SQUnsignedInteger size);
SQUnsignedInteger _numofslots;
SQUnsignedInteger _slotused;
- SQUnsignedInteger _buffersize;
+ RefNode *_nodes;
RefNode *_freelist;
RefNode **_buckets;
};
SQChar* GetScratchPad(SQInteger size);
SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
#ifndef NO_GARBAGE_COLLECTOR
- SQInteger CollectGarbage(SQVM *vm);
+ SQInteger CollectGarbage(SQVM *vm);
static void MarkObject(SQObjectPtr &o,SQCollectable **chain);
#endif
SQObjectPtrVec *_metamethods;
static SQRegFunction _instance_default_delegate_funcz[];
SQObjectPtr _weakref_default_delegate;
static SQRegFunction _weakref_default_delegate_funcz[];
-
+
SQCOMPILERERROR _compilererrorhandler;
SQPRINTFUNCTION _printfunc;
bool _debuginfo;
#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 _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 _instance_ddel _table(_sharedstate->_instance_default_delegate)
-#define _weakref_ddel _table(_sharedstate->_weakref_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 _instance_ddel _table(_sharedstate->_instance_default_delegate)
+#define _weakref_ddel _table(_sharedstate->_weakref_default_delegate)
#ifdef SQUNICODE //rsl REAL STRING LEN
#define rsl(l) ((l)<<1)
void SQTable::Remove(const SQObjectPtr &key)
{
-
+
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
if (n) {
n->val = n->key = _null_;
if (type(old->key) != OT_NULL)
NewSlot(old->key,old->val);
}
- for(SQInteger k=0;k<oldsize;k++)
+ for(SQInteger k=0;k<oldsize;k++)
nold[k].~_HashNode();
SQ_FREE(nold,oldsize*sizeof(_HashNode));
}
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){
return false;
}
-void SQTable::Finalize()
+void SQTable::_ClearNodes()
{
for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }
- SetDelegate(NULL);
+}
+
+void SQTable::Finalize()
+{
+ _ClearNodes();
+ SetDelegate(NULL);
+}
+
+void SQTable::Clear()
+{
+ _ClearNodes();
+ _usednodes = 0;
+ Rehash(true);
}
}
}
-struct SQTable : public SQDelegable
+struct SQTable : public SQDelegable
{
private:
struct _HashNode
_HashNode *_nodes;
SQInteger _numofnodes;
SQInteger _usednodes;
-
+
///////////////////////////
void AllocNodes(SQInteger nSize);
void Rehash(bool force);
SQTable(SQSharedState *ss, SQInteger nInitialSize);
+ void _ClearNodes();
public:
static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
{
for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
}
-#ifndef NO_GARBAGE_COLLECTOR
+#ifndef NO_GARBAGE_COLLECTOR
void Mark(SQCollectable **chain);
#endif
inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
//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);
}
-
+
};
#endif //_SQTABLE_H_
this->~SQUserData();
SQ_FREE(this, sizeof(SQUserData) + tsize);
}
-
+
SQInteger _size;
SQRELEASEHOOK _hook;
SQUserPointer _typetag;
#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
-#define SQ_MALLOC(__size) sq_vm_malloc(__size);
-#define SQ_FREE(__ptr,__size) sq_vm_free(__ptr,__size);
-#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc(__ptr,__oldsize,__size);
+#define SQ_MALLOC(__size) sq_vm_malloc((__size));
+#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
+#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
//sqvector mini vector class, supports objects by value
template<typename T> class sqvector
#include "sqarray.h"
#include "sqclass.h"
-#define TOP() (_stack[_top-1])
+#define TOP() (_stack._vals[_top-1])
bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
{
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;
{
if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) {
+ SQInteger res, i1 = _integer(o1), i2 = _integer(o2);
switch(op) {
- case '+': trg = _integer(o1) + _integer(o2); break;
- case '-': trg = _integer(o1) - _integer(o2); break;
- case '/': if(_integer(o2) == 0) { Raise_Error(_SC("division by zero")); return false; }
- trg = _integer(o1) / _integer(o2);
+ case '+': res = i1 + i2; break;
+ case '-': res = i1 - i2; break;
+ case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
+ res = i1 / i2;
break;
- case '*': trg = _integer(o1) * _integer(o2); break;
- case '%': trg = _integer(o1) % _integer(o2); break;
+ case '*': res = i1 * i2; break;
+ case '%': res = i1 % i2; break;
+ default: res = 0xDEADBEEF;
}
+ trg = res;
}else{
+ SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
switch(op) {
- case '+': trg = tofloat(o1) + tofloat(o2); break;
- case '-': trg = tofloat(o1) - tofloat(o2); break;
- case '/': trg = tofloat(o1) / tofloat(o2); break;
- case '*': trg = tofloat(o1) * tofloat(o2); break;
- case '%': trg = SQFloat(fmod((double)tofloat(o1),(double)tofloat(o2))); break;
+ 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;
+ }
} else {
if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){
if(!StringCat(o1, o2, trg)) return false;
}
- else if(!ArithMetaMethod(op,o1,o2,trg)) {
- Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false;
+ else if(!ArithMetaMethod(op,o1,o2,trg)) {
+ Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false;
}
}
return true;
SQVM::~SQVM()
{
Finalize();
+ sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
}
bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
{
-
+
switch(type(o)) {
case OT_INTEGER:
trg = -_integer(o);
return false;
}
-#define _RET_SUCCEED(exp) { result = (exp); return true; }
+#define _RET_SUCCEED(exp) { result = (exp); return true; }
bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
{
if(type(o1)==type(o2)){
case OT_TABLE:
case OT_USERDATA:
case OT_INSTANCE:
- Push(o1);Push(o2);
- if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res);
- break;
- default: break; //shutup compiler
+ if(_delegable(o1)->_delegate) {
+ Push(o1);Push(o2);
+ if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break;
+ }
+ //continues through (no break needed)
+ default:
+ _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
}
if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }
_RET_SUCCEED(_integer(res));
-
+
}
else{
if(sq_isnumeric(o1) && sq_isnumeric(o2)){
- if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) {
+ if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) {
if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }
else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }
_RET_SUCCEED(1);
else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);}
else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);}
else { Raise_CompareError(o1,o2); return false; }
-
+
}
assert(0);
_RET_SUCCEED(0); //cannot happen
case CMP_GE: res = (r >= 0)?_true_:_false_; return true;
case CMP_L: res = (r < 0)?_true_:_false_; return true;
case CMP_LE: res = (r <= 0)?_true_:_false_; return true;
-
+
}
assert(0);
}
ToString(obj, b);
SQInteger l = _string(a)->_len , ol = _string(b)->_len;
SQChar *s = _sp(rsl(l + ol + 1));
- memcpy(s, _stringval(a), rsl(l));
+ memcpy(s, _stringval(a), rsl(l));
memcpy(s + l, _stringval(b), rsl(ol));
dest = SQString::Create(_ss(this), _spval, l + ol);
return true;
const SQChar *GetTypeName(const SQObjectPtr &obj1)
{
- return IdType2Name(type(obj1));
+ return IdType2Name(type(obj1));
}
void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
{
_stack.resize(stacksize);
- _callsstack.reserve(4);
+ //_callsstack.reserve(4);
+ _alloccallsstacksize = 4;
+ _callsstacksize = 0;
+ _callsstack = (CallInfo*)sq_malloc(_alloccallsstacksize*sizeof(CallInfo));
_stackbase = 0;
_top = 0;
- if(!friendvm)
+ if(!friendvm)
_roottable = SQTable::Create(_ss(this), 0);
else {
_roottable = friendvm->_roottable;
_errorhandler = friendvm->_errorhandler;
_debughook = friendvm->_debughook;
}
-
+
sq_base_register(this);
return true;
}
bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger nargs,SQInteger stackbase,bool tailcall)
{
SQFunctionProto *func = _funcproto(closure->_function);
-
- const SQInteger paramssize = func->_parameters.size();
+
+ const SQInteger paramssize = func->_nparameters;
const SQInteger newtop = stackbase + func->_stacksize;
-
-
+
+
if (paramssize != nargs) {
if(func->_varparams)
{
return false;
}
for(SQInteger n = 0; n < nargs - paramssize; n++) {
- _vargsstack.push_back(_stack[stackbase+paramssize+n]);
- _stack[stackbase+paramssize+n] = _null_;
+ _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]);
+ _stack._vals[stackbase+paramssize+n] = _null_;
}
}
else {
}
if(type(closure->_env) == OT_WEAKREF) {
- _stack[stackbase] = _weakref(closure->_env)->_obj;
+ _stack._vals[stackbase] = _weakref(closure->_env)->_obj;
}
if (!tailcall) {
CallInfo lc;
lc._etraps = 0;
- lc._prevstkbase = stackbase - _stackbase;
- lc._target = target;
- lc._prevtop = _top - _stackbase;
+ lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );
+ lc._target = (SQInt32) target;
+ lc._prevtop = (SQInt32) (_top - _stackbase);
lc._ncalls = 1;
lc._root = SQFalse;
PUSH_CALLINFO(this, lc);
}
else {
ci->_ncalls++;
- if(ci->_vargs.size) PopVarArgs(ci->_vargs);
}
- ci->_vargs.size = (nargs - paramssize);
- ci->_vargs.base = _vargsstack.size()-(ci->_vargs.size);
+ ci->_vargs.size = (SQInt32)(nargs - paramssize);
+ ci->_vargs.base = (SQInt32) (_vargsstack.size()-(ci->_vargs.size));
ci->_closure._unVal.pClosure = closure;
ci->_closure._type = OT_CLOSURE;
- ci->_iv = &func->_instructions;
- ci->_literals = &func->_literals;
+ ci->_literals = func->_literals;
+ ci->_ip = func->_instructions;
//grows the stack if needed
if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) {
_stack.resize(_stack.size() + (func->_stacksize<<1));
}
-
+
_top = newtop;
_stackbase = stackbase;
- ci->_ip = ci->_iv->_vals;
return true;
}
if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
for(SQInteger i=0;i<ci->_ncalls;i++)
CallDebugHook(_SC('r'));
-
+
SQBool broot = ci->_root;
SQInteger last_top = _top;
SQInteger target = ci->_target;
if(ci->_vargs.size) PopVarArgs(ci->_vargs);
POP_CALLINFO(this);
if (broot) {
- if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1];
+ if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1];
else retval = _null_;
}
else {
if(target != -1) { //-1 is when a class contructor ret value has to be ignored
if (_arg0 != MAX_FUNC_STACKSIZE)
- STK(target) = _stack[oldstackbase+_arg1];
+ STK(target) = _stack._vals[oldstackbase+_arg1];
else
STK(target) = _null_;
}
}
- while (last_top >= _top) _stack[last_top--].Null();
- assert(oldstackbase >= _stackbase);
+ while (last_top >= _top) _stack._vals[last_top--].Null();
+ assert(oldstackbase >= _stackbase);
return broot?true:false;
}
_vargsstack.pop_back();
}
-#define _FINISH(stoploop) {finished = stoploop; return true; }
-bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
-&o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished)
+#define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }
+bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
+&o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump)
{
SQInteger nrefidx;
switch(type(o1)) {
case OT_TABLE:
- if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(true);
- o4 = (SQInteger)nrefidx; _FINISH(false);
+ 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(true);
- o4 = (SQInteger) nrefidx; _FINISH(false);
+ 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(true);
- o4 = (SQInteger)nrefidx; _FINISH(false);
+ 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(true);
- o4 = (SQInteger)nrefidx; _FINISH(false);
+ 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) {
Push(o4);
if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){
o4 = o2 = itr;
- if(type(itr) == OT_NULL) _FINISH(true);
+ if(type(itr) == OT_NULL) _FINISH(exitpos);
if(!Get(o1, itr, o3, false,false)) {
Raise_Error(_SC("_nexti returned an invalid idx"));
return false;
}
- _FINISH(false);
+ _FINISH(1);
}
Raise_Error(_SC("_nexti failed"));
return false;
}
break;
case OT_GENERATOR:
- if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(true);
+ if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos);
if(_generator(o1)->_state == SQGenerator::eSuspended) {
SQInteger idx = 0;
if(type(o4) == OT_INTEGER) {
o2 = idx;
o4 = idx;
_generator(o1)->Resume(this, arg_2+1);
- _FINISH(false);
+ _FINISH(0);
}
- default:
+ default:
Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
}
return false; //cannot be hit(just to avoid warnings)
trg = o1;
return true;
}
-#define COND_LITERAL (arg3!=0?(*ci->_literals)[arg1]:STK(arg1))
+#define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} }
{
SQInteger nouters;
SQClosure *closure = SQClosure::Create(_ss(this), func);
- if((nouters = func->_outervalues.size())) {
+ if((nouters = func->_noutervalues)) {
closure->_outervalues.reserve(nouters);
for(SQInteger i = 0; i<nouters; i++) {
SQOuterVar &v = func->_outervalues[i];
SQInteger traps = 0;
//temp_reg vars for OP_CALL
SQInteger ct_target;
- bool ct_tailcall;
+ SQInteger ct_stackbase;
+ bool ct_tailcall;
switch(et) {
- case ET_CALL:
- if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) {
+ case ET_CALL:
+ if(!StartCall(_closure(closure), _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;
case ET_RESUME_VM:
traps = _suspended_traps;
ci->_root = _suspended_root;
+ ci->_vargs = _suspend_varargs;
_suspended = SQFalse;
break;
}
-
+
exception_restore:
//
{
if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
CallDebugHook(_SC('l'),arg1);
continue;
- case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue;
+ case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
case _OP_LOADINT: TARGET = (SQInteger)arg1; continue;
- case _OP_DLOAD: TARGET = (*ci->_literals)[arg1]; STK(arg2) = (*ci->_literals)[arg3];continue;
+ case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
+ case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
case _OP_TAILCALL:
temp_reg = STK(arg1);
- if (type(temp_reg) == OT_CLOSURE){
+ if (type(temp_reg) == OT_CLOSURE){
ct_tailcall = true;
if(ci->_vargs.size) PopVarArgs(ci->_vargs);
for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
ct_target = ci->_target;
+ ct_stackbase = _stackbase;
goto common_call;
}
case _OP_CALL: {
ct_tailcall = false;
ct_target = arg0;
temp_reg = STK(arg1);
+ ct_stackbase = _stackbase+arg2;
+
common_call:
SQInteger last_top = _top;
switch (type(temp_reg)) {
case OT_CLOSURE:{
- _GUARD(StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall));
+ _GUARD(StartCall(_closure(temp_reg), ct_target, arg3, ct_stackbase, ct_tailcall));
if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));
_GUARD(gen->Yield(this));
Return(1, ct_target, temp_reg);
+
+
+
+
STK(ct_target) = gen;
- while (last_top >= _top) _stack[last_top--].Null();
+ while (last_top >= _top) _stack._vals[last_top--].Null();
continue;
}
if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
CallDebugHook(_SC('c'));
}
- break;
+ continue;
case OT_NATIVECLOSURE: {
bool suspend;
- _GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend));
+ _GUARD(CallNative(_nativeclosure(temp_reg), arg3, ct_stackbase, temp_reg,suspend));
if(suspend){
_suspended = SQTrue;
_suspended_target = ct_target;
_suspended_root = ci->_root;
_suspended_traps = traps;
+ _suspend_varargs = ci->_vargs;
outres = temp_reg;
return true;
}
- if(ct_target != -1) { //skip return value for contructors
+ if(ct_target != -1) { //skip return value for constructors
STK(ct_target) = temp_reg;
}
}
- break;
+ continue;
case OT_CLASS:{
SQObjectPtr inst;
_GUARD(CreateClassInstance(_class(temp_reg),inst,temp_reg));
STK(ct_target) = inst;
- ct_target = -1; //fakes return value target so that is not overwritten by the contructor
+ ct_target = -1; //fakes return value target so that is not overwritten by the constructor
if(type(temp_reg) != OT_NULL) {
- _stack[_stackbase+arg2] = inst;
- goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the contructor)
+ _stack._vals[ct_stackbase] = inst;
+ goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor)
}
}
break;
}
continue;
case _OP_PREPCALL:
- if (!Get(STK(arg2), STK(arg1), temp_reg, false,true))
- { Raise_IdxError(STK(arg1)); SQ_THROW(); }
- goto common_prepcall;
case _OP_PREPCALLK:
- if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg,false,true)) {
- if(type(STK(arg2)) == OT_CLASS) { //hack?
- if(_class_ddel->Get((*ci->_literals)[arg1],temp_reg)) {
- STK(arg3) = STK(arg2);
+ {
+ SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
+ SQObjectPtr &o = STK(arg2);
+ if (!Get(o, key, temp_reg,false,true)) {
+ if(type(o) == OT_CLASS) { //hack?
+ if(_class_ddel->Get(key,temp_reg)) {
+ STK(arg3) = o;
TARGET = temp_reg;
continue;
}
}
- { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}
- }
-common_prepcall:
- if(type(STK(arg2)) == OT_CLASS) {
- STK(arg3) = STK(0); // this
- }
- else {
- STK(arg3) = STK(arg2);
+ { Raise_IdxError(key); SQ_THROW();}
}
+
+ STK(arg3) = type(o) == OT_CLASS?STK(0):o;
TARGET = temp_reg;
+ }
continue;
case _OP_GETK:
- if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg, false,true)) { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}
+ if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,true)) { Raise_IdxError(ci->_literals[arg1]); SQ_THROW();}
TARGET = temp_reg;
continue;
case _OP_MOVE: TARGET = STK(arg1); continue;
if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
TARGET = res?_true_:_false_;
}continue;
- case _OP_NE:{
+ case _OP_NE:{
bool res;
if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
TARGET = (!res)?_true_:_false_;
case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue;
case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue;
- case _OP_GETVARGV:
- if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); }
+ case _OP_GETVARGV:
+ if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); }
continue;
case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
case _OP_PINCL: {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, true,false)?_true_:_false_;continue;
- case _OP_INSTANCEOF:
+ case _OP_INSTANCEOF:
if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE)
{Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_;
continue;
- case _OP_AND:
+ case _OP_AND:
if(IsFalse(STK(arg2))) {
TARGET = STK(arg2);
ci->_ip += (sarg1);
outres = temp_reg;
return true;
}
-
+
}
continue;
case _OP_RESUME:
_GUARD(_generator(STK(arg1))->Resume(this, arg0));
traps += ci->_etraps;
continue;
- case _OP_FOREACH:{ bool finished;
- _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,finished));
- if(finished) ci->_ip += sarg1; }
+ 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(type(STK(arg0)) == OT_GENERATOR);
+ if(_generator(STK(arg0))->_state == SQGenerator::eDead)
+ ci->_ip += (sarg1 - 1);
continue;
case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue;
case _OP_CLONE:
{ Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();}
continue;
case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue;
- case _OP_PUSHTRAP:
- _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++;
+ case _OP_PUSHTRAP:{
+ SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions;
+ _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
ci->_etraps++;
+ }
continue;
- case _OP_POPTRAP:
+ 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_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
}
continue;
}
-
+
}
}
exception_trap:
ci->_ip = et._ip;
_top = et._stacksize;
_stackbase = et._stackbase;
- _stack[_stackbase+et._extarget] = currerror;
+ _stack._vals[_stackbase+et._extarget] = currerror;
_etraps.pop_back(); traps--; ci->_etraps--;
- while(last_top >= _top) _stack[last_top--].Null();
+ while(last_top >= _top) _stack._vals[last_top--].Null();
goto exception_restore;
}
//if is a native closure
PopVarArgs(ci->_vargs);
POP_CALLINFO(this);
n++;
- } while(_callsstack.size());
+ } while(_callsstacksize);
}
else {
//call the hook
PopVarArgs(ci->_vargs);
POP_CALLINFO(this);
if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;
- } while(_callsstack.size());
+ } while(_callsstacksize);
- while(last_top >= _top) _stack[last_top--].Null();
+ while(last_top >= _top) _stack._vals[last_top--].Null();
}
_lasterror = currerror;
return false;
Pop(nparams);
}
-bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend)
+bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend)
{
if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
SQInteger nparamscheck = nclosure->_nparamscheck;
SQInteger tcs;
if((tcs = nclosure->_typecheck.size())) {
for(SQInteger i = 0; i < nargs && i < tcs; i++)
- if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) {
- Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i]));
+ if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) {
+ Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i]));
return false;
}
}
SQInteger oldtop = _top;
SQInteger oldstackbase = _stackbase;
_top = stackbase + nargs;
- PUSH_CALLINFO(this, CallInfo());
- ci->_etraps = 0;
- ci->_closure._unVal.pNativeClosure = nclosure;
- ci->_closure._type = OT_NATIVECLOSURE;
- ci->_prevstkbase = stackbase - _stackbase;
- ci->_ncalls = 1;
+ CallInfo lci;
+ lci._etraps = 0;
+ lci._closure._unVal.pNativeClosure = nclosure;
+ lci._closure._type = OT_NATIVECLOSURE;
+ lci._prevstkbase = (SQInt32) (stackbase - _stackbase);
+ lci._ncalls = 1;
+ lci._prevtop = (SQInt32) (oldtop - oldstackbase);
+ PUSH_CALLINFO(this, lci);
_stackbase = stackbase;
//push free variables
SQInteger outers = nclosure->_outervalues.size();
_stack[stackbase] = _weakref(nclosure->_env)->_obj;
}
- ci->_prevtop = (oldtop - oldstackbase);
+
SQInteger ret = (nclosure->_function)(this);
_nnativecalls--;
suspend = false;
if( ret == SQ_SUSPEND_FLAG) suspend = true;
- else if (ret < 0) {
+ else if (ret < 0) {
_stackbase = oldstackbase;
_top = oldtop;
POP_CALLINFO(this);
Raise_Error(_lasterror);
return false;
}
-
+
if (ret != 0){ retval = TOP(); }
else { retval = _null_; }
_stackbase = oldstackbase;
bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw)
{
switch(type(self)){
- case OT_CLASS:
+ case OT_CLASS:
return _class(self)->Get(key,dest);
break;
case OT_TABLE:
//delegation
if(_delegable(self)->_delegate) {
if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false))
- return true;
+ return true;
if(raw)return false;
Push(self);Push(key);
if(CallMetaMethod(_delegable(self),MT_GET,2,dest))
return _instance_ddel->Get(key,dest);
}
return true;
- case OT_INTEGER:case OT_FLOAT:case OT_BOOL:
+ case OT_INTEGER:case OT_FLOAT:case OT_BOOL:
if(raw)return false;
return _number_ddel->Get(key,dest);
- case OT_GENERATOR:
+ case OT_GENERATOR:
if(raw)return false;
return _generator_ddel->Get(key,dest);
- case OT_CLOSURE: case OT_NATIVECLOSURE:
+ case OT_CLOSURE: case OT_NATIVECLOSURE:
if(raw)return false;
return _closure_ddel->Get(key,dest);
case OT_THREAD:
}
target = newobj;
return true;
- case OT_ARRAY:
+ case OT_ARRAY:
target = _array(self)->Clone();
return true;
default: return false;
}
}
if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
-
+
break;}
- case OT_CLASS:
+ 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"));
break;
case OT_NATIVECLOSURE:{
bool suspend;
- return CallNative(_nativeclosure(closure), nparams, stackbase, false, outres,suspend);
-
+ return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
+
}
break;
case OT_CLASS: {
SQInteger size=dumpall?_stack.size():_top;
SQInteger n=0;
scprintf(_SC("\n>>>>stack dump<<<<\n"));
- CallInfo &ci=_callsstack.back();
+ 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<size;i++){
- SQObjectPtr &obj=_stack[i];
+ SQObjectPtr &obj=_stack[i];
if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
scprintf(_SC("[%d]:"),n);
switch(type(obj)){
SQInteger _extarget;
};
-#define _INLINE
+#define _INLINE
#define STK(a) _stack._vals[_stackbase+(a)]
#define TARGET _stack._vals[_stackbase+arg0]
{
struct VarArgs {
VarArgs() { size = 0; base = 0; }
- SQInteger size;
- SQInteger base;
+ unsigned short size;
+ unsigned short base;
};
struct CallInfo{
CallInfo() { _generator._type = OT_NULL;}
- //CallInfo(const CallInfo& ci) { }
- SQInstructionVec *_iv;
- SQObjectPtrVec *_literals;
+ SQInstruction *_ip;
+ SQObjectPtr *_literals;
SQObject _closure;
SQObject _generator;
- SQInteger _etraps;
- SQInteger _prevstkbase;
- SQInteger _prevtop;
- SQInteger _target;
- SQInstruction *_ip;
- SQInteger _ncalls;
+ SQInt32 _etraps;
+ SQInt32 _prevstkbase;
+ SQInt32 _prevtop;
+ SQInt32 _target;
+ SQInt32 _ncalls;
SQBool _root;
VarArgs _vargs;
};
-
+
typedef sqvector<CallInfo> CallInfoVec;
public:
enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };
bool Init(SQVM *friendvm, SQInteger stacksize);
bool Execute(SQObjectPtr &func, SQInteger target, 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 stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);
+ bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend);
//starts a SQUIRREL 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);
void ToString(const SQObjectPtr &o,SQObjectPtr &res);
SQString *PrintObjVal(const SQObject &o);
-
+
void Raise_Error(const SQChar *s, ...);
void Raise_Error(SQObjectPtr &desc);
void Raise_IdxError(SQObject &o);
bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target);
//return true if the loop is finished
- bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished);
+ bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
_INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
void Mark(SQCollectable **chain);
#endif
void Finalize();
-
+ void GrowCallStack() {
+ SQInteger newsize = _alloccallsstacksize*2;
+ _callsstack = (CallInfo*)sq_realloc(_callsstack,_alloccallsstacksize*sizeof(CallInfo),newsize*sizeof(CallInfo));
+ _alloccallsstacksize = newsize;
+ }
void Release(){ sq_delete(this,SQVM); } //does nothing
////////////////////////////////////////////////////////////////////////////
//stack functions for the api
void Remove(SQInteger n);
bool IsFalse(SQObjectPtr &o);
-
+
void Pop();
void Pop(SQInteger n);
void Push(const SQObjectPtr &o);
SQObjectPtr _debughook;
SQObjectPtr temp_reg;
- CallInfoVec _callsstack;
+
+
+ CallInfo* _callsstack;
+ SQInteger _callsstacksize;
+ SQInteger _alloccallsstacksize;
+
ExceptionsTraps _etraps;
CallInfo *ci;
void *_foreignptr;
SQBool _suspended_root;
SQInteger _suspended_target;
SQInteger _suspended_traps;
+ VarArgs _suspend_varargs;
};
struct AutoDec{
#endif
#define PUSH_CALLINFO(v,nci){ \
- v->ci = &v->_callsstack.push_back(nci); \
+ if(v->_callsstacksize == v->_alloccallsstacksize) { \
+ v->GrowCallStack(); \
+ } \
+ v->ci = &v->_callsstack[v->_callsstacksize]; \
+ *(v->ci) = nci; \
+ v->_callsstacksize++; \
}
#define POP_CALLINFO(v){ \
- v->_callsstack.pop_back(); \
- if(v->_callsstack.size()) \
- v->ci = &v->_callsstack.back() ; \
+ v->_callsstacksize--; \
+ if(v->_callsstacksize) \
+ v->ci = &v->_callsstack[v->_callsstacksize-1] ; \
else \
v->ci = NULL; \
}