Update to Squirrel 3.0.6
authorTobias Markus <tobbi@mozilla-uk.org>
Tue, 12 Aug 2014 23:44:17 +0000 (01:44 +0200)
committerTobias Markus <tobbi@mozilla-uk.org>
Tue, 12 Aug 2014 23:44:17 +0000 (01:44 +0200)
53 files changed:
external/squirrel/COPYRIGHT [changed mode: 0755->0644]
external/squirrel/HISTORY [changed mode: 0755->0644]
external/squirrel/README [changed mode: 0755->0644]
external/squirrel/include/sqstdaux.h [changed mode: 0755->0644]
external/squirrel/include/sqstdblob.h [changed mode: 0755->0644]
external/squirrel/include/sqstdio.h [changed mode: 0755->0644]
external/squirrel/include/sqstdmath.h [changed mode: 0755->0644]
external/squirrel/include/sqstdstring.h [changed mode: 0755->0644]
external/squirrel/include/sqstdsystem.h [changed mode: 0755->0644]
external/squirrel/include/squirrel.h [changed mode: 0755->0644]
external/squirrel/sqdbg/serialize_state.inl [changed mode: 0644->0755]
external/squirrel/sqdbg/sqdbgserver.cpp [changed mode: 0644->0755]
external/squirrel/sqdbg/sqdbgserver.h [changed mode: 0644->0755]
external/squirrel/sqdbg/sqrdbg.cpp [changed mode: 0644->0755]
external/squirrel/sqdbg/sqrdbg.h [changed mode: 0644->0755]
external/squirrel/sqstdlib/sqstdaux.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdblob.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdblobimpl.h [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdio.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdmath.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdrex.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdstream.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdstream.h [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdstring.cpp [changed mode: 0755->0644]
external/squirrel/sqstdlib/sqstdsystem.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqapi.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqarray.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqbaselib.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqclass.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqclass.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqclosure.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqcompiler.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqcompiler.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqdebug.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqfuncproto.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqfuncstate.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqfuncstate.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqlexer.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqlexer.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqmem.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqobject.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqobject.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqopcodes.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqpcheader.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqstate.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqstate.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqstring.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqtable.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqtable.h [changed mode: 0755->0644]
external/squirrel/squirrel/squserdata.h [changed mode: 0755->0644]
external/squirrel/squirrel/squtils.h [changed mode: 0755->0644]
external/squirrel/squirrel/sqvm.cpp [changed mode: 0755->0644]
external/squirrel/squirrel/sqvm.h [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index 2a20755..8e0c12f
@@ -1,29 +1,21 @@
-Copyright (c) 2003-2011 Alberto Demichelis\r
+Copyright (c) 2003-2014 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
+Permission is hereby granted, free of charge, to any person obtaining a copy\r
+of this software and associated documentation files (the "Software"), to deal\r
+in the Software without restriction, including without limitation the rights\r
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+copies of the Software, and to permit persons to whom the Software is\r
+furnished to do so, subject to the following conditions:\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
+The above copyright notice and this permission notice shall be included in\r
+all copies or substantial portions of the Software.\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
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+THE SOFTWARE.\r
 -----------------------------------------------------\r
-END OF COPYRIGHT
\ No newline at end of file
+END OF COPYRIGHT\r
old mode 100755 (executable)
new mode 100644 (file)
index 31b8a8f..53c09bd
-***version 2.2.5 stable***\r
--sq_getsize() now returns userdatasize for classes and instances\r
--added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)\r
+***version 3.0.6 stable***\r
+-fixed compiler bug that can cause memory corruption, the bug was introduced in 3.0.5(thx Alex95)\r
+\r
+***2014-03-22             ***\r
+***version 3.0.5 stable***\r
+-fixed crash in compiler when trying to write 'base'\r
+-fixed bug in gc\r
+-fixed few bugs in the compiler\r
+\r
+***2012-11-10             ***\r
+***version 3.0.4 stable***\r
+-sq_deleteslot slot now pops the key in case of failure\r
+-fixed bug when _get metamethod throws null\r
+-fixed a bug in rstrip\r
+-added some error handling\r
+-minor bugfixes\r
+\r
+***2012-06-19             ***\r
+***version 3.0.3 stable***\r
+-improved error messages for _cmp(when a non integer value is returned) (thx Yexo)\r
+-added class.newmember() built in method (thx Nam)\r
+-added class.rawnewmember()  built in method (thx Nam)\r
+-added sq_rawnewmember() (thx Nam)\r
+-added sq_getversion()\r
+-added sq_typeof()\r
+-added sq_getclosurename()\r
+-added file.close() in stdlib\r
+-documented closure.getinfos() built-in method\r
+-fixed string iteration doesn't return negative numbers for characters > 127\r
+-fixed bug in tofloat() when converting a string with scientific notation without a decimal point (thx wr2)\r
+-fixed potential infinite loop in array.sort() when the _cmp function is inconsistent (thx Yexo)\r
+-fixed obscure bug in the compiler(thx yishin)\r
+-fixed some minor bug\r
+\r
+***2011-11-28             ***\r
+***version 3.0.2 stable***\r
+-added sq_gethash API\r
 -now array.sort() is implemented with heapsort\r
--added SQUIRREL_VERSION_NUMBER preprocessor definition\r
 -now floats in scientific notation also accept numbers with no '.' (eg. 1e+6 or 1e6)\r
--fixed some compiler warning\r
--fixed a minor compiler bug\r
--fixed some bugs when SQUSEDOUBLE is used in 32bits systems\r
+-fixed some warning\r
+-fixed some documentation\r
 -fixed bug in GC\r
 \r
-***2009-11-15          ***\r
-***version 2.2.4 stable***\r
--fixed bug in functions with default parameters\r
+***2011-09-08             ***\r
+***version 3.0.1 stable***\r
+-added # as alternative symbol for "line comment"(mostly useful for shell scripts)\r
+-added sq_throwobject() to throw an arbitrary object from the C API\r
+-added alignement flag for userdata types, SQ_ALIGNMENT (thx Shigemasa)\r
+-added rawset() and rawget() to class and instance default delegate\r
+-changed bytecode format now ensures matching integer size and float size\r
+-now inherited classes also inherit userdatasize\r
+-added SQUIRREL_VERSION_NUMBER in squirrel.h and _versionnumber_ global symbol\r
+-fixed sq_getmemberhandle\r
+-fixed sq_getrefcount\r
+-refactored some sqstdio code\r
+-refactored some clone code\r
+-refactored some stuff in the string lib\r
+-added -s and -fno-exceptions in GCC makefile(better performance when using GCC)\r
+\r
+***2011-03-13        ***\r
+***version 3.0 stable***\r
+-added sq_getcallee()\r
+-sq_getfreevariable() also works for native closures\r
+-minior optimizations\r
+-removed several warning when compiling with GCC 4.x\r
+-fixed some errors in the documentation\r
+-fixed bug when using SQUSEDOUBLE and 32bits intengers\r
+-fixed bug when invoking generators with closure.call() (thx huntercool)\r
+\r
+***2010-12-19                                          ***\r
+***version 3.0 release candidate 1(RC 1)***\r
+-improved metamethods error handling\r
+-added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)\r
+-added sq_getrefcount() to return number of refences from C++(thx G.Meyer)\r
+\r
+***2010-11-07        ***\r
+***version 3.0 beta 3***\r
+-license changed to "MIT license"\r
+-added sq_resurrectunreachable() and resurrectunreachable()\r
+-added callee() built in function, returns the current running closure\r
+-added thread.getstackinfos()\r
+-added sq_objtouserpointer()\r
+-added sq_newtableex()\r
+-various refactoring and optimizations\r
+-fixed several 64bits issues regarding integer to string conversions\r
+-fixed some bugs when SQUSEDOUBLE is used in 32bits systems\r
+\r
+***2010-08-18          ***\r
+***version 3.0 beta 2.1***\r
+-fixed bug in class constructor\r
+-fixed bug in compound arith\r
 \r
-***2009-06-30          ***\r
-***version 2.2.3 stable***\r
+***2010-08-12        ***\r
+***version 3.0 beta 2***\r
+-class methods can be added or replaced after the class as been instantiated\r
+-JSON compliant table syntax, this is currently an experimental feature (thx atai)\r
+-sq_getsize() now returns userdatasize for classes and instances\r
+-now setroottable() and setconsttable() return the previous value of the respective table\r
+-fixed bug in compound arith operators when used on a free variable (thx ellon)\r
+-fixed some x64 minor bugs\r
+-fixed minor bug in the compiler\r
+-refactored some VM internals\r
+-documented sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes\r
+\r
+***2009-11-15        ***\r
+***version 3.0 beta 1***\r
+-various refactoring and optimizations\r
+-fixed bug in free variables (thx mokehehe)\r
+-fixed bug in functions with default parameters (thx ara & Yexo)\r
+-fixed bug in exception handling\r
+-improved error propagation in _set and _get metamethods ( and 'throw null' for clean failure)\r
+-added sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes\r
+\r
+***2009-06-30         ***\r
+***version 3.0 alpha 2***\r
+-added real free variables(thx Paul Ruizendaal)\r
+-added refactored function call implementation and compiler(thx Paul Ruizendaal)\r
 -added sq_getfunctioninfo\r
 -added compile time flag SQUSEDOUBLE to use double precision floats\r
 -added global slot _floatsize_ int the base lib to recognize single precision and double precision builds\r
 -sq_wakeupvm can now resume the vm with an exception\r
 -added sqstd_format\r
+-now blobs can be cloned\r
 -generators can now be instantiated by calling sq_call() or closure.call()\r
--fixed a bug in sqstd_printcallstack(thx takayuki_h)\r
--fixed modulo by zero(thx jup)\r
--fixed negative enums and constants\r
--fixed generator crash bug if invoked as tail call (thx Mr.Accident)\r
--fixed some minor bug\r
-\r
-***2008-09-24          ***\r
-***version 2.2.2 stable***\r
--fixed some behaviour inconsistencies in thread.call() and thread.wakeup() (thx Mr.Accident)\r
--fixed coroutine error propagation\r
--fixed lingering return value from native function (thx Tom Leonard)\r
--fixed a bug if array.sort() is given a bad sort function (thx Tom Leonard)\r
--fixed some minor api bug\r
+-fixed debughook bug\r
+-fixed cooroutine error propagation\r
+\r
+***2008-07-23         ***\r
+***version 3.0 alpha 1***\r
+-first branch from 2.x source tree\r
+-added 'base' keyword\r
+-removed 'delegate' keyword\r
+-now compiled scripts are vararg functions\r
+-added setdelegate() and getdelegate() table builtin methods\r
+-added <=> 3 ways compare operator\r
+-added lambda expression @(a,b) a + b\r
+-added local function statement\r
+-added array built-in map(),reduce(),apply(),filter() and find()\r
+-generators hold only a weak reference of the enviroment object\r
+-removed 'vargv' and 'vargc' keywords\r
+-now var args are passed as an array called vargv(as a paramter)\r
+-removed 'parent' keyword\r
+-added class getbase() built in method\r
+-instanceof doesn't throw an exception if the left expression is not a class\r
+-lexical scoping for free variables(free variables are no longer in the second parameter list)\r
+-sq_setprintfunc accept error func\r
+-sq_geterrorfunc()\r
 -added sq_arrayremove() and sq_arrayinsert()\r
+-error() built in function(works like print but prints using the errorfunc)\r
+-added native debug hook\r
 \r
-***2008-05-16          ***\r
-***version 2.2.1 stable***\r
--fixed a tailcall bug\r
-\r
-***2008-02-17          ***\r
-***version 2.2 stable  ***\r
+***2008-02-17        ***\r
+***version 2.2 stable***\r
 -added _newslot metamethod in classes\r
 -added enums added constants\r
 -added sq_pushconsttable, sq_setconsttable\r
@@ -61,7 +170,7 @@ will terminate the iteration but will not be returned as foreach iteration
 -fixed sq_cmp() (thx jyuill)\r
 -fixed minor bugs\r
 \r
-***2006-08-21       ***\r
+***2006-08-21             ***\r
 ***version 2.1.1 stable***\r
 -vm refactoring\r
 -optimized internal function memory layout\r
@@ -180,7 +289,7 @@ will terminate the iteration but will not be returned as foreach iteration
 ***2004-11-01        ***\r
 ***version 1.0 stable***\r
 -fixed some minor bug\r
--improoved operator 'delete' performances\r
+-improved operator 'delete' performances\r
 -added scientific notation for float numbers( eg. 2.e16 or 2.e-2)\r
 \r
 ***2004-08-30        ***\r
@@ -284,7 +393,7 @@ will terminate the iteration but will not be returned as foreach iteration
 -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
+-improved 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
old mode 100755 (executable)
new mode 100644 (file)
index 2d1e000..803b26a
@@ -1,20 +1,21 @@
-The programming language SQUIRREL 2.2.5 stable\r
+The programming language SQUIRREL 3.0 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
+The project has been compiled and run on Windows(x86 and x64) and\r
+Linux(x86 and x64) and Solaris(x86 and 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
+       MS Visual C++ 6.0,7.0,7.1,8.0,9.0,10.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
+       Linux gcc 4.0.0 (x86 & 64bits)\r
+       Solaris 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
+community forums - http://forum.squirrel-lang.org\r
 wiki - http://wiki.squirrel-lang.org\r
 author - alberto@demichelis.net\r
 \r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 864b4f1..1174201
@@ -7,7 +7,6 @@
 #define SQSTD_STREAM_TYPE_TAG 0x80000000\r
 \r
 struct SQStream {\r
-       virtual ~SQStream() {}\r
        virtual SQInteger Read(void *buffer, SQInteger size) = 0;\r
        virtual SQInteger Write(void *buffer, SQInteger size) = 0;\r
        virtual SQInteger Flush() = 0;\r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index df1f7fe..d4fc8fb
@@ -1,32 +1,23 @@
 /*\r
-Copyright (c) 2003-2011 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
+Copyright (c) 2003-2014 Alberto Demichelis\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy\r
+of this software and associated documentation files (the "Software"), to deal\r
+in the Software without restriction, including without limitation the rights\r
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+copies of the Software, and to permit persons to whom the Software is\r
+furnished to do so, subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in\r
+all copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+THE SOFTWARE.\r
 */\r
 #ifndef _SQUIRREL_H_\r
 #define _SQUIRREL_H_\r
@@ -45,21 +36,23 @@ extern "C" {
 #endif\r
 #endif\r
 \r
-\r
 #ifdef _SQ64\r
+\r
 #ifdef _MSC_VER\r
 typedef __int64 SQInteger;\r
 typedef unsigned __int64 SQUnsignedInteger;\r
 typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/\r
 #else\r
-typedef long SQInteger;\r
-typedef unsigned long SQUnsignedInteger;\r
-typedef unsigned long SQHash; /*should be the same size of a pointer*/\r
+typedef long long SQInteger;\r
+typedef unsigned long long SQUnsignedInteger;\r
+typedef unsigned long long SQHash; /*should be the same size of a pointer*/\r
 #endif\r
 typedef int SQInt32; \r
+typedef unsigned int SQUnsignedInteger32;\r
 #else \r
 typedef int SQInteger;\r
 typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/\r
+typedef unsigned int SQUnsignedInteger32; /*must be 32 bits(also on 64bits processors)*/\r
 typedef unsigned int SQUnsignedInteger;\r
 typedef unsigned int SQHash; /*should be the same size of a pointer*/\r
 #endif\r
@@ -83,6 +76,14 @@ typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64
 #define SQ_OBJECT_RAWINIT()\r
 #endif\r
 \r
+#ifndef SQ_ALIGNMENT // SQ_ALIGNMENT shall be less than or equal to SQ_MALLOC alignments, and its value shall be power of 2.\r
+#if defined(SQUSEDOUBLE) || defined(_SQ64)\r
+#define SQ_ALIGNMENT 8\r
+#else\r
+#define SQ_ALIGNMENT 4\r
+#endif\r
+#endif\r
+\r
 typedef void* SQUserPointer;\r
 typedef SQUnsignedInteger SQBool;\r
 typedef SQInteger SQRESULT;\r
@@ -103,6 +104,7 @@ struct SQRefCounted;
 struct SQClass;\r
 struct SQInstance;\r
 struct SQDelegable;\r
+struct SQOuter;\r
 \r
 #ifdef _UNICODE\r
 #define SQUNICODE\r
@@ -111,7 +113,7 @@ struct SQDelegable;
 #ifdef SQUNICODE\r
 #if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8\r
 \r
-#if defined(wchar_t) //this is if the compiler considers wchar_t as native type\r
+#if !defined(_NATIVE_WCHAR_T_DEFINED) //this is if the compiler considers wchar_t as native type\r
 #define wchar_t unsigned short\r
 #endif\r
 \r
@@ -125,7 +127,11 @@ typedef wchar_t SQChar;
 #define scsprintf      swprintf\r
 #define scstrlen       wcslen\r
 #define scstrtod       wcstod\r
+#ifdef _SQ64\r
+#define scstrtol       _wcstoi64\r
+#else\r
 #define scstrtol       wcstol\r
+#endif\r
 #define scatoi         _wtoi\r
 #define scstrtoul      wcstoul\r
 #define scvsprintf     vswprintf\r
@@ -145,7 +151,15 @@ typedef char SQChar;
 #define scsprintf      sprintf\r
 #define scstrlen       strlen\r
 #define scstrtod       strtod\r
+#ifdef _SQ64\r
+#ifdef _MSC_VER\r
+#define scstrtol       _strtoi64\r
+#else\r
+#define scstrtol       strtoll\r
+#endif\r
+#else\r
 #define scstrtol       strtol\r
+#endif\r
 #define scatoi         atoi\r
 #define scstrtoul      strtoul\r
 #define scvsprintf     vsprintf\r
@@ -160,10 +174,17 @@ typedef char SQChar;
 #define MAX_CHAR 0xFF\r
 #endif\r
 \r
-#define SQUIRREL_VERSION       _SC("Squirrel 2.2.5 stable")\r
-#define SQUIRREL_COPYRIGHT     _SC("Copyright (C) 2003-2010 Alberto Demichelis")\r
+#ifdef _SQ64\r
+#define _PRINT_INT_PREC _SC("ll")\r
+#define _PRINT_INT_FMT _SC("%lld")\r
+#else\r
+#define _PRINT_INT_FMT _SC("%d")\r
+#endif\r
+\r
+#define SQUIRREL_VERSION       _SC("Squirrel 3.0.6 stable")\r
+#define SQUIRREL_COPYRIGHT     _SC("Copyright (C) 2003-2014 Alberto Demichelis")\r
 #define SQUIRREL_AUTHOR                _SC("Alberto Demichelis")\r
-#define SQUIRREL_VERSION_NUMBER        225\r
+#define SQUIRREL_VERSION_NUMBER        306\r
 \r
 #define SQ_VMSTATE_IDLE                        0\r
 #define SQ_VMSTATE_RUNNING             1\r
@@ -199,6 +220,7 @@ typedef char SQChar;
 #define _RT_CLASS                      0x00004000\r
 #define _RT_INSTANCE           0x00008000\r
 #define _RT_WEAKREF                    0x00010000\r
+#define _RT_OUTER                      0x00020000\r
 \r
 typedef enum tagSQObjectType{\r
        OT_NULL =                       (_RT_NULL|SQOBJECT_CANBEFALSE),\r
@@ -217,7 +239,8 @@ typedef enum tagSQObjectType{
        OT_FUNCPROTO =          (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only\r
        OT_CLASS =                      (_RT_CLASS|SQOBJECT_REF_COUNTED),\r
        OT_INSTANCE =           (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),\r
-       OT_WEAKREF =            (_RT_WEAKREF|SQOBJECT_REF_COUNTED)\r
+       OT_WEAKREF =            (_RT_WEAKREF|SQOBJECT_REF_COUNTED),\r
+       OT_OUTER =                      (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only\r
 }SQObjectType;\r
 \r
 #define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)\r
@@ -228,6 +251,7 @@ typedef union tagSQObjectValue
        struct SQTable *pTable;\r
        struct SQArray *pArray;\r
        struct SQClosure *pClosure;\r
+       struct SQOuter *pOuter;\r
        struct SQGenerator *pGenerator;\r
        struct SQNativeClosure *pNativeClosure;\r
        struct SQString *pString;\r
@@ -252,6 +276,11 @@ typedef struct tagSQObject
        SQObjectValue _unVal;\r
 }SQObject;\r
 \r
+typedef struct  tagSQMemberHandle{\r
+       SQBool _static;\r
+       SQInteger _index;\r
+}SQMemberHandle;\r
+\r
 typedef struct tagSQStackInfos{\r
        const SQChar* funcname;\r
        const SQChar* source;\r
@@ -260,11 +289,12 @@ typedef struct tagSQStackInfos{
 \r
 typedef struct SQVM* HSQUIRRELVM;\r
 typedef SQObject HSQOBJECT;\r
+typedef SQMemberHandle HSQMEMBERHANDLE;\r
 typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);\r
 typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);\r
 typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);\r
 typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);\r
-\r
+typedef void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/);\r
 typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);\r
 typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);\r
 \r
@@ -283,7 +313,6 @@ typedef struct tagSQFunctionInfo {
        const SQChar *source;\r
 }SQFunctionInfo;\r
 \r
-\r
 /*vm*/\r
 SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);\r
 SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);\r
@@ -291,11 +320,13 @@ SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
 SQUIRREL_API void sq_close(HSQUIRRELVM v);\r
 SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);\r
 SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);\r
+SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc);\r
 SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);\r
+SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v);\r
 SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);\r
 SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);\r
 SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v);\r
+SQUIRREL_API SQInteger sq_getversion();\r
 \r
 /*compiler*/\r
 SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);\r
@@ -311,13 +342,14 @@ SQUIRREL_API void sq_poptop(HSQUIRRELVM v);
 SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v);\r
 SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop);\r
-SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize);\r
+SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize);\r
 SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v);\r
 SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);\r
 \r
 /*object creation handling*/\r
 SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);\r
 SQUIRREL_API void sq_newtable(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity);\r
 SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);\r
 SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);\r
 SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);\r
@@ -329,10 +361,12 @@ SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b);
 SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);\r
 SQUIRREL_API void sq_pushnull(HSQUIRRELVM v);\r
 SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx);\r
 SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);\r
 SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);\r
 SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);\r
@@ -345,8 +379,9 @@ SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer ty
 SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);\r
 SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);\r
 SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);\r
-SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger idx,SQFunctionInfo *fi);\r
+SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi);\r
 SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);\r
+SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);\r
 SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);\r
 SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);\r
@@ -358,6 +393,9 @@ SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx);
 SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t);\r
+SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);\r
+SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);\r
+SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);\r
 \r
 /*object manipulation*/\r
 SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);\r
@@ -372,6 +410,8 @@ SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
 SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);\r
+SQUIRREL_API SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);\r
+SQUIRREL_API SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);\r
 SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);\r
 SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); \r
 SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); \r
@@ -390,8 +430,10 @@ SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
 SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);\r
 SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);\r
 SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);\r
+SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v);\r
 SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);\r
 SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);\r
+SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v);\r
 SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);\r
 SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);\r
 \r
@@ -400,15 +442,18 @@ SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);
 SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);\r
 SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);\r
 SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);\r
+SQUIRREL_API SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po);\r
 SQUIRREL_API void sq_resetobject(HSQOBJECT *po);\r
-SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o);\r
-SQUIRREL_API SQBool sq_objtobool(HSQOBJECT *o);\r
-SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o);\r
-SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o);\r
-SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag);\r
+SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o);\r
+SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o);\r
+SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o);\r
+SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o);\r
+SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o);\r
+SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag);\r
 \r
 /*GC*/\r
 SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v);\r
 \r
 /*serialization*/\r
 SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);\r
@@ -422,6 +467,7 @@ SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size);
 /*debug*/\r
 SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);\r
 SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook);\r
 \r
 /*UTILITY MACRO*/\r
 #define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)\r
old mode 100644 (file)
new mode 100755 (executable)
index 347ee63..2c69bae
-static const SQChar serialize_state_nut[] = {
-0x74, 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x6c, 0x6f, 
-0x63, 0x61, 0x6c, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 
-0x3d, 0x7b, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x3d, 0x30, 0x2c, 0x72, 0x65, 
-0x66, 0x73, 0x3d, 0x7b, 0x7d, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 
-0x6d, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 
-0x3c, 0x2d, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x74, 0x61, 0x62, 
-0x6c, 0x65, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 
-0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x5d, 
-0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 
-0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 
-0x75, 0x6c, 0x6c, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x69, 0x6e, 0x73, 
-0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 
-0x6c, 0x6c, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x77, 0x65, 0x61, 0x6b, 
-0x72, 0x65, 0x66, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 
-0x2c, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 
-0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 
-0x65, 0x66, 0x73, 0x28, 0x74, 0x29, 0x3a, 0x28, 0x6f, 0x62, 0x6a, 0x73, 
-0x5f, 0x72, 0x65, 0x67, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 
-0x66, 0x28, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x3a, 0x3a, 0x67, 0x65, 0x74, 
-0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x29, 
-0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0d, 
-0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x74, 0x79, 0x70, 
-0x65, 0x20, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x28, 0x74, 
-0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x28, 0x6f, 0x74, 0x79, 0x70, 
-0x65, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 
-0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 
-0x0a, 0x09, 0x09, 0x69, 0x66, 0x28, 0x21, 0x28, 0x74, 0x20, 0x69, 0x6e, 
-0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 
-0x66, 0x73, 0x29, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x6f, 
-0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 
-0x5b, 0x74, 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 
-0x72, 0x65, 0x67, 0x2e, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x2b, 0x2b, 0x3b, 
-0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 
-0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 
-0x74, 0x28, 0x74, 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 
-0x28, 0x6f, 0x2c, 0x69, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3a, 0x28, 0x6f, 
-0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x29, 0x0d, 0x0a, 0x09, 0x09, 
-0x20, 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x20, 0x20, 
-0x20, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 
-0x28, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x20, 
-0x20, 0x20, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 
-0x73, 0x28, 0x69, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 
-0x20, 0x7d, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 
-0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 
-0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x76, 
-0x61, 0x6c, 0x75, 0x65, 0x28, 0x76, 0x29, 0x3a, 0x28, 0x6f, 0x62, 0x6a, 
-0x73, 0x5f, 0x72, 0x65, 0x67, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 
-0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70, 
-0x65, 0x28, 0x76, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 
-0x09, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 
-0x22, 0x3a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 
-0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x3a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 
-0x61, 0x73, 0x65, 0x20, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x3a, 
-0x0d, 0x0a, 0x09, 0x09, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x69, 0x6e, 
-0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x0d, 0x0a, 0x09, 0x09, 
-0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x73, 
-0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x5b, 0x76, 0x5d, 
-0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x3b, 
-0x0d, 0x0a, 0x09, 0x09, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x69, 0x6e, 
-0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x3a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 
-0x61, 0x73, 0x65, 0x20, 0x22, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x22, 0x3a, 
-0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 
-0x72, 0x6e, 0x20, 0x76, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x61, 0x73, 
-0x65, 0x20, 0x22, 0x62, 0x6f, 0x6f, 0x6c, 0x22, 0x3a, 0x0d, 0x0a, 0x09, 
-0x09, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 
-0x76, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x73, 
-0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b, 0x0d, 0x0a, 0x09, 
-0x09, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x6e, 0x75, 0x6c, 0x6c, 0x22, 
-0x3a, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 
-0x75, 0x72, 0x6e, 0x20, 0x22, 0x6e, 0x75, 0x6c, 0x6c, 0x22, 0x3b, 0x0d, 
-0x0a, 0x09, 0x09, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x0d, 
-0x0a, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 
-0x75, 0x72, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 
-0x65, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 
-0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 
-0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3d, 0x7b, 0x0d, 0x0a, 0x09, 0x5b, 
-0x22, 0x6e, 0x75, 0x6c, 0x6c, 0x22, 0x5d, 0x3d, 0x22, 0x6e, 0x22, 0x2c, 
-0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 
-0x5d, 0x3d, 0x22, 0x73, 0x22, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x69, 
-0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x5d, 0x3d, 0x22, 0x69, 0x22, 
-0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x22, 
-0x5d, 0x3d, 0x22, 0x66, 0x22, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x75, 
-0x73, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5d, 0x3d, 0x22, 0x75, 
-0x22, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 
-0x69, 0x6f, 0x6e, 0x22, 0x5d, 0x3d, 0x22, 0x66, 0x6e, 0x22, 0x2c, 0x0d, 
-0x0a, 0x09, 0x5b, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x5d, 0x3d, 
-0x22, 0x74, 0x22, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x61, 0x72, 0x72, 
-0x61, 0x79, 0x22, 0x5d, 0x3d, 0x22, 0x61, 0x22, 0x2c, 0x0d, 0x0a, 0x09, 
-0x5b, 0x22, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 
-0x5d, 0x3d, 0x22, 0x67, 0x22, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x74, 
-0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x5d, 0x3d, 0x22, 0x68, 0x22, 0x2c, 
-0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 
-0x65, 0x22, 0x5d, 0x3d, 0x22, 0x78, 0x22, 0x2c, 0x20, 0x0d, 0x0a, 0x09, 
-0x5b, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x5d, 0x3d, 0x22, 0x79, 
-0x22, 0x2c, 0x20, 0x20, 0x0d, 0x0a, 0x09, 0x5b, 0x22, 0x62, 0x6f, 0x6f, 
-0x6c, 0x22, 0x5d, 0x3d, 0x22, 0x62, 0x22, 0x2c, 0x0d, 0x0a, 0x09, 0x5b, 
-0x22, 0x77, 0x65, 0x61, 0x6b, 0x72, 0x65, 0x66, 0x22, 0x5d, 0x3d, 0x22, 
-0x77, 0x22, 0x20, 0x20, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 
-0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 
-0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x74, 0x79, 0x70, 0x65, 0x29, 0x3a, 
-0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 
-0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x28, 0x74, 
-0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 
-0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x29, 0x72, 0x65, 0x74, 0x75, 
-0x72, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x74, 0x79, 
-0x70, 0x65, 0x73, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x5d, 0x0d, 0x0a, 0x09, 
-0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0d, 
-0x0a, 0x7d, 0x20, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 
-0x69, 0x6f, 0x6e, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x6f, 
-0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x66, 0x75, 
-0x6e, 0x63, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 
-0x61, 0x6c, 0x20, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 0x79, 
-0x70, 0x65, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 
-0x66, 0x28, 0x74, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x69, 0x6e, 0x73, 
-0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 
-0x09, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x20, 0x2f, 0x2f, 0x54, 0x52, 0x59, 
-0x20, 0x54, 0x4f, 0x20, 0x55, 0x53, 0x45, 0x20, 0x5f, 0x6e, 0x65, 0x78, 
-0x74, 0x69, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 
-0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 
-0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x0d, 0x0a, 0x09, 
-0x09, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 
-0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x69, 0x64, 0x78, 
-0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 
-0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 
-0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 
-0x09, 0x09, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 
-0x28, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 
-0x6f, 0x62, 0x6a, 0x2e, 0x67, 0x65, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 
-0x28, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x7b, 0x0d, 
-0x0a, 0x09, 0x09, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 
-0x2c, 0x69, 0x64, 0x78, 0x2c, 0x6f, 0x62, 0x6a, 0x5b, 0x69, 0x64, 0x78, 
-0x5d, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x7d, 0x0d, 
-0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 
-0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x28, 0x74, 0x79, 0x20, 0x3d, 0x3d, 
-0x20, 0x22, 0x77, 0x65, 0x61, 0x6b, 0x72, 0x65, 0x66, 0x22, 0x29, 0x20, 
-0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 
-0x6a, 0x2c, 0x22, 0x40, 0x72, 0x65, 0x66, 0x22, 0x2c, 0x6f, 0x62, 0x6a, 
-0x2e, 0x72, 0x65, 0x66, 0x28, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 
-0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 
-0x09, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x64, 0x78, 
-0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, 
-0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 
-0x20, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x69, 0x64, 
-0x78, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 
-0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x7d, 
-0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 
-0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x28, 
-0x29, 0x3a, 0x28, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x29, 
-0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 
-0x68, 0x28, 0x69, 0x2c, 0x6f, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 
-0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x29, 0x0d, 
-0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x65, 0x67, 0x69, 0x6e, 
-0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x22, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 
-0x74, 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x28, 0x69, 
-0x3d, 0x3d, 0x3a, 0x3a, 0x67, 0x65, 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 
-0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x3f, 0x22, 0x72, 0x22, 0x3a, 0x70, 
-0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, 0x74, 
-0x79, 0x70, 0x65, 0x28, 0x69, 0x29, 0x29, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 
-0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x74, 0x79, 0x70, 
-0x65, 0x6f, 0x66, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 
-0x20, 0x69, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x28, 0x5f, 0x74, 
-0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x21, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 
-0x79, 0x70, 0x65, 0x28, 0x69, 0x29, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 
-0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 
-0x22, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x22, 0x2c, 0x5f, 0x74, 0x79, 
-0x70, 0x65, 0x6f, 0x66, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 
-0x0a, 0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 
-0x28, 0x22, 0x72, 0x65, 0x66, 0x22, 0x2c, 0x6f, 0x2e, 0x74, 0x6f, 0x73, 
-0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 
-0x09, 0x69, 0x66, 0x28, 0x69, 0x20, 0x21, 0x3d, 0x20, 0x3a, 0x3a, 0x67, 
-0x65, 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 
-0x29, 0x29, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x74, 0x65, 0x72, 
-0x61, 0x74, 0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x69, 0x2c, 
-0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6f, 0x62, 
-0x6a, 0x2c, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x20, 0x7b, 
-0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x28, 0x3a, 0x3a, 0x74, 
-0x79, 0x70, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x20, 0x3d, 0x3d, 0x20, 
-0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, 0x0d, 
-0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 
-0x09, 0x09, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 
-0x6e, 0x74, 0x28, 0x22, 0x65, 0x22, 0x29, 0x3b, 0x09, 0x0d, 0x0a, 0x09, 
-0x09, 0x09, 0x09, 0x09, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 
-0x65, 0x28, 0x22, 0x6b, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x76, 0x22, 0x2c, 
-0x69, 0x64, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 
-0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x22, 0x76, 
-0x74, 0x22, 0x2c, 0x22, 0x76, 0x22, 0x2c, 0x6f, 0x62, 0x6a, 0x5b, 0x69, 
-0x64, 0x78, 0x5d, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x65, 
-0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x65, 
-0x22, 0x29, 0x3b, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 
-0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 
-0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x22, 
-0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 
-0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x76, 
-0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 
-0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x2c, 0x69, 0x64, 0x2c, 0x65, 
-0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 
-0x7b, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 
-0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x72, 0x65, 0x74, 0x75, 
-0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 
-0x28, 0x22, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 
-0x61, 0x72, 0x61, 0x6d, 0x73, 0x3d, 0x5b, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 
-0x0d, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x70, 
-0x70, 0x65, 0x6e, 0x64, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x5b, 
-0x22, 0x74, 0x68, 0x69, 0x73, 0x22, 0x5d, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 
-0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x3d, 0x31, 
-0x3b, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 
-0x69, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 
-0x73, 0x29, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x28, 0x69, 0x21, 
-0x3d, 0x22, 0x74, 0x68, 0x69, 0x73, 0x22, 0x20, 0x26, 0x26, 0x20, 0x69, 
-0x5b, 0x30, 0x5d, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x40, 0x27, 0x29, 0x7b, 
-0x20, 0x2f, 0x2f, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20, 0x69, 
-0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x73, 0x74, 0x61, 
-0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x40, 0x0d, 0x0a, 0x09, 
-0x09, 0x09, 0x69, 0x66, 0x28, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74, 0x29, 
-0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x5f, 
-0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 
-0x2b, 0x22, 0x2c, 0x22, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 
-0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x69, 0x72, 
-0x73, 0x74, 0x3d, 0x6e, 0x75, 0x6c, 0x6c, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 
-0x64, 0x28, 0x76, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x75, 0x6e, 
-0x63, 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 
-0x72, 0x63, 0x2b, 0x69, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 
-0x7d, 0x0d, 0x0a, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 
-0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x2b, 0x22, 0x29, 
-0x7b, 0x5c, 0x6e, 0x22, 0x0d, 0x0a, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x5f, 
-0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 
-0x2b, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x22, 0x2b, 
-0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2b, 0x22, 
-0x29, 0x5c, 0x6e, 0x7d, 0x22, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x74, 
-0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 
-0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x3d, 0x3a, 0x3a, 0x63, 0x6f, 0x6d, 
-0x70, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x66, 
-0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 
-0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x7b, 0x73, 0x74, 0x61, 
-0x74, 0x75, 0x73, 0x3d, 0x22, 0x6f, 0x6b, 0x22, 0x20, 0x2c, 0x20, 0x76, 
-0x61, 0x6c, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x29, 0x2e, 0x61, 0x63, 
-0x61, 0x6c, 0x6c, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x7d, 
-0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x63, 0x61, 0x74, 0x63, 
-0x68, 0x28, 0x65, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 
-0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x7b, 
-0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x22, 0x65, 0x72, 0x72, 0x6f, 
-0x72, 0x22, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 
-0x0d, 0x0a, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x0d, 0x0a, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 
-0x2f, 0x2f, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 
-0x20, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x74, 
-0x79, 0x70, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x76, 
-0x61, 0x6c, 0x75, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 
-0x76, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x74, 
-0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x74, 0x79, 0x70, 0x65, 
-0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x70, 0x61, 0x63, 0x6b, 
-0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 
-0x28, 0x76, 0x61, 0x6c, 0x29, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 
-0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x76, 0x61, 0x6c, 
-0x75, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x67, 0x65, 
-0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x2e, 
-0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 
-0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 
-0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x3d, 0x5b, 0x5d, 0x0d, 0x0a, 0x6c, 
-0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x33, 
-0x3b, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x69, 0x3b, 
-0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x0d, 
-0x0a, 0x09, 0x2f, 0x2f, 0x45, 0x4e, 0x55, 0x4d, 0x45, 0x52, 0x41, 0x54, 
-0x45, 0x20, 0x54, 0x48, 0x45, 0x20, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x20, 
-0x57, 0x41, 0x54, 0x43, 0x48, 0x45, 0x53, 0x0d, 0x0a, 0x09, 0x77, 0x68, 
-0x69, 0x6c, 0x65, 0x28, 0x73, 0x69, 0x3d, 0x3a, 0x3a, 0x67, 0x65, 0x74, 
-0x73, 0x74, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x28, 0x6c, 
-0x65, 0x76, 0x65, 0x6c, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 
-0x09, 0x09, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x70, 0x65, 
-0x6e, 0x64, 0x28, 0x73, 0x69, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 
-0x65, 0x76, 0x65, 0x6c, 0x2b, 0x2b, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 
-0x0a, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x45, 0x56, 0x41, 0x4c, 0x55, 0x41, 
-0x54, 0x45, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x57, 0x41, 0x54, 0x43, 0x48, 
-0x45, 0x53, 0x0d, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 
-0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x5b, 0x3a, 0x3a, 0x67, 0x65, 0x74, 
-0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x5d, 
-0x20, 0x3c, 0x2d, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 
-0x2e, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x2b, 0x2b, 0x3b, 0x0d, 0x0a, 0x09, 
-0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x61, 
-0x6c, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x29, 0x0d, 
-0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x28, 0x76, 0x61, 
-0x6c, 0x2e, 0x73, 0x72, 0x63, 0x21, 0x3d, 0x22, 0x4e, 0x41, 0x54, 0x49, 
-0x56, 0x45, 0x22, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 
-0x66, 0x28, 0x22, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0x20, 
-0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 
-0x09, 0x09, 0x09, 0x09, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 
-0x68, 0x65, 0x73, 0x20, 0x3c, 0x2d, 0x20, 0x7b, 0x7d, 0x0d, 0x0a, 0x09, 
-0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 
-0x2c, 0x77, 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x61, 
-0x74, 0x63, 0x68, 0x65, 0x73, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 
-0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x28, 0x76, 
-0x61, 0x6c, 0x2e, 0x73, 0x72, 0x63, 0x21, 0x3d, 0x22, 0x4e, 0x41, 0x54, 
-0x49, 0x56, 0x45, 0x22, 0x29, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 
-0x09, 0x09, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 
-0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x65, 0x76, 0x61, 0x6c, 
-0x75, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x28, 0x76, 
-0x61, 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x2c, 0x69, 0x2c, 
-0x77, 0x61, 0x74, 0x63, 0x68, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x09, 0x09, 0x09, 0x69, 0x66, 0x28, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 
-0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x2e, 0x73, 0x74, 0x61, 
-0x74, 0x75, 0x73, 0x21, 0x3d, 0x22, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 
-0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x75, 
-0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x28, 0x76, 0x61, 0x6c, 
-0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x2e, 
-0x76, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 
-0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 
-0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x61, 0x6c, 
-0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 
-0x3c, 0x2d, 0x20, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x22, 
-0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x61, 
-0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, 
-0x2e, 0x65, 0x78, 0x70, 0x20, 0x3c, 0x2d, 0x20, 0x77, 0x61, 0x74, 0x63, 
-0x68, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 
-0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 
-0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 
-0x68, 0x28, 0x69, 0x2c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x76, 0x61, 0x6c, 
-0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x29, 0x0d, 0x0a, 0x09, 0x09, 
-0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x28, 
-0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x0d, 
-0x0a, 0x09, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 
-0x6e, 0x74, 0x28, 0x22, 0x6f, 0x62, 0x6a, 0x73, 0x22, 0x29, 0x3b, 0x0d, 
-0x0a, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 
-0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 
-0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x62, 0x6a, 0x73, 0x22, 0x29, 
-0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 
-0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 
-0x73, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 
-0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 
-0x6e, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 
-0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 
-0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 
-0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 
-0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x66, 0x6e, 0x63, 0x22, 0x2c, 0x76, 
-0x61, 0x6c, 0x2e, 0x66, 0x75, 0x6e, 0x63, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 
-0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 
-0x73, 0x72, 0x63, 0x22, 0x2c, 0x76, 0x61, 0x6c, 0x2e, 0x73, 0x72, 0x63, 
-0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 
-0x75, 0x74, 0x65, 0x28, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x2c, 0x76, 
-0x61, 0x6c, 0x2e, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x74, 0x6f, 0x73, 0x74, 
-0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 
-0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x20, 
-0x69, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 
-0x73, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 
-0x28, 0x22, 0x6c, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 
-0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x6e, 
-0x61, 0x6d, 0x65, 0x22, 0x2c, 0x67, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x75, 
-0x65, 0x28, 0x69, 0x29, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 
-0x67, 0x28, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x65, 
-0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x22, 0x74, 0x79, 
-0x70, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61, 0x6c, 0x22, 0x2c, 0x76, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 
-0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6c, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 
-0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x28, 0x22, 0x77, 
-0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x76, 
-0x61, 0x6c, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 
-0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x20, 0x69, 0x6e, 
-0x20, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 
-0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x09, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 
-0x74, 0x28, 0x22, 0x77, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 
-0x22, 0x69, 0x64, 0x22, 0x2c, 0x69, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 
-0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 
-0x22, 0x65, 0x78, 0x70, 0x22, 0x2c, 0x76, 0x2e, 0x65, 0x78, 0x70, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x61, 0x74, 0x74, 0x72, 
-0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 
-0x73, 0x22, 0x2c, 0x76, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x28, 0x76, 
-0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x21, 0x3d, 0x22, 0x65, 0x72, 
-0x72, 0x6f, 0x72, 0x22, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 
-0x09, 0x09, 0x09, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 
-0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61, 0x6c, 
-0x22, 0x2c, 0x76, 0x2e, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 
-0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x65, 
-0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x77, 
-0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 
-0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 
-0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 0x22, 0x29, 
-0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 
-0x09, 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 
-0x22, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 
-0x0a, 0x0d, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 
-0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, 0x0d, 0x0a, 0x09, 0x73, 
-0x74, 0x61, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, 
-0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x28, 0x22, 0x63, 0x6f, 
-0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 
-0x22, 0x20, 0x69, 0x6e, 0x20, 0x3a, 0x3a, 0x67, 0x65, 0x74, 0x72, 0x6f, 
-0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x29, 0x20, 0x3a, 
-0x3a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 
-0x61, 0x67, 0x65, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x63, 0x61, 0x74, 
-0x63, 0x68, 0x28, 0x65, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x3a, 
-0x3a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x22, 0x45, 0x52, 0x52, 0x4f, 
-0x52, 0x22, 0x2b, 0x65, 0x2b, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x3b, 0x0d, 
-0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 
-};
+static const SQChar serialize_state_nut[] = {\r
+ 0x74, 0x72, 0x79, 0x20, 0x7b,  0xd,  0xa,  0x9,  0xd,  0xa, 0x6c, 0x6f,\r
+ 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67,\r
+ 0x3d, 0x7b, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x3d, 0x30, 0x2c, 0x72, 0x65,\r
+ 0x66, 0x73, 0x3d, 0x7b, 0x7d, 0x7d,  0xd,  0xa,  0xd,  0xa, 0x63, 0x6f,\r
+ 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20,\r
+ 0x3c, 0x2d, 0x20, 0x7b,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x74, 0x61, 0x62,\r
+ 0x6c, 0x65, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2c,\r
+  0xd,  0xa,  0x9, 0x5b, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x5d,\r
+ 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2c,  0xd,  0xa,  0x9, 0x5b,\r
+ 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e,\r
+ 0x75, 0x6c, 0x6c, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x69, 0x6e, 0x73,\r
+ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75,\r
+ 0x6c, 0x6c, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x77, 0x65, 0x61, 0x6b,\r
+ 0x72, 0x65, 0x66, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c,\r
+ 0x2c,  0xd,  0xa, 0x7d,  0xd,  0xa,  0xd,  0xa, 0x66, 0x75, 0x6e, 0x63,\r
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72,\r
+ 0x65, 0x66, 0x73, 0x28, 0x74, 0x29,  0xd,  0xa, 0x7b,  0xd,  0xa,  0x9,\r
+ 0x69, 0x66, 0x28, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x3a, 0x3a, 0x67, 0x65,\r
+ 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29,\r
+ 0x29,  0xd,  0xa,  0x9,  0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b,\r
+  0xd,  0xa,  0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x74, 0x79,\r
+ 0x70, 0x65, 0x20, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x28,\r
+ 0x74, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x69, 0x66, 0x28, 0x6f, 0x74, 0x79,\r
+ 0x70, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,\r
+ 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x29,  0xd,  0xa,  0x9, 0x7b,\r
+  0xd,  0xa,  0x9,  0x9, 0x69, 0x66, 0x28, 0x21, 0x28, 0x74, 0x20, 0x69,\r
+ 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72,\r
+ 0x65, 0x66, 0x73, 0x29, 0x29, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+ 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66,\r
+ 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x6f, 0x62, 0x6a, 0x73,\r
+ 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x2b, 0x2b,\r
+ 0x3b,  0xd,  0xa,  0x9,  0x9,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20,\r
+ 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x6f, 0x62, 0x6a, 0x65,\r
+ 0x63, 0x74, 0x28, 0x74, 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,\r
+ 0x6e, 0x28, 0x6f, 0x2c, 0x69, 0x2c, 0x76, 0x61, 0x6c, 0x29,  0xd,  0xa,\r
+  0x9,  0x9, 0x20, 0x20, 0x20, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65,\r
+ 0x66, 0x73, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9, 0x20, 0x20, 0x20, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72,\r
+ 0x65, 0x66, 0x73, 0x28, 0x69, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x20,\r
+ 0x20, 0x20, 0x20, 0x7d, 0x29,  0xd,  0xa,  0x9,  0x9, 0x7d,  0xd,  0xa,\r
+  0x9,  0x9,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa, 0x7d,  0xd,  0xa,  0xd,\r
+  0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65,\r
+ 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x76, 0x29,  0xd,  0xa, 0x7b,\r
+  0xd,  0xa,  0x9, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x28, 0x3a, 0x3a,\r
+ 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x29,  0xd,  0xa,  0x9, 0x7b,\r
+  0xd,  0xa,  0x9,  0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x74, 0x61,\r
+ 0x62, 0x6c, 0x65, 0x22, 0x3a,  0xd,  0xa,  0x9,  0x9, 0x63, 0x61, 0x73,\r
+ 0x65, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x3a,  0xd,  0xa,\r
+  0x9,  0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x63, 0x6c, 0x61, 0x73,\r
+ 0x73, 0x22, 0x3a,  0xd,  0xa,  0x9,  0x9, 0x63, 0x61, 0x73, 0x65, 0x20,\r
+ 0x22, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x3a,  0xd,\r
+  0xa,  0x9,  0x9,  0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f,\r
+ 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73,\r
+ 0x5b, 0x76, 0x5d, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,\r
+ 0x28, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x63, 0x61, 0x73, 0x65, 0x20,\r
+ 0x22, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x3a,  0xd,  0xa,\r
+  0x9,  0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x66, 0x6c, 0x6f, 0x61,\r
+ 0x74, 0x22, 0x3a,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20, 0x20, 0x72,\r
+ 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b,  0xd,  0xa,  0x9,  0x9,\r
+ 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x62, 0x6f, 0x6f, 0x6c, 0x22, 0x3a,\r
+  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,\r
+ 0x72, 0x6e, 0x20, 0x76, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e,\r
+ 0x67, 0x28, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x63, 0x61, 0x73, 0x65,\r
+ 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a,  0xd,  0xa,\r
+  0x9,  0x9,  0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b,\r
+  0xd,  0xa,  0x9,  0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x6e, 0x75,\r
+ 0x6c, 0x6c, 0x22, 0x3a,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20, 0x20,\r
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x22, 0x6e, 0x75, 0x6c, 0x6c,\r
+ 0x22, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,\r
+ 0x74, 0x3a,  0xd,  0xa,  0x9,  0x9,  0x9,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x5f,\r
+ 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x28,\r
+ 0x76, 0x29, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa, 0x7d,  0xd,\r
+  0xa,  0xd,  0xa, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x63,\r
+ 0x6b, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3d, 0x7b,  0xd,\r
+  0xa,  0x9, 0x5b, 0x22, 0x6e, 0x75, 0x6c, 0x6c, 0x22, 0x5d, 0x3d, 0x22,\r
+ 0x6e, 0x22, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x73, 0x74, 0x72, 0x69,\r
+ 0x6e, 0x67, 0x22, 0x5d, 0x3d, 0x22, 0x73, 0x22, 0x2c,  0xd,  0xa,  0x9,\r
+ 0x5b, 0x22, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x5d, 0x3d,\r
+ 0x22, 0x69, 0x22, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x66, 0x6c, 0x6f,\r
+ 0x61, 0x74, 0x22, 0x5d, 0x3d, 0x22, 0x66, 0x22, 0x2c,  0xd,  0xa,  0x9,\r
+ 0x5b, 0x22, 0x75, 0x73, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5d,\r
+ 0x3d, 0x22, 0x75, 0x22, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x66, 0x75,\r
+ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5d, 0x3d, 0x22, 0x66, 0x6e,\r
+ 0x22, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65,\r
+ 0x22, 0x5d, 0x3d, 0x22, 0x74, 0x22, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22,\r
+ 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x5d, 0x3d, 0x22, 0x61, 0x22, 0x2c,\r
+  0xd,  0xa,  0x9, 0x5b, 0x22, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,\r
+ 0x6f, 0x72, 0x22, 0x5d, 0x3d, 0x22, 0x67, 0x22, 0x2c,  0xd,  0xa,  0x9,\r
+ 0x5b, 0x22, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x5d, 0x3d, 0x22,\r
+ 0x68, 0x22, 0x2c,  0xd,  0xa,  0x9, 0x5b, 0x22, 0x69, 0x6e, 0x73, 0x74,\r
+ 0x61, 0x6e, 0x63, 0x65, 0x22, 0x5d, 0x3d, 0x22, 0x78, 0x22, 0x2c, 0x20,\r
+  0xd,  0xa,  0x9, 0x5b, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x5d,\r
+ 0x3d, 0x22, 0x79, 0x22, 0x2c, 0x20, 0x20,  0xd,  0xa,  0x9, 0x5b, 0x22,\r
+ 0x62, 0x6f, 0x6f, 0x6c, 0x22, 0x5d, 0x3d, 0x22, 0x62, 0x22, 0x2c,  0xd,\r
+  0xa,  0x9, 0x5b, 0x22, 0x77, 0x65, 0x61, 0x6b, 0x72, 0x65, 0x66, 0x22,\r
+ 0x5d, 0x3d, 0x22, 0x77, 0x22, 0x20, 0x20,  0xd,  0xa, 0x7d,  0xd,  0xa,\r
+  0xd,  0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70,\r
+ 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x74, 0x79, 0x70,\r
+ 0x65, 0x29,  0xd,  0xa, 0x7b,  0xd,  0xa,  0x9, 0x69, 0x66, 0x28, 0x74,\r
+ 0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65,\r
+ 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x29, 0x72, 0x65, 0x74, 0x75,\r
+ 0x72, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x74, 0x79,\r
+ 0x70, 0x65, 0x73, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x5d,  0xd,  0xa,  0x9,\r
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65,  0xd,\r
+  0xa, 0x7d, 0x20,  0xd,  0xa,  0xd,  0xa, 0x66, 0x75, 0x6e, 0x63, 0x74,\r
+ 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x6f,\r
+ 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x66, 0x75,\r
+ 0x6e, 0x63, 0x29,  0xd,  0xa, 0x7b,  0xd,  0xa,  0x9, 0x6c, 0x6f, 0x63,\r
+ 0x61, 0x6c, 0x20, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 0x79,\r
+ 0x70, 0x65, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x69,\r
+ 0x66, 0x28, 0x74, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x69, 0x6e, 0x73,\r
+ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x29, 0x20, 0x7b,  0xd,  0xa,  0x9,\r
+  0x9, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x20, 0x2f, 0x2f, 0x54, 0x52, 0x59,\r
+ 0x20, 0x54, 0x4f, 0x20, 0x55, 0x53, 0x45, 0x20, 0x5f, 0x6e, 0x65, 0x78,\r
+ 0x74, 0x69,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,\r
+ 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61,\r
+ 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29,  0xd,  0xa,  0x9,\r
+  0x9, 0x20, 0x20, 0x20, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,\r
+ 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x69, 0x64, 0x78,\r
+ 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20,\r
+ 0x20, 0x20, 0x7d,  0xd,  0xa,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9,\r
+ 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x29, 0x20, 0x7b,  0xd,  0xa,\r
+  0x9,  0x9, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68,\r
+ 0x28, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20,\r
+ 0x6f, 0x62, 0x6a, 0x2e, 0x67, 0x65, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73,\r
+ 0x28, 0x29, 0x29,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20, 0x7b,  0xd,\r
+  0xa,  0x9,  0x9,  0x9, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a,\r
+ 0x2c, 0x69, 0x64, 0x78, 0x2c, 0x6f, 0x62, 0x6a, 0x5b, 0x69, 0x64, 0x78,\r
+ 0x5d, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20, 0x7d,  0xd,\r
+  0xa,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa,  0x9, 0x65,\r
+ 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x28, 0x74, 0x79, 0x20, 0x3d, 0x3d,\r
+ 0x20, 0x22, 0x77, 0x65, 0x61, 0x6b, 0x72, 0x65, 0x66, 0x22, 0x29, 0x20,\r
+ 0x7b,  0xd,  0xa,  0x9,  0x9, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62,\r
+ 0x6a, 0x2c, 0x22, 0x40, 0x72, 0x65, 0x66, 0x22, 0x2c, 0x6f, 0x62, 0x6a,\r
+ 0x2e, 0x72, 0x65, 0x66, 0x28, 0x29, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x7d,\r
+  0xd,  0xa,  0x9, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b,  0xd,  0xa,  0x9,\r
+  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x64, 0x78,\r
+ 0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29,\r
+  0xd,  0xa,  0x9,  0x9, 0x7b,  0xd,  0xa,  0x9,  0x9, 0x20, 0x20, 0x20,\r
+ 0x20, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x69, 0x64,\r
+ 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x7d,\r
+  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9,  0x9,  0xd,  0xa, 0x7d,\r
+  0xd,  0xa,  0xd,  0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,\r
+ 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x28,\r
+ 0x29,  0xd,  0xa, 0x7b,  0xd,  0xa,  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61,\r
+ 0x63, 0x68, 0x28, 0x69, 0x2c, 0x6f, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62,\r
+ 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x29,\r
+  0xd,  0xa,  0x9, 0x7b,  0xd,  0xa,  0x9,  0x9, 0x62, 0x65, 0x67, 0x69,\r
+ 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x22,\r
+ 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,\r
+ 0x75, 0x74, 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x28,\r
+ 0x69, 0x3d, 0x3d, 0x3a, 0x3a, 0x67, 0x65, 0x74, 0x72, 0x6f, 0x6f, 0x74,\r
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x3f, 0x22, 0x72, 0x22, 0x3a,\r
+ 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a,\r
+ 0x74, 0x79, 0x70, 0x65, 0x28, 0x69, 0x29, 0x29, 0x29, 0x29, 0x3b,  0xd,\r
+  0xa,  0x9,  0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x74, 0x79,\r
+ 0x70, 0x65, 0x6f, 0x66, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x6f,\r
+ 0x66, 0x20, 0x69, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x69, 0x66, 0x28, 0x5f,\r
+ 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x21, 0x3d, 0x20, 0x3a, 0x3a,\r
+ 0x74, 0x79, 0x70, 0x65, 0x28, 0x69, 0x29, 0x29, 0x20, 0x7b,  0xd,  0xa,\r
+  0x9,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,\r
+ 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x22, 0x2c, 0x5f, 0x74,\r
+ 0x79, 0x70, 0x65, 0x6f, 0x66, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x7d,\r
+  0xd,  0xa,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,\r
+ 0x65, 0x28, 0x22, 0x72, 0x65, 0x66, 0x22, 0x2c, 0x6f, 0x2e, 0x74, 0x6f,\r
+ 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b,  0xd,  0xa,\r
+  0x9,  0x9, 0x69, 0x66, 0x28, 0x69, 0x20, 0x21, 0x3d, 0x20, 0x3a, 0x3a,\r
+ 0x67, 0x65, 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65,\r
+ 0x28, 0x29, 0x29, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9, 0x69, 0x74, 0x65,\r
+ 0x72, 0x61, 0x74, 0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x69,\r
+ 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6f,\r
+ 0x62, 0x6a, 0x2c, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x20,\r
+ 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9, 0x69, 0x66, 0x28, 0x3a, 0x3a,\r
+ 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x20, 0x3d, 0x3d,\r
+ 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29,\r
+  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9, 0x72, 0x65, 0x74, 0x75, 0x72,\r
+ 0x6e, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9,  0xd,  0xa,  0x9,\r
+  0x9,  0x9,  0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d,\r
+ 0x65, 0x6e, 0x74, 0x28, 0x22, 0x65, 0x22, 0x29, 0x3b,  0x9,  0xd,  0xa,\r
+  0x9,  0x9,  0x9,  0x9,  0x9, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c,\r
+ 0x75, 0x65, 0x28, 0x22, 0x6b, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x76, 0x22,\r
+ 0x2c, 0x69, 0x64, 0x78, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,\r
+  0x9, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x22,\r
+ 0x76, 0x74, 0x22, 0x2c, 0x22, 0x76, 0x22, 0x2c, 0x6f, 0x62, 0x6a, 0x5b,\r
+ 0x69, 0x64, 0x78, 0x5d, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,\r
+ 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22,\r
+ 0x65, 0x22, 0x29, 0x3b,  0x9,  0xd,  0xa,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+ 0x7d, 0x29,  0xd,  0xa,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9, 0x65,\r
+ 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f,\r
+ 0x22, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa, 0x7d,  0xd,  0xa,\r
+  0xd,  0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65,\r
+ 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x63,\r
+ 0x68, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x2c, 0x69, 0x64, 0x2c,\r
+ 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x29,  0xd,\r
+  0xa, 0x7b,  0xd,  0xa,  0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66,\r
+ 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x72, 0x65, 0x74,\r
+ 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,\r
+ 0x20, 0x28, 0x22,  0xd,  0xa,  0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,\r
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3d, 0x5b, 0x5d, 0x3b,  0xd,  0xa,\r
+  0x9,  0xd,  0xa,  0x9, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61,\r
+ 0x70, 0x70, 0x65, 0x6e, 0x64, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73,\r
+ 0x5b, 0x22, 0x74, 0x68, 0x69, 0x73, 0x22, 0x5d, 0x29,  0xd,  0xa,  0x9,\r
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x3d,\r
+ 0x31, 0x3b,  0xd,  0xa,  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68,\r
+ 0x28, 0x69, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x63, 0x61,\r
+ 0x6c, 0x73, 0x29, 0x7b,  0xd,  0xa,  0x9,  0x9, 0x69, 0x66, 0x28, 0x69,\r
+ 0x21, 0x3d, 0x22, 0x74, 0x68, 0x69, 0x73, 0x22, 0x20, 0x26, 0x26, 0x20,\r
+ 0x69, 0x5b, 0x30, 0x5d, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x40, 0x27, 0x29,\r
+ 0x7b, 0x20, 0x2f, 0x2f, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20,\r
+ 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x73, 0x74,\r
+ 0x61, 0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x40,  0xd,  0xa,\r
+  0x9,  0x9,  0x9, 0x69, 0x66, 0x28, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74,\r
+ 0x29, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9, 0x66, 0x75, 0x6e, 0x63,\r
+ 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72,\r
+ 0x63, 0x2b, 0x22, 0x2c, 0x22,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0xd,\r
+  0xa,  0x9,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9,  0x9, 0x66, 0x69,\r
+ 0x72, 0x73, 0x74, 0x3d, 0x6e, 0x75, 0x6c, 0x6c,  0xd,  0xa,  0x9,  0x9,\r
+  0x9, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x70, 0x70, 0x65,\r
+ 0x6e, 0x64, 0x28, 0x76, 0x29,  0xd,  0xa,  0x9,  0x9,  0x9, 0x66, 0x75,\r
+ 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f,\r
+ 0x73, 0x72, 0x63, 0x2b, 0x69,  0xd,  0xa,  0x9,  0x9, 0x7d,  0xd,  0xa,\r
+  0x9, 0x7d,  0xd,  0xa,  0x9, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72,\r
+ 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x2b, 0x22,\r
+ 0x29, 0x7b, 0x5c, 0x6e, 0x22,  0xd,  0xa,  0x9, 0x66, 0x75, 0x6e, 0x63,\r
+ 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72,\r
+ 0x63, 0x2b, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x22,\r
+ 0x2b, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2b,\r
+ 0x22, 0x29, 0x5c, 0x6e, 0x7d, 0x22,  0xd,  0xa,  0x9,  0xd,  0xa,  0x9,\r
+ 0x74, 0x72, 0x79, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9, 0x6c, 0x6f, 0x63,\r
+ 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x3d, 0x3a, 0x3a, 0x63, 0x6f,\r
+ 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28,\r
+ 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x29, 0x3b,  0xd,  0xa,\r
+  0x9,  0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x7b, 0x73, 0x74,\r
+ 0x61, 0x74, 0x75, 0x73, 0x3d, 0x22, 0x6f, 0x6b, 0x22, 0x20, 0x2c, 0x20,\r
+ 0x76, 0x61, 0x6c, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x29, 0x2e, 0x61,\r
+ 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29,\r
+ 0x7d, 0x3b,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa,  0x9, 0x63, 0x61, 0x74,\r
+ 0x63, 0x68, 0x28, 0x65, 0x29,  0xd,  0xa,  0x9, 0x7b,  0xd,  0xa,  0x9,\r
+  0x9,  0xd,  0xa,  0x9,  0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,\r
+ 0x7b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x22, 0x65, 0x72, 0x72,\r
+ 0x6f, 0x72, 0x22, 0x7d,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa, 0x7d,  0xd,\r
+  0xa,  0xd,  0xa, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,  0xd,  0xa, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,\r
+ 0x2f, 0x2f, 0x2f,  0xd,  0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,\r
+ 0x6e, 0x20, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28,\r
+ 0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c,\r
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,\r
+ 0x2c, 0x76, 0x61, 0x6c, 0x29,  0xd,  0xa, 0x7b,  0xd,  0xa,  0x9, 0x61,\r
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x74, 0x79, 0x70,\r
+ 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x70, 0x61, 0x63,\r
+ 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70,\r
+ 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x29, 0x29, 0x3b,  0xd,  0xa,  0x9,\r
+ 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x76, 0x61,\r
+ 0x6c, 0x75, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x67,\r
+ 0x65, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29,\r
+ 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29,\r
+ 0x3b,  0xd,  0xa, 0x7d,  0xd,  0xa,  0xd,  0xa, 0x6c, 0x6f, 0x63, 0x61,\r
+ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x3d, 0x5b, 0x5d,  0xd,  0xa,\r
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d,\r
+ 0x33, 0x3b,  0xd,  0xa, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x69,\r
+ 0x3b,  0xd,  0xa,  0xd,  0xa, 0x2f, 0x2f, 0x74, 0x72, 0x79, 0x20, 0x7b,\r
+  0xd,  0xa,  0x9, 0x2f, 0x2f, 0x45, 0x4e, 0x55, 0x4d, 0x45, 0x52, 0x41,\r
+ 0x54, 0x45, 0x20, 0x54, 0x48, 0x45, 0x20, 0x53, 0x54, 0x41, 0x43, 0x4b,\r
+ 0x20, 0x57, 0x41, 0x54, 0x43, 0x48, 0x45, 0x53,  0xd,  0xa,  0x9, 0x77,\r
+ 0x68, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x69, 0x3d, 0x3a, 0x3a, 0x67, 0x65,\r
+ 0x74, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x28,\r
+ 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x29, 0x29,  0xd,  0xa,  0x9, 0x7b,  0xd,\r
+  0xa,  0x9,  0x9, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x70,\r
+ 0x65, 0x6e, 0x64, 0x28, 0x73, 0x69, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,\r
+ 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2b, 0x2b, 0x3b,  0xd,  0xa,  0x9, 0x7d,\r
+  0xd,  0xa,  0xd,  0xa,  0x9, 0x2f, 0x2f, 0x45, 0x56, 0x41, 0x4c, 0x55,\r
+ 0x41, 0x54, 0x45, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x57, 0x41, 0x54, 0x43,\r
+ 0x48, 0x45, 0x53,  0xd,  0xa,  0x9, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72,\r
+ 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x5b, 0x3a, 0x3a, 0x67, 0x65,\r
+ 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29,\r
+ 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65,\r
+ 0x67, 0x2e, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x2b, 0x2b, 0x3b,  0xd,  0xa,\r
+  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76,\r
+ 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x29,\r
+  0xd,  0xa,  0x9, 0x7b,  0xd,  0xa,  0x9,  0x9, 0x69, 0x66, 0x28, 0x76,\r
+ 0x61, 0x6c, 0x2e, 0x73, 0x72, 0x63, 0x21, 0x3d, 0x22, 0x4e, 0x41, 0x54,\r
+ 0x49, 0x56, 0x45, 0x22, 0x29, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+ 0x69, 0x66, 0x28, 0x22, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22,\r
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x7b,  0xd,\r
+  0xa,  0x9,  0x9,  0x9,  0x9, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74,\r
+ 0x63, 0x68, 0x65, 0x73, 0x20, 0x3c, 0x2d, 0x20, 0x7b, 0x7d,  0xd,  0xa,\r
+  0x9,  0x9,  0x9,  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28,\r
+ 0x69, 0x2c, 0x77, 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x77,\r
+ 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x29,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+  0x9, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9, 0x69, 0x66, 0x28,\r
+ 0x76, 0x61, 0x6c, 0x2e, 0x73, 0x72, 0x63, 0x21, 0x3d, 0x22, 0x4e, 0x41,\r
+ 0x54, 0x49, 0x56, 0x45, 0x22, 0x29, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+  0x9,  0x9,  0x9, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68,\r
+ 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x65, 0x76, 0x61,\r
+ 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x28,\r
+ 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x2c, 0x69,\r
+ 0x2c, 0x77, 0x61, 0x74, 0x63, 0x68, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9,  0x9,  0x9,  0x9, 0x69, 0x66, 0x28, 0x76, 0x61, 0x6c, 0x2e, 0x77,\r
+ 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x2e, 0x73, 0x74,\r
+ 0x61, 0x74, 0x75, 0x73, 0x21, 0x3d, 0x22, 0x65, 0x72, 0x72, 0x6f, 0x72,\r
+ 0x22, 0x29,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9,  0x9,  0x9, 0x62,\r
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x28, 0x76, 0x61,\r
+ 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d,\r
+ 0x2e, 0x76, 0x61, 0x6c, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,\r
+  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9, 0x65, 0x6c, 0x73,\r
+ 0x65, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9,  0x9, 0x76, 0x61,\r
+ 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d,\r
+ 0x20, 0x3c, 0x2d, 0x20, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d,\r
+ 0x22, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7d,  0xd,  0xa,  0x9,  0x9,\r
+  0x9,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9, 0x76,\r
+ 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69,\r
+ 0x5d, 0x2e, 0x65, 0x78, 0x70, 0x20, 0x3c, 0x2d, 0x20, 0x77, 0x61, 0x74,\r
+ 0x63, 0x68, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9, 0x7d,  0xd,  0xa,\r
+  0x9,  0x9,  0x9,  0x9,  0xd,  0xa,  0x9,  0x9,  0x9, 0x7d,  0xd,  0xa,\r
+  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61,\r
+ 0x63, 0x68, 0x28, 0x69, 0x2c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x76, 0x61,\r
+ 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x29,  0xd,  0xa,  0x9,\r
+  0x9,  0x9, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73,\r
+ 0x28, 0x6c, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x7d,  0xd,  0xa,  0xd,  0xa,\r
+  0xd,  0xa,  0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d,\r
+ 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x62, 0x6a, 0x73, 0x22, 0x29, 0x3b,\r
+  0xd,  0xa,  0x9, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x65,\r
+ 0x65, 0x28, 0x29, 0x3b,  0xd,  0xa,  0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c,\r
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x62, 0x6a, 0x73, 0x22,\r
+ 0x29, 0x3b,  0xd,  0xa,  0xd,  0xa,  0x9, 0x62, 0x65, 0x67, 0x69, 0x6e,\r
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c,\r
+ 0x6c, 0x73, 0x22, 0x29, 0x3b,  0xd,  0xa,  0xd,  0xa,  0x9, 0x66, 0x6f,\r
+ 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x61, 0x6c, 0x20,\r
+ 0x69, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x29,  0xd,  0xa,  0x9,\r
+ 0x7b,  0xd,  0xa,  0xd,  0xa,  0x9,  0x9, 0x62, 0x65, 0x67, 0x69, 0x6e,\r
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c,\r
+ 0x6c, 0x22, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72,\r
+ 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x66, 0x6e, 0x63, 0x22, 0x2c,\r
+ 0x76, 0x61, 0x6c, 0x2e, 0x66, 0x75, 0x6e, 0x63, 0x29, 0x3b,  0xd,  0xa,\r
+  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28,\r
+ 0x22, 0x73, 0x72, 0x63, 0x22, 0x2c, 0x76, 0x61, 0x6c, 0x2e, 0x73, 0x72,\r
+ 0x63, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69,\r
+ 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x2c,\r
+ 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x74, 0x6f, 0x73,\r
+ 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b,  0xd,  0xa,  0x9,\r
+  0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76,\r
+ 0x20, 0x69, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61,\r
+ 0x6c, 0x73, 0x29,  0xd,  0xa,  0x9,  0x9, 0x7b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,\r
+ 0x74, 0x28, 0x22, 0x6c, 0x22, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,\r
+  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22,\r
+ 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x67, 0x65, 0x74, 0x76, 0x61, 0x6c,\r
+ 0x75, 0x65, 0x28, 0x69, 0x29, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69,\r
+ 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,\r
+ 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x22, 0x74,\r
+ 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61, 0x6c, 0x22, 0x2c, 0x76,\r
+ 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c,\r
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6c, 0x22, 0x29, 0x3b,  0xd,\r
+  0xa,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9, 0x69, 0x66, 0x28, 0x22,\r
+ 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0x20, 0x69, 0x6e, 0x20,\r
+ 0x76, 0x61, 0x6c, 0x29, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9,  0x9, 0x66,\r
+ 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x20, 0x69,\r
+ 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65,\r
+ 0x73, 0x29,  0xd,  0xa,  0x9,  0x9,  0x9, 0x7b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9,  0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65,\r
+ 0x6e, 0x74, 0x28, 0x22, 0x77, 0x22, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,\r
+ 0x28, 0x22, 0x69, 0x64, 0x22, 0x2c, 0x69, 0x2e, 0x74, 0x6f, 0x73, 0x74,\r
+ 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9,  0x9,  0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,\r
+ 0x28, 0x22, 0x65, 0x78, 0x70, 0x22, 0x2c, 0x76, 0x2e, 0x65, 0x78, 0x70,\r
+ 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9, 0x61, 0x74, 0x74,\r
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x73, 0x74, 0x61, 0x74,\r
+ 0x75, 0x73, 0x22, 0x2c, 0x76, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,\r
+ 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,  0x9, 0x69, 0x66, 0x28,\r
+ 0x76, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x21, 0x3d, 0x22, 0x65,\r
+ 0x72, 0x72, 0x6f, 0x72, 0x22, 0x29, 0x20, 0x7b,  0xd,  0xa,  0x9,  0x9,\r
+  0x9,  0x9,  0x9,  0x9, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75,\r
+ 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61,\r
+ 0x6c, 0x22, 0x2c, 0x76, 0x2e, 0x76, 0x61, 0x6c, 0x29, 0x3b,  0xd,  0xa,\r
+  0x9,  0x9,  0x9,  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9,  0x9,  0x9,\r
+ 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22,\r
+ 0x77, 0x22, 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9,  0x9, 0x7d,  0xd,  0xa,\r
+  0x9,  0x9, 0x7d,  0xd,  0xa,  0x9,  0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c,\r
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 0x22,\r
+ 0x29, 0x3b,  0xd,  0xa,  0x9,  0x9, 0x20,  0xd,  0xa,  0x9, 0x7d,  0xd,\r
+  0xa,  0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,\r
+ 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x22, 0x29, 0x3b,  0xd,  0xa,\r
+  0xd,  0xa,  0xd,  0xa,  0x9, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65,\r
+ 0x67, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b,  0xd,  0xa,  0x9,\r
+ 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c,\r
+ 0x3b,  0xd,  0xa,  0x9,  0xd,  0xa,  0x9, 0x69, 0x66, 0x28, 0x22, 0x63,\r
+ 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 0x61, 0x67,\r
+ 0x65, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x3a, 0x3a, 0x67, 0x65, 0x74, 0x72,\r
+ 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x29, 0x20,\r
+ 0x3a, 0x3a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72,\r
+ 0x62, 0x61, 0x67, 0x65, 0x28, 0x29, 0x3b,  0xd,  0xa, 0x7d, 0x63, 0x61,\r
+ 0x74, 0x63, 0x68, 0x28, 0x65, 0x29,  0xd,  0xa, 0x7b,  0xd,  0xa,  0x9,\r
+ 0x3a, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x22, 0x45, 0x52, 0x52,\r
+ 0x4f, 0x52, 0x22, 0x2b, 0x65, 0x2b, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x3b,\r
+  0xd,  0xa, 0x7d,  0xd,  0xa,  0xd,  0xa };\r
old mode 100644 (file)
new mode 100755 (executable)
index 6009e0a..c7909c8
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <squirrel.h>
-#include <assert.h>
-#include <sqstdblob.h>
-#include "sqrdbg.h"
-#include "sqdbgserver.h"
-
-
-#ifndef _UNICODE
-#define scstrcpy strcpy
-#else
-#define scstrcpy wcscpy
-#endif
-struct XMLEscape{
-       const SQChar c;
-       const SQChar *esc;
-};
-
-#define SQDBG_DEBUG_HOOK _SC("_sqdbg_debug_hook_")
-#define SQDBG_ERROR_HANDLER _SC("_sqdbg_error_handler_")
-
-XMLEscape g_escapes[]={
-       {_SC('<'),_SC("&lt;")},{'>',_SC("&gt;")},{_SC('&'),_SC("&amp;")},{_SC('\''),_SC("&apos;")},{_SC('\"'),_SC("&quot;")},{_SC('\n'),_SC("&quot;n")},{_SC('\r'),_SC("&quot;r")},{0, NULL}
-};
-
-const SQChar *IntToString(int n)
-{
-       static SQChar temp[256];
-       scsprintf(temp,_SC("%d"),n);
-       return temp;
-}
-
-SQInteger debug_hook(HSQUIRRELVM v);
-SQInteger error_handler(HSQUIRRELVM v);
-
-SQInteger beginelement(HSQUIRRELVM v)
-{
-       SQUserPointer up;
-       const SQChar *name;
-       sq_getuserpointer(v,-1,&up);
-       SQDbgServer *self = (SQDbgServer*)up;
-       sq_getuserpointer(v,-1,&up);
-       sq_getstring(v,2,&name);
-       self->BeginElement(name);
-       return 0;
-}
-
-SQInteger endelement(HSQUIRRELVM v)
-{
-       SQUserPointer up;
-       const SQChar *name;
-       sq_getuserpointer(v,-1,&up);
-       SQDbgServer *self = (SQDbgServer*)up;
-       sq_getuserpointer(v,-1,&up);
-       sq_getstring(v,2,&name);
-       self->EndElement(name);
-       return 0;
-}
-
-SQInteger attribute(HSQUIRRELVM v)
-{
-       SQUserPointer up;
-       const SQChar *name,*value;
-       sq_getuserpointer(v,-1,&up);
-       SQDbgServer *self = (SQDbgServer*)up;
-       sq_getuserpointer(v,-1,&up);
-       sq_getstring(v,2,&name);
-       sq_getstring(v,3,&value);
-       self->Attribute(name,value);
-       return 0;
-}
-
-const SQChar *EscapeXMLString(HSQUIRRELVM v,const SQChar *s)
-{
-
-       SQChar *temp=sq_getscratchpad(v,((int)scstrlen(s)*6) + sizeof(SQChar));
-       SQChar *dest=temp;
-       while(*s!=_SC('\0')){
-               int i=0;
-               bool escaped=false;
-               while(g_escapes[i].esc!=NULL){
-                       if(*s==g_escapes[i].c){
-                               scstrcpy(dest,g_escapes[i].esc);
-                               dest+=scstrlen(g_escapes[i].esc);
-                               escaped=true;
-                               break;
-                       }
-                       i++;
-               }
-               if(!escaped){*dest=*s;*dest++;}
-               *s++;
-       }
-       *dest=_SC('\0');
-       return temp;
-}
-
-SQDbgServer::SQDbgServer(HSQUIRRELVM v)
-{
-       _ready = false;
-       _nestedcalls = 0;
-       _autoupdate = false;
-       _v = v;
-       _state = eDBG_Running;
-       _accept = INVALID_SOCKET;
-       _endpoint = INVALID_SOCKET;
-       _maxrecursion = 10;
-       sq_resetobject(&_debugroot);
-}
-
-SQDbgServer::~SQDbgServer()
-{
-       sq_release(_v,&_debugroot);
-       if(_accept != INVALID_SOCKET)
-               sqdbg_closesocket(_accept);
-       if(_endpoint != INVALID_SOCKET)
-               sqdbg_closesocket(_endpoint);
-}
-
-bool SQDbgServer::Init()
-{
-       //creates  an environment table for the debugger
-
-       sq_newtable(_v);
-       sq_getstackobj(_v,-1,&_debugroot);
-       sq_addref(_v,&_debugroot);
-
-       //creates a emptyslot to store the watches
-       sq_pushstring(_v,_SC("watches"),-1);
-       sq_pushnull(_v);
-       sq_createslot(_v,-3);
-
-       sq_pushstring(_v,_SC("beginelement"),-1);
-       sq_pushuserpointer(_v,this);
-       sq_newclosure(_v,beginelement,1);
-       sq_setparamscheck(_v,2,_SC(".s"));
-       sq_createslot(_v,-3);
-
-       sq_pushstring(_v,_SC("endelement"),-1);
-       sq_pushuserpointer(_v,this);
-       sq_newclosure(_v,endelement,1);
-       sq_setparamscheck(_v,2,_SC(".s"));
-       sq_createslot(_v,-3);
-
-       sq_pushstring(_v,_SC("attribute"),-1);
-       sq_pushuserpointer(_v,this);
-       sq_newclosure(_v,attribute,1);
-       sq_setparamscheck(_v,3,_SC(".ss"));
-       sq_createslot(_v,-3);
-
-       sq_pop(_v,1);
-
-       //stores debug hook and error handler in the registry
-       sq_pushregistrytable(_v);
-
-       sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);
-       sq_pushuserpointer(_v,this);
-       sq_newclosure(_v,debug_hook,1);
-       sq_createslot(_v,-3);
-
-       sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1);
-       sq_pushuserpointer(_v,this);
-       sq_newclosure(_v,error_handler,1);
-       sq_createslot(_v,-3);
-
-
-       sq_pop(_v,1);
-
-       //sets the error handlers
-       SetErrorHandlers();
-       return true;
-}
-
-bool SQDbgServer::ReadMsg()
-{
-       return false;
-}
-
-void SQDbgServer::BusyWait()
-{
-       while( !ReadMsg() )
-               sleep(0);
-}
-
-void SQDbgServer::SendChunk(const SQChar *chunk)
-{
-       char *buf=NULL;
-       int buf_len=0;
-#ifdef _UNICODE
-       buf_len=(int)scstrlen(chunk)+1;
-       buf=(char *)sq_getscratchpad(_v,(buf_len)*3);
-       wcstombs((char *)buf,chunk,buf_len);
-#else
-       buf_len=(int)scstrlen(chunk);
-       buf=(char *)chunk;
-#endif
-       send(_endpoint,(const char*)buf,(int)strlen((const char *)buf),0);
-}
-
-
-void SQDbgServer::Terminated()
-{
-       BeginElement(_SC("terminated"));
-       EndElement(_SC("terminated"));
-       ::usleep(200);
-}
-
-void SQDbgServer::Hook(int type,int line,const SQChar *src,const SQChar *func)
-{
-       switch(_state){
-       case eDBG_Running:
-               if(type==_SC('l') && _breakpoints.size()) {
-                       BreakPointSetItor itr = _breakpoints.find(BreakPoint(line,src));
-                       if(itr != _breakpoints.end()) {
-                               Break(line,src,_SC("breakpoint"));
-                               BreakExecution();
-                       }
-               }
-               break;
-       case eDBG_Suspended:
-               _nestedcalls=0;
-       case eDBG_StepOver:
-               switch(type){
-               case _SC('l'):
-                       if(_nestedcalls==0) {
-                               Break(line,src,_SC("step"));
-                               BreakExecution();
-                       }
-                       break;
-               case _SC('c'):
-                       _nestedcalls++;
-                       break;
-               case _SC('r'):
-                       if(_nestedcalls==0){
-                               _nestedcalls=0;
-
-                       }else{
-                               _nestedcalls--;
-                       }
-                       break;
-               }
-               break;
-       case eDBG_StepInto:
-               switch(type){
-               case _SC('l'):
-                       _nestedcalls=0;
-                       Break(line,src,_SC("step"));
-                       BreakExecution();
-                       break;
-
-               }
-               break;
-       case eDBG_StepReturn:
-               switch(type){
-               case _SC('l'):
-                       break;
-               case _SC('c'):
-                       _nestedcalls++;
-                       break;
-               case _SC('r'):
-                       if(_nestedcalls==0){
-                               _nestedcalls=0;
-                               _state=eDBG_StepOver;
-                       }else{
-                               _nestedcalls--;
-                       }
-
-                       break;
-               }
-               break;
-       case eDBG_Disabled:
-               break;
-       }
-}
-
-
-#define MSG_ID(x,y) ((y<<8)|x)
-//ab Add Breakpoint
-//rb Remove Breakpoint
-//sp Suspend
-void SQDbgServer::ParseMsg(const char *msg)
-{
-
-       switch(*((unsigned short *)msg)){
-               case MSG_ID('a','b'): {
-                       BreakPoint bp;
-                       if(ParseBreakpoint(msg+3,bp)){
-                               AddBreakpoint(bp);
-                               scprintf(_SC("added bp %d %s\n"),bp._line,bp._src.c_str());
-                       }
-                       else
-                               scprintf(_SC("error parsing add breakpoint"));
-                                                        }
-                       break;
-               case MSG_ID('r','b'): {
-                       BreakPoint bp;
-                       if(ParseBreakpoint(msg+3,bp)){
-                               RemoveBreakpoint(bp);
-                               scprintf(_SC("removed bp %d %s\n"),bp._line,bp._src.c_str());
-                       }else
-                               scprintf(_SC("error parsing remove breakpoint"));
-                                                       }
-                       break;
-               case MSG_ID('g','o'):
-                       if(_state!=eDBG_Running){
-                               _state=eDBG_Running;
-                               BeginDocument();
-                                       BeginElement(_SC("resumed"));
-                                       EndElement(_SC("resumed"));
-                               EndDocument();
-//                             Send(_SC("<resumed/>\r\n"));
-                               scprintf(_SC("go (execution resumed)\n"));
-                       }
-                       break;
-               case MSG_ID('s','p'):
-                       if(_state!=eDBG_Suspended){
-                               _state=eDBG_Suspended;
-                               scprintf(_SC("suspend\n"));
-                       }
-                       break;
-               case MSG_ID('s','o'):
-                       if(_state==eDBG_Suspended){
-                               _state=eDBG_StepOver;
-                       }
-                       break;
-               case MSG_ID('s','i'):
-                       if(_state==eDBG_Suspended){
-                               _state=eDBG_StepInto;
-                               scprintf(_SC("step into\n"));
-                       }
-                       break;
-               case MSG_ID('s','r'):
-                       if(_state==eDBG_Suspended){
-                               _state=eDBG_StepReturn;
-                               scprintf(_SC("step return\n"));
-                       }
-                       break;
-               case MSG_ID('d','i'):
-                       if(_state!=eDBG_Disabled){
-                               _state=eDBG_Disabled;
-                               scprintf(_SC("disabled\n"));
-                       }
-                       break;
-               case MSG_ID('a','w'): {
-                       Watch w;
-                       if(ParseWatch(msg+3,w))
-                       {
-                               AddWatch(w);
-                               scprintf(_SC("added watch %d %s\n"),w._id,w._exp.c_str());
-                       }
-                       else
-                               scprintf(_SC("error parsing add watch"));
-                                                               }
-                       break;
-               case MSG_ID('r','w'): {
-                       int id;
-                       if(ParseRemoveWatch(msg+3,id))
-                       {
-                               RemoveWatch(id);
-                               scprintf(_SC("added watch %d\n"),id);
-                       }
-                       else
-                               scprintf(_SC("error parsing remove watch"));
-                                                               }
-                       break;
-               case MSG_ID('t','r'):
-                       scprintf(_SC("terminate from user\n"));
-                       break;
-               case MSG_ID('r','d'):
-                       scprintf(_SC("ready\n"));
-                       _ready=true;
-                       break;
-               default:
-                       scprintf(_SC("unknown packet"));
-
-       }
-}
-
-/*
-       see copyright notice in sqrdbg.h
-*/
-bool SQDbgServer::ParseBreakpoint(const char *msg,BreakPoint &out)
-{
-       static char stemp[MAX_BP_PATH];
-       char *ep=NULL;
-       out._line=strtoul(msg,&ep,16);
-       if(ep==msg || (*ep)!=':')return false;
-
-       char *dest=stemp;
-       ep++;
-       while((*ep)!='\n' && (*ep)!='\0')
-       {
-               *dest=*ep;
-               *dest++;*ep++;
-       }
-       *dest='\0';
-       *dest++;
-       *dest='\0';
-#ifdef _UNICODE
-       int len=(int)strlen(stemp);
-       SQChar *p=sq_getscratchpad(_v,(SQInteger)(mbstowcs(NULL,stemp,len)+2)*sizeof(SQChar));
-       size_t destlen=mbstowcs(p,stemp,len);
-       p[destlen]=_SC('\0');
-       out._src=p;
-#else
-       out._src=stemp;
-#endif
-       return true;
-}
-
-bool SQDbgServer::ParseWatch(const char *msg,Watch &out)
-{
-       char *ep=NULL;
-       out._id=strtoul(msg,&ep,16);
-       if(ep==msg || (*ep)!=':')return false;
-
-       //char *dest=out._src;
-       ep++;
-       while((*ep)!='\n' && (*ep)!='\0')
-       {
-               out._exp.append(1,*ep);
-               *ep++;
-       }
-       return true;
-}
-
-bool SQDbgServer::ParseRemoveWatch(const char *msg,int &id)
-{
-       char *ep=NULL;
-       id=strtoul(msg,&ep,16);
-       if(ep==msg)return false;
-       return true;
-}
-
-
-void SQDbgServer::BreakExecution()
-{
-       _state=eDBG_Suspended;
-       while(_state==eDBG_Suspended){
-               if(SQ_FAILED(sq_rdbg_update(this)))
-                       exit(0);
-               usleep(10);
-       }
-}
-
-//COMMANDS
-void SQDbgServer::AddBreakpoint(BreakPoint &bp)
-{
-       _breakpoints.insert(bp);
-       BeginDocument();
-               BeginElement(_SC("addbreakpoint"));
-                       Attribute(_SC("line"),IntToString(bp._line));
-                       Attribute(_SC("src"),bp._src.c_str());
-               EndElement(_SC("addbreakpoint"));
-       EndDocument();
-}
-
-void SQDbgServer::AddWatch(Watch &w)
-{
-       _watches.insert(w);
-}
-
-void SQDbgServer::RemoveWatch(int id)
-{
-       WatchSetItor itor=_watches.find(Watch(id,_SC("")));
-       if(itor==_watches.end()){
-               BeginDocument();
-               BeginElement(_SC("error"));
-                       Attribute(_SC("desc"),_SC("the watch does not exists"));
-               EndElement(_SC("error"));
-       EndDocument();
-       }
-       else{
-               _watches.erase(itor);
-               scprintf(_SC("removed watch %d\n"),id);
-       }
-}
-
-void SQDbgServer::RemoveBreakpoint(BreakPoint &bp)
-{
-       BreakPointSetItor itor=_breakpoints.find(bp);
-       if(itor==_breakpoints.end()){
-               BeginDocument();
-                       BeginElement(_SC("break"));
-                               Attribute(_SC("desc"),_SC("the breakpoint doesn't exists"));
-                       EndElement(_SC("break"));
-               EndDocument();
-       }
-       else{
-               BeginDocument();
-                       BeginElement(_SC("removebreakpoint"));
-                               Attribute(_SC("line"),IntToString(bp._line));
-                               Attribute(_SC("src"),bp._src.c_str());
-                       EndElement(_SC("removebreakpoint"));
-               EndDocument();
-               _breakpoints.erase(itor);
-       }
-}
-
-void SQDbgServer::Break(int line,const SQChar *src,const SQChar *type,const SQChar *error)
-{
-       if(!error){
-               BeginDocument();
-                       BeginElement(_SC("break"));
-                               Attribute(_SC("line"),IntToString(line));
-                               Attribute(_SC("src"),src);
-                               Attribute(_SC("type"),type);
-                               SerializeState();
-                       EndElement(_SC("break"));
-               EndDocument();
-       }else{
-               BeginDocument();
-                       BeginElement(_SC("break"));
-                               Attribute(_SC("line"),IntToString(line));
-                               Attribute(_SC("src"),src);
-                               Attribute(_SC("type"),type);
-                               Attribute(_SC("error"),error);
-                               SerializeState();
-                       EndElement(_SC("break"));
-               EndDocument();
-       }
-}
-
-void SQDbgServer::SerializeState()
-{
-       sq_pushnull(_v);
-       sq_setdebughook(_v);
-       sq_pushnull(_v);
-       sq_seterrorhandler(_v);
-       const SQChar *sz;
-       sq_pushobject(_v,_serializefunc);
-       sq_pushobject(_v,_debugroot);
-       sq_pushstring(_v,_SC("watches"),-1);
-       sq_newtable(_v);
-       for(WatchSetItor i=_watches.begin(); i!=_watches.end(); ++i)
-       {
-               sq_pushinteger(_v,i->_id);
-               sq_pushstring(_v,i->_exp.c_str(),(int)i->_exp.length());
-               sq_createslot(_v,-3);
-       }
-       sq_rawset(_v,-3);
-       if(SQ_SUCCEEDED(sq_call(_v,1,SQTrue,SQTrue))){
-               if(SQ_SUCCEEDED(sqstd_getblob(_v,-1,(SQUserPointer*)&sz)))
-                       SendChunk(sz);
-       }
-       sq_pop(_v,2);
-
-       SetErrorHandlers();
-}
-
-
-void SQDbgServer::SetErrorHandlers()
-{
-       sq_pushregistrytable(_v);
-       sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);
-       sq_rawget(_v,-2);
-       sq_setdebughook(_v);
-       sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1);
-       sq_rawget(_v,-2);
-       sq_seterrorhandler(_v);
-       sq_pop(_v,1);
-}
-
-void SQDbgServer::BeginElement(const SQChar *name)
-{
-       _xmlcurrentement++;
-       XMLElementState *self = &xmlstate[_xmlcurrentement];
-       scstrcpy(self->name,name);
-       self->haschildren = false;
-       if(_xmlcurrentement > 0) {
-               XMLElementState *parent = &xmlstate[_xmlcurrentement-1];
-               if(!parent->haschildren) {
-                       SendChunk(_SC(">")); // closes the parent tag
-                       parent->haschildren = true;
-               }
-       }
-       _scratchstring.resize(2+scstrlen(name));
-       scsprintf(&_scratchstring[0],_SC("<%s"),name);
-       SendChunk(&_scratchstring[0]);
-}
-
-void SQDbgServer::Attribute(const SQChar *name,const SQChar *value)
-{
-       XMLElementState *self = &xmlstate[_xmlcurrentement];
-       assert(!self->haschildren); //cannot have attributes if already has children
-       const SQChar *escval = escape_xml(value);
-       _scratchstring.resize(5+scstrlen(name)+scstrlen(escval));
-       scsprintf(&_scratchstring[0],_SC(" %s=\"%s\""),name,escval);
-       SendChunk(&_scratchstring[0]);
-}
-
-void SQDbgServer::EndElement(const SQChar *name)
-{
-       XMLElementState *self = &xmlstate[_xmlcurrentement];
-       assert(scstrcmp(self->name,name) == 0);
-       if(self->haschildren) {
-               _scratchstring.resize(4+scstrlen(name));
-               scsprintf(&_scratchstring[0],_SC("</%s>"),name);
-               SendChunk(&_scratchstring[0]);
-
-       }
-       else {
-               SendChunk(_SC("/>"));
-       }
-       _xmlcurrentement--;
-}
-
-void SQDbgServer::EndDocument()
-{
-       SendChunk(_SC("\r\n"));
-}
-
-//this can be done much better/faster(do we need that?)
-const SQChar *SQDbgServer::escape_xml(const SQChar *s)
-{
-       SQChar *temp=sq_getscratchpad(_v,((int)scstrlen(s)*6) + sizeof(SQChar));
-       SQChar *dest=temp;
-       while(*s!=_SC('\0')){
-               int i=0;
-               bool escaped=false;
-               while(g_escapes[i].esc!=NULL){
-                       if(*s==g_escapes[i].c){
-                               scstrcpy(dest,g_escapes[i].esc);
-                               dest+=scstrlen(g_escapes[i].esc);
-                               escaped=true;
-                               break;
-                       }
-                       i++;
-               }
-               if(!escaped){*dest=*s;*dest++;}
-               *s++;
-       }
-       *dest=_SC('\0');
-       return temp;
-
-}
+#include <squirrel.h>\r
+#include <assert.h>\r
+#include <sqstdblob.h>\r
+#include "sqrdbg.h"\r
+#include "sqdbgserver.h"\r
+\r
+\r
+#ifndef _UNICODE\r
+#define scstrcpy strcpy\r
+#else\r
+#define scstrcpy wcscpy\r
+#endif\r
+struct XMLEscape{\r
+       const SQChar c;\r
+       const SQChar *esc;\r
+};\r
+\r
+#define SQDBG_DEBUG_HOOK _SC("_sqdbg_debug_hook_")\r
+#define SQDBG_ERROR_HANDLER _SC("_sqdbg_error_handler_")\r
+\r
+XMLEscape g_escapes[]={\r
+       {_SC('<'),_SC("&lt;")},{'>',_SC("&gt;")},{_SC('&'),_SC("&amp;")},{_SC('\''),_SC("&apos;")},{_SC('\"'),_SC("&quot;")},{_SC('\n'),_SC("&quot;n")},{_SC('\r'),_SC("&quot;r")},{NULL,NULL}\r
+};\r
+\r
+const SQChar *IntToString(SQInteger n)\r
+{\r
+       static SQChar temp[256];\r
+       scsprintf(temp,_SC("%d"),n);\r
+       return temp;\r
+}\r
+\r
+const SQChar *PtrToString(void *p)\r
+{\r
+       static SQChar temp[256];\r
+       scsprintf(temp,_SC("%p"),p);\r
+       return temp;\r
+}\r
+\r
+SQInteger debug_hook(HSQUIRRELVM v);\r
+SQInteger error_handler(HSQUIRRELVM v);\r
+\r
+SQInteger beginelement(HSQUIRRELVM v)\r
+{\r
+       SQUserPointer up;\r
+       const SQChar *name;\r
+       sq_getuserpointer(v,-1,&up);\r
+       SQDbgServer *self = (SQDbgServer*)up;\r
+       sq_getuserpointer(v,-1,&up);\r
+       sq_getstring(v,2,&name);\r
+       self->BeginElement(name);\r
+       return 0;\r
+}\r
+\r
+SQInteger endelement(HSQUIRRELVM v)\r
+{\r
+       SQUserPointer up;\r
+       const SQChar *name;\r
+       sq_getuserpointer(v,-1,&up);\r
+       SQDbgServer *self = (SQDbgServer*)up;\r
+       sq_getuserpointer(v,-1,&up);\r
+       sq_getstring(v,2,&name);\r
+       self->EndElement(name);\r
+       return 0;\r
+}\r
+\r
+SQInteger attribute(HSQUIRRELVM v)\r
+{\r
+       SQUserPointer up;\r
+       const SQChar *name,*value;\r
+       sq_getuserpointer(v,-1,&up);\r
+       SQDbgServer *self = (SQDbgServer*)up;\r
+       sq_getuserpointer(v,-1,&up);\r
+       sq_getstring(v,2,&name);\r
+       sq_getstring(v,3,&value);\r
+       self->Attribute(name,value);\r
+       return 0;\r
+}\r
+\r
+SQDbgServer::SQDbgServer(HSQUIRRELVM v)\r
+{\r
+       _ready = false;\r
+       //_nestedcalls = 0;\r
+       _autoupdate = false;\r
+       _v = v;\r
+       _state = eDBG_Running;\r
+       _accept = INVALID_SOCKET;\r
+       _endpoint = INVALID_SOCKET;\r
+       //_maxrecursion = 10;\r
+       sq_resetobject(&_debugroot);\r
+}\r
+\r
+SQDbgServer::~SQDbgServer()\r
+{\r
+       VMStateMap::iterator itr = _vmstate.begin();\r
+       while(itr != _vmstate.end()) {\r
+               VMState *vs = itr->second;\r
+               delete vs;\r
+               ++itr;\r
+       }\r
+       _vmstate.clear();\r
+       sq_pushobject(_v,_debugroot);\r
+       sq_clear(_v,-1);\r
+       sq_release(_v,&_debugroot);\r
+       if(_accept != INVALID_SOCKET)\r
+               sqdbg_closesocket(_accept);\r
+       if(_endpoint != INVALID_SOCKET)\r
+               sqdbg_closesocket(_endpoint);\r
+}\r
+\r
+bool SQDbgServer::Init()\r
+{\r
+       //creates  an environment table for the debugger\r
+       \r
+       sq_newtable(_v);\r
+       sq_getstackobj(_v,-1,&_debugroot);\r
+       sq_addref(_v,&_debugroot);\r
+\r
+       //creates a emptyslot to store the watches\r
+       sq_pushstring(_v,_SC("watches"),-1);\r
+       sq_pushnull(_v);\r
+       sq_newslot(_v,-3, SQFalse);\r
+\r
+       sq_pushstring(_v,_SC("beginelement"),-1);\r
+       sq_pushuserpointer(_v,this);\r
+       sq_newclosure(_v,beginelement,1);\r
+       sq_setparamscheck(_v,2,_SC(".s"));\r
+       sq_newslot(_v,-3, SQFalse);\r
+\r
+       sq_pushstring(_v,_SC("endelement"),-1);\r
+       sq_pushuserpointer(_v,this);\r
+       sq_newclosure(_v,endelement,1);\r
+       sq_setparamscheck(_v,2,_SC(".s"));\r
+       sq_newslot(_v,-3, SQFalse);\r
+\r
+       sq_pushstring(_v,_SC("attribute"),-1);\r
+       sq_pushuserpointer(_v,this);\r
+       sq_newclosure(_v,attribute,1);\r
+       sq_setparamscheck(_v,3,_SC(".ss"));\r
+       sq_newslot(_v,-3, SQFalse);\r
+\r
+       sq_pop(_v,1);\r
+\r
+       //stores debug hook and error handler in the registry\r
+       sq_pushregistrytable(_v);\r
+\r
+       sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);\r
+       sq_pushuserpointer(_v,this);\r
+       sq_newclosure(_v,debug_hook,1);\r
+       sq_newslot(_v,-3, SQFalse);\r
+       \r
+       sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1);\r
+       sq_pushuserpointer(_v,this);\r
+       sq_newclosure(_v,error_handler,1);\r
+       sq_newslot(_v,-3, SQFalse);\r
+\r
+       \r
+       sq_pop(_v,1);\r
+\r
+       //sets the error handlers\r
+       SetErrorHandlers(_v);\r
+       return true;\r
+}\r
+\r
+bool SQDbgServer::ReadMsg()\r
+{\r
+       return false;\r
+}\r
+\r
+void SQDbgServer::BusyWait()\r
+{\r
+       while( !ReadMsg() )\r
+               Sleep(0);\r
+}\r
+\r
+\r
+\r
+void SQDbgServer::SendChunk(const SQChar *chunk)\r
+{\r
+       char *buf=NULL;\r
+       int buf_len=0;\r
+#ifdef _UNICODE\r
+       buf_len=(int)scstrlen(chunk)+1;\r
+       buf=(char *)sq_getscratchpad(_v,(buf_len)*3);\r
+       //wcstombs((char *)buf,chunk,buf_len*3);\r
+       WideCharToMultiByte(CP_UTF8,0,chunk,-1,buf,buf_len*3,NULL,NULL);\r
+#else\r
+       buf_len=(int)scstrlen(chunk);\r
+       buf=(char *)chunk;\r
+#endif\r
+       send(_endpoint,(const char*)buf,(int)strlen((const char *)buf),0);\r
+}\r
+\r
+\r
+void SQDbgServer::Terminated()\r
+{\r
+       BeginElement(_SC("terminated"));\r
+       EndElement(_SC("terminated"));\r
+       ::Sleep(200);\r
+}\r
+\r
+VMState *SQDbgServer::GetVMState(HSQUIRRELVM v)\r
+{\r
+       VMState *ret = NULL;\r
+       VMStateMap::iterator itr = _vmstate.find(v);\r
+       if(itr == _vmstate.end()) {\r
+               ret = new VMState();\r
+               _vmstate.insert(VMStateMap::value_type(v,ret));\r
+       }\r
+       else {\r
+               ret = itr->second;\r
+       }\r
+       return ret;\r
+}\r
+\r
+void SQDbgServer::Hook(HSQUIRRELVM v,SQInteger type,SQInteger line,const SQChar *src,const SQChar *func)\r
+{\r
+       \r
+       VMState *vs = GetVMState(v);\r
+       switch(_state){\r
+       case eDBG_Running:\r
+               if(type==_SC('l') && _breakpoints.size()) {\r
+                       BreakPointSetItor itr = _breakpoints.find(BreakPoint(line,src));\r
+                       if(itr != _breakpoints.end()) {\r
+                               Break(v,line,src,_SC("breakpoint"));\r
+                               BreakExecution();\r
+                       }\r
+               }\r
+               break;\r
+       case eDBG_Suspended:\r
+               vs->_nestedcalls=0;\r
+       case eDBG_StepOver:\r
+               switch(type){\r
+               case _SC('l'):\r
+                       if(vs->_nestedcalls==0) {\r
+                               Break(v,line,src,_SC("step"));\r
+                               BreakExecution();\r
+                       }\r
+                       break;\r
+               case _SC('c'):\r
+                       vs->_nestedcalls++;\r
+                       break;\r
+               case _SC('r'):\r
+                       if(vs->_nestedcalls==0){\r
+                               vs->_nestedcalls=0;\r
+                               \r
+                       }else{\r
+                               vs->_nestedcalls--;\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       case eDBG_StepInto:\r
+               switch(type){\r
+               case _SC('l'):\r
+                       vs->_nestedcalls=0;\r
+                       Break(v,line,src,_SC("step"));\r
+                       BreakExecution();\r
+                       break;\r
+               \r
+               }\r
+               break;\r
+       case eDBG_StepReturn:\r
+               switch(type){\r
+               case _SC('l'):\r
+                       break;\r
+               case _SC('c'):\r
+                       vs->_nestedcalls++;\r
+                       break;\r
+               case _SC('r'):\r
+                       if(vs->_nestedcalls==0){\r
+                               vs->_nestedcalls=0;\r
+                               _state=eDBG_StepOver;\r
+                       }else{\r
+                               vs->_nestedcalls--;\r
+                       }\r
+                       \r
+                       break;\r
+               }\r
+               break;\r
+       case eDBG_Disabled:\r
+               break;\r
+       }\r
+}\r
+\r
+\r
+#define MSG_ID(x,y) ((y<<8)|x)\r
+//ab Add Breakpoint\r
+//rb Remove Breakpoint\r
+//sp Suspend\r
+void SQDbgServer::ParseMsg(const char *msg)\r
+{\r
+       \r
+       switch(*((unsigned short *)msg)){\r
+               case MSG_ID('a','b'): {\r
+                       BreakPoint bp;\r
+                       if(ParseBreakpoint(msg+3,bp)){\r
+                               AddBreakpoint(bp);\r
+                               scprintf(_SC("added bp %d %s\n"),bp._line,bp._src.c_str());\r
+                       }\r
+                       else\r
+                               scprintf(_SC("error parsing add breakpoint"));\r
+                                                        }\r
+                       break;\r
+               case MSG_ID('r','b'): {\r
+                       BreakPoint bp;\r
+                       if(ParseBreakpoint(msg+3,bp)){\r
+                               RemoveBreakpoint(bp);\r
+                               scprintf(_SC("removed bp %d %s\n"),bp._line,bp._src.c_str());\r
+                       }else\r
+                               scprintf(_SC("error parsing remove breakpoint"));\r
+                                                       }\r
+                       break;\r
+               case MSG_ID('g','o'):\r
+                       if(_state!=eDBG_Running){\r
+                               _state=eDBG_Running;\r
+                               BeginDocument();\r
+                                       BeginElement(_SC("resumed"));\r
+                                       EndElement(_SC("resumed"));\r
+                               EndDocument();\r
+//                             Send(_SC("<resumed/>\r\n"));\r
+                               scprintf(_SC("go (execution resumed)\n"));\r
+                       }\r
+                       break;\r
+               case MSG_ID('s','p'):\r
+                       if(_state!=eDBG_Suspended){\r
+                               _state=eDBG_Suspended;\r
+                               scprintf(_SC("suspend\n"));\r
+                       }\r
+                       break;\r
+               case MSG_ID('s','o'):\r
+                       if(_state==eDBG_Suspended){\r
+                               _state=eDBG_StepOver;\r
+                       }\r
+                       break;\r
+               case MSG_ID('s','i'):\r
+                       if(_state==eDBG_Suspended){\r
+                               _state=eDBG_StepInto;\r
+                               scprintf(_SC("step into\n"));\r
+                       }\r
+                       break;\r
+               case MSG_ID('s','r'):\r
+                       if(_state==eDBG_Suspended){\r
+                               _state=eDBG_StepReturn;\r
+                               scprintf(_SC("step return\n"));\r
+                       }\r
+                       break;\r
+               case MSG_ID('d','i'):\r
+                       if(_state!=eDBG_Disabled){\r
+                               _state=eDBG_Disabled;\r
+                               scprintf(_SC("disabled\n"));\r
+                       }\r
+                       break;\r
+               case MSG_ID('a','w'): {\r
+                       Watch w;\r
+                       if(ParseWatch(msg+3,w))\r
+                       {\r
+                               AddWatch(w);\r
+                               scprintf(_SC("added watch %d %s\n"),w._id,w._exp.c_str());\r
+                               /*if(_state == eDBG_Suspended) {\r
+                                       Break(_line,_src.c_str(),_break_type.c_str());\r
+                               }*/\r
+                       }\r
+                       else\r
+                               scprintf(_SC("error parsing add watch"));\r
+                                                               }\r
+                       break;\r
+               case MSG_ID('r','w'): {\r
+                       SQInteger id;\r
+                       if(ParseRemoveWatch(msg+3,id))\r
+                       {\r
+                               RemoveWatch(id);\r
+                               scprintf(_SC("added watch %d\n"),id);\r
+                       }\r
+                       else\r
+                               scprintf(_SC("error parsing remove watch"));\r
+                                                               }\r
+                       break;\r
+               case MSG_ID('t','r'):\r
+                       scprintf(_SC("terminate from user\n"));\r
+                       break;\r
+               case MSG_ID('r','d'):\r
+                       scprintf(_SC("ready\n"));\r
+                       _ready=true;\r
+                       break;\r
+               default:\r
+                       scprintf(_SC("unknown packet"));\r
+\r
+       }\r
+}\r
+\r
+bool SQDbgServer::ParseBreakpoint(const char *msg,BreakPoint &out)\r
+{\r
+       static char stemp[MAX_BP_PATH];\r
+       static SQChar desttemp[MAX_BP_PATH];\r
+       char *ep=NULL;\r
+       out._line=strtoul(msg,&ep,16);\r
+       if(ep==msg || (*ep)!=':')return false;\r
+       \r
+       char *dest=stemp;\r
+       ep++;\r
+       while((*ep)!='\n' && (*ep)!='\0')\r
+       {\r
+               *dest=tolower(*ep);\r
+               *dest++;*ep++;\r
+       }\r
+       *dest='\0';\r
+       *dest++;\r
+       *dest='\0';\r
+#ifdef _UNICODE\r
+       int len=(int)strlen(stemp);\r
+       SQChar *p = desttemp;\r
+       size_t destlen = mbstowcs(p,stemp,len);\r
+       p[destlen]=_SC('\0');\r
+       out._src=p;\r
+#else\r
+       out._src=stemp;\r
+#endif\r
+       return true;\r
+}\r
+\r
+bool SQDbgServer::ParseWatch(const char *msg,Watch &out)\r
+{\r
+       char *ep=NULL;\r
+       out._id=strtoul(msg,&ep,16);\r
+       if(ep==msg || (*ep)!=':')return false;\r
+\r
+       //char *dest=out._src;\r
+       ep++;\r
+       while((*ep)!='\n' && (*ep)!='\0')\r
+       {\r
+               out._exp.append(1,*ep);\r
+               *ep++;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SQDbgServer::ParseRemoveWatch(const char *msg,SQInteger &id)\r
+{\r
+       char *ep=NULL;\r
+       id=strtoul(msg,&ep,16);\r
+       if(ep==msg)return false;\r
+       return true;\r
+}\r
+\r
+\r
+void SQDbgServer::BreakExecution()\r
+{\r
+       _state=eDBG_Suspended;\r
+       while(_state==eDBG_Suspended){\r
+               if(SQ_FAILED(sq_rdbg_update(this)))\r
+                       exit(0);\r
+               Sleep(10);\r
+       }\r
+}\r
+\r
+//COMMANDS\r
+void SQDbgServer::AddBreakpoint(BreakPoint &bp)\r
+{\r
+       _breakpoints.insert(bp);\r
+       BeginDocument();\r
+               BeginElement(_SC("addbreakpoint"));\r
+                       Attribute(_SC("line"),IntToString(bp._line));\r
+                       Attribute(_SC("src"),bp._src.c_str());\r
+               EndElement(_SC("addbreakpoint"));\r
+       EndDocument();\r
+}\r
+\r
+void SQDbgServer::AddWatch(Watch &w)\r
+{\r
+       _watches.insert(w);\r
+}\r
+\r
+void SQDbgServer::RemoveWatch(SQInteger id)\r
+{\r
+       WatchSetItor itor=_watches.find(Watch(id,_SC("")));\r
+       if(itor==_watches.end()){\r
+               BeginDocument();\r
+               BeginElement(_SC("error"));\r
+                       Attribute(_SC("desc"),_SC("the watch does not exists"));\r
+               EndElement(_SC("error"));\r
+       EndDocument();\r
+       }\r
+       else{\r
+               _watches.erase(itor);\r
+               scprintf(_SC("removed watch %d\n"),id);\r
+       }\r
+}\r
+\r
+void SQDbgServer::RemoveBreakpoint(BreakPoint &bp)\r
+{\r
+       BreakPointSetItor itor=_breakpoints.find(bp);\r
+       if(itor==_breakpoints.end()){\r
+               BeginDocument();\r
+                       BeginElement(_SC("break"));\r
+                               Attribute(_SC("desc"),_SC("the breakpoint doesn't exists"));\r
+                       EndElement(_SC("break"));\r
+               EndDocument();\r
+       }\r
+       else{\r
+               BeginDocument();\r
+                       BeginElement(_SC("removebreakpoint"));\r
+                               Attribute(_SC("line"),IntToString(bp._line));\r
+                               Attribute(_SC("src"),bp._src.c_str());\r
+                       EndElement(_SC("removebreakpoint"));\r
+               EndDocument();\r
+               _breakpoints.erase(itor);\r
+       }\r
+}\r
+\r
+void SQDbgServer::Break(HSQUIRRELVM v,SQInteger line,const SQChar *src,const SQChar *type,const SQChar *error)\r
+{\r
+       _line = line;\r
+       _src = src;\r
+       _break_type = src;\r
+       if(!error){\r
+               BeginDocument();\r
+                       BeginElement(_SC("break"));\r
+                               Attribute(_SC("thread"),PtrToString(v));\r
+                               Attribute(_SC("line"),IntToString(line));\r
+                               Attribute(_SC("src"),src);\r
+                               Attribute(_SC("type"),type);\r
+                               SerializeState(v);\r
+                       EndElement(_SC("break"));\r
+               EndDocument();\r
+       }else{\r
+               BeginDocument();\r
+                       BeginElement(_SC("break"));\r
+                               Attribute(_SC("thread"),PtrToString(v));\r
+                               Attribute(_SC("line"),IntToString(line));\r
+                               Attribute(_SC("src"),src);\r
+                               Attribute(_SC("type"),type);\r
+                               Attribute(_SC("error"),error);\r
+                               SerializeState(v);\r
+                       EndElement(_SC("break"));\r
+               EndDocument();\r
+       }\r
+}\r
+\r
+void SQDbgServer::SerializeState(HSQUIRRELVM v)\r
+{\r
+       sq_pushnull(v);\r
+       sq_setdebughook(v);\r
+       sq_pushnull(v);\r
+       sq_seterrorhandler(v);\r
+       sq_pushobject(v,_serializefunc);\r
+       sq_pushobject(v,_debugroot);\r
+       sq_pushstring(v,_SC("watches"),-1);\r
+       sq_newtable(v);\r
+       for(WatchSetItor i=_watches.begin(); i!=_watches.end(); ++i)\r
+       {\r
+               sq_pushinteger(v,i->_id);\r
+               sq_pushstring(v,i->_exp.c_str(),(SQInteger)i->_exp.length());\r
+               sq_createslot(v,-3);\r
+       }\r
+       sq_rawset(v,-3);\r
+       if(SQ_SUCCEEDED(sq_call(v,1,SQTrue,SQFalse))){\r
+               //if(SQ_SUCCEEDED(sqstd_getblob(v,-1,(SQUserPointer*)&sz)))\r
+                       //SendChunk(sz);\r
+       }\r
+       sq_pop(v,2);\r
+       \r
+       SetErrorHandlers(v);\r
+}\r
+\r
+\r
+void SQDbgServer::SetErrorHandlers(HSQUIRRELVM v)\r
+{\r
+       sq_pushregistrytable(v);\r
+       sq_pushstring(v,SQDBG_DEBUG_HOOK,-1);\r
+       sq_rawget(v,-2);\r
+       sq_setdebughook(v);\r
+       sq_pushstring(v,SQDBG_ERROR_HANDLER,-1);\r
+       sq_rawget(v,-2);\r
+       sq_seterrorhandler(v);\r
+       sq_pop(v,1);\r
+}\r
+\r
+void SQDbgServer::BeginDocument()\r
+{ \r
+       _xmlcurrentement = -1; \r
+       SendChunk(_SC("<?xml version='1.0' encoding='utf-8'?>"));\r
+}\r
+\r
+void SQDbgServer::BeginElement(const SQChar *name)\r
+{\r
+       _xmlcurrentement++;\r
+       XMLElementState *self = &xmlstate[_xmlcurrentement];\r
+       scstrcpy(self->name,name);\r
+       self->haschildren = false;\r
+       if(_xmlcurrentement > 0) {\r
+               XMLElementState *parent = &xmlstate[_xmlcurrentement-1];\r
+               if(!parent->haschildren) {\r
+                       SendChunk(_SC(">")); // closes the parent tag\r
+                       parent->haschildren = true;\r
+               }\r
+       }\r
+       _scratchstring.resize(2+scstrlen(name));\r
+       scsprintf(&_scratchstring[0],_SC("<%s"),name);\r
+       SendChunk(&_scratchstring[0]);\r
+}\r
+\r
+void SQDbgServer::Attribute(const SQChar *name,const SQChar *value)\r
+{\r
+       XMLElementState *self = &xmlstate[_xmlcurrentement];\r
+       assert(!self->haschildren); //cannot have attributes if already has children\r
+       const SQChar *escval = escape_xml(value);\r
+       _scratchstring.resize(10+scstrlen(name)+scstrlen(escval));\r
+       scsprintf(&_scratchstring[0],_SC(" %s=\"%s\""),name,escval);\r
+       SendChunk(&_scratchstring[0]);\r
+}\r
+\r
+void SQDbgServer::EndElement(const SQChar *name)\r
+{\r
+       XMLElementState *self = &xmlstate[_xmlcurrentement];\r
+       assert(scstrcmp(self->name,name) == 0);\r
+       if(self->haschildren) {\r
+               _scratchstring.resize(10+scstrlen(name));\r
+               scsprintf(&_scratchstring[0],_SC("</%s>"),name);\r
+               SendChunk(&_scratchstring[0]);\r
+               \r
+       }\r
+       else {\r
+               SendChunk(_SC("/>"));\r
+       }\r
+       _xmlcurrentement--;\r
+}\r
+\r
+void SQDbgServer::EndDocument()\r
+{\r
+       SendChunk(_SC("\r\n"));\r
+}\r
+\r
+//this can be done much better/faster(do we need that?)\r
+const SQChar *SQDbgServer::escape_xml(const SQChar *s)\r
+{\r
+       SQChar *temp=sq_getscratchpad(_v,((SQInteger)scstrlen(s)*6) + sizeof SQChar);\r
+       SQChar *dest=temp;\r
+       while(*s!=_SC('\0')){\r
+               \r
+               const SQChar *escape = NULL;\r
+               switch(*s) {\r
+                       case _SC('<'): escape = _SC("&lt;"); break;\r
+                       case _SC('>'): escape = _SC("&gt;"); break;\r
+                       case _SC('&'): escape = _SC("&amp;"); break;\r
+                       case _SC('\''): escape = _SC("&apos;"); break;\r
+                       case _SC('\"'): escape = _SC("&quot;"); break;\r
+                       case _SC('\n'): escape = _SC("\\n"); break;\r
+                       case _SC('\r'): escape = _SC("\\r"); break;\r
+               }\r
+               if(escape) {\r
+                       scstrcpy(dest,escape);\r
+                       dest += scstrlen(escape);\r
+               }\r
+               else {\r
+                       *dest=*s;*dest++;\r
+               }\r
+               *s++;\r
+       }\r
+       *dest=_SC('\0');\r
+       return temp;\r
+       \r
+}
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index 4d91192..272fce3
-#ifndef _SQ_DBGSERVER_H_
-#define _SQ_DBGSERVER_H_
-
-#define MAX_BP_PATH 512
-#define MAX_MSG_LEN 2049
-
-#include <set>
-#include <string>
-#include <vector>
-
-#ifdef _WIN32
-#include <winsock.h>
-#define sqdbg_closesocket(x) closesocket((x))
-typedef socklen_t int;
-#else
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <fcntl.h>
-
-#define sqdbg_closesocket(x) close((x))
-typedef int SOCKET;
-typedef struct timeval TIMEVAL;
-#define SOCKET_ERROR -1
-#define INVALID_SOCKET -1
-#endif
-
-typedef std::basic_string<SQChar> SQDBGString;
-
-inline bool dbg_less(const SQChar *x,const SQChar *y)
-{
-       // [SuperTux] commented out to avoid compiler warning
-       //int n = 0;
-       do {
-               int xl = *x == '\\' ? '/' : tolower(*x);
-               int yl = *y == '\\' ? '/' : tolower(*y);
-               int diff = xl - yl;
-               if(diff != 0)
-                       return diff > 0?true:false;
-               x++; y++;
-       }while(*x != 0 && *y != 0);
-       return false;
-}
-
-struct BreakPoint{
-       BreakPoint(){_line=0;}
-       BreakPoint(int line, const SQChar *src){ _line = line; _src = src; }
-       BreakPoint(const BreakPoint& bp){ _line = bp._line; _src=bp._src; }
-       inline bool operator<(const BreakPoint& bp) const
-       {
-               if(_line<bp._line)
-                       return true;
-               if(_line==bp._line){
-                       return dbg_less(_src.c_str(),bp._src.c_str());
-               }
-               return false;
-       }
-
-       int _line;
-       SQDBGString _src;
-};
-
-struct Watch{
-       Watch() { _id = 0; }
-       Watch(int id,const SQChar *exp) { _id = id; _exp = exp; }
-       Watch(const Watch &w) { _id = w._id; _exp = w._exp; }
-       bool operator<(const Watch& w) const { return _id<w._id; }
-       bool operator==(const Watch& w) const { return _id == w._id; }
-       int _id;
-       SQDBGString _exp;
-};
-
-typedef std::set<BreakPoint> BreakPointSet;
-typedef BreakPointSet::iterator BreakPointSetItor;
-
-typedef std::set<Watch> WatchSet;
-typedef WatchSet::iterator WatchSetItor;
-
-typedef std::vector<SQChar> SQCharVec;
-struct SQDbgServer{
-public:
-       enum eDbgState{
-               eDBG_Running,
-               eDBG_StepOver,
-               eDBG_StepInto,
-               eDBG_StepReturn,
-               eDBG_Suspended,
-               eDBG_Disabled,
-       };
-
-       SQDbgServer(HSQUIRRELVM v);
-       ~SQDbgServer();
-       bool Init();
-       //returns true if a message has been received
-       bool WaitForClient();
-       bool ReadMsg();
-       void BusyWait();
-       void Hook(int type,int line,const SQChar *src,const SQChar *func);
-       void ParseMsg(const char *msg);
-       bool ParseBreakpoint(const char *msg,BreakPoint &out);
-       bool ParseWatch(const char *msg,Watch &out);
-       bool ParseRemoveWatch(const char *msg,int &id);
-       void Terminated();
-       //
-       void BreakExecution();
-       void Send(const SQChar *s,...);
-       void SendChunk(const SQChar *chunk);
-       void Break(int line,const SQChar *src,const SQChar *type,const SQChar *error=NULL);
-
-
-       void SerializeState();
-       //COMMANDS
-       void AddBreakpoint(BreakPoint &bp);
-       void AddWatch(Watch &w);
-       void RemoveWatch(int id);
-       void RemoveBreakpoint(BreakPoint &bp);
-
-       //
-       void SetErrorHandlers();
-
-       //XML RELATED STUFF///////////////////////
-       #define MAX_NESTING 10
-       struct XMLElementState {
-               SQChar name[256];
-               bool haschildren;
-       };
-
-       XMLElementState xmlstate[MAX_NESTING];
-       int _xmlcurrentement;
-
-       void BeginDocument() { _xmlcurrentement = -1; }
-       void BeginElement(const SQChar *name);
-       void Attribute(const SQChar *name, const SQChar *value);
-       void EndElement(const SQChar *name);
-       void EndDocument();
-
-       const SQChar *escape_xml(const SQChar *x);
-       //////////////////////////////////////////////
-       HSQUIRRELVM _v;
-       HSQOBJECT _debugroot;
-       eDbgState _state;
-       SOCKET _accept;
-       SOCKET _endpoint;
-       BreakPointSet _breakpoints;
-       WatchSet _watches;
-       int _recursionlevel;
-       int _maxrecursion;
-       int _nestedcalls;
-       bool _ready;
-       bool _autoupdate;
-       HSQOBJECT _serializefunc;
-       SQCharVec _scratchstring;
-
-};
-
-#endif //_SQ_DBGSERVER_H_
+#ifndef _SQ_DBGSERVER_H_\r
+#define _SQ_DBGSERVER_H_\r
+\r
+#define MAX_BP_PATH 512\r
+#define MAX_MSG_LEN 2049\r
+\r
+#include <set>\r
+#include <map>\r
+#include <string>\r
+#include <vector>\r
+#include <winsock.h>\r
+\r
+typedef std::basic_string<SQChar> SQDBGString;\r
+\r
+struct BreakPoint{\r
+       BreakPoint(){_line=0;}\r
+       BreakPoint(SQInteger line, const SQChar *src){ _line = line; _src = src; }\r
+       BreakPoint(const BreakPoint& bp){ _line = bp._line; _src=bp._src; }\r
+       bool operator<(const BreakPoint& bp) const\r
+       {\r
+               if(_line<bp._line)\r
+                       return true;\r
+               if(_line==bp._line){\r
+                       if(_src<bp._src){\r
+                               return true;\r
+                       }\r
+                       return false;\r
+               }\r
+               return false;\r
+       }\r
+       bool operator==(const BreakPoint& other)\r
+       {\r
+               if(_line==other._line\r
+                       && (_src==other._src))\r
+                       return true;\r
+               return false;\r
+       }\r
+       SQInteger _line;\r
+       SQDBGString _src;\r
+};\r
+\r
+struct Watch{\r
+       Watch() { _id = 0; }\r
+       Watch(SQInteger id,const SQChar *exp) { _id = id; _exp = exp; }\r
+       Watch(const Watch &w) { _id = w._id; _exp = w._exp; }\r
+       bool operator<(const Watch& w) const { return _id<w._id; }\r
+       bool operator==(const Watch& w) const { return _id == w._id; }\r
+       SQInteger _id;\r
+       SQDBGString _exp;\r
+};\r
+\r
+struct VMState {\r
+       VMState() { _nestedcalls = 0;}\r
+       SQInteger _nestedcalls;\r
+};\r
+typedef std::map<HSQUIRRELVM,VMState*> VMStateMap;\r
+typedef std::set<BreakPoint> BreakPointSet;\r
+typedef BreakPointSet::iterator BreakPointSetItor;\r
+\r
+typedef std::set<Watch> WatchSet;\r
+typedef WatchSet::iterator WatchSetItor;\r
+\r
+typedef std::vector<SQChar> SQCharVec;\r
+struct SQDbgServer{\r
+public:\r
+       enum eDbgState{\r
+               eDBG_Running,\r
+               eDBG_StepOver,\r
+               eDBG_StepInto,\r
+               eDBG_StepReturn,\r
+               eDBG_Suspended,\r
+               eDBG_Disabled,\r
+       };\r
+\r
+       SQDbgServer(HSQUIRRELVM v);\r
+       ~SQDbgServer();\r
+       bool Init();\r
+       //returns true if a message has been received\r
+       bool WaitForClient();\r
+       bool ReadMsg();\r
+       void BusyWait();\r
+       void Hook(HSQUIRRELVM v,SQInteger type,SQInteger line,const SQChar *src,const SQChar *func);\r
+       void ParseMsg(const char *msg);\r
+       bool ParseBreakpoint(const char *msg,BreakPoint &out);\r
+       bool ParseWatch(const char *msg,Watch &out);\r
+       bool ParseRemoveWatch(const char *msg,SQInteger &id);\r
+       void Terminated();\r
+       //\r
+       void BreakExecution();\r
+       void Send(const SQChar *s,...);\r
+       void SendChunk(const SQChar *chunk);\r
+       void Break(HSQUIRRELVM v,SQInteger line,const SQChar *src,const SQChar *type,const SQChar *error=NULL);\r
+       \r
+\r
+       void SerializeState(HSQUIRRELVM v);\r
+       //COMMANDS\r
+       void AddBreakpoint(BreakPoint &bp);\r
+       void AddWatch(Watch &w);\r
+       void RemoveWatch(SQInteger id);\r
+       void RemoveBreakpoint(BreakPoint &bp);\r
+\r
+       //\r
+       void SetErrorHandlers(HSQUIRRELVM v);\r
+       VMState *GetVMState(HSQUIRRELVM v);\r
+\r
+       //XML RELATED STUFF///////////////////////\r
+       #define MAX_NESTING 10\r
+       struct XMLElementState {\r
+               SQChar name[256];\r
+               bool haschildren;\r
+       };\r
+\r
+       XMLElementState xmlstate[MAX_NESTING];\r
+       SQInteger _xmlcurrentement;\r
+\r
+       void BeginDocument();\r
+       void BeginElement(const SQChar *name);\r
+       void Attribute(const SQChar *name, const SQChar *value);\r
+       void EndElement(const SQChar *name);\r
+       void EndDocument();\r
+\r
+       const SQChar *escape_xml(const SQChar *x);\r
+       //////////////////////////////////////////////\r
+       HSQUIRRELVM _v;\r
+       HSQOBJECT _debugroot;\r
+       eDbgState _state;\r
+       SOCKET _accept;\r
+       SOCKET _endpoint;\r
+       BreakPointSet _breakpoints;\r
+       WatchSet _watches;\r
+       //int _recursionlevel; \r
+       //int _maxrecursion;\r
+       \r
+       bool _ready;\r
+       bool _autoupdate;\r
+       HSQOBJECT _serializefunc;\r
+       SQCharVec _scratchstring;\r
+\r
+       SQInteger _line;\r
+       SQDBGString _src;\r
+       SQDBGString _break_type;\r
+       VMStateMap _vmstate;    \r
+};\r
+\r
+#ifdef _WIN32\r
+#define sqdbg_closesocket(x) closesocket((x))\r
+#else\r
+#define sqdbg_closesocket(x) close((x))\r
+#endif\r
+\r
+#endif //_SQ_DBGSERVER_H_ 
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index 1a085cd..542b048
-/*
-       see copyright notice in sqrdbg.h
-*/
-#include <string.h>
-#include <stdio.h>
-#include <squirrel.h>
-#include "sqrdbg.h"
-#include "sqdbgserver.h"
-SQInteger debug_hook(HSQUIRRELVM v);
-SQInteger error_handler(HSQUIRRELVM v);
-
-#include "serialize_state.inl"
-
-HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate)
-{
-       sockaddr_in bindaddr;
-#ifdef _WIN32
-       WSADATA wsadata;
-       if (WSAStartup (MAKEWORD(1,1), &wsadata) != 0){
-               return NULL;
-       }
-#endif
-
-       SQDbgServer *rdbg = new SQDbgServer(v);
-       rdbg->_autoupdate = autoupdate?true:false;
-       rdbg->_accept = socket(AF_INET,SOCK_STREAM,0);
-       bindaddr.sin_family = AF_INET;
-       bindaddr.sin_port = htons(port);
-       bindaddr.sin_addr.s_addr = htonl (INADDR_ANY);
-       if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){
-               delete rdbg;
-               sq_throwerror(v,_SC("failed to bind the socket"));
-               return NULL;
-       }
-       if(!rdbg->Init()) {
-               delete rdbg;
-               sq_throwerror(v,_SC("failed to initialize the debugger"));
-               return NULL;
-       }
-
-    return rdbg;
-}
-
-SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg)
-{
-       if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) {
-               sq_throwerror(rdbg->_v,_SC("error compiling the serialization function"));
-       }
-       sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc);
-       sq_addref(rdbg->_v,&rdbg->_serializefunc);
-       sq_pop(rdbg->_v,1);
-
-       sockaddr_in cliaddr;
-       socklen_t addrlen=sizeof(cliaddr);
-       if(listen(rdbg->_accept,0)==SOCKET_ERROR)
-               return sq_throwerror(rdbg->_v,_SC("error on listen(socket)"));
-       rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,&addrlen);
-       //do not accept any other connection
-       sqdbg_closesocket(rdbg->_accept);
-       rdbg->_accept = INVALID_SOCKET;
-       if(rdbg->_endpoint==INVALID_SOCKET){
-               return sq_throwerror(rdbg->_v,_SC("error accept(socket)"));
-       }
-       while(!rdbg->_ready){
-               sq_rdbg_update(rdbg);
-       }
-       return SQ_OK;
-}
-
-SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg)
-{
-       TIMEVAL time;
-       time.tv_sec=0;
-       time.tv_usec=0;
-       fd_set read_flags;
-    FD_ZERO(&read_flags);
-       FD_SET(rdbg->_endpoint, &read_flags);
-       select(FD_SETSIZE, &read_flags, NULL, NULL, &time);
-
-       if(FD_ISSET(rdbg->_endpoint,&read_flags)){
-               char temp[1024];
-               int size=0;
-               char c,prev=0;
-               memset(&temp,0,sizeof(temp));
-               int res;
-               FD_CLR(rdbg->_endpoint, &read_flags);
-               while((res = recv(rdbg->_endpoint,&c,1,0))>0){
-
-                       if(c=='\n')break;
-                       if(c!='\r'){
-                               temp[size]=c;
-                               prev=c;
-                               size++;
-                       }
-               }
-               switch(res){
-               case 0:
-                       return sq_throwerror(rdbg->_v,_SC("disconnected"));
-               case SOCKET_ERROR:
-                       return sq_throwerror(rdbg->_v,_SC("socket error"));
-        }
-
-               temp[size]=0;
-               temp[size+1]=0;
-               rdbg->ParseMsg(temp);
-       }
-       return SQ_OK;
-}
-
-SQInteger debug_hook(HSQUIRRELVM v)
-{
-       SQUserPointer up;
-       SQInteger event_type,line;
-       const SQChar *src,*func;
-       sq_getinteger(v,2,&event_type);
-       sq_getstring(v,3,&src);
-       sq_getinteger(v,4,&line);
-       sq_getstring(v,5,&func);
-       sq_getuserpointer(v,-1,&up);
-       HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up;
-       rdbg->Hook(event_type,line,src,func);
-       if(rdbg->_autoupdate) {
-               if(SQ_FAILED(sq_rdbg_update(rdbg)))
-                       return sq_throwerror(v,_SC("socket failed"));
-       }
-       return 0;
-}
-
-SQInteger error_handler(HSQUIRRELVM v)
-{
-       SQUserPointer up;
-       const SQChar *sErr=NULL;
-       const SQChar *fn=_SC("unknown");
-       const SQChar *src=_SC("unknown");
-       int line=-1;
-       SQStackInfos si;
-       sq_getuserpointer(v,-1,&up);
-       HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up;
-       if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si)))
-       {
-               if(si.funcname)fn=si.funcname;
-               if(si.source)src=si.source;
-               line=si.line;
-               scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line);
-       }
-       if(sq_gettop(v)>=1){
-               if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr)))       {
-                       scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);
-                       rdbg->Break(si.line,src,_SC("error"),sErr);
-               }
-               else{
-                       scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n"));
-                       rdbg->Break(si.line,src,_SC("error"),_SC("unknown"));
-               }
-       }
-       rdbg->BreakExecution();
-       return 0;
-}
-
-
-SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg)
-{
-       delete rdbg;
-#ifdef _WIN32
-       WSACleanup();
-#endif
-       return SQ_OK;
-}
+#include <squirrel.h>\r
+#include <winsock.h>\r
+#include <squirrel.h>\r
+#include <squirrel.h>\r
+#include "sqrdbg.h"\r
+#include "sqdbgserver.h"\r
+SQInteger debug_hook(HSQUIRRELVM v);\r
+SQInteger error_handler(HSQUIRRELVM v);\r
+\r
+#include "serialize_state.inl"\r
+\r
+HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate)\r
+{\r
+       WSADATA wsadata;\r
+       sockaddr_in bindaddr;\r
+#ifdef _WIN32\r
+       if (WSAStartup (MAKEWORD(2,2), &wsadata) != 0){\r
+               return NULL;  \r
+       }       \r
+#endif \r
+       SQDbgServer *rdbg = new SQDbgServer(v);\r
+       rdbg->_autoupdate = autoupdate?true:false;\r
+       rdbg->_accept = socket(AF_INET,SOCK_STREAM,0);\r
+       bindaddr.sin_family = AF_INET;\r
+       bindaddr.sin_port = htons(port);\r
+       bindaddr.sin_addr.s_addr = htonl (INADDR_ANY);\r
+       if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){\r
+               delete rdbg;\r
+               sq_throwerror(v,_SC("failed to bind the socket"));\r
+               return NULL;\r
+       }\r
+       if(!rdbg->Init()) {\r
+               delete rdbg;\r
+               sq_throwerror(v,_SC("failed to initialize the debugger"));\r
+               return NULL;\r
+       }\r
+       \r
+    return rdbg;\r
+}\r
+\r
+SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg)\r
+{\r
+       if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) {\r
+               sq_throwerror(rdbg->_v,_SC("error compiling the serialization function"));\r
+       }\r
+       sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc);\r
+       sq_addref(rdbg->_v,&rdbg->_serializefunc);\r
+       sq_pop(rdbg->_v,1);\r
+\r
+       sockaddr_in cliaddr;\r
+       int addrlen=sizeof(cliaddr);\r
+       if(listen(rdbg->_accept,0)==SOCKET_ERROR)\r
+               return sq_throwerror(rdbg->_v,_SC("error on listen(socket)"));\r
+       rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,&addrlen);\r
+       //do not accept any other connection\r
+       sqdbg_closesocket(rdbg->_accept);\r
+       rdbg->_accept = INVALID_SOCKET;\r
+       if(rdbg->_endpoint==INVALID_SOCKET){\r
+               return sq_throwerror(rdbg->_v,_SC("error accept(socket)"));\r
+       }\r
+       while(!rdbg->_ready){\r
+               sq_rdbg_update(rdbg);\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg)\r
+{\r
+       TIMEVAL time;\r
+       time.tv_sec=0;\r
+       time.tv_usec=0;\r
+       fd_set read_flags;\r
+    FD_ZERO(&read_flags);\r
+       FD_SET(rdbg->_endpoint, &read_flags);\r
+       select(NULL/*ignored*/, &read_flags, NULL, NULL, &time);\r
+\r
+       if(FD_ISSET(rdbg->_endpoint,&read_flags)){\r
+               char temp[1024];\r
+               int size=0;\r
+               char c,prev=NULL;\r
+               memset(&temp,0,sizeof(temp));\r
+               int res;\r
+               FD_CLR(rdbg->_endpoint, &read_flags);\r
+               while((res = recv(rdbg->_endpoint,&c,1,0))>0){\r
+                       \r
+                       if(c=='\n')break;\r
+                       if(c!='\r'){\r
+                               temp[size]=c;\r
+                               prev=c;\r
+                               size++;\r
+                       }\r
+                       if(size >= sizeof(temp)-2) break;\r
+               }\r
+               switch(res){\r
+\r
+               case 0:\r
+                       return sq_throwerror(rdbg->_v,_SC("disconnected"));\r
+               case SOCKET_ERROR:\r
+                       return sq_throwerror(rdbg->_v,_SC("socket error"));\r
+        }\r
+               \r
+               temp[size]=NULL;\r
+               temp[size+1]=NULL;\r
+               rdbg->ParseMsg(temp);\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQInteger debug_hook(HSQUIRRELVM v)\r
+{\r
+       SQUserPointer up;\r
+       SQInteger event_type,line;\r
+       const SQChar *src,*func;\r
+       sq_getinteger(v,2,&event_type);\r
+       sq_getstring(v,3,&src);\r
+       sq_getinteger(v,4,&line);\r
+       sq_getstring(v,5,&func);\r
+       sq_getuserpointer(v,-1,&up);\r
+       HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up;\r
+       rdbg->Hook(v,event_type,line,src,func);\r
+       if(rdbg->_autoupdate) {\r
+               if(SQ_FAILED(sq_rdbg_update(rdbg)))\r
+                       return sq_throwerror(v,_SC("socket failed"));\r
+       }\r
+       return 0;\r
+}\r
+\r
+SQInteger error_handler(HSQUIRRELVM v)\r
+{\r
+       SQUserPointer up;\r
+       const SQChar *sErr=NULL;\r
+       const SQChar *fn=_SC("unknown");\r
+       const SQChar *src=_SC("unknown");\r
+       SQInteger line=-1;\r
+       SQStackInfos si;\r
+       sq_getuserpointer(v,-1,&up);\r
+       HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up;\r
+       if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si)))\r
+       {\r
+               if(si.funcname)fn=si.funcname;\r
+               if(si.source)src=si.source;\r
+               line=si.line;\r
+               scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line);\r
+       }\r
+       if(sq_gettop(v)>=1){\r
+               if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr)))       {\r
+                       scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);\r
+                       rdbg->Break(v,si.line,src,_SC("error"),sErr);\r
+               }\r
+               else{\r
+                       scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n"));\r
+                       rdbg->Break(v,si.line,src,_SC("error"),_SC("unknown"));\r
+               }\r
+       }\r
+       rdbg->BreakExecution();\r
+       return 0;\r
+}\r
+\r
+\r
+SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg)\r
+{\r
+       delete rdbg;\r
+#ifdef _WIN32\r
+       WSACleanup();\r
+#endif\r
+       return SQ_OK;\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index 6302790..c3cc568
@@ -1,50 +1,21 @@
-/*
-Copyright (c) 2003-2005 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.
-
-*/
-#ifndef _SQ_RDBG_H_
-#define _SQ_RDBG_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct SQDbgServer;
-typedef SQDbgServer* HSQREMOTEDBG;
-
-HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate);
-SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg);
-SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg);
-SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg);
-
-#ifdef __cplusplus
-} /*extern "C"*/
-#endif
-
-#endif //_SQ_RDBG_H_
+#ifndef _SQ_RDBG_H_\r
+#define _SQ_RDBG_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+#pragma comment(lib, "WSOCK32.LIB")\r
+\r
+struct SQDbgServer;\r
+typedef SQDbgServer* HSQREMOTEDBG;\r
+\r
+HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate);\r
+SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg);\r
+SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg);\r
+SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg);\r
\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif //_SQ_RDBG_H_
\ No newline at end of file
old mode 100755 (executable)
new mode 100644 (file)
index 5b87639..e115770
@@ -5,11 +5,10 @@
 \r
 void sqstd_printcallstack(HSQUIRRELVM v)\r
 {\r
-       SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+       SQPRINTFUNCTION pf = sq_geterrorfunc(v);\r
        if(pf) {\r
                SQStackInfos si;\r
                SQInteger i;\r
-               SQBool b;\r
                SQFloat f;\r
                const SQChar *s;\r
                SQInteger level=1; //1 is to skip this function that is level 0\r
@@ -84,8 +83,8 @@ void sqstd_printcallstack(HSQUIRRELVM v)
                                        pf(v,_SC("[%s] WEAKREF\n"),name);\r
                                        break;\r
                                case OT_BOOL:{\r
-                                       sq_getbool(v,-1,&b);\r
-                                       pf(v,_SC("[%s] %s\n"),name,b?_SC("true"):_SC("false"));\r
+                                       sq_getinteger(v,-1,&i);\r
+                                       pf(v,_SC("[%s] %s\n"),name,i?_SC("true"):_SC("false"));\r
                                                         }\r
                                        break;\r
                                default: assert(0); break;\r
@@ -98,7 +97,7 @@ void sqstd_printcallstack(HSQUIRRELVM v)
 \r
 static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)\r
 {\r
-       SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+       SQPRINTFUNCTION pf = sq_geterrorfunc(v);\r
        if(pf) {\r
                const SQChar *sErr = 0;\r
                if(sq_gettop(v)>=1) {\r
@@ -116,7 +115,7 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
 \r
 void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column)\r
 {\r
-       SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+       SQPRINTFUNCTION pf = sq_geterrorfunc(v);\r
        if(pf) {\r
                pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr);\r
        }\r
old mode 100755 (executable)
new mode 100644 (file)
index 05ef8d9..59cff0d
@@ -15,7 +15,9 @@
 #define SETUP_BLOB(v) \\r
        SQBlob *self = NULL; \\r
        { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \\r
-               return SQ_ERROR; }\r
+               return sq_throwerror(v,_SC("invalid type tag"));  } \\r
+       if(!self || !self->IsValid())  \\r
+               return sq_throwerror(v,_SC("the blob is invalid"));\r
 \r
 \r
 static SQInteger _blob_resize(HSQUIRRELVM v)\r
@@ -115,7 +117,8 @@ static SQInteger _blob__typeof(HSQUIRRELVM v)
 static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size)\r
 {\r
        SQBlob *self = (SQBlob*)p;\r
-       delete self;\r
+       self->~SQBlob();\r
+       sq_free(self,sizeof(SQBlob));\r
        return 1;\r
 }\r
 \r
@@ -127,10 +130,32 @@ static SQInteger _blob_constructor(HSQUIRRELVM v)
                sq_getinteger(v, 2, &size);\r
        }\r
        if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
-       SQBlob *b = new SQBlob(size);\r
+       //SQBlob *b = new SQBlob(size);\r
+\r
+       SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size);\r
        if(SQ_FAILED(sq_setinstanceup(v,1,b))) {\r
-               delete b;\r
-               return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
+               b->~SQBlob();\r
+               sq_free(b,sizeof(SQBlob));\r
+               return sq_throwerror(v, _SC("cannot create blob"));\r
+       }\r
+       sq_setreleasehook(v,1,_blob_releasehook);\r
+       return 0;\r
+}\r
+\r
+static SQInteger _blob__cloned(HSQUIRRELVM v)\r
+{\r
+       SQBlob *other = NULL;\r
+       { \r
+               if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))\r
+                       return SQ_ERROR; \r
+       }\r
+       //SQBlob *thisone = new SQBlob(other->Len());\r
+       SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());\r
+       memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());\r
+       if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {\r
+               thisone->~SQBlob();\r
+               sq_free(thisone,sizeof(SQBlob));\r
+               return sq_throwerror(v, _SC("cannot clone blob"));\r
        }\r
        sq_setreleasehook(v,1,_blob_releasehook);\r
        return 0;\r
@@ -146,6 +171,7 @@ static SQRegFunction _blob_methods[] = {
        _DECL_BLOB_FUNC(_get,2,_SC("xn")),\r
        _DECL_BLOB_FUNC(_typeof,1,_SC("x")),\r
        _DECL_BLOB_FUNC(_nexti,2,_SC("x")),\r
+       _DECL_BLOB_FUNC(_cloned,2,_SC("xx")),\r
        {0,0,0,0}\r
 };\r
 \r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 2d0d442..b365a07
@@ -117,7 +117,8 @@ static SQInteger _file__typeof(HSQUIRRELVM v)
 static SQInteger _file_releasehook(SQUserPointer p, SQInteger size)\r
 {\r
        SQFile *self = (SQFile*)p;\r
-       delete self;\r
+       self->~SQFile();\r
+       sq_free(self,sizeof(SQFile));\r
        return 1;\r
 }\r
 \r
@@ -138,20 +139,34 @@ static SQInteger _file_constructor(HSQUIRRELVM v)
        } else {\r
                return sq_throwerror(v,_SC("wrong parameter"));\r
        }\r
-       f = new SQFile(newf,owns);\r
+       \r
+       f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);\r
        if(SQ_FAILED(sq_setinstanceup(v,1,f))) {\r
-               delete f;\r
+               f->~SQFile();\r
+               sq_free(f,sizeof(SQFile));\r
                return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
        }\r
        sq_setreleasehook(v,1,_file_releasehook);\r
        return 0;\r
 }\r
 \r
+static SQInteger _file_close(HSQUIRRELVM v)\r
+{\r
+       SQFile *self = NULL;\r
+       if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))\r
+               && self != NULL)\r
+       {\r
+               self->Close();\r
+       }\r
+       return 0;\r
+}\r
+\r
 //bindings\r
 #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}\r
 static SQRegFunction _file_methods[] = {\r
        _DECL_FILE_FUNC(constructor,3,_SC("x")),\r
        _DECL_FILE_FUNC(_typeof,1,_SC("x")),\r
+       _DECL_FILE_FUNC(close,1,_SC("x")),\r
        {0,0,0,0},\r
 };\r
 \r
@@ -193,7 +208,7 @@ SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
 \r
 \r
 \r
-static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file)\r
+static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer file)\r
 {\r
        SQInteger ret;\r
        char c;\r
@@ -202,6 +217,7 @@ static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file)
        return 0;\r
 }\r
 \r
+#ifdef SQUNICODE\r
 static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)\r
 {\r
 #define READ() \\r
@@ -238,6 +254,7 @@ static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)
        }\r
        return c;\r
 }\r
+#endif\r
 \r
 static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file)\r
 {\r
@@ -277,7 +294,7 @@ SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
        SQInteger ret;\r
        unsigned short us;\r
        unsigned char uc;\r
-       SQLEXREADFUNC func = _io_file_lexfeed_ASCII;\r
+       SQLEXREADFUNC func = _io_file_lexfeed_PLAIN;\r
        if(file){\r
                ret = sqstd_fread(&us,1,2,file);\r
                if(ret != 2) {\r
@@ -306,7 +323,11 @@ SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
                                                sqstd_fclose(file); \r
                                                return sq_throwerror(v,_SC("Unrecognozed ecoding")); \r
                                        }\r
+#ifdef SQUNICODE\r
                                        func = _io_file_lexfeed_UTF8;\r
+#else\r
+                                       func = _io_file_lexfeed_PLAIN;\r
+#endif\r
                                        break;//UTF-8 ;\r
                                default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii\r
                        }\r
@@ -398,13 +419,13 @@ SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
        declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);\r
        sq_pushstring(v,_SC("stdout"),-1);\r
        sqstd_createfile(v,stdout,SQFalse);\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3,SQFalse);\r
        sq_pushstring(v,_SC("stdin"),-1);\r
        sqstd_createfile(v,stdin,SQFalse);\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3,SQFalse);\r
        sq_pushstring(v,_SC("stderr"),-1);\r
        sqstd_createfile(v,stderr,SQFalse);\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3,SQFalse);\r
        sq_settop(v,top);\r
        return SQ_OK;\r
 }\r
old mode 100755 (executable)
new mode 100644 (file)
index c54a7dc..ef50359
@@ -80,6 +80,7 @@ static SQRegFunction mathlib_funcs[] = {
        _DECL_FUNC(abs,2,_SC(".n")),\r
        {0,0},\r
 };\r
+#undef _DECL_FUNC\r
 \r
 #ifndef M_PI\r
 #define M_PI (3.14159265358979323846)\r
@@ -93,14 +94,14 @@ SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)
                sq_newclosure(v,mathlib_funcs[i].f,0);\r
                sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);\r
                sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                i++;\r
        }\r
        sq_pushstring(v,_SC("RAND_MAX"),-1);\r
        sq_pushinteger(v,RAND_MAX);\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3,SQFalse);\r
        sq_pushstring(v,_SC("PI"),-1);\r
        sq_pushfloat(v,(SQFloat)M_PI);\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3,SQFalse);\r
        return SQ_OK;\r
 }\r
old mode 100755 (executable)
new mode 100644 (file)
index 8eebb27..20aa57d
@@ -3,7 +3,7 @@
 #include <string.h>\r
 #include <ctype.h>\r
 #include <setjmp.h>\r
-#include "sqstdstring.h"\r
+#include <sqstdstring.h>\r
 \r
 #ifdef _UINCODE\r
 #define scisprint iswprint\r
@@ -263,7 +263,6 @@ static SQInteger sqstd_rex_element(SQRex *exp)
        }\r
 \r
 \r
-       SQInteger op;\r
        SQBool isgreedy = SQFalse;\r
        unsigned short p0 = 0, p1 = 0;\r
        switch(*exp->_p){\r
@@ -297,7 +296,6 @@ static SQInteger sqstd_rex_element(SQRex *exp)
        }\r
        if(isgreedy) {\r
                SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);\r
-               op = OP_GREEDY;\r
                exp->_nodes[nnode].left = ret;\r
                exp->_nodes[nnode].right = ((p0)<<16)|p1;\r
                ret = nnode;\r
@@ -461,7 +459,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
                                exp->_matches[capture].begin = cur;\r
                                exp->_currsubexp++;\r
                        }\r
-                       \r
+                       int tempcap = exp->_currsubexp;\r
                        do {\r
                                SQRexNode *subnext = NULL;\r
                                if(n->next != -1) {\r
@@ -478,12 +476,13 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
                                }\r
                        } while((n->next != -1) && (n = &exp->_nodes[n->next]));\r
 \r
+                       exp->_currsubexp = tempcap;\r
                        if(capture != -1) \r
                                exp->_matches[capture].len = cur - exp->_matches[capture].begin;\r
                        return cur;\r
        }                                \r
        case OP_WB:\r
-               if(str == exp->_bol && !isspace(*str)\r
+               if((str == exp->_bol && !isspace(*str))\r
                 || (str == exp->_eol && !isspace(*(str-1)))\r
                 || (!isspace(*str) && isspace(*(str+1)))\r
                 || (isspace(*str) && !isspace(*(str+1))) ) {\r
@@ -497,25 +496,25 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
                if(str == exp->_eol) return str;\r
                return NULL;\r
        case OP_DOT:{\r
-               *str++;\r
+               str++;\r
                                }\r
                return str;\r
        case OP_NCLASS:\r
        case OP_CLASS:\r
                if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {\r
-                       *str++;\r
+                       str++;\r
                        return str;\r
                }\r
                return NULL;\r
        case OP_CCLASS:\r
                if(sqstd_rex_matchcclass(node->left,*str)) {\r
-                       *str++;\r
+                       str++;\r
                        return str;\r
                }\r
                return NULL;\r
        default: /* char */\r
                if(*str != node->type) return NULL;\r
-               *str++;\r
+               str++;\r
                return str;\r
        }\r
        return NULL;\r
@@ -605,7 +604,7 @@ SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* t
                                break;\r
                        node = exp->_nodes[node].next;\r
                }\r
-               *text_begin++;\r
+               text_begin++;\r
        } while(cur == NULL && text_begin != text_end);\r
 \r
        if(cur == NULL)\r
old mode 100755 (executable)
new mode 100644 (file)
index 606a9b8..1b7a08f
@@ -13,7 +13,7 @@
        SQStream *self = NULL; \\r
        if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \\r
                return sq_throwerror(v,_SC("invalid type tag")); \\r
-       if(!self->IsValid())  \\r
+       if(!self || !self->IsValid())  \\r
                return sq_throwerror(v,_SC("the stream is invalid"));\r
 \r
 SQInteger _stream_readblob(HSQUIRRELVM v)\r
@@ -233,6 +233,11 @@ SQInteger _stream_eos(HSQUIRRELVM v)
        return 1;\r
 }\r
 \r
+ SQInteger _stream__cloned(HSQUIRRELVM v)\r
+ {\r
+        return sq_throwerror(v,_SC("this object cannot be cloned"));\r
+ }\r
+\r
 static SQRegFunction _stream_methods[] = {\r
        _DECL_STREAM_FUNC(readblob,2,_SC("xn")),\r
        _DECL_STREAM_FUNC(readn,2,_SC("xn")),\r
@@ -243,6 +248,7 @@ static SQRegFunction _stream_methods[] = {
        _DECL_STREAM_FUNC(len,1,_SC("x")),\r
        _DECL_STREAM_FUNC(eos,1,_SC("x")),\r
        _DECL_STREAM_FUNC(flush,1,_SC("x")),\r
+       _DECL_STREAM_FUNC(_cloned,0,NULL),\r
        {0,0}\r
 };\r
 \r
@@ -260,15 +266,15 @@ void init_streamclass(HSQUIRRELVM v)
                        sq_pushstring(v,f.name,-1);\r
                        sq_newclosure(v,f.f,0);\r
                        sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
-                       sq_createslot(v,-3);\r
+                       sq_newslot(v,-3,SQFalse);\r
                        i++;\r
                }\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                sq_pushroottable(v);\r
                sq_pushstring(v,_SC("stream"),-1);\r
                sq_pushstring(v,_SC("std_stream"),-1);\r
                sq_get(v,-4);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                sq_pop(v,1);\r
        }\r
        else {\r
@@ -297,10 +303,10 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c
                        sq_newclosure(v,f.f,0);\r
                        sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
                        sq_setnativeclosurename(v,-1,f.name);\r
-                       sq_createslot(v,-3);\r
+                       sq_newslot(v,-3,SQFalse);\r
                        i++;\r
                }\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                sq_pop(v,1);\r
                \r
                i = 0;\r
@@ -311,7 +317,7 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c
                        sq_newclosure(v,f.f,0);\r
                        sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
                        sq_setnativeclosurename(v,-1,f.name);\r
-                       sq_createslot(v,-3);\r
+                       sq_newslot(v,-3,SQFalse);\r
                        i++;\r
                }\r
                //register the class in the target table\r
@@ -320,7 +326,7 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c
                sq_pushstring(v,reg_name,-1);\r
                sq_get(v,-2);\r
                sq_remove(v,-2);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
 \r
                sq_settop(v,top);\r
                return SQ_OK;\r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index af84237..33316fa
@@ -65,7 +65,6 @@ static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src,
        return n;\r
 }\r
 \r
-\r
 SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)\r
 {\r
        const SQChar *format;\r
@@ -103,7 +102,21 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen
                                addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));\r
                                valtype = 's';\r
                                break;\r
-                       case 'i': case 'd': case 'c':case 'o':  case 'u':  case 'x':  case 'X':\r
+                       case 'i': case 'd': case 'o': case 'u':  case 'x':  case 'X':\r
+#ifdef _SQ64\r
+                               {\r
+                               size_t flen = scstrlen(fmt);\r
+                               SQInteger fpos = flen - 1;\r
+                               SQChar f = fmt[fpos];\r
+                               SQChar *prec = (SQChar *)_PRINT_INT_PREC;\r
+                               while(*prec != _SC('\0')) {\r
+                                       fmt[fpos++] = *prec++;\r
+                               }\r
+                               fmt[fpos++] = f;\r
+                               fmt[fpos++] = _SC('\0');\r
+                               }\r
+#endif\r
+                       case 'c':\r
                                if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) \r
                                        return sq_throwerror(v,_SC("integer expected for the specified format"));\r
                                addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));\r
@@ -159,8 +172,8 @@ static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)
                return;\r
        }\r
        const SQChar *t = &str[len-1];\r
-       while(t != str && scisspace(*t)) { t--; }\r
-       *end = t+1;\r
+       while(t >= str && scisspace(*t)) { t--; }\r
+       *end = t + 1;\r
 }\r
 \r
 static SQInteger _string_strip(HSQUIRRELVM v)\r
@@ -321,6 +334,7 @@ static SQRegFunction rexobj_funcs[]={
        _DECL_REX_FUNC(_typeof,1,_SC("x")),\r
        {0,0}\r
 };\r
+#undef _DECL_REX_FUNC\r
 \r
 #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}\r
 static SQRegFunction stringlib_funcs[]={\r
@@ -331,6 +345,7 @@ static SQRegFunction stringlib_funcs[]={
        _DECL_FUNC(split,3,_SC(".ss")),\r
        {0,0}\r
 };\r
+#undef _DECL_FUNC\r
 \r
 \r
 SQInteger sqstd_register_stringlib(HSQUIRRELVM v)\r
@@ -344,10 +359,10 @@ SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
                sq_newclosure(v,f.f,0);\r
                sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
                sq_setnativeclosurename(v,-1,f.name);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                i++;\r
        }\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3,SQFalse);\r
 \r
        i = 0;\r
        while(stringlib_funcs[i].name!=0)\r
@@ -356,7 +371,7 @@ SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
                sq_newclosure(v,stringlib_funcs[i].f,0);\r
                sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);\r
                sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                i++;\r
        }\r
        return 1;\r
old mode 100755 (executable)
new mode 100644 (file)
index c7153a6..40f78d7
@@ -122,14 +122,14 @@ static SQInteger _system_date(HSQUIRRELVM v)
 static SQRegFunction systemlib_funcs[]={\r
        _DECL_FUNC(getenv,2,_SC(".s")),\r
        _DECL_FUNC(system,2,_SC(".s")),\r
-       _DECL_FUNC(clock,1,NULL),\r
+       _DECL_FUNC(clock,0,NULL),\r
        _DECL_FUNC(time,1,NULL),\r
        _DECL_FUNC(date,-1,_SC(".nn")),\r
        _DECL_FUNC(remove,2,_SC(".s")),\r
        _DECL_FUNC(rename,3,_SC(".ss")),\r
        {0,0}\r
 };\r
-\r
+#undef _DECL_FUNC\r
 \r
 SQInteger sqstd_register_systemlib(HSQUIRRELVM v)\r
 {\r
@@ -140,7 +140,7 @@ SQInteger sqstd_register_systemlib(HSQUIRRELVM v)
                sq_newclosure(v,systemlib_funcs[i].f,0);\r
                sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask);\r
                sq_setnativeclosurename(v,-1,systemlib_funcs[i].name);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3,SQFalse);\r
                i++;\r
        }\r
        return 1;\r
old mode 100755 (executable)
new mode 100644 (file)
index a629909..5b1d872
@@ -31,11 +31,6 @@ bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPt
        if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\\r
 }              \r
 \r
-SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)\r
-{\r
-       v->_lasterror = e;\r
-       return SQ_ERROR;\r
-}\r
 \r
 SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)\r
 {\r
@@ -98,11 +93,20 @@ void sq_seterrorhandler(HSQUIRRELVM v)
        }\r
 }\r
 \r
+void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)\r
+{\r
+       v->_debughook_native = hook;\r
+       v->_debughook_closure.Null();\r
+       v->_debughook = hook?true:false;\r
+}\r
+\r
 void sq_setdebughook(HSQUIRRELVM v)\r
 {\r
        SQObject o = stack_get(v,-1);\r
        if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
-               v->_debughook = o;\r
+               v->_debughook_closure = o;\r
+               v->_debughook_native = NULL;\r
+               v->_debughook = !sq_isnull(o);\r
                v->Pop();\r
        }\r
 }\r
@@ -114,14 +118,23 @@ void sq_close(HSQUIRRELVM v)
        sq_delete(ss, SQSharedState);\r
 }\r
 \r
+SQInteger sq_getversion()\r
+{\r
+       return SQUIRREL_VERSION_NUMBER;\r
+}\r
+\r
 SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)\r
 {\r
        SQObjectPtr o;\r
+#ifndef NO_COMPILER\r
        if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {\r
                v->Push(SQClosure::Create(_ss(v), _funcproto(o)));\r
                return SQ_OK;\r
        }\r
        return SQ_ERROR;\r
+#else\r
+       return sq_throwerror(v,_SC("this is a no compiler build"));\r
+#endif\r
 }\r
 \r
 void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)\r
@@ -144,18 +157,29 @@ void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
 #endif\r
 }\r
 \r
+SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po)\r
+{\r
+       if(!ISREFCOUNTED(type(*po))) return 0;\r
+#ifdef NO_GARBAGE_COLLECTOR\r
+   return po->_unVal.pRefCounted->_uiRef; \r
+#else\r
+   return _ss(v)->_refs_table.GetRefCount(*po); \r
+#endif \r
+}\r
+\r
 SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)\r
 {\r
        if(!ISREFCOUNTED(type(*po))) return SQTrue;\r
 #ifdef NO_GARBAGE_COLLECTOR\r
+       bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse;\r
        __Release(po->_type,po->_unVal);\r
-       return SQFalse; //the ret val doesn't work(and cannot be fixed)\r
+       return ret; //the ret val doesn't work(and cannot be fixed)\r
 #else\r
        return _ss(v)->_refs_table.Release(*po);\r
 #endif\r
 }\r
 \r
-const SQChar *sq_objtostring(HSQOBJECT *o) \r
+const SQChar *sq_objtostring(const HSQOBJECT *o) \r
 {\r
        if(sq_type(*o) == OT_STRING) {\r
                return _stringval(*o);\r
@@ -163,7 +187,7 @@ const SQChar *sq_objtostring(HSQOBJECT *o)
        return NULL;\r
 }\r
 \r
-SQInteger sq_objtointeger(HSQOBJECT *o) \r
+SQInteger sq_objtointeger(const HSQOBJECT *o) \r
 {\r
        if(sq_isnumeric(*o)) {\r
                return tointeger(*o);\r
@@ -171,7 +195,7 @@ SQInteger sq_objtointeger(HSQOBJECT *o)
        return 0;\r
 }\r
 \r
-SQFloat sq_objtofloat(HSQOBJECT *o) \r
+SQFloat sq_objtofloat(const HSQOBJECT *o) \r
 {\r
        if(sq_isnumeric(*o)) {\r
                return tofloat(*o);\r
@@ -179,7 +203,7 @@ SQFloat sq_objtofloat(HSQOBJECT *o)
        return 0;\r
 }\r
 \r
-SQBool sq_objtobool(HSQOBJECT *o) \r
+SQBool sq_objtobool(const HSQOBJECT *o) \r
 {\r
        if(sq_isbool(*o)) {\r
                return _integer(*o);\r
@@ -187,16 +211,24 @@ SQBool sq_objtobool(HSQOBJECT *o)
        return SQFalse;\r
 }\r
 \r
+SQUserPointer sq_objtouserpointer(const HSQOBJECT *o)\r
+{\r
+       if(sq_isuserpointer(*o)) {\r
+               return _userpointer(*o);\r
+       }\r
+       return 0;\r
+}\r
+\r
 void sq_pushnull(HSQUIRRELVM v)\r
 {\r
-       v->Push(_null_);\r
+       v->PushNull();\r
 }\r
 \r
 void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)\r
 {\r
        if(s)\r
                v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));\r
-       else v->Push(_null_);\r
+       else v->PushNull();\r
 }\r
 \r
 void sq_pushinteger(HSQUIRRELVM v,SQInteger n)\r
@@ -223,7 +255,7 @@ SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)
 {\r
        SQUserData *ud = SQUserData::Create(_ss(v), size);\r
        v->Push(ud);\r
-       return ud->_val;\r
+       return (SQUserPointer)sq_aligning(ud + 1);\r
 }\r
 \r
 void sq_newtable(HSQUIRRELVM v)\r
@@ -231,6 +263,11 @@ void sq_newtable(HSQUIRRELVM v)
        v->Push(SQTable::Create(_ss(v), 0));    \r
 }\r
 \r
+void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)\r
+{\r
+       v->Push(SQTable::Create(_ss(v), initialcapacity));      \r
+}\r
+\r
 void sq_newarray(HSQUIRRELVM v,SQInteger size)\r
 {\r
        v->Push(SQArray::Create(_ss(v), size)); \r
@@ -266,7 +303,7 @@ SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx)
        SQObjectPtr *arr;\r
        _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
        _array(*arr)->Append(v->GetUp(-1));\r
-       v->Pop(1);\r
+       v->Pop();\r
        return SQ_OK;\r
 }\r
 \r
@@ -334,13 +371,12 @@ SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
        return ret;\r
 }\r
 \r
-\r
 void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)\r
 {\r
-       SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);\r
+       SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars);\r
        nc->_nparamscheck = 0;\r
        for(SQUnsignedInteger i = 0; i < nfreevars; i++) {\r
-               nc->_outervalues.push_back(v->Top());\r
+               nc->_outervalues[i] = v->Top();\r
                v->Pop();\r
        }\r
        v->Push(SQObjectPtr(nc));       \r
@@ -349,11 +385,18 @@ void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
 SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)\r
 {\r
        SQObject o = stack_get(v, idx);\r
-       if(sq_isclosure(o)) {\r
+       if(type(o) == OT_CLOSURE) {\r
                SQClosure *c = _closure(o);\r
-               SQFunctionProto *proto = _funcproto(c->_function);\r
+               SQFunctionProto *proto = c->_function;\r
                *nparams = (SQUnsignedInteger)proto->_nparameters;\r
-        *nfreevars = (SQUnsignedInteger)c->_outervalues.size();\r
+               *nfreevars = (SQUnsignedInteger)proto->_noutervalues;\r
+               return SQ_OK;\r
+       }\r
+       else if(type(o) == OT_NATIVECLOSURE)\r
+       {\r
+               SQNativeClosure *c = _nativeclosure(o);\r
+               *nparams = (SQUnsignedInteger)c->_nparamscheck;\r
+               *nfreevars = c->_noutervalues;\r
                return SQ_OK;\r
        }\r
        return sq_throwerror(v,_SC("the object is not a closure"));\r
@@ -403,16 +446,24 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
                !sq_isclass(env) &&\r
                !sq_isinstance(env))\r
                return sq_throwerror(v,_SC("invalid environment"));\r
-       SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env));\r
+       SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));\r
        SQObjectPtr ret;\r
        if(sq_isclosure(o)) {\r
                SQClosure *c = _closure(o)->Clone();\r
+               __ObjRelease(c->_env);\r
                c->_env = w;\r
+               __ObjAddRef(c->_env);\r
+               if(_closure(o)->_base) {\r
+                       c->_base = _closure(o)->_base;\r
+                       __ObjAddRef(c->_base);\r
+               }\r
                ret = c;\r
        }\r
        else { //then must be a native closure\r
                SQNativeClosure *c = _nativeclosure(o)->Clone();\r
+               __ObjRelease(c->_env);\r
                c->_env = w;\r
+               __ObjAddRef(c->_env);\r
                ret = c;\r
        }\r
        v->Pop();\r
@@ -420,6 +471,22 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
        return SQ_OK;\r
 }\r
 \r
+SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+       SQObjectPtr &o = stack_get(v,idx);\r
+       if(!sq_isnativeclosure(o) &&\r
+               !sq_isclosure(o))\r
+               return sq_throwerror(v,_SC("the target is not a closure"));\r
+       if(sq_isnativeclosure(o))\r
+       {\r
+               v->Push(_nativeclosure(o)->_name);\r
+       }\r
+       else { //closure\r
+               v->Push(_closure(o)->_function->_name);\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
 SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObject &o=stack_get(v,idx);\r
@@ -491,19 +558,32 @@ SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)
        return type(stack_get(v, idx));\r
 }\r
 \r
+SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+       SQObjectPtr &o = stack_get(v, idx);\r
+       SQObjectPtr res;\r
+       if(!v->TypeOf(o,res)) {\r
+               return SQ_ERROR;\r
+       }\r
+       v->Push(res);\r
+       return SQ_OK;\r
+}\r
 \r
-void sq_tostring(HSQUIRRELVM v,SQInteger idx)\r
+SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr &o = stack_get(v, idx);\r
        SQObjectPtr res;\r
-       v->ToString(o,res);\r
+       if(!v->ToString(o,res)) {\r
+               return SQ_ERROR;\r
+       }\r
        v->Push(res);\r
+       return SQ_OK;\r
 }\r
 \r
 void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)\r
 {\r
        SQObjectPtr &o = stack_get(v, idx);\r
-       *b = v->IsFalse(o)?SQFalse:SQTrue;\r
+       *b = SQVM::IsFalse(o)?SQFalse:SQTrue;\r
 }\r
 \r
 SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i)\r
@@ -555,10 +635,10 @@ SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread)
 SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr &o = stack_get(v,idx);\r
-       v->Push(_null_);\r
+       v->PushNull();\r
        if(!v->Clone(o, stack_get(v, -1))){\r
                v->Pop();\r
-               return sq_aux_invalidtype(v, type(o));\r
+               return SQ_ERROR;\r
        }\r
        return SQ_OK;\r
 }\r
@@ -579,6 +659,12 @@ SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
        }\r
 }\r
 \r
+SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx)\r
+{\r
+       SQObjectPtr &o = stack_get(v, idx);\r
+       return HashObj(o);\r
+}\r
+\r
 SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag)\r
 {\r
        SQObjectPtr *o = NULL;\r
@@ -599,7 +685,7 @@ SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)
        return SQ_OK;\r
 }\r
 \r
-SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag)\r
+SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag)\r
 {\r
   switch(type(*o)) {\r
     case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;\r
@@ -722,27 +808,31 @@ SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
        if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
        SQObjectPtr res;\r
        if(!v->DeleteSlot(*self, key, res)){\r
+               v->Pop();\r
                return SQ_ERROR;\r
        }\r
        if(pushval)     v->GetUp(-1) = res;\r
-       else v->Pop(1);\r
+       else v->Pop();\r
        return SQ_OK;\r
 }\r
 \r
 SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr &self = stack_get(v, idx);\r
-       if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {\r
+       if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) {\r
                v->Pop(2);\r
                return SQ_OK;\r
        }\r
-       v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
+       return SQ_ERROR;\r
 }\r
 \r
 SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr &self = stack_get(v, idx);\r
-       if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
+       if(type(v->GetUp(-2)) == OT_NULL) {\r
+               v->Pop(2);\r
+               return sq_throwerror(v, _SC("null key"));\r
+       }\r
        switch(type(self)) {\r
        case OT_TABLE:\r
                _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));\r
@@ -773,6 +863,26 @@ SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)
        v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
 }\r
 \r
+SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)\r
+{\r
+       SQObjectPtr &self = stack_get(v, idx);\r
+       if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));\r
+       if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
+       if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false))\r
+               return SQ_ERROR;\r
+       return SQ_OK; \r
+}\r
+\r
+SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)\r
+{\r
+       SQObjectPtr &self = stack_get(v, idx);\r
+       if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));\r
+       if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
+       if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true))\r
+               return SQ_ERROR;\r
+       return SQ_OK; \r
+}\r
+\r
 SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr &self = stack_get(v, idx);\r
@@ -811,9 +921,9 @@ SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
                _table(*self)->Remove(key);\r
        }\r
        if(pushval != 0)\r
-               if(pushval)     v->GetUp(-1) = t;\r
+               v->GetUp(-1) = t;\r
        else\r
-               v->Pop(1);\r
+               v->Pop();\r
        return SQ_OK;\r
 }\r
 \r
@@ -824,7 +934,7 @@ SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)
        case OT_TABLE:\r
        case OT_USERDATA:\r
                if(!_delegable(self)->_delegate){\r
-                       v->Push(_null_);\r
+                       v->PushNull();\r
                        break;\r
                }\r
                v->Push(SQObjectPtr(_delegable(self)->_delegate));\r
@@ -838,10 +948,10 @@ SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)
 SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr &self=stack_get(v,idx);\r
-       if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))\r
+       if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,DONT_FALL_BACK))\r
                return SQ_OK;\r
-       v->Pop(1);\r
-       return sq_throwerror(v,_SC("the index doesn't exist"));\r
+       v->Pop();\r
+       return SQ_ERROR;\r
 }\r
 \r
 SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)\r
@@ -860,15 +970,24 @@ SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)
                if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
                        return SQ_OK;\r
                break;\r
-       case OT_ARRAY:\r
-               if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))\r
-                       return SQ_OK;\r
+       case OT_ARRAY:{\r
+               SQObjectPtr& key = v->GetUp(-1);\r
+               if(sq_isnumeric(key)){\r
+                       if(_array(self)->Get(tointeger(key),v->GetUp(-1))) {\r
+                               return SQ_OK;\r
+                       }\r
+               }\r
+               else {\r
+                       v->Pop();\r
+                       return sq_throwerror(v,_SC("invalid index type for an array"));\r
+               }\r
+                                 }\r
                break;\r
        default:\r
-               v->Pop(1);\r
+               v->Pop();\r
                return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));\r
        }       \r
-       v->Pop(1);\r
+       v->Pop();\r
        return sq_throwerror(v,_SC("the index doesn't exist"));\r
 }\r
 \r
@@ -892,9 +1011,9 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege
                if(type(ci._closure)!=OT_CLOSURE)\r
                        return NULL;\r
                SQClosure *c=_closure(ci._closure);\r
-               SQFunctionProto *func=_funcproto(c->_function);\r
+               SQFunctionProto *func=c->_function;\r
                if(func->_noutervalues > (SQInteger)idx) {\r
-                       v->Push(c->_outervalues[idx]);\r
+                       v->Push(*_outer(c->_outervalues[idx])->_valptr);\r
                        return _stringval(func->_outervalues[idx]._name);\r
                }\r
                idx -= func->_noutervalues;\r
@@ -916,12 +1035,20 @@ void sq_resetobject(HSQOBJECT *po)
 SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)\r
 {\r
        v->_lasterror=SQString::Create(_ss(v),err);\r
-       return -1;\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_throwobject(HSQUIRRELVM v)\r
+{\r
+       v->_lasterror = v->GetUp(-1);\r
+       v->Pop();\r
+       return SQ_ERROR;\r
 }\r
 \r
+\r
 void sq_reseterror(HSQUIRRELVM v)\r
 {\r
-       v->_lasterror = _null_;\r
+       v->_lasterror.Null();\r
 }\r
 \r
 void sq_getlasterror(HSQUIRRELVM v)\r
@@ -929,18 +1056,22 @@ void sq_getlasterror(HSQUIRRELVM v)
        v->Push(v->_lasterror);\r
 }\r
 \r
-void sq_reservestack(HSQUIRRELVM v,SQInteger nsize)\r
+SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize)\r
 {\r
        if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {\r
+               if(v->_nmetamethodscall) {\r
+                       return sq_throwerror(v,_SC("cannot resize stack while in  a metamethod"));\r
+               }\r
                v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));\r
        }\r
+       return SQ_OK;\r
 }\r
 \r
 SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)\r
 {\r
        if(type(v->GetUp(-1))==OT_GENERATOR){\r
-               v->Push(_null_); //retval\r
-               if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR))\r
+               v->PushNull(); //retval\r
+               if(!v->Execute(v->GetUp(-2),0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR))\r
                {v->Raise_Error(v->_lasterror); return SQ_ERROR;}\r
                if(!retval)\r
                        v->Pop();\r
@@ -953,6 +1084,7 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)
 {\r
        SQObjectPtr res;\r
        if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){\r
+\r
                if(!v->_suspended) {\r
                        v->Pop(params);//pop closure and args\r
                }\r
@@ -980,14 +1112,16 @@ SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseer
        SQObjectPtr ret;\r
        if(!v->_suspended)\r
                return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));\r
+       SQInteger target = v->_suspended_target;\r
        if(wakeupret) {\r
-               v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval\r
+               if(target != -1) {\r
+                       v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval\r
+               }\r
                v->Pop();\r
-       } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_;\r
-       if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM))\r
+       } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }\r
+       SQObjectPtr dummy;\r
+       if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) {\r
                return SQ_ERROR;\r
-       if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) {\r
-               while (v->_top > 1) v->_stack[--v->_top] = _null_;\r
        }\r
        if(retval)\r
                v->Push(ret);\r
@@ -1017,6 +1151,8 @@ SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
        SQObjectPtr *o = NULL;\r
        _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);\r
        unsigned short tag = SQ_BYTECODE_STREAM_TAG;\r
+       if(_closure(*o)->_function->_noutervalues) \r
+               return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized"));\r
        if(w(up,&tag,2) != 2)\r
                return sq_throwerror(v,_SC("io error"));\r
        if(!_closure(*o)->Save(v,up,w))\r
@@ -1044,6 +1180,16 @@ SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
        return _ss(v)->GetScratchPad(minsize);\r
 }\r
 \r
+SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)\r
+{\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       _ss(v)->ResurrectUnreachable(v);\r
+       return SQ_OK;\r
+#else\r
+       return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build"));\r
+#endif\r
+}\r
+\r
 SQInteger sq_collectgarbage(HSQUIRRELVM v)\r
 {\r
 #ifndef NO_GARBAGE_COLLECTOR\r
@@ -1053,17 +1199,41 @@ SQInteger sq_collectgarbage(HSQUIRRELVM v)
 #endif\r
 }\r
 \r
+SQRESULT sq_getcallee(HSQUIRRELVM v)\r
+{\r
+       if(v->_callsstacksize > 1)\r
+       {\r
+               v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("no closure in the calls stack"));\r
+}\r
+\r
 const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)\r
 {\r
-       SQObjectPtr &self = stack_get(v,idx);\r
+       SQObjectPtr &self=stack_get(v,idx);\r
        const SQChar *name = NULL;\r
-       if(type(self) == OT_CLOSURE) {\r
-               if(_closure(self)->_outervalues.size()>nval) {\r
-                       v->Push(_closure(self)->_outervalues[nval]);\r
-                       SQFunctionProto *fp = _funcproto(_closure(self)->_function);\r
+       switch(type(self))\r
+       {\r
+       case OT_CLOSURE:{\r
+               SQClosure *clo = _closure(self);\r
+               SQFunctionProto *fp = clo->_function;\r
+               if(((SQUnsignedInteger)fp->_noutervalues) > nval) {\r
+                       v->Push(*(_outer(clo->_outervalues[nval])->_valptr));\r
                        SQOuterVar &ov = fp->_outervalues[nval];\r
                        name = _stringval(ov._name);\r
                }\r
+                                       }\r
+               break;\r
+       case OT_NATIVECLOSURE:{\r
+               SQNativeClosure *clo = _nativeclosure(self);\r
+               if(clo->_noutervalues > nval) {\r
+                       v->Push(clo->_outervalues[nval]);\r
+                       name = _SC("@NATIVE");\r
+               }\r
+                                                 }\r
+               break;\r
+       default: break; //shutup compiler\r
        }\r
        return name;\r
 }\r
@@ -1073,22 +1243,24 @@ SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
        SQObjectPtr &self=stack_get(v,idx);\r
        switch(type(self))\r
        {\r
-       case OT_CLOSURE:\r
-               if(_closure(self)->_outervalues.size()>nval){\r
-                       _closure(self)->_outervalues[nval]=stack_get(v,-1);\r
+       case OT_CLOSURE:{\r
+               SQFunctionProto *fp = _closure(self)->_function;\r
+               if(((SQUnsignedInteger)fp->_noutervalues) > nval){\r
+                       *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);\r
                }\r
                else return sq_throwerror(v,_SC("invalid free var index"));\r
+                                       }\r
                break;\r
        case OT_NATIVECLOSURE:\r
-               if(_nativeclosure(self)->_outervalues.size()>nval){\r
-                       _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1);\r
+               if(_nativeclosure(self)->_noutervalues > nval){\r
+                       _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1);\r
                }\r
                else return sq_throwerror(v,_SC("invalid free var index"));\r
                break;\r
        default:\r
                return sq_aux_invalidtype(v,type(self));\r
        }\r
-       v->Pop(1);\r
+       v->Pop();\r
        return SQ_OK;\r
 }\r
 \r
@@ -1134,6 +1306,77 @@ SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)
        return sq_throwerror(v,_SC("wrong index"));\r
 }\r
 \r
+SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
+       SQObjectPtr &key = stack_get(v,-1);\r
+       SQTable *m = _class(*o)->_members;\r
+       SQObjectPtr val;\r
+       if(m->Get(key,val)) {\r
+               handle->_static = _isfield(val) ? SQFalse : SQTrue;\r
+               handle->_index = _member_idx(val);\r
+               v->Pop();\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong index"));\r
+}\r
+\r
+SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val)\r
+{\r
+       switch(type(self)) {\r
+               case OT_INSTANCE: {\r
+                               SQInstance *i = _instance(self);\r
+                               if(handle->_static) {\r
+                                       SQClass *c = i->_class;\r
+                                       val = &c->_methods[handle->_index].val;\r
+                               }\r
+                               else {\r
+                                       val = &i->_values[handle->_index];\r
+                                       \r
+                               }\r
+                       }\r
+                       break;\r
+               case OT_CLASS: {\r
+                               SQClass *c = _class(self);\r
+                               if(handle->_static) {\r
+                                       val = &c->_methods[handle->_index].val;\r
+                               }\r
+                               else {\r
+                                       val = &c->_defaultvalues[handle->_index].val;\r
+                               }\r
+                       }\r
+                       break;\r
+               default:\r
+                       return sq_throwerror(v,_SC("wrong type(expected class or instance)"));\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)\r
+{\r
+       SQObjectPtr &self = stack_get(v,idx);\r
+       SQObjectPtr *val = NULL;\r
+       if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {\r
+               return SQ_ERROR;\r
+       }\r
+       v->Push(_realval(*val));\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)\r
+{\r
+       SQObjectPtr &self = stack_get(v,idx);\r
+       SQObjectPtr &newval = stack_get(v,-1);\r
+       SQObjectPtr *val = NULL;\r
+       if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {\r
+               return SQ_ERROR;\r
+       }\r
+       *val = newval;\r
+       v->Pop();\r
+       return SQ_OK;\r
+}\r
+\r
 SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)\r
 {\r
        SQObjectPtr *o = NULL;\r
@@ -1141,7 +1384,7 @@ SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)
        if(_class(*o)->_base)\r
                v->Push(SQObjectPtr(_class(*o)->_base));\r
        else\r
-               v->Push(_null_);\r
+               v->PushNull();\r
        return SQ_OK;\r
 }\r
 \r
@@ -1244,9 +1487,10 @@ void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
        dest->Push(stack_get(src,idx));\r
 }\r
 \r
-void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc)\r
+void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc)\r
 {\r
        _ss(v)->_printfunc = printfunc;\r
+       _ss(v)->_errorfunc = errfunc;\r
 }\r
 \r
 SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)\r
@@ -1254,6 +1498,11 @@ SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
        return _ss(v)->_printfunc;\r
 }\r
 \r
+SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)\r
+{\r
+       return _ss(v)->_errorfunc;\r
+}\r
+\r
 void *sq_malloc(SQUnsignedInteger size)\r
 {\r
        return SQ_MALLOC(size);\r
old mode 100755 (executable)
new mode 100644 (file)
index 7f4faa9..c3a57ab
@@ -18,6 +18,7 @@ public:
        }\r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
+       SQObjectType GetType() {return OT_ARRAY;}\r
 #endif\r
        void Finalize(){\r
                _values.resize(0);\r
@@ -53,9 +54,14 @@ public:
                //nothing to iterate anymore\r
                return -1;\r
        }\r
-       SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; }\r
+       SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),0); anew->_values.copy(_values); return anew; }\r
        SQInteger Size() const {return _values.size();}\r
-       void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); }\r
+       void Resize(SQInteger size)\r
+       {\r
+               SQObjectPtr _null;\r
+               Resize(size,_null);\r
+       }\r
+       void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); }\r
        void Reserve(SQInteger size) { _values.reserve(size); }\r
        void Append(const SQObject &o){_values.push_back(o);}\r
        void Extend(const SQArray *a);\r
@@ -82,6 +88,7 @@ public:
        {\r
                sq_delete(this,SQArray);\r
        }\r
+       \r
        SQObjectPtrVec _values;\r
 };\r
 #endif //_SQARRAY_H_\r
old mode 100755 (executable)
new mode 100644 (file)
index 9b1fb5b..4a7d39d
 bool str2num(const SQChar *s,SQObjectPtr &res)\r
 {\r
        SQChar *end;\r
-       if(scstrstr(s,_SC("."))){\r
+       const SQChar *e = s;\r
+       SQBool isfloat = SQFalse;\r
+       SQChar c;\r
+       while((c = *e) != _SC('\0'))\r
+       {\r
+               if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation\r
+                       isfloat = SQTrue;\r
+                       break;\r
+               }\r
+               e++;\r
+       }\r
+       if(isfloat){\r
                SQFloat r = SQFloat(scstrtod(s,&end));\r
                if(s == end) return false;\r
                res = r;\r
-               return true;\r
        }\r
        else{\r
                SQInteger r = SQInteger(scstrtol(s,&end,10));\r
                if(s == end) return false;\r
                res = r;\r
-               return true;\r
        }\r
+       return true;\r
 }\r
 \r
 static SQInteger base_dummy(HSQUIRRELVM v)\r
@@ -41,6 +51,11 @@ static SQInteger base_collectgarbage(HSQUIRRELVM v)
        sq_pushinteger(v, sq_collectgarbage(v));\r
        return 1;\r
 }\r
+static SQInteger base_resurectureachable(HSQUIRRELVM v)\r
+{\r
+       sq_resurrectunreachable(v);\r
+       return 1;\r
+}\r
 #endif\r
 \r
 static SQInteger base_getroottable(HSQUIRRELVM v)\r
@@ -58,7 +73,7 @@ static SQInteger base_getconsttable(HSQUIRRELVM v)
 \r
 static SQInteger base_setroottable(HSQUIRRELVM v)\r
 {\r
-       SQObjectPtr &o=stack_get(v,2);\r
+       SQObjectPtr o = v->_roottable;\r
        if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;\r
        v->Push(o);\r
        return 1;\r
@@ -66,7 +81,7 @@ static SQInteger base_setroottable(HSQUIRRELVM v)
 \r
 static SQInteger base_setconsttable(HSQUIRRELVM v)\r
 {\r
-       SQObjectPtr &o=stack_get(v,2);\r
+       SQObjectPtr o = _ss(v)->_consts;\r
        if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;\r
        v->Push(o);\r
        return 1;\r
@@ -87,17 +102,17 @@ static SQInteger base_setdebughook(HSQUIRRELVM v)
 static SQInteger base_enabledebuginfo(HSQUIRRELVM v)\r
 {\r
        SQObjectPtr &o=stack_get(v,2);\r
-       sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);\r
+       \r
+       sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue);\r
        return 0;\r
 }\r
 \r
-static SQInteger base_getstackinfos(HSQUIRRELVM v)\r
+static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level)\r
 {\r
-       SQInteger level;\r
        SQStackInfos si;\r
        SQInteger seq = 0;\r
        const SQChar *name = NULL;\r
-       sq_getinteger(v, -1, &level);\r
+       \r
        if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))\r
        {\r
                const SQChar *fn = _SC("unknown");\r
@@ -107,33 +122,39 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v)
                sq_newtable(v);\r
                sq_pushstring(v, _SC("func"), -1);\r
                sq_pushstring(v, fn, -1);\r
-               sq_createslot(v, -3);\r
+               sq_newslot(v, -3, SQFalse);\r
                sq_pushstring(v, _SC("src"), -1);\r
                sq_pushstring(v, src, -1);\r
-               sq_createslot(v, -3);\r
+               sq_newslot(v, -3, SQFalse);\r
                sq_pushstring(v, _SC("line"), -1);\r
                sq_pushinteger(v, si.line);\r
-               sq_createslot(v, -3);\r
+               sq_newslot(v, -3, SQFalse);\r
                sq_pushstring(v, _SC("locals"), -1);\r
                sq_newtable(v);\r
                seq=0;\r
                while ((name = sq_getlocal(v, level, seq))) {\r
                        sq_pushstring(v, name, -1);\r
                        sq_push(v, -2);\r
-                       sq_createslot(v, -4);\r
+                       sq_newslot(v, -4, SQFalse);\r
                        sq_pop(v, 1);\r
                        seq++;\r
                }\r
-               sq_createslot(v, -3);\r
+               sq_newslot(v, -3, SQFalse);\r
                return 1;\r
        }\r
 \r
        return 0;\r
 }\r
+static SQInteger base_getstackinfos(HSQUIRRELVM v)\r
+{\r
+       SQInteger level;\r
+       sq_getinteger(v, -1, &level);\r
+       return __getcallstackinfos(v,level);\r
+}\r
 \r
 static SQInteger base_assert(HSQUIRRELVM v)\r
 {\r
-       if(v->IsFalse(stack_get(v,2))){\r
+       if(SQVM::IsFalse(stack_get(v,2))){\r
                return sq_throwerror(v,_SC("assertion failed"));\r
        }\r
        return 0;\r
@@ -170,6 +191,15 @@ static SQInteger base_print(HSQUIRRELVM v)
        return 0;\r
 }\r
 \r
+static SQInteger base_error(HSQUIRRELVM v)\r
+{\r
+       const SQChar *str;\r
+       sq_tostring(v,2);\r
+       sq_getstring(v,-1,&str);\r
+       if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str);\r
+       return 0;\r
+}\r
+\r
 static SQInteger base_compilestring(HSQUIRRELVM v)\r
 {\r
        SQInteger nargs=sq_gettop(v);\r
@@ -189,7 +219,7 @@ static SQInteger base_compilestring(HSQUIRRELVM v)
 static SQInteger base_newthread(HSQUIRRELVM v)\r
 {\r
        SQObjectPtr &func = stack_get(v,2);\r
-       SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;\r
+       SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2;\r
        HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);\r
        sq_move(newv,v,-2);\r
        return 1;\r
@@ -222,6 +252,16 @@ static SQInteger base_type(HSQUIRRELVM v)
        return 1;\r
 }\r
 \r
+static SQInteger base_callee(HSQUIRRELVM v)\r
+{\r
+       if(v->_callsstacksize > 1)\r
+       {\r
+               v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);\r
+               return 1;\r
+       }\r
+       return sq_throwerror(v,_SC("no closure in the calls stack"));\r
+}\r
+\r
 static SQRegFunction base_funcs[]={\r
        //generic\r
        {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},\r
@@ -234,14 +274,17 @@ static SQRegFunction base_funcs[]={
        {_SC("setconsttable"),base_setconsttable,2, NULL},\r
        {_SC("assert"),base_assert,2, NULL},\r
        {_SC("print"),base_print,2, NULL},\r
+       {_SC("error"),base_error,2, NULL},\r
        {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},\r
        {_SC("newthread"),base_newthread,2, _SC(".c")},\r
        {_SC("suspend"),base_suspend,-1, NULL},\r
        {_SC("array"),base_array,-2, _SC(".n")},\r
        {_SC("type"),base_type,2, NULL},\r
+       {_SC("callee"),base_callee,0,NULL},\r
        {_SC("dummy"),base_dummy,0,NULL},\r
 #ifndef NO_GARBAGE_COLLECTOR\r
-       {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},\r
+       {_SC("collectgarbage"),base_collectgarbage,0, NULL},\r
+       {_SC("resurrectunreachable"),base_resurectureachable,0, NULL},\r
 #endif\r
        {0,0}\r
 };\r
@@ -255,21 +298,25 @@ void sq_base_register(HSQUIRRELVM v)
                sq_newclosure(v,base_funcs[i].f,0);\r
                sq_setnativeclosurename(v,-1,base_funcs[i].name);\r
                sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);\r
-               sq_createslot(v,-3);\r
+               sq_newslot(v,-3, SQFalse);\r
                i++;\r
        }\r
+       \r
+       sq_pushstring(v,_SC("_versionnumber_"),-1);\r
+       sq_pushinteger(v,SQUIRREL_VERSION_NUMBER);\r
+       sq_newslot(v,-3, SQFalse);\r
        sq_pushstring(v,_SC("_version_"),-1);\r
        sq_pushstring(v,SQUIRREL_VERSION,-1);\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3, SQFalse);\r
        sq_pushstring(v,_SC("_charsize_"),-1);\r
        sq_pushinteger(v,sizeof(SQChar));\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3, SQFalse);\r
        sq_pushstring(v,_SC("_intsize_"),-1);\r
        sq_pushinteger(v,sizeof(SQInteger));\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3, SQFalse);\r
        sq_pushstring(v,_SC("_floatsize_"),-1);\r
        sq_pushinteger(v,sizeof(SQFloat));\r
-       sq_createslot(v,-3);\r
+       sq_newslot(v,-3, SQFalse);\r
        sq_pop(v,1);\r
 }\r
 \r
@@ -298,7 +345,7 @@ static SQInteger default_delegate_tofloat(HSQUIRRELVM v)
                v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));\r
                break;\r
        default:\r
-               v->Push(_null_);\r
+               v->PushNull();\r
                break;\r
        }\r
        return 1;\r
@@ -323,7 +370,7 @@ static SQInteger default_delegate_tointeger(HSQUIRRELVM v)
                v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));\r
                break;\r
        default:\r
-               v->Push(_null_);\r
+               v->PushNull();\r
                break;\r
        }\r
        return 1;\r
@@ -356,6 +403,7 @@ static SQInteger number_delegate_tochar(HSQUIRRELVM v)
 }\r
 \r
 \r
+\r
 /////////////////////////////////////////////////////////////////\r
 //TABLE DEFAULT DELEGATE\r
 \r
@@ -377,27 +425,41 @@ static SQInteger container_rawexists(HSQUIRRELVM v)
        return 1;\r
 }\r
 \r
-static SQInteger table_rawset(HSQUIRRELVM v)\r
+static SQInteger container_rawset(HSQUIRRELVM v)\r
 {\r
        return sq_rawset(v,-3);\r
 }\r
 \r
 \r
-static SQInteger table_rawget(HSQUIRRELVM v)\r
+static SQInteger container_rawget(HSQUIRRELVM v)\r
 {\r
        return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;\r
 }\r
 \r
+static SQInteger table_setdelegate(HSQUIRRELVM v)\r
+{\r
+       if(SQ_FAILED(sq_setdelegate(v,-2)))\r
+               return SQ_ERROR;\r
+       sq_push(v,-1); // -1 because sq_setdelegate pops 1\r
+       return 1;\r
+}\r
+\r
+static SQInteger table_getdelegate(HSQUIRRELVM v)\r
+{\r
+       return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;\r
+}\r
 \r
 SQRegFunction SQSharedState::_table_default_delegate_funcz[]={\r
        {_SC("len"),default_delegate_len,1, _SC("t")},\r
-       {_SC("rawget"),table_rawget,2, _SC("t")},\r
-       {_SC("rawset"),table_rawset,3, _SC("t")},\r
+       {_SC("rawget"),container_rawget,2, _SC("t")},\r
+       {_SC("rawset"),container_rawset,3, _SC("t")},\r
        {_SC("rawdelete"),table_rawdelete,2, _SC("t")},\r
        {_SC("rawin"),container_rawexists,2, _SC("t")},\r
        {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
        {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
        {_SC("clear"),obj_clear,1, _SC(".")},\r
+       {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},\r
+       {_SC("getdelegate"),table_getdelegate,1, _SC(".")},\r
        {0,0}\r
 };\r
 \r
@@ -472,6 +534,111 @@ static SQInteger array_resize(HSQUIRRELVM v)
        return sq_throwerror(v, _SC("size must be a number"));\r
 }\r
 \r
+static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {\r
+       SQObjectPtr temp;\r
+       SQInteger size = src->Size();\r
+       for(SQInteger n = 0; n < size; n++) {\r
+               src->Get(n,temp);\r
+               v->Push(src);\r
+               v->Push(temp);\r
+               if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {\r
+                       return SQ_ERROR;\r
+               }\r
+               dest->Set(n,v->GetUp(-1));\r
+               v->Pop();\r
+       }\r
+       return 0;\r
+}\r
+\r
+static SQInteger array_map(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v,1);\r
+       SQInteger size = _array(o)->Size();\r
+       SQObjectPtr ret = SQArray::Create(_ss(v),size);\r
+       if(SQ_FAILED(__map_array(_array(ret),_array(o),v)))\r
+               return SQ_ERROR;\r
+       v->Push(ret);\r
+       return 1;\r
+}\r
+\r
+static SQInteger array_apply(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v,1);\r
+       if(SQ_FAILED(__map_array(_array(o),_array(o),v)))\r
+               return SQ_ERROR;\r
+       return 0;\r
+}\r
+\r
+static SQInteger array_reduce(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v,1);\r
+       SQArray *a = _array(o);\r
+       SQInteger size = a->Size();\r
+       if(size == 0) {\r
+               return 0;\r
+       }\r
+       SQObjectPtr res;\r
+       a->Get(0,res);\r
+       if(size > 1) {\r
+               SQObjectPtr other;\r
+               for(SQInteger n = 1; n < size; n++) {\r
+                       a->Get(n,other);\r
+                       v->Push(o);\r
+                       v->Push(res);\r
+                       v->Push(other);\r
+                       if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {\r
+                               return SQ_ERROR;\r
+                       }\r
+                       res = v->GetUp(-1);\r
+                       v->Pop();\r
+               }\r
+       }\r
+       v->Push(res);\r
+       return 1;\r
+}\r
+\r
+static SQInteger array_filter(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v,1);\r
+       SQArray *a = _array(o);\r
+       SQObjectPtr ret = SQArray::Create(_ss(v),0);\r
+       SQInteger size = a->Size();\r
+       SQObjectPtr val;\r
+       for(SQInteger n = 0; n < size; n++) {\r
+               a->Get(n,val);\r
+               v->Push(o);\r
+               v->Push(n);\r
+               v->Push(val);\r
+               if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {\r
+                       return SQ_ERROR;\r
+               }\r
+               if(!SQVM::IsFalse(v->GetUp(-1))) {\r
+                       _array(ret)->Append(val);\r
+               }\r
+               v->Pop();\r
+       }\r
+       v->Push(ret);\r
+       return 1;\r
+}\r
+\r
+static SQInteger array_find(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v,1);\r
+       SQObjectPtr &val = stack_get(v,2);\r
+       SQArray *a = _array(o);\r
+       SQInteger size = a->Size();\r
+       SQObjectPtr temp;\r
+       for(SQInteger n = 0; n < size; n++) {\r
+               bool res = false;\r
+               a->Get(n,temp);\r
+               if(SQVM::IsEqual(temp,val,res) && res) {\r
+                       v->Push(n);\r
+                       return 1;\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
 \r
 bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret)\r
 {\r
@@ -499,7 +666,7 @@ bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQ
        return true;\r
 }\r
 \r
-bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, int root, int bottom, SQInteger func)\r
+bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)\r
 {\r
        SQInteger maxChild;\r
        SQInteger done = 0;\r
@@ -524,6 +691,11 @@ bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, int root, int bottom, SQIntege
                if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))\r
                        return false;\r
                if (ret < 0) {\r
+                       if (root == maxChild) {\r
+                v->Raise_Error(_SC("inconsistent compare function"));\r
+                return false; // We'd be swapping ourselve. The compare function is incorrect\r
+            }\r
+\r
                        _Swap(arr->_values[root],arr->_values[maxChild]);\r
                        root = maxChild;\r
                }\r
@@ -602,6 +774,11 @@ SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
        {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
        {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
        {_SC("clear"),obj_clear,1, _SC(".")},\r
+       {_SC("map"),array_map,2, _SC("ac")}, \r
+       {_SC("apply"),array_apply,2, _SC("ac")}, \r
+       {_SC("reduce"),array_reduce,2, _SC("ac")}, \r
+       {_SC("filter"),array_filter,2, _SC("ac")},\r
+       {_SC("find"),array_find,2, _SC("a.")},\r
        {0,0}\r
 };\r
 \r
@@ -717,12 +894,16 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) {
        SQObject o = stack_get(v,1);\r
        SQTable *res = SQTable::Create(_ss(v),4);\r
        if(type(o) == OT_CLOSURE) {\r
-               SQFunctionProto *f = _funcproto(_closure(o)->_function);\r
+               SQFunctionProto *f = _closure(o)->_function;\r
                SQInteger nparams = f->_nparameters + (f->_varparams?1:0);\r
                SQObjectPtr params = SQArray::Create(_ss(v),nparams);\r
+    SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams);\r
                for(SQInteger n = 0; n<f->_nparameters; n++) {\r
                        _array(params)->Set((SQInteger)n,f->_parameters[n]);\r
                }\r
+    for(SQInteger j = 0; j<f->_ndefaultparams; j++) {\r
+                       _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]);\r
+               }\r
                if(f->_varparams) {\r
                        _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1));\r
                }\r
@@ -731,6 +912,7 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) {
                res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename);\r
                res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);\r
                res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);\r
+    res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams);\r
        }\r
        else { //OT_NATIVECLOSURE \r
                SQNativeClosure *nc = _nativeclosure(o);\r
@@ -752,6 +934,7 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) {
 }\r
 \r
 \r
+\r
 SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={\r
        {_SC("call"),closure_call,-1, _SC("c")},\r
        {_SC("pcall"),closure_pcall,-1, _SC("c")},\r
@@ -784,17 +967,15 @@ SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
 };\r
 \r
 //THREAD DEFAULT DELEGATE\r
-\r
 static SQInteger thread_call(HSQUIRRELVM v)\r
 {\r
-       \r
        SQObjectPtr o = stack_get(v,1);\r
        if(type(o) == OT_THREAD) {\r
                SQInteger nparams = sq_gettop(v);\r
                _thread(o)->Push(_thread(o)->_roottable);\r
                for(SQInteger i = 2; i<(nparams+1); i++)\r
                        sq_move(_thread(o),v,i);\r
-               if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) {\r
+               if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) {\r
                        sq_move(v,_thread(o),-1);\r
                        sq_pop(_thread(o),1);\r
                        return 1;\r
@@ -860,46 +1041,117 @@ static SQInteger thread_getstatus(HSQUIRRELVM v)
        return 1;\r
 }\r
 \r
+static SQInteger thread_getstackinfos(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr o = stack_get(v,1);\r
+       if(type(o) == OT_THREAD) {\r
+               SQVM *thread = _thread(o);\r
+               SQInteger threadtop = sq_gettop(thread);\r
+               SQInteger level;\r
+               sq_getinteger(v,-1,&level);\r
+               SQRESULT res = __getcallstackinfos(thread,level);\r
+               if(SQ_FAILED(res))\r
+               {\r
+                       sq_settop(thread,threadtop);\r
+                       if(type(thread->_lasterror) == OT_STRING) {\r
+                               sq_throwerror(v,_stringval(thread->_lasterror));\r
+                       }\r
+                       else {\r
+                               sq_throwerror(v,_SC("unknown error"));\r
+                       }\r
+               }\r
+               if(res > 0) {\r
+                       //some result\r
+                       sq_move(v,thread,-1);\r
+                       sq_settop(thread,threadtop);\r
+                       return 1;\r
+               }\r
+               //no result\r
+               sq_settop(thread,threadtop);\r
+               return 0;\r
+               \r
+       }\r
+       return sq_throwerror(v,_SC("wrong parameter"));\r
+}\r
+\r
 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {\r
        {_SC("call"), thread_call, -1, _SC("v")},\r
        {_SC("wakeup"), thread_wakeup, -1, _SC("v")},\r
        {_SC("getstatus"), thread_getstatus, 1, _SC("v")},\r
        {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+       {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")},\r
        {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
        {0,0},\r
 };\r
 \r
 static SQInteger class_getattributes(HSQUIRRELVM v)\r
 {\r
-       if(SQ_SUCCEEDED(sq_getattributes(v,-2)))\r
-               return 1;\r
-       return SQ_ERROR;\r
+       return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR;\r
 }\r
 \r
 static SQInteger class_setattributes(HSQUIRRELVM v)\r
 {\r
-       if(SQ_SUCCEEDED(sq_setattributes(v,-3)))\r
-               return 1;\r
-       return SQ_ERROR;\r
+       return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR;\r
 }\r
 \r
 static SQInteger class_instance(HSQUIRRELVM v)\r
 {\r
-       if(SQ_SUCCEEDED(sq_createinstance(v,-1)))\r
-               return 1;\r
-       return SQ_ERROR;\r
+       return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger class_getbase(HSQUIRRELVM v)\r
+{\r
+       return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger class_newmember(HSQUIRRELVM v)\r
+{\r
+       SQInteger top = sq_gettop(v);\r
+       SQBool bstatic = SQFalse;\r
+       if(top == 5)\r
+       {\r
+               sq_tobool(v,-1,&bstatic);\r
+               sq_pop(v,1);\r
+       }\r
+\r
+       if(top < 4) {\r
+               sq_pushnull(v);\r
+       }\r
+       return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger class_rawnewmember(HSQUIRRELVM v)\r
+{\r
+       SQInteger top = sq_gettop(v);\r
+       SQBool bstatic = SQFalse;\r
+       if(top == 5)\r
+       {\r
+               sq_tobool(v,-1,&bstatic);\r
+               sq_pop(v,1);\r
+       }\r
+\r
+       if(top < 4) {\r
+               sq_pushnull(v);\r
+       }\r
+       return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR;\r
 }\r
 \r
 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {\r
        {_SC("getattributes"), class_getattributes, 2, _SC("y.")},\r
        {_SC("setattributes"), class_setattributes, 3, _SC("y..")},\r
+       {_SC("rawget"),container_rawget,2, _SC("y")},\r
+       {_SC("rawset"),container_rawset,3, _SC("y")},\r
        {_SC("rawin"),container_rawexists,2, _SC("y")},\r
        {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
        {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
        {_SC("instance"),class_instance,1, _SC("y")},\r
+       {_SC("getbase"),class_getbase,1, _SC("y")},\r
+       {_SC("newmember"),class_newmember,-3, _SC("y")},\r
+       {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")},\r
        {0,0}\r
 };\r
 \r
+\r
 static SQInteger instance_getclass(HSQUIRRELVM v)\r
 {\r
        if(SQ_SUCCEEDED(sq_getclass(v,1)))\r
@@ -909,6 +1161,8 @@ static SQInteger instance_getclass(HSQUIRRELVM v)
 \r
 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {\r
        {_SC("getclass"), instance_getclass, 1, _SC("x")},\r
+       {_SC("rawget"),container_rawget,2, _SC("x")},\r
+       {_SC("rawset"),container_rawset,3, _SC("x")},\r
        {_SC("rawin"),container_rawexists,2, _SC("x")},\r
        {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
        {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
@@ -929,4 +1183,3 @@ SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
        {0,0}\r
 };\r
 \r
-\r
old mode 100755 (executable)
new mode 100644 (file)
index f4bcbea..086dd2a
@@ -5,33 +5,39 @@
 #include "sqvm.h"\r
 #include "sqtable.h"\r
 #include "sqclass.h"\r
+#include "sqfuncproto.h"\r
 #include "sqclosure.h"\r
 \r
+\r
+\r
 SQClass::SQClass(SQSharedState *ss,SQClass *base)\r
 {\r
        _base = base;\r
        _typetag = 0;\r
        _hook = NULL;\r
        _udsize = 0;\r
-       _metamethods.resize(MT_LAST); //size it to max size\r
+       _locked = false;\r
+       _constructoridx = -1;\r
        if(_base) {\r
+               _constructoridx = _base->_constructoridx;\r
+               _udsize = _base->_udsize;\r
                _defaultvalues.copy(base->_defaultvalues);\r
                _methods.copy(base->_methods);\r
-               _metamethods.copy(base->_metamethods);\r
+               _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);\r
                __ObjAddRef(_base);\r
        }\r
        _members = base?base->_members->Clone() : SQTable::Create(ss,0);\r
        __ObjAddRef(_members);\r
-       _locked = false;\r
+       \r
        INIT_CHAIN();\r
        ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
 }\r
 \r
 void SQClass::Finalize() { \r
-       _attributes = _null_;\r
-       _defaultvalues.resize(0);\r
+       _attributes.Null();\r
+       _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());\r
        _methods.resize(0);\r
-       _metamethods.resize(0);\r
+       _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);\r
        __ObjRelease(_members);\r
        if(_base) {\r
                __ObjRelease(_base);\r
@@ -47,28 +53,40 @@ SQClass::~SQClass()
 bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)\r
 {\r
        SQObjectPtr temp;\r
-       if(_locked) \r
+       bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;\r
+       if(_locked && !belongs_to_static_table) \r
                return false; //the class already has an instance so cannot be modified\r
        if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value\r
        {\r
                _defaultvalues[_member_idx(temp)].val = val;\r
                return true;\r
        }\r
-       if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) {\r
+       if(belongs_to_static_table) {\r
                SQInteger mmidx;\r
                if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && \r
                        (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {\r
                        _metamethods[mmidx] = val;\r
                } \r
                else {\r
+                       SQObjectPtr theval = val;\r
+                       if(_base && type(val) == OT_CLOSURE) {\r
+                               theval = _closure(val)->Clone();\r
+                               _closure(theval)->_base = _base;\r
+                               __ObjAddRef(_base); //ref for the closure\r
+                       }\r
                        if(type(temp) == OT_NULL) {\r
+                               bool isconstructor;\r
+                               SQVM::IsEqual(ss->_constructoridx, key, isconstructor);\r
+                               if(isconstructor) {\r
+                                       _constructoridx = (SQInteger)_methods.size();\r
+                               }\r
                                SQClassMember m;\r
-                               m.val = val;\r
+                               m.val = theval;\r
                                _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));\r
                                _methods.push_back(m);\r
                        }\r
                        else {\r
-                               _methods[_member_idx(temp)].val = val;\r
+                               _methods[_member_idx(temp)].val = theval;\r
                        }\r
                }\r
                return true;\r
@@ -162,9 +180,10 @@ void SQInstance::Finalize()
 {\r
        SQUnsignedInteger nvalues = _class->_defaultvalues.size();\r
        __ObjRelease(_class);\r
-       for(SQUnsignedInteger i = 0; i < nvalues; i++) {\r
-               _values[i] = _null_;\r
-       }\r
+       _NULL_SQOBJECT_VECTOR(_values,nvalues);\r
+       //for(SQUnsignedInteger i = 0; i < nvalues; i++) {\r
+//             _values[i].Null();\r
+//     }\r
 }\r
 \r
 SQInstance::~SQInstance()\r
old mode 100755 (executable)
new mode 100644 (file)
index 281b0fa..4e40d55
@@ -5,13 +5,12 @@
 struct SQInstance;\r
 \r
 struct SQClassMember {\r
-       SQClassMember(){}\r
-       SQClassMember(const SQClassMember &o) {\r
-               val = o.val;\r
-               attrs = o.attrs;\r
-       }\r
        SQObjectPtr val;\r
        SQObjectPtr attrs;\r
+       void Null() {\r
+               val.Null();\r
+               attrs.Null();\r
+       }\r
 };\r
 \r
 typedef sqvector<SQClassMember> SQClassMemberVec;\r
@@ -50,6 +49,14 @@ public:
                }\r
                return false;\r
        }\r
+       bool GetConstructor(SQObjectPtr &ctor)\r
+       {\r
+               if(_constructoridx != -1) {\r
+                       ctor = _methods[_constructoridx].val;\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
        bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);\r
        bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);\r
        void Lock() { _locked = true; if(_base) _base->Lock(); }\r
@@ -60,6 +67,7 @@ public:
        void Finalize();\r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable ** );\r
+       SQObjectType GetType() {return OT_CLASS;}\r
 #endif\r
        SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
        SQInstance *CreateInstance();\r
@@ -67,16 +75,17 @@ public:
        SQClass *_base;\r
        SQClassMemberVec _defaultvalues;\r
        SQClassMemberVec _methods;\r
-       SQObjectPtrVec _metamethods;\r
+       SQObjectPtr _metamethods[MT_LAST];\r
        SQObjectPtr _attributes;\r
        SQUserPointer _typetag;\r
        SQRELEASEHOOK _hook;\r
        bool _locked;\r
+       SQInteger _constructoridx;\r
        SQInteger _udsize;\r
 };\r
 \r
 #define calcinstancesize(_theclass_) \\r
-       (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))\r
+       (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) +  (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))\r
 \r
 struct SQInstance : public SQDelegable \r
 {\r
@@ -138,6 +147,7 @@ public:
        void Finalize();\r
 #ifndef NO_GARBAGE_COLLECTOR \r
        void Mark(SQCollectable ** );\r
+       SQObjectType GetType() {return OT_INSTANCE;}\r
 #endif\r
        bool InstanceOf(SQClass *trg);\r
        bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);\r
old mode 100755 (executable)
new mode 100644 (file)
index 949fb38..07b3efc
 #ifndef _SQCLOSURE_H_\r
 #define _SQCLOSURE_H_\r
 \r
-struct SQFunctionProto;\r
 \r
+#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr)))\r
+\r
+struct SQFunctionProto;\r
+struct SQClass;\r
 struct SQClosure : public CHAINABLE_OBJ\r
 {\r
 private:\r
-       SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
+       SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;}\r
 public:\r
        static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){\r
-               SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure));\r
+               SQInteger size = _CALC_CLOSURE_SIZE(func);\r
+               SQClosure *nc=(SQClosure*)SQ_MALLOC(size);\r
                new (nc) SQClosure(ss,func);\r
+               nc->_outervalues = (SQObjectPtr *)(nc + 1);\r
+               nc->_defaultparams = &nc->_outervalues[func->_noutervalues];\r
+               _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues);\r
+               _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams);\r
                return nc;\r
        }\r
        void Release(){\r
-               sq_delete(this,SQClosure);\r
+               SQFunctionProto *f = _function;\r
+               SQInteger size = _CALC_CLOSURE_SIZE(f);\r
+               _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues);\r
+               _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams);\r
+               __ObjRelease(_function);\r
+               this->~SQClosure();\r
+               sq_vm_free(this,size);\r
        }\r
+       \r
        SQClosure *Clone()\r
        {\r
-               SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function));\r
+               SQFunctionProto *f = _function;\r
+               SQClosure * ret = SQClosure::Create(_opt_ss(this),f);\r
                ret->_env = _env;\r
-               ret->_outervalues.copy(_outervalues);\r
-               ret->_defaultparams.copy(_defaultparams);\r
+               if(ret->_env) __ObjAddRef(ret->_env);\r
+               _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);\r
+               _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);\r
                return ret;\r
        }\r
-       ~SQClosure()\r
-       {\r
-               REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
-       }\r
+       ~SQClosure();\r
+       \r
        bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
        static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);\r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
-       void Finalize(){_outervalues.resize(0); }\r
+       void Finalize(){\r
+               SQFunctionProto *f = _function;\r
+               _NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues);\r
+               _NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams);\r
+       }\r
+       SQObjectType GetType() {return OT_CLOSURE;}\r
 #endif\r
-       SQObjectPtr _env;\r
-       SQObjectPtr _function;\r
-       SQObjectPtrVec _outervalues;\r
-       SQObjectPtrVec _defaultparams;\r
+       SQWeakRef *_env;\r
+       SQClass *_base;\r
+       SQFunctionProto *_function;\r
+       SQObjectPtr *_outervalues;\r
+       SQObjectPtr *_defaultparams;\r
 };\r
+\r
+//////////////////////////////////////////////\r
+struct SQOuter : public CHAINABLE_OBJ\r
+{\r
+\r
+private:\r
+       SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); }\r
+\r
+public:\r
+       static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer)\r
+       {\r
+               SQOuter *nc  = (SQOuter*)SQ_MALLOC(sizeof(SQOuter));\r
+               new (nc) SQOuter(ss, outer);\r
+               return nc;\r
+       }\r
+       ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); }\r
+\r
+       void Release()\r
+       {\r
+               this->~SQOuter();\r
+               sq_vm_free(this,sizeof(SQOuter));\r
+       }\r
+       \r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+       void Finalize() { _value.Null(); }\r
+       SQObjectType GetType() {return OT_OUTER;}\r
+#endif\r
+\r
+       SQObjectPtr *_valptr;  /* pointer to value on stack, or _value below */\r
+       SQInteger    _idx;     /* idx in stack array, for relocation */\r
+       SQObjectPtr  _value;   /* value of outer after stack frame is closed */\r
+       SQOuter     *_next;    /* pointer to next outer when frame is open   */\r
+};\r
+\r
 //////////////////////////////////////////////\r
 struct SQGenerator : public CHAINABLE_OBJ \r
 {\r
@@ -59,60 +115,75 @@ public:
     void Kill(){\r
                _state=eDead;\r
                _stack.resize(0);\r
-               _closure=_null_;}\r
+               _closure.Null();}\r
        void Release(){\r
                sq_delete(this,SQGenerator);\r
        }\r
-       bool Yield(SQVM *v);\r
-       bool Resume(SQVM *v,SQInteger target);\r
+       \r
+       bool Yield(SQVM *v,SQInteger target);\r
+       bool Resume(SQVM *v,SQObjectPtr &dest);\r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
-       void Finalize(){_stack.resize(0);_closure=_null_;}\r
+       void Finalize(){_stack.resize(0);_closure.Null();}\r
+       SQObjectType GetType() {return OT_GENERATOR;}\r
 #endif\r
        SQObjectPtr _closure;\r
        SQObjectPtrVec _stack;\r
-       SQObjectPtrVec _vargsstack;\r
        SQVM::CallInfo _ci;\r
        ExceptionsTraps _etraps;\r
        SQGeneratorState _state;\r
 };\r
 \r
+#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr)))\r
+\r
 struct SQNativeClosure : public CHAINABLE_OBJ\r
 {\r
 private:\r
-       SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);        }\r
+       SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;}\r
 public:\r
-       static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func)\r
+       static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters)\r
        {\r
-               SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure));\r
+               SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters);\r
+               SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size);\r
                new (nc) SQNativeClosure(ss,func);\r
+               nc->_outervalues = (SQObjectPtr *)(nc + 1);\r
+               nc->_noutervalues = nouters;\r
+               _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues);\r
                return nc;\r
        }\r
        SQNativeClosure *Clone()\r
        {\r
-               SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function);\r
+               SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues);\r
                ret->_env = _env;\r
+               if(ret->_env) __ObjAddRef(ret->_env);\r
                ret->_name = _name;\r
-               ret->_outervalues.copy(_outervalues);\r
+               _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues);\r
                ret->_typecheck.copy(_typecheck);\r
                ret->_nparamscheck = _nparamscheck;\r
                return ret;\r
        }\r
        ~SQNativeClosure()\r
        {\r
+               __ObjRelease(_env);\r
                REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
        }\r
        void Release(){\r
-               sq_delete(this,SQNativeClosure);\r
+               SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues);\r
+               _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues);\r
+               this->~SQNativeClosure();\r
+               sq_free(this,size);\r
        }\r
+       \r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
-       void Finalize(){_outervalues.resize(0);}\r
+       void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }\r
+       SQObjectType GetType() {return OT_NATIVECLOSURE;}\r
 #endif\r
        SQInteger _nparamscheck;\r
        SQIntVec _typecheck;\r
-       SQObjectPtrVec _outervalues;\r
-       SQObjectPtr _env;\r
+       SQObjectPtr *_outervalues;\r
+       SQUnsignedInteger _noutervalues;\r
+       SQWeakRef *_env;\r
        SQFUNCTION _function;\r
        SQObjectPtr _name;\r
 };\r
old mode 100755 (executable)
new mode 100644 (file)
index 461c2bc..1f8a20c
@@ -2,6 +2,7 @@
        see copyright notice in squirrel.h\r
 */\r
 #include "sqpcheader.h"\r
+#ifndef NO_COMPILER\r
 #include <stdarg.h>\r
 #include <setjmp.h>\r
 #include "sqopcodes.h"\r
 #include "sqvm.h"\r
 #include "sqtable.h"\r
 \r
-#define DEREF_NO_DEREF -1\r
-#define DEREF_FIELD            -2\r
+#define EXPR   1\r
+#define OBJECT 2\r
+#define BASE   3\r
+#define LOCAL  4\r
+#define OUTER  5\r
 \r
-struct ExpState\r
-{\r
-       ExpState()\r
-       {\r
-               _deref = DEREF_NO_DEREF;\r
-               _freevar = false;\r
-               _class_or_delete = false;\r
-               _funcarg = false;\r
-       }\r
-       bool _class_or_delete;\r
-       bool _funcarg;\r
-       bool _freevar;\r
-       SQInteger _deref;\r
+struct SQExpState {\r
+  SQInteger  etype;       /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */\r
+  SQInteger  epos;        /* expr. location on stack; -1 for OBJECT and BASE */\r
+  bool       donot_get;   /* signal not to deref the next value */\r
+};\r
+\r
+#define MAX_COMPILER_ERROR_LEN 256\r
+\r
+struct SQScope {\r
+       SQInteger outers;\r
+       SQInteger stacksize;\r
 };\r
 \r
-typedef sqvector<ExpState> ExpStateVec;\r
+#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \\r
+                                        _scope.outers = _fs->_outers; \\r
+                                        _scope.stacksize = _fs->GetStackSize();\r
+\r
+#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \\r
+                                                       if(_fs->CountOuters(_scope.stacksize)) { \\r
+                                                               _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \\r
+                                                       } \\r
+                                               }\r
+\r
+#define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \\r
+                                                       _fs->SetStackSize(_scope.stacksize); \\r
+                                               } \\r
+                                               _scope = __oldscope__; \\r
+                                       }\r
 \r
-#define _exst (_expstates.top())\r
+#define END_SCOPE() {  SQInteger oldouters = _fs->_outers;\\r
+                                               if(_fs->GetStackSize() != _scope.stacksize) { \\r
+                                                       _fs->SetStackSize(_scope.stacksize); \\r
+                                                       if(oldouters != _fs->_outers) { \\r
+                                                               _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \\r
+                                                       } \\r
+                                               } \\r
+                                               _scope = __oldscope__; \\r
+                                       }\r
 \r
 #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \\r
                                                        SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \\r
@@ -54,7 +78,9 @@ public:
                _lex.Init(_ss(v), rg, up,ThrowError,this);\r
                _sourcename = SQString::Create(_ss(v), sourcename);\r
                _lineinfo = lineinfo;_raiseerror = raiseerror;\r
-               compilererror = NULL;\r
+               _scope.outers = 0;\r
+               _scope.stacksize = 0;\r
+               _compilererror[0] = NULL;\r
        }\r
        static void ThrowError(void *ud, const SQChar *s) {\r
                SQCompiler *c = (SQCompiler *)ud;\r
@@ -62,36 +88,18 @@ public:
        }\r
        void Error(const SQChar *s, ...)\r
        {\r
-               static SQChar temp[256];\r
                va_list vl;\r
                va_start(vl, s);\r
-               scvsprintf(temp, s, vl);\r
+               scvsprintf(_compilererror, s, vl);\r
                va_end(vl);\r
-               compilererror = temp;\r
                longjmp(_errorjmp,1);\r
        }\r
        void Lex(){     _token = _lex.Lex();}\r
-       void PushExpState(){ _expstates.push_back(ExpState()); }\r
-       bool IsDerefToken(SQInteger tok)\r
-       {\r
-               switch(tok){\r
-               case _SC('='): case _SC('('): case TK_NEWSLOT:\r
-               case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;\r
-               }\r
-               return false;\r
-       }\r
-       ExpState PopExpState()\r
-       {\r
-               ExpState ret = _expstates.top();\r
-               _expstates.pop_back();\r
-               return ret;\r
-       }\r
        SQObject Expect(SQInteger tok)\r
        {\r
                \r
                if(_token != tok) {\r
                        if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {\r
-                               //ret = SQString::Create(_ss(_vm),_SC("constructor"));\r
                                //do nothing\r
                        }\r
                        else {\r
@@ -162,15 +170,17 @@ public:
                funcstate._name = SQString::Create(_ss(_vm), _SC("main"));\r
                _fs = &funcstate;\r
                _fs->AddParameter(_fs->CreateString(_SC("this")));\r
+               _fs->AddParameter(_fs->CreateString(_SC("vargv")));\r
+               _fs->_varparams = true;\r
                _fs->_sourcename = _sourcename;\r
                SQInteger stacksize = _fs->GetStackSize();\r
                if(setjmp(_errorjmp) == 0) {\r
                        Lex();\r
                        while(_token > 0){\r
                                Statement();\r
-                               if(_lex._prevtoken != _SC('}')) OptionalSemicolon();\r
+                               if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
                        }\r
-                       CleanStack(stacksize);\r
+                       _fs->SetStackSize(stacksize);\r
                        _fs->AddLineInfos(_lex._currentline, _lineinfo, true);\r
                        _fs->AddInstruction(_OP_RETURN, 0xFF);\r
                        _fs->SetStackSize(0);\r
@@ -181,10 +191,10 @@ public:
                }\r
                else {\r
                        if(_raiseerror && _ss(_vm)->_compilererrorhandler) {\r
-                               _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),\r
+                               _ss(_vm)->_compilererrorhandler(_vm, _compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),\r
                                        _lex._currentline, _lex._currentcolumn);\r
                        }\r
-                       _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);\r
+                       _vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1);\r
                        return false;\r
                }\r
                return true;\r
@@ -196,7 +206,7 @@ public:
                        if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
                }\r
        }\r
-       void Statement()\r
+       void Statement(bool closeframe = true)\r
        {\r
                _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
                switch(_token){\r
@@ -213,7 +223,6 @@ public:
                        SQOpcode op;\r
                        if(_token == TK_RETURN) {\r
                                op = _OP_RETURN;\r
-                               \r
                        }\r
                        else {\r
                                op = _OP_YIELD;\r
@@ -226,13 +235,13 @@ public:
                                if(op == _OP_RETURN && _fs->_traps > 0)\r
                                        _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);\r
                                _fs->_returnexp = retexp;\r
-                               _fs->AddInstruction(op, 1, _fs->PopTarget());\r
+                               _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize());\r
                        }\r
                        else{ \r
                                if(op == _OP_RETURN && _fs->_traps > 0)\r
                                        _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);\r
                                _fs->_returnexp = -1;\r
-                               _fs->AddInstruction(op, 0xFF); \r
+                               _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); \r
                        }\r
                        break;}\r
                case TK_BREAK:\r
@@ -240,6 +249,7 @@ public:
                        if(_fs->_breaktargets.top() > 0){\r
                                _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);\r
                        }\r
+                       RESOLVE_OUTERS();\r
                        _fs->AddInstruction(_OP_JMP, 0, -1234);\r
                        _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());\r
                        Lex();\r
@@ -249,6 +259,7 @@ public:
                        if(_fs->_continuetargets.top() > 0) {\r
                                _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);\r
                        }\r
+                       RESOLVE_OUTERS();\r
                        _fs->AddInstruction(_OP_JMP, 0, -1234);\r
                        _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());\r
                        Lex();\r
@@ -263,11 +274,16 @@ public:
                        EnumStatement();\r
                        break;\r
                case _SC('{'):{\r
-                               SQInteger stacksize = _fs->GetStackSize();\r
+                               BEGIN_SCOPE();\r
                                Lex();\r
                                Statements();\r
                                Expect(_SC('}'));\r
-                               _fs->SetStackSize(stacksize);\r
+                               if(closeframe) {\r
+                                       END_SCOPE();\r
+                               }\r
+                               else {\r
+                                       END_SCOPE_NO_CLOSE();\r
+                               }\r
                        }\r
                        break;\r
                case TK_TRY:\r
@@ -293,7 +309,8 @@ public:
                        break;\r
                default:\r
                        CommaExpr();\r
-                       _fs->PopTarget();\r
+                       _fs->DiscardTarget();\r
+                       //_fs->PopTarget();\r
                        break;\r
                }\r
                _fs->SnoozeOpt();\r
@@ -311,38 +328,50 @@ public:
                SQInteger p1 = _fs->PopTarget(); //key in OP_GET\r
                _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);\r
        }\r
-       void EmitCompoundArith(SQInteger tok,bool deref)\r
+       void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos)\r
        {\r
-               SQInteger oper;\r
-               switch(tok){\r
-               case TK_MINUSEQ: oper = '-'; break;\r
-               case TK_PLUSEQ: oper = '+'; break;\r
-               case TK_MULEQ: oper = '*'; break;\r
-               case TK_DIVEQ: oper = '/'; break;\r
-               case TK_MODEQ: oper = '%'; break;\r
-               default: oper = 0; //shut up compiler\r
-                       assert(0); break;\r
-               };\r
-               if(deref) {\r
-                       SQInteger val = _fs->PopTarget();\r
-                       SQInteger key = _fs->PopTarget();\r
-                       SQInteger src = _fs->PopTarget();\r
-                       //mixes dest obj and source val in the arg1(hack?)\r
-                       _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);\r
-               }\r
-               else {\r
-                       Emit2ArgsOP(_OP_COMPARITHL, oper);\r
+               /* Generate code depending on the expression type */\r
+               switch(etype) {\r
+               case LOCAL:{\r
+                       SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
+                       SQInteger p1 = _fs->PopTarget(); //key in OP_GET\r
+                       _fs->PushTarget(p1);\r
+                       //EmitCompArithLocal(tok, p1, p1, p2);\r
+                       _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);\r
+                       _fs->SnoozeOpt();\r
+                                  }\r
+                       break;\r
+               case OBJECT:\r
+               case BASE:\r
+                       {\r
+                               SQInteger val = _fs->PopTarget();\r
+                               SQInteger key = _fs->PopTarget();\r
+                               SQInteger src = _fs->PopTarget();\r
+                               /* _OP_COMPARITH mixes dest obj and source val in the arg1 */\r
+                               _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));\r
+                       }\r
+                       break;\r
+               case OUTER:\r
+                       {\r
+                               SQInteger val = _fs->TopTarget();\r
+                               SQInteger tmp = _fs->PushTarget();\r
+                               _fs->AddInstruction(_OP_GETOUTER,   tmp, pos);\r
+                               _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);\r
+                               _fs->AddInstruction(_OP_SETOUTER, tmp, pos, tmp);\r
+                       }\r
+                       break;\r
                }\r
        }\r
        void CommaExpr()\r
        {\r
                for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());\r
        }\r
-       ExpState Expression(bool funcarg = false)\r
+       void Expression()\r
        {\r
-               PushExpState();\r
-               _exst._class_or_delete = false;\r
-               _exst._funcarg = funcarg;\r
+                SQExpState es = _es;\r
+               _es.etype     = EXPR;\r
+               _es.epos      = -1;\r
+               _es.donot_get = false;\r
                LogicalOrExp();\r
                switch(_token)  {\r
                case _SC('='):\r
@@ -351,40 +380,51 @@ public:
                case TK_PLUSEQ:\r
                case TK_MULEQ:\r
                case TK_DIVEQ:\r
-               case TK_MODEQ:\r
-               {\r
-                               SQInteger op = _token;\r
-                               SQInteger ds = _exst._deref;\r
-                               bool freevar = _exst._freevar;\r
-                               if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));\r
-                               Lex(); Expression();\r
+               case TK_MODEQ:{\r
+                       SQInteger op = _token;\r
+                       SQInteger ds = _es.etype;\r
+                       SQInteger pos = _es.epos;\r
+                       if(ds == EXPR) Error(_SC("can't assign expression"));\r
+                       else if(ds == BASE) Error(_SC("'base' cannot be modified"));\r
 \r
-                               switch(op){\r
-                               case TK_NEWSLOT:\r
-                                       if(freevar) Error(_SC("free variables cannot be modified"));\r
-                                       if(ds == DEREF_FIELD)\r
-                                               EmitDerefOp(_OP_NEWSLOT);\r
-                                       else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
-                                               Error(_SC("can't 'create' a local slot"));\r
-                                       break;\r
-                               case _SC('='): //ASSIGN\r
-                                       if(freevar) Error(_SC("free variables cannot be modified"));\r
-                                       if(ds == DEREF_FIELD)\r
-                                               EmitDerefOp(_OP_SET);\r
-                                       else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
-                                               SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
-                                               SQInteger p1 = _fs->TopTarget(); //key in OP_GET\r
-                                               _fs->AddInstruction(_OP_MOVE, p1, p2);\r
+                       Lex(); Expression();\r
+\r
+                       switch(op){\r
+                       case TK_NEWSLOT:\r
+                               if(ds == OBJECT || ds == BASE)\r
+                                       EmitDerefOp(_OP_NEWSLOT);\r
+                               else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
+                                       Error(_SC("can't 'create' a local slot"));\r
+                               break;\r
+                       case _SC('='): //ASSIGN\r
+                               switch(ds) {\r
+                               case LOCAL:\r
+                                       {\r
+                                               SQInteger src = _fs->PopTarget();\r
+                                               SQInteger dst = _fs->TopTarget();\r
+                                               _fs->AddInstruction(_OP_MOVE, dst, src);\r
                                        }\r
                                        break;\r
-                               case TK_MINUSEQ:\r
-                               case TK_PLUSEQ:\r
-                               case TK_MULEQ:\r
-                               case TK_DIVEQ:\r
-                               case TK_MODEQ:\r
-                                       EmitCompoundArith(op,ds == DEREF_FIELD);\r
+                               case OBJECT:\r
+                               case BASE:\r
+                                       EmitDerefOp(_OP_SET);\r
                                        break;\r
+                               case OUTER:\r
+                                       {\r
+                                               SQInteger src = _fs->PopTarget();\r
+                                               SQInteger dst = _fs->PushTarget();\r
+                                               _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);\r
+                                       }\r
                                }\r
+                               break;\r
+                       case TK_MINUSEQ:\r
+                       case TK_PLUSEQ:\r
+                       case TK_MULEQ:\r
+                       case TK_DIVEQ:\r
+                       case TK_MODEQ:\r
+                               EmitCompoundArith(op, ds, pos);\r
+                               break;\r
+                       }\r
                        }\r
                        break;\r
                case _SC('?'): {\r
@@ -408,11 +448,21 @@ public:
                        }\r
                        break;\r
                }\r
-               return PopExpState();\r
+               _es = es;\r
        }\r
-       void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0)\r
+       template<typename T> void INVOKE_EXP(T f)\r
        {\r
-               Lex(); (this->*f)();\r
+               SQExpState es = _es;\r
+               _es.etype     = EXPR;\r
+               _es.epos      = -1;\r
+               _es.donot_get = false;\r
+               (this->*f)();\r
+               _es = es;\r
+       }\r
+       template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)\r
+       {\r
+               Lex(); \r
+               INVOKE_EXP(f);\r
                SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();\r
                _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);\r
        }\r
@@ -425,7 +475,7 @@ public:
                        _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);\r
                        SQInteger jpos = _fs->GetCurrentPos();\r
                        if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
-                       Lex(); LogicalOrExp();\r
+                       Lex(); INVOKE_EXP(&SQCompiler::LogicalOrExp);\r
                        _fs->SnoozeOpt();\r
                        SQInteger second_exp = _fs->PopTarget();\r
                        if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
@@ -444,7 +494,7 @@ public:
                        _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);\r
                        SQInteger jpos = _fs->GetCurrentPos();\r
                        if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
-                       Lex(); LogicalAndExp();\r
+                       Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp);\r
                        _fs->SnoozeOpt();\r
                        SQInteger second_exp = _fs->PopTarget();\r
                        if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
@@ -452,8 +502,7 @@ public:
                        _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
                        break;\r
                        }\r
-               case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;\r
-               case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;\r
+    \r
                default:\r
                        return;\r
                }\r
@@ -474,21 +523,31 @@ public:
        }\r
        void BitwiseAndExp()\r
        {\r
-               CompExp();\r
+               EqExp();\r
                for(;;) if(_token == _SC('&'))\r
-               {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);\r
+               {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);\r
                }else return;\r
        }\r
+       void EqExp()\r
+       {\r
+               CompExp();\r
+               for(;;) switch(_token) {\r
+               case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;\r
+               case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;\r
+               case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;\r
+               default: return;        \r
+               }\r
+       }\r
        void CompExp()\r
        {\r
                ShiftExp();\r
                for(;;) switch(_token) {\r
-               case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;\r
                case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;\r
                case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;\r
                case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;\r
                case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;\r
-               case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;\r
+               case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break;\r
+               case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::ShiftExp); break;\r
                default: return;        \r
                }\r
        }\r
@@ -502,12 +561,38 @@ public:
                default: return;        \r
                }\r
        }\r
+       SQOpcode ChooseArithOpByToken(SQInteger tok)\r
+       {\r
+               switch(tok) {\r
+                       case TK_PLUSEQ: case '+': return _OP_ADD;\r
+                       case TK_MINUSEQ: case '-': return _OP_SUB;\r
+                       case TK_MULEQ: case '*': return _OP_MUL;\r
+                       case TK_DIVEQ: case '/': return _OP_DIV;\r
+                       case TK_MODEQ: case '%': return _OP_MOD;\r
+                       default: assert(0);\r
+               }\r
+               return _OP_ADD;\r
+       }\r
+       SQInteger ChooseCompArithCharByToken(SQInteger tok)\r
+       {\r
+               SQInteger oper;\r
+               switch(tok){\r
+               case TK_MINUSEQ: oper = '-'; break;\r
+               case TK_PLUSEQ: oper = '+'; break;\r
+               case TK_MULEQ: oper = '*'; break;\r
+               case TK_DIVEQ: oper = '/'; break;\r
+               case TK_MODEQ: oper = '%'; break;\r
+               default: oper = 0; //shut up compiler\r
+                       assert(0); break;\r
+               };\r
+               return oper;\r
+       }\r
        void PlusExp()\r
        {\r
                MultExp();\r
                for(;;) switch(_token) {\r
                case _SC('+'): case _SC('-'):\r
-                       BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;\r
+                       BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;\r
                default: return;\r
                }\r
        }\r
@@ -517,7 +602,7 @@ public:
                PrefixedExpr();\r
                for(;;) switch(_token) {\r
                case _SC('*'): case _SC('/'): case _SC('%'):\r
-                       BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;\r
+                       BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;\r
                default: return;\r
                }\r
        }\r
@@ -525,69 +610,97 @@ public:
        void PrefixedExpr()\r
        {\r
                SQInteger pos = Factor();\r
-               \r
                for(;;) {\r
                        switch(_token) {\r
-                       case _SC('.'): {\r
+                       case _SC('.'):\r
                                pos = -1;\r
                                Lex(); \r
-                               if(_token == TK_PARENT) {\r
-                                       Lex();\r
-                                       if(!NeedGet())\r
-                                               Error(_SC("parent cannot be set"));\r
-                                       SQInteger src = _fs->PopTarget();\r
-                                       _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);\r
+\r
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
+                               if(_es.etype==BASE) {\r
+                                       Emit2ArgsOP(_OP_GET);\r
+                                       pos = _fs->TopTarget();\r
+                                       _es.etype = EXPR;\r
+                                       _es.epos   = pos;\r
                                }\r
                                else {\r
-                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
-                                       if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
-                               }\r
-                               _exst._deref = DEREF_FIELD;\r
-                               _exst._freevar = false;\r
+                                       if(NeedGet()) {\r
+                                               Emit2ArgsOP(_OP_GET);\r
+                                       }\r
+                                       _es.etype = OBJECT;\r
                                }\r
                                break;\r
                        case _SC('['):\r
                                if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));\r
                                Lex(); Expression(); Expect(_SC(']')); \r
                                pos = -1;\r
-                               if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
-                               _exst._deref = DEREF_FIELD;\r
-                               _exst._freevar = false;\r
+                               if(_es.etype==BASE) {\r
+                                       Emit2ArgsOP(_OP_GET);\r
+                                       pos = _fs->TopTarget();\r
+                                       _es.etype = EXPR;\r
+                                       _es.epos   = pos;\r
+                               }\r
+                               else {\r
+                                       if(NeedGet()) {\r
+                                               Emit2ArgsOP(_OP_GET);\r
+                                       }\r
+                                       _es.etype = OBJECT;\r
+                               }\r
                                break;\r
                        case TK_MINUSMINUS:\r
                        case TK_PLUSPLUS:\r
-                       if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { \r
-                               SQInteger tok = _token; Lex();\r
-                               if(pos < 0)\r
-                                       Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);\r
-                               else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
-                                       SQInteger src = _fs->PopTarget();\r
-                                       _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);\r
+                               {\r
+                                       if(IsEndOfStatement()) return;\r
+                                       SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;\r
+                                       Lex();\r
+                                       switch(_es.etype)\r
+                                       {\r
+                                               case EXPR: Error(_SC("can't '++' or '--' an expression")); break;\r
+                                               case OBJECT:\r
+                                               case BASE:\r
+                                                       Emit2ArgsOP(_OP_PINC, diff);\r
+                                                       break;\r
+                                               case LOCAL: {\r
+                                                       SQInteger src = _fs->PopTarget();\r
+                                                       _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);\r
+                                                                       }\r
+                                                       break;\r
+                                               case OUTER: {\r
+                                                       SQInteger tmp1 = _fs->PushTarget();\r
+                                                       SQInteger tmp2 = _fs->PushTarget();\r
+                                                       _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);\r
+                                                       _fs->AddInstruction(_OP_PINCL,    tmp1, tmp2, 0, diff);\r
+                                                       _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);\r
+                                                       _fs->PopTarget();\r
+                                               }\r
+                                       }\r
                                }\r
-                               \r
-                       }\r
-                       return;\r
-                       break;  \r
+                               return;\r
+                               break;  \r
                        case _SC('('): \r
-                               {\r
-                               if(_exst._deref != DEREF_NO_DEREF) {\r
-                                       if(pos<0) {\r
-                                               SQInteger key = _fs->PopTarget(); //key\r
-                                               SQInteger table = _fs->PopTarget(); //table etc...\r
-                                               SQInteger closure = _fs->PushTarget();\r
-                                               SQInteger ttarget = _fs->PushTarget();\r
+                               switch(_es.etype) {\r
+                                       case OBJECT: {\r
+                                               SQInteger key     = _fs->PopTarget();  /* location of the key */\r
+                                               SQInteger table   = _fs->PopTarget();  /* location of the object */\r
+                                               SQInteger closure = _fs->PushTarget(); /* location for the closure */\r
+                                               SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */\r
                                                _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);\r
-                                       }\r
-                                       else{\r
+                                               }\r
+                                               break;\r
+                                       case BASE:\r
+                                               //Emit2ArgsOP(_OP_GET);\r
+                                               _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
+                                               break;\r
+                                       case OUTER:\r
+                                               _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);\r
+                                               _fs->AddInstruction(_OP_MOVE,     _fs->PushTarget(), 0);\r
+                                               break;\r
+                                       default:\r
                                                _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
-                                       }\r
                                }\r
-                               else\r
-                                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
-                               _exst._deref = DEREF_NO_DEREF;\r
+                               _es.etype = EXPR;\r
                                Lex();\r
                                FunctionCallArgs();\r
-                                }\r
                                break;\r
                        default: return;\r
                        }\r
@@ -595,123 +708,116 @@ public:
        }\r
        SQInteger Factor()\r
        {\r
-               _exst._deref = DEREF_NO_DEREF;\r
+               _es.etype = EXPR;\r
                switch(_token)\r
                {\r
-               case TK_STRING_LITERAL: {\r
-                               //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));\r
-                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));\r
-                               Lex(); \r
-                       }\r
+               case TK_STRING_LITERAL:\r
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));\r
+                       Lex(); \r
                        break;\r
-               case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;\r
-               case TK_VARGV: { Lex();\r
-                       Expect(_SC('['));\r
-                       Expression();\r
-                       Expect(_SC(']'));\r
-                       SQInteger src = _fs->PopTarget();\r
-                       _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);\r
-                                          }\r
+               case TK_BASE:\r
+                       Lex();\r
+                       _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());\r
+                       _es.etype  = BASE;\r
+                       _es.epos   = _fs->TopTarget();\r
+                       return (_es.epos);\r
                        break;\r
                case TK_IDENTIFIER:\r
                case TK_CONSTRUCTOR:\r
                case TK_THIS:{\r
-                       _exst._freevar = false;\r
-                       SQObject id;\r
-                       SQObject constant;\r
+                               SQObject id;\r
+                               SQObject constant;\r
+\r
                                switch(_token) {\r
-                                       case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;\r
-                                       case TK_THIS: id = _fs->CreateString(_SC("this")); break;\r
+                                       case TK_IDENTIFIER:  id = _fs->CreateString(_lex._svalue);       break;\r
+                                       case TK_THIS:        id = _fs->CreateString(_SC("this"));        break;\r
                                        case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;\r
                                }\r
+\r
                                SQInteger pos = -1;\r
                                Lex();\r
-                               if((pos = _fs->GetLocalVariable(id)) == -1) {\r
-                                       //checks if is a free variable\r
-                                       if((pos = _fs->GetOuterVariable(id)) != -1) {\r
-                                               _exst._deref = _fs->PushTarget();\r
-                                               _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);        \r
-                                               _exst._freevar = true;\r
+                               if((pos = _fs->GetLocalVariable(id)) != -1) {\r
+                                       /* Handle a local variable (includes 'this') */\r
+                                       _fs->PushTarget(pos);\r
+                                       _es.etype  = LOCAL;\r
+                                       _es.epos   = pos;\r
+                               }\r
+\r
+                               else if((pos = _fs->GetOuterVariable(id)) != -1) {\r
+                                       /* Handle a free var */\r
+                                       if(NeedGet()) {\r
+                                               _es.epos  = _fs->PushTarget();\r
+                                               _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);       \r
+                                               /* _es.etype = EXPR; already default value */\r
                                        }\r
-                                       else if(_fs->IsConstant(id,constant)) { //line 634\r
-                                               SQObjectPtr constval;\r
-                                               SQObject constid;\r
-                                               if(type(constant) == OT_TABLE) {\r
-                                                       Expect('.'); constid = Expect(TK_IDENTIFIER);\r
-                                                       if(!_table(constant)->Get(constid,constval)) {\r
-                                                               constval.Null();\r
-                                                               Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid));\r
-                                                       }\r
-                                               }\r
-                                               else {\r
-                                                       constval = constant;\r
-                                               }\r
-                                               _exst._deref = _fs->PushTarget();\r
-                                               SQObjectType ctype = type(constval);\r
-                                               if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) {\r
-                                                       _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval));\r
-                                               }\r
-                                               else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) {\r
-                                                       SQFloat f = _float(constval);\r
-                                                       _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f));\r
-                                               }\r
-                                               else {\r
-                                                       _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval));\r
-                                               }\r
+                                       else {\r
+                                               _es.etype = OUTER;\r
+                                               _es.epos  = pos;\r
+                                       }\r
+                               }\r
 \r
-                                               _exst._freevar = true;\r
+                               else if(_fs->IsConstant(id, constant)) {\r
+                                       /* Handle named constant */\r
+                                       SQObjectPtr constval;\r
+                                       SQObject    constid;\r
+                                       if(type(constant) == OT_TABLE) {\r
+                                               Expect('.');\r
+                                               constid = Expect(TK_IDENTIFIER);\r
+                                               if(!_table(constant)->Get(constid, constval)) {\r
+                                                       constval.Null();\r
+                                                       Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));\r
+                                               }\r
                                        }\r
                                        else {\r
-                                               _fs->PushTarget(0);\r
-                                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
-                                               if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
-                                               _exst._deref = DEREF_FIELD;\r
+                                               constval = constant;\r
+                                       }\r
+                                       _es.epos = _fs->PushTarget();\r
+\r
+                                       /* generate direct or literal function depending on size */\r
+                                       SQObjectType ctype = type(constval);\r
+                                       switch(ctype) {\r
+                                               case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;\r
+                                               case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;\r
+                                               default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;\r
                                        }\r
+                                       _es.etype = EXPR;\r
                                }\r
-                               \r
-                               else{\r
-                                       _fs->PushTarget(pos);\r
-                                       _exst._deref = pos;\r
+                               else {\r
+                                       /* Handle a non-local variable, aka a field. Push the 'this' pointer on\r
+                                       * the virtual stack (always found in offset 0, so no instruction needs to\r
+                                       * be generated), and push the key next. Generate an _OP_LOAD instruction\r
+                                       * for the latter. If we are not using the variable as a dref expr, generate\r
+                                       * the _OP_GET instruction.\r
+                                       */\r
+                                       _fs->PushTarget(0);\r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
+                                       if(NeedGet()) {\r
+                                               Emit2ArgsOP(_OP_GET);\r
+                                       }\r
+                                       _es.etype = OBJECT;\r
                                }\r
-                               return _exst._deref;\r
+                               return _es.epos;\r
                        }\r
                        break;\r
-               case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;\r
                case TK_DOUBLE_COLON:  // "::"\r
-                       _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());\r
-                       _exst._deref = DEREF_FIELD;\r
-                       _token = _SC('.'); //hack\r
-                       return -1;\r
+                       _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());\r
+                       _es.etype = OBJECT;\r
+                       _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/\r
+                       _es.epos = -1;\r
+                       return _es.epos;\r
                        break;\r
                case TK_NULL: \r
                        _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
                        Lex();\r
                        break;\r
-               case TK_INTEGER: {\r
-                       if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits?\r
-                               _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);\r
-                       }\r
-                       else {\r
-                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));\r
-                       }\r
-                       Lex();\r
-                                                }\r
-                       break;\r
-               case TK_FLOAT:\r
-                       if(sizeof(SQFloat) == sizeof(SQInt32)) {\r
-                               _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));\r
-                       }\r
-                       else {\r
-                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));\r
-                       }\r
-                       Lex();\r
-                       break;\r
+               case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex();      break;\r
+               case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break;\r
                case TK_TRUE: case TK_FALSE:\r
                        _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);\r
                        Lex();\r
                        break;\r
                case _SC('['): {\r
-                               _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());\r
+                               _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);\r
                                SQInteger apos = _fs->GetCurrentPos(),key = 0;\r
                                Lex();\r
                                while(_token != _SC(']')) {\r
@@ -719,57 +825,90 @@ public:
                                        if(_token == _SC(',')) Lex();\r
                                        SQInteger val = _fs->PopTarget();\r
                                        SQInteger array = _fs->TopTarget();\r
-                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val);\r
+                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);\r
                                        key++;\r
                                }\r
                                _fs->SetIntructionParam(apos, 1, key);\r
                                Lex();\r
                        }\r
                        break;\r
-               case _SC('{'):{\r
-                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
-                       Lex();ParseTableOrClass(_SC(','));\r
-                                }\r
+               case _SC('{'):\r
+                       _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);\r
+                       Lex();ParseTableOrClass(_SC(','),_SC('}'));\r
                        break;\r
                case TK_FUNCTION: FunctionExp(_token);break;\r
+               case _SC('@'): FunctionExp(_token,true);break;\r
                case TK_CLASS: Lex(); ClassExp();break;\r
-               case _SC('-'): UnaryOP(_OP_NEG); break;\r
-               case _SC('!'): UnaryOP(_OP_NOT); break;\r
-               case _SC('~'): UnaryOP(_OP_BWNOT); break;\r
-               case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;\r
-               case TK_RESUME : UnaryOP(_OP_RESUME); break;\r
-               case TK_CLONE : UnaryOP(_OP_CLONE); break;\r
+               case _SC('-'): \r
+                       Lex(); \r
+                       switch(_token) {\r
+                       case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;\r
+                       case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;\r
+                       default: UnaryOP(_OP_NEG);\r
+                       }\r
+                       break;\r
+               case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;\r
+               case _SC('~'): \r
+                       Lex(); \r
+                       if(_token == TK_INTEGER)  { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }\r
+                       UnaryOP(_OP_BWNOT); \r
+                       break;\r
+               case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;\r
+               case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;\r
+               case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;\r
                case TK_MINUSMINUS : \r
                case TK_PLUSPLUS :PrefixIncDec(_token); break;\r
                case TK_DELETE : DeleteExpr(); break;\r
-               case TK_DELEGATE : DelegateExpr(); break;\r
                case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));\r
                        break;\r
                default: Error(_SC("expression expected"));\r
                }\r
                return -1;\r
        }\r
+       void EmitLoadConstInt(SQInteger value,SQInteger target)\r
+       {\r
+               if(target < 0) {\r
+                       target = _fs->PushTarget();\r
+               }\r
+               if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits?\r
+                       _fs->AddInstruction(_OP_LOADINT, target,value);\r
+               }\r
+               else {\r
+                       _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));\r
+               }\r
+       }\r
+       void EmitLoadConstFloat(SQFloat value,SQInteger target)\r
+       {\r
+               if(target < 0) {\r
+                       target = _fs->PushTarget();\r
+               }\r
+               if(sizeof(SQFloat) == sizeof(SQInt32)) {\r
+                       _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));\r
+               }\r
+               else {\r
+                       _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));\r
+               }\r
+       }\r
        void UnaryOP(SQOpcode op)\r
        {\r
-               Lex(); PrefixedExpr();\r
+               PrefixedExpr();\r
                SQInteger src = _fs->PopTarget();\r
                _fs->AddInstruction(op, _fs->PushTarget(), src);\r
        }\r
        bool NeedGet()\r
        {\r
                switch(_token) {\r
-               case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:\r
-               case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:\r
+               case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:\r
+           case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS:\r
                        return false;\r
                }\r
-               return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));\r
+               return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));\r
        }\r
-       \r
        void FunctionCallArgs()\r
        {\r
                SQInteger nargs = 1;//this\r
                 while(_token != _SC(')')) {\r
-                        Expression(true);\r
+                        Expression();\r
                         MoveIfCurrentTargetIsLocal();\r
                         nargs++; \r
                         if(_token == _SC(',')){ \r
@@ -783,17 +922,16 @@ public:
                 SQInteger closure = _fs->PopTarget();\r
          _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);\r
        }\r
-       void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')\r
+       void ParseTableOrClass(SQInteger separator,SQInteger terminator)\r
        {\r
                SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;\r
-               \r
                while(_token != terminator) {\r
                        bool hasattrs = false;\r
                        bool isstatic = false;\r
                        //check if is an attribute\r
                        if(separator == ';') {\r
                                if(_token == TK_ATTR_OPEN) {\r
-                                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();\r
+                                       _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();\r
                                        ParseTableOrClass(',',TK_ATTR_CLOSE);\r
                                        hasattrs = true;\r
                                }\r
@@ -803,36 +941,45 @@ public:
                                }\r
                        }\r
                        switch(_token) {\r
-                               case TK_FUNCTION:\r
-                               case TK_CONSTRUCTOR:{\r
-                                       SQInteger tk = _token;\r
-                                       Lex();\r
-                                       SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));\r
-                                       Expect(_SC('('));\r
-                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
-                                       CreateFunction(id);\r
-                                       _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
-                                                                 }\r
-                                                                 break;\r
-                               case _SC('['):\r
-                                       Lex(); CommaExpr(); Expect(_SC(']'));\r
-                                       Expect(_SC('=')); Expression();\r
+                       case TK_FUNCTION:\r
+                       case TK_CONSTRUCTOR:{\r
+                               SQInteger tk = _token;\r
+                               Lex();\r
+                               SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));\r
+                               Expect(_SC('('));\r
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
+                               CreateFunction(id);\r
+                               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
+                                                               }\r
+                                                               break;\r
+                       case _SC('['):\r
+                               Lex(); CommaExpr(); Expect(_SC(']'));\r
+                               Expect(_SC('=')); Expression();\r
+                               break;\r
+                       case TK_STRING_LITERAL: //JSON\r
+                               if(separator == ',') { //only works for tables\r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL)));\r
+                                       Expect(_SC(':')); Expression();\r
                                        break;\r
-                               default :\r
-                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
-                                       Expect(_SC('=')); Expression();\r
+                               }\r
+                       default :\r
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\r
+                               Expect(_SC('=')); Expression();\r
                        }\r
-\r
                        if(_token == separator) Lex();//optional comma/semicolon\r
                        nkeys++;\r
                        SQInteger val = _fs->PopTarget();\r
                        SQInteger key = _fs->PopTarget();\r
                        SQInteger attrs = hasattrs ? _fs->PopTarget():-1;\r
-                       assert(hasattrs && attrs == key-1 || !hasattrs);\r
+                       assert((hasattrs && (attrs == key-1)) || !hasattrs);\r
                        unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);\r
                        SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE\r
-                       _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);\r
-                       //_fs->PopTarget();\r
+                       if(separator == _SC(',')) { //hack recognizes a table from the separator\r
+                               _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);\r
+                       }\r
+                       else {\r
+                               _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember\r
+                       }\r
                }\r
                if(separator == _SC(',')) //hack recognizes a table from the separator\r
                        _fs->SetIntructionParam(tpos, 1, nkeys);\r
@@ -841,8 +988,20 @@ public:
        void LocalDeclStatement()\r
        {\r
                SQObject varname;\r
+               Lex();\r
+               if( _token == TK_FUNCTION) {\r
+                       Lex();\r
+                       varname = Expect(TK_IDENTIFIER);\r
+                       Expect(_SC('('));\r
+                       CreateFunction(varname,false);\r
+                       _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
+                       _fs->PopTarget();\r
+                       _fs->PushLocalVariable(varname);\r
+                       return;\r
+               }\r
+\r
                do {\r
-                       Lex(); varname = Expect(TK_IDENTIFIER);\r
+                       varname = Expect(TK_IDENTIFIER);\r
                        if(_token == _SC('=')) {\r
                                Lex(); Expression();\r
                                SQInteger src = _fs->PopTarget();\r
@@ -854,51 +1013,50 @@ public:
                        }\r
                        _fs->PopTarget();\r
                        _fs->PushLocalVariable(varname);\r
-               \r
-               } while(_token == _SC(','));\r
+                       if(_token == _SC(',')) Lex(); else break;\r
+               } while(1);\r
        }\r
        void IfStatement()\r
-       {\r
-               SQInteger jmppos;\r
-               bool haselse = false;\r
-               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
-               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
-               SQInteger jnepos = _fs->GetCurrentPos();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               \r
-               Statement();\r
-               //\r
-               if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
-               \r
-               CleanStack(stacksize);\r
-               SQInteger endifblock = _fs->GetCurrentPos();\r
-               if(_token == TK_ELSE){\r
-                       haselse = true;\r
-                       stacksize = _fs->GetStackSize();\r
-                       _fs->AddInstruction(_OP_JMP);\r
-                       jmppos = _fs->GetCurrentPos();\r
-                       Lex();\r
-                       Statement(); OptionalSemicolon();\r
-                       CleanStack(stacksize);\r
-                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
-               }\r
-               _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));\r
-       }\r
+    {\r
+        SQInteger jmppos;\r
+        bool haselse = false;\r
+        Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
+        _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
+        SQInteger jnepos = _fs->GetCurrentPos();\r
+        BEGIN_SCOPE();\r
+        \r
+        Statement();\r
+        //\r
+        if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
+        \r
+        END_SCOPE();\r
+        SQInteger endifblock = _fs->GetCurrentPos();\r
+        if(_token == TK_ELSE){\r
+            haselse = true;\r
+            BEGIN_SCOPE();\r
+            _fs->AddInstruction(_OP_JMP);\r
+            jmppos = _fs->GetCurrentPos();\r
+            Lex();\r
+            Statement(); if(_lex._prevtoken != _SC('}')) OptionalSemicolon();\r
+            END_SCOPE();\r
+            _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
+        }\r
+        _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));\r
+    }\r
        void WhileStatement()\r
        {\r
                SQInteger jzpos, jmppos;\r
-               SQInteger stacksize = _fs->GetStackSize();\r
                jmppos = _fs->GetCurrentPos();\r
                Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
                \r
                BEGIN_BREAKBLE_BLOCK();\r
                _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
                jzpos = _fs->GetCurrentPos();\r
-               stacksize = _fs->GetStackSize();\r
+               BEGIN_SCOPE();\r
                \r
                Statement();\r
                \r
-               CleanStack(stacksize);\r
+               END_SCOPE();\r
                _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
                _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
                \r
@@ -907,21 +1065,22 @@ public:
        void DoWhileStatement()\r
        {\r
                Lex();\r
-               SQInteger jzpos = _fs->GetCurrentPos();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               SQInteger jmptrg = _fs->GetCurrentPos();\r
                BEGIN_BREAKBLE_BLOCK()\r
+               BEGIN_SCOPE();\r
                Statement();\r
-               CleanStack(stacksize);\r
+               END_SCOPE();\r
                Expect(TK_WHILE);\r
                SQInteger continuetrg = _fs->GetCurrentPos();\r
                Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
-               _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);\r
+               _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);\r
+               _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);\r
                END_BREAKBLE_BLOCK(continuetrg);\r
        }\r
        void ForStatement()\r
        {\r
                Lex();\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               BEGIN_SCOPE();\r
                Expect(_SC('('));\r
                if(_token == TK_LOCAL) LocalDeclStatement();\r
                else if(_token != _SC(';')){\r
@@ -959,7 +1118,7 @@ public:
                }\r
                _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);\r
                if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
-               CleanStack(stacksize);\r
+               END_SCOPE();\r
                \r
                END_BREAKBLE_BLOCK(continuetrg);\r
        }\r
@@ -977,7 +1136,7 @@ public:
                Expect(TK_IN);\r
                \r
                //save the stack size\r
-               SQInteger stacksize = _fs->GetStackSize();\r
+               BEGIN_SCOPE();\r
                //put the table in the stack(evaluate the table expression)\r
                Expression(); Expect(_SC(')'));\r
                SQInteger container = _fs->TopTarget();\r
@@ -1000,9 +1159,10 @@ public:
                _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
                _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);\r
                _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);\r
-               //restore the local variable stack(remove index,val and ref idx)\r
-               CleanStack(stacksize);\r
                END_BREAKBLE_BLOCK(foreachpos - 1);\r
+               //restore the local variable stack(remove index,val and ref idx)\r
+               _fs->PopTarget();\r
+               END_SCOPE();\r
        }\r
        void SwitchStatement()\r
        {\r
@@ -1015,7 +1175,6 @@ public:
                SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();\r
                _fs->_breaktargets.push_back(0);\r
                while(_token == TK_CASE) {\r
-                       //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one\r
                        if(!bfirst) {\r
                                _fs->AddInstruction(_OP_JMP, 0, 0);\r
                                skipcondjmp = _fs->GetCurrentPos();\r
@@ -1024,33 +1183,40 @@ public:
                        //condition\r
                        Lex(); Expression(); Expect(_SC(':'));\r
                        SQInteger trg = _fs->PopTarget();\r
-                       _fs->AddInstruction(_OP_EQ, trg, trg, expr);\r
-                       _fs->AddInstruction(_OP_JZ, trg, 0);\r
+                       SQInteger eqtarget = trg;\r
+                       bool local = _fs->IsLocal(trg);\r
+                       if(local) {\r
+                               eqtarget = _fs->PushTarget(); //we need to allocate a extra reg\r
+                       }\r
+                       _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);\r
+                       _fs->AddInstruction(_OP_JZ, eqtarget, 0);\r
+                       if(local) {\r
+                               _fs->PopTarget();\r
+                       }\r
+                       \r
                        //end condition\r
                        if(skipcondjmp != -1) {\r
                                _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));\r
                        }\r
                        tonextcondjmp = _fs->GetCurrentPos();\r
-                       SQInteger stacksize = _fs->GetStackSize();\r
+                       BEGIN_SCOPE();\r
                        Statements();\r
-                       _fs->SetStackSize(stacksize);\r
+                       END_SCOPE();\r
                        bfirst = false;\r
                }\r
                if(tonextcondjmp != -1)\r
                        _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
                if(_token == TK_DEFAULT) {\r
-               //      _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
                        Lex(); Expect(_SC(':'));\r
-                       SQInteger stacksize = _fs->GetStackSize();\r
+                       BEGIN_SCOPE();\r
                        Statements();\r
-                       _fs->SetStackSize(stacksize);\r
+                       END_SCOPE();\r
                }\r
                Expect(_SC('}'));\r
                _fs->PopTarget();\r
                __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;\r
                if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);\r
                _fs->_breaktargets.pop_back();\r
-               \r
        }\r
        void FunctionStatement()\r
        {\r
@@ -1074,23 +1240,28 @@ public:
        }\r
        void ClassStatement()\r
        {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
+               SQExpState es;\r
+               Lex();\r
+               es = _es;\r
+               _es.donot_get = true;\r
                PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));\r
-               if(es._deref == DEREF_FIELD) {\r
+               if(_es.etype == EXPR) {\r
+                       Error(_SC("invalid class name"));\r
+               }\r
+               else if(_es.etype == OBJECT || _es.etype == BASE) {\r
                        ClassExp();\r
                        EmitDerefOp(_OP_NEWSLOT);\r
                        _fs->PopTarget();\r
                }\r
-               else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));\r
+               else {\r
+                       Error(_SC("cannot create a class in a local with the syntax(class <local>)"));\r
+               }\r
+               _es = es;\r
        }\r
        SQObject ExpectScalar()\r
        {\r
                SQObject val;\r
+               val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x\r
                switch(_token) {\r
                        case TK_INTEGER:\r
                                val._type = OT_INTEGER;\r
@@ -1103,6 +1274,11 @@ public:
                        case TK_STRING_LITERAL:\r
                                val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);\r
                                break;\r
+                       case TK_TRUE:\r
+                       case TK_FALSE:\r
+                               val._type = OT_BOOL;\r
+                               val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;\r
+                               break;\r
                        case '-':\r
                                Lex();\r
                                switch(_token)\r
@@ -1120,14 +1296,13 @@ public:
                                }\r
                                break;\r
                        default:\r
-                       Error(_SC("scalar expected : integer,float or string"));\r
+                               Error(_SC("scalar expected : integer,float or string"));\r
                }\r
                Lex();\r
                return val;\r
        }\r
        void EnumStatement()\r
        {\r
-               \r
                Lex(); \r
                SQObject id = Expect(TK_IDENTIFIER);\r
                Expect(_SC('{'));\r
@@ -1150,15 +1325,9 @@ public:
                }\r
                SQTable *enums = _table(_ss(_vm)->_consts);\r
                SQObjectPtr strongid = id; \r
-               /*SQObjectPtr dummy;\r
-               if(enums->Get(strongid,dummy)) {\r
-                       dummy.Null(); strongid.Null();\r
-                       Error(_SC("enumeration already exists"));\r
-               }*/\r
                enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));\r
                strongid.Null();\r
                Lex();\r
-               \r
        }\r
        void TryCatchStatement()\r
        {\r
@@ -1169,7 +1338,11 @@ public:
                if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;\r
                if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;\r
                SQInteger trappos = _fs->GetCurrentPos();\r
-               Statement();\r
+               {\r
+                       BEGIN_SCOPE();\r
+                       Statement();\r
+                       END_SCOPE();\r
+               }\r
                _fs->_traps--;\r
                _fs->AddInstruction(_OP_POPTRAP, 1, 0);\r
                if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;\r
@@ -1178,17 +1351,20 @@ public:
                SQInteger jmppos = _fs->GetCurrentPos();\r
                _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));\r
                Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));\r
-               SQInteger stacksize = _fs->GetStackSize();\r
-               SQInteger ex_target = _fs->PushLocalVariable(exid);\r
-               _fs->SetIntructionParam(trappos, 0, ex_target);\r
-               Statement();\r
-               _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);\r
-               CleanStack(stacksize);\r
+               {\r
+                       BEGIN_SCOPE();\r
+                       SQInteger ex_target = _fs->PushLocalVariable(exid);\r
+                       _fs->SetIntructionParam(trappos, 0, ex_target);\r
+                       Statement();\r
+                       _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);\r
+                       END_SCOPE();\r
+               }\r
        }\r
-       void FunctionExp(SQInteger ftype)\r
+       void FunctionExp(SQInteger ftype,bool lambda = false)\r
        {\r
                Lex(); Expect(_SC('('));\r
-               CreateFunction(_null_);\r
+               SQObjectPtr dummy;\r
+               CreateFunction(dummy,lambda);\r
                _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);\r
        }\r
        void ClassExp()\r
@@ -1201,53 +1377,61 @@ public:
                }\r
                if(_token == TK_ATTR_OPEN) {\r
                        Lex();\r
-                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
+                       _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);\r
                        ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);\r
                        attrs = _fs->TopTarget();\r
                }\r
                Expect(_SC('{'));\r
                if(attrs != -1) _fs->PopTarget();\r
                if(base != -1) _fs->PopTarget();\r
-               _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);\r
-               ParseTableOrClass(_SC(';'));\r
-       }\r
-       void DelegateExpr()\r
-       {\r
-               Lex(); CommaExpr();\r
-               Expect(_SC(':'));\r
-               CommaExpr();\r
-               SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget();\r
-               _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);\r
+               _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);\r
+               ParseTableOrClass(_SC(';'),_SC('}'));\r
        }\r
        void DeleteExpr()\r
        {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
+               SQExpState es;\r
+               Lex();\r
+               es = _es;\r
+               _es.donot_get = true;\r
                PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));\r
-               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);\r
-               else Error(_SC("cannot delete a local"));\r
+               if(_es.etype==EXPR) Error(_SC("can't delete an expression"));\r
+               if(_es.etype==OBJECT || _es.etype==BASE) {\r
+                       Emit2ArgsOP(_OP_DELETE);\r
+               }\r
+               else {\r
+                       Error(_SC("cannot delete an (outer) local"));\r
+               }\r
+               _es = es;\r
        }\r
        void PrefixIncDec(SQInteger token)\r
        {\r
-               ExpState es;\r
-               Lex(); PushExpState();\r
-               _exst._class_or_delete = true;\r
-               _exst._funcarg = false;\r
+               SQExpState  es;\r
+               SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;\r
+               Lex();\r
+               es = _es;\r
+               _es.donot_get = true;\r
                PrefixedExpr();\r
-               es = PopExpState();\r
-               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);\r
-               else {\r
-                       SQInteger src = _fs->PopTarget();\r
-                       _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);\r
+               if(_es.etype==EXPR) {\r
+                       Error(_SC("can't '++' or '--' an expression"));\r
+               }\r
+               else if(_es.etype==OBJECT || _es.etype==BASE) {\r
+                       Emit2ArgsOP(_OP_INC, diff);\r
                }\r
+               else if(_es.etype==LOCAL) {\r
+                       SQInteger src = _fs->TopTarget();\r
+                       _fs->AddInstruction(_OP_INCL, src, src, 0, diff);\r
+                       \r
+               }\r
+               else if(_es.etype==OUTER) {\r
+                       SQInteger tmp = _fs->PushTarget();\r
+                       _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);\r
+                       _fs->AddInstruction(_OP_INCL,     tmp, tmp, 0, diff);\r
+                       _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);\r
+               }\r
+               _es = es;\r
        }\r
-       void CreateFunction(SQObject &name)\r
+       void CreateFunction(SQObject &name,bool lambda = false)\r
        {\r
-               \r
                SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));\r
                funcstate->_name = name;\r
                SQObject paramname;\r
@@ -1257,6 +1441,7 @@ public:
                while(_token!=_SC(')')) {\r
                        if(_token == TK_VARPARAMS) {\r
                                if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));\r
+                               funcstate->AddParameter(_fs->CreateString(_SC("vargv")));\r
                                funcstate->_varparams = true;\r
                                Lex();\r
                                if(_token != _SC(')')) Error(_SC("expected ')'"));\r
@@ -1282,26 +1467,19 @@ public:
                for(SQInteger n = 0; n < defparams; n++) {\r
                        _fs->PopTarget();\r
                }\r
-               //outer values\r
-               if(_token == _SC(':')) {\r
-                       Lex(); Expect(_SC('('));\r
-                       while(_token != _SC(')')) {\r
-                               paramname = Expect(TK_IDENTIFIER);\r
-                               //outers are treated as implicit local variables\r
-                               funcstate->AddOuterValue(paramname);\r
-                               if(_token == _SC(',')) Lex();\r
-                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
-                       }\r
-                       Lex();\r
-               }\r
-               \r
+                               \r
                SQFuncState *currchunk = _fs;\r
                _fs = funcstate;\r
-               Statement();\r
+               if(lambda) { \r
+                       Expression(); \r
+                       _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}\r
+               else { \r
+                       Statement(false); \r
+               }\r
                funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);\r
         funcstate->AddInstruction(_OP_RETURN, -1);\r
                funcstate->SetStackSize(0);\r
-               //_fs->->_stacksize = _fs->_stacksize;\r
+\r
                SQFunctionProto *func = funcstate->BuildProto();\r
 #ifdef _DEBUG_DUMP\r
                funcstate->Dump(func);\r
@@ -1310,11 +1488,6 @@ public:
                _fs->_functions.push_back(func);\r
                _fs->PopChildState();\r
        }\r
-       void CleanStack(SQInteger stacksize)\r
-       {\r
-               if(_fs->GetStackSize() != stacksize)\r
-                       _fs->SetStackSize(stacksize);\r
-       }\r
        void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)\r
        {\r
                while(ntoresolve > 0) {\r
@@ -1344,8 +1517,9 @@ private:
        bool _raiseerror;\r
        SQInteger _debugline;\r
        SQInteger _debugop;\r
-       ExpStateVec _expstates;\r
-       SQChar *compilererror;\r
+       SQExpState   _es;\r
+       SQScope _scope;\r
+       SQChar _compilererror[MAX_COMPILER_ERROR_LEN];\r
        jmp_buf _errorjmp;\r
        SQVM *_vm;\r
 };\r
@@ -1355,3 +1529,5 @@ bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcena
        SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);\r
        return p.Compile(out);\r
 }\r
+\r
+#endif\r
old mode 100755 (executable)
new mode 100644 (file)
index deab994..fcfd46a
@@ -8,7 +8,7 @@ struct SQVM;
 #define        TK_STRING_LITERAL       259\r
 #define        TK_INTEGER      260\r
 #define        TK_FLOAT        261\r
-#define        TK_DELEGATE     262\r
+#define        TK_BASE 262\r
 #define        TK_DELETE       263\r
 #define        TK_EQ   264\r
 #define        TK_NE   265\r
@@ -51,15 +51,15 @@ struct SQVM;
 #define TK_THIS 302\r
 #define TK_PLUSPLUS 303\r
 #define TK_MINUSMINUS 304\r
-#define TK_PARENT 305\r
+#define TK_3WAYSCMP 305\r
 #define TK_USHIFTR 306\r
 #define TK_CLASS 307\r
 #define TK_EXTENDS 308\r
 #define TK_CONSTRUCTOR 310\r
 #define TK_INSTANCEOF 311\r
 #define TK_VARPARAMS 312\r
-#define TK_VARGC 313\r
-#define TK_VARGV 314\r
+//#define TK_VARGC 313\r
+//#define TK_VARGV 314\r
 #define TK_TRUE 315\r
 #define TK_FALSE 316\r
 #define TK_MULEQ 317\r
old mode 100755 (executable)
new mode 100644 (file)
index d027f61..6f39231
@@ -15,7 +15,7 @@ SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)
                SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];\r
                if(sq_isclosure(ci._closure)) {\r
                        SQClosure *c = _closure(ci._closure);\r
-                       SQFunctionProto *proto = _funcproto(c->_function);\r
+                       SQFunctionProto *proto = c->_function;\r
                        fi->funcid = proto;\r
                        fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");\r
                        fi->source = type(proto->_name) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");\r
@@ -33,7 +33,7 @@ SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
                SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];\r
                switch (type(ci._closure)) {\r
                case OT_CLOSURE:{\r
-                       SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function);\r
+                       SQFunctionProto *func = _closure(ci._closure)->_function;\r
                        if (type(func->_name) == OT_STRING)\r
                                si->funcname = _stringval(func->_name);\r
                        if (type(func->_sourcename) == OT_STRING)\r
@@ -64,17 +64,17 @@ void SQVM::Raise_Error(const SQChar *s, ...)
        _lasterror = SQString::Create(_ss(this),_spval,-1);\r
 }\r
 \r
-void SQVM::Raise_Error(SQObjectPtr &desc)\r
+void SQVM::Raise_Error(const SQObjectPtr &desc)\r
 {\r
        _lasterror = desc;\r
 }\r
 \r
-SQString *SQVM::PrintObjVal(const SQObject &o)\r
+SQString *SQVM::PrintObjVal(const SQObjectPtr &o)\r
 {\r
        switch(type(o)) {\r
        case OT_STRING: return _string(o);\r
        case OT_INTEGER:\r
-               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o));\r
+               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _PRINT_INT_FMT, _integer(o));\r
                return SQString::Create(_ss(this), _spval);\r
                break;\r
        case OT_FLOAT:\r
@@ -86,7 +86,7 @@ SQString *SQVM::PrintObjVal(const SQObject &o)
        }\r
 }\r
 \r
-void SQVM::Raise_IdxError(SQObject &o)\r
+void SQVM::Raise_IdxError(const SQObjectPtr &o)\r
 {\r
        SQObjectPtr oval = PrintObjVal(o);\r
        Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));\r
@@ -95,7 +95,7 @@ void SQVM::Raise_IdxError(SQObject &o)
 void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)\r
 {\r
        SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);\r
-       Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2));\r
+       Raise_Error(_SC("comparison between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2));\r
 }\r
 \r
 \r
old mode 100755 (executable)
new mode 100644 (file)
index 50c6fd7..cd48aa6
@@ -6,8 +6,7 @@
 \r
 enum SQOuterType {\r
        otLOCAL = 0,\r
-       otSYMBOL = 1,\r
-       otOUTER = 2\r
+       otOUTER = 1\r
 };\r
 \r
 struct SQOuterVar\r
@@ -33,7 +32,7 @@ struct SQOuterVar
 \r
 struct SQLocalVarInfo\r
 {\r
-       SQLocalVarInfo():_start_op(0),_end_op(0){}\r
+       SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){}\r
        SQLocalVarInfo(const SQLocalVarInfo &lvi)\r
        {\r
                _name=lvi._name;\r
@@ -59,25 +58,15 @@ typedef sqvector<SQLineInfo> SQLineInfoVec;
                +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \\r
                +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))\r
 \r
-#define _CONSTRUCT_VECTOR(type,size,ptr) { \\r
-       for(SQInteger n = 0; n < size; n++) { \\r
-                       new (&ptr[n]) type(); \\r
-               } \\r
-}\r
-\r
-#define _DESTRUCT_VECTOR(type,size,ptr) { \\r
-       for(SQInteger nl = 0; nl < size; nl++) { \\r
-                       ptr[nl].~type(); \\r
-       } \\r
-}\r
-struct SQFunctionProto : public SQRefCounted\r
+\r
+struct SQFunctionProto : public CHAINABLE_OBJ\r
 {\r
 private:\r
-       SQFunctionProto(){\r
-       _stacksize=0;\r
-       _bgenerator=false;}\r
+       SQFunctionProto(SQSharedState *ss);\r
+       ~SQFunctionProto();\r
+       \r
 public:\r
-       static SQFunctionProto *Create(SQInteger ninstructions,\r
+       static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,\r
                SQInteger nliterals,SQInteger nparameters,\r
                SQInteger nfunctions,SQInteger noutervalues,\r
                SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)\r
@@ -85,7 +74,7 @@ public:
                SQFunctionProto *f;\r
                //I compact the whole class and members in a single memory allocation\r
                f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));\r
-               new (f) SQFunctionProto;\r
+               new (f) SQFunctionProto(ss);\r
                f->_ninstructions = ninstructions;\r
                f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];\r
                f->_nliterals = nliterals;\r
@@ -121,16 +110,21 @@ public:
                this->~SQFunctionProto();\r
                sq_vm_free(this,size);\r
        }\r
+       \r
        const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);\r
        SQInteger GetLine(SQInstruction *curr);\r
        bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
        static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);\r
-\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+       void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); }\r
+       SQObjectType GetType() {return OT_FUNCPROTO;}\r
+#endif\r
        SQObjectPtr _sourcename;\r
        SQObjectPtr _name;\r
     SQInteger _stacksize;\r
        bool _bgenerator;\r
-       bool _varparams;\r
+       SQInteger _varparams;\r
 \r
        SQInteger _nlocalvarinfos;\r
        SQLocalVarInfo *_localvarinfos;\r
old mode 100755 (executable)
new mode 100644 (file)
index 525a499..aff80e5
@@ -2,9 +2,10 @@
        see copyright notice in squirrel.h\r
 */\r
 #include "sqpcheader.h"\r
+#ifndef NO_COMPILER\r
 #include "sqcompiler.h"\r
-#include "sqfuncproto.h"\r
 #include "sqstring.h"\r
+#include "sqfuncproto.h"\r
 #include "sqtable.h"\r
 #include "sqopcodes.h"\r
 #include "sqfuncstate.h"\r
@@ -28,25 +29,25 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_GET")},\r
        {_SC("_OP_EQ")},\r
        {_SC("_OP_NE")},\r
-       {_SC("_OP_ARITH")},\r
+       {_SC("_OP_ADD")},\r
+       {_SC("_OP_SUB")},\r
+       {_SC("_OP_MUL")},\r
+       {_SC("_OP_DIV")},\r
+       {_SC("_OP_MOD")},\r
        {_SC("_OP_BITW")},\r
        {_SC("_OP_RETURN")},\r
        {_SC("_OP_LOADNULLS")},\r
-       {_SC("_OP_LOADROOTTABLE")},\r
+       {_SC("_OP_LOADROOT")},\r
        {_SC("_OP_LOADBOOL")},\r
        {_SC("_OP_DMOVE")},\r
        {_SC("_OP_JMP")},\r
-       {_SC("_OP_JNZ")},\r
+       {_SC("_OP_JCMP")},\r
        {_SC("_OP_JZ")},\r
-       {_SC("_OP_LOADFREEVAR")},\r
-       {_SC("_OP_VARGC")},\r
-       {_SC("_OP_GETVARGV")},\r
-       {_SC("_OP_NEWTABLE")},\r
-       {_SC("_OP_NEWARRAY")},\r
+       {_SC("_OP_SETOUTER")},\r
+       {_SC("_OP_GETOUTER")},\r
+       {_SC("_OP_NEWOBJ")},\r
        {_SC("_OP_APPENDARRAY")},\r
-       {_SC("_OP_GETPARENT")},\r
        {_SC("_OP_COMPARITH")},\r
-       {_SC("_OP_COMPARITHL")},\r
        {_SC("_OP_INC")},\r
        {_SC("_OP_INCL")},\r
        {_SC("_OP_PINC")},\r
@@ -64,14 +65,15 @@ SQInstructionDesc g_InstrDesc[]={
        {_SC("_OP_RESUME")},\r
        {_SC("_OP_FOREACH")},\r
        {_SC("_OP_POSTFOREACH")},\r
-       {_SC("_OP_DELEGATE")},\r
        {_SC("_OP_CLONE")},\r
        {_SC("_OP_TYPEOF")},\r
        {_SC("_OP_PUSHTRAP")},\r
        {_SC("_OP_POPTRAP")},\r
        {_SC("_OP_THROW")},\r
-       {_SC("_OP_CLASS")},\r
-       {_SC("_OP_NEWSLOTA")}\r
+       {_SC("_OP_NEWSLOTA")},\r
+       {_SC("_OP_GETBASE")},\r
+       {_SC("_OP_CLOSE")},\r
+       {_SC("_OP_JCMP")}\r
 };\r
 #endif\r
 void DumpLiteral(SQObjectPtr &o)\r
@@ -79,9 +81,9 @@ void DumpLiteral(SQObjectPtr &o)
        switch(type(o)){\r
                case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;\r
                case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;\r
-               case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;\r
+               case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;\r
                case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;\r
-               default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler\r
+               default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler\r
        }\r
 }\r
 \r
@@ -101,6 +103,8 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc
                _errfunc = efunc;\r
                _errtarget = ed;\r
                _bgenerator = false;\r
+               _outers = 0;\r
+               _ss = ss;\r
 \r
 }\r
 \r
@@ -195,11 +199,12 @@ void SQFuncState::Dump(SQFunctionProto *func)
                else if(inst.op==_OP_LOADFLOAT) {\r
                        scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);\r
                }\r
-               else if(inst.op==_OP_ARITH){\r
+       /*      else if(inst.op==_OP_ARITH){\r
                        scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
-               }\r
-               else \r
+               }*/\r
+               else {\r
                        scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
+               }\r
                n++;\r
        }\r
        scprintf(_SC("-----\n"));\r
@@ -283,8 +288,9 @@ SQInteger SQFuncState::TopTarget(){
 }\r
 SQInteger SQFuncState::PopTarget()\r
 {\r
-       SQInteger npos=_targetstack.back();\r
-       SQLocalVarInfo t=_vlocals[_targetstack.back()];\r
+       SQUnsignedInteger npos=_targetstack.back();\r
+       assert(npos < _vlocals.size());\r
+       SQLocalVarInfo &t = _vlocals[npos];\r
        if(type(t._name)==OT_NULL){\r
                _vlocals.pop_back();\r
        }\r
@@ -297,14 +303,31 @@ SQInteger SQFuncState::GetStackSize()
        return _vlocals.size();\r
 }\r
 \r
+SQInteger SQFuncState::CountOuters(SQInteger stacksize)\r
+{\r
+       SQInteger outers = 0;\r
+       SQInteger k = _vlocals.size() - 1;\r
+       while(k >= stacksize) {\r
+               SQLocalVarInfo &lvi = _vlocals[k];\r
+               k--;\r
+               if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer\r
+                       outers++;\r
+               }\r
+       }\r
+       return outers;\r
+}\r
+\r
 void SQFuncState::SetStackSize(SQInteger n)\r
 {\r
        SQInteger size=_vlocals.size();\r
        while(size>n){\r
                size--;\r
-               SQLocalVarInfo lvi=_vlocals.back();\r
+               SQLocalVarInfo lvi = _vlocals.back();\r
                if(type(lvi._name)!=OT_NULL){\r
-                       lvi._end_op=GetCurrentPos();\r
+                       if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer\r
+                               _outers--;\r
+                       }\r
+                       lvi._end_op = GetCurrentPos();\r
                        _localvarinfos.push_back(lvi);\r
                }\r
                _vlocals.pop_back();\r
@@ -337,15 +360,17 @@ SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
        lvi._pos=_vlocals.size();\r
        _vlocals.push_back(lvi);\r
        if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();\r
-       \r
        return pos;\r
 }\r
 \r
+\r
+\r
 SQInteger SQFuncState::GetLocalVariable(const SQObject &name)\r
 {\r
        SQInteger locals=_vlocals.size();\r
        while(locals>=1){\r
-               if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){\r
+               SQLocalVarInfo &lvi = _vlocals[locals-1];\r
+               if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){\r
                        return locals-1;\r
                }\r
                locals--;\r
@@ -353,6 +378,13 @@ SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
        return -1;\r
 }\r
 \r
+void SQFuncState::MarkLocalAsOuter(SQInteger pos)\r
+{\r
+       SQLocalVarInfo &lvi = _vlocals[pos];\r
+       lvi._end_op = UINT_MINUS_ONE;\r
+       _outers++;\r
+}\r
+\r
 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)\r
 {\r
        SQInteger outers = _outervalues.size();\r
@@ -360,11 +392,6 @@ SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
                if(_string(_outervalues[i]._name) == _string(name))\r
                        return i;\r
        }\r
-       return -1;\r
-}\r
-\r
-void SQFuncState::AddOuterValue(const SQObject &name)\r
-{\r
        SQInteger pos=-1;\r
        if(_parent) { \r
                pos = _parent->GetLocalVariable(name);\r
@@ -372,15 +399,18 @@ void SQFuncState::AddOuterValue(const SQObject &name)
                        pos = _parent->GetOuterVariable(name);\r
                        if(pos != -1) {\r
                                _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local\r
-                               return;\r
+                               return _outervalues.size() - 1; \r
                        }\r
                }\r
                else {\r
+                       _parent->MarkLocalAsOuter(pos);\r
                        _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local\r
-                       return;\r
+                       return _outervalues.size() - 1;\r
+                       \r
+                       \r
                }\r
-       }       \r
-       _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global\r
+       }\r
+       return -1;\r
 }\r
 \r
 void SQFuncState::AddParameter(const SQObject &name)\r
@@ -395,20 +425,58 @@ void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
                SQLineInfo li;\r
                li._line=line;li._op=(GetCurrentPos()+1);\r
                if(lineop)AddInstruction(_OP_LINE,0,line);\r
-               _lineinfos.push_back(li);\r
+               if(_lastline!=line) {\r
+                       _lineinfos.push_back(li);\r
+               }\r
                _lastline=line;\r
        }\r
 }\r
 \r
+void SQFuncState::DiscardTarget()\r
+{\r
+       SQInteger discardedtarget = PopTarget();\r
+       SQInteger size = _instructions.size();\r
+       if(size > 0 && _optimization){\r
+               SQInstruction &pi = _instructions[size-1];//previous instruction\r
+               switch(pi.op) {\r
+               case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:\r
+                       if(pi._arg0 == discardedtarget) {\r
+                               pi._arg0 = 0xFF;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
 void SQFuncState::AddInstruction(SQInstruction &i)\r
 {\r
        SQInteger size = _instructions.size();\r
        if(size > 0 && _optimization){ //simple optimizer\r
                SQInstruction &pi = _instructions[size-1];//previous instruction\r
                switch(i.op) {\r
+               case _OP_JZ:\r
+                       if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {\r
+                               pi.op = _OP_JCMP;\r
+                               pi._arg0 = (unsigned char)pi._arg1;\r
+                               pi._arg1 = i._arg1;\r
+                               return;\r
+                       }\r
+               case _OP_SET:\r
+               case _OP_NEWSLOT:\r
+                       if(i._arg0 == i._arg3) {\r
+                               i._arg0 = 0xFF;\r
+                       }\r
+                       break;\r
+               case _OP_SETOUTER:\r
+                       if(i._arg0 == i._arg2) {\r
+                               i._arg0 = 0xFF;\r
+                       }\r
+                       break;\r
                case _OP_RETURN:\r
                        if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {\r
                                pi.op = _OP_TAILCALL;\r
+                       } else if(pi.op == _OP_CLOSE){\r
+                               pi = i;\r
+                               return;\r
                        }\r
                break;\r
                case _OP_GET:\r
@@ -431,22 +499,37 @@ void SQFuncState::AddInstruction(SQInstruction &i)
                                return;\r
                        }\r
                        break;\r
-               case _OP_APPENDARRAY:\r
-                       if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
+               case _OP_APPENDARRAY: {\r
+                       SQInteger aat = -1;\r
+                       switch(pi.op) {\r
+                       case _OP_LOAD: aat = AAT_LITERAL; break;\r
+                       case _OP_LOADINT: aat = AAT_INT; break;\r
+                       case _OP_LOADBOOL: aat = AAT_BOOL; break;\r
+                       case _OP_LOADFLOAT: aat = AAT_FLOAT; break;\r
+                       default: break;\r
+                       }\r
+                       if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
                                pi.op = _OP_APPENDARRAY;\r
                                pi._arg0 = i._arg0;\r
                                pi._arg1 = pi._arg1;\r
-                               pi._arg2 = MAX_FUNC_STACKSIZE;\r
+                               pi._arg2 = (unsigned char)aat;\r
                                pi._arg3 = MAX_FUNC_STACKSIZE;\r
                                return;\r
                        }\r
+                                                         }\r
                        break;\r
-               case _OP_MOVE: \r
-                       if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))\r
-                       {\r
-                               pi._arg0 = i._arg0;\r
-                               _optimization = false;\r
-                               return;\r
+               case _OP_MOVE:\r
+                       switch(pi.op) {\r
+                       case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:\r
+                       case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:\r
+\r
+                               if(pi._arg0 == i._arg1)\r
+                               {\r
+                                       pi._arg0 = i._arg0;\r
+                                       _optimization = false;\r
+                                       //_result_elimination = false;\r
+                                       return;\r
+                               }\r
                        }\r
 \r
                        if(pi.op == _OP_MOVE)\r
@@ -512,7 +595,8 @@ SQObject SQFuncState::CreateTable()
 \r
 SQFunctionProto *SQFuncState::BuildProto()\r
 {\r
-       SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),\r
+       \r
+       SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),\r
                _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),\r
                _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());\r
 \r
@@ -532,9 +616,9 @@ SQFunctionProto *SQFuncState::BuildProto()
        for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];\r
        for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];\r
        for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];\r
-       for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];\r
-       for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];\r
-       for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];\r
+       for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];\r
+       for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];\r
+       for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];\r
 \r
        memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));\r
 \r
@@ -565,3 +649,5 @@ SQFuncState::~SQFuncState()
                PopChildState();\r
        }\r
 }\r
+\r
+#endif\r
old mode 100755 (executable)
new mode 100644 (file)
index 775a33e..1da1321
@@ -21,6 +21,7 @@ struct SQFuncState
        SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}\r
        void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}\r
        void SetStackSize(SQInteger n);\r
+       SQInteger CountOuters(SQInteger stacksize);\r
        void SnoozeOpt(){_optimization=false;}\r
        void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }\r
        SQInteger GetDefaultParamCount() { return _defaultparams.size(); }\r
@@ -29,8 +30,9 @@ struct SQFuncState
        SQInteger GetNumericConstant(const SQFloat cons);\r
        SQInteger PushLocalVariable(const SQObject &name);\r
        void AddParameter(const SQObject &name);\r
-       void AddOuterValue(const SQObject &name);\r
+       //void AddOuterValue(const SQObject &name);\r
        SQInteger GetLocalVariable(const SQObject &name);\r
+       void MarkLocalAsOuter(SQInteger pos);\r
        SQInteger GetOuterVariable(const SQObject &name);\r
        SQInteger GenerateCode();\r
        SQInteger GetStackSize();\r
@@ -42,6 +44,7 @@ struct SQFuncState
        SQInteger PopTarget();\r
        SQInteger TopTarget();\r
        SQInteger GetUpTarget(SQInteger n);\r
+       void DiscardTarget();\r
        bool IsLocal(SQUnsignedInteger stkpos);\r
        SQObject CreateString(const SQChar *s,SQInteger len = -1);\r
        SQObject CreateTable();\r
@@ -66,11 +69,13 @@ struct SQFuncState
        SQInteger _nliterals;\r
        SQLineInfoVec _lineinfos;\r
        SQFuncState *_parent;\r
+       SQIntVec _scope_blocks;\r
        SQIntVec _breaktargets;\r
        SQIntVec _continuetargets;\r
        SQIntVec _defaultparams;\r
        SQInteger _lastline;\r
        SQInteger _traps; //contains number of nested exception traps\r
+       SQInteger _outers;\r
        bool _optimization;\r
        SQSharedState *_sharedstate;\r
        sqvector<SQFuncState*> _childstates;\r
@@ -78,6 +83,7 @@ struct SQFuncState
 private:\r
        CompilerErrorFunc _errfunc;\r
        void *_errtarget;\r
+       SQSharedState *_ss;\r
 };\r
 \r
 \r
old mode 100755 (executable)
new mode 100644 (file)
index 0326825..547835b
@@ -44,7 +44,7 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile
        ADD_KEYWORD(foreach, TK_FOREACH);\r
        ADD_KEYWORD(in, TK_IN);\r
        ADD_KEYWORD(typeof, TK_TYPEOF);\r
-       ADD_KEYWORD(delegate, TK_DELEGATE);\r
+       ADD_KEYWORD(base, TK_BASE);\r
        ADD_KEYWORD(delete, TK_DELETE);\r
        ADD_KEYWORD(try, TK_TRY);\r
        ADD_KEYWORD(catch, TK_CATCH);\r
@@ -56,13 +56,10 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile
        ADD_KEYWORD(case, TK_CASE);\r
        ADD_KEYWORD(default, TK_DEFAULT);\r
        ADD_KEYWORD(this, TK_THIS);\r
-       ADD_KEYWORD(parent,TK_PARENT);\r
        ADD_KEYWORD(class,TK_CLASS);\r
        ADD_KEYWORD(extends,TK_EXTENDS);\r
        ADD_KEYWORD(constructor,TK_CONSTRUCTOR);\r
        ADD_KEYWORD(instanceof,TK_INSTANCEOF);\r
-       ADD_KEYWORD(vargc,TK_VARGC);\r
-       ADD_KEYWORD(vargv,TK_VARGV);\r
        ADD_KEYWORD(true,TK_TRUE);\r
        ADD_KEYWORD(false,TK_FALSE);\r
        ADD_KEYWORD(static,TK_STATIC);\r
@@ -74,6 +71,7 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile
        _lasttokenline = _currentline = 1;\r
        _currentcolumn = 0;\r
        _prevtoken = -1;\r
+       _reached_eof = SQFalse;\r
        Next();\r
 }\r
 \r
@@ -91,6 +89,7 @@ void SQLexer::Next()
                return;\r
        }\r
        _currdata = SQUIRREL_EOB;\r
+       _reached_eof = SQTrue;\r
 }\r
 \r
 const SQChar *SQLexer::Tok2Str(SQInteger tok)\r
@@ -117,6 +116,10 @@ void SQLexer::LexBlockComment()
                }\r
        }\r
 }\r
+void SQLexer::LexLineComment()\r
+{\r
+       do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));\r
+}\r
 \r
 SQInteger SQLexer::Lex()\r
 {\r
@@ -131,6 +134,7 @@ SQInteger SQLexer::Lex()
                        NEXT();\r
                        _currentcolumn=1;\r
                        continue;\r
+               case _SC('#'): LexLineComment(); continue;\r
                case _SC('/'):\r
                        NEXT();\r
                        switch(CUR_CHAR){\r
@@ -139,7 +143,7 @@ SQInteger SQLexer::Lex()
                                LexBlockComment();\r
                                continue;       \r
                        case _SC('/'):\r
-                               do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));\r
+                               LexLineComment();\r
                                continue;\r
                        case _SC('='):\r
                                NEXT();\r
@@ -158,12 +162,20 @@ SQInteger SQLexer::Lex()
                        else { NEXT(); RETURN_TOKEN(TK_EQ); }\r
                case _SC('<'):\r
                        NEXT();\r
-                       if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }\r
-                       else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }\r
-                       else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }\r
-                       else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }\r
-                       //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }\r
-                       else { RETURN_TOKEN('<') }\r
+                       switch(CUR_CHAR) {\r
+                       case _SC('='):\r
+                               NEXT(); \r
+                               if(CUR_CHAR == _SC('>')) {\r
+                                       NEXT();\r
+                                       RETURN_TOKEN(TK_3WAYSCMP); \r
+                               }\r
+                               RETURN_TOKEN(TK_LE) \r
+                               break;\r
+                       case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break;\r
+                       case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break;\r
+                       case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break;\r
+                       }\r
+                       RETURN_TOKEN('<');\r
                case _SC('>'):\r
                        NEXT();\r
                        if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}\r
@@ -182,9 +194,10 @@ SQInteger SQLexer::Lex()
                        else { NEXT(); RETURN_TOKEN(TK_NE); }\r
                case _SC('@'): {\r
                        SQInteger stype;\r
-                       NEXT(); \r
-                       if(CUR_CHAR != _SC('"'))\r
-                               Error(_SC("string expected"));\r
+                       NEXT();\r
+                       if(CUR_CHAR != _SC('"')) {\r
+                               RETURN_TOKEN('@');\r
+                       }\r
                        if((stype=ReadString('"',true))!=-1) {\r
                                RETURN_TOKEN(stype);\r
                        }\r
old mode 100755 (executable)
new mode 100644 (file)
index aedff15..d3283c6
@@ -21,10 +21,12 @@ private:
        SQInteger ReadString(SQInteger ndelim,bool verbatim);\r
        SQInteger ReadNumber();\r
        void LexBlockComment();\r
+       void LexLineComment();\r
        SQInteger ReadID();\r
        void Next();\r
        SQInteger _curtoken;\r
        SQTable *_keywords;\r
+       SQBool _reached_eof;\r
 public:\r
        SQInteger _prevtoken;\r
        SQInteger _currentline;\r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 40c5ba4..18ea008
@@ -35,6 +35,7 @@ const SQChar *IdType2Name(SQObjectType type)
        case _RT_CLASS: return _SC("class");\r
        case _RT_INSTANCE: return _SC("instance");\r
        case _RT_WEAKREF: return _SC("weakref");\r
+       case _RT_OUTER: return _SC("outer");\r
        default:\r
                return NULL;\r
        }\r
@@ -48,7 +49,6 @@ const SQChar *GetTypeName(const SQObjectPtr &obj1)
 SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)\r
 {\r
        SQString *str=ADD_STRING(ss,s,len);\r
-       str->_sharedstate=ss;\r
        return str;\r
 }\r
 \r
@@ -62,7 +62,7 @@ SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjec
        SQInteger idx = (SQInteger)TranslateIndex(refpos);\r
        while(idx < _len){\r
                outkey = (SQInteger)idx;\r
-               outval = SQInteger(_val[idx]);\r
+               outval = (SQInteger)((SQUnsignedInteger)_val[idx]);\r
                //return idx for the next iteration\r
                return ++idx;\r
        }\r
@@ -128,22 +128,24 @@ bool SQDelegable::SetDelegate(SQTable *mt)
        return true;\r
 }\r
 \r
-bool SQGenerator::Yield(SQVM *v)\r
+bool SQGenerator::Yield(SQVM *v,SQInteger target)\r
 {\r
        if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}\r
        if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
        SQInteger size = v->_top-v->_stackbase;\r
-       _ci=*v->ci;\r
+       \r
        _stack.resize(size);\r
-       for(SQInteger n =0; n<size; n++) {\r
+       SQObject _this = v->_stack[v->_stackbase];\r
+       _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;\r
+       for(SQInteger n =1; n<target; n++) {\r
                _stack._vals[n] = v->_stack[v->_stackbase+n];\r
-               v->_stack[v->_stackbase+n] = _null_;\r
        }\r
-       SQInteger nvargs = v->ci->_vargs.size;\r
-       SQInteger vargsbase = v->ci->_vargs.base;\r
-       for(SQInteger j = nvargs - 1; j >= 0; j--) {\r
-               _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
+       for(SQInteger j =0; j < size; j++)\r
+       {\r
+               v->_stack[v->_stackbase+j].Null();\r
        }\r
+\r
+       _ci = *v->ci;\r
        _ci._generator=NULL;\r
        for(SQInteger i=0;i<_ci._etraps;i++) {\r
                _etraps.push_back(v->_etraps.top());\r
@@ -153,37 +155,39 @@ bool SQGenerator::Yield(SQVM *v)
        return true;\r
 }\r
 \r
-bool SQGenerator::Resume(SQVM *v,SQInteger target)\r
+bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest)\r
 {\r
-       SQInteger size=_stack.size();\r
        if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
        if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
-       SQInteger prevtop=v->_top-v->_stackbase;\r
-       PUSH_CALLINFO(v,_ci);\r
-       SQInteger oldstackbase=v->_stackbase;\r
-       v->_stackbase = v->_top;\r
-       v->ci->_target = (SQInt32)target;\r
-       v->ci->_generator = this;\r
-       v->ci->_vargs.size = (unsigned short)_vargsstack.size();\r
-       \r
+       SQInteger size = _stack.size();\r
+       SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);\r
+       assert(target>=0 && target<=255);\r
+       if(!v->EnterFrame(v->_top, v->_top + size, false)) \r
+               return false;\r
+       v->ci->_generator   = this;\r
+       v->ci->_target      = (SQInt32)target;\r
+       v->ci->_closure     = _ci._closure;\r
+       v->ci->_ip          = _ci._ip;\r
+       v->ci->_literals    = _ci._literals;\r
+       v->ci->_ncalls      = _ci._ncalls;\r
+       v->ci->_etraps      = _ci._etraps;\r
+       v->ci->_root        = _ci._root;\r
+\r
+\r
        for(SQInteger i=0;i<_ci._etraps;i++) {\r
                v->_etraps.push_back(_etraps.top());\r
                _etraps.pop_back();\r
        }\r
-       for(SQInteger n =0; n<size; n++) {\r
+       SQObject _this = _stack._vals[0];\r
+       v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;\r
+\r
+       for(SQInteger n = 1; n<size; n++) {\r
                v->_stack[v->_stackbase+n] = _stack._vals[n];\r
-               _stack._vals[0] = _null_;\r
+               _stack._vals[n].Null();\r
        }\r
-       while(_vargsstack.size()) {\r
-               v->_vargsstack.push_back(_vargsstack.back());\r
-               _vargsstack.pop_back();\r
-       }\r
-       v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);\r
-       v->_top=v->_stackbase+size;\r
-       v->ci->_prevtop = (SQInt32)prevtop;\r
-       v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);\r
+\r
        _state=eRunning;\r
-       if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure))\r
+       if (v->_debughook)\r
                v->CallDebugHook(_SC('c'));\r
 \r
        return true;\r
@@ -216,18 +220,45 @@ const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQU
        return res;\r
 }\r
 \r
+\r
 SQInteger SQFunctionProto::GetLine(SQInstruction *curr)\r
 {\r
        SQInteger op = (SQInteger)(curr-_instructions);\r
        SQInteger line=_lineinfos[0]._line;\r
-       for(SQInteger i=1;i<_nlineinfos;i++){\r
-               if(_lineinfos[i]._op>=op)\r
-                       return line;\r
-               line=_lineinfos[i]._line;\r
+       SQInteger low = 0;\r
+       SQInteger high = _nlineinfos - 1;\r
+       SQInteger mid = 0;\r
+       while(low <= high)\r
+       {\r
+               mid = low + ((high - low) >> 1);\r
+               SQInteger curop = _lineinfos[mid]._op;\r
+               if(curop > op)\r
+               {\r
+                       high = mid - 1;\r
+               }\r
+               else if(curop < op) {\r
+                       if(mid < (_nlineinfos - 1) \r
+                               && _lineinfos[mid + 1]._op >= op) {\r
+                               break;\r
+                       }\r
+                       low = mid + 1;\r
+               }\r
+               else { //equal\r
+                       break;\r
+               }\r
        }\r
+\r
+       line = _lineinfos[mid]._line;\r
        return line;\r
 }\r
 \r
+SQClosure::~SQClosure()\r
+{\r
+       __ObjRelease(_env);\r
+       __ObjRelease(_base);\r
+       REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
 #define _CHECK_IO(exp)  { if(!exp)return false; }\r
 bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
 {\r
@@ -247,14 +278,14 @@ bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest
        return true;\r
 }\r
 \r
-bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag)\r
+bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)\r
 {\r
        return SafeWrite(v,write,up,&tag,sizeof(tag));\r
 }\r
 \r
-bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)\r
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag)\r
 {\r
-       SQInteger t;\r
+       SQUnsignedInteger32 t;\r
        _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
        if(t != tag){\r
                v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
@@ -265,12 +296,14 @@ bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)
 \r
 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
 {\r
-       _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
+       SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);\r
+       _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));\r
        switch(type(o)){\r
        case OT_STRING:\r
                _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
                _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
                break;\r
+       case OT_BOOL:\r
        case OT_INTEGER:\r
                _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
        case OT_FLOAT:\r
@@ -286,8 +319,9 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o
 \r
 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
 {\r
-       SQObjectType t;\r
-       _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
+       SQUnsignedInteger32 _type;\r
+       _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));\r
+       SQObjectType t = (SQObjectType)_type;\r
        switch(t){\r
        case OT_STRING:{\r
                SQInteger len;\r
@@ -300,12 +334,16 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
                SQInteger i;\r
                _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
                                        }\r
+       case OT_BOOL:{\r
+               SQInteger i;\r
+               _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;\r
+                                       }\r
        case OT_FLOAT:{\r
                SQFloat f;\r
                _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
                                  }\r
        case OT_NULL:\r
-               o=_null_;\r
+               o.Null();\r
                break;\r
        default:\r
                v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
@@ -318,7 +356,9 @@ bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
 {\r
        _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
        _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
-       _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
+       _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger)));\r
+       _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat)));\r
+       _CHECK_IO(_function->Save(v,up,write));\r
        _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
        return true;\r
 }\r
@@ -327,6 +367,8 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
 {\r
        _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
        _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
+       _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger)));\r
+       _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat)));\r
        SQObjectPtr func;\r
        _CHECK_IO(SQFunctionProto::Load(v,up,read,func));\r
        _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
@@ -334,6 +376,18 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
        return true;\r
 }\r
 \r
+SQFunctionProto::SQFunctionProto(SQSharedState *ss)\r
+{\r
+       _stacksize=0;\r
+       _bgenerator=false;\r
+       INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
+SQFunctionProto::~SQFunctionProto()\r
+{\r
+       REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
 bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
 {\r
        SQInteger i,nliterals = _nliterals,nparameters = _nparameters;\r
@@ -419,7 +473,7 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr
        _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));\r
        \r
 \r
-       SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,\r
+       SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters,\r
                        nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);\r
        SQObjectPtr proto = f; //gets a ref in case of failure\r
        f->_sourcename = sourcename;\r
@@ -492,11 +546,10 @@ void SQVM::Mark(SQCollectable **chain)
        START_MARK()\r
                SQSharedState::MarkObject(_lasterror,chain);\r
                SQSharedState::MarkObject(_errorhandler,chain);\r
-               SQSharedState::MarkObject(_debughook,chain);\r
+               SQSharedState::MarkObject(_debughook_closure,chain);\r
                SQSharedState::MarkObject(_roottable, chain);\r
                SQSharedState::MarkObject(temp_reg, chain);\r
                for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
-               for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
                for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);\r
        END_MARK()\r
 }\r
@@ -534,7 +587,7 @@ void SQClass::Mark(SQCollectable **chain)
                        SQSharedState::MarkObject(_methods[j].val, chain);\r
                        SQSharedState::MarkObject(_methods[j].attrs, chain);\r
                }\r
-               for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) {\r
+               for(SQUnsignedInteger k =0; k< MT_LAST; k++) {\r
                        SQSharedState::MarkObject(_metamethods[k], chain);\r
                }\r
        END_MARK()\r
@@ -555,23 +608,43 @@ void SQGenerator::Mark(SQCollectable **chain)
 {\r
        START_MARK()\r
                for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
-               for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
                SQSharedState::MarkObject(_closure, chain);\r
        END_MARK()\r
 }\r
 \r
+void SQFunctionProto::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain);\r
+               for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain);\r
+       END_MARK()\r
+}\r
+\r
 void SQClosure::Mark(SQCollectable **chain)\r
 {\r
        START_MARK()\r
-               for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
-               for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain);\r
+               if(_base) _base->Mark(chain);\r
+               SQFunctionProto *fp = _function;\r
+               fp->Mark(chain);\r
+               for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+               for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain);\r
        END_MARK()\r
 }\r
 \r
 void SQNativeClosure::Mark(SQCollectable **chain)\r
 {\r
        START_MARK()\r
-               for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+               for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQOuter::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+    /* If the valptr points to a closed value, that value is alive */\r
+    if(_valptr == &_value) {\r
+      SQSharedState::MarkObject(_value, chain);\r
+    }\r
        END_MARK()\r
 }\r
 \r
old mode 100755 (executable)
new mode 100644 (file)
index d6f6ef1..e0e235e
@@ -4,6 +4,12 @@
 \r
 #include "squtils.h"\r
 \r
+#ifdef _SQ64\r
+#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)\r
+#else\r
+#define UINT_MINUS_ONE (0xFFFFFFFF)\r
+#endif\r
+\r
 #define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))\r
 #define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))\r
 #define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))\r
@@ -51,16 +57,42 @@ enum SQMetaMethod{
 #define MM_NEWMEMBER _SC("_newmember")\r
 #define MM_INHERITED _SC("_inherited")\r
 \r
+\r
+#define _CONSTRUCT_VECTOR(type,size,ptr) { \\r
+       for(SQInteger n = 0; n < ((SQInteger)size); n++) { \\r
+                       new (&ptr[n]) type(); \\r
+               } \\r
+}\r
+\r
+#define _DESTRUCT_VECTOR(type,size,ptr) { \\r
+       for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \\r
+                       ptr[nl].~type(); \\r
+       } \\r
+}\r
+\r
+#define _COPY_VECTOR(dest,src,size) { \\r
+       for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \\r
+               dest[_n_] = src[_n_]; \\r
+       } \\r
+}\r
+\r
+#define _NULL_SQOBJECT_VECTOR(vec,size) { \\r
+       for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \\r
+               vec[_n_].Null(); \\r
+       } \\r
+}\r
+\r
 #define MINPOWER2 4\r
 \r
 struct SQRefCounted\r
 {\r
+       SQUnsignedInteger _uiRef;\r
+       struct SQWeakRef *_weakref;\r
        SQRefCounted() { _uiRef = 0; _weakref = NULL; }\r
        virtual ~SQRefCounted();\r
        SQWeakRef *GetWeakRef(SQObjectType type);\r
-       SQUnsignedInteger _uiRef;\r
-       struct SQWeakRef *_weakref;\r
        virtual void Release()=0;\r
+       \r
 };\r
 \r
 struct SQWeakRef : SQRefCounted\r
@@ -78,7 +110,7 @@ struct SQObjectPtr;
                        unval.pRefCounted->_uiRef++; \\r
                }  \r
 \r
-#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0))     \\r
+#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0))     \\r
                {       \\r
                        unval.pRefCounted->Release();   \\r
                }\r
@@ -116,17 +148,61 @@ struct SQObjectPtr;
 #define _instance(obj) ((obj)._unVal.pInstance)\r
 #define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)\r
 #define _weakref(obj) ((obj)._unVal.pWeakRef)\r
+#define _outer(obj) ((obj)._unVal.pOuter)\r
 #define _refcounted(obj) ((obj)._unVal.pRefCounted)\r
 #define _rawval(obj) ((obj)._unVal.raw)\r
 \r
 #define _stringval(obj) (obj)._unVal.pString->_val\r
-#define _userdataval(obj) (obj)._unVal.pUserData->_val\r
+#define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1))\r
 \r
 #define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))\r
-#define tointeger(num) (       (type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))\r
-\r
+#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))\r
 /////////////////////////////////////////////////////////////////////////////////////\r
 /////////////////////////////////////////////////////////////////////////////////////\r
+#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)\r
+#define SQ_REFOBJECT_INIT()    SQ_OBJECT_RAWINIT()\r
+#else\r
+#define SQ_REFOBJECT_INIT()\r
+#endif\r
+\r
+#define _REF_TYPE_DECL(type,_class,sym) \\r
+       SQObjectPtr(_class * x) \\r
+       { \\r
+               SQ_OBJECT_RAWINIT() \\r
+               _type=type; \\r
+               _unVal.sym = x; \\r
+               assert(_unVal.pTable); \\r
+               _unVal.pRefCounted->_uiRef++; \\r
+       } \\r
+       inline SQObjectPtr& operator=(_class *x) \\r
+       {  \\r
+               SQObjectType tOldType; \\r
+               SQObjectValue unOldVal; \\r
+               tOldType=_type; \\r
+               unOldVal=_unVal; \\r
+               _type = type; \\r
+               SQ_REFOBJECT_INIT() \\r
+               _unVal.sym = x; \\r
+               _unVal.pRefCounted->_uiRef++; \\r
+               __Release(tOldType,unOldVal); \\r
+               return *this; \\r
+       }\r
+\r
+#define _SCALAR_TYPE_DECL(type,_class,sym) \\r
+       SQObjectPtr(_class x) \\r
+       { \\r
+               SQ_OBJECT_RAWINIT() \\r
+               _type=type; \\r
+               _unVal.sym = x; \\r
+       } \\r
+       inline SQObjectPtr& operator=(_class x) \\r
+       {  \\r
+               __Release(_type,_unVal); \\r
+               _type = type; \\r
+               SQ_OBJECT_RAWINIT() \\r
+               _unVal.sym = x; \\r
+               return *this; \\r
+       }\r
 struct SQObjectPtr : public SQObject\r
 {\r
        SQObjectPtr()\r
@@ -137,168 +213,54 @@ struct SQObjectPtr : public SQObject
        }\r
        SQObjectPtr(const SQObjectPtr &o)\r
        {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=o._type;\r
-               _unVal=o._unVal;\r
+               _type = o._type;\r
+               _unVal = o._unVal;\r
                __AddRef(_type,_unVal);\r
        }\r
        SQObjectPtr(const SQObject &o)\r
        {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=o._type;\r
-               _unVal=o._unVal;\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQTable *pTable)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_TABLE;\r
-               _unVal.pTable=pTable;\r
-               assert(_unVal.pTable);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQClass *pClass)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_CLASS;\r
-               _unVal.pClass=pClass;\r
-               assert(_unVal.pClass);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQInstance *pInstance)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_INSTANCE;\r
-               _unVal.pInstance=pInstance;\r
-               assert(_unVal.pInstance);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQArray *pArray)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_ARRAY;\r
-               _unVal.pArray=pArray;\r
-               assert(_unVal.pArray);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQClosure *pClosure)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_CLOSURE;\r
-               _unVal.pClosure=pClosure;\r
-               assert(_unVal.pClosure);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQGenerator *pGenerator)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_GENERATOR;\r
-               _unVal.pGenerator=pGenerator;\r
-               assert(_unVal.pGenerator);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQNativeClosure *pNativeClosure)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_NATIVECLOSURE;\r
-               _unVal.pNativeClosure=pNativeClosure;\r
-               assert(_unVal.pNativeClosure);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQString *pString)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_STRING;\r
-               _unVal.pString=pString;\r
-               assert(_unVal.pString);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQUserData *pUserData)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_USERDATA;\r
-               _unVal.pUserData=pUserData;\r
-               assert(_unVal.pUserData);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQVM *pThread)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_THREAD;\r
-               _unVal.pThread=pThread;\r
-               assert(_unVal.pThread);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQWeakRef *pWeakRef)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_WEAKREF;\r
-               _unVal.pWeakRef=pWeakRef;\r
-               assert(_unVal.pWeakRef);\r
-               __AddRef(_type,_unVal);\r
-       }\r
-       SQObjectPtr(SQFunctionProto *pFunctionProto)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_FUNCPROTO;\r
-               _unVal.pFunctionProto=pFunctionProto;\r
-               assert(_unVal.pFunctionProto);\r
+               _type = o._type;\r
+               _unVal = o._unVal;\r
                __AddRef(_type,_unVal);\r
        }\r
-       SQObjectPtr(SQInteger nInteger)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_INTEGER;\r
-               _unVal.nInteger=nInteger;\r
-       }\r
-       SQObjectPtr(SQFloat fFloat)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_FLOAT;\r
-               _unVal.fFloat=fFloat;\r
-       }\r
+       _REF_TYPE_DECL(OT_TABLE,SQTable,pTable)\r
+       _REF_TYPE_DECL(OT_CLASS,SQClass,pClass)\r
+       _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance)\r
+       _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray)\r
+       _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure)\r
+       _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure)\r
+       _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter)\r
+       _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator)\r
+       _REF_TYPE_DECL(OT_STRING,SQString,pString)\r
+       _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData)\r
+       _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef)\r
+       _REF_TYPE_DECL(OT_THREAD,SQVM,pThread)\r
+       _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto)\r
+       \r
+       _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger)\r
+       _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat)\r
+       _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer)\r
+\r
        SQObjectPtr(bool bBool)\r
        {\r
                SQ_OBJECT_RAWINIT()\r
                _type = OT_BOOL;\r
                _unVal.nInteger = bBool?1:0;\r
        }\r
-       SQObjectPtr(SQUserPointer pUserPointer)\r
-       {\r
-               SQ_OBJECT_RAWINIT()\r
-               _type=OT_USERPOINTER;\r
-               _unVal.pUserPointer=pUserPointer;\r
-       }\r
-       ~SQObjectPtr()\r
-       {\r
-               __Release(_type,_unVal);\r
-       }\r
-       inline void Null()\r
-       {\r
-               SQObjectType tOldType;\r
-               SQObjectValue unOldVal;\r
-               tOldType = _type;\r
-               unOldVal = _unVal;\r
-               _type = OT_NULL;\r
-               _unVal.pUserPointer = NULL;\r
-               __Release(tOldType,unOldVal);\r
-       }\r
-       inline SQObjectPtr& operator=(SQInteger i)\r
+       inline SQObjectPtr& operator=(bool b)\r
        { \r
                __Release(_type,_unVal);\r
                SQ_OBJECT_RAWINIT()\r
-               _unVal.nInteger = i;\r
-               _type = OT_INTEGER;\r
+               _type = OT_BOOL;\r
+               _unVal.nInteger = b?1:0;\r
                return *this;\r
        }\r
-       inline SQObjectPtr& operator=(SQFloat f)\r
-       { \r
+\r
+       ~SQObjectPtr()\r
+       {\r
                __Release(_type,_unVal);\r
-               SQ_OBJECT_RAWINIT()\r
-               _unVal.fFloat = f;\r
-               _type = OT_FLOAT;\r
-               return *this;\r
        }\r
+                       \r
        inline SQObjectPtr& operator=(const SQObjectPtr& obj)\r
        { \r
                SQObjectType tOldType;\r
@@ -323,10 +285,19 @@ struct SQObjectPtr : public SQObject
                __Release(tOldType,unOldVal);\r
                return *this;\r
        }\r
+       inline void Null()\r
+       {\r
+               SQObjectType tOldType = _type;\r
+               SQObjectValue unOldVal = _unVal;\r
+               _type = OT_NULL;\r
+               _unVal.raw = (SQRawObjectVal)NULL;\r
+               __Release(tOldType ,unOldVal);\r
+       }\r
        private:\r
                SQObjectPtr(const SQChar *){} //safety\r
 };\r
 \r
+\r
 inline void _Swap(SQObject &a,SQObject &b)\r
 {\r
        SQObjectType tOldType = a._type;\r
@@ -336,6 +307,7 @@ inline void _Swap(SQObject &a,SQObject &b)
        b._type = tOldType;\r
        b._unVal = unOldVal;\r
 }\r
+\r
 /////////////////////////////////////////////////////////////////////////////////////\r
 #ifndef NO_GARBAGE_COLLECTOR\r
 #define MARK_FLAG 0x80000000\r
@@ -343,6 +315,7 @@ struct SQCollectable : public SQRefCounted {
        SQCollectable *_next;\r
        SQCollectable *_prev;\r
        SQSharedState *_sharedstate;\r
+       virtual SQObjectType GetType()=0;\r
        virtual void Release()=0;\r
        virtual void Mark(SQCollectable **chain)=0;\r
        void UnMark();\r
old mode 100755 (executable)
new mode 100644 (file)
index 3867a59..4d17981
@@ -18,8 +18,24 @@ enum CmpOP {
        CMP_G = 0,\r
        CMP_GE = 2,     \r
        CMP_L = 3,\r
-       CMP_LE = 4\r
+       CMP_LE = 4,\r
+       CMP_3W = 5\r
 };\r
+\r
+enum NewObjectType {\r
+       NOT_TABLE = 0,\r
+       NOT_ARRAY = 1,\r
+       NOT_CLASS = 2\r
+};\r
+\r
+enum AppendArrayType {\r
+       AAT_STACK = 0,\r
+       AAT_LITERAL = 1,\r
+       AAT_INT = 2,\r
+       AAT_FLOAT = 3,\r
+       AAT_BOOL = 4\r
+};\r
+\r
 enum SQOpcode\r
 {\r
        _OP_LINE=                               0x00,   \r
@@ -39,25 +55,26 @@ enum SQOpcode
        _OP_GET=                                0x0E,\r
        _OP_EQ=                                 0x0F,\r
        _OP_NE=                                 0x10,\r
-       _OP_ARITH=                              0x11,\r
-       _OP_BITW=                               0x12,\r
-       _OP_RETURN=                             0x13,   \r
-       _OP_LOADNULLS=                  0x14,   \r
-       _OP_LOADROOTTABLE=              0x15,\r
-       _OP_LOADBOOL=                   0x16,\r
-       _OP_DMOVE=                              0x17,   \r
-       _OP_JMP=                                0x18,   \r
-       _OP_JNZ=                                0x19,   \r
-       _OP_JZ=                                 0x1A,   \r
-       _OP_LOADFREEVAR=                0x1B,   \r
-       _OP_VARGC=                              0x1C,   \r
-       _OP_GETVARGV=                   0x1D,   \r
-       _OP_NEWTABLE=                   0x1E,   \r
-       _OP_NEWARRAY=                   0x1F,   \r
-       _OP_APPENDARRAY=                0x20,   \r
-       _OP_GETPARENT=                  0x21,   \r
-       _OP_COMPARITH=                  0x22,   \r
-       _OP_COMPARITHL=                 0x23,   \r
+       _OP_ADD=                                0x11,\r
+       _OP_SUB=                                0x12,\r
+       _OP_MUL=                                0x13,\r
+       _OP_DIV=                                0x14,\r
+       _OP_MOD=                                0x15,\r
+       _OP_BITW=                               0x16,\r
+       _OP_RETURN=                             0x17,   \r
+       _OP_LOADNULLS=                  0x18,   \r
+       _OP_LOADROOT=                   0x19,\r
+       _OP_LOADBOOL=                   0x1A,\r
+       _OP_DMOVE=                              0x1B,   \r
+       _OP_JMP=                                0x1C,   \r
+       //_OP_JNZ=                              0x1D,\r
+       _OP_JCMP=                               0x1D,\r
+       _OP_JZ=                                 0x1E,   \r
+       _OP_SETOUTER=                   0x1F,   \r
+       _OP_GETOUTER=                   0x20,   \r
+       _OP_NEWOBJ=                             0x21,\r
+       _OP_APPENDARRAY=                0x22,   \r
+       _OP_COMPARITH=                  0x23,   \r
        _OP_INC=                                0x24,   \r
        _OP_INCL=                               0x25,   \r
        _OP_PINC=                               0x26,   \r
@@ -75,14 +92,14 @@ enum SQOpcode
        _OP_RESUME=                             0x32,\r
        _OP_FOREACH=                    0x33,\r
        _OP_POSTFOREACH=                0x34,\r
-       _OP_DELEGATE=                   0x35,\r
-       _OP_CLONE=                              0x36,\r
-       _OP_TYPEOF=                             0x37,\r
-       _OP_PUSHTRAP=                   0x38,\r
-       _OP_POPTRAP=                    0x39,\r
-       _OP_THROW=                              0x3A,\r
-       _OP_CLASS=                              0x3B,\r
-       _OP_NEWSLOTA=                   0x3C,\r
+       _OP_CLONE=                              0x35,\r
+       _OP_TYPEOF=                             0x36,\r
+       _OP_PUSHTRAP=                   0x37,\r
+       _OP_POPTRAP=                    0x38,\r
+       _OP_THROW=                              0x39,\r
+       _OP_NEWSLOTA=                   0x3A,\r
+       _OP_GETBASE=                    0x3B,\r
+       _OP_CLOSE=                              0x3C,\r
 };                                                       \r
 \r
 struct SQInstructionDesc {       \r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index fd84b0a..bfea9c4
 #include "squserdata.h"\r
 #include "sqclass.h"\r
 \r
-SQObjectPtr _null_;\r
-SQObjectPtr _true_(true);\r
-SQObjectPtr _false_(false);\r
-SQObjectPtr _one_((SQInteger)1);\r
-SQObjectPtr _minusone_((SQInteger)-1);\r
+//SQObjectPtr _null_;\r
+//SQObjectPtr _true_(true);\r
+//SQObjectPtr _false_(false);\r
+//SQObjectPtr _one_((SQInteger)1);\r
+//SQObjectPtr _minusone_((SQInteger)-1);\r
 \r
 SQSharedState::SQSharedState()\r
 {\r
        _compilererrorhandler = NULL;\r
        _printfunc = NULL;\r
+       _errorfunc = NULL;\r
        _debuginfo = false;\r
        _notifyallexceptions = false;\r
 }\r
@@ -83,7 +84,7 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
        SQInteger i=0;\r
        SQTable *t=SQTable::Create(ss,0);\r
        while(funcz[i].name!=0){\r
-               SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);\r
+               SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0);\r
                nc->_nparamscheck = funcz[i].nparamscheck;\r
                nc->_name = SQString::Create(ss,funcz[i].name);\r
                if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))\r
@@ -101,7 +102,8 @@ void SQSharedState::Init()
 #ifndef NO_GARBAGE_COLLECTOR\r
        _gc_chain=NULL;\r
 #endif\r
-       sq_new(_stringtable,SQStringTable);\r
+       _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));\r
+       new (_stringtable) SQStringTable(this);\r
        sq_new(_metamethods,SQObjectPtrVec);\r
        sq_new(_systemstrings,SQObjectPtrVec);\r
        sq_new(_types,SQObjectPtrVec);\r
@@ -161,29 +163,29 @@ void SQSharedState::Init()
 \r
 SQSharedState::~SQSharedState()\r
 {\r
-       _constructoridx = _null_;\r
+       _constructoridx.Null();\r
        _table(_registry)->Finalize();\r
        _table(_consts)->Finalize();\r
        _table(_metamethodsmap)->Finalize();\r
-       _registry = _null_;\r
-       _consts = _null_;\r
-       _metamethodsmap = _null_;\r
+       _registry.Null();\r
+       _consts.Null();\r
+       _metamethodsmap.Null();\r
        while(!_systemstrings->empty()) {\r
-               _systemstrings->back()=_null_;\r
+               _systemstrings->back().Null();\r
                _systemstrings->pop_back();\r
        }\r
        _thread(_root_vm)->Finalize();\r
-       _root_vm = _null_;\r
-       _table_default_delegate = _null_;\r
-       _array_default_delegate = _null_;\r
-       _string_default_delegate = _null_;\r
-       _number_default_delegate = _null_;\r
-       _closure_default_delegate = _null_;\r
-       _generator_default_delegate = _null_;\r
-       _thread_default_delegate = _null_;\r
-       _class_default_delegate = _null_;\r
-       _instance_default_delegate = _null_;\r
-       _weakref_default_delegate = _null_;\r
+       _root_vm.Null();\r
+       _table_default_delegate.Null();\r
+       _array_default_delegate.Null();\r
+       _string_default_delegate.Null();\r
+       _number_default_delegate.Null();\r
+       _closure_default_delegate.Null();\r
+       _generator_default_delegate.Null();\r
+       _thread_default_delegate.Null();\r
+       _class_default_delegate.Null();\r
+       _instance_default_delegate.Null();\r
+       _weakref_default_delegate.Null();\r
        _refs_table.Finalize();\r
 #ifndef NO_GARBAGE_COLLECTOR\r
        SQCollectable *t = _gc_chain;\r
@@ -239,34 +241,98 @@ void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
        case OT_THREAD:_thread(o)->Mark(chain);break;\r
        case OT_CLASS:_class(o)->Mark(chain);break;\r
        case OT_INSTANCE:_instance(o)->Mark(chain);break;\r
+       case OT_OUTER:_outer(o)->Mark(chain);break;\r
+       case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break;\r
        default: break; //shutup compiler\r
        }\r
 }\r
 \r
 \r
-SQInteger SQSharedState::CollectGarbage(SQVM *vm)\r
+void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain)\r
 {\r
-       SQInteger n=0;\r
-       SQCollectable *tchain=NULL;\r
        SQVM *vms = _thread(_root_vm);\r
        \r
-       vms->Mark(&tchain);\r
-       SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
-       _refs_table.Mark(&tchain);\r
-       MarkObject(_registry,&tchain);\r
-       MarkObject(_consts,&tchain);\r
-       MarkObject(_metamethodsmap,&tchain);\r
-       MarkObject(_table_default_delegate,&tchain);\r
-       MarkObject(_array_default_delegate,&tchain);\r
-       MarkObject(_string_default_delegate,&tchain);\r
-       MarkObject(_number_default_delegate,&tchain);\r
-       MarkObject(_generator_default_delegate,&tchain);\r
-       MarkObject(_thread_default_delegate,&tchain);\r
-       MarkObject(_closure_default_delegate,&tchain);\r
-       MarkObject(_class_default_delegate,&tchain);\r
-       MarkObject(_instance_default_delegate,&tchain);\r
-       MarkObject(_weakref_default_delegate,&tchain);\r
+       vms->Mark(tchain);\r
        \r
+       _refs_table.Mark(tchain);\r
+       MarkObject(_registry,tchain);\r
+       MarkObject(_consts,tchain);\r
+       MarkObject(_metamethodsmap,tchain);\r
+       MarkObject(_table_default_delegate,tchain);\r
+       MarkObject(_array_default_delegate,tchain);\r
+       MarkObject(_string_default_delegate,tchain);\r
+       MarkObject(_number_default_delegate,tchain);\r
+       MarkObject(_generator_default_delegate,tchain);\r
+       MarkObject(_thread_default_delegate,tchain);\r
+       MarkObject(_closure_default_delegate,tchain);\r
+       MarkObject(_class_default_delegate,tchain);\r
+       MarkObject(_instance_default_delegate,tchain);\r
+       MarkObject(_weakref_default_delegate,tchain);\r
+\r
+}\r
+\r
+SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm)\r
+{\r
+       SQInteger n=0;\r
+       SQCollectable *tchain=NULL;\r
+\r
+       RunMark(vm,&tchain);\r
+\r
+       SQCollectable *resurrected = _gc_chain;\r
+       SQCollectable *t = resurrected;\r
+       //SQCollectable *nx = NULL;\r
+\r
+       _gc_chain = tchain;\r
+\r
+       SQArray *ret = NULL;\r
+       if(resurrected) {\r
+               ret = SQArray::Create(this,0);\r
+               SQCollectable *rlast = NULL;\r
+               while(t) {\r
+                       rlast = t;\r
+                       SQObjectType type = t->GetType();\r
+                       if(type != OT_FUNCPROTO && type != OT_OUTER) {\r
+                               SQObject sqo;\r
+                               sqo._type = type;\r
+                               sqo._unVal.pRefCounted = t;\r
+                               ret->Append(sqo);\r
+                       }\r
+                       t = t->_next;\r
+                       n++;\r
+               }\r
+\r
+               assert(rlast->_next == NULL);\r
+               rlast->_next = _gc_chain;\r
+               if(_gc_chain)\r
+               {\r
+                       _gc_chain->_prev = rlast;\r
+               }\r
+               _gc_chain = resurrected;\r
+       }\r
+\r
+       t = _gc_chain;\r
+       while(t) {\r
+               t->UnMark();\r
+               t = t->_next;\r
+       }\r
+\r
+       if(ret) {\r
+               SQObjectPtr temp = ret;\r
+               vm->Push(temp);\r
+       }\r
+       else {\r
+               vm->PushNull();\r
+       }\r
+       return n;\r
+}\r
+\r
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)\r
+{\r
+       SQInteger n = 0;\r
+       SQCollectable *tchain = NULL;\r
+\r
+       RunMark(vm,&tchain);\r
+\r
        SQCollectable *t = _gc_chain;\r
        SQCollectable *nx = NULL;\r
        if(t) {\r
@@ -288,8 +354,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm)
                t = t->_next;\r
        }\r
        _gc_chain = tchain;\r
-       SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
-       assert(z == x);\r
+       \r
        return n;\r
 }\r
 #endif\r
@@ -341,7 +406,7 @@ void RefTable::Finalize()
 {\r
        RefNode *nodes = _nodes;\r
        for(SQUnsignedInteger n = 0; n < _numofslots; n++) {\r
-               nodes->obj = _null_;\r
+               nodes->obj.Null();\r
                nodes++;\r
        }\r
 }\r
@@ -372,6 +437,15 @@ void RefTable::AddRef(SQObject &obj)
        ref->refs++;\r
 }\r
 \r
+SQUnsignedInteger RefTable::GetRefCount(SQObject &obj)\r
+{\r
+     SQHash mainpos;\r
+     RefNode *prev;\r
+     RefNode *ref = Get(obj,mainpos,&prev,true);\r
+     return ref->refs;\r
+}\r
+\r
+\r
 SQBool RefTable::Release(SQObject &obj)\r
 {\r
        SQHash mainpos;\r
@@ -389,7 +463,7 @@ SQBool RefTable::Release(SQObject &obj)
                        ref->next = _freelist;\r
                        _freelist = ref;\r
                        _slotused--;\r
-                       ref->obj = _null_;\r
+                       ref->obj.Null();\r
                        //<<FIXME>>test for shrink?\r
                        return SQTrue;\r
                }\r
@@ -414,7 +488,7 @@ void RefTable::Resize(SQUnsignedInteger size)
                        assert(t->refs != 0);\r
                        RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);\r
                        nn->refs = t->refs; \r
-                       t->obj = _null_;\r
+                       t->obj.Null();\r
                        nfound++;\r
                }\r
                t++;\r
@@ -491,8 +565,9 @@ void RefTable::AllocNodes(SQUnsignedInteger size)
 * http://www.lua.org/source/4.0.1/src_lstring.c.html\r
 */\r
 \r
-SQStringTable::SQStringTable()\r
+SQStringTable::SQStringTable(SQSharedState *ss)\r
 {\r
+       _sharedstate = ss;\r
        AllocNodes(4);\r
        _slotused = 0;\r
 }\r
@@ -514,19 +589,21 @@ SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
 {\r
        if(len<0)\r
                len = (SQInteger)scstrlen(news);\r
-       SQHash h = ::_hashstr(news,len)&(_numofslots-1);\r
+       SQHash newhash = ::_hashstr(news,len);\r
+       SQHash h = newhash&(_numofslots-1);\r
        SQString *s;\r
        for (s = _strings[h]; s; s = s->_next){\r
                if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))\r
                        return s; //found\r
        }\r
 \r
-       SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));\r
+       SQString *t = (SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));\r
        new (t) SQString;\r
+       t->_sharedstate = _sharedstate;\r
        memcpy(t->_val,news,rsl(len));\r
        t->_val[len] = _SC('\0');\r
        t->_len = len;\r
-       t->_hash = ::_hashstr(news,len);\r
+       t->_hash = newhash;\r
        t->_next = _strings[h];\r
        _strings[h] = t;\r
        _slotused++;\r
old mode 100755 (executable)
new mode 100644 (file)
index e06da7a..ed9d6fc
@@ -11,7 +11,7 @@ struct SQTable;
 \r
 struct SQStringTable\r
 {\r
-       SQStringTable();\r
+       SQStringTable(SQSharedState*ss);\r
        ~SQStringTable();\r
        SQString *Add(const SQChar *,SQInteger len);\r
        void Remove(SQString *);\r
@@ -21,6 +21,7 @@ private:
        SQString **_strings;\r
        SQUnsignedInteger _numofslots;\r
        SQUnsignedInteger _slotused;\r
+       SQSharedState *_sharedstate;\r
 };\r
 \r
 struct RefTable {\r
@@ -33,6 +34,7 @@ struct RefTable {
        ~RefTable();\r
        void AddRef(SQObject &obj);\r
        SQBool Release(SQObject &obj);\r
+       SQUnsignedInteger GetRefCount(SQObject &obj);\r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
 #endif\r
@@ -63,7 +65,9 @@ public:
        SQChar* GetScratchPad(SQInteger size);\r
        SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);\r
 #ifndef NO_GARBAGE_COLLECTOR\r
-       SQInteger CollectGarbage(SQVM *vm); \r
+       SQInteger CollectGarbage(SQVM *vm);\r
+       void RunMark(SQVM *vm,SQCollectable **tchain);\r
+       SQInteger ResurrectUnreachable(SQVM *vm);\r
        static void MarkObject(SQObjectPtr &o,SQCollectable **chain);\r
 #endif\r
        SQObjectPtrVec *_metamethods;\r
@@ -102,6 +106,7 @@ public:
        \r
        SQCOMPILERERROR _compilererrorhandler;\r
        SQPRINTFUNCTION _printfunc;\r
+       SQPRINTFUNCTION _errorfunc;\r
        bool _debuginfo;\r
        bool _notifyallexceptions;\r
 private:\r
@@ -129,15 +134,9 @@ private:
 #define rsl(l) (l)\r
 #endif\r
 \r
-extern SQObjectPtr _null_;\r
-extern SQObjectPtr _true_;\r
-extern SQObjectPtr _false_;\r
-extern SQObjectPtr _one_;\r
-extern SQObjectPtr _minusone_;\r
+//extern SQObjectPtr _null_;\r
 \r
 bool CompileTypemask(SQIntVec &res,const SQChar *typemask);\r
 \r
-void *sq_vm_malloc(SQUnsignedInteger size);\r
-void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);\r
-void sq_vm_free(void *p,SQUnsignedInteger size);\r
+\r
 #endif //_SQSTATE_H_\r
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 87f8cbf..60382fd
@@ -23,7 +23,8 @@ void SQTable::Remove(const SQObjectPtr &key)
        \r
        _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
        if (n) {\r
-               n->val = n->key = _null_;\r
+               n->val.Null();\r
+               n->key.Null();\r
                _usednodes--;\r
                Rehash(false);\r
        }\r
@@ -33,8 +34,9 @@ void SQTable::AllocNodes(SQInteger nSize)
 {\r
        _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);\r
        for(SQInteger i=0;i<nSize;i++){\r
-               new (&nodes[i]) _HashNode;\r
-               nodes[i].next=NULL;\r
+               _HashNode &n = nodes[i];\r
+               new (&n) _HashNode;\r
+               n.next=NULL;\r
        }\r
        _numofnodes=nSize;\r
        _nodes=nodes;\r
@@ -71,11 +73,34 @@ void SQTable::Rehash(bool force)
 SQTable *SQTable::Clone()\r
 {\r
        SQTable *nt=Create(_opt_ss(this),_numofnodes);\r
+#ifdef _FAST_CLONE\r
+       _HashNode *basesrc = _nodes;\r
+       _HashNode *basedst = nt->_nodes;\r
+       _HashNode *src = _nodes;\r
+       _HashNode *dst = nt->_nodes;\r
+       SQInteger n = 0;\r
+       for(n = 0; n < _numofnodes; n++) {\r
+               dst->key = src->key;\r
+               dst->val = src->val;\r
+               if(src->next) {\r
+                       assert(src->next > basesrc);\r
+                       dst->next = basedst + (src->next - basesrc);\r
+                       assert(dst != dst->next);\r
+               }\r
+               dst++;\r
+               src++;\r
+       }\r
+       assert(_firstfree > basesrc);\r
+       assert(_firstfree != NULL);\r
+       nt->_firstfree = basedst + (_firstfree - basesrc);\r
+       nt->_usednodes = _usednodes;\r
+#else\r
        SQInteger ridx=0;\r
        SQObjectPtr key,val;\r
        while((ridx=Next(true,ridx,key,val))!=-1){\r
                nt->NewSlot(key,val);\r
        }\r
+#endif\r
        nt->SetDelegate(_delegate);\r
        return nt;\r
 }\r
@@ -122,8 +147,8 @@ bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
                        n->key = mp->key;\r
                        n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */\r
                        n->next = mp->next;\r
-                       mp->key = _null_;\r
-                       mp->val = _null_;\r
+                       mp->key.Null();\r
+                       mp->val.Null();\r
                        mp->next = NULL;  /* now `mp' is free */\r
                }\r
                else{\r
@@ -179,7 +204,7 @@ bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
 \r
 void SQTable::_ClearNodes()\r
 {\r
-       for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }\r
+       for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); }\r
 }\r
 \r
 void SQTable::Finalize()\r
old mode 100755 (executable)
new mode 100644 (file)
index 5b9ee72..2f64870
@@ -61,6 +61,7 @@ public:
        }\r
 #ifndef NO_GARBAGE_COLLECTOR \r
        void Mark(SQCollectable **chain);\r
+       SQObjectType GetType() {return OT_TABLE;}\r
 #endif\r
        inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)\r
        {\r
old mode 100755 (executable)
new mode 100644 (file)
index 8fe0411..dea27ae
@@ -12,7 +12,7 @@ struct SQUserData : SQDelegable
        }\r
        static SQUserData* Create(SQSharedState *ss, SQInteger size)\r
        {\r
-               SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1));\r
+               SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size);\r
                new (ud) SQUserData(ss);\r
                ud->_size = size;\r
                ud->_typetag = 0;\r
@@ -21,18 +21,20 @@ struct SQUserData : SQDelegable
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
        void Finalize(){SetDelegate(NULL);}\r
+       SQObjectType GetType(){ return OT_USERDATA;}\r
 #endif\r
        void Release() {\r
-               if (_hook) _hook(_val,_size);\r
-               SQInteger tsize = _size - 1;\r
+               if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size);\r
+               SQInteger tsize = _size;\r
                this->~SQUserData();\r
-               SQ_FREE(this, sizeof(SQUserData) + tsize);\r
+               SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize);\r
        }\r
+       \r
                \r
        SQInteger _size;\r
        SQRELEASEHOOK _hook;\r
        SQUserPointer _typetag;\r
-       SQChar _val[1];\r
+       //SQChar _val[1];\r
 };\r
 \r
 #endif //_SQUSERDATA_H_\r
old mode 100755 (executable)
new mode 100644 (file)
index 6deef43..84a1176
@@ -2,7 +2,6 @@
 #ifndef _SQUTILS_H_\r
 #define _SQUTILS_H_\r
 \r
-/* clang fix: "error: call to function 'sq_vm_free' that is neither visible in the template definition nor found by argument-dependent lookup" */\r
 void *sq_vm_malloc(SQUnsignedInteger size);\r
 void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);\r
 void sq_vm_free(void *p,SQUnsignedInteger size);\r
@@ -13,6 +12,8 @@ void sq_vm_free(void *p,SQUnsignedInteger size);
 #define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));\r
 #define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));\r
 \r
+#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))\r
+\r
 //sqvector mini vector class, supports objects by value\r
 template<typename T> class sqvector\r
 {\r
@@ -29,7 +30,13 @@ public:
        }\r
        void copy(const sqvector<T>& v)\r
        {\r
-               resize(v._size);\r
+               if(_size) {\r
+                       resize(0); //destroys all previous stuff\r
+               }\r
+               //resize(v._size);\r
+               if(v._size > _allocated) {\r
+                       _realloc(v._size);\r
+               }\r
                for(SQUnsignedInteger i = 0; i < v._size; i++) {\r
                        new ((void *)&_vals[i]) T(v._vals[i]);\r
                }\r
old mode 100755 (executable)
new mode 100644 (file)
index e240b5c..77e5eef
@@ -5,8 +5,8 @@
 #include <math.h>\r
 #include <stdlib.h>\r
 #include "sqopcodes.h"\r
-#include "sqfuncproto.h"\r
 #include "sqvm.h"\r
+#include "sqfuncproto.h"\r
 #include "sqclosure.h"\r
 #include "sqstring.h"\r
 #include "sqtable.h"\r
 \r
 #define TOP() (_stack._vals[_top-1])\r
 \r
-#define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); }\r
-void SQVM::ClearStack(SQInteger last_top)\r
-{\r
-       SQObjectType tOldType;\r
-       SQObjectValue unOldVal;\r
-       while (last_top >= _top) {\r
-               SQObjectPtr &o = _stack._vals[last_top--];\r
-               tOldType = o._type;\r
-               unOldVal = o._unVal;\r
-               o._type = OT_NULL;\r
-               o._unVal.pUserPointer = NULL;\r
-               __Release(tOldType,unOldVal);\r
-       }\r
-}\r
-\r
 bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)\r
 {\r
        SQInteger res;\r
-       SQInteger i1 = _integer(o1), i2 = _integer(o2);\r
-       if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER))\r
+       if((type(o1)|type(o2)) == OT_INTEGER)\r
        {\r
+               SQInteger i1 = _integer(o1), i2 = _integer(o2);\r
                switch(op) {\r
                        case BW_AND:    res = i1 & i2; break;\r
                        case BW_OR:             res = i1 | i2; break;\r
@@ -52,80 +37,111 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,con
        return true;\r
 }\r
 \r
+#define _ARITH_(op,trg,o1,o2) \\r
+{ \\r
+       SQInteger tmask = type(o1)|type(o2); \\r
+       switch(tmask) { \\r
+               case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \\r
+               case (OT_FLOAT|OT_INTEGER): \\r
+               case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\\r
+               default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\\r
+       } \\r
+}\r
+\r
+#define _ARITH_NOZERO(op,trg,o1,o2,err) \\r
+{ \\r
+       SQInteger tmask = type(o1)|type(o2); \\r
+       switch(tmask) { \\r
+               case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\\r
+               case (OT_FLOAT|OT_INTEGER): \\r
+               case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\\r
+               default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\\r
+       } \\r
+}\r
+\r
 bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)\r
 {\r
-       if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
-                       if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) {\r
-                               SQInteger res, i1 = _integer(o1), i2 = _integer(o2);\r
-                               switch(op) {\r
-                               case '+': res = i1 + i2; break;\r
-                               case '-': res = i1 - i2; break;\r
-                               case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }\r
+       SQInteger tmask = type(o1)|type(o2);\r
+       switch(tmask) {\r
+               case OT_INTEGER:{\r
+                       SQInteger res, i1 = _integer(o1), i2 = _integer(o2);\r
+                       switch(op) {\r
+                       case '+': res = i1 + i2; break;\r
+                       case '-': res = i1 - i2; break;\r
+                       case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }\r
                                        res = i1 / i2; \r
                                        break;\r
-                               case '*': res = i1 * i2; break;\r
-                               case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }\r
+                       case '*': res = i1 * i2; break;\r
+                       case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }\r
                                        res = i1 % i2; \r
                                        break;\r
-                               default: res = 0xDEADBEEF;\r
-                               }\r
-                               trg = res;\r
-                       }else{\r
-                               SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);\r
-                               switch(op) {\r
-                               case '+': res = f1 + f2; break;\r
-                               case '-': res = f1 - f2; break;\r
-                               case '/': res = f1 / f2; break;\r
-                               case '*': res = f1 * f2; break;\r
-                               case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;\r
-                               default: res = 0x0f;\r
-                               }\r
-                               trg = res;\r
-                       }       \r
-               } else {\r
-                       if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){\r
-                                       if(!StringCat(o1, o2, trg)) return false;\r
+                       default: res = 0xDEADBEEF;\r
+                       }\r
+                       trg = res; }\r
+                       break;\r
+               case (OT_FLOAT|OT_INTEGER):\r
+               case (OT_FLOAT):{\r
+                       SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);\r
+                       switch(op) {\r
+                       case '+': res = f1 + f2; break;\r
+                       case '-': res = f1 - f2; break;\r
+                       case '/': res = f1 / f2; break;\r
+                       case '*': res = f1 * f2; break;\r
+                       case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;\r
+                       default: res = 0x0f;\r
+                       }\r
+                       trg = res; }\r
+                       break;\r
+               default:\r
+                       if(op == '+' && (tmask & _RT_STRING)){\r
+                               if(!StringCat(o1, o2, trg)) return false;\r
                        }\r
                        else if(!ArithMetaMethod(op,o1,o2,trg)) { \r
-                               Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; \r
+                               return false; \r
                        }\r
-               }\r
-               return true;\r
+       }\r
+       return true;\r
 }\r
 \r
 SQVM::SQVM(SQSharedState *ss)\r
 {\r
        _sharedstate=ss;\r
        _suspended = SQFalse;\r
-       _suspended_target=-1;\r
+       _suspended_target = -1;\r
        _suspended_root = SQFalse;\r
-       _suspended_traps=-1;\r
-       _foreignptr=NULL;\r
-       _nnativecalls=0;\r
-       _lasterror = _null_;\r
-       _errorhandler = _null_;\r
-       _debughook = _null_;\r
+       _suspended_traps = -1;\r
+       _foreignptr = NULL;\r
+       _nnativecalls = 0;\r
+       _nmetamethodscall = 0;\r
+       _lasterror.Null();\r
+       _errorhandler.Null();\r
+       _debughook = false;\r
+       _debughook_native = NULL;\r
+       _debughook_closure.Null();\r
+       _openouters = NULL;\r
        ci = NULL;\r
        INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
 }\r
 \r
 void SQVM::Finalize()\r
 {\r
-       _roottable = _null_;\r
-       _lasterror = _null_;\r
-       _errorhandler = _null_;\r
-       _debughook = _null_;\r
-       temp_reg = _null_;\r
+       if(_openouters) CloseOuters(&_stack._vals[0]);\r
+       _roottable.Null();\r
+       _lasterror.Null();\r
+       _errorhandler.Null();\r
+       _debughook = false;\r
+       _debughook_native = NULL;\r
+       _debughook_closure.Null();\r
+       temp_reg.Null();\r
        _callstackdata.resize(0);\r
        SQInteger size=_stack.size();\r
        for(SQInteger i=0;i<size;i++)\r
-               _stack[i]=_null_;\r
+               _stack[i].Null();\r
 }\r
 \r
 SQVM::~SQVM()\r
 {\r
        Finalize();\r
-       //sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));\r
        REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
 }\r
 \r
@@ -141,9 +157,14 @@ bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr
                default: mm = MT_ADD; assert(0); break; //shutup compiler\r
        }\r
        if(is_delegable(o1) && _delegable(o1)->_delegate) {\r
-               Push(o1);Push(o2);\r
-               return CallMetaMethod(_delegable(o1),mm,2,dest);\r
+               \r
+               SQObjectPtr closure;\r
+               if(_delegable(o1)->GetMetaMethod(this, mm, closure)) {\r
+                       Push(o1);Push(o2);\r
+                       return CallMetaMethod(closure,mm,2,dest);\r
+               }\r
        }\r
+       Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); \r
        return false;\r
 }\r
 \r
@@ -161,10 +182,13 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
        case OT_USERDATA:\r
        case OT_INSTANCE:\r
                if(_delegable(o)->_delegate) {\r
-                       Push(o);\r
-                       if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) {\r
-                               trg = temp_reg;\r
+                       SQObjectPtr closure;\r
+                       if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) {\r
+                               Push(o);\r
+                               if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false;\r
+                               _Swap(trg,temp_reg);\r
                                return true;\r
+\r
                        }\r
                }\r
        default:break; //shutup compiler\r
@@ -176,34 +200,46 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
 #define _RET_SUCCEED(exp) { result = (exp); return true; } \r
 bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)\r
 {\r
-       if(type(o1)==type(o2)){\r
-               if(_rawval(o1)==_rawval(o2))_RET_SUCCEED(0);\r
+       SQObjectType t1 = type(o1), t2 = type(o2);\r
+       if(t1 == t2) {\r
+               if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0);\r
                SQObjectPtr res;\r
-               switch(type(o1)){\r
+               switch(t1){\r
                case OT_STRING:\r
                        _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));\r
                case OT_INTEGER:\r
-                       _RET_SUCCEED(_integer(o1)-_integer(o2));\r
+                       _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1);\r
                case OT_FLOAT:\r
                        _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);\r
                case OT_TABLE:\r
                case OT_USERDATA:\r
                case OT_INSTANCE:\r
                        if(_delegable(o1)->_delegate) {\r
-                               Push(o1);Push(o2);\r
-                               if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break;\r
+                               SQObjectPtr closure;\r
+                               if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) {\r
+                                       Push(o1);Push(o2);\r
+                                       if(CallMetaMethod(closure,MT_CMP,2,res)) {\r
+                                               if(type(res) != OT_INTEGER) {\r
+                                                       Raise_Error(_SC("_cmp must return an integer"));\r
+                                                       return false;\r
+                                               }\r
+                                               _RET_SUCCEED(_integer(res))\r
+                                       }\r
+                                       return false;\r
+                               }\r
                        }\r
                        //continues through (no break needed)\r
                default: \r
                        _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );\r
                }\r
-               if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }\r
-                       _RET_SUCCEED(_integer(res));\r
+               assert(0);\r
+               //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }\r
+               //      _RET_SUCCEED(_integer(res));\r
                \r
        }\r
        else{\r
                if(sq_isnumeric(o1) && sq_isnumeric(o2)){\r
-                       if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { \r
+                       if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { \r
                                if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }\r
                                else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }\r
                                _RET_SUCCEED(1);\r
@@ -214,8 +250,8 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
                                _RET_SUCCEED(1);\r
                        }\r
                }\r
-               else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);}\r
-               else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);}\r
+               else if(t1==OT_NULL) {_RET_SUCCEED(-1);}\r
+               else if(t2==OT_NULL) {_RET_SUCCEED(1);}\r
                else { Raise_CompareError(o1,o2); return false; }\r
                \r
        }\r
@@ -228,28 +264,28 @@ bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObject
        SQInteger r;\r
        if(ObjCmp(o1,o2,r)) {\r
                switch(op) {\r
-                       case CMP_G: res = (r > 0)?_true_:_false_; return true;\r
-                       case CMP_GE: res = (r >= 0)?_true_:_false_; return true;\r
-                       case CMP_L: res = (r < 0)?_true_:_false_; return true;\r
-                       case CMP_LE: res = (r <= 0)?_true_:_false_; return true;\r
-                       \r
+                       case CMP_G: res = (r > 0); return true;\r
+                       case CMP_GE: res = (r >= 0); return true;\r
+                       case CMP_L: res = (r < 0); return true;\r
+                       case CMP_LE: res = (r <= 0); return true;\r
+                       case CMP_3W: res = r; return true;\r
                }\r
                assert(0);\r
        }\r
        return false;\r
 }\r
 \r
-void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)\r
+bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)\r
 {\r
        switch(type(o)) {\r
        case OT_STRING:\r
                res = o;\r
-               return;\r
+               return true;\r
        case OT_FLOAT:\r
                scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o));\r
                break;\r
        case OT_INTEGER:\r
-               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));\r
+               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_PRINT_INT_FMT,_integer(o));\r
                break;\r
        case OT_BOOL:\r
                scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false"));\r
@@ -258,25 +294,31 @@ void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
        case OT_USERDATA:\r
        case OT_INSTANCE:\r
                if(_delegable(o)->_delegate) {\r
-                       Push(o);\r
-                       if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) {\r
-                               if(type(res) == OT_STRING)\r
-                                       return;\r
-                               //else keeps going to the default\r
+                       SQObjectPtr closure;\r
+                       if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) {\r
+                               Push(o);\r
+                               if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {;\r
+                                       if(type(res) == OT_STRING)\r
+                                               return true;\r
+                               } \r
+                               else {\r
+                                       return false;\r
+                               }\r
                        }\r
                }\r
        default:\r
                scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));\r
        }\r
        res = SQString::Create(_ss(this),_spval);\r
+       return true;\r
 }\r
 \r
 \r
 bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)\r
 {\r
        SQObjectPtr a, b;\r
-       ToString(str, a);\r
-       ToString(obj, b);\r
+       if(!ToString(str, a)) return false;\r
+       if(!ToString(obj, b)) return false;\r
        SQInteger l = _string(a)->_len , ol = _string(b)->_len;\r
        SQChar *s = _sp(rsl(l + ol + 1));\r
        memcpy(s, _stringval(a), rsl(l)); \r
@@ -285,14 +327,17 @@ bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &
        return true;\r
 }\r
 \r
-void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)\r
+bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)\r
 {\r
        if(is_delegable(obj1) && _delegable(obj1)->_delegate) {\r
-               Push(obj1);\r
-               if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest))\r
-                       return;\r
+               SQObjectPtr closure;\r
+               if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) {\r
+                       Push(obj1);\r
+                       return CallMetaMethod(closure,MT_TYPEOF,1,dest);\r
+               }\r
        }\r
        dest = SQString::Create(_ss(this),GetTypeName(obj1));\r
+       return true;\r
 }\r
 \r
 bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)\r
@@ -310,22 +355,44 @@ bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
                _roottable = friendvm->_roottable;\r
                _errorhandler = friendvm->_errorhandler;\r
                _debughook = friendvm->_debughook;\r
+               _debughook_native = friendvm->_debughook_native;\r
+               _debughook_closure = friendvm->_debughook_closure;\r
        }\r
        \r
        sq_base_register(this);\r
        return true;\r
 }\r
 \r
-extern SQInstructionDesc g_InstrDesc[];\r
 \r
 bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)\r
 {\r
-       SQFunctionProto *func = _funcproto(closure->_function);\r
-       \r
-       const SQInteger paramssize = func->_nparameters;\r
+       SQFunctionProto *func = closure->_function;\r
+\r
+       SQInteger paramssize = func->_nparameters;\r
        const SQInteger newtop = stackbase + func->_stacksize;\r
        SQInteger nargs = args;\r
-       if (paramssize != nargs) {\r
+       if(func->_varparams)\r
+       {\r
+               paramssize--;\r
+               if (nargs < paramssize) {\r
+                       Raise_Error(_SC("wrong number of parameters"));\r
+                       return false;\r
+               }\r
+\r
+               //dumpstack(stackbase);\r
+               SQInteger nvargs = nargs - paramssize;\r
+               SQArray *arr = SQArray::Create(_ss(this),nvargs);\r
+               SQInteger pbase = stackbase+paramssize;\r
+               for(SQInteger n = 0; n < nvargs; n++) {\r
+                       arr->_values[n] = _stack._vals[pbase];\r
+                       _stack._vals[pbase].Null();\r
+                       pbase++;\r
+\r
+               }\r
+               _stack._vals[stackbase+paramssize] = arr;\r
+               //dumpstack(stackbase);\r
+       }\r
+       else if (paramssize != nargs) {\r
                SQInteger ndef = func->_ndefaultparams;\r
                SQInteger diff;\r
                if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {\r
@@ -333,99 +400,75 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege
                                _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];\r
                        }\r
                }\r
-               else if(func->_varparams)\r
-               {\r
-                       if (nargs < paramssize) {\r
-                               Raise_Error(_SC("wrong number of parameters"));\r
-                               return false;\r
-                       }\r
-                       for(SQInteger n = 0; n < nargs - paramssize; n++) {\r
-                               _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]);\r
-                               _stack._vals[stackbase+paramssize+n] = _null_;\r
-                       }\r
-               }\r
                else {\r
                        Raise_Error(_SC("wrong number of parameters"));\r
                        return false;\r
                }\r
        }\r
 \r
-       if(type(closure->_env) == OT_WEAKREF) {\r
-               _stack._vals[stackbase] = _weakref(closure->_env)->_obj;\r
+       if(closure->_env) {\r
+               _stack._vals[stackbase] = closure->_env->_obj;\r
        }\r
 \r
-       if (!tailcall) {\r
-               CallInfo lc;\r
-               lc._generator = NULL;\r
-               lc._etraps = 0;\r
-               lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );\r
-               lc._target = (SQInt32) target;\r
-               lc._prevtop = (SQInt32) (_top - _stackbase);\r
-               lc._ncalls = 1;\r
-               lc._root = SQFalse;\r
-               PUSH_CALLINFO(this, lc);\r
-       }\r
-       else {\r
-               ci->_ncalls++;\r
-       }\r
-       ci->_vargs.size = (SQInt32)(nargs - paramssize);\r
-       ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size));\r
-       ci->_closure = closure;\r
+       if(!EnterFrame(stackbase, newtop, tailcall)) return false;\r
+\r
+       ci->_closure  = closure;\r
        ci->_literals = func->_literals;\r
-       ci->_ip = func->_instructions;\r
-       //grows the stack if needed\r
-       if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) {\r
-               _stack.resize(_stack.size() + (func->_stacksize<<1));\r
-       }\r
-               \r
-       _top = newtop;\r
-       _stackbase = stackbase;\r
-       if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
+       ci->_ip       = func->_instructions;\r
+       ci->_target   = (SQInt32)target;\r
+\r
+       if (_debughook) {\r
                CallDebugHook(_SC('c'));\r
+       }\r
+\r
+       if (closure->_function->_bgenerator) {\r
+               SQFunctionProto *f = closure->_function;\r
+               SQGenerator *gen = SQGenerator::Create(_ss(this), closure);\r
+               if(!gen->Yield(this,f->_stacksize))\r
+                       return false;\r
+               SQObjectPtr temp;\r
+               Return(1, target, temp);\r
+               STK(target) = gen;\r
+       }\r
+\r
+\r
        return true;\r
 }\r
 \r
 bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)\r
 {\r
-       if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
-               for(SQInteger i=0;i<ci->_ncalls;i++)\r
+       SQBool    _isroot      = ci->_root;\r
+       SQInteger callerbase   = _stackbase - ci->_prevstkbase;\r
+\r
+       if (_debughook) {\r
+               for(SQInteger i=0; i<ci->_ncalls; i++) {\r
                        CallDebugHook(_SC('r'));\r
-                       \r
-       SQBool broot = ci->_root;\r
-       SQInteger last_top = _top;\r
-       SQInteger target = ci->_target;\r
-       SQInteger oldstackbase = _stackbase;\r
-       _stackbase -= ci->_prevstkbase;\r
-       _top = _stackbase + ci->_prevtop;\r
-       if(ci->_vargs.size) PopVarArgs(ci->_vargs);\r
-       POP_CALLINFO(this);\r
-       if (broot) {\r
-               if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1];\r
-               else retval = _null_;\r
-       }\r
-       else {\r
-               if(target != -1) { //-1 is when a class contructor ret value has to be ignored\r
-                       if (_arg0 != MAX_FUNC_STACKSIZE)\r
-                               STK(target) = _stack._vals[oldstackbase+_arg1];\r
-                       else\r
-                               STK(target) = _null_;\r
                }\r
        }\r
 \r
-       CLEARSTACK(last_top);\r
-       assert(oldstackbase >= _stackbase); \r
-       return broot?true:false;\r
+       SQObjectPtr *dest;\r
+       if (_isroot) {\r
+               dest = &(retval);\r
+       } else if (ci->_target == -1) {\r
+               dest = NULL;\r
+       } else {\r
+               dest = &_stack._vals[callerbase + ci->_target];\r
+       }\r
+       if (dest) {\r
+               if(_arg0 != 0xFF) {\r
+                       *dest = _stack._vals[_stackbase+_arg1];\r
+               }\r
+               else {\r
+                       dest->Null();\r
+               }\r
+               //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_;\r
+       }\r
+       LeaveFrame();\r
+       return _isroot ? true : false;\r
 }\r
 \r
 #define _RET_ON_FAIL(exp) { if(!exp) return false; }\r
 \r
-bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)\r
-{\r
-       _RET_ON_FAIL(ARITH_OP( op , target, a, incr));\r
-       a = target;\r
-       return true;\r
-}\r
-\r
 bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)\r
 {\r
        SQObjectPtr trg;\r
@@ -435,17 +478,18 @@ bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObject
        return true;\r
 }\r
 \r
-bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix)\r
+bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx)\r
 {\r
        SQObjectPtr tmp, tself = self, tkey = key;\r
-       if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; }\r
+       if (!Get(tself, tkey, tmp, false, selfidx)) { return false; }\r
        _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))\r
-       Set(tself, tkey, target,true);\r
+       if (!Set(tself, tkey, target,selfidx)) { return false; }\r
        if (postfix) target = tmp;\r
        return true;\r
 }\r
 \r
 #define arg0 (_i_._arg0)\r
+#define sarg0 ((SQInteger)*((signed char *)&_i_._arg0))\r
 #define arg1 (_i_._arg1)\r
 #define sarg1 (*((SQInt32 *)&_i_._arg1))\r
 #define arg2 (_i_._arg2)\r
@@ -461,11 +505,6 @@ SQRESULT SQVM::Suspend()
        return SQ_SUSPEND_FLAG;\r
 }\r
 \r
-void SQVM::PopVarArgs(VarArgs &vargs)\r
-{\r
-       for(SQInteger n = 0; n< vargs.size; n++)\r
-               _vargsstack.pop_back();\r
-}\r
 \r
 #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }\r
 bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr \r
@@ -489,16 +528,22 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
        case OT_INSTANCE:\r
                if(_delegable(o1)->_delegate) {\r
                        SQObjectPtr itr;\r
-                       Push(o1);\r
-                       Push(o4);\r
-                       if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){\r
-                               o4 = o2 = itr;\r
-                               if(type(itr) == OT_NULL) _FINISH(exitpos);\r
-                               if(!Get(o1, itr, o3, false,false)) {\r
-                                       Raise_Error(_SC("_nexti returned an invalid idx"));\r
+                       SQObjectPtr closure;\r
+                       if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) {\r
+                               Push(o1);\r
+                               Push(o4);\r
+                               if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) {\r
+                                       o4 = o2 = itr;\r
+                                       if(type(itr) == OT_NULL) _FINISH(exitpos);\r
+                                       if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) {\r
+                                               Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed\r
+                                               return false;\r
+                                       }\r
+                                       _FINISH(1);\r
+                               }\r
+                               else {\r
                                        return false;\r
                                }\r
-                               _FINISH(1);\r
                        }\r
                        Raise_Error(_SC("_nexti failed"));\r
                        return false;\r
@@ -513,7 +558,7 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
                        }\r
                        o2 = idx;\r
                        o4 = idx;\r
-                       _generator(o1)->Resume(this, arg_2+1);\r
+                       _generator(o1)->Resume(this, o3);\r
                        _FINISH(0);\r
                }\r
        default: \r
@@ -522,62 +567,34 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
        return false; //cannot be hit(just to avoid warnings)\r
 }\r
 \r
-bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)\r
-{\r
-       if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; }\r
-       switch(type(o2)) {\r
-       case OT_TABLE:\r
-               if(!_table(o1)->SetDelegate(_table(o2))){\r
-                       Raise_Error(_SC("delegate cycle detected"));\r
-                       return false;\r
-               }\r
-               break;\r
-       case OT_NULL:\r
-               _table(o1)->SetDelegate(NULL);\r
-               break;\r
-       default:\r
-               Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2));\r
-               return false;\r
-               break;\r
-       }\r
-       trg = o1;\r
-       return true;\r
-}\r
 #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))\r
 \r
-#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} }\r
-\r
 #define SQ_THROW() { goto exception_trap; }\r
 \r
+#define _GUARD(exp) { if(!exp) { SQ_THROW();} }\r
+\r
 bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)\r
 {\r
        SQInteger nouters;\r
        SQClosure *closure = SQClosure::Create(_ss(this), func);\r
        if((nouters = func->_noutervalues)) {\r
-               closure->_outervalues.reserve(nouters);\r
                for(SQInteger i = 0; i<nouters; i++) {\r
                        SQOuterVar &v = func->_outervalues[i];\r
                        switch(v._type){\r
-                       case otSYMBOL:\r
-                               closure->_outervalues.push_back(_null_);\r
-                               if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true))\r
-                               {Raise_IdxError(v._src); return false; }\r
-                               break;\r
                        case otLOCAL:\r
-                               closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]);\r
+                               FindOuter(closure->_outervalues[i], &STK(_integer(v._src)));\r
                                break;\r
                        case otOUTER:\r
-                               closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]);\r
+                               closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)];\r
                                break;\r
                        }\r
                }\r
        }\r
        SQInteger ndefparams;\r
        if((ndefparams = func->_ndefaultparams)) {\r
-               closure->_defaultparams.reserve(ndefparams);\r
                for(SQInteger i = 0; i < ndefparams; i++) {\r
                        SQInteger spos = func->_defaultparams[i];\r
-                       closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]);\r
+                       closure->_defaultparams[i] = _stack._vals[_stackbase + spos];\r
                }\r
        }\r
        target = closure;\r
@@ -585,21 +602,6 @@ bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
 \r
 }\r
 \r
-bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci)\r
-{\r
-       if(ci->_vargs.size == 0) {\r
-               Raise_Error(_SC("the function doesn't have var args"));\r
-               return false;\r
-       }\r
-       if(!sq_isnumeric(index)){\r
-               Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index));\r
-               return false;\r
-       }\r
-       SQInteger idx = tointeger(index);\r
-       if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; }\r
-       target = _vargsstack[ci->_vargs.base+idx];\r
-       return true;\r
-}\r
 \r
 bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes)\r
 {\r
@@ -624,18 +626,14 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes
        return true;\r
 }\r
 \r
-\r
-\r
-bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)\r
+bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res)\r
 {\r
        if(type(o1) == type(o2)) {\r
-               res = ((_rawval(o1) == _rawval(o2)?true:false));\r
+               res = (_rawval(o1) == _rawval(o2));\r
        }\r
        else {\r
                if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
-                       SQInteger cmpres;\r
-                       if(!ObjCmp(o1, o2,cmpres)) return false;\r
-                       res = (cmpres == 0);\r
+                       res = (tofloat(o1) == tofloat(o2));\r
                }\r
                else {\r
                        res = false;\r
@@ -646,65 +644,47 @@ bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)
 \r
 bool SQVM::IsFalse(SQObjectPtr &o)\r
 {\r
-       if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )\r
-               || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL\r
+       if(((type(o) & SQOBJECT_CANBEFALSE) \r
+               && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) ))\r
+#if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64))\r
+               || (_integer(o) == 0) )  //OT_NULL|OT_INTEGER|OT_BOOL\r
+#else\r
+               || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) )  //OT_NULL|OT_INTEGER|OT_BOOL\r
+#endif\r
+       {\r
                return true;\r
        }\r
        return false;\r
 }\r
 \r
-bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target)\r
-{\r
-       switch(type(o)) {\r
-               case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_;\r
-                       break;\r
-               case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_;\r
-                       break;\r
-               default:\r
-                       Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o));\r
-                       return false;\r
-       }\r
-       return true;\r
-}\r
-\r
-bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)\r
+bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)\r
 {\r
        if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
        _nnativecalls++;\r
        AutoDec ad(&_nnativecalls);\r
        SQInteger traps = 0;\r
-       //temp_reg vars for OP_CALL\r
-       SQInteger ct_target;\r
-       SQInteger ct_stackbase;\r
-       bool ct_tailcall; \r
-\r
+       CallInfo *prevci = ci;\r
+               \r
        switch(et) {\r
                case ET_CALL: {\r
-                       SQInteger last_top = _top;\r
                        temp_reg = closure;\r
                        if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { \r
                                //call the handler if there are no calls in the stack, if not relies on the previous node\r
                                if(ci == NULL) CallErrorHandler(_lasterror);\r
                                return false;\r
                        }\r
-                       if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {\r
-                               SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function);\r
-                               SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));\r
-                               _GUARD(gen->Yield(this));\r
-                               Return(1, ci->_target, temp_reg);\r
-                               outres = gen;\r
-                               CLEARSTACK(last_top);\r
+                       if(ci == prevci) {\r
+                               outres = STK(_top-nargs);\r
                                return true;\r
                        }\r
                        ci->_root = SQTrue;\r
                                          }\r
                        break;\r
-               case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break;\r
+               case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break;\r
                case ET_RESUME_VM:\r
                case ET_RESUME_THROW_VM:\r
                        traps = _suspended_traps;\r
                        ci->_root = _suspended_root;\r
-                       ci->_vargs = _suspend_varargs;\r
                        _suspended = SQFalse;\r
                        if(et  == ET_RESUME_THROW_VM) { SQ_THROW(); }\r
                        break;\r
@@ -720,86 +700,88 @@ exception_restore:
                        //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);\r
                        switch(_i_.op)\r
                        {\r
-                       case _OP_LINE:\r
-                               if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
-                                       CallDebugHook(_SC('l'),arg1);\r
-                               continue;\r
+                       case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;\r
                        case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;\r
-                       case _OP_LOADINT: TARGET = (SQInteger)arg1; continue;\r
+                       case _OP_LOADINT: \r
+#ifndef _SQ64\r
+                               TARGET = (SQInteger)arg1; continue;\r
+#else\r
+                               TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue;\r
+#endif\r
                        case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;\r
                        case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;\r
-                       case _OP_TAILCALL:\r
-                               temp_reg = STK(arg1);\r
-                               if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){ \r
-                                       ct_tailcall = true;\r
-                                       if(ci->_vargs.size) PopVarArgs(ci->_vargs);\r
+                       case _OP_TAILCALL:{\r
+                               SQObjectPtr &t = STK(arg1);\r
+                               if (type(t) == OT_CLOSURE \r
+                                       && (!_closure(t)->_function->_bgenerator)){\r
+                                       SQObjectPtr clo = t;\r
+                                       if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));\r
                                        for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);\r
-                                       ct_target = ci->_target;\r
-                                       ct_stackbase = _stackbase;\r
-                                       goto common_call;\r
+                                       _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));\r
+                                       continue;\r
                                }\r
+                                                         }\r
                        case _OP_CALL: {\r
-                                       ct_tailcall = false;\r
-                                       ct_target = arg0;\r
-                                       temp_reg = STK(arg1);\r
-                                       ct_stackbase = _stackbase+arg2;\r
-\r
-common_call:\r
-                                       SQObjectPtr clo = temp_reg;\r
-                                       SQInteger last_top = _top;\r
+                                       SQObjectPtr clo = STK(arg1);\r
                                        switch (type(clo)) {\r
-                                       case OT_CLOSURE:{\r
-                                               _GUARD(StartCall(_closure(clo), ct_target, arg3, ct_stackbase, ct_tailcall));\r
-                                               if (_funcproto(_closure(clo)->_function)->_bgenerator) {\r
-                                                       SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(clo));\r
-                                                       _GUARD(gen->Yield(this));\r
-                                                       Return(1, ct_target, clo);\r
-                                                       STK(ct_target) = gen;\r
-                                                       CLEARSTACK(last_top);\r
-                                                       continue;\r
-                                               }\r
-                                               }\r
+                                       case OT_CLOSURE:\r
+                                               _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));\r
                                                continue;\r
                                        case OT_NATIVECLOSURE: {\r
                                                bool suspend;\r
-                                               _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend));\r
+                                               _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));\r
                                                if(suspend){\r
                                                        _suspended = SQTrue;\r
-                                                       _suspended_target = ct_target;\r
+                                                       _suspended_target = sarg0;\r
                                                        _suspended_root = ci->_root;\r
                                                        _suspended_traps = traps;\r
-                                                       _suspend_varargs = ci->_vargs;\r
                                                        outres = clo;\r
                                                        return true;\r
                                                }\r
-                                               if(ct_target != -1) { //skip return value for constructors\r
-                                                       STK(ct_target) = clo;\r
+                                               if(sarg0 != -1) {\r
+                                                       STK(arg0) = clo;\r
                                                }\r
                                                                                   }\r
                                                continue;\r
                                        case OT_CLASS:{\r
                                                SQObjectPtr inst;\r
-                                               _GUARD(CreateClassInstance(_class(clo),inst,temp_reg));\r
-                                               STK(ct_target) = inst;\r
-                                               ct_target = -1; //fakes return value target so that is not overwritten by the constructor\r
-                                               if(type(temp_reg) != OT_NULL) {\r
-                                                       _stack._vals[ct_stackbase] = inst;\r
-                                                       goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor)\r
+                                               _GUARD(CreateClassInstance(_class(clo),inst,clo));\r
+                                               if(sarg0 != -1) {\r
+                                                       STK(arg0) = inst;\r
+                                               }\r
+                                               SQInteger stkbase;\r
+                                               switch(type(clo)) {\r
+                                                       case OT_CLOSURE:\r
+                                                               stkbase = _stackbase+arg2;\r
+                                                               _stack._vals[stkbase] = inst;\r
+                                                               _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));\r
+                                                               break;\r
+                                                       case OT_NATIVECLOSURE:\r
+                                                               bool suspend;\r
+                                                               stkbase = _stackbase+arg2;\r
+                                                               _stack._vals[stkbase] = inst;\r
+                                                               _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));\r
+                                                               break;\r
+                                                       default: break; //shutup GCC 4.x\r
                                                }\r
                                                }\r
                                                break;\r
                                        case OT_TABLE:\r
                                        case OT_USERDATA:\r
-                                       case OT_INSTANCE:\r
-                                               {\r
-                                               Push(clo);\r
-                                               for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));\r
-                                               if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){\r
-                                                       STK(ct_target) = clo;\r
+                                       case OT_INSTANCE:{\r
+                                               SQObjectPtr closure;\r
+                                               if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {\r
+                                                       Push(clo);\r
+                                                       for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));\r
+                                                       if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW();\r
+                                                       if(sarg0 != -1) {\r
+                                                               STK(arg0) = clo;\r
+                                                       }\r
                                                        break;\r
                                                }\r
-                                               Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));\r
-                                               SQ_THROW();\r
+                                                                        \r
+                                               //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));\r
+                                               //SQ_THROW();\r
                                          }\r
                                        default:\r
                                                Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));\r
@@ -808,93 +790,158 @@ common_call:
                                }\r
                                  continue;\r
                        case _OP_PREPCALL:\r
-                       case _OP_PREPCALLK:\r
-                               {\r
+                       case _OP_PREPCALLK:     {\r
                                        SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);\r
                                        SQObjectPtr &o = STK(arg2);\r
-                                       if (!Get(o, key, temp_reg,false,true)) {\r
-                                               if(type(o) == OT_CLASS) { //hack?\r
-                                                       if(_class_ddel->Get(key,temp_reg)) {\r
-                                                               STK(arg3) = o;\r
-                                                               TARGET = temp_reg;\r
-                                                               continue;\r
-                                                       }\r
-                                               }\r
-                                               { Raise_IdxError(key); SQ_THROW();}\r
+                                       if (!Get(o, key, temp_reg,false,arg2)) {\r
+                                               SQ_THROW();\r
                                        }\r
-\r
-                                       STK(arg3) = type(o) == OT_CLASS?STK(0):o;\r
-                                       TARGET = temp_reg;\r
+                                       STK(arg3) = o;\r
+                                       _Swap(TARGET,temp_reg);//TARGET = temp_reg;\r
                                }\r
                                continue;\r
                        case _OP_GETK:\r
-                               if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,true)) { Raise_IdxError(ci->_literals[arg1]); SQ_THROW();}\r
-                               TARGET = temp_reg;\r
+                               if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();}\r
+                               _Swap(TARGET,temp_reg);//TARGET = temp_reg;\r
                                continue;\r
                        case _OP_MOVE: TARGET = STK(arg1); continue;\r
                        case _OP_NEWSLOT:\r
                                _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));\r
-                               if(arg0 != arg3) TARGET = STK(arg3);\r
+                               if(arg0 != 0xFF) TARGET = STK(arg3);\r
                                continue;\r
                        case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;\r
                        case _OP_SET:\r
-                               if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }\r
-                               if (arg0 != arg3) TARGET = STK(arg3);\r
+                               if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); }\r
+                               if (arg0 != 0xFF) TARGET = STK(arg3);\r
                                continue;\r
                        case _OP_GET:\r
-                               if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }\r
-                               TARGET = temp_reg;\r
+                               if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); }\r
+                               _Swap(TARGET,temp_reg);//TARGET = temp_reg;\r
                                continue;\r
                        case _OP_EQ:{\r
                                bool res;\r
                                if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }\r
-                               TARGET = res?_true_:_false_;\r
+                               TARGET = res?true:false;\r
                                }continue;\r
                        case _OP_NE:{ \r
                                bool res;\r
                                if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }\r
-                               TARGET = (!res)?_true_:_false_;\r
+                               TARGET = (!res)?true:false;\r
                                } continue;\r
-                       case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue;\r
+                       case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;\r
+                       case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;\r
+                       case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;\r
+                       case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;\r
+                       case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;\r
                        case _OP_BITW:  _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;\r
                        case _OP_RETURN:\r
-                               if(ci->_generator) {\r
-                                       ci->_generator->Kill();\r
+                               if((ci)->_generator) {\r
+                                       (ci)->_generator->Kill();\r
                                }\r
                                if(Return(arg0, arg1, temp_reg)){\r
                                        assert(traps==0);\r
-                                       outres = temp_reg;\r
+                                       //outres = temp_reg;\r
+                                       _Swap(outres,temp_reg);\r
                                        return true;\r
                                }\r
                                continue;\r
-                       case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n) = _null_; }continue;\r
-                       case _OP_LOADROOTTABLE: TARGET = _roottable; continue;\r
-                       case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue;\r
+                       case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;\r
+                       case _OP_LOADROOT:      TARGET = _roottable; continue;\r
+                       case _OP_LOADBOOL: TARGET = arg1?true:false; continue;\r
                        case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;\r
                        case _OP_JMP: ci->_ip += (sarg1); continue;\r
-                       case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
+                       //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
+                       case _OP_JCMP: \r
+                               _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));\r
+                               if(IsFalse(temp_reg)) ci->_ip+=(sarg1);\r
+                               continue;\r
                        case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
-                       case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue;\r
-                       case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue;\r
-                       case _OP_GETVARGV: \r
-                               if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } \r
+                       case _OP_GETOUTER: {\r
+                               SQClosure *cur_cls = _closure(ci->_closure);\r
+                               SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);\r
+                               TARGET = *(otr->_valptr);\r
+                               }\r
+                       continue;\r
+                       case _OP_SETOUTER: {\r
+                               SQClosure *cur_cls = _closure(ci->_closure);\r
+                               SQOuter   *otr = _outer(cur_cls->_outervalues[arg1]);\r
+                               *(otr->_valptr) = STK(arg2);\r
+                               if(arg0 != 0xFF) {\r
+                                       TARGET = STK(arg2);\r
+                               }\r
+                               }\r
+                       continue;\r
+                       case _OP_NEWOBJ: \r
+                               switch(arg3) {\r
+                                       case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;\r
+                                       case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;\r
+                                       case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;\r
+                                       default: assert(0); continue;\r
+                               }\r
+                       case _OP_APPENDARRAY: \r
+                               {\r
+                                       SQObject val;\r
+                                       val._unVal.raw = 0;\r
+                               switch(arg2) {\r
+                               case AAT_STACK:\r
+                                       val = STK(arg1); break;\r
+                               case AAT_LITERAL:\r
+                                       val = ci->_literals[arg1]; break;\r
+                               case AAT_INT:\r
+                                       val._type = OT_INTEGER;\r
+#ifndef _SQ64\r
+                                       val._unVal.nInteger = (SQInteger)arg1; \r
+#else\r
+                                       val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1);\r
+#endif\r
+                                       break;\r
+                               case AAT_FLOAT:\r
+                                       val._type = OT_FLOAT;\r
+                                       val._unVal.fFloat = *((SQFloat *)&arg1);\r
+                                       break;\r
+                               case AAT_BOOL:\r
+                                       val._type = OT_BOOL;\r
+                                       val._unVal.nInteger = arg1;\r
+                                       break;\r
+                               default: assert(0); break;\r
+\r
+                               }\r
+                               _array(STK(arg0))->Append(val); continue;\r
+                               }\r
+                       case _OP_COMPARITH: {\r
+                               SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);\r
+                               _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); \r
+                                                               }\r
                                continue;\r
-                       case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;\r
-                       case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;\r
-                       case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL);  continue;\r
-                       case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue;\r
-                       case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue;\r
-                       case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue;\r
-                       case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue;\r
-                       case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue;\r
-                       case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue;\r
-                       case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue;\r
+                       case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;\r
+                       case _OP_INCL: {\r
+                               SQObjectPtr &a = STK(arg1);\r
+                               if(type(a) == OT_INTEGER) {\r
+                                       a._unVal.nInteger = _integer(a) + sarg3;\r
+                               }\r
+                               else {\r
+                                       SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));\r
+                                       _ARITH_(+,a,a,o);\r
+                               }\r
+                                                  } continue;\r
+                       case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;\r
+                       case _OP_PINCL: {\r
+                               SQObjectPtr &a = STK(arg1);\r
+                               if(type(a) == OT_INTEGER) {\r
+                                       TARGET = a;\r
+                                       a._unVal.nInteger = _integer(a) + sarg3;\r
+                               }\r
+                               else {\r
+                                       SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));\r
+                               }\r
+                               \r
+                                               } continue;\r
                        case _OP_CMP:   _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET))  continue;\r
-                       case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue;\r
+                       case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue;\r
                        case _OP_INSTANCEOF: \r
-                               if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE)\r
+                               if(type(STK(arg1)) != OT_CLASS)\r
                                {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}\r
-                               TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_;\r
+                               TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;\r
                                continue;\r
                        case _OP_AND: \r
                                if(IsFalse(STK(arg2))) {\r
@@ -909,7 +956,7 @@ common_call:
                                }\r
                                continue;\r
                        case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;\r
-                       case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue;\r
+                       case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;\r
                        case _OP_BWNOT:\r
                                if(type(STK(arg1)) == OT_INTEGER) {\r
                                        SQInteger t = _integer(STK(arg1));\r
@@ -920,16 +967,16 @@ common_call:
                                SQ_THROW();\r
                        case _OP_CLOSURE: {\r
                                SQClosure *c = ci->_closure._unVal.pClosure;\r
-                               SQFunctionProto *fp = c->_function._unVal.pFunctionProto;\r
+                               SQFunctionProto *fp = c->_function;\r
                                if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }\r
                                continue;\r
                        }\r
                        case _OP_YIELD:{\r
                                if(ci->_generator) {\r
                                        if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);\r
-                                       _GUARD(ci->_generator->Yield(this));\r
+                                       _GUARD(ci->_generator->Yield(this,arg2));\r
                                        traps -= ci->_etraps;\r
-                                       if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg;\r
+                                       if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg;\r
                                }\r
                                else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}\r
                                if(Return(arg0, arg1, temp_reg)){\r
@@ -942,7 +989,7 @@ common_call:
                                continue;\r
                        case _OP_RESUME:\r
                                if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}\r
-                               _GUARD(_generator(STK(arg1))->Resume(this, arg0));\r
+                               _GUARD(_generator(STK(arg1))->Resume(this, TARGET));\r
                                traps += ci->_etraps;\r
                 continue;\r
                        case _OP_FOREACH:{ int tojump;\r
@@ -954,14 +1001,10 @@ common_call:
                                if(_generator(STK(arg0))->_state == SQGenerator::eDead) \r
                                        ci->_ip += (sarg1 - 1);\r
                                continue;\r
-                       case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue;\r
-                       case _OP_CLONE:\r
-                               if(!Clone(STK(arg1), TARGET))\r
-                               { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();}\r
-                               continue;\r
-                       case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue;\r
+                       case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;\r
+                       case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;\r
                        case _OP_PUSHTRAP:{\r
-                               SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions;\r
+                               SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;\r
                                _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;\r
                                ci->_etraps++;\r
                                                          }\r
@@ -974,27 +1017,23 @@ common_call:
                                                          }\r
                                continue;\r
                        case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;\r
-                       case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;\r
                        case _OP_NEWSLOTA:\r
-                               bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false;\r
-                               if(type(STK(arg1)) == OT_CLASS) {\r
-                                       if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) {\r
-                                               Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3));\r
-                                               Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_);\r
-                                               Push(bstatic);\r
-                                               int nparams = 5;\r
-                                               if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) {\r
-                                                       Pop(nparams);\r
-                                                       continue;\r
-                                               }\r
-                                       }\r
+                               _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));\r
+                               continue;\r
+                       case _OP_GETBASE:{\r
+                               SQClosure *clo = _closure(ci->_closure);\r
+                               if(clo->_base) {\r
+                                       TARGET = clo->_base;\r
                                }\r
-                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic));\r
-                               if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) {\r
-                                       _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));\r
+                               else {\r
+                                       TARGET.Null();\r
                                }\r
                                continue;\r
                        }\r
+                       case _OP_CLOSE:\r
+                               if(_openouters) CloseOuters(&(STK(arg1)));\r
+                               continue;\r
+                       }\r
                        \r
                }\r
        }\r
@@ -1002,50 +1041,35 @@ exception_trap:
        {\r
                SQObjectPtr currerror = _lasterror;\r
 //             dumpstack(_stackbase);\r
-               SQInteger n = 0;\r
+//             SQInteger n = 0;\r
                SQInteger last_top = _top;\r
-               if(ci) {\r
-                       if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror);\r
-\r
-                       if(traps) {\r
-                               do {\r
-                                       if(ci->_etraps > 0) {\r
-                                               SQExceptionTrap &et = _etraps.top();\r
-                                               ci->_ip = et._ip;\r
-                                               _top = et._stacksize;\r
-                                               _stackbase = et._stackbase;\r
-                                               _stack._vals[_stackbase+et._extarget] = currerror;\r
-                                               _etraps.pop_back(); traps--; ci->_etraps--;\r
-                                               CLEARSTACK(last_top);\r
-                                               goto exception_restore;\r
-                                       }\r
-                                       //if is a native closure\r
-                                       if(type(ci->_closure) != OT_CLOSURE && n)\r
-                                               break;\r
-                                       if(ci->_generator) ci->_generator->Kill();\r
-                                       PopVarArgs(ci->_vargs);\r
-                                       POP_CALLINFO(this);\r
-                                       n++;\r
-                               } while(_callsstacksize);\r
+               \r
+               if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);\r
+\r
+               while( ci ) {\r
+                       if(ci->_etraps > 0) {\r
+                               SQExceptionTrap &et = _etraps.top();\r
+                               ci->_ip = et._ip;\r
+                               _top = et._stacksize;\r
+                               _stackbase = et._stackbase;\r
+                               _stack._vals[_stackbase + et._extarget] = currerror;\r
+                               _etraps.pop_back(); traps--; ci->_etraps--;\r
+                               while(last_top >= _top) _stack._vals[last_top--].Null();\r
+                               goto exception_restore;\r
                        }\r
-                       else {\r
-                               //call the hook\r
-                               if(raiseerror && !_ss(this)->_notifyallexceptions)\r
-                                       CallErrorHandler(currerror);\r
+                       else if (_debughook) { \r
+                                       //notify debugger of a "return"\r
+                                       //even if it really an exception unwinding the stack\r
+                                       for(SQInteger i = 0; i < ci->_ncalls; i++) {\r
+                                               CallDebugHook(_SC('r'));\r
+                                       }\r
                        }\r
-                       //remove call stack until a C function is found or the cstack is empty\r
-                       if(ci) do {\r
-                               SQBool exitafterthisone = ci->_root;\r
-                               if(ci->_generator) ci->_generator->Kill();\r
-                               _stackbase -= ci->_prevstkbase;\r
-                               _top = _stackbase + ci->_prevtop;\r
-                               PopVarArgs(ci->_vargs);\r
-                               POP_CALLINFO(this);\r
-                               if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;\r
-                       } while(_callsstacksize);\r
-\r
-                       CLEARSTACK(last_top);\r
+                       if(ci->_generator) ci->_generator->Kill();\r
+                       bool mustbreak = ci && ci->_root;\r
+                       LeaveFrame();\r
+                       if(mustbreak) break;\r
                }\r
+                                               \r
                _lasterror = currerror;\r
                return false;\r
        }\r
@@ -1055,8 +1079,8 @@ exception_trap:
 bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)\r
 {\r
        inst = theclass->CreateInstance();\r
-       if(!theclass->Get(_ss(this)->_constructoridx,constructor)) {\r
-               constructor = _null_;\r
+       if(!theclass->GetConstructor(constructor)) {\r
+               constructor.Null();\r
        }\r
        return true;\r
 }\r
@@ -1071,219 +1095,270 @@ void SQVM::CallErrorHandler(SQObjectPtr &error)
        }\r
 }\r
 \r
+\r
 void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)\r
 {\r
-       SQObjectPtr temp_reg;\r
-       SQInteger nparams=5;\r
-       SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function);\r
-       Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);\r
-       Call(_debughook,nparams,_top-nparams,temp_reg,SQFalse);\r
-       Pop(nparams);\r
+       _debughook = false;\r
+       SQFunctionProto *func=_closure(ci->_closure)->_function;\r
+       if(_debughook_native) {\r
+               const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;\r
+               const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;\r
+               SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip);\r
+               _debughook_native(this,type,src,line,fname);\r
+       }\r
+       else {\r
+               SQObjectPtr temp_reg;\r
+               SQInteger nparams=5;\r
+               Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);\r
+               Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse);\r
+               Pop(nparams);\r
+       }\r
+       _debughook = true;\r
 }\r
 \r
-bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend)\r
+bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)\r
 {\r
-       if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
        SQInteger nparamscheck = nclosure->_nparamscheck;\r
-       if(((nparamscheck > 0) && (nparamscheck != nargs))\r
-               || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) {\r
+       SQInteger newtop = newbase + nargs + nclosure->_noutervalues;\r
+       \r
+       if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {\r
+               Raise_Error(_SC("Native stack overflow"));\r
+               return false;\r
+       }\r
+\r
+       if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||\r
+               ((nparamscheck < 0) && (nargs < (-nparamscheck)))))\r
+       {\r
                Raise_Error(_SC("wrong number of parameters"));\r
                return false;\r
-               }\r
+       }\r
 \r
        SQInteger tcs;\r
-       if((tcs = nclosure->_typecheck.size())) {\r
-               for(SQInteger i = 0; i < nargs && i < tcs; i++)\r
-                       if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) {\r
-                Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i]));\r
+       SQIntVec &tc = nclosure->_typecheck;\r
+       if((tcs = tc.size())) {\r
+               for(SQInteger i = 0; i < nargs && i < tcs; i++) {\r
+                       if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {\r
+                               Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));\r
                                return false;\r
                        }\r
+               }\r
        }\r
-       _nnativecalls++;\r
-       if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) {\r
-               _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));\r
-       }\r
-       SQInteger oldtop = _top;\r
-       SQInteger oldstackbase = _stackbase;\r
-       _top = stackbase + nargs;\r
-       CallInfo lci;\r
-       lci._closure = nclosure;\r
-       lci._generator = NULL;\r
-       lci._etraps = 0;\r
-       lci._prevstkbase = (SQInt32) (stackbase - _stackbase);\r
-       lci._ncalls = 1;\r
-       lci._prevtop = (SQInt32) (oldtop - oldstackbase);\r
-       PUSH_CALLINFO(this, lci);\r
-       _stackbase = stackbase;\r
-       //push free variables\r
-       SQInteger outers = nclosure->_outervalues.size();\r
+\r
+       if(!EnterFrame(newbase, newtop, false)) return false;\r
+       ci->_closure  = nclosure;\r
+\r
+       SQInteger outers = nclosure->_noutervalues;\r
        for (SQInteger i = 0; i < outers; i++) {\r
-               Push(nclosure->_outervalues[i]);\r
+               _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];\r
        }\r
-\r
-       if(type(nclosure->_env) == OT_WEAKREF) {\r
-               _stack[stackbase] = _weakref(nclosure->_env)->_obj;\r
+       if(nclosure->_env) {\r
+               _stack._vals[newbase] = nclosure->_env->_obj;\r
        }\r
 \r
-       \r
+       _nnativecalls++;\r
        SQInteger ret = (nclosure->_function)(this);\r
        _nnativecalls--;\r
+\r
        suspend = false;\r
-       if( ret == SQ_SUSPEND_FLAG) suspend = true;\r
-       else if (ret < 0) { \r
-               _stackbase = oldstackbase;\r
-               _top = oldtop;\r
-               POP_CALLINFO(this);\r
+       if (ret == SQ_SUSPEND_FLAG) {\r
+               suspend = true;\r
+       }\r
+       else if (ret < 0) {\r
+               LeaveFrame();\r
                Raise_Error(_lasterror);\r
                return false;\r
        }\r
-       \r
-       if (ret != 0){ retval = TOP(); TOP().Null(); }\r
-       else { retval = _null_; }\r
-       _stackbase = oldstackbase;\r
-       _top = oldtop;\r
-       POP_CALLINFO(this);\r
+       if(ret) {\r
+               retval = _stack._vals[_top-1];\r
+       }\r
+       else {\r
+               retval.Null();\r
+       }\r
+       //retval = ret ? _stack._vals[_top-1] : _null_;\r
+       LeaveFrame();\r
        return true;\r
 }\r
 \r
-bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot)\r
+#define FALLBACK_OK                    0\r
+#define FALLBACK_NO_MATCH      1\r
+#define FALLBACK_ERROR         2\r
+\r
+bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx)\r
 {\r
        switch(type(self)){\r
        case OT_TABLE:\r
                if(_table(self)->Get(key,dest))return true;\r
                break;\r
        case OT_ARRAY:\r
-               if(sq_isnumeric(key)){\r
-                       return _array(self)->Get(tointeger(key),dest);\r
-               }\r
+               if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; }\r
                break;\r
        case OT_INSTANCE:\r
                if(_instance(self)->Get(key,dest)) return true;\r
                break;\r
+       case OT_CLASS: \r
+               if(_class(self)->Get(key,dest)) return true;\r
+               break;\r
+       case OT_STRING:\r
+               if(sq_isnumeric(key)){\r
+                       SQInteger n = tointeger(key);\r
+                       if(abs((int)n) < _string(self)->_len) {\r
+                               if(n < 0) n = _string(self)->_len - n;\r
+                               dest = SQInteger(_stringval(self)[n]);\r
+                               return true;\r
+                       }\r
+                       Raise_IdxError(key);\r
+                       return false;\r
+               }\r
+               break;\r
        default:break; //shut up compiler\r
        }\r
-       if(FallBackGet(self,key,dest,raw)) return true;\r
-\r
-       if(fetchroot) {\r
-               if(_rawval(STK(0)) == _rawval(self) &&\r
-                       type(STK(0)) == type(self)) {\r
-                               return _table(_roottable)->Get(key,dest);\r
+       if(!raw) {\r
+               switch(FallBackGet(self,key,dest)) {\r
+                       case FALLBACK_OK: return true; //okie\r
+                       case FALLBACK_NO_MATCH: break; //keep falling back\r
+                       case FALLBACK_ERROR: return false; // the metamethod failed\r
+               }\r
+               if(InvokeDefaultDelegate(self,key,dest)) {\r
+                       return true;\r
                }\r
        }\r
+//#ifdef ROOT_FALLBACK\r
+       if(selfidx == 0) {\r
+               if(_table(_roottable)->Get(key,dest)) return true;\r
+       }\r
+//#endif\r
+       Raise_IdxError(key);\r
        return false;\r
 }\r
 \r
-bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw)\r
+bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)\r
+{\r
+       SQTable *ddel = NULL;\r
+       switch(type(self)) {\r
+               case OT_CLASS: ddel = _class_ddel; break;\r
+               case OT_TABLE: ddel = _table_ddel; break;\r
+               case OT_ARRAY: ddel = _array_ddel; break;\r
+               case OT_STRING: ddel = _string_ddel; break;\r
+               case OT_INSTANCE: ddel = _instance_ddel; break;\r
+               case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;\r
+               case OT_GENERATOR: ddel = _generator_ddel; break;\r
+               case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break;\r
+               case OT_THREAD: ddel = _thread_ddel; break;\r
+               case OT_WEAKREF: ddel = _weakref_ddel; break;\r
+               default: return false;\r
+       }\r
+       return  ddel->Get(key,dest);\r
+}\r
+\r
+\r
+SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)\r
 {\r
        switch(type(self)){\r
-       case OT_CLASS: \r
-               return _class(self)->Get(key,dest);\r
-               break;\r
        case OT_TABLE:\r
        case OT_USERDATA:\r
         //delegation\r
                if(_delegable(self)->_delegate) {\r
-                       if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false))\r
-                               return true;    \r
-                       if(raw)return false;\r
-                       Push(self);Push(key);\r
-                       if(CallMetaMethod(_delegable(self),MT_GET,2,dest))\r
-                               return true;\r
+                       if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK;     \r
                }\r
-               if(type(self) == OT_TABLE) {\r
-                       if(raw) return false;\r
-                       return _table_ddel->Get(key,dest);\r
+               else {\r
+                       return FALLBACK_NO_MATCH;\r
                }\r
-               return false;\r
-               break;\r
-       case OT_ARRAY:\r
-               if(raw)return false;\r
-               return _array_ddel->Get(key,dest);\r
-       case OT_STRING:\r
-               if(sq_isnumeric(key)){\r
-                       SQInteger n=tointeger(key);\r
-                       if(abs((int)n)<_string(self)->_len){\r
-                               if(n<0)n=_string(self)->_len-n;\r
-                               dest=SQInteger(_stringval(self)[n]);\r
-                               return true;\r
+               //go through\r
+       case OT_INSTANCE: {\r
+               SQObjectPtr closure;\r
+               if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {\r
+                       Push(self);Push(key);\r
+                       _nmetamethodscall++;\r
+                       AutoDec ad(&_nmetamethodscall);\r
+                       if(Call(closure, 2, _top - 2, dest, SQFalse)) {\r
+                               Pop(2);\r
+                               return FALLBACK_OK;\r
+                       }\r
+                       else {\r
+                               Pop(2);\r
+                               if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)\r
+                                       return FALLBACK_ERROR;\r
+                               }\r
                        }\r
-                       return false;\r
-               }\r
-               else {\r
-                       if(raw)return false;\r
-                       return _string_ddel->Get(key,dest);\r
                }\r
+                                         }\r
                break;\r
-       case OT_INSTANCE:\r
-               if(raw)return false;\r
-               Push(self);Push(key);\r
-               if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) {\r
-                       return _instance_ddel->Get(key,dest);\r
-               }\r
-               return true;\r
-       case OT_INTEGER:case OT_FLOAT:case OT_BOOL: \r
-               if(raw)return false;\r
-               return _number_ddel->Get(key,dest);\r
-       case OT_GENERATOR: \r
-               if(raw)return false;\r
-               return _generator_ddel->Get(key,dest);\r
-       case OT_CLOSURE: case OT_NATIVECLOSURE: \r
-               if(raw)return false;\r
-               return _closure_ddel->Get(key,dest);\r
-       case OT_THREAD:\r
-               if(raw)return false;\r
-               return  _thread_ddel->Get(key,dest);\r
-       case OT_WEAKREF:\r
-               if(raw)return false;\r
-               return  _weakref_ddel->Get(key,dest);\r
-       default:return false;\r
+       default: break;//shutup GCC 4.x\r
        }\r
-       return false;\r
+       // no metamethod or no fallback type\r
+       return FALLBACK_NO_MATCH;\r
 }\r
 \r
-bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot)\r
+bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx)\r
 {\r
        switch(type(self)){\r
        case OT_TABLE:\r
-               if(_table(self)->Set(key,val))\r
-                       return true;\r
-               if(_table(self)->_delegate) {\r
-                       if(Set(_table(self)->_delegate,key,val,false)) {\r
-                               return true;\r
-                       }\r
-               }\r
-               //keeps going\r
-       case OT_USERDATA:\r
-               if(_delegable(self)->_delegate) {\r
-                       SQObjectPtr t;\r
-                       Push(self);Push(key);Push(val);\r
-                       if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;\r
-               }\r
+               if(_table(self)->Set(key,val)) return true;\r
                break;\r
-       case OT_INSTANCE:{\r
-               if(_instance(self)->Set(key,val))\r
-                       return true;\r
-               SQObjectPtr t;\r
-               Push(self);Push(key);Push(val);\r
-               if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;\r
-               }\r
+       case OT_INSTANCE:\r
+               if(_instance(self)->Set(key,val)) return true;\r
                break;\r
        case OT_ARRAY:\r
-               if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }\r
-               return _array(self)->Set(tointeger(key),val);\r
+               if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }\r
+               if(!_array(self)->Set(tointeger(key),val)) {\r
+                       Raise_IdxError(key);\r
+                       return false;\r
+               }\r
+               return true;\r
        default:\r
                Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));\r
                return false;\r
        }\r
-       if(fetchroot) {\r
-               if(_rawval(STK(0)) == _rawval(self) &&\r
-                       type(STK(0)) == type(self)) {\r
-                               return _table(_roottable)->Set(key,val);\r
-                       }\r
+\r
+       switch(FallBackSet(self,key,val)) {\r
+               case FALLBACK_OK: return true; //okie\r
+               case FALLBACK_NO_MATCH: break; //keep falling back\r
+               case FALLBACK_ERROR: return false; // the metamethod failed\r
+       }\r
+       if(selfidx == 0) {\r
+               if(_table(_roottable)->Set(key,val))\r
+                       return true;\r
        }\r
+       Raise_IdxError(key);\r
        return false;\r
 }\r
 \r
+SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+       switch(type(self)) {\r
+       case OT_TABLE:\r
+               if(_table(self)->_delegate) {\r
+                       if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK;\r
+               }\r
+               //keps on going\r
+       case OT_INSTANCE:\r
+       case OT_USERDATA:{\r
+               SQObjectPtr closure;\r
+               SQObjectPtr t;\r
+               if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {\r
+                       Push(self);Push(key);Push(val);\r
+                       _nmetamethodscall++;\r
+                       AutoDec ad(&_nmetamethodscall);\r
+                       if(Call(closure, 3, _top - 3, t, SQFalse)) {\r
+                               Pop(3);\r
+                               return FALLBACK_OK;\r
+                       }\r
+                       else {\r
+                               if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)\r
+                                       //error\r
+                                       Pop(3);\r
+                                       return FALLBACK_ERROR;\r
+                               }\r
+                       }\r
+               }\r
+                                        }\r
+               break;\r
+               default: break;//shutup GCC 4.x\r
+       }\r
+       // no metamethod or no fallback type\r
+       return FALLBACK_NO_MATCH;\r
+}\r
+\r
 bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)\r
 {\r
        SQObjectPtr temp_reg;\r
@@ -1292,21 +1367,50 @@ bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)
        case OT_TABLE:\r
                newobj = _table(self)->Clone();\r
                goto cloned_mt;\r
-       case OT_INSTANCE:\r
+       case OT_INSTANCE: {\r
                newobj = _instance(self)->Clone(_ss(this));\r
 cloned_mt:\r
-               if(_delegable(newobj)->_delegate){\r
+               SQObjectPtr closure;\r
+               if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {\r
                        Push(newobj);\r
                        Push(self);\r
-                       CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg);\r
+                       if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))\r
+                               return false;\r
+               }\r
                }\r
                target = newobj;\r
                return true;\r
        case OT_ARRAY: \r
                target = _array(self)->Clone();\r
                return true;\r
-       default: return false;\r
+       default: \r
+               Raise_Error(_SC("cloning a %s"), GetTypeName(self));\r
+               return false;\r
+       }\r
+}\r
+\r
+bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw)\r
+{\r
+       if(type(self) != OT_CLASS) {\r
+               Raise_Error(_SC("object must be a class"));\r
+               return false;\r
        }\r
+       SQClass *c = _class(self);\r
+       if(!raw) {\r
+               SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];\r
+               if(type(mm) != OT_NULL ) {\r
+                       Push(self); Push(key); Push(val);\r
+                       Push(attrs);\r
+                       Push(bstatic);\r
+                       return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg);\r
+               }\r
+       }\r
+       if(!NewSlot(self, key, val,bstatic))\r
+               return false;\r
+       if(type(attrs) != OT_NULL) {\r
+               c->SetAttributes(key,attrs);\r
+       }\r
+       return true;\r
 }\r
 \r
 bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)\r
@@ -1318,8 +1422,17 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject
                if(_table(self)->_delegate) {\r
                        SQObjectPtr res;\r
                        if(!_table(self)->Get(key,res)) {\r
-                               Push(self);Push(key);Push(val);\r
-                               rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res);\r
+                               SQObjectPtr closure;\r
+                               if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {\r
+                                       Push(self);Push(key);Push(val);\r
+                                       if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {\r
+                                               return false;\r
+                                       }\r
+                                       rawcall = false;\r
+                               }\r
+                               else {\r
+                                       rawcall = true;\r
+                               }\r
                        }\r
                }\r
                if(rawcall) _table(self)->NewSlot(key,val); //cannot fail\r
@@ -1327,11 +1440,16 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject
                break;}\r
        case OT_INSTANCE: {\r
                SQObjectPtr res;\r
-               Push(self);Push(key);Push(val);\r
-               if(!CallMetaMethod(_instance(self),MT_NEWSLOT,3,res)) {\r
-                       Raise_Error(_SC("class instances do not support the new slot operator"));\r
-                       return false;\r
+               SQObjectPtr closure;\r
+               if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {\r
+                       Push(self);Push(key);Push(val);\r
+                       if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {\r
+                               return false;\r
+                       }\r
+                       break;\r
                }\r
+               Raise_Error(_SC("class instances do not support the new slot operator"));\r
+               return false;\r
                break;}\r
        case OT_CLASS: \r
                if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {\r
@@ -1354,6 +1472,8 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject
        return true;\r
 }\r
 \r
+\r
+\r
 bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)\r
 {\r
        switch(type(self)) {\r
@@ -1361,13 +1481,13 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr
        case OT_INSTANCE:\r
        case OT_USERDATA: {\r
                SQObjectPtr t;\r
-               bool handled = false;\r
-               if(_delegable(self)->_delegate) {\r
+               //bool handled = false;\r
+               SQObjectPtr closure;\r
+               if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {\r
                        Push(self);Push(key);\r
-                       handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t);\r
+                       return CallMetaMethod(closure,MT_DELSLOT,2,res);\r
                }\r
-\r
-               if(!handled) {\r
+               else {\r
                        if(type(self) == OT_TABLE) {\r
                                if(_table(self)->Get(key,t)) {\r
                                        _table(self)->Remove(key);\r
@@ -1399,7 +1519,7 @@ SQInteger prevstackbase = _stackbase;
 #endif\r
        switch(type(closure)) {\r
        case OT_CLOSURE:\r
-               return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror);\r
+               return Execute(closure, nparams, stackbase, outres, raiseerror);\r
                break;\r
        case OT_NATIVECLOSURE:{\r
                bool suspend;\r
@@ -1429,38 +1549,130 @@ SQInteger prevstackbase = _stackbase;
        return true;\r
 }\r
 \r
-bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)\r
+bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)\r
 {\r
-       SQObjectPtr closure;\r
-       if(del->GetMetaMethod(this, mm, closure)) {\r
-               if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {\r
-                       Pop(nparams);\r
-                       return true;\r
-               }\r
+       //SQObjectPtr closure;\r
+       \r
+       _nmetamethodscall++;\r
+       if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {\r
+               _nmetamethodscall--;\r
+               Pop(nparams);\r
+               return true;\r
        }\r
+       _nmetamethodscall--;\r
+       //}\r
        Pop(nparams);\r
        return false;\r
 }\r
 \r
+void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)\r
+{\r
+       SQOuter **pp = &_openouters;\r
+       SQOuter *p;\r
+       SQOuter *otr;\r
+\r
+       while ((p = *pp) != NULL && p->_valptr >= stackindex) {\r
+               if (p->_valptr == stackindex) {\r
+                       target = SQObjectPtr(p);\r
+                       return;\r
+               }\r
+               pp = &p->_next;\r
+       }\r
+       otr = SQOuter::Create(_ss(this), stackindex);\r
+       otr->_next = *pp;\r
+       otr->_idx  = (stackindex - _stack._vals);\r
+       __ObjAddRef(otr);\r
+       *pp = otr;\r
+       target = SQObjectPtr(otr);\r
+}\r
+\r
+bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall)\r
+{\r
+       if( !tailcall ) {\r
+               if( _callsstacksize == _alloccallsstacksize ) {\r
+                       GrowCallStack();\r
+               }\r
+               ci = &_callsstack[_callsstacksize++];\r
+               ci->_prevstkbase = (SQInt32)(newbase - _stackbase);\r
+               ci->_prevtop = (SQInt32)(_top - _stackbase);\r
+               ci->_etraps = 0;\r
+               ci->_ncalls = 1;\r
+               ci->_generator = NULL;\r
+               ci->_root = SQFalse;\r
+       }\r
+       else {\r
+               ci->_ncalls++;\r
+       }\r
+\r
+       _stackbase = newbase;\r
+       _top = newtop;\r
+       if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) {\r
+               if(_nmetamethodscall) {\r
+                       Raise_Error(_SC("stack overflow, cannot resize stack while in  a metamethod"));\r
+                       return false;\r
+               }\r
+               _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2));\r
+               RelocateOuters();\r
+       }\r
+       return true;\r
+}\r
+\r
+void SQVM::LeaveFrame() {\r
+       SQInteger last_top = _top;\r
+       SQInteger last_stackbase = _stackbase;\r
+       SQInteger css = --_callsstacksize;\r
+\r
+       /* First clean out the call stack frame */\r
+       ci->_closure.Null();\r
+       _stackbase -= ci->_prevstkbase;\r
+       _top = _stackbase + ci->_prevtop;\r
+       ci = (css) ? &_callsstack[css-1] : NULL;\r
+\r
+       if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));\r
+       while (last_top >= _top) {\r
+               _stack._vals[last_top--].Null();\r
+       }\r
+}\r
+\r
+void SQVM::RelocateOuters()\r
+{\r
+       SQOuter *p = _openouters;\r
+       while (p) {\r
+               p->_valptr = _stack._vals + p->_idx;\r
+               p = p->_next;\r
+       }\r
+}\r
+\r
+void SQVM::CloseOuters(SQObjectPtr *stackindex) {\r
+  SQOuter *p;\r
+  while ((p = _openouters) != NULL && p->_valptr >= stackindex) {\r
+    p->_value = *(p->_valptr);\r
+    p->_valptr = &p->_value;\r
+    _openouters = p->_next;\r
+       __ObjRelease(p);\r
+  }\r
+}\r
+\r
 void SQVM::Remove(SQInteger n) {\r
        n = (n >= 0)?n + _stackbase - 1:_top + n;\r
        for(SQInteger i = n; i < _top; i++){\r
                _stack[i] = _stack[i+1];\r
        }\r
-       _stack[_top] = _null_;\r
+       _stack[_top].Null();\r
        _top--;\r
 }\r
 \r
 void SQVM::Pop() {\r
-       _stack[--_top] = _null_;\r
+       _stack[--_top].Null();\r
 }\r
 \r
 void SQVM::Pop(SQInteger n) {\r
        for(SQInteger i = 0; i < n; i++){\r
-               _stack[--_top] = _null_;\r
+               _stack[--_top].Null();\r
        }\r
 }\r
 \r
+void SQVM::PushNull() { _stack[_top++].Null(); }\r
 void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }\r
 SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }\r
 SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }\r
old mode 100755 (executable)
new mode 100644 (file)
index 202a7a1..13b3706
@@ -5,9 +5,10 @@
 #include "sqopcodes.h"\r
 #include "sqobject.h"\r
 #define MAX_NATIVE_CALLS 100\r
-#define MIN_STACK_OVERHEAD 10\r
+#define MIN_STACK_OVERHEAD 15\r
 \r
 #define SQ_SUSPEND_FLAG -666\r
+#define DONT_FALL_BACK 666\r
 //base lib\r
 void sq_base_register(HSQUIRRELVM v);\r
 \r
@@ -30,14 +31,8 @@ typedef sqvector<SQExceptionTrap> ExceptionsTraps;
 \r
 struct SQVM : public CHAINABLE_OBJ\r
 {\r
-       struct VarArgs {\r
-               VarArgs() { size = 0; base = 0; }\r
-               unsigned short size;\r
-               unsigned short base;\r
-       };\r
-\r
        struct CallInfo{\r
-               //CallInfo() { _generator._type = OT_NULL;}\r
+               //CallInfo() { _generator = NULL;}\r
                SQInstruction *_ip;\r
                SQObjectPtr *_literals;\r
                SQObjectPtr _closure;\r
@@ -48,18 +43,19 @@ struct SQVM : public CHAINABLE_OBJ
                SQInt32 _target;\r
                SQInt32 _ncalls;\r
                SQBool _root;\r
-               VarArgs _vargs;\r
        };\r
        \r
 typedef sqvector<CallInfo> CallInfoVec;\r
 public:\r
-       enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_THROW_VM };\r
+       void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);\r
+       static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);\r
+       enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM };\r
        SQVM(SQSharedState *ss);\r
        ~SQVM();\r
        bool Init(SQVM *friendvm, SQInteger stacksize);\r
-       bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);\r
+       bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);\r
        //starts a native call return when the NATIVE closure returns\r
-       bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend);\r
+       bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend);\r
        //starts a SQUIRREL call in the same "Execution loop"\r
        bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);\r
        bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);\r
@@ -69,27 +65,34 @@ public:
 \r
        void CallDebugHook(SQInteger type,SQInteger forcedline=0);\r
        void CallErrorHandler(SQObjectPtr &e);\r
-       bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);\r
-       bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);\r
-       bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);\r
+       bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, SQInteger selfidx);\r
+       SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);\r
+       bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);\r
+       bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx);\r
+       SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val);\r
        bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic);\r
+       bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw);\r
        bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);\r
        bool Clone(const SQObjectPtr &self, SQObjectPtr &target);\r
        bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);\r
        bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);\r
-       bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);\r
-       void ToString(const SQObjectPtr &o,SQObjectPtr &res);\r
-       SQString *PrintObjVal(const SQObject &o);\r
+       static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res);\r
+       bool ToString(const SQObjectPtr &o,SQObjectPtr &res);\r
+       SQString *PrintObjVal(const SQObjectPtr &o);\r
 \r
  \r
        void Raise_Error(const SQChar *s, ...);\r
-       void Raise_Error(SQObjectPtr &desc);\r
-       void Raise_IdxError(SQObject &o);\r
+       void Raise_Error(const SQObjectPtr &desc);\r
+       void Raise_IdxError(const SQObjectPtr &o);\r
        void Raise_CompareError(const SQObject &o1, const SQObject &o2);\r
        void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);\r
 \r
-       void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);\r
-       bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);\r
+       void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex);\r
+       void RelocateOuters();\r
+       void CloseOuters(SQObjectPtr *stackindex);\r
+\r
+       bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);\r
+       bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);\r
        bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
        bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);\r
        //new stuff\r
@@ -98,23 +101,19 @@ public:
        _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);\r
        _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);\r
        bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);\r
-       bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);\r
        bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);\r
-       bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target);\r
        //return true if the loop is finished\r
        bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);\r
-       bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);\r
-       _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
+       //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
        _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
-       _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);\r
-       void PopVarArgs(VarArgs &vargs);\r
-       void ClearStack(SQInteger last_top);\r
+       _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0);\r
 #ifdef _DEBUG_DUMP\r
        void dumpstack(SQInteger stackbase=-1, bool dumpall = false);\r
 #endif\r
 \r
 #ifndef NO_GARBAGE_COLLECTOR\r
        void Mark(SQCollectable **chain);\r
+       SQObjectType GetType() {return OT_THREAD;}\r
 #endif\r
        void Finalize();\r
        void GrowCallStack() {\r
@@ -123,29 +122,36 @@ public:
                _callsstack = &_callstackdata[0];\r
                _alloccallsstacksize = newsize;\r
        }\r
-       void Release(){ sq_delete(this,SQVM); } //does nothing\r
+       bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall);\r
+       void LeaveFrame();\r
+       void Release(){ sq_delete(this,SQVM); }\r
 ////////////////////////////////////////////////////////////////////////////\r
        //stack functions for the api\r
        void Remove(SQInteger n);\r
 \r
-       bool IsFalse(SQObjectPtr &o);\r
+       static bool IsFalse(SQObjectPtr &o);\r
        \r
        void Pop();\r
        void Pop(SQInteger n);\r
        void Push(const SQObjectPtr &o);\r
+       void PushNull();\r
        SQObjectPtr &Top();\r
        SQObjectPtr &PopGet();\r
        SQObjectPtr &GetUp(SQInteger n);\r
        SQObjectPtr &GetAt(SQInteger n);\r
 \r
        SQObjectPtrVec _stack;\r
-       SQObjectPtrVec _vargsstack;\r
+\r
        SQInteger _top;\r
        SQInteger _stackbase;\r
+       SQOuter *_openouters;\r
        SQObjectPtr _roottable;\r
        SQObjectPtr _lasterror;\r
        SQObjectPtr _errorhandler;\r
-       SQObjectPtr _debughook;\r
+\r
+       bool _debughook;\r
+       SQDEBUGHOOK _debughook_native;\r
+       SQObjectPtr _debughook_closure;\r
 \r
        SQObjectPtr temp_reg;\r
        \r
@@ -161,12 +167,12 @@ public:
        //VMs sharing the same state\r
        SQSharedState *_sharedstate;\r
        SQInteger _nnativecalls;\r
+       SQInteger _nmetamethodscall;\r
        //suspend infos\r
        SQBool _suspended;\r
        SQBool _suspended_root;\r
        SQInteger _suspended_target;\r
        SQInteger _suspended_traps;\r
-       VarArgs _suspend_varargs;\r
 };\r
 \r
 struct AutoDec{\r
@@ -186,20 +192,18 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->
 #endif\r
 \r
 #define PUSH_CALLINFO(v,nci){ \\r
-       if(v->_callsstacksize == v->_alloccallsstacksize) { \\r
+       SQInteger css = v->_callsstacksize; \\r
+       if(css == v->_alloccallsstacksize) { \\r
                v->GrowCallStack(); \\r
        } \\r
-       v->ci = &v->_callsstack[v->_callsstacksize]; \\r
+       v->ci = &v->_callsstack[css]; \\r
        *(v->ci) = nci; \\r
        v->_callsstacksize++; \\r
 }\r
 \r
 #define POP_CALLINFO(v){ \\r
-       v->_callsstacksize--; \\r
+       SQInteger css = --v->_callsstacksize; \\r
        v->ci->_closure.Null(); \\r
-       if(v->_callsstacksize)  \\r
-               v->ci = &v->_callsstack[v->_callsstacksize-1] ; \\r
-       else    \\r
-               v->ci = NULL; \\r
+       v->ci = css?&v->_callsstack[css-1]:NULL;        \\r
 }\r
 #endif //_SQVM_H_\r