From bc25f6fa2616df7e905fed68ceb4e3ebc186a623 Mon Sep 17 00:00:00 2001 From: Tobias Markus Date: Wed, 26 Feb 2014 17:46:58 +0100 Subject: [PATCH] Update to SQUIRREL 3.0.4 --- external/squirrel/COPYRIGHT | 42 +- external/squirrel/HISTORY | 167 +++- external/squirrel/README | 13 +- external/squirrel/include/sqstdaux.h | 0 external/squirrel/include/sqstdblob.h | 0 external/squirrel/include/sqstdio.h | 1 - external/squirrel/include/sqstdmath.h | 0 external/squirrel/include/sqstdstring.h | 0 external/squirrel/include/sqstdsystem.h | 0 external/squirrel/include/squirrel.h | 142 ++- external/squirrel/sqstdlib/sqstdaux.cpp | 11 +- external/squirrel/sqstdlib/sqstdblob.cpp | 36 +- external/squirrel/sqstdlib/sqstdblobimpl.h | 0 external/squirrel/sqstdlib/sqstdio.cpp | 37 +- external/squirrel/sqstdlib/sqstdmath.cpp | 7 +- external/squirrel/sqstdlib/sqstdrex.cpp | 19 +- external/squirrel/sqstdlib/sqstdstream.cpp | 22 +- external/squirrel/sqstdlib/sqstdstream.h | 0 external/squirrel/sqstdlib/sqstdstring.cpp | 29 +- external/squirrel/sqstdlib/sqstdsystem.cpp | 6 +- external/squirrel/squirrel/sqapi.cpp | 385 ++++++-- external/squirrel/squirrel/sqarray.h | 11 +- external/squirrel/squirrel/sqbaselib.cpp | 339 ++++++- external/squirrel/squirrel/sqclass.cpp | 43 +- external/squirrel/squirrel/sqclass.h | 20 +- external/squirrel/squirrel/sqclosure.h | 131 ++- external/squirrel/squirrel/sqcompiler.cpp | 894 +++++++++-------- external/squirrel/squirrel/sqcompiler.h | 8 +- external/squirrel/squirrel/sqdebug.cpp | 14 +- external/squirrel/squirrel/sqfuncproto.h | 38 +- external/squirrel/squirrel/sqfuncstate.cpp | 182 +++- external/squirrel/squirrel/sqfuncstate.h | 8 +- external/squirrel/squirrel/sqlexer.cpp | 41 +- external/squirrel/squirrel/sqlexer.h | 2 + external/squirrel/squirrel/sqmem.cpp | 0 external/squirrel/squirrel/sqobject.cpp | 170 +++- external/squirrel/squirrel/sqobject.h | 271 +++--- external/squirrel/squirrel/sqopcodes.h | 73 +- external/squirrel/squirrel/sqpcheader.h | 0 external/squirrel/squirrel/sqstate.cpp | 179 +++- external/squirrel/squirrel/sqstate.h | 19 +- external/squirrel/squirrel/sqstring.h | 0 external/squirrel/squirrel/sqtable.cpp | 37 +- external/squirrel/squirrel/sqtable.h | 1 + external/squirrel/squirrel/squserdata.h | 12 +- external/squirrel/squirrel/squtils.h | 11 +- external/squirrel/squirrel/sqvm.cpp | 1438 ++++++++++++++++------------ external/squirrel/squirrel/sqvm.h | 86 +- src/scripting/squirrel_util.cpp | 2 +- 49 files changed, 3195 insertions(+), 1752 deletions(-) mode change 100755 => 100644 external/squirrel/COPYRIGHT mode change 100755 => 100644 external/squirrel/HISTORY mode change 100755 => 100644 external/squirrel/README mode change 100755 => 100644 external/squirrel/include/sqstdaux.h mode change 100755 => 100644 external/squirrel/include/sqstdblob.h mode change 100755 => 100644 external/squirrel/include/sqstdio.h mode change 100755 => 100644 external/squirrel/include/sqstdmath.h mode change 100755 => 100644 external/squirrel/include/sqstdstring.h mode change 100755 => 100644 external/squirrel/include/sqstdsystem.h mode change 100755 => 100644 external/squirrel/include/squirrel.h mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdaux.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdblob.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdblobimpl.h mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdio.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdmath.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdrex.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdstream.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdstream.h mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdstring.cpp mode change 100755 => 100644 external/squirrel/sqstdlib/sqstdsystem.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqapi.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqarray.h mode change 100755 => 100644 external/squirrel/squirrel/sqbaselib.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqclass.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqclass.h mode change 100755 => 100644 external/squirrel/squirrel/sqclosure.h mode change 100755 => 100644 external/squirrel/squirrel/sqcompiler.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqcompiler.h mode change 100755 => 100644 external/squirrel/squirrel/sqdebug.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqfuncproto.h mode change 100755 => 100644 external/squirrel/squirrel/sqfuncstate.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqfuncstate.h mode change 100755 => 100644 external/squirrel/squirrel/sqlexer.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqlexer.h mode change 100755 => 100644 external/squirrel/squirrel/sqmem.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqobject.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqobject.h mode change 100755 => 100644 external/squirrel/squirrel/sqopcodes.h mode change 100755 => 100644 external/squirrel/squirrel/sqpcheader.h mode change 100755 => 100644 external/squirrel/squirrel/sqstate.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqstate.h mode change 100755 => 100644 external/squirrel/squirrel/sqstring.h mode change 100755 => 100644 external/squirrel/squirrel/sqtable.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqtable.h mode change 100755 => 100644 external/squirrel/squirrel/squserdata.h mode change 100755 => 100644 external/squirrel/squirrel/squtils.h mode change 100755 => 100644 external/squirrel/squirrel/sqvm.cpp mode change 100755 => 100644 external/squirrel/squirrel/sqvm.h diff --git a/external/squirrel/COPYRIGHT b/external/squirrel/COPYRIGHT old mode 100755 new mode 100644 index 2a20755b6..26a19974f --- a/external/squirrel/COPYRIGHT +++ b/external/squirrel/COPYRIGHT @@ -1,29 +1,21 @@ -Copyright (c) 2003-2011 Alberto Demichelis +Copyright (c) 2003-2012 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 hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -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: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 1. The origin of this software must not be - misrepresented; you must not claim that - you wrote the original software. If you - use this software in a product, an - acknowledgment in the product - documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly - marked as such, and must not be - misrepresented as being the original - software. - - 3. This notice may not be removed or - altered from any source distribution. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. ----------------------------------------------------- -END OF COPYRIGHT \ No newline at end of file +END OF COPYRIGHT diff --git a/external/squirrel/HISTORY b/external/squirrel/HISTORY old mode 100755 new mode 100644 index 31b8a8ff8..435d4f446 --- a/external/squirrel/HISTORY +++ b/external/squirrel/HISTORY @@ -1,47 +1,146 @@ -***version 2.2.5 stable*** --sq_getsize() now returns userdatasize for classes and instances --added parameter 'isstatic' to _newmember metamethod(thx G.Meyer) +***version 3.0.4 stable*** +-sq_deleteslot slot now pops the key in case of failure +-fixed bug when _get metamethod throws null +-fixed a bug in rstrip +-added some error handling +-minor bugfixes + +***2012-06-19 *** +***version 3.0.3 stable*** +-improved error messages for _cmp(when a non integer value is returned) (thx Yexo) +-added class.newmember() built in method (thx Nam) +-added class.rawnewmember() built in method (thx Nam) +-added sq_rawnewmember() (thx Nam) +-added sq_getversion() +-added sq_typeof() +-added sq_getclosurename() +-added file.close() in stdlib +-documented closure.getinfos() built-in method +-fixed string iteration doesn't return negative numbers for characters > 127 +-fixed bug in tofloat() when converting a string with scientific notation without a decimal point (thx wr2) +-fixed potential infinite loop in array.sort() when the _cmp function is inconsistent (thx Yexo) +-fixed obscure bug in the compiler(thx yishin) +-fixed some minor bug + +***2011-11-28 *** +***version 3.0.2 stable*** +-added sq_gethash API -now array.sort() is implemented with heapsort --added SQUIRREL_VERSION_NUMBER preprocessor definition -now floats in scientific notation also accept numbers with no '.' (eg. 1e+6 or 1e6) --fixed some compiler warning --fixed a minor compiler bug --fixed some bugs when SQUSEDOUBLE is used in 32bits systems +-fixed some warning +-fixed some documentation -fixed bug in GC -***2009-11-15 *** -***version 2.2.4 stable*** --fixed bug in functions with default parameters +***2011-09-08 *** +***version 3.0.1 stable*** +-added # as alternative symbol for "line comment"(mostly useful for shell scripts) +-added sq_throwobject() to throw an arbitrary object from the C API +-added alignement flag for userdata types, SQ_ALIGNMENT (thx Shigemasa) +-added rawset() and rawget() to class and instance default delegate +-changed bytecode format now ensures matching integer size and float size +-now inherited classes also inherit userdatasize +-added SQUIRREL_VERSION_NUMBER in squirrel.h and _versionnumber_ global symbol +-fixed sq_getmemberhandle +-fixed sq_getrefcount +-refactored some sqstdio code +-refactored some clone code +-refactored some stuff in the string lib +-added -s and -fno-exceptions in GCC makefile(better performance when using GCC) + +***2011-03-13 *** +***version 3.0 stable*** +-added sq_getcallee() +-sq_getfreevariable() also works for native closures +-minior optimizations +-removed several warning when compiling with GCC 4.x +-fixed some errors in the documentation +-fixed bug when using SQUSEDOUBLE and 32bits intengers +-fixed bug when invoking generators with closure.call() (thx huntercool) + +***2010-12-19 *** +***version 3.0 release candidate 1(RC 1)*** +-improved metamethods error handling +-added parameter 'isstatic' to _newmember metamethod(thx G.Meyer) +-added sq_getrefcount() to return number of refences from C++(thx G.Meyer) + +***2010-11-07 *** +***version 3.0 beta 3*** +-license changed to "MIT license" +-added sq_resurrectunreachable() and resurrectunreachable() +-added callee() built in function, returns the current running closure +-added thread.getstackinfos() +-added sq_objtouserpointer() +-added sq_newtableex() +-various refactoring and optimizations +-fixed several 64bits issues regarding integer to string conversions +-fixed some bugs when SQUSEDOUBLE is used in 32bits systems + +***2010-08-18 *** +***version 3.0 beta 2.1*** +-fixed bug in class constructor +-fixed bug in compound arith -***2009-06-30 *** -***version 2.2.3 stable*** +***2010-08-12 *** +***version 3.0 beta 2*** +-class methods can be added or replaced after the class as been instantiated +-JSON compliant table syntax, this is currently an experimental feature (thx atai) +-sq_getsize() now returns userdatasize for classes and instances +-now setroottable() and setconsttable() return the previous value of the respective table +-fixed bug in compound arith operators when used on a free variable (thx ellon) +-fixed some x64 minor bugs +-fixed minor bug in the compiler +-refactored some VM internals +-documented sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes + +***2009-11-15 *** +***version 3.0 beta 1*** +-various refactoring and optimizations +-fixed bug in free variables (thx mokehehe) +-fixed bug in functions with default parameters (thx ara & Yexo) +-fixed bug in exception handling +-improved error propagation in _set and _get metamethods ( and 'throw null' for clean failure) +-added sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes + +***2009-06-30 *** +***version 3.0 alpha 2*** +-added real free variables(thx Paul Ruizendaal) +-added refactored function call implementation and compiler(thx Paul Ruizendaal) -added sq_getfunctioninfo -added compile time flag SQUSEDOUBLE to use double precision floats -added global slot _floatsize_ int the base lib to recognize single precision and double precision builds -sq_wakeupvm can now resume the vm with an exception -added sqstd_format +-now blobs can be cloned -generators can now be instantiated by calling sq_call() or closure.call() --fixed a bug in sqstd_printcallstack(thx takayuki_h) --fixed modulo by zero(thx jup) --fixed negative enums and constants --fixed generator crash bug if invoked as tail call (thx Mr.Accident) --fixed some minor bug - -***2008-09-24 *** -***version 2.2.2 stable*** --fixed some behaviour inconsistencies in thread.call() and thread.wakeup() (thx Mr.Accident) --fixed coroutine error propagation --fixed lingering return value from native function (thx Tom Leonard) --fixed a bug if array.sort() is given a bad sort function (thx Tom Leonard) --fixed some minor api bug +-fixed debughook bug +-fixed cooroutine error propagation + +***2008-07-23 *** +***version 3.0 alpha 1*** +-first branch from 2.x source tree +-added 'base' keyword +-removed 'delegate' keyword +-now compiled scripts are vararg functions +-added setdelegate() and getdelegate() table builtin methods +-added <=> 3 ways compare operator +-added lambda expression @(a,b) a + b +-added local function statement +-added array built-in map(),reduce(),apply(),filter() and find() +-generators hold only a weak reference of the enviroment object +-removed 'vargv' and 'vargc' keywords +-now var args are passed as an array called vargv(as a paramter) +-removed 'parent' keyword +-added class getbase() built in method +-instanceof doesn't throw an exception if the left expression is not a class +-lexical scoping for free variables(free variables are no longer in the second parameter list) +-sq_setprintfunc accept error func +-sq_geterrorfunc() -added sq_arrayremove() and sq_arrayinsert() +-error() built in function(works like print but prints using the errorfunc) +-added native debug hook -***2008-05-16 *** -***version 2.2.1 stable*** --fixed a tailcall bug - -***2008-02-17 *** -***version 2.2 stable *** +***2008-02-17 *** +***version 2.2 stable*** -added _newslot metamethod in classes -added enums added constants -added sq_pushconsttable, sq_setconsttable @@ -61,7 +160,7 @@ will terminate the iteration but will not be returned as foreach iteration -fixed sq_cmp() (thx jyuill) -fixed minor bugs -***2006-08-21 *** +***2006-08-21 *** ***version 2.1.1 stable*** -vm refactoring -optimized internal function memory layout @@ -180,7 +279,7 @@ will terminate the iteration but will not be returned as foreach iteration ***2004-11-01 *** ***version 1.0 stable*** -fixed some minor bug --improoved operator 'delete' performances +-improved operator 'delete' performances -added scientific notation for float numbers( eg. 2.e16 or 2.e-2) ***2004-08-30 *** @@ -284,7 +383,7 @@ will terminate the iteration but will not be returned as foreach iteration -fixed a garbage collection bug -fixed == operator now can compare correctly different types -new built in method getstackinfos(level) --improoved line informations precision for the debug hook +-improved line informations precision for the debug hook -new api call sq_compilebuffer() -new built-in api function compilestring() -new syntactic sugar for function declarations inside tables diff --git a/external/squirrel/README b/external/squirrel/README old mode 100755 new mode 100644 index 2d1e00000..803b26aa1 --- a/external/squirrel/README +++ b/external/squirrel/README @@ -1,20 +1,21 @@ -The programming language SQUIRREL 2.2.5 stable +The programming language SQUIRREL 3.0 stable -------------------------------------------------- -The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and -Linux(Slackware 9.0 on Intel x86, Fedora Core 4 on AMD x64). +The project has been compiled and run on Windows(x86 and x64) and +Linux(x86 and x64) and Solaris(x86 and x64). Has been tested with the following compilers: - MS Visual C++ 6.0,7.0,7.1 and 8.0 (32 and 64bits) + MS Visual C++ 6.0,7.0,7.1,8.0,9.0,10.0 (32 and 64bits) MinGW gcc 3.2 (mingw special 20020817-1) Cygnus gcc 3.2 Linux gcc 3.2.3 - Linux gcc 4.0.0 (x86 64bits) + Linux gcc 4.0.0 (x86 & 64bits) + Solaris gcc 4.0.0 (x86 & 64bits) Feedback and suggestions are appreciated project page - http://www.squirrel-lang.org -community forums - http://www.squirrel-lang.org/Forums +community forums - http://forum.squirrel-lang.org wiki - http://wiki.squirrel-lang.org author - alberto@demichelis.net diff --git a/external/squirrel/include/sqstdaux.h b/external/squirrel/include/sqstdaux.h old mode 100755 new mode 100644 diff --git a/external/squirrel/include/sqstdblob.h b/external/squirrel/include/sqstdblob.h old mode 100755 new mode 100644 diff --git a/external/squirrel/include/sqstdio.h b/external/squirrel/include/sqstdio.h old mode 100755 new mode 100644 index 864b4f1de..1174201a9 --- a/external/squirrel/include/sqstdio.h +++ b/external/squirrel/include/sqstdio.h @@ -7,7 +7,6 @@ #define SQSTD_STREAM_TYPE_TAG 0x80000000 struct SQStream { - virtual ~SQStream() {} virtual SQInteger Read(void *buffer, SQInteger size) = 0; virtual SQInteger Write(void *buffer, SQInteger size) = 0; virtual SQInteger Flush() = 0; diff --git a/external/squirrel/include/sqstdmath.h b/external/squirrel/include/sqstdmath.h old mode 100755 new mode 100644 diff --git a/external/squirrel/include/sqstdstring.h b/external/squirrel/include/sqstdstring.h old mode 100755 new mode 100644 diff --git a/external/squirrel/include/sqstdsystem.h b/external/squirrel/include/sqstdsystem.h old mode 100755 new mode 100644 diff --git a/external/squirrel/include/squirrel.h b/external/squirrel/include/squirrel.h old mode 100755 new mode 100644 index df1f7fe0a..da3a4d1ce --- a/external/squirrel/include/squirrel.h +++ b/external/squirrel/include/squirrel.h @@ -1,32 +1,23 @@ /* -Copyright (c) 2003-2011 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. - +Copyright (c) 2003-2012 Alberto Demichelis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ #ifndef _SQUIRREL_H_ #define _SQUIRREL_H_ @@ -45,21 +36,23 @@ extern "C" { #endif #endif - #ifdef _SQ64 + #ifdef _MSC_VER typedef __int64 SQInteger; typedef unsigned __int64 SQUnsignedInteger; typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/ #else -typedef long SQInteger; -typedef unsigned long SQUnsignedInteger; -typedef unsigned long SQHash; /*should be the same size of a pointer*/ +typedef long long SQInteger; +typedef unsigned long long SQUnsignedInteger; +typedef unsigned long long SQHash; /*should be the same size of a pointer*/ #endif typedef int SQInt32; +typedef unsigned int SQUnsignedInteger32; #else typedef int SQInteger; typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/ +typedef unsigned int SQUnsignedInteger32; /*must be 32 bits(also on 64bits processors)*/ typedef unsigned int SQUnsignedInteger; typedef unsigned int SQHash; /*should be the same size of a pointer*/ #endif @@ -83,6 +76,14 @@ typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64 #define SQ_OBJECT_RAWINIT() #endif +#ifndef SQ_ALIGNMENT // SQ_ALIGNMENT shall be less than or equal to SQ_MALLOC alignments, and its value shall be power of 2. +#if defined(SQUSEDOUBLE) || defined(_SQ64) +#define SQ_ALIGNMENT 8 +#else +#define SQ_ALIGNMENT 4 +#endif +#endif + typedef void* SQUserPointer; typedef SQUnsignedInteger SQBool; typedef SQInteger SQRESULT; @@ -103,6 +104,7 @@ struct SQRefCounted; struct SQClass; struct SQInstance; struct SQDelegable; +struct SQOuter; #ifdef _UNICODE #define SQUNICODE @@ -111,7 +113,7 @@ struct SQDelegable; #ifdef SQUNICODE #if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8 -#if defined(wchar_t) //this is if the compiler considers wchar_t as native type +#if !defined(_NATIVE_WCHAR_T_DEFINED) //this is if the compiler considers wchar_t as native type #define wchar_t unsigned short #endif @@ -125,7 +127,11 @@ typedef wchar_t SQChar; #define scsprintf swprintf #define scstrlen wcslen #define scstrtod wcstod +#ifdef _SQ64 +#define scstrtol _wcstoi64 +#else #define scstrtol wcstol +#endif #define scatoi _wtoi #define scstrtoul wcstoul #define scvsprintf vswprintf @@ -145,7 +151,15 @@ typedef char SQChar; #define scsprintf sprintf #define scstrlen strlen #define scstrtod strtod +#ifdef _SQ64 +#ifdef _MSC_VER +#define scstrtol _strtoi64 +#else +#define scstrtol strtoll +#endif +#else #define scstrtol strtol +#endif #define scatoi atoi #define scstrtoul strtoul #define scvsprintf vsprintf @@ -160,10 +174,17 @@ typedef char SQChar; #define MAX_CHAR 0xFF #endif -#define SQUIRREL_VERSION _SC("Squirrel 2.2.5 stable") -#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2010 Alberto Demichelis") +#ifdef _SQ64 +#define _PRINT_INT_PREC _SC("ll") +#define _PRINT_INT_FMT _SC("%lld") +#else +#define _PRINT_INT_FMT _SC("%d") +#endif + +#define SQUIRREL_VERSION _SC("Squirrel 3.0.4 stable") +#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2012 Alberto Demichelis") #define SQUIRREL_AUTHOR _SC("Alberto Demichelis") -#define SQUIRREL_VERSION_NUMBER 225 +#define SQUIRREL_VERSION_NUMBER 304 #define SQ_VMSTATE_IDLE 0 #define SQ_VMSTATE_RUNNING 1 @@ -199,6 +220,7 @@ typedef char SQChar; #define _RT_CLASS 0x00004000 #define _RT_INSTANCE 0x00008000 #define _RT_WEAKREF 0x00010000 +#define _RT_OUTER 0x00020000 typedef enum tagSQObjectType{ OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), @@ -217,7 +239,8 @@ typedef enum tagSQObjectType{ OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED) + OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED), + OT_OUTER = (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only }SQObjectType; #define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED) @@ -228,6 +251,7 @@ typedef union tagSQObjectValue struct SQTable *pTable; struct SQArray *pArray; struct SQClosure *pClosure; + struct SQOuter *pOuter; struct SQGenerator *pGenerator; struct SQNativeClosure *pNativeClosure; struct SQString *pString; @@ -252,6 +276,11 @@ typedef struct tagSQObject SQObjectValue _unVal; }SQObject; +typedef struct tagSQMemberHandle{ + SQBool _static; + SQInteger _index; +}SQMemberHandle; + typedef struct tagSQStackInfos{ const SQChar* funcname; const SQChar* source; @@ -260,11 +289,12 @@ typedef struct tagSQStackInfos{ typedef struct SQVM* HSQUIRRELVM; typedef SQObject HSQOBJECT; +typedef SQMemberHandle HSQMEMBERHANDLE; typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM); typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/); typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...); - +typedef void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/); typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger); typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger); @@ -283,7 +313,6 @@ typedef struct tagSQFunctionInfo { const SQChar *source; }SQFunctionInfo; - /*vm*/ SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize); SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize); @@ -291,11 +320,13 @@ SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v); SQUIRREL_API void sq_close(HSQUIRRELVM v); SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p); SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v); -SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc); +SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc); SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v); +SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v); SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v); SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror); SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v); +SQUIRREL_API SQInteger sq_getversion(); /*compiler*/ SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror); @@ -311,13 +342,14 @@ SQUIRREL_API void sq_poptop(HSQUIRRELVM v); SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v); SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop); -SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize); +SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize); SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v); SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx); /*object creation handling*/ SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size); SQUIRREL_API void sq_newtable(HSQUIRRELVM v); +SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity); SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size); SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars); SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask); @@ -329,10 +361,12 @@ SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b); SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p); SQUIRREL_API void sq_pushnull(HSQUIRRELVM v); SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx); SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v); -SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b); SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c); SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i); @@ -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); SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook); SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize); -SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger idx,SQFunctionInfo *fi); +SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi); SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars); +SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name); SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p); SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag); @@ -358,6 +393,9 @@ SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t); +SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle); +SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle); +SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle); /*object manipulation*/ SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v); @@ -372,6 +410,8 @@ SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic); +SQUIRREL_API SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic); SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); @@ -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); SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror); SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx); +SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v); SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err); +SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v); SQUIRREL_API void sq_reseterror(HSQUIRRELVM v); SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v); @@ -400,15 +442,18 @@ SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po); SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj); SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po); SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po); +SQUIRREL_API SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po); SQUIRREL_API void sq_resetobject(HSQOBJECT *po); -SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o); -SQUIRREL_API SQBool sq_objtobool(HSQOBJECT *o); -SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o); -SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o); -SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag); +SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o); +SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o); +SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o); +SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o); +SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o); +SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag); /*GC*/ SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v); /*serialization*/ SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up); @@ -422,6 +467,7 @@ SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size); /*debug*/ SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si); SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v); +SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook); /*UTILITY MACRO*/ #define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC) diff --git a/external/squirrel/sqstdlib/sqstdaux.cpp b/external/squirrel/sqstdlib/sqstdaux.cpp old mode 100755 new mode 100644 index 5b8763990..e115770a8 --- a/external/squirrel/sqstdlib/sqstdaux.cpp +++ b/external/squirrel/sqstdlib/sqstdaux.cpp @@ -5,11 +5,10 @@ void sqstd_printcallstack(HSQUIRRELVM v) { - SQPRINTFUNCTION pf = sq_getprintfunc(v); + SQPRINTFUNCTION pf = sq_geterrorfunc(v); if(pf) { SQStackInfos si; SQInteger i; - SQBool b; SQFloat f; const SQChar *s; SQInteger level=1; //1 is to skip this function that is level 0 @@ -84,8 +83,8 @@ void sqstd_printcallstack(HSQUIRRELVM v) pf(v,_SC("[%s] WEAKREF\n"),name); break; case OT_BOOL:{ - sq_getbool(v,-1,&b); - pf(v,_SC("[%s] %s\n"),name,b?_SC("true"):_SC("false")); + sq_getinteger(v,-1,&i); + pf(v,_SC("[%s] %s\n"),name,i?_SC("true"):_SC("false")); } break; default: assert(0); break; @@ -98,7 +97,7 @@ void sqstd_printcallstack(HSQUIRRELVM v) static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v) { - SQPRINTFUNCTION pf = sq_getprintfunc(v); + SQPRINTFUNCTION pf = sq_geterrorfunc(v); if(pf) { const SQChar *sErr = 0; if(sq_gettop(v)>=1) { @@ -116,7 +115,7 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v) void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column) { - SQPRINTFUNCTION pf = sq_getprintfunc(v); + SQPRINTFUNCTION pf = sq_geterrorfunc(v); if(pf) { pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr); } diff --git a/external/squirrel/sqstdlib/sqstdblob.cpp b/external/squirrel/sqstdlib/sqstdblob.cpp old mode 100755 new mode 100644 index 05ef8d92a..59cff0df1 --- a/external/squirrel/sqstdlib/sqstdblob.cpp +++ b/external/squirrel/sqstdlib/sqstdblob.cpp @@ -15,7 +15,9 @@ #define SETUP_BLOB(v) \ SQBlob *self = NULL; \ { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ - return SQ_ERROR; } + return sq_throwerror(v,_SC("invalid type tag")); } \ + if(!self || !self->IsValid()) \ + return sq_throwerror(v,_SC("the blob is invalid")); static SQInteger _blob_resize(HSQUIRRELVM v) @@ -115,7 +117,8 @@ static SQInteger _blob__typeof(HSQUIRRELVM v) static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size) { SQBlob *self = (SQBlob*)p; - delete self; + self->~SQBlob(); + sq_free(self,sizeof(SQBlob)); return 1; } @@ -127,10 +130,32 @@ static SQInteger _blob_constructor(HSQUIRRELVM v) sq_getinteger(v, 2, &size); } if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); - SQBlob *b = new SQBlob(size); + //SQBlob *b = new SQBlob(size); + + SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size); if(SQ_FAILED(sq_setinstanceup(v,1,b))) { - delete b; - return sq_throwerror(v, _SC("cannot create blob with negative size")); + b->~SQBlob(); + sq_free(b,sizeof(SQBlob)); + return sq_throwerror(v, _SC("cannot create blob")); + } + sq_setreleasehook(v,1,_blob_releasehook); + return 0; +} + +static SQInteger _blob__cloned(HSQUIRRELVM v) +{ + SQBlob *other = NULL; + { + if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + return SQ_ERROR; + } + //SQBlob *thisone = new SQBlob(other->Len()); + SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len()); + memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len()); + if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) { + thisone->~SQBlob(); + sq_free(thisone,sizeof(SQBlob)); + return sq_throwerror(v, _SC("cannot clone blob")); } sq_setreleasehook(v,1,_blob_releasehook); return 0; @@ -146,6 +171,7 @@ static SQRegFunction _blob_methods[] = { _DECL_BLOB_FUNC(_get,2,_SC("xn")), _DECL_BLOB_FUNC(_typeof,1,_SC("x")), _DECL_BLOB_FUNC(_nexti,2,_SC("x")), + _DECL_BLOB_FUNC(_cloned,2,_SC("xx")), {0,0,0,0} }; diff --git a/external/squirrel/sqstdlib/sqstdblobimpl.h b/external/squirrel/sqstdlib/sqstdblobimpl.h old mode 100755 new mode 100644 diff --git a/external/squirrel/sqstdlib/sqstdio.cpp b/external/squirrel/sqstdlib/sqstdio.cpp old mode 100755 new mode 100644 index 2d0d44279..b365a07ca --- a/external/squirrel/sqstdlib/sqstdio.cpp +++ b/external/squirrel/sqstdlib/sqstdio.cpp @@ -117,7 +117,8 @@ static SQInteger _file__typeof(HSQUIRRELVM v) static SQInteger _file_releasehook(SQUserPointer p, SQInteger size) { SQFile *self = (SQFile*)p; - delete self; + self->~SQFile(); + sq_free(self,sizeof(SQFile)); return 1; } @@ -138,20 +139,34 @@ static SQInteger _file_constructor(HSQUIRRELVM v) } else { return sq_throwerror(v,_SC("wrong parameter")); } - f = new SQFile(newf,owns); + + f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns); if(SQ_FAILED(sq_setinstanceup(v,1,f))) { - delete f; + f->~SQFile(); + sq_free(f,sizeof(SQFile)); return sq_throwerror(v, _SC("cannot create blob with negative size")); } sq_setreleasehook(v,1,_file_releasehook); return 0; } +static SQInteger _file_close(HSQUIRRELVM v) +{ + SQFile *self = NULL; + if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG)) + && self != NULL) + { + self->Close(); + } + return 0; +} + //bindings #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck} static SQRegFunction _file_methods[] = { _DECL_FILE_FUNC(constructor,3,_SC("x")), _DECL_FILE_FUNC(_typeof,1,_SC("x")), + _DECL_FILE_FUNC(close,1,_SC("x")), {0,0,0,0}, }; @@ -193,7 +208,7 @@ SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file) -static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file) +static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer file) { SQInteger ret; char c; @@ -202,6 +217,7 @@ static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file) return 0; } +#ifdef SQUNICODE static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file) { #define READ() \ @@ -238,6 +254,7 @@ static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file) } return c; } +#endif static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file) { @@ -277,7 +294,7 @@ SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror) SQInteger ret; unsigned short us; unsigned char uc; - SQLEXREADFUNC func = _io_file_lexfeed_ASCII; + SQLEXREADFUNC func = _io_file_lexfeed_PLAIN; if(file){ ret = sqstd_fread(&us,1,2,file); if(ret != 2) { @@ -306,7 +323,11 @@ SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror) sqstd_fclose(file); return sq_throwerror(v,_SC("Unrecognozed ecoding")); } +#ifdef SQUNICODE func = _io_file_lexfeed_UTF8; +#else + func = _io_file_lexfeed_PLAIN; +#endif break;//UTF-8 ; default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii } @@ -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); sq_pushstring(v,_SC("stdout"),-1); sqstd_createfile(v,stdout,SQFalse); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_pushstring(v,_SC("stdin"),-1); sqstd_createfile(v,stdin,SQFalse); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_pushstring(v,_SC("stderr"),-1); sqstd_createfile(v,stderr,SQFalse); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_settop(v,top); return SQ_OK; } diff --git a/external/squirrel/sqstdlib/sqstdmath.cpp b/external/squirrel/sqstdlib/sqstdmath.cpp old mode 100755 new mode 100644 index c54a7dc44..ef50359bd --- a/external/squirrel/sqstdlib/sqstdmath.cpp +++ b/external/squirrel/sqstdlib/sqstdmath.cpp @@ -80,6 +80,7 @@ static SQRegFunction mathlib_funcs[] = { _DECL_FUNC(abs,2,_SC(".n")), {0,0}, }; +#undef _DECL_FUNC #ifndef M_PI #define M_PI (3.14159265358979323846) @@ -93,14 +94,14 @@ SQRESULT sqstd_register_mathlib(HSQUIRRELVM v) sq_newclosure(v,mathlib_funcs[i].f,0); sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); sq_setnativeclosurename(v,-1,mathlib_funcs[i].name); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } sq_pushstring(v,_SC("RAND_MAX"),-1); sq_pushinteger(v,RAND_MAX); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_pushstring(v,_SC("PI"),-1); sq_pushfloat(v,(SQFloat)M_PI); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); return SQ_OK; } diff --git a/external/squirrel/sqstdlib/sqstdrex.cpp b/external/squirrel/sqstdlib/sqstdrex.cpp old mode 100755 new mode 100644 index 8eebb2716..20aa57d9b --- a/external/squirrel/sqstdlib/sqstdrex.cpp +++ b/external/squirrel/sqstdlib/sqstdrex.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "sqstdstring.h" +#include #ifdef _UINCODE #define scisprint iswprint @@ -263,7 +263,6 @@ static SQInteger sqstd_rex_element(SQRex *exp) } - SQInteger op; SQBool isgreedy = SQFalse; unsigned short p0 = 0, p1 = 0; switch(*exp->_p){ @@ -297,7 +296,6 @@ static SQInteger sqstd_rex_element(SQRex *exp) } if(isgreedy) { SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY); - op = OP_GREEDY; exp->_nodes[nnode].left = ret; exp->_nodes[nnode].right = ((p0)<<16)|p1; ret = nnode; @@ -461,7 +459,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar exp->_matches[capture].begin = cur; exp->_currsubexp++; } - + int tempcap = exp->_currsubexp; do { SQRexNode *subnext = NULL; if(n->next != -1) { @@ -478,12 +476,13 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar } } while((n->next != -1) && (n = &exp->_nodes[n->next])); + exp->_currsubexp = tempcap; if(capture != -1) exp->_matches[capture].len = cur - exp->_matches[capture].begin; return cur; } case OP_WB: - if(str == exp->_bol && !isspace(*str) + if((str == exp->_bol && !isspace(*str)) || (str == exp->_eol && !isspace(*(str-1))) || (!isspace(*str) && isspace(*(str+1))) || (isspace(*str) && !isspace(*(str+1))) ) { @@ -497,25 +496,25 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar if(str == exp->_eol) return str; return NULL; case OP_DOT:{ - *str++; + str++; } return str; case OP_NCLASS: case OP_CLASS: if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { - *str++; + str++; return str; } return NULL; case OP_CCLASS: if(sqstd_rex_matchcclass(node->left,*str)) { - *str++; + str++; return str; } return NULL; default: /* char */ if(*str != node->type) return NULL; - *str++; + str++; return str; } return NULL; @@ -605,7 +604,7 @@ SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* t break; node = exp->_nodes[node].next; } - *text_begin++; + text_begin++; } while(cur == NULL && text_begin != text_end); if(cur == NULL) diff --git a/external/squirrel/sqstdlib/sqstdstream.cpp b/external/squirrel/sqstdlib/sqstdstream.cpp old mode 100755 new mode 100644 index 606a9b868..1b7a08f95 --- a/external/squirrel/sqstdlib/sqstdstream.cpp +++ b/external/squirrel/sqstdlib/sqstdstream.cpp @@ -13,7 +13,7 @@ SQStream *self = NULL; \ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \ return sq_throwerror(v,_SC("invalid type tag")); \ - if(!self->IsValid()) \ + if(!self || !self->IsValid()) \ return sq_throwerror(v,_SC("the stream is invalid")); SQInteger _stream_readblob(HSQUIRRELVM v) @@ -233,6 +233,11 @@ SQInteger _stream_eos(HSQUIRRELVM v) return 1; } + SQInteger _stream__cloned(HSQUIRRELVM v) + { + return sq_throwerror(v,_SC("this object cannot be cloned")); + } + static SQRegFunction _stream_methods[] = { _DECL_STREAM_FUNC(readblob,2,_SC("xn")), _DECL_STREAM_FUNC(readn,2,_SC("xn")), @@ -243,6 +248,7 @@ static SQRegFunction _stream_methods[] = { _DECL_STREAM_FUNC(len,1,_SC("x")), _DECL_STREAM_FUNC(eos,1,_SC("x")), _DECL_STREAM_FUNC(flush,1,_SC("x")), + _DECL_STREAM_FUNC(_cloned,0,NULL), {0,0} }; @@ -260,15 +266,15 @@ void init_streamclass(HSQUIRRELVM v) sq_pushstring(v,f.name,-1); sq_newclosure(v,f.f,0); sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_pushroottable(v); sq_pushstring(v,_SC("stream"),-1); sq_pushstring(v,_SC("std_stream"),-1); sq_get(v,-4); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_pop(v,1); } else { @@ -297,10 +303,10 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c sq_newclosure(v,f.f,0); sq_setparamscheck(v,f.nparamscheck,f.typemask); sq_setnativeclosurename(v,-1,f.name); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_pop(v,1); i = 0; @@ -311,7 +317,7 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c sq_newclosure(v,f.f,0); sq_setparamscheck(v,f.nparamscheck,f.typemask); sq_setnativeclosurename(v,-1,f.name); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } //register the class in the target table @@ -320,7 +326,7 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c sq_pushstring(v,reg_name,-1); sq_get(v,-2); sq_remove(v,-2); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); sq_settop(v,top); return SQ_OK; diff --git a/external/squirrel/sqstdlib/sqstdstream.h b/external/squirrel/sqstdlib/sqstdstream.h old mode 100755 new mode 100644 diff --git a/external/squirrel/sqstdlib/sqstdstring.cpp b/external/squirrel/sqstdlib/sqstdstring.cpp old mode 100755 new mode 100644 index af842373d..33316faa4 --- a/external/squirrel/sqstdlib/sqstdstring.cpp +++ b/external/squirrel/sqstdlib/sqstdstring.cpp @@ -65,7 +65,6 @@ static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, return n; } - SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output) { const SQChar *format; @@ -103,7 +102,21 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); valtype = 's'; break; - case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X': + case 'i': case 'd': case 'o': case 'u': case 'x': case 'X': +#ifdef _SQ64 + { + size_t flen = scstrlen(fmt); + SQInteger fpos = flen - 1; + SQChar f = fmt[fpos]; + SQChar *prec = (SQChar *)_PRINT_INT_PREC; + while(*prec != _SC('\0')) { + fmt[fpos++] = *prec++; + } + fmt[fpos++] = f; + fmt[fpos++] = _SC('\0'); + } +#endif + case 'c': if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) return sq_throwerror(v,_SC("integer expected for the specified format")); addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); @@ -159,8 +172,8 @@ static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end) return; } const SQChar *t = &str[len-1]; - while(t != str && scisspace(*t)) { t--; } - *end = t+1; + while(t >= str && scisspace(*t)) { t--; } + *end = t + 1; } static SQInteger _string_strip(HSQUIRRELVM v) @@ -321,6 +334,7 @@ static SQRegFunction rexobj_funcs[]={ _DECL_REX_FUNC(_typeof,1,_SC("x")), {0,0} }; +#undef _DECL_REX_FUNC #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask} static SQRegFunction stringlib_funcs[]={ @@ -331,6 +345,7 @@ static SQRegFunction stringlib_funcs[]={ _DECL_FUNC(split,3,_SC(".ss")), {0,0} }; +#undef _DECL_FUNC SQInteger sqstd_register_stringlib(HSQUIRRELVM v) @@ -344,10 +359,10 @@ SQInteger sqstd_register_stringlib(HSQUIRRELVM v) sq_newclosure(v,f.f,0); sq_setparamscheck(v,f.nparamscheck,f.typemask); sq_setnativeclosurename(v,-1,f.name); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i = 0; while(stringlib_funcs[i].name!=0) @@ -356,7 +371,7 @@ SQInteger sqstd_register_stringlib(HSQUIRRELVM v) sq_newclosure(v,stringlib_funcs[i].f,0); sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask); sq_setnativeclosurename(v,-1,stringlib_funcs[i].name); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } return 1; diff --git a/external/squirrel/sqstdlib/sqstdsystem.cpp b/external/squirrel/sqstdlib/sqstdsystem.cpp old mode 100755 new mode 100644 index c7153a67c..40f78d785 --- a/external/squirrel/sqstdlib/sqstdsystem.cpp +++ b/external/squirrel/sqstdlib/sqstdsystem.cpp @@ -122,14 +122,14 @@ static SQInteger _system_date(HSQUIRRELVM v) static SQRegFunction systemlib_funcs[]={ _DECL_FUNC(getenv,2,_SC(".s")), _DECL_FUNC(system,2,_SC(".s")), - _DECL_FUNC(clock,1,NULL), + _DECL_FUNC(clock,0,NULL), _DECL_FUNC(time,1,NULL), _DECL_FUNC(date,-1,_SC(".nn")), _DECL_FUNC(remove,2,_SC(".s")), _DECL_FUNC(rename,3,_SC(".ss")), {0,0} }; - +#undef _DECL_FUNC SQInteger sqstd_register_systemlib(HSQUIRRELVM v) { @@ -140,7 +140,7 @@ SQInteger sqstd_register_systemlib(HSQUIRRELVM v) sq_newclosure(v,systemlib_funcs[i].f,0); sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); - sq_createslot(v,-3); + sq_newslot(v,-3,SQFalse); i++; } return 1; diff --git a/external/squirrel/squirrel/sqapi.cpp b/external/squirrel/squirrel/sqapi.cpp old mode 100755 new mode 100644 index a62990938..5b1d872cd --- a/external/squirrel/squirrel/sqapi.cpp +++ b/external/squirrel/squirrel/sqapi.cpp @@ -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; }\ } -SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e) -{ - v->_lasterror = e; - return SQ_ERROR; -} SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type) { @@ -98,11 +93,20 @@ void sq_seterrorhandler(HSQUIRRELVM v) } } +void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook) +{ + v->_debughook_native = hook; + v->_debughook_closure.Null(); + v->_debughook = hook?true:false; +} + void sq_setdebughook(HSQUIRRELVM v) { SQObject o = stack_get(v,-1); if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { - v->_debughook = o; + v->_debughook_closure = o; + v->_debughook_native = NULL; + v->_debughook = !sq_isnull(o); v->Pop(); } } @@ -114,14 +118,23 @@ void sq_close(HSQUIRRELVM v) sq_delete(ss, SQSharedState); } +SQInteger sq_getversion() +{ + return SQUIRREL_VERSION_NUMBER; +} + SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) { SQObjectPtr o; +#ifndef NO_COMPILER if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { v->Push(SQClosure::Create(_ss(v), _funcproto(o))); return SQ_OK; } return SQ_ERROR; +#else + return sq_throwerror(v,_SC("this is a no compiler build")); +#endif } void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable) @@ -144,18 +157,29 @@ void sq_addref(HSQUIRRELVM v,HSQOBJECT *po) #endif } +SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po) +{ + if(!ISREFCOUNTED(type(*po))) return 0; +#ifdef NO_GARBAGE_COLLECTOR + return po->_unVal.pRefCounted->_uiRef; +#else + return _ss(v)->_refs_table.GetRefCount(*po); +#endif +} + SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po) { if(!ISREFCOUNTED(type(*po))) return SQTrue; #ifdef NO_GARBAGE_COLLECTOR + bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse; __Release(po->_type,po->_unVal); - return SQFalse; //the ret val doesn't work(and cannot be fixed) + return ret; //the ret val doesn't work(and cannot be fixed) #else return _ss(v)->_refs_table.Release(*po); #endif } -const SQChar *sq_objtostring(HSQOBJECT *o) +const SQChar *sq_objtostring(const HSQOBJECT *o) { if(sq_type(*o) == OT_STRING) { return _stringval(*o); @@ -163,7 +187,7 @@ const SQChar *sq_objtostring(HSQOBJECT *o) return NULL; } -SQInteger sq_objtointeger(HSQOBJECT *o) +SQInteger sq_objtointeger(const HSQOBJECT *o) { if(sq_isnumeric(*o)) { return tointeger(*o); @@ -171,7 +195,7 @@ SQInteger sq_objtointeger(HSQOBJECT *o) return 0; } -SQFloat sq_objtofloat(HSQOBJECT *o) +SQFloat sq_objtofloat(const HSQOBJECT *o) { if(sq_isnumeric(*o)) { return tofloat(*o); @@ -179,7 +203,7 @@ SQFloat sq_objtofloat(HSQOBJECT *o) return 0; } -SQBool sq_objtobool(HSQOBJECT *o) +SQBool sq_objtobool(const HSQOBJECT *o) { if(sq_isbool(*o)) { return _integer(*o); @@ -187,16 +211,24 @@ SQBool sq_objtobool(HSQOBJECT *o) return SQFalse; } +SQUserPointer sq_objtouserpointer(const HSQOBJECT *o) +{ + if(sq_isuserpointer(*o)) { + return _userpointer(*o); + } + return 0; +} + void sq_pushnull(HSQUIRRELVM v) { - v->Push(_null_); + v->PushNull(); } void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len) { if(s) v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); - else v->Push(_null_); + else v->PushNull(); } void sq_pushinteger(HSQUIRRELVM v,SQInteger n) @@ -223,7 +255,7 @@ SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size) { SQUserData *ud = SQUserData::Create(_ss(v), size); v->Push(ud); - return ud->_val; + return (SQUserPointer)sq_aligning(ud + 1); } void sq_newtable(HSQUIRRELVM v) @@ -231,6 +263,11 @@ void sq_newtable(HSQUIRRELVM v) v->Push(SQTable::Create(_ss(v), 0)); } +void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity) +{ + v->Push(SQTable::Create(_ss(v), initialcapacity)); +} + void sq_newarray(HSQUIRRELVM v,SQInteger size) { v->Push(SQArray::Create(_ss(v), size)); @@ -266,7 +303,7 @@ SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx) SQObjectPtr *arr; _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); _array(*arr)->Append(v->GetUp(-1)); - v->Pop(1); + v->Pop(); return SQ_OK; } @@ -334,13 +371,12 @@ SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos) return ret; } - void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) { - SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func); + SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars); nc->_nparamscheck = 0; for(SQUnsignedInteger i = 0; i < nfreevars; i++) { - nc->_outervalues.push_back(v->Top()); + nc->_outervalues[i] = v->Top(); v->Pop(); } v->Push(SQObjectPtr(nc)); @@ -349,11 +385,18 @@ void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars) { SQObject o = stack_get(v, idx); - if(sq_isclosure(o)) { + if(type(o) == OT_CLOSURE) { SQClosure *c = _closure(o); - SQFunctionProto *proto = _funcproto(c->_function); + SQFunctionProto *proto = c->_function; *nparams = (SQUnsignedInteger)proto->_nparameters; - *nfreevars = (SQUnsignedInteger)c->_outervalues.size(); + *nfreevars = (SQUnsignedInteger)proto->_noutervalues; + return SQ_OK; + } + else if(type(o) == OT_NATIVECLOSURE) + { + SQNativeClosure *c = _nativeclosure(o); + *nparams = (SQUnsignedInteger)c->_nparamscheck; + *nfreevars = c->_noutervalues; return SQ_OK; } return sq_throwerror(v,_SC("the object is not a closure")); @@ -403,16 +446,24 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) !sq_isclass(env) && !sq_isinstance(env)) return sq_throwerror(v,_SC("invalid environment")); - SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env)); + SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env)); SQObjectPtr ret; if(sq_isclosure(o)) { SQClosure *c = _closure(o)->Clone(); + __ObjRelease(c->_env); c->_env = w; + __ObjAddRef(c->_env); + if(_closure(o)->_base) { + c->_base = _closure(o)->_base; + __ObjAddRef(c->_base); + } ret = c; } else { //then must be a native closure SQNativeClosure *c = _nativeclosure(o)->Clone(); + __ObjRelease(c->_env); c->_env = w; + __ObjAddRef(c->_env); ret = c; } v->Pop(); @@ -420,6 +471,22 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) return SQ_OK; } +SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + if(!sq_isnativeclosure(o) && + !sq_isclosure(o)) + return sq_throwerror(v,_SC("the target is not a closure")); + if(sq_isnativeclosure(o)) + { + v->Push(_nativeclosure(o)->_name); + } + else { //closure + v->Push(_closure(o)->_function->_name); + } + return SQ_OK; +} + SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx) { SQObject &o=stack_get(v,idx); @@ -491,19 +558,32 @@ SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx) return type(stack_get(v, idx)); } +SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + SQObjectPtr res; + if(!v->TypeOf(o,res)) { + return SQ_ERROR; + } + v->Push(res); + return SQ_OK; +} -void sq_tostring(HSQUIRRELVM v,SQInteger idx) +SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &o = stack_get(v, idx); SQObjectPtr res; - v->ToString(o,res); + if(!v->ToString(o,res)) { + return SQ_ERROR; + } v->Push(res); + return SQ_OK; } void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b) { SQObjectPtr &o = stack_get(v, idx); - *b = v->IsFalse(o)?SQFalse:SQTrue; + *b = SQVM::IsFalse(o)?SQFalse:SQTrue; } SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i) @@ -555,10 +635,10 @@ SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread) SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &o = stack_get(v,idx); - v->Push(_null_); + v->PushNull(); if(!v->Clone(o, stack_get(v, -1))){ v->Pop(); - return sq_aux_invalidtype(v, type(o)); + return SQ_ERROR; } return SQ_OK; } @@ -579,6 +659,12 @@ SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx) } } +SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + return HashObj(o); +} + SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) { SQObjectPtr *o = NULL; @@ -599,7 +685,7 @@ SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag) return SQ_OK; } -SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag) +SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag) { switch(type(*o)) { case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; @@ -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")); SQObjectPtr res; if(!v->DeleteSlot(*self, key, res)){ + v->Pop(); return SQ_ERROR; } if(pushval) v->GetUp(-1) = res; - else v->Pop(1); + else v->Pop(); return SQ_OK; } SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self = stack_get(v, idx); - if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) { v->Pop(2); return SQ_OK; } - v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; + return SQ_ERROR; } SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self = stack_get(v, idx); - if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(type(v->GetUp(-2)) == OT_NULL) { + v->Pop(2); + return sq_throwerror(v, _SC("null key")); + } switch(type(self)) { case OT_TABLE: _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1)); @@ -773,6 +863,26 @@ SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; } +SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic) +{ + SQObjectPtr &self = stack_get(v, idx); + if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); + if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false)) + return SQ_ERROR; + return SQ_OK; +} + +SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic) +{ + SQObjectPtr &self = stack_get(v, idx); + if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); + if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true)) + return SQ_ERROR; + return SQ_OK; +} + SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self = stack_get(v, idx); @@ -811,9 +921,9 @@ SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) _table(*self)->Remove(key); } if(pushval != 0) - if(pushval) v->GetUp(-1) = t; + v->GetUp(-1) = t; else - v->Pop(1); + v->Pop(); return SQ_OK; } @@ -824,7 +934,7 @@ SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) case OT_TABLE: case OT_USERDATA: if(!_delegable(self)->_delegate){ - v->Push(_null_); + v->PushNull(); break; } v->Push(SQObjectPtr(_delegable(self)->_delegate)); @@ -838,10 +948,10 @@ SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self=stack_get(v,idx); - if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) + if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,DONT_FALL_BACK)) return SQ_OK; - v->Pop(1); - return sq_throwerror(v,_SC("the index doesn't exist")); + v->Pop(); + return SQ_ERROR; } SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) @@ -860,15 +970,24 @@ SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1))) return SQ_OK; break; - case OT_ARRAY: - if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) - return SQ_OK; + case OT_ARRAY:{ + SQObjectPtr& key = v->GetUp(-1); + if(sq_isnumeric(key)){ + if(_array(self)->Get(tointeger(key),v->GetUp(-1))) { + return SQ_OK; + } + } + else { + v->Pop(); + return sq_throwerror(v,_SC("invalid index type for an array")); + } + } break; default: - v->Pop(1); + v->Pop(); return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); } - v->Pop(1); + v->Pop(); return sq_throwerror(v,_SC("the index doesn't exist")); } @@ -892,9 +1011,9 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege if(type(ci._closure)!=OT_CLOSURE) return NULL; SQClosure *c=_closure(ci._closure); - SQFunctionProto *func=_funcproto(c->_function); + SQFunctionProto *func=c->_function; if(func->_noutervalues > (SQInteger)idx) { - v->Push(c->_outervalues[idx]); + v->Push(*_outer(c->_outervalues[idx])->_valptr); return _stringval(func->_outervalues[idx]._name); } idx -= func->_noutervalues; @@ -916,12 +1035,20 @@ void sq_resetobject(HSQOBJECT *po) SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) { v->_lasterror=SQString::Create(_ss(v),err); - return -1; + return SQ_ERROR; +} + +SQRESULT sq_throwobject(HSQUIRRELVM v) +{ + v->_lasterror = v->GetUp(-1); + v->Pop(); + return SQ_ERROR; } + void sq_reseterror(HSQUIRRELVM v) { - v->_lasterror = _null_; + v->_lasterror.Null(); } void sq_getlasterror(HSQUIRRELVM v) @@ -929,18 +1056,22 @@ void sq_getlasterror(HSQUIRRELVM v) v->Push(v->_lasterror); } -void sq_reservestack(HSQUIRRELVM v,SQInteger nsize) +SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize) { if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { + if(v->_nmetamethodscall) { + return sq_throwerror(v,_SC("cannot resize stack while in a metamethod")); + } v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); } + return SQ_OK; } SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror) { if(type(v->GetUp(-1))==OT_GENERATOR){ - v->Push(_null_); //retval - if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) + v->PushNull(); //retval + if(!v->Execute(v->GetUp(-2),0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) {v->Raise_Error(v->_lasterror); return SQ_ERROR;} if(!retval) v->Pop(); @@ -953,6 +1084,7 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror) { SQObjectPtr res; if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){ + if(!v->_suspended) { v->Pop(params);//pop closure and args } @@ -980,14 +1112,16 @@ SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseer SQObjectPtr ret; if(!v->_suspended) return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); + SQInteger target = v->_suspended_target; if(wakeupret) { - v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + if(target != -1) { + v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + } v->Pop(); - } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_; - if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) + } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); } + SQObjectPtr dummy; + if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) { return SQ_ERROR; - if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) { - while (v->_top > 1) v->_stack[--v->_top] = _null_; } if(retval) v->Push(ret); @@ -1017,6 +1151,8 @@ SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) SQObjectPtr *o = NULL; _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); unsigned short tag = SQ_BYTECODE_STREAM_TAG; + if(_closure(*o)->_function->_noutervalues) + return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized")); if(w(up,&tag,2) != 2) return sq_throwerror(v,_SC("io error")); if(!_closure(*o)->Save(v,up,w)) @@ -1044,6 +1180,16 @@ SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize) return _ss(v)->GetScratchPad(minsize); } +SQRESULT sq_resurrectunreachable(HSQUIRRELVM v) +{ +#ifndef NO_GARBAGE_COLLECTOR + _ss(v)->ResurrectUnreachable(v); + return SQ_OK; +#else + return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build")); +#endif +} + SQInteger sq_collectgarbage(HSQUIRRELVM v) { #ifndef NO_GARBAGE_COLLECTOR @@ -1053,17 +1199,41 @@ SQInteger sq_collectgarbage(HSQUIRRELVM v) #endif } +SQRESULT sq_getcallee(HSQUIRRELVM v) +{ + if(v->_callsstacksize > 1) + { + v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); + return SQ_OK; + } + return sq_throwerror(v,_SC("no closure in the calls stack")); +} + const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) { - SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr &self=stack_get(v,idx); const SQChar *name = NULL; - if(type(self) == OT_CLOSURE) { - if(_closure(self)->_outervalues.size()>nval) { - v->Push(_closure(self)->_outervalues[nval]); - SQFunctionProto *fp = _funcproto(_closure(self)->_function); + switch(type(self)) + { + case OT_CLOSURE:{ + SQClosure *clo = _closure(self); + SQFunctionProto *fp = clo->_function; + if(((SQUnsignedInteger)fp->_noutervalues) > nval) { + v->Push(*(_outer(clo->_outervalues[nval])->_valptr)); SQOuterVar &ov = fp->_outervalues[nval]; name = _stringval(ov._name); } + } + break; + case OT_NATIVECLOSURE:{ + SQNativeClosure *clo = _nativeclosure(self); + if(clo->_noutervalues > nval) { + v->Push(clo->_outervalues[nval]); + name = _SC("@NATIVE"); + } + } + break; + default: break; //shutup compiler } return name; } @@ -1073,22 +1243,24 @@ SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) SQObjectPtr &self=stack_get(v,idx); switch(type(self)) { - case OT_CLOSURE: - if(_closure(self)->_outervalues.size()>nval){ - _closure(self)->_outervalues[nval]=stack_get(v,-1); + case OT_CLOSURE:{ + SQFunctionProto *fp = _closure(self)->_function; + if(((SQUnsignedInteger)fp->_noutervalues) > nval){ + *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1); } else return sq_throwerror(v,_SC("invalid free var index")); + } break; case OT_NATIVECLOSURE: - if(_nativeclosure(self)->_outervalues.size()>nval){ - _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1); + if(_nativeclosure(self)->_noutervalues > nval){ + _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1); } else return sq_throwerror(v,_SC("invalid free var index")); break; default: return sq_aux_invalidtype(v,type(self)); } - v->Pop(1); + v->Pop(); return SQ_OK; } @@ -1134,6 +1306,77 @@ SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) return sq_throwerror(v,_SC("wrong index")); } +SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-1); + SQTable *m = _class(*o)->_members; + SQObjectPtr val; + if(m->Get(key,val)) { + handle->_static = _isfield(val) ? SQFalse : SQTrue; + handle->_index = _member_idx(val); + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); +} + +SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val) +{ + switch(type(self)) { + case OT_INSTANCE: { + SQInstance *i = _instance(self); + if(handle->_static) { + SQClass *c = i->_class; + val = &c->_methods[handle->_index].val; + } + else { + val = &i->_values[handle->_index]; + + } + } + break; + case OT_CLASS: { + SQClass *c = _class(self); + if(handle->_static) { + val = &c->_methods[handle->_index].val; + } + else { + val = &c->_defaultvalues[handle->_index].val; + } + } + break; + default: + return sq_throwerror(v,_SC("wrong type(expected class or instance)")); + } + return SQ_OK; +} + +SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle) +{ + SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr *val = NULL; + if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { + return SQ_ERROR; + } + v->Push(_realval(*val)); + return SQ_OK; +} + +SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle) +{ + SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr &newval = stack_get(v,-1); + SQObjectPtr *val = NULL; + if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { + return SQ_ERROR; + } + *val = newval; + v->Pop(); + return SQ_OK; +} + SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr *o = NULL; @@ -1141,7 +1384,7 @@ SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) if(_class(*o)->_base) v->Push(SQObjectPtr(_class(*o)->_base)); else - v->Push(_null_); + v->PushNull(); return SQ_OK; } @@ -1244,9 +1487,10 @@ void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx) dest->Push(stack_get(src,idx)); } -void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc) +void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc) { _ss(v)->_printfunc = printfunc; + _ss(v)->_errorfunc = errfunc; } SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) @@ -1254,6 +1498,11 @@ SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) return _ss(v)->_printfunc; } +SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v) +{ + return _ss(v)->_errorfunc; +} + void *sq_malloc(SQUnsignedInteger size) { return SQ_MALLOC(size); diff --git a/external/squirrel/squirrel/sqarray.h b/external/squirrel/squirrel/sqarray.h old mode 100755 new mode 100644 index 7f4faa9f6..c3a57abcc --- a/external/squirrel/squirrel/sqarray.h +++ b/external/squirrel/squirrel/sqarray.h @@ -18,6 +18,7 @@ public: } #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); + SQObjectType GetType() {return OT_ARRAY;} #endif void Finalize(){ _values.resize(0); @@ -53,9 +54,14 @@ public: //nothing to iterate anymore return -1; } - SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; } + SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),0); anew->_values.copy(_values); return anew; } SQInteger Size() const {return _values.size();} - void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); } + void Resize(SQInteger size) + { + SQObjectPtr _null; + Resize(size,_null); + } + void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); } void Reserve(SQInteger size) { _values.reserve(size); } void Append(const SQObject &o){_values.push_back(o);} void Extend(const SQArray *a); @@ -82,6 +88,7 @@ public: { sq_delete(this,SQArray); } + SQObjectPtrVec _values; }; #endif //_SQARRAY_H_ diff --git a/external/squirrel/squirrel/sqbaselib.cpp b/external/squirrel/squirrel/sqbaselib.cpp old mode 100755 new mode 100644 index 9b1fb5bb9..4a7d39d88 --- a/external/squirrel/squirrel/sqbaselib.cpp +++ b/external/squirrel/squirrel/sqbaselib.cpp @@ -16,18 +16,28 @@ bool str2num(const SQChar *s,SQObjectPtr &res) { SQChar *end; - if(scstrstr(s,_SC("."))){ + const SQChar *e = s; + SQBool isfloat = SQFalse; + SQChar c; + while((c = *e) != _SC('\0')) + { + if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation + isfloat = SQTrue; + break; + } + e++; + } + if(isfloat){ SQFloat r = SQFloat(scstrtod(s,&end)); if(s == end) return false; res = r; - return true; } else{ SQInteger r = SQInteger(scstrtol(s,&end,10)); if(s == end) return false; res = r; - return true; } + return true; } static SQInteger base_dummy(HSQUIRRELVM v) @@ -41,6 +51,11 @@ static SQInteger base_collectgarbage(HSQUIRRELVM v) sq_pushinteger(v, sq_collectgarbage(v)); return 1; } +static SQInteger base_resurectureachable(HSQUIRRELVM v) +{ + sq_resurrectunreachable(v); + return 1; +} #endif static SQInteger base_getroottable(HSQUIRRELVM v) @@ -58,7 +73,7 @@ static SQInteger base_getconsttable(HSQUIRRELVM v) static SQInteger base_setroottable(HSQUIRRELVM v) { - SQObjectPtr &o=stack_get(v,2); + SQObjectPtr o = v->_roottable; if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; v->Push(o); return 1; @@ -66,7 +81,7 @@ static SQInteger base_setroottable(HSQUIRRELVM v) static SQInteger base_setconsttable(HSQUIRRELVM v) { - SQObjectPtr &o=stack_get(v,2); + SQObjectPtr o = _ss(v)->_consts; if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR; v->Push(o); return 1; @@ -87,17 +102,17 @@ static SQInteger base_setdebughook(HSQUIRRELVM v) static SQInteger base_enabledebuginfo(HSQUIRRELVM v) { SQObjectPtr &o=stack_get(v,2); - sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0); + + sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue); return 0; } -static SQInteger base_getstackinfos(HSQUIRRELVM v) +static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level) { - SQInteger level; SQStackInfos si; SQInteger seq = 0; const SQChar *name = NULL; - sq_getinteger(v, -1, &level); + if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) { const SQChar *fn = _SC("unknown"); @@ -107,33 +122,39 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v) sq_newtable(v); sq_pushstring(v, _SC("func"), -1); sq_pushstring(v, fn, -1); - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); sq_pushstring(v, _SC("src"), -1); sq_pushstring(v, src, -1); - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); sq_pushstring(v, _SC("line"), -1); sq_pushinteger(v, si.line); - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); sq_pushstring(v, _SC("locals"), -1); sq_newtable(v); seq=0; while ((name = sq_getlocal(v, level, seq))) { sq_pushstring(v, name, -1); sq_push(v, -2); - sq_createslot(v, -4); + sq_newslot(v, -4, SQFalse); sq_pop(v, 1); seq++; } - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); return 1; } return 0; } +static SQInteger base_getstackinfos(HSQUIRRELVM v) +{ + SQInteger level; + sq_getinteger(v, -1, &level); + return __getcallstackinfos(v,level); +} static SQInteger base_assert(HSQUIRRELVM v) { - if(v->IsFalse(stack_get(v,2))){ + if(SQVM::IsFalse(stack_get(v,2))){ return sq_throwerror(v,_SC("assertion failed")); } return 0; @@ -170,6 +191,15 @@ static SQInteger base_print(HSQUIRRELVM v) return 0; } +static SQInteger base_error(HSQUIRRELVM v) +{ + const SQChar *str; + sq_tostring(v,2); + sq_getstring(v,-1,&str); + if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str); + return 0; +} + static SQInteger base_compilestring(HSQUIRRELVM v) { SQInteger nargs=sq_gettop(v); @@ -189,7 +219,7 @@ static SQInteger base_compilestring(HSQUIRRELVM v) static SQInteger base_newthread(HSQUIRRELVM v) { SQObjectPtr &func = stack_get(v,2); - SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2; + SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2; HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); sq_move(newv,v,-2); return 1; @@ -222,6 +252,16 @@ static SQInteger base_type(HSQUIRRELVM v) return 1; } +static SQInteger base_callee(HSQUIRRELVM v) +{ + if(v->_callsstacksize > 1) + { + v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); + return 1; + } + return sq_throwerror(v,_SC("no closure in the calls stack")); +} + static SQRegFunction base_funcs[]={ //generic {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, @@ -234,14 +274,17 @@ static SQRegFunction base_funcs[]={ {_SC("setconsttable"),base_setconsttable,2, NULL}, {_SC("assert"),base_assert,2, NULL}, {_SC("print"),base_print,2, NULL}, + {_SC("error"),base_error,2, NULL}, {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, {_SC("newthread"),base_newthread,2, _SC(".c")}, {_SC("suspend"),base_suspend,-1, NULL}, {_SC("array"),base_array,-2, _SC(".n")}, {_SC("type"),base_type,2, NULL}, + {_SC("callee"),base_callee,0,NULL}, {_SC("dummy"),base_dummy,0,NULL}, #ifndef NO_GARBAGE_COLLECTOR - {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")}, + {_SC("collectgarbage"),base_collectgarbage,0, NULL}, + {_SC("resurrectunreachable"),base_resurectureachable,0, NULL}, #endif {0,0} }; @@ -255,21 +298,25 @@ void sq_base_register(HSQUIRRELVM v) sq_newclosure(v,base_funcs[i].f,0); sq_setnativeclosurename(v,-1,base_funcs[i].name); sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); i++; } + + sq_pushstring(v,_SC("_versionnumber_"),-1); + sq_pushinteger(v,SQUIRREL_VERSION_NUMBER); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_version_"),-1); sq_pushstring(v,SQUIRREL_VERSION,-1); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_charsize_"),-1); sq_pushinteger(v,sizeof(SQChar)); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_intsize_"),-1); sq_pushinteger(v,sizeof(SQInteger)); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_floatsize_"),-1); sq_pushinteger(v,sizeof(SQFloat)); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pop(v,1); } @@ -298,7 +345,7 @@ static SQInteger default_delegate_tofloat(HSQUIRRELVM v) v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); break; default: - v->Push(_null_); + v->PushNull(); break; } return 1; @@ -323,7 +370,7 @@ static SQInteger default_delegate_tointeger(HSQUIRRELVM v) v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); break; default: - v->Push(_null_); + v->PushNull(); break; } return 1; @@ -356,6 +403,7 @@ static SQInteger number_delegate_tochar(HSQUIRRELVM v) } + ///////////////////////////////////////////////////////////////// //TABLE DEFAULT DELEGATE @@ -377,27 +425,41 @@ static SQInteger container_rawexists(HSQUIRRELVM v) return 1; } -static SQInteger table_rawset(HSQUIRRELVM v) +static SQInteger container_rawset(HSQUIRRELVM v) { return sq_rawset(v,-3); } -static SQInteger table_rawget(HSQUIRRELVM v) +static SQInteger container_rawget(HSQUIRRELVM v) { return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; } +static SQInteger table_setdelegate(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_setdelegate(v,-2))) + return SQ_ERROR; + sq_push(v,-1); // -1 because sq_setdelegate pops 1 + return 1; +} + +static SQInteger table_getdelegate(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR; +} SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ {_SC("len"),default_delegate_len,1, _SC("t")}, - {_SC("rawget"),table_rawget,2, _SC("t")}, - {_SC("rawset"),table_rawset,3, _SC("t")}, + {_SC("rawget"),container_rawget,2, _SC("t")}, + {_SC("rawset"),container_rawset,3, _SC("t")}, {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, {_SC("rawin"),container_rawexists,2, _SC("t")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {_SC("clear"),obj_clear,1, _SC(".")}, + {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")}, + {_SC("getdelegate"),table_getdelegate,1, _SC(".")}, {0,0} }; @@ -472,6 +534,111 @@ static SQInteger array_resize(HSQUIRRELVM v) return sq_throwerror(v, _SC("size must be a number")); } +static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) { + SQObjectPtr temp; + SQInteger size = src->Size(); + for(SQInteger n = 0; n < size; n++) { + src->Get(n,temp); + v->Push(src); + v->Push(temp); + if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) { + return SQ_ERROR; + } + dest->Set(n,v->GetUp(-1)); + v->Pop(); + } + return 0; +} + +static SQInteger array_map(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQInteger size = _array(o)->Size(); + SQObjectPtr ret = SQArray::Create(_ss(v),size); + if(SQ_FAILED(__map_array(_array(ret),_array(o),v))) + return SQ_ERROR; + v->Push(ret); + return 1; +} + +static SQInteger array_apply(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + if(SQ_FAILED(__map_array(_array(o),_array(o),v))) + return SQ_ERROR; + return 0; +} + +static SQInteger array_reduce(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQArray *a = _array(o); + SQInteger size = a->Size(); + if(size == 0) { + return 0; + } + SQObjectPtr res; + a->Get(0,res); + if(size > 1) { + SQObjectPtr other; + for(SQInteger n = 1; n < size; n++) { + a->Get(n,other); + v->Push(o); + v->Push(res); + v->Push(other); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + res = v->GetUp(-1); + v->Pop(); + } + } + v->Push(res); + return 1; +} + +static SQInteger array_filter(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQArray *a = _array(o); + SQObjectPtr ret = SQArray::Create(_ss(v),0); + SQInteger size = a->Size(); + SQObjectPtr val; + for(SQInteger n = 0; n < size; n++) { + a->Get(n,val); + v->Push(o); + v->Push(n); + v->Push(val); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + if(!SQVM::IsFalse(v->GetUp(-1))) { + _array(ret)->Append(val); + } + v->Pop(); + } + v->Push(ret); + return 1; +} + +static SQInteger array_find(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQObjectPtr &val = stack_get(v,2); + SQArray *a = _array(o); + SQInteger size = a->Size(); + SQObjectPtr temp; + for(SQInteger n = 0; n < size; n++) { + bool res = false; + a->Get(n,temp); + if(SQVM::IsEqual(temp,val,res) && res) { + v->Push(n); + return 1; + } + } + return 0; +} + bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) { @@ -499,7 +666,7 @@ bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQ return true; } -bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, int root, int bottom, SQInteger func) +bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func) { SQInteger maxChild; SQInteger done = 0; @@ -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)) return false; if (ret < 0) { + if (root == maxChild) { + v->Raise_Error(_SC("inconsistent compare function")); + return false; // We'd be swapping ourselve. The compare function is incorrect + } + _Swap(arr->_values[root],arr->_values[maxChild]); root = maxChild; } @@ -602,6 +774,11 @@ SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {_SC("clear"),obj_clear,1, _SC(".")}, + {_SC("map"),array_map,2, _SC("ac")}, + {_SC("apply"),array_apply,2, _SC("ac")}, + {_SC("reduce"),array_reduce,2, _SC("ac")}, + {_SC("filter"),array_filter,2, _SC("ac")}, + {_SC("find"),array_find,2, _SC("a.")}, {0,0} }; @@ -717,12 +894,16 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) { SQObject o = stack_get(v,1); SQTable *res = SQTable::Create(_ss(v),4); if(type(o) == OT_CLOSURE) { - SQFunctionProto *f = _funcproto(_closure(o)->_function); + SQFunctionProto *f = _closure(o)->_function; SQInteger nparams = f->_nparameters + (f->_varparams?1:0); SQObjectPtr params = SQArray::Create(_ss(v),nparams); + SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams); for(SQInteger n = 0; n_nparameters; n++) { _array(params)->Set((SQInteger)n,f->_parameters[n]); } + for(SQInteger j = 0; j_ndefaultparams; j++) { + _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]); + } if(f->_varparams) { _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1)); } @@ -731,6 +912,7 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) { res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename); res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params); res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams); + res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams); } else { //OT_NATIVECLOSURE SQNativeClosure *nc = _nativeclosure(o); @@ -752,6 +934,7 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) { } + SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={ {_SC("call"),closure_call,-1, _SC("c")}, {_SC("pcall"),closure_pcall,-1, _SC("c")}, @@ -784,17 +967,15 @@ SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={ }; //THREAD DEFAULT DELEGATE - static SQInteger thread_call(HSQUIRRELVM v) { - SQObjectPtr o = stack_get(v,1); if(type(o) == OT_THREAD) { SQInteger nparams = sq_gettop(v); _thread(o)->Push(_thread(o)->_roottable); for(SQInteger i = 2; i<(nparams+1); i++) sq_move(_thread(o),v,i); - if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) { + if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) { sq_move(v,_thread(o),-1); sq_pop(_thread(o),1); return 1; @@ -860,46 +1041,117 @@ static SQInteger thread_getstatus(HSQUIRRELVM v) return 1; } +static SQInteger thread_getstackinfos(HSQUIRRELVM v) +{ + SQObjectPtr o = stack_get(v,1); + if(type(o) == OT_THREAD) { + SQVM *thread = _thread(o); + SQInteger threadtop = sq_gettop(thread); + SQInteger level; + sq_getinteger(v,-1,&level); + SQRESULT res = __getcallstackinfos(thread,level); + if(SQ_FAILED(res)) + { + sq_settop(thread,threadtop); + if(type(thread->_lasterror) == OT_STRING) { + sq_throwerror(v,_stringval(thread->_lasterror)); + } + else { + sq_throwerror(v,_SC("unknown error")); + } + } + if(res > 0) { + //some result + sq_move(v,thread,-1); + sq_settop(thread,threadtop); + return 1; + } + //no result + sq_settop(thread,threadtop); + return 0; + + } + return sq_throwerror(v,_SC("wrong parameter")); +} + SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { {_SC("call"), thread_call, -1, _SC("v")}, {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")}, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {0,0}, }; static SQInteger class_getattributes(HSQUIRRELVM v) { - if(SQ_SUCCEEDED(sq_getattributes(v,-2))) - return 1; - return SQ_ERROR; + return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR; } static SQInteger class_setattributes(HSQUIRRELVM v) { - if(SQ_SUCCEEDED(sq_setattributes(v,-3))) - return 1; - return SQ_ERROR; + return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR; } static SQInteger class_instance(HSQUIRRELVM v) { - if(SQ_SUCCEEDED(sq_createinstance(v,-1))) - return 1; - return SQ_ERROR; + return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR; +} + +static SQInteger class_getbase(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR; +} + +static SQInteger class_newmember(HSQUIRRELVM v) +{ + SQInteger top = sq_gettop(v); + SQBool bstatic = SQFalse; + if(top == 5) + { + sq_tobool(v,-1,&bstatic); + sq_pop(v,1); + } + + if(top < 4) { + sq_pushnull(v); + } + return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR; +} + +static SQInteger class_rawnewmember(HSQUIRRELVM v) +{ + SQInteger top = sq_gettop(v); + SQBool bstatic = SQFalse; + if(top == 5) + { + sq_tobool(v,-1,&bstatic); + sq_pop(v,1); + } + + if(top < 4) { + sq_pushnull(v); + } + return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR; } SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, + {_SC("rawget"),container_rawget,2, _SC("y")}, + {_SC("rawset"),container_rawset,3, _SC("y")}, {_SC("rawin"),container_rawexists,2, _SC("y")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {_SC("instance"),class_instance,1, _SC("y")}, + {_SC("getbase"),class_getbase,1, _SC("y")}, + {_SC("newmember"),class_newmember,-3, _SC("y")}, + {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")}, {0,0} }; + static SQInteger instance_getclass(HSQUIRRELVM v) { if(SQ_SUCCEEDED(sq_getclass(v,1))) @@ -909,6 +1161,8 @@ static SQInteger instance_getclass(HSQUIRRELVM v) SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { {_SC("getclass"), instance_getclass, 1, _SC("x")}, + {_SC("rawget"),container_rawget,2, _SC("x")}, + {_SC("rawset"),container_rawset,3, _SC("x")}, {_SC("rawin"),container_rawexists,2, _SC("x")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, @@ -929,4 +1183,3 @@ SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { {0,0} }; - diff --git a/external/squirrel/squirrel/sqclass.cpp b/external/squirrel/squirrel/sqclass.cpp old mode 100755 new mode 100644 index f4bcbead1..1f26cc92f --- a/external/squirrel/squirrel/sqclass.cpp +++ b/external/squirrel/squirrel/sqclass.cpp @@ -5,33 +5,39 @@ #include "sqvm.h" #include "sqtable.h" #include "sqclass.h" +#include "sqfuncproto.h" #include "sqclosure.h" + + SQClass::SQClass(SQSharedState *ss,SQClass *base) { _base = base; _typetag = 0; _hook = NULL; _udsize = 0; - _metamethods.resize(MT_LAST); //size it to max size + _locked = false; + _constructoridx = -1; if(_base) { + _constructoridx = _base->_constructoridx; + _udsize = _base->_udsize; _defaultvalues.copy(base->_defaultvalues); _methods.copy(base->_methods); - _metamethods.copy(base->_metamethods); + _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST); __ObjAddRef(_base); } _members = base?base->_members->Clone() : SQTable::Create(ss,0); __ObjAddRef(_members); - _locked = false; + INIT_CHAIN(); ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); } void SQClass::Finalize() { - _attributes = _null_; + _attributes.Null(); _defaultvalues.resize(0); _methods.resize(0); - _metamethods.resize(0); + _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST); __ObjRelease(_members); if(_base) { __ObjRelease(_base); @@ -47,28 +53,40 @@ SQClass::~SQClass() bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) { SQObjectPtr temp; - if(_locked) + bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic; + if(_locked && !belongs_to_static_table) return false; //the class already has an instance so cannot be modified if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value { _defaultvalues[_member_idx(temp)].val = val; return true; } - if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) { + if(belongs_to_static_table) { SQInteger mmidx; if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { _metamethods[mmidx] = val; } else { + SQObjectPtr theval = val; + if(_base && type(val) == OT_CLOSURE) { + theval = _closure(val)->Clone(); + _closure(theval)->_base = _base; + __ObjAddRef(_base); //ref for the closure + } if(type(temp) == OT_NULL) { + bool isconstructor; + SQVM::IsEqual(ss->_constructoridx, key, isconstructor); + if(isconstructor) { + _constructoridx = (SQInteger)_methods.size(); + } SQClassMember m; - m.val = val; + m.val = theval; _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); _methods.push_back(m); } else { - _methods[_member_idx(temp)].val = val; + _methods[_member_idx(temp)].val = theval; } } return true; @@ -162,9 +180,10 @@ void SQInstance::Finalize() { SQUnsignedInteger nvalues = _class->_defaultvalues.size(); __ObjRelease(_class); - for(SQUnsignedInteger i = 0; i < nvalues; i++) { - _values[i] = _null_; - } + _NULL_SQOBJECT_VECTOR(_values,nvalues); + //for(SQUnsignedInteger i = 0; i < nvalues; i++) { +// _values[i].Null(); +// } } SQInstance::~SQInstance() diff --git a/external/squirrel/squirrel/sqclass.h b/external/squirrel/squirrel/sqclass.h old mode 100755 new mode 100644 index 281b0fa27..996a3df70 --- a/external/squirrel/squirrel/sqclass.h +++ b/external/squirrel/squirrel/sqclass.h @@ -5,11 +5,6 @@ struct SQInstance; struct SQClassMember { - SQClassMember(){} - SQClassMember(const SQClassMember &o) { - val = o.val; - attrs = o.attrs; - } SQObjectPtr val; SQObjectPtr attrs; }; @@ -50,6 +45,14 @@ public: } return false; } + bool GetConstructor(SQObjectPtr &ctor) + { + if(_constructoridx != -1) { + ctor = _methods[_constructoridx].val; + return true; + } + return false; + } bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); void Lock() { _locked = true; if(_base) _base->Lock(); } @@ -60,6 +63,7 @@ public: void Finalize(); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable ** ); + SQObjectType GetType() {return OT_CLASS;} #endif SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); SQInstance *CreateInstance(); @@ -67,16 +71,17 @@ public: SQClass *_base; SQClassMemberVec _defaultvalues; SQClassMemberVec _methods; - SQObjectPtrVec _metamethods; + SQObjectPtr _metamethods[MT_LAST]; SQObjectPtr _attributes; SQUserPointer _typetag; SQRELEASEHOOK _hook; bool _locked; + SQInteger _constructoridx; SQInteger _udsize; }; #define calcinstancesize(_theclass_) \ - (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))) + (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))) struct SQInstance : public SQDelegable { @@ -138,6 +143,7 @@ public: void Finalize(); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable ** ); + SQObjectType GetType() {return OT_INSTANCE;} #endif bool InstanceOf(SQClass *trg); bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); diff --git a/external/squirrel/squirrel/sqclosure.h b/external/squirrel/squirrel/sqclosure.h old mode 100755 new mode 100644 index 949fb38b0..07b3efcfe --- a/external/squirrel/squirrel/sqclosure.h +++ b/external/squirrel/squirrel/sqclosure.h @@ -2,44 +2,100 @@ #ifndef _SQCLOSURE_H_ #define _SQCLOSURE_H_ -struct SQFunctionProto; +#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr))) + +struct SQFunctionProto; +struct SQClass; struct SQClosure : public CHAINABLE_OBJ { private: - SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} public: static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){ - SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure)); + SQInteger size = _CALC_CLOSURE_SIZE(func); + SQClosure *nc=(SQClosure*)SQ_MALLOC(size); new (nc) SQClosure(ss,func); + nc->_outervalues = (SQObjectPtr *)(nc + 1); + nc->_defaultparams = &nc->_outervalues[func->_noutervalues]; + _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues); + _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams); return nc; } void Release(){ - sq_delete(this,SQClosure); + SQFunctionProto *f = _function; + SQInteger size = _CALC_CLOSURE_SIZE(f); + _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues); + _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams); + __ObjRelease(_function); + this->~SQClosure(); + sq_vm_free(this,size); } + SQClosure *Clone() { - SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function)); + SQFunctionProto *f = _function; + SQClosure * ret = SQClosure::Create(_opt_ss(this),f); ret->_env = _env; - ret->_outervalues.copy(_outervalues); - ret->_defaultparams.copy(_defaultparams); + if(ret->_env) __ObjAddRef(ret->_env); + _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues); + _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams); return ret; } - ~SQClosure() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } + ~SQClosure(); + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); - void Finalize(){_outervalues.resize(0); } + void Finalize(){ + SQFunctionProto *f = _function; + _NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues); + _NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams); + } + SQObjectType GetType() {return OT_CLOSURE;} #endif - SQObjectPtr _env; - SQObjectPtr _function; - SQObjectPtrVec _outervalues; - SQObjectPtrVec _defaultparams; + SQWeakRef *_env; + SQClass *_base; + SQFunctionProto *_function; + SQObjectPtr *_outervalues; + SQObjectPtr *_defaultparams; }; + +////////////////////////////////////////////// +struct SQOuter : public CHAINABLE_OBJ +{ + +private: + SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } + +public: + static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer) + { + SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter)); + new (nc) SQOuter(ss, outer); + return nc; + } + ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } + + void Release() + { + this->~SQOuter(); + sq_vm_free(this,sizeof(SQOuter)); + } + +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize() { _value.Null(); } + SQObjectType GetType() {return OT_OUTER;} +#endif + + SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */ + SQInteger _idx; /* idx in stack array, for relocation */ + SQObjectPtr _value; /* value of outer after stack frame is closed */ + SQOuter *_next; /* pointer to next outer when frame is open */ +}; + ////////////////////////////////////////////// struct SQGenerator : public CHAINABLE_OBJ { @@ -59,60 +115,75 @@ public: void Kill(){ _state=eDead; _stack.resize(0); - _closure=_null_;} + _closure.Null();} void Release(){ sq_delete(this,SQGenerator); } - bool Yield(SQVM *v); - bool Resume(SQVM *v,SQInteger target); + + bool Yield(SQVM *v,SQInteger target); + bool Resume(SQVM *v,SQObjectPtr &dest); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); - void Finalize(){_stack.resize(0);_closure=_null_;} + void Finalize(){_stack.resize(0);_closure.Null();} + SQObjectType GetType() {return OT_GENERATOR;} #endif SQObjectPtr _closure; SQObjectPtrVec _stack; - SQObjectPtrVec _vargsstack; SQVM::CallInfo _ci; ExceptionsTraps _etraps; SQGeneratorState _state; }; +#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr))) + struct SQNativeClosure : public CHAINABLE_OBJ { private: - SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } + SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} public: - static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func) + static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters) { - SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure)); + SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters); + SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size); new (nc) SQNativeClosure(ss,func); + nc->_outervalues = (SQObjectPtr *)(nc + 1); + nc->_noutervalues = nouters; + _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues); return nc; } SQNativeClosure *Clone() { - SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function); + SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues); ret->_env = _env; + if(ret->_env) __ObjAddRef(ret->_env); ret->_name = _name; - ret->_outervalues.copy(_outervalues); + _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues); ret->_typecheck.copy(_typecheck); ret->_nparamscheck = _nparamscheck; return ret; } ~SQNativeClosure() { + __ObjRelease(_env); REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } void Release(){ - sq_delete(this,SQNativeClosure); + SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues); + _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues); + this->~SQNativeClosure(); + sq_free(this,size); } + #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); - void Finalize(){_outervalues.resize(0);} + void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); } + SQObjectType GetType() {return OT_NATIVECLOSURE;} #endif SQInteger _nparamscheck; SQIntVec _typecheck; - SQObjectPtrVec _outervalues; - SQObjectPtr _env; + SQObjectPtr *_outervalues; + SQUnsignedInteger _noutervalues; + SQWeakRef *_env; SQFUNCTION _function; SQObjectPtr _name; }; diff --git a/external/squirrel/squirrel/sqcompiler.cpp b/external/squirrel/squirrel/sqcompiler.cpp old mode 100755 new mode 100644 index 461c2bcf4..a8dbee6c2 --- a/external/squirrel/squirrel/sqcompiler.cpp +++ b/external/squirrel/squirrel/sqcompiler.cpp @@ -2,6 +2,7 @@ see copyright notice in squirrel.h */ #include "sqpcheader.h" +#ifndef NO_COMPILER #include #include #include "sqopcodes.h" @@ -13,27 +14,48 @@ #include "sqvm.h" #include "sqtable.h" -#define DEREF_NO_DEREF -1 -#define DEREF_FIELD -2 +#define EXPR 1 +#define OBJECT 2 +#define BASE 3 +#define LOCAL 4 +#define OUTER 5 -struct ExpState -{ - ExpState() - { - _deref = DEREF_NO_DEREF; - _freevar = false; - _class_or_delete = false; - _funcarg = false; - } - bool _class_or_delete; - bool _funcarg; - bool _freevar; - SQInteger _deref; +struct SQExpState { + SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */ + SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */ + bool donot_get; /* signal not to deref the next value */ +}; + +struct SQScope { + SQInteger outers; + SQInteger stacksize; }; -typedef sqvector ExpStateVec; +#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \ + _scope.outers = _fs->_outers; \ + _scope.stacksize = _fs->GetStackSize(); + +#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \ + if(_fs->CountOuters(_scope.stacksize)) { \ + _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ + } \ + } -#define _exst (_expstates.top()) +#define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \ + _fs->SetStackSize(_scope.stacksize); \ + } \ + _scope = __oldscope__; \ + } + +#define END_SCOPE() { SQInteger oldouters = _fs->_outers;\ + if(_fs->GetStackSize() != _scope.stacksize) { \ + _fs->SetStackSize(_scope.stacksize); \ + if(oldouters != _fs->_outers) { \ + _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ + } \ + } \ + _scope = __oldscope__; \ + } #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \ SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ @@ -54,6 +76,8 @@ public: _lex.Init(_ss(v), rg, up,ThrowError,this); _sourcename = SQString::Create(_ss(v), sourcename); _lineinfo = lineinfo;_raiseerror = raiseerror; + _scope.outers = 0; + _scope.stacksize = 0; compilererror = NULL; } static void ThrowError(void *ud, const SQChar *s) { @@ -71,27 +95,11 @@ public: longjmp(_errorjmp,1); } void Lex(){ _token = _lex.Lex();} - void PushExpState(){ _expstates.push_back(ExpState()); } - bool IsDerefToken(SQInteger tok) - { - switch(tok){ - case _SC('='): case _SC('('): case TK_NEWSLOT: - case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true; - } - return false; - } - ExpState PopExpState() - { - ExpState ret = _expstates.top(); - _expstates.pop_back(); - return ret; - } SQObject Expect(SQInteger tok) { if(_token != tok) { if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { - //ret = SQString::Create(_ss(_vm),_SC("constructor")); //do nothing } else { @@ -162,15 +170,17 @@ public: funcstate._name = SQString::Create(_ss(_vm), _SC("main")); _fs = &funcstate; _fs->AddParameter(_fs->CreateString(_SC("this"))); + _fs->AddParameter(_fs->CreateString(_SC("vargv"))); + _fs->_varparams = true; _fs->_sourcename = _sourcename; SQInteger stacksize = _fs->GetStackSize(); if(setjmp(_errorjmp) == 0) { Lex(); while(_token > 0){ Statement(); - if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); + if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); } - CleanStack(stacksize); + _fs->SetStackSize(stacksize); _fs->AddLineInfos(_lex._currentline, _lineinfo, true); _fs->AddInstruction(_OP_RETURN, 0xFF); _fs->SetStackSize(0); @@ -196,7 +206,7 @@ public: if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); } } - void Statement() + void Statement(bool closeframe = true) { _fs->AddLineInfos(_lex._currentline, _lineinfo); switch(_token){ @@ -213,7 +223,6 @@ public: SQOpcode op; if(_token == TK_RETURN) { op = _OP_RETURN; - } else { op = _OP_YIELD; @@ -226,13 +235,13 @@ public: if(op == _OP_RETURN && _fs->_traps > 0) _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); _fs->_returnexp = retexp; - _fs->AddInstruction(op, 1, _fs->PopTarget()); + _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize()); } else{ if(op == _OP_RETURN && _fs->_traps > 0) _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); _fs->_returnexp = -1; - _fs->AddInstruction(op, 0xFF); + _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); } break;} case TK_BREAK: @@ -240,6 +249,7 @@ public: if(_fs->_breaktargets.top() > 0){ _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); } + RESOLVE_OUTERS(); _fs->AddInstruction(_OP_JMP, 0, -1234); _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); Lex(); @@ -249,6 +259,7 @@ public: if(_fs->_continuetargets.top() > 0) { _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); } + RESOLVE_OUTERS(); _fs->AddInstruction(_OP_JMP, 0, -1234); _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); Lex(); @@ -263,11 +274,16 @@ public: EnumStatement(); break; case _SC('{'):{ - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Lex(); Statements(); Expect(_SC('}')); - _fs->SetStackSize(stacksize); + if(closeframe) { + END_SCOPE(); + } + else { + END_SCOPE_NO_CLOSE(); + } } break; case TK_TRY: @@ -293,7 +309,8 @@ public: break; default: CommaExpr(); - _fs->PopTarget(); + _fs->DiscardTarget(); + //_fs->PopTarget(); break; } _fs->SnoozeOpt(); @@ -311,38 +328,49 @@ public: SQInteger p1 = _fs->PopTarget(); //key in OP_GET _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); } - void EmitCompoundArith(SQInteger tok,bool deref) + void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos) { - SQInteger oper; - switch(tok){ - case TK_MINUSEQ: oper = '-'; break; - case TK_PLUSEQ: oper = '+'; break; - case TK_MULEQ: oper = '*'; break; - case TK_DIVEQ: oper = '/'; break; - case TK_MODEQ: oper = '%'; break; - default: oper = 0; //shut up compiler - assert(0); break; - }; - if(deref) { - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger src = _fs->PopTarget(); - //mixes dest obj and source val in the arg1(hack?) - _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper); - } - else { - Emit2ArgsOP(_OP_COMPARITHL, oper); + /* Generate code depending on the expression type */ + switch(etype) { + case LOCAL:{ + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->PopTarget(); //key in OP_GET + _fs->PushTarget(p1); + //EmitCompArithLocal(tok, p1, p1, p2); + _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0); + } + break; + case OBJECT: + case BASE: + { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + /* _OP_COMPARITH mixes dest obj and source val in the arg1 */ + _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok)); + } + break; + case OUTER: + { + SQInteger val = _fs->TopTarget(); + SQInteger tmp = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp, pos); + _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0); + _fs->AddInstruction(_OP_SETOUTER, tmp, pos, tmp); + } + break; } } void CommaExpr() { for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()); } - ExpState Expression(bool funcarg = false) + void Expression() { - PushExpState(); - _exst._class_or_delete = false; - _exst._funcarg = funcarg; + SQExpState es = _es; + _es.etype = EXPR; + _es.epos = -1; + _es.donot_get = false; LogicalOrExp(); switch(_token) { case _SC('='): @@ -351,40 +379,49 @@ public: case TK_PLUSEQ: case TK_MULEQ: case TK_DIVEQ: - case TK_MODEQ: - { - SQInteger op = _token; - SQInteger ds = _exst._deref; - bool freevar = _exst._freevar; - if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression")); - Lex(); Expression(); + case TK_MODEQ:{ + SQInteger op = _token; + SQInteger ds = _es.etype; + SQInteger pos = _es.epos; + if(ds == EXPR) Error(_SC("can't assign expression")); + Lex(); Expression(); - switch(op){ - case TK_NEWSLOT: - if(freevar) Error(_SC("free variables cannot be modified")); - if(ds == DEREF_FIELD) - EmitDerefOp(_OP_NEWSLOT); - else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - Error(_SC("can't 'create' a local slot")); - break; - case _SC('='): //ASSIGN - if(freevar) Error(_SC("free variables cannot be modified")); - if(ds == DEREF_FIELD) - EmitDerefOp(_OP_SET); - else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - SQInteger p2 = _fs->PopTarget(); //src in OP_GET - SQInteger p1 = _fs->TopTarget(); //key in OP_GET - _fs->AddInstruction(_OP_MOVE, p1, p2); + switch(op){ + case TK_NEWSLOT: + if(ds == OBJECT || ds == BASE) + EmitDerefOp(_OP_NEWSLOT); + else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + Error(_SC("can't 'create' a local slot")); + break; + case _SC('='): //ASSIGN + switch(ds) { + case LOCAL: + { + SQInteger src = _fs->PopTarget(); + SQInteger dst = _fs->TopTarget(); + _fs->AddInstruction(_OP_MOVE, dst, src); } break; - case TK_MINUSEQ: - case TK_PLUSEQ: - case TK_MULEQ: - case TK_DIVEQ: - case TK_MODEQ: - EmitCompoundArith(op,ds == DEREF_FIELD); + case OBJECT: + case BASE: + EmitDerefOp(_OP_SET); break; + case OUTER: + { + SQInteger src = _fs->PopTarget(); + SQInteger dst = _fs->PushTarget(); + _fs->AddInstruction(_OP_SETOUTER, dst, pos, src); + } } + break; + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + EmitCompoundArith(op, ds, pos); + break; + } } break; case _SC('?'): { @@ -408,9 +445,9 @@ public: } break; } - return PopExpState(); + _es = es; } - void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0) + template void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0) { Lex(); (this->*f)(); SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); @@ -474,21 +511,29 @@ public: } void BitwiseAndExp() { - CompExp(); + EqExp(); for(;;) if(_token == _SC('&')) - {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND); + {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND); }else return; } + void EqExp() + { + CompExp(); + for(;;) switch(_token) { + case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break; + case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break; + case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break; + default: return; + } + } void CompExp() { ShiftExp(); for(;;) switch(_token) { - case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break; case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; - case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break; default: return; } } @@ -502,12 +547,38 @@ public: default: return; } } + SQOpcode ChooseArithOpByToken(SQInteger tok) + { + switch(tok) { + case TK_PLUSEQ: case '+': return _OP_ADD; + case TK_MINUSEQ: case '-': return _OP_SUB; + case TK_MULEQ: case '*': return _OP_MUL; + case TK_DIVEQ: case '/': return _OP_DIV; + case TK_MODEQ: case '%': return _OP_MOD; + default: assert(0); + } + return _OP_ADD; + } + SQInteger ChooseCompArithCharByToken(SQInteger tok) + { + SQInteger oper; + switch(tok){ + case TK_MINUSEQ: oper = '-'; break; + case TK_PLUSEQ: oper = '+'; break; + case TK_MULEQ: oper = '*'; break; + case TK_DIVEQ: oper = '/'; break; + case TK_MODEQ: oper = '%'; break; + default: oper = 0; //shut up compiler + assert(0); break; + }; + return oper; + } void PlusExp() { MultExp(); for(;;) switch(_token) { case _SC('+'): case _SC('-'): - BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break; + BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break; default: return; } } @@ -517,7 +588,7 @@ public: PrefixedExpr(); for(;;) switch(_token) { case _SC('*'): case _SC('/'): case _SC('%'): - BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break; + BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break; default: return; } } @@ -525,69 +596,97 @@ public: void PrefixedExpr() { SQInteger pos = Factor(); - for(;;) { switch(_token) { - case _SC('.'): { + case _SC('.'): pos = -1; Lex(); - if(_token == TK_PARENT) { - Lex(); - if(!NeedGet()) - Error(_SC("parent cannot be set")); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src); + + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + if(_es.etype==BASE) { + Emit2ArgsOP(_OP_GET); + pos = _fs->TopTarget(); + _es.etype = EXPR; + _es.epos = pos; } else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - if(NeedGet()) Emit2ArgsOP(_OP_GET); - } - _exst._deref = DEREF_FIELD; - _exst._freevar = false; + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; } break; case _SC('['): if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); Lex(); Expression(); Expect(_SC(']')); pos = -1; - if(NeedGet()) Emit2ArgsOP(_OP_GET); - _exst._deref = DEREF_FIELD; - _exst._freevar = false; + if(_es.etype==BASE) { + Emit2ArgsOP(_OP_GET); + pos = _fs->TopTarget(); + _es.etype = EXPR; + _es.epos = pos; + } + else { + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; + } break; case TK_MINUSMINUS: case TK_PLUSPLUS: - if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { - SQInteger tok = _token; Lex(); - if(pos < 0) - Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1); - else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1); + { + if(IsEndOfStatement()) return; + SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1; + Lex(); + switch(_es.etype) + { + case EXPR: Error(_SC("can't '++' or '--' an expression")); break; + case OBJECT: + case BASE: + Emit2ArgsOP(_OP_PINC, diff); + break; + case LOCAL: { + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff); + } + break; + case OUTER: { + SQInteger tmp1 = _fs->PushTarget(); + SQInteger tmp2 = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos); + _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff); + _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2); + _fs->PopTarget(); + } + } } - - } - return; - break; + return; + break; case _SC('('): - { - if(_exst._deref != DEREF_NO_DEREF) { - if(pos<0) { - SQInteger key = _fs->PopTarget(); //key - SQInteger table = _fs->PopTarget(); //table etc... - SQInteger closure = _fs->PushTarget(); - SQInteger ttarget = _fs->PushTarget(); + switch(_es.etype) { + case OBJECT: { + SQInteger key = _fs->PopTarget(); /* location of the key */ + SQInteger table = _fs->PopTarget(); /* location of the object */ + SQInteger closure = _fs->PushTarget(); /* location for the closure */ + SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */ _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); - } - else{ + } + break; + case BASE: + //Emit2ArgsOP(_OP_GET); + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + break; + case OUTER: + _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos); + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + break; + default: _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - } } - else - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - _exst._deref = DEREF_NO_DEREF; + _es.etype = EXPR; Lex(); FunctionCallArgs(); - } break; default: return; } @@ -595,123 +694,116 @@ public: } SQInteger Factor() { - _exst._deref = DEREF_NO_DEREF; + _es.etype = EXPR; switch(_token) { - case TK_STRING_LITERAL: { - //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1)); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); - Lex(); - } + case TK_STRING_LITERAL: + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); + Lex(); break; - case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break; - case TK_VARGV: { Lex(); - Expect(_SC('[')); - Expression(); - Expect(_SC(']')); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src); - } + case TK_BASE: + Lex(); + _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget()); + _es.etype = BASE; + _es.epos = _fs->TopTarget(); + return (_es.epos); break; case TK_IDENTIFIER: case TK_CONSTRUCTOR: case TK_THIS:{ - _exst._freevar = false; - SQObject id; - SQObject constant; + SQObject id; + SQObject constant; + switch(_token) { - case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; - case TK_THIS: id = _fs->CreateString(_SC("this")); break; + case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; + case TK_THIS: id = _fs->CreateString(_SC("this")); break; case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break; } + SQInteger pos = -1; Lex(); - if((pos = _fs->GetLocalVariable(id)) == -1) { - //checks if is a free variable - if((pos = _fs->GetOuterVariable(id)) != -1) { - _exst._deref = _fs->PushTarget(); - _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos); - _exst._freevar = true; + if((pos = _fs->GetLocalVariable(id)) != -1) { + /* Handle a local variable (includes 'this') */ + _fs->PushTarget(pos); + _es.etype = LOCAL; + _es.epos = pos; + } + + else if((pos = _fs->GetOuterVariable(id)) != -1) { + /* Handle a free var */ + if(NeedGet()) { + _es.epos = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos); + /* _es.etype = EXPR; already default value */ } - else if(_fs->IsConstant(id,constant)) { //line 634 - SQObjectPtr constval; - SQObject constid; - if(type(constant) == OT_TABLE) { - Expect('.'); constid = Expect(TK_IDENTIFIER); - if(!_table(constant)->Get(constid,constval)) { - constval.Null(); - Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid)); - } - } - else { - constval = constant; - } - _exst._deref = _fs->PushTarget(); - SQObjectType ctype = type(constval); - if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) { - _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval)); - } - else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) { - SQFloat f = _float(constval); - _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f)); - } - else { - _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval)); - } + else { + _es.etype = OUTER; + _es.epos = pos; + } + } - _exst._freevar = true; + else if(_fs->IsConstant(id, constant)) { + /* Handle named constant */ + SQObjectPtr constval; + SQObject constid; + if(type(constant) == OT_TABLE) { + Expect('.'); + constid = Expect(TK_IDENTIFIER); + if(!_table(constant)->Get(constid, constval)) { + constval.Null(); + Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid)); + } } else { - _fs->PushTarget(0); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(NeedGet()) Emit2ArgsOP(_OP_GET); - _exst._deref = DEREF_FIELD; + constval = constant; + } + _es.epos = _fs->PushTarget(); + + /* generate direct or literal function depending on size */ + SQObjectType ctype = type(constval); + switch(ctype) { + case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break; + case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break; + default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break; } + _es.etype = EXPR; } - - else{ - _fs->PushTarget(pos); - _exst._deref = pos; + else { + /* Handle a non-local variable, aka a field. Push the 'this' pointer on + * the virtual stack (always found in offset 0, so no instruction needs to + * be generated), and push the key next. Generate an _OP_LOAD instruction + * for the latter. If we are not using the variable as a dref expr, generate + * the _OP_GET instruction. + */ + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; } - return _exst._deref; + return _es.epos; } break; - case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break; case TK_DOUBLE_COLON: // "::" - _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget()); - _exst._deref = DEREF_FIELD; - _token = _SC('.'); //hack - return -1; + _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget()); + _es.etype = OBJECT; + _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/ + _es.epos = -1; + return _es.epos; break; case TK_NULL: _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); Lex(); break; - case TK_INTEGER: { - if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits? - _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue); - } - else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue)); - } - Lex(); - } - break; - case TK_FLOAT: - if(sizeof(SQFloat) == sizeof(SQInt32)) { - _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue)); - } - else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue)); - } - Lex(); - break; + case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break; + case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break; case TK_TRUE: case TK_FALSE: _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); Lex(); break; case _SC('['): { - _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget()); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY); SQInteger apos = _fs->GetCurrentPos(),key = 0; Lex(); while(_token != _SC(']')) { @@ -719,57 +811,90 @@ public: if(_token == _SC(',')) Lex(); SQInteger val = _fs->PopTarget(); SQInteger array = _fs->TopTarget(); - _fs->AddInstruction(_OP_APPENDARRAY, array, val); + _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK); key++; } _fs->SetIntructionParam(apos, 1, key); Lex(); } break; - case _SC('{'):{ - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); - Lex();ParseTableOrClass(_SC(',')); - } + case _SC('{'): + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); + Lex();ParseTableOrClass(_SC(','),_SC('}')); break; case TK_FUNCTION: FunctionExp(_token);break; + case _SC('@'): FunctionExp(_token,true);break; case TK_CLASS: Lex(); ClassExp();break; - case _SC('-'): UnaryOP(_OP_NEG); break; - case _SC('!'): UnaryOP(_OP_NOT); break; - case _SC('~'): UnaryOP(_OP_BWNOT); break; - case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break; - case TK_RESUME : UnaryOP(_OP_RESUME); break; - case TK_CLONE : UnaryOP(_OP_CLONE); break; + case _SC('-'): + Lex(); + switch(_token) { + case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break; + case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break; + default: UnaryOP(_OP_NEG); + } + break; + case _SC('!'): Lex(); UnaryOP(_OP_NOT); break; + case _SC('~'): + Lex(); + if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; } + UnaryOP(_OP_BWNOT); + break; + case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break; + case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break; + case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break; case TK_MINUSMINUS : case TK_PLUSPLUS :PrefixIncDec(_token); break; case TK_DELETE : DeleteExpr(); break; - case TK_DELEGATE : DelegateExpr(); break; case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); break; default: Error(_SC("expression expected")); } return -1; } + void EmitLoadConstInt(SQInteger value,SQInteger target) + { + if(target < 0) { + target = _fs->PushTarget(); + } + if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits? + _fs->AddInstruction(_OP_LOADINT, target,value); + } + else { + _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); + } + } + void EmitLoadConstFloat(SQFloat value,SQInteger target) + { + if(target < 0) { + target = _fs->PushTarget(); + } + if(sizeof(SQFloat) == sizeof(SQInt32)) { + _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value)); + } + else { + _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); + } + } void UnaryOP(SQOpcode op) { - Lex(); PrefixedExpr(); + PrefixedExpr(); SQInteger src = _fs->PopTarget(); _fs->AddInstruction(op, _fs->PushTarget(), src); } bool NeedGet() { switch(_token) { - case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS: - case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ: + case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ: + case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return false; } - return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('['))); + return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('[')))); } - void FunctionCallArgs() { SQInteger nargs = 1;//this while(_token != _SC(')')) { - Expression(true); + Expression(); MoveIfCurrentTargetIsLocal(); nargs++; if(_token == _SC(',')){ @@ -783,17 +908,16 @@ public: SQInteger closure = _fs->PopTarget(); _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); } - void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}') + void ParseTableOrClass(SQInteger separator,SQInteger terminator) { SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; - while(_token != terminator) { bool hasattrs = false; bool isstatic = false; //check if is an attribute if(separator == ';') { if(_token == TK_ATTR_OPEN) { - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex(); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex(); ParseTableOrClass(',',TK_ATTR_CLOSE); hasattrs = true; } @@ -803,36 +927,45 @@ public: } } switch(_token) { - case TK_FUNCTION: - case TK_CONSTRUCTOR:{ - SQInteger tk = _token; - Lex(); - SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); - Expect(_SC('(')); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - CreateFunction(id); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - } - break; - case _SC('['): - Lex(); CommaExpr(); Expect(_SC(']')); - Expect(_SC('=')); Expression(); + case TK_FUNCTION: + case TK_CONSTRUCTOR:{ + SQInteger tk = _token; + Lex(); + SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); + Expect(_SC('(')); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + } + break; + case _SC('['): + Lex(); CommaExpr(); Expect(_SC(']')); + Expect(_SC('=')); Expression(); + break; + case TK_STRING_LITERAL: //JSON + if(separator == ',') { //only works for tables + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL))); + Expect(_SC(':')); Expression(); break; - default : - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - Expect(_SC('=')); Expression(); + } + default : + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + Expect(_SC('=')); Expression(); } - if(_token == separator) Lex();//optional comma/semicolon nkeys++; SQInteger val = _fs->PopTarget(); SQInteger key = _fs->PopTarget(); SQInteger attrs = hasattrs ? _fs->PopTarget():-1; - assert(hasattrs && attrs == key-1 || !hasattrs); + assert((hasattrs && (attrs == key-1)) || !hasattrs); unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOTA, flags, table, key, val); - //_fs->PopTarget(); + if(separator == _SC(',')) { //hack recognizes a table from the separator + _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val); + } + else { + _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember + } } if(separator == _SC(',')) //hack recognizes a table from the separator _fs->SetIntructionParam(tpos, 1, nkeys); @@ -841,8 +974,20 @@ public: void LocalDeclStatement() { SQObject varname; + Lex(); + if( _token == TK_FUNCTION) { + Lex(); + varname = Expect(TK_IDENTIFIER); + Expect(_SC('(')); + CreateFunction(varname,false); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + _fs->PopTarget(); + _fs->PushLocalVariable(varname); + return; + } + do { - Lex(); varname = Expect(TK_IDENTIFIER); + varname = Expect(TK_IDENTIFIER); if(_token == _SC('=')) { Lex(); Expression(); SQInteger src = _fs->PopTarget(); @@ -854,8 +999,8 @@ public: } _fs->PopTarget(); _fs->PushLocalVariable(varname); - - } while(_token == _SC(',')); + if(_token == _SC(',')) Lex(); else break; + } while(1); } void IfStatement() { @@ -864,22 +1009,22 @@ public: Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); SQInteger jnepos = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Statement(); // if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon(); - CleanStack(stacksize); + END_SCOPE(); SQInteger endifblock = _fs->GetCurrentPos(); if(_token == TK_ELSE){ haselse = true; - stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); _fs->AddInstruction(_OP_JMP); jmppos = _fs->GetCurrentPos(); Lex(); Statement(); OptionalSemicolon(); - CleanStack(stacksize); + END_SCOPE(); _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); } _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); @@ -887,18 +1032,17 @@ public: void WhileStatement() { SQInteger jzpos, jmppos; - SQInteger stacksize = _fs->GetStackSize(); jmppos = _fs->GetCurrentPos(); Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); BEGIN_BREAKBLE_BLOCK(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); - stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Statement(); - CleanStack(stacksize); + END_SCOPE(); _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); @@ -907,21 +1051,22 @@ public: void DoWhileStatement() { Lex(); - SQInteger jzpos = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); + SQInteger jmptrg = _fs->GetCurrentPos(); BEGIN_BREAKBLE_BLOCK() + BEGIN_SCOPE(); Statement(); - CleanStack(stacksize); + END_SCOPE(); Expect(TK_WHILE); SQInteger continuetrg = _fs->GetCurrentPos(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1); + _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1); END_BREAKBLE_BLOCK(continuetrg); } void ForStatement() { Lex(); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Expect(_SC('(')); if(_token == TK_LOCAL) LocalDeclStatement(); else if(_token != _SC(';')){ @@ -959,7 +1104,7 @@ public: } _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - CleanStack(stacksize); + END_SCOPE(); END_BREAKBLE_BLOCK(continuetrg); } @@ -977,7 +1122,7 @@ public: Expect(TK_IN); //save the stack size - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); //put the table in the stack(evaluate the table expression) Expression(); Expect(_SC(')')); SQInteger container = _fs->TopTarget(); @@ -1000,9 +1145,10 @@ public: _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos); - //restore the local variable stack(remove index,val and ref idx) - CleanStack(stacksize); END_BREAKBLE_BLOCK(foreachpos - 1); + //restore the local variable stack(remove index,val and ref idx) + _fs->PopTarget(); + END_SCOPE(); } void SwitchStatement() { @@ -1015,7 +1161,6 @@ public: SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); _fs->_breaktargets.push_back(0); while(_token == TK_CASE) { - //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one if(!bfirst) { _fs->AddInstruction(_OP_JMP, 0, 0); skipcondjmp = _fs->GetCurrentPos(); @@ -1031,26 +1176,24 @@ public: _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); } tonextcondjmp = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Statements(); - _fs->SetStackSize(stacksize); + END_SCOPE(); bfirst = false; } if(tonextcondjmp != -1) _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); if(_token == TK_DEFAULT) { - // _fs->AddLineInfos(_lex._currentline, _lineinfo); Lex(); Expect(_SC(':')); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Statements(); - _fs->SetStackSize(stacksize); + END_SCOPE(); } Expect(_SC('}')); _fs->PopTarget(); __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); _fs->_breaktargets.pop_back(); - } void FunctionStatement() { @@ -1074,23 +1217,28 @@ public: } void ClassStatement() { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; + SQExpState es; + Lex(); + es = _es; + _es.donot_get = true; PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name")); - if(es._deref == DEREF_FIELD) { + if(_es.etype == EXPR) { + Error(_SC("invalid class name")); + } + else if(_es.etype == OBJECT || _es.etype == BASE) { ClassExp(); EmitDerefOp(_OP_NEWSLOT); _fs->PopTarget(); } - else Error(_SC("cannot create a class in a local with the syntax(class )")); + else { + Error(_SC("cannot create a class in a local with the syntax(class )")); + } + _es = es; } SQObject ExpectScalar() { SQObject val; + val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x switch(_token) { case TK_INTEGER: val._type = OT_INTEGER; @@ -1120,14 +1268,13 @@ public: } break; default: - Error(_SC("scalar expected : integer,float or string")); + Error(_SC("scalar expected : integer,float or string")); } Lex(); return val; } void EnumStatement() { - Lex(); SQObject id = Expect(TK_IDENTIFIER); Expect(_SC('{')); @@ -1150,15 +1297,9 @@ public: } SQTable *enums = _table(_ss(_vm)->_consts); SQObjectPtr strongid = id; - /*SQObjectPtr dummy; - if(enums->Get(strongid,dummy)) { - dummy.Null(); strongid.Null(); - Error(_SC("enumeration already exists")); - }*/ enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table)); strongid.Null(); Lex(); - } void TryCatchStatement() { @@ -1169,7 +1310,11 @@ public: if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; SQInteger trappos = _fs->GetCurrentPos(); - Statement(); + { + BEGIN_SCOPE(); + Statement(); + END_SCOPE(); + } _fs->_traps--; _fs->AddInstruction(_OP_POPTRAP, 1, 0); if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; @@ -1178,17 +1323,20 @@ public: SQInteger jmppos = _fs->GetCurrentPos(); _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); - SQInteger stacksize = _fs->GetStackSize(); - SQInteger ex_target = _fs->PushLocalVariable(exid); - _fs->SetIntructionParam(trappos, 0, ex_target); - Statement(); - _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); - CleanStack(stacksize); + { + BEGIN_SCOPE(); + SQInteger ex_target = _fs->PushLocalVariable(exid); + _fs->SetIntructionParam(trappos, 0, ex_target); + Statement(); + _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); + END_SCOPE(); + } } - void FunctionExp(SQInteger ftype) + void FunctionExp(SQInteger ftype,bool lambda = false) { Lex(); Expect(_SC('(')); - CreateFunction(_null_); + SQObjectPtr dummy; + CreateFunction(dummy,lambda); _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); } void ClassExp() @@ -1201,53 +1349,61 @@ public: } if(_token == TK_ATTR_OPEN) { Lex(); - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); attrs = _fs->TopTarget(); } Expect(_SC('{')); if(attrs != -1) _fs->PopTarget(); if(base != -1) _fs->PopTarget(); - _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs); - ParseTableOrClass(_SC(';')); - } - void DelegateExpr() - { - Lex(); CommaExpr(); - Expect(_SC(':')); - CommaExpr(); - SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget(); - _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS); + ParseTableOrClass(_SC(';'),_SC('}')); } void DeleteExpr() { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; + SQExpState es; + Lex(); + es = _es; + _es.donot_get = true; PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression")); - if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE); - else Error(_SC("cannot delete a local")); + if(_es.etype==EXPR) Error(_SC("can't delete an expression")); + if(_es.etype==OBJECT || _es.etype==BASE) { + Emit2ArgsOP(_OP_DELETE); + } + else { + Error(_SC("cannot delete an (outer) local")); + } + _es = es; } void PrefixIncDec(SQInteger token) { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; + SQExpState es; + SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1; + Lex(); + es = _es; + _es.donot_get = true; PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1); - else { - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1); + if(_es.etype==EXPR) { + Error(_SC("can't '++' or '--' an expression")); + } + else if(_es.etype==OBJECT || _es.etype==BASE) { + Emit2ArgsOP(_OP_INC, diff); + } + else if(_es.etype==LOCAL) { + SQInteger src = _fs->TopTarget(); + _fs->AddInstruction(_OP_INCL, src, src, 0, diff); + + } + else if(_es.etype==OUTER) { + SQInteger tmp = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos); + _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff); + _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp); } + _es = es; } - void CreateFunction(SQObject &name) + void CreateFunction(SQObject &name,bool lambda = false) { - SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); funcstate->_name = name; SQObject paramname; @@ -1257,6 +1413,7 @@ public: while(_token!=_SC(')')) { if(_token == TK_VARPARAMS) { if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters")); + funcstate->AddParameter(_fs->CreateString(_SC("vargv"))); funcstate->_varparams = true; Lex(); if(_token != _SC(')')) Error(_SC("expected ')'")); @@ -1282,26 +1439,19 @@ public: for(SQInteger n = 0; n < defparams; n++) { _fs->PopTarget(); } - //outer values - if(_token == _SC(':')) { - Lex(); Expect(_SC('(')); - while(_token != _SC(')')) { - paramname = Expect(TK_IDENTIFIER); - //outers are treated as implicit local variables - funcstate->AddOuterValue(paramname); - if(_token == _SC(',')) Lex(); - else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); - } - Lex(); - } - + SQFuncState *currchunk = _fs; _fs = funcstate; - Statement(); + if(lambda) { + Expression(); + _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());} + else { + Statement(false); + } funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); funcstate->AddInstruction(_OP_RETURN, -1); funcstate->SetStackSize(0); - //_fs->->_stacksize = _fs->_stacksize; + SQFunctionProto *func = funcstate->BuildProto(); #ifdef _DEBUG_DUMP funcstate->Dump(func); @@ -1310,11 +1460,6 @@ public: _fs->_functions.push_back(func); _fs->PopChildState(); } - void CleanStack(SQInteger stacksize) - { - if(_fs->GetStackSize() != stacksize) - _fs->SetStackSize(stacksize); - } void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) { while(ntoresolve > 0) { @@ -1344,7 +1489,8 @@ private: bool _raiseerror; SQInteger _debugline; SQInteger _debugop; - ExpStateVec _expstates; + SQExpState _es; + SQScope _scope; SQChar *compilererror; jmp_buf _errorjmp; SQVM *_vm; @@ -1355,3 +1501,5 @@ bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcena SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo); return p.Compile(out); } + +#endif diff --git a/external/squirrel/squirrel/sqcompiler.h b/external/squirrel/squirrel/sqcompiler.h old mode 100755 new mode 100644 index deab994ad..fcfd46a99 --- a/external/squirrel/squirrel/sqcompiler.h +++ b/external/squirrel/squirrel/sqcompiler.h @@ -8,7 +8,7 @@ struct SQVM; #define TK_STRING_LITERAL 259 #define TK_INTEGER 260 #define TK_FLOAT 261 -#define TK_DELEGATE 262 +#define TK_BASE 262 #define TK_DELETE 263 #define TK_EQ 264 #define TK_NE 265 @@ -51,15 +51,15 @@ struct SQVM; #define TK_THIS 302 #define TK_PLUSPLUS 303 #define TK_MINUSMINUS 304 -#define TK_PARENT 305 +#define TK_3WAYSCMP 305 #define TK_USHIFTR 306 #define TK_CLASS 307 #define TK_EXTENDS 308 #define TK_CONSTRUCTOR 310 #define TK_INSTANCEOF 311 #define TK_VARPARAMS 312 -#define TK_VARGC 313 -#define TK_VARGV 314 +//#define TK_VARGC 313 +//#define TK_VARGV 314 #define TK_TRUE 315 #define TK_FALSE 316 #define TK_MULEQ 317 diff --git a/external/squirrel/squirrel/sqdebug.cpp b/external/squirrel/squirrel/sqdebug.cpp old mode 100755 new mode 100644 index d027f6105..6f392318a --- a/external/squirrel/squirrel/sqdebug.cpp +++ b/external/squirrel/squirrel/sqdebug.cpp @@ -15,7 +15,7 @@ SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi) SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; if(sq_isclosure(ci._closure)) { SQClosure *c = _closure(ci._closure); - SQFunctionProto *proto = _funcproto(c->_function); + SQFunctionProto *proto = c->_function; fi->funcid = proto; fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown"); fi->source = type(proto->_name) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown"); @@ -33,7 +33,7 @@ SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si) SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; switch (type(ci._closure)) { case OT_CLOSURE:{ - SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function); + SQFunctionProto *func = _closure(ci._closure)->_function; if (type(func->_name) == OT_STRING) si->funcname = _stringval(func->_name); if (type(func->_sourcename) == OT_STRING) @@ -64,17 +64,17 @@ void SQVM::Raise_Error(const SQChar *s, ...) _lasterror = SQString::Create(_ss(this),_spval,-1); } -void SQVM::Raise_Error(SQObjectPtr &desc) +void SQVM::Raise_Error(const SQObjectPtr &desc) { _lasterror = desc; } -SQString *SQVM::PrintObjVal(const SQObject &o) +SQString *SQVM::PrintObjVal(const SQObjectPtr &o) { switch(type(o)) { case OT_STRING: return _string(o); case OT_INTEGER: - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o)); + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _PRINT_INT_FMT, _integer(o)); return SQString::Create(_ss(this), _spval); break; case OT_FLOAT: @@ -86,7 +86,7 @@ SQString *SQVM::PrintObjVal(const SQObject &o) } } -void SQVM::Raise_IdxError(SQObject &o) +void SQVM::Raise_IdxError(const SQObjectPtr &o) { SQObjectPtr oval = PrintObjVal(o); Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); @@ -95,7 +95,7 @@ void SQVM::Raise_IdxError(SQObject &o) void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2) { SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); - Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); + Raise_Error(_SC("comparison between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); } diff --git a/external/squirrel/squirrel/sqfuncproto.h b/external/squirrel/squirrel/sqfuncproto.h old mode 100755 new mode 100644 index 50c6fd71f..cd48aa6df --- a/external/squirrel/squirrel/sqfuncproto.h +++ b/external/squirrel/squirrel/sqfuncproto.h @@ -6,8 +6,7 @@ enum SQOuterType { otLOCAL = 0, - otSYMBOL = 1, - otOUTER = 2 + otOUTER = 1 }; struct SQOuterVar @@ -33,7 +32,7 @@ struct SQOuterVar struct SQLocalVarInfo { - SQLocalVarInfo():_start_op(0),_end_op(0){} + SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){} SQLocalVarInfo(const SQLocalVarInfo &lvi) { _name=lvi._name; @@ -59,25 +58,15 @@ typedef sqvector SQLineInfoVec; +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \ +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger))) -#define _CONSTRUCT_VECTOR(type,size,ptr) { \ - for(SQInteger n = 0; n < size; n++) { \ - new (&ptr[n]) type(); \ - } \ -} - -#define _DESTRUCT_VECTOR(type,size,ptr) { \ - for(SQInteger nl = 0; nl < size; nl++) { \ - ptr[nl].~type(); \ - } \ -} -struct SQFunctionProto : public SQRefCounted + +struct SQFunctionProto : public CHAINABLE_OBJ { private: - SQFunctionProto(){ - _stacksize=0; - _bgenerator=false;} + SQFunctionProto(SQSharedState *ss); + ~SQFunctionProto(); + public: - static SQFunctionProto *Create(SQInteger ninstructions, + static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions, SQInteger nliterals,SQInteger nparameters, SQInteger nfunctions,SQInteger noutervalues, SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams) @@ -85,7 +74,7 @@ public: SQFunctionProto *f; //I compact the whole class and members in a single memory allocation f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams)); - new (f) SQFunctionProto; + new (f) SQFunctionProto(ss); f->_ninstructions = ninstructions; f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions]; f->_nliterals = nliterals; @@ -121,16 +110,21 @@ public: this->~SQFunctionProto(); sq_vm_free(this,size); } + const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); SQInteger GetLine(SQInstruction *curr); bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); - +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); } + SQObjectType GetType() {return OT_FUNCPROTO;} +#endif SQObjectPtr _sourcename; SQObjectPtr _name; SQInteger _stacksize; bool _bgenerator; - bool _varparams; + SQInteger _varparams; SQInteger _nlocalvarinfos; SQLocalVarInfo *_localvarinfos; diff --git a/external/squirrel/squirrel/sqfuncstate.cpp b/external/squirrel/squirrel/sqfuncstate.cpp old mode 100755 new mode 100644 index 525a49996..aff80e59d --- a/external/squirrel/squirrel/sqfuncstate.cpp +++ b/external/squirrel/squirrel/sqfuncstate.cpp @@ -2,9 +2,10 @@ see copyright notice in squirrel.h */ #include "sqpcheader.h" +#ifndef NO_COMPILER #include "sqcompiler.h" -#include "sqfuncproto.h" #include "sqstring.h" +#include "sqfuncproto.h" #include "sqtable.h" #include "sqopcodes.h" #include "sqfuncstate.h" @@ -28,25 +29,25 @@ SQInstructionDesc g_InstrDesc[]={ {_SC("_OP_GET")}, {_SC("_OP_EQ")}, {_SC("_OP_NE")}, - {_SC("_OP_ARITH")}, + {_SC("_OP_ADD")}, + {_SC("_OP_SUB")}, + {_SC("_OP_MUL")}, + {_SC("_OP_DIV")}, + {_SC("_OP_MOD")}, {_SC("_OP_BITW")}, {_SC("_OP_RETURN")}, {_SC("_OP_LOADNULLS")}, - {_SC("_OP_LOADROOTTABLE")}, + {_SC("_OP_LOADROOT")}, {_SC("_OP_LOADBOOL")}, {_SC("_OP_DMOVE")}, {_SC("_OP_JMP")}, - {_SC("_OP_JNZ")}, + {_SC("_OP_JCMP")}, {_SC("_OP_JZ")}, - {_SC("_OP_LOADFREEVAR")}, - {_SC("_OP_VARGC")}, - {_SC("_OP_GETVARGV")}, - {_SC("_OP_NEWTABLE")}, - {_SC("_OP_NEWARRAY")}, + {_SC("_OP_SETOUTER")}, + {_SC("_OP_GETOUTER")}, + {_SC("_OP_NEWOBJ")}, {_SC("_OP_APPENDARRAY")}, - {_SC("_OP_GETPARENT")}, {_SC("_OP_COMPARITH")}, - {_SC("_OP_COMPARITHL")}, {_SC("_OP_INC")}, {_SC("_OP_INCL")}, {_SC("_OP_PINC")}, @@ -64,14 +65,15 @@ SQInstructionDesc g_InstrDesc[]={ {_SC("_OP_RESUME")}, {_SC("_OP_FOREACH")}, {_SC("_OP_POSTFOREACH")}, - {_SC("_OP_DELEGATE")}, {_SC("_OP_CLONE")}, {_SC("_OP_TYPEOF")}, {_SC("_OP_PUSHTRAP")}, {_SC("_OP_POPTRAP")}, {_SC("_OP_THROW")}, - {_SC("_OP_CLASS")}, - {_SC("_OP_NEWSLOTA")} + {_SC("_OP_NEWSLOTA")}, + {_SC("_OP_GETBASE")}, + {_SC("_OP_CLOSE")}, + {_SC("_OP_JCMP")} }; #endif void DumpLiteral(SQObjectPtr &o) @@ -79,9 +81,9 @@ void DumpLiteral(SQObjectPtr &o) switch(type(o)){ case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break; case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break; - case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break; + case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break; case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break; - default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler + default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler } } @@ -101,6 +103,8 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc _errfunc = efunc; _errtarget = ed; _bgenerator = false; + _outers = 0; + _ss = ss; } @@ -195,11 +199,12 @@ void SQFuncState::Dump(SQFunctionProto *func) else if(inst.op==_OP_LOADFLOAT) { scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3); } - else if(inst.op==_OP_ARITH){ + /* else if(inst.op==_OP_ARITH){ scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); - } - else + }*/ + else { scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + } n++; } scprintf(_SC("-----\n")); @@ -283,8 +288,9 @@ SQInteger SQFuncState::TopTarget(){ } SQInteger SQFuncState::PopTarget() { - SQInteger npos=_targetstack.back(); - SQLocalVarInfo t=_vlocals[_targetstack.back()]; + SQUnsignedInteger npos=_targetstack.back(); + assert(npos < _vlocals.size()); + SQLocalVarInfo &t = _vlocals[npos]; if(type(t._name)==OT_NULL){ _vlocals.pop_back(); } @@ -297,14 +303,31 @@ SQInteger SQFuncState::GetStackSize() return _vlocals.size(); } +SQInteger SQFuncState::CountOuters(SQInteger stacksize) +{ + SQInteger outers = 0; + SQInteger k = _vlocals.size() - 1; + while(k >= stacksize) { + SQLocalVarInfo &lvi = _vlocals[k]; + k--; + if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer + outers++; + } + } + return outers; +} + void SQFuncState::SetStackSize(SQInteger n) { SQInteger size=_vlocals.size(); while(size>n){ size--; - SQLocalVarInfo lvi=_vlocals.back(); + SQLocalVarInfo lvi = _vlocals.back(); if(type(lvi._name)!=OT_NULL){ - lvi._end_op=GetCurrentPos(); + if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer + _outers--; + } + lvi._end_op = GetCurrentPos(); _localvarinfos.push_back(lvi); } _vlocals.pop_back(); @@ -337,15 +360,17 @@ SQInteger SQFuncState::PushLocalVariable(const SQObject &name) lvi._pos=_vlocals.size(); _vlocals.push_back(lvi); if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); - return pos; } + + SQInteger SQFuncState::GetLocalVariable(const SQObject &name) { SQInteger locals=_vlocals.size(); while(locals>=1){ - if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){ + SQLocalVarInfo &lvi = _vlocals[locals-1]; + if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){ return locals-1; } locals--; @@ -353,6 +378,13 @@ SQInteger SQFuncState::GetLocalVariable(const SQObject &name) return -1; } +void SQFuncState::MarkLocalAsOuter(SQInteger pos) +{ + SQLocalVarInfo &lvi = _vlocals[pos]; + lvi._end_op = UINT_MINUS_ONE; + _outers++; +} + SQInteger SQFuncState::GetOuterVariable(const SQObject &name) { SQInteger outers = _outervalues.size(); @@ -360,11 +392,6 @@ SQInteger SQFuncState::GetOuterVariable(const SQObject &name) if(_string(_outervalues[i]._name) == _string(name)) return i; } - return -1; -} - -void SQFuncState::AddOuterValue(const SQObject &name) -{ SQInteger pos=-1; if(_parent) { pos = _parent->GetLocalVariable(name); @@ -372,15 +399,18 @@ void SQFuncState::AddOuterValue(const SQObject &name) pos = _parent->GetOuterVariable(name); if(pos != -1) { _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local - return; + return _outervalues.size() - 1; } } else { + _parent->MarkLocalAsOuter(pos); _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local - return; + return _outervalues.size() - 1; + + } - } - _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global + } + return -1; } void SQFuncState::AddParameter(const SQObject &name) @@ -395,20 +425,58 @@ void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force) SQLineInfo li; li._line=line;li._op=(GetCurrentPos()+1); if(lineop)AddInstruction(_OP_LINE,0,line); - _lineinfos.push_back(li); + if(_lastline!=line) { + _lineinfos.push_back(li); + } _lastline=line; } } +void SQFuncState::DiscardTarget() +{ + SQInteger discardedtarget = PopTarget(); + SQInteger size = _instructions.size(); + if(size > 0 && _optimization){ + SQInstruction &pi = _instructions[size-1];//previous instruction + switch(pi.op) { + case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL: + if(pi._arg0 == discardedtarget) { + pi._arg0 = 0xFF; + } + } + } +} + void SQFuncState::AddInstruction(SQInstruction &i) { SQInteger size = _instructions.size(); if(size > 0 && _optimization){ //simple optimizer SQInstruction &pi = _instructions[size-1];//previous instruction switch(i.op) { + case _OP_JZ: + if( pi.op == _OP_CMP && pi._arg1 < 0xFF) { + pi.op = _OP_JCMP; + pi._arg0 = (unsigned char)pi._arg1; + pi._arg1 = i._arg1; + return; + } + case _OP_SET: + case _OP_NEWSLOT: + if(i._arg0 == i._arg3) { + i._arg0 = 0xFF; + } + break; + case _OP_SETOUTER: + if(i._arg0 == i._arg2) { + i._arg0 = 0xFF; + } + break; case _OP_RETURN: if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { pi.op = _OP_TAILCALL; + } else if(pi.op == _OP_CLOSE){ + pi = i; + return; } break; case _OP_GET: @@ -431,22 +499,37 @@ void SQFuncState::AddInstruction(SQInstruction &i) return; } break; - case _OP_APPENDARRAY: - if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + case _OP_APPENDARRAY: { + SQInteger aat = -1; + switch(pi.op) { + case _OP_LOAD: aat = AAT_LITERAL; break; + case _OP_LOADINT: aat = AAT_INT; break; + case _OP_LOADBOOL: aat = AAT_BOOL; break; + case _OP_LOADFLOAT: aat = AAT_FLOAT; break; + default: break; + } + if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ pi.op = _OP_APPENDARRAY; pi._arg0 = i._arg0; pi._arg1 = pi._arg1; - pi._arg2 = MAX_FUNC_STACKSIZE; + pi._arg2 = (unsigned char)aat; pi._arg3 = MAX_FUNC_STACKSIZE; return; } + } break; - case _OP_MOVE: - if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1)) - { - pi._arg0 = i._arg0; - _optimization = false; - return; + case _OP_MOVE: + switch(pi.op) { + case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW: + case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD: + + if(pi._arg0 == i._arg1) + { + pi._arg0 = i._arg0; + _optimization = false; + //_result_elimination = false; + return; + } } if(pi.op == _OP_MOVE) @@ -512,7 +595,8 @@ SQObject SQFuncState::CreateTable() SQFunctionProto *SQFuncState::BuildProto() { - SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(), + + SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(), _nliterals,_parameters.size(),_functions.size(),_outervalues.size(), _lineinfos.size(),_localvarinfos.size(),_defaultparams.size()); @@ -532,9 +616,9 @@ SQFunctionProto *SQFuncState::BuildProto() for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf]; for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np]; for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no]; - for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no]; - for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no]; - for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no]; + for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl]; + for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni]; + for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd]; memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction)); @@ -565,3 +649,5 @@ SQFuncState::~SQFuncState() PopChildState(); } } + +#endif diff --git a/external/squirrel/squirrel/sqfuncstate.h b/external/squirrel/squirrel/sqfuncstate.h old mode 100755 new mode 100644 index 775a33e1e..1da13212a --- a/external/squirrel/squirrel/sqfuncstate.h +++ b/external/squirrel/squirrel/sqfuncstate.h @@ -21,6 +21,7 @@ struct SQFuncState SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];} void PopInstructions(SQInteger size){for(SQInteger i=0;i _childstates; @@ -78,6 +83,7 @@ struct SQFuncState private: CompilerErrorFunc _errfunc; void *_errtarget; + SQSharedState *_ss; }; diff --git a/external/squirrel/squirrel/sqlexer.cpp b/external/squirrel/squirrel/sqlexer.cpp old mode 100755 new mode 100644 index 03268258d..547835b6c --- a/external/squirrel/squirrel/sqlexer.cpp +++ b/external/squirrel/squirrel/sqlexer.cpp @@ -44,7 +44,7 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile ADD_KEYWORD(foreach, TK_FOREACH); ADD_KEYWORD(in, TK_IN); ADD_KEYWORD(typeof, TK_TYPEOF); - ADD_KEYWORD(delegate, TK_DELEGATE); + ADD_KEYWORD(base, TK_BASE); ADD_KEYWORD(delete, TK_DELETE); ADD_KEYWORD(try, TK_TRY); ADD_KEYWORD(catch, TK_CATCH); @@ -56,13 +56,10 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile ADD_KEYWORD(case, TK_CASE); ADD_KEYWORD(default, TK_DEFAULT); ADD_KEYWORD(this, TK_THIS); - ADD_KEYWORD(parent,TK_PARENT); ADD_KEYWORD(class,TK_CLASS); ADD_KEYWORD(extends,TK_EXTENDS); ADD_KEYWORD(constructor,TK_CONSTRUCTOR); ADD_KEYWORD(instanceof,TK_INSTANCEOF); - ADD_KEYWORD(vargc,TK_VARGC); - ADD_KEYWORD(vargv,TK_VARGV); ADD_KEYWORD(true,TK_TRUE); ADD_KEYWORD(false,TK_FALSE); ADD_KEYWORD(static,TK_STATIC); @@ -74,6 +71,7 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile _lasttokenline = _currentline = 1; _currentcolumn = 0; _prevtoken = -1; + _reached_eof = SQFalse; Next(); } @@ -91,6 +89,7 @@ void SQLexer::Next() return; } _currdata = SQUIRREL_EOB; + _reached_eof = SQTrue; } const SQChar *SQLexer::Tok2Str(SQInteger tok) @@ -117,6 +116,10 @@ void SQLexer::LexBlockComment() } } } +void SQLexer::LexLineComment() +{ + do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); +} SQInteger SQLexer::Lex() { @@ -131,6 +134,7 @@ SQInteger SQLexer::Lex() NEXT(); _currentcolumn=1; continue; + case _SC('#'): LexLineComment(); continue; case _SC('/'): NEXT(); switch(CUR_CHAR){ @@ -139,7 +143,7 @@ SQInteger SQLexer::Lex() LexBlockComment(); continue; case _SC('/'): - do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); + LexLineComment(); continue; case _SC('='): NEXT(); @@ -158,12 +162,20 @@ SQInteger SQLexer::Lex() else { NEXT(); RETURN_TOKEN(TK_EQ); } case _SC('<'): NEXT(); - if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) } - else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); } - else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); } - else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); } - //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); } - else { RETURN_TOKEN('<') } + switch(CUR_CHAR) { + case _SC('='): + NEXT(); + if(CUR_CHAR == _SC('>')) { + NEXT(); + RETURN_TOKEN(TK_3WAYSCMP); + } + RETURN_TOKEN(TK_LE) + break; + case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break; + case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break; + case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break; + } + RETURN_TOKEN('<'); case _SC('>'): NEXT(); if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} @@ -182,9 +194,10 @@ SQInteger SQLexer::Lex() else { NEXT(); RETURN_TOKEN(TK_NE); } case _SC('@'): { SQInteger stype; - NEXT(); - if(CUR_CHAR != _SC('"')) - Error(_SC("string expected")); + NEXT(); + if(CUR_CHAR != _SC('"')) { + RETURN_TOKEN('@'); + } if((stype=ReadString('"',true))!=-1) { RETURN_TOKEN(stype); } diff --git a/external/squirrel/squirrel/sqlexer.h b/external/squirrel/squirrel/sqlexer.h old mode 100755 new mode 100644 index aedff1560..d3283c6f7 --- a/external/squirrel/squirrel/sqlexer.h +++ b/external/squirrel/squirrel/sqlexer.h @@ -21,10 +21,12 @@ private: SQInteger ReadString(SQInteger ndelim,bool verbatim); SQInteger ReadNumber(); void LexBlockComment(); + void LexLineComment(); SQInteger ReadID(); void Next(); SQInteger _curtoken; SQTable *_keywords; + SQBool _reached_eof; public: SQInteger _prevtoken; SQInteger _currentline; diff --git a/external/squirrel/squirrel/sqmem.cpp b/external/squirrel/squirrel/sqmem.cpp old mode 100755 new mode 100644 diff --git a/external/squirrel/squirrel/sqobject.cpp b/external/squirrel/squirrel/sqobject.cpp old mode 100755 new mode 100644 index 40c5ba44c..bdcbfa6ed --- a/external/squirrel/squirrel/sqobject.cpp +++ b/external/squirrel/squirrel/sqobject.cpp @@ -35,6 +35,7 @@ const SQChar *IdType2Name(SQObjectType type) case _RT_CLASS: return _SC("class"); case _RT_INSTANCE: return _SC("instance"); case _RT_WEAKREF: return _SC("weakref"); + case _RT_OUTER: return _SC("outer"); default: return NULL; } @@ -48,7 +49,6 @@ const SQChar *GetTypeName(const SQObjectPtr &obj1) SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len) { SQString *str=ADD_STRING(ss,s,len); - str->_sharedstate=ss; return str; } @@ -62,7 +62,7 @@ SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjec SQInteger idx = (SQInteger)TranslateIndex(refpos); while(idx < _len){ outkey = (SQInteger)idx; - outval = SQInteger(_val[idx]); + outval = (SQInteger)((SQUnsignedInteger)_val[idx]); //return idx for the next iteration return ++idx; } @@ -128,22 +128,24 @@ bool SQDelegable::SetDelegate(SQTable *mt) return true; } -bool SQGenerator::Yield(SQVM *v) +bool SQGenerator::Yield(SQVM *v,SQInteger target) { if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } SQInteger size = v->_top-v->_stackbase; - _ci=*v->ci; + _stack.resize(size); - for(SQInteger n =0; n_stack[v->_stackbase]; + _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this; + for(SQInteger n =1; n_stack[v->_stackbase+n]; - v->_stack[v->_stackbase+n] = _null_; } - SQInteger nvargs = v->ci->_vargs.size; - SQInteger vargsbase = v->ci->_vargs.base; - for(SQInteger j = nvargs - 1; j >= 0; j--) { - _vargsstack.push_back(v->_vargsstack[vargsbase+j]); + for(SQInteger j =0; j < size; j++) + { + v->_stack[v->_stackbase+j].Null(); } + + _ci = *v->ci; _ci._generator=NULL; for(SQInteger i=0;i<_ci._etraps;i++) { _etraps.push_back(v->_etraps.top()); @@ -153,37 +155,39 @@ bool SQGenerator::Yield(SQVM *v) return true; } -bool SQGenerator::Resume(SQVM *v,SQInteger target) +bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest) { - SQInteger size=_stack.size(); if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } - SQInteger prevtop=v->_top-v->_stackbase; - PUSH_CALLINFO(v,_ci); - SQInteger oldstackbase=v->_stackbase; - v->_stackbase = v->_top; - v->ci->_target = (SQInt32)target; - v->ci->_generator = this; - v->ci->_vargs.size = (unsigned short)_vargsstack.size(); - + SQInteger size = _stack.size(); + SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]); + assert(target>=0 && target<=255); + if(!v->EnterFrame(v->_top, v->_top + size, false)) + return false; + v->ci->_generator = this; + v->ci->_target = (SQInt32)target; + v->ci->_closure = _ci._closure; + v->ci->_ip = _ci._ip; + v->ci->_literals = _ci._literals; + v->ci->_ncalls = _ci._ncalls; + v->ci->_etraps = _ci._etraps; + v->ci->_root = _ci._root; + + for(SQInteger i=0;i<_ci._etraps;i++) { v->_etraps.push_back(_etraps.top()); _etraps.pop_back(); } - for(SQInteger n =0; n_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this; + + for(SQInteger n = 1; n_stack[v->_stackbase+n] = _stack._vals[n]; - _stack._vals[0] = _null_; + _stack._vals[n].Null(); } - while(_vargsstack.size()) { - v->_vargsstack.push_back(_vargsstack.back()); - _vargsstack.pop_back(); - } - v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size); - v->_top=v->_stackbase+size; - v->ci->_prevtop = (SQInt32)prevtop; - v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase); + _state=eRunning; - if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure)) + if (v->_debughook) v->CallDebugHook(_SC('c')); return true; @@ -216,18 +220,45 @@ const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQU return res; } + SQInteger SQFunctionProto::GetLine(SQInstruction *curr) { SQInteger op = (SQInteger)(curr-_instructions); SQInteger line=_lineinfos[0]._line; - for(SQInteger i=1;i<_nlineinfos;i++){ - if(_lineinfos[i]._op>=op) - return line; - line=_lineinfos[i]._line; + SQInteger low = 0; + SQInteger high = _nlineinfos - 1; + SQInteger mid = 0; + while(low <= high) + { + mid = low + ((high - low) >> 1); + SQInteger curop = _lineinfos[mid]._op; + if(curop > op) + { + high = mid - 1; + } + else if(curop < op) { + if(mid < (_nlineinfos - 1) + && _lineinfos[mid + 1]._op >= op) { + break; + } + low = mid + 1; + } + else { //equal + break; + } } + + line = _lineinfos[mid]._line; return line; } +SQClosure::~SQClosure() +{ + __ObjRelease(_env); + __ObjRelease(_base); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); +} + #define _CHECK_IO(exp) { if(!exp)return false; } bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size) { @@ -247,14 +278,14 @@ bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest return true; } -bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag) +bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag) { return SafeWrite(v,write,up,&tag,sizeof(tag)); } -bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) +bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag) { - SQInteger t; + SQUnsignedInteger32 t; _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); if(t != tag){ v->Raise_Error(_SC("invalid or corrupted closure stream")); @@ -265,7 +296,8 @@ bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o) { - _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType))); + SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o); + _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type))); switch(type(o)){ case OT_STRING: _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); @@ -286,8 +318,9 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) { - SQObjectType t; - _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType))); + SQUnsignedInteger32 _type; + _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type))); + SQObjectType t = (SQObjectType)_type; switch(t){ case OT_STRING:{ SQInteger len; @@ -305,7 +338,7 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; } case OT_NULL: - o=_null_; + o.Null(); break; default: v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); @@ -318,7 +351,9 @@ bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) { _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); - _CHECK_IO(_funcproto(_function)->Save(v,up,write)); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger))); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat))); + _CHECK_IO(_function->Save(v,up,write)); _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); return true; } @@ -327,6 +362,8 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) { _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger))); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat))); SQObjectPtr func; _CHECK_IO(SQFunctionProto::Load(v,up,read,func)); _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); @@ -334,6 +371,18 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) return true; } +SQFunctionProto::SQFunctionProto(SQSharedState *ss) +{ + _stacksize=0; + _bgenerator=false; + INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); +} + +SQFunctionProto::~SQFunctionProto() +{ + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); +} + bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) { SQInteger i,nliterals = _nliterals,nparameters = _nparameters; @@ -419,7 +468,7 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions))); - SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters, + SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters, nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams); SQObjectPtr proto = f; //gets a ref in case of failure f->_sourcename = sourcename; @@ -492,11 +541,10 @@ void SQVM::Mark(SQCollectable **chain) START_MARK() SQSharedState::MarkObject(_lasterror,chain); SQSharedState::MarkObject(_errorhandler,chain); - SQSharedState::MarkObject(_debughook,chain); + SQSharedState::MarkObject(_debughook_closure,chain); SQSharedState::MarkObject(_roottable, chain); SQSharedState::MarkObject(temp_reg, chain); for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); - for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain); END_MARK() } @@ -534,7 +582,7 @@ void SQClass::Mark(SQCollectable **chain) SQSharedState::MarkObject(_methods[j].val, chain); SQSharedState::MarkObject(_methods[j].attrs, chain); } - for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) { + for(SQUnsignedInteger k =0; k< MT_LAST; k++) { SQSharedState::MarkObject(_metamethods[k], chain); } END_MARK() @@ -555,23 +603,43 @@ void SQGenerator::Mark(SQCollectable **chain) { START_MARK() for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); - for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); SQSharedState::MarkObject(_closure, chain); END_MARK() } +void SQFunctionProto::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain); + for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain); + END_MARK() +} + void SQClosure::Mark(SQCollectable **chain) { START_MARK() - for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); - for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain); + if(_base) _base->Mark(chain); + SQFunctionProto *fp = _function; + fp->Mark(chain); + for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain); + for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain); END_MARK() } void SQNativeClosure::Mark(SQCollectable **chain) { START_MARK() - for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); + for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain); + END_MARK() +} + +void SQOuter::Mark(SQCollectable **chain) +{ + START_MARK() + /* If the valptr points to a closed value, that value is alive */ + if(_valptr == &_value) { + SQSharedState::MarkObject(_value, chain); + } END_MARK() } diff --git a/external/squirrel/squirrel/sqobject.h b/external/squirrel/squirrel/sqobject.h old mode 100755 new mode 100644 index d6f6ef1f7..e0e235e1c --- a/external/squirrel/squirrel/sqobject.h +++ b/external/squirrel/squirrel/sqobject.h @@ -4,6 +4,12 @@ #include "squtils.h" +#ifdef _SQ64 +#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF) +#else +#define UINT_MINUS_ONE (0xFFFFFFFF) +#endif + #define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R')) #define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T')) #define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L')) @@ -51,16 +57,42 @@ enum SQMetaMethod{ #define MM_NEWMEMBER _SC("_newmember") #define MM_INHERITED _SC("_inherited") + +#define _CONSTRUCT_VECTOR(type,size,ptr) { \ + for(SQInteger n = 0; n < ((SQInteger)size); n++) { \ + new (&ptr[n]) type(); \ + } \ +} + +#define _DESTRUCT_VECTOR(type,size,ptr) { \ + for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \ + ptr[nl].~type(); \ + } \ +} + +#define _COPY_VECTOR(dest,src,size) { \ + for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ + dest[_n_] = src[_n_]; \ + } \ +} + +#define _NULL_SQOBJECT_VECTOR(vec,size) { \ + for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ + vec[_n_].Null(); \ + } \ +} + #define MINPOWER2 4 struct SQRefCounted { + SQUnsignedInteger _uiRef; + struct SQWeakRef *_weakref; SQRefCounted() { _uiRef = 0; _weakref = NULL; } virtual ~SQRefCounted(); SQWeakRef *GetWeakRef(SQObjectType type); - SQUnsignedInteger _uiRef; - struct SQWeakRef *_weakref; virtual void Release()=0; + }; struct SQWeakRef : SQRefCounted @@ -78,7 +110,7 @@ struct SQObjectPtr; unval.pRefCounted->_uiRef++; \ } -#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \ +#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0)) \ { \ unval.pRefCounted->Release(); \ } @@ -116,17 +148,61 @@ struct SQObjectPtr; #define _instance(obj) ((obj)._unVal.pInstance) #define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable) #define _weakref(obj) ((obj)._unVal.pWeakRef) +#define _outer(obj) ((obj)._unVal.pOuter) #define _refcounted(obj) ((obj)._unVal.pRefCounted) #define _rawval(obj) ((obj)._unVal.raw) #define _stringval(obj) (obj)._unVal.pString->_val -#define _userdataval(obj) (obj)._unVal.pUserData->_val +#define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1)) #define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num)) -#define tointeger(num) ( (type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) - +#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// +#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64) +#define SQ_REFOBJECT_INIT() SQ_OBJECT_RAWINIT() +#else +#define SQ_REFOBJECT_INIT() +#endif + +#define _REF_TYPE_DECL(type,_class,sym) \ + SQObjectPtr(_class * x) \ + { \ + SQ_OBJECT_RAWINIT() \ + _type=type; \ + _unVal.sym = x; \ + assert(_unVal.pTable); \ + _unVal.pRefCounted->_uiRef++; \ + } \ + inline SQObjectPtr& operator=(_class *x) \ + { \ + SQObjectType tOldType; \ + SQObjectValue unOldVal; \ + tOldType=_type; \ + unOldVal=_unVal; \ + _type = type; \ + SQ_REFOBJECT_INIT() \ + _unVal.sym = x; \ + _unVal.pRefCounted->_uiRef++; \ + __Release(tOldType,unOldVal); \ + return *this; \ + } + +#define _SCALAR_TYPE_DECL(type,_class,sym) \ + SQObjectPtr(_class x) \ + { \ + SQ_OBJECT_RAWINIT() \ + _type=type; \ + _unVal.sym = x; \ + } \ + inline SQObjectPtr& operator=(_class x) \ + { \ + __Release(_type,_unVal); \ + _type = type; \ + SQ_OBJECT_RAWINIT() \ + _unVal.sym = x; \ + return *this; \ + } struct SQObjectPtr : public SQObject { SQObjectPtr() @@ -137,168 +213,54 @@ struct SQObjectPtr : public SQObject } SQObjectPtr(const SQObjectPtr &o) { - SQ_OBJECT_RAWINIT() - _type=o._type; - _unVal=o._unVal; + _type = o._type; + _unVal = o._unVal; __AddRef(_type,_unVal); } SQObjectPtr(const SQObject &o) { - SQ_OBJECT_RAWINIT() - _type=o._type; - _unVal=o._unVal; - __AddRef(_type,_unVal); - } - SQObjectPtr(SQTable *pTable) - { - SQ_OBJECT_RAWINIT() - _type=OT_TABLE; - _unVal.pTable=pTable; - assert(_unVal.pTable); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQClass *pClass) - { - SQ_OBJECT_RAWINIT() - _type=OT_CLASS; - _unVal.pClass=pClass; - assert(_unVal.pClass); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQInstance *pInstance) - { - SQ_OBJECT_RAWINIT() - _type=OT_INSTANCE; - _unVal.pInstance=pInstance; - assert(_unVal.pInstance); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQArray *pArray) - { - SQ_OBJECT_RAWINIT() - _type=OT_ARRAY; - _unVal.pArray=pArray; - assert(_unVal.pArray); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQClosure *pClosure) - { - SQ_OBJECT_RAWINIT() - _type=OT_CLOSURE; - _unVal.pClosure=pClosure; - assert(_unVal.pClosure); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQGenerator *pGenerator) - { - SQ_OBJECT_RAWINIT() - _type=OT_GENERATOR; - _unVal.pGenerator=pGenerator; - assert(_unVal.pGenerator); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQNativeClosure *pNativeClosure) - { - SQ_OBJECT_RAWINIT() - _type=OT_NATIVECLOSURE; - _unVal.pNativeClosure=pNativeClosure; - assert(_unVal.pNativeClosure); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQString *pString) - { - SQ_OBJECT_RAWINIT() - _type=OT_STRING; - _unVal.pString=pString; - assert(_unVal.pString); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQUserData *pUserData) - { - SQ_OBJECT_RAWINIT() - _type=OT_USERDATA; - _unVal.pUserData=pUserData; - assert(_unVal.pUserData); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQVM *pThread) - { - SQ_OBJECT_RAWINIT() - _type=OT_THREAD; - _unVal.pThread=pThread; - assert(_unVal.pThread); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQWeakRef *pWeakRef) - { - SQ_OBJECT_RAWINIT() - _type=OT_WEAKREF; - _unVal.pWeakRef=pWeakRef; - assert(_unVal.pWeakRef); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQFunctionProto *pFunctionProto) - { - SQ_OBJECT_RAWINIT() - _type=OT_FUNCPROTO; - _unVal.pFunctionProto=pFunctionProto; - assert(_unVal.pFunctionProto); + _type = o._type; + _unVal = o._unVal; __AddRef(_type,_unVal); } - SQObjectPtr(SQInteger nInteger) - { - SQ_OBJECT_RAWINIT() - _type=OT_INTEGER; - _unVal.nInteger=nInteger; - } - SQObjectPtr(SQFloat fFloat) - { - SQ_OBJECT_RAWINIT() - _type=OT_FLOAT; - _unVal.fFloat=fFloat; - } + _REF_TYPE_DECL(OT_TABLE,SQTable,pTable) + _REF_TYPE_DECL(OT_CLASS,SQClass,pClass) + _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance) + _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray) + _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure) + _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure) + _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter) + _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator) + _REF_TYPE_DECL(OT_STRING,SQString,pString) + _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData) + _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef) + _REF_TYPE_DECL(OT_THREAD,SQVM,pThread) + _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto) + + _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger) + _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat) + _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer) + SQObjectPtr(bool bBool) { SQ_OBJECT_RAWINIT() _type = OT_BOOL; _unVal.nInteger = bBool?1:0; } - SQObjectPtr(SQUserPointer pUserPointer) - { - SQ_OBJECT_RAWINIT() - _type=OT_USERPOINTER; - _unVal.pUserPointer=pUserPointer; - } - ~SQObjectPtr() - { - __Release(_type,_unVal); - } - inline void Null() - { - SQObjectType tOldType; - SQObjectValue unOldVal; - tOldType = _type; - unOldVal = _unVal; - _type = OT_NULL; - _unVal.pUserPointer = NULL; - __Release(tOldType,unOldVal); - } - inline SQObjectPtr& operator=(SQInteger i) + inline SQObjectPtr& operator=(bool b) { __Release(_type,_unVal); SQ_OBJECT_RAWINIT() - _unVal.nInteger = i; - _type = OT_INTEGER; + _type = OT_BOOL; + _unVal.nInteger = b?1:0; return *this; } - inline SQObjectPtr& operator=(SQFloat f) - { + + ~SQObjectPtr() + { __Release(_type,_unVal); - SQ_OBJECT_RAWINIT() - _unVal.fFloat = f; - _type = OT_FLOAT; - return *this; } + inline SQObjectPtr& operator=(const SQObjectPtr& obj) { SQObjectType tOldType; @@ -323,10 +285,19 @@ struct SQObjectPtr : public SQObject __Release(tOldType,unOldVal); return *this; } + inline void Null() + { + SQObjectType tOldType = _type; + SQObjectValue unOldVal = _unVal; + _type = OT_NULL; + _unVal.raw = (SQRawObjectVal)NULL; + __Release(tOldType ,unOldVal); + } private: SQObjectPtr(const SQChar *){} //safety }; + inline void _Swap(SQObject &a,SQObject &b) { SQObjectType tOldType = a._type; @@ -336,6 +307,7 @@ inline void _Swap(SQObject &a,SQObject &b) b._type = tOldType; b._unVal = unOldVal; } + ///////////////////////////////////////////////////////////////////////////////////// #ifndef NO_GARBAGE_COLLECTOR #define MARK_FLAG 0x80000000 @@ -343,6 +315,7 @@ struct SQCollectable : public SQRefCounted { SQCollectable *_next; SQCollectable *_prev; SQSharedState *_sharedstate; + virtual SQObjectType GetType()=0; virtual void Release()=0; virtual void Mark(SQCollectable **chain)=0; void UnMark(); diff --git a/external/squirrel/squirrel/sqopcodes.h b/external/squirrel/squirrel/sqopcodes.h old mode 100755 new mode 100644 index 3867a5960..4d179812f --- a/external/squirrel/squirrel/sqopcodes.h +++ b/external/squirrel/squirrel/sqopcodes.h @@ -18,8 +18,24 @@ enum CmpOP { CMP_G = 0, CMP_GE = 2, CMP_L = 3, - CMP_LE = 4 + CMP_LE = 4, + CMP_3W = 5 }; + +enum NewObjectType { + NOT_TABLE = 0, + NOT_ARRAY = 1, + NOT_CLASS = 2 +}; + +enum AppendArrayType { + AAT_STACK = 0, + AAT_LITERAL = 1, + AAT_INT = 2, + AAT_FLOAT = 3, + AAT_BOOL = 4 +}; + enum SQOpcode { _OP_LINE= 0x00, @@ -39,25 +55,26 @@ enum SQOpcode _OP_GET= 0x0E, _OP_EQ= 0x0F, _OP_NE= 0x10, - _OP_ARITH= 0x11, - _OP_BITW= 0x12, - _OP_RETURN= 0x13, - _OP_LOADNULLS= 0x14, - _OP_LOADROOTTABLE= 0x15, - _OP_LOADBOOL= 0x16, - _OP_DMOVE= 0x17, - _OP_JMP= 0x18, - _OP_JNZ= 0x19, - _OP_JZ= 0x1A, - _OP_LOADFREEVAR= 0x1B, - _OP_VARGC= 0x1C, - _OP_GETVARGV= 0x1D, - _OP_NEWTABLE= 0x1E, - _OP_NEWARRAY= 0x1F, - _OP_APPENDARRAY= 0x20, - _OP_GETPARENT= 0x21, - _OP_COMPARITH= 0x22, - _OP_COMPARITHL= 0x23, + _OP_ADD= 0x11, + _OP_SUB= 0x12, + _OP_MUL= 0x13, + _OP_DIV= 0x14, + _OP_MOD= 0x15, + _OP_BITW= 0x16, + _OP_RETURN= 0x17, + _OP_LOADNULLS= 0x18, + _OP_LOADROOT= 0x19, + _OP_LOADBOOL= 0x1A, + _OP_DMOVE= 0x1B, + _OP_JMP= 0x1C, + //_OP_JNZ= 0x1D, + _OP_JCMP= 0x1D, + _OP_JZ= 0x1E, + _OP_SETOUTER= 0x1F, + _OP_GETOUTER= 0x20, + _OP_NEWOBJ= 0x21, + _OP_APPENDARRAY= 0x22, + _OP_COMPARITH= 0x23, _OP_INC= 0x24, _OP_INCL= 0x25, _OP_PINC= 0x26, @@ -75,14 +92,14 @@ enum SQOpcode _OP_RESUME= 0x32, _OP_FOREACH= 0x33, _OP_POSTFOREACH= 0x34, - _OP_DELEGATE= 0x35, - _OP_CLONE= 0x36, - _OP_TYPEOF= 0x37, - _OP_PUSHTRAP= 0x38, - _OP_POPTRAP= 0x39, - _OP_THROW= 0x3A, - _OP_CLASS= 0x3B, - _OP_NEWSLOTA= 0x3C, + _OP_CLONE= 0x35, + _OP_TYPEOF= 0x36, + _OP_PUSHTRAP= 0x37, + _OP_POPTRAP= 0x38, + _OP_THROW= 0x39, + _OP_NEWSLOTA= 0x3A, + _OP_GETBASE= 0x3B, + _OP_CLOSE= 0x3C, }; struct SQInstructionDesc { diff --git a/external/squirrel/squirrel/sqpcheader.h b/external/squirrel/squirrel/sqpcheader.h old mode 100755 new mode 100644 diff --git a/external/squirrel/squirrel/sqstate.cpp b/external/squirrel/squirrel/sqstate.cpp old mode 100755 new mode 100644 index fd84b0a24..bfea9c495 --- a/external/squirrel/squirrel/sqstate.cpp +++ b/external/squirrel/squirrel/sqstate.cpp @@ -12,16 +12,17 @@ #include "squserdata.h" #include "sqclass.h" -SQObjectPtr _null_; -SQObjectPtr _true_(true); -SQObjectPtr _false_(false); -SQObjectPtr _one_((SQInteger)1); -SQObjectPtr _minusone_((SQInteger)-1); +//SQObjectPtr _null_; +//SQObjectPtr _true_(true); +//SQObjectPtr _false_(false); +//SQObjectPtr _one_((SQInteger)1); +//SQObjectPtr _minusone_((SQInteger)-1); SQSharedState::SQSharedState() { _compilererrorhandler = NULL; _printfunc = NULL; + _errorfunc = NULL; _debuginfo = false; _notifyallexceptions = false; } @@ -83,7 +84,7 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) SQInteger i=0; SQTable *t=SQTable::Create(ss,0); while(funcz[i].name!=0){ - SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f); + SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0); nc->_nparamscheck = funcz[i].nparamscheck; nc->_name = SQString::Create(ss,funcz[i].name); if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) @@ -101,7 +102,8 @@ void SQSharedState::Init() #ifndef NO_GARBAGE_COLLECTOR _gc_chain=NULL; #endif - sq_new(_stringtable,SQStringTable); + _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable)); + new (_stringtable) SQStringTable(this); sq_new(_metamethods,SQObjectPtrVec); sq_new(_systemstrings,SQObjectPtrVec); sq_new(_types,SQObjectPtrVec); @@ -161,29 +163,29 @@ void SQSharedState::Init() SQSharedState::~SQSharedState() { - _constructoridx = _null_; + _constructoridx.Null(); _table(_registry)->Finalize(); _table(_consts)->Finalize(); _table(_metamethodsmap)->Finalize(); - _registry = _null_; - _consts = _null_; - _metamethodsmap = _null_; + _registry.Null(); + _consts.Null(); + _metamethodsmap.Null(); while(!_systemstrings->empty()) { - _systemstrings->back()=_null_; + _systemstrings->back().Null(); _systemstrings->pop_back(); } _thread(_root_vm)->Finalize(); - _root_vm = _null_; - _table_default_delegate = _null_; - _array_default_delegate = _null_; - _string_default_delegate = _null_; - _number_default_delegate = _null_; - _closure_default_delegate = _null_; - _generator_default_delegate = _null_; - _thread_default_delegate = _null_; - _class_default_delegate = _null_; - _instance_default_delegate = _null_; - _weakref_default_delegate = _null_; + _root_vm.Null(); + _table_default_delegate.Null(); + _array_default_delegate.Null(); + _string_default_delegate.Null(); + _number_default_delegate.Null(); + _closure_default_delegate.Null(); + _generator_default_delegate.Null(); + _thread_default_delegate.Null(); + _class_default_delegate.Null(); + _instance_default_delegate.Null(); + _weakref_default_delegate.Null(); _refs_table.Finalize(); #ifndef NO_GARBAGE_COLLECTOR SQCollectable *t = _gc_chain; @@ -239,34 +241,98 @@ void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain) case OT_THREAD:_thread(o)->Mark(chain);break; case OT_CLASS:_class(o)->Mark(chain);break; case OT_INSTANCE:_instance(o)->Mark(chain);break; + case OT_OUTER:_outer(o)->Mark(chain);break; + case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break; default: break; //shutup compiler } } -SQInteger SQSharedState::CollectGarbage(SQVM *vm) +void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain) { - SQInteger n=0; - SQCollectable *tchain=NULL; SQVM *vms = _thread(_root_vm); - vms->Mark(&tchain); - SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed(); - _refs_table.Mark(&tchain); - MarkObject(_registry,&tchain); - MarkObject(_consts,&tchain); - MarkObject(_metamethodsmap,&tchain); - MarkObject(_table_default_delegate,&tchain); - MarkObject(_array_default_delegate,&tchain); - MarkObject(_string_default_delegate,&tchain); - MarkObject(_number_default_delegate,&tchain); - MarkObject(_generator_default_delegate,&tchain); - MarkObject(_thread_default_delegate,&tchain); - MarkObject(_closure_default_delegate,&tchain); - MarkObject(_class_default_delegate,&tchain); - MarkObject(_instance_default_delegate,&tchain); - MarkObject(_weakref_default_delegate,&tchain); + vms->Mark(tchain); + _refs_table.Mark(tchain); + MarkObject(_registry,tchain); + MarkObject(_consts,tchain); + MarkObject(_metamethodsmap,tchain); + MarkObject(_table_default_delegate,tchain); + MarkObject(_array_default_delegate,tchain); + MarkObject(_string_default_delegate,tchain); + MarkObject(_number_default_delegate,tchain); + MarkObject(_generator_default_delegate,tchain); + MarkObject(_thread_default_delegate,tchain); + MarkObject(_closure_default_delegate,tchain); + MarkObject(_class_default_delegate,tchain); + MarkObject(_instance_default_delegate,tchain); + MarkObject(_weakref_default_delegate,tchain); + +} + +SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm) +{ + SQInteger n=0; + SQCollectable *tchain=NULL; + + RunMark(vm,&tchain); + + SQCollectable *resurrected = _gc_chain; + SQCollectable *t = resurrected; + //SQCollectable *nx = NULL; + + _gc_chain = tchain; + + SQArray *ret = NULL; + if(resurrected) { + ret = SQArray::Create(this,0); + SQCollectable *rlast = NULL; + while(t) { + rlast = t; + SQObjectType type = t->GetType(); + if(type != OT_FUNCPROTO && type != OT_OUTER) { + SQObject sqo; + sqo._type = type; + sqo._unVal.pRefCounted = t; + ret->Append(sqo); + } + t = t->_next; + n++; + } + + assert(rlast->_next == NULL); + rlast->_next = _gc_chain; + if(_gc_chain) + { + _gc_chain->_prev = rlast; + } + _gc_chain = resurrected; + } + + t = _gc_chain; + while(t) { + t->UnMark(); + t = t->_next; + } + + if(ret) { + SQObjectPtr temp = ret; + vm->Push(temp); + } + else { + vm->PushNull(); + } + return n; +} + +SQInteger SQSharedState::CollectGarbage(SQVM *vm) +{ + SQInteger n = 0; + SQCollectable *tchain = NULL; + + RunMark(vm,&tchain); + SQCollectable *t = _gc_chain; SQCollectable *nx = NULL; if(t) { @@ -288,8 +354,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm) t = t->_next; } _gc_chain = tchain; - SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed(); - assert(z == x); + return n; } #endif @@ -341,7 +406,7 @@ void RefTable::Finalize() { RefNode *nodes = _nodes; for(SQUnsignedInteger n = 0; n < _numofslots; n++) { - nodes->obj = _null_; + nodes->obj.Null(); nodes++; } } @@ -372,6 +437,15 @@ void RefTable::AddRef(SQObject &obj) ref->refs++; } +SQUnsignedInteger RefTable::GetRefCount(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + return ref->refs; +} + + SQBool RefTable::Release(SQObject &obj) { SQHash mainpos; @@ -389,7 +463,7 @@ SQBool RefTable::Release(SQObject &obj) ref->next = _freelist; _freelist = ref; _slotused--; - ref->obj = _null_; + ref->obj.Null(); //<>test for shrink? return SQTrue; } @@ -414,7 +488,7 @@ void RefTable::Resize(SQUnsignedInteger size) assert(t->refs != 0); RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj); nn->refs = t->refs; - t->obj = _null_; + t->obj.Null(); nfound++; } t++; @@ -491,8 +565,9 @@ void RefTable::AllocNodes(SQUnsignedInteger size) * http://www.lua.org/source/4.0.1/src_lstring.c.html */ -SQStringTable::SQStringTable() +SQStringTable::SQStringTable(SQSharedState *ss) { + _sharedstate = ss; AllocNodes(4); _slotused = 0; } @@ -514,19 +589,21 @@ SQString *SQStringTable::Add(const SQChar *news,SQInteger len) { if(len<0) len = (SQInteger)scstrlen(news); - SQHash h = ::_hashstr(news,len)&(_numofslots-1); + SQHash newhash = ::_hashstr(news,len); + SQHash h = newhash&(_numofslots-1); SQString *s; for (s = _strings[h]; s; s = s->_next){ if(s->_len == len && (!memcmp(news,s->_val,rsl(len)))) return s; //found } - SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); + SQString *t = (SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); new (t) SQString; + t->_sharedstate = _sharedstate; memcpy(t->_val,news,rsl(len)); t->_val[len] = _SC('\0'); t->_len = len; - t->_hash = ::_hashstr(news,len); + t->_hash = newhash; t->_next = _strings[h]; _strings[h] = t; _slotused++; diff --git a/external/squirrel/squirrel/sqstate.h b/external/squirrel/squirrel/sqstate.h old mode 100755 new mode 100644 index e06da7a20..ed9d6fc8a --- a/external/squirrel/squirrel/sqstate.h +++ b/external/squirrel/squirrel/sqstate.h @@ -11,7 +11,7 @@ struct SQTable; struct SQStringTable { - SQStringTable(); + SQStringTable(SQSharedState*ss); ~SQStringTable(); SQString *Add(const SQChar *,SQInteger len); void Remove(SQString *); @@ -21,6 +21,7 @@ private: SQString **_strings; SQUnsignedInteger _numofslots; SQUnsignedInteger _slotused; + SQSharedState *_sharedstate; }; struct RefTable { @@ -33,6 +34,7 @@ struct RefTable { ~RefTable(); void AddRef(SQObject &obj); SQBool Release(SQObject &obj); + SQUnsignedInteger GetRefCount(SQObject &obj); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); #endif @@ -63,7 +65,9 @@ public: SQChar* GetScratchPad(SQInteger size); SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); #ifndef NO_GARBAGE_COLLECTOR - SQInteger CollectGarbage(SQVM *vm); + SQInteger CollectGarbage(SQVM *vm); + void RunMark(SQVM *vm,SQCollectable **tchain); + SQInteger ResurrectUnreachable(SQVM *vm); static void MarkObject(SQObjectPtr &o,SQCollectable **chain); #endif SQObjectPtrVec *_metamethods; @@ -102,6 +106,7 @@ public: SQCOMPILERERROR _compilererrorhandler; SQPRINTFUNCTION _printfunc; + SQPRINTFUNCTION _errorfunc; bool _debuginfo; bool _notifyallexceptions; private: @@ -129,15 +134,9 @@ private: #define rsl(l) (l) #endif -extern SQObjectPtr _null_; -extern SQObjectPtr _true_; -extern SQObjectPtr _false_; -extern SQObjectPtr _one_; -extern SQObjectPtr _minusone_; +//extern SQObjectPtr _null_; bool CompileTypemask(SQIntVec &res,const SQChar *typemask); -void *sq_vm_malloc(SQUnsignedInteger size); -void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size); -void sq_vm_free(void *p,SQUnsignedInteger size); + #endif //_SQSTATE_H_ diff --git a/external/squirrel/squirrel/sqstring.h b/external/squirrel/squirrel/sqstring.h old mode 100755 new mode 100644 diff --git a/external/squirrel/squirrel/sqtable.cpp b/external/squirrel/squirrel/sqtable.cpp old mode 100755 new mode 100644 index 87f8cbf1f..60382fd18 --- a/external/squirrel/squirrel/sqtable.cpp +++ b/external/squirrel/squirrel/sqtable.cpp @@ -23,7 +23,8 @@ void SQTable::Remove(const SQObjectPtr &key) _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); if (n) { - n->val = n->key = _null_; + n->val.Null(); + n->key.Null(); _usednodes--; Rehash(false); } @@ -33,8 +34,9 @@ void SQTable::AllocNodes(SQInteger nSize) { _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); for(SQInteger i=0;i_nodes; + _HashNode *src = _nodes; + _HashNode *dst = nt->_nodes; + SQInteger n = 0; + for(n = 0; n < _numofnodes; n++) { + dst->key = src->key; + dst->val = src->val; + if(src->next) { + assert(src->next > basesrc); + dst->next = basedst + (src->next - basesrc); + assert(dst != dst->next); + } + dst++; + src++; + } + assert(_firstfree > basesrc); + assert(_firstfree != NULL); + nt->_firstfree = basedst + (_firstfree - basesrc); + nt->_usednodes = _usednodes; +#else SQInteger ridx=0; SQObjectPtr key,val; while((ridx=Next(true,ridx,key,val))!=-1){ nt->NewSlot(key,val); } +#endif nt->SetDelegate(_delegate); return nt; } @@ -122,8 +147,8 @@ bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) n->key = mp->key; n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ n->next = mp->next; - mp->key = _null_; - mp->val = _null_; + mp->key.Null(); + mp->val.Null(); mp->next = NULL; /* now `mp' is free */ } else{ @@ -179,7 +204,7 @@ bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val) void SQTable::_ClearNodes() { - for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; } + for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); } } void SQTable::Finalize() diff --git a/external/squirrel/squirrel/sqtable.h b/external/squirrel/squirrel/sqtable.h old mode 100755 new mode 100644 index 5b9ee7223..2f6487023 --- a/external/squirrel/squirrel/sqtable.h +++ b/external/squirrel/squirrel/sqtable.h @@ -61,6 +61,7 @@ public: } #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); + SQObjectType GetType() {return OT_TABLE;} #endif inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) { diff --git a/external/squirrel/squirrel/squserdata.h b/external/squirrel/squirrel/squserdata.h old mode 100755 new mode 100644 index 8fe0411ea..dea27ae78 --- a/external/squirrel/squirrel/squserdata.h +++ b/external/squirrel/squirrel/squserdata.h @@ -12,7 +12,7 @@ struct SQUserData : SQDelegable } static SQUserData* Create(SQSharedState *ss, SQInteger size) { - SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1)); + SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size); new (ud) SQUserData(ss); ud->_size = size; ud->_typetag = 0; @@ -21,18 +21,20 @@ struct SQUserData : SQDelegable #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); void Finalize(){SetDelegate(NULL);} + SQObjectType GetType(){ return OT_USERDATA;} #endif void Release() { - if (_hook) _hook(_val,_size); - SQInteger tsize = _size - 1; + if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size); + SQInteger tsize = _size; this->~SQUserData(); - SQ_FREE(this, sizeof(SQUserData) + tsize); + SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize); } + SQInteger _size; SQRELEASEHOOK _hook; SQUserPointer _typetag; - SQChar _val[1]; + //SQChar _val[1]; }; #endif //_SQUSERDATA_H_ diff --git a/external/squirrel/squirrel/squtils.h b/external/squirrel/squirrel/squtils.h old mode 100755 new mode 100644 index 6deef43bf..84a11760f --- a/external/squirrel/squirrel/squtils.h +++ b/external/squirrel/squirrel/squtils.h @@ -2,7 +2,6 @@ #ifndef _SQUTILS_H_ #define _SQUTILS_H_ -/* clang fix: "error: call to function 'sq_vm_free' that is neither visible in the template definition nor found by argument-dependent lookup" */ void *sq_vm_malloc(SQUnsignedInteger size); void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size); void sq_vm_free(void *p,SQUnsignedInteger size); @@ -13,6 +12,8 @@ void sq_vm_free(void *p,SQUnsignedInteger size); #define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size)); #define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size)); +#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1))) + //sqvector mini vector class, supports objects by value template class sqvector { @@ -29,7 +30,13 @@ public: } void copy(const sqvector& v) { - resize(v._size); + if(_size) { + resize(0); //destroys all previous stuff + } + //resize(v._size); + if(v._size > _allocated) { + _realloc(v._size); + } for(SQUnsignedInteger i = 0; i < v._size; i++) { new ((void *)&_vals[i]) T(v._vals[i]); } diff --git a/external/squirrel/squirrel/sqvm.cpp b/external/squirrel/squirrel/sqvm.cpp old mode 100755 new mode 100644 index e240b5c5a..77e5eefb4 --- a/external/squirrel/squirrel/sqvm.cpp +++ b/external/squirrel/squirrel/sqvm.cpp @@ -5,8 +5,8 @@ #include #include #include "sqopcodes.h" -#include "sqfuncproto.h" #include "sqvm.h" +#include "sqfuncproto.h" #include "sqclosure.h" #include "sqstring.h" #include "sqtable.h" @@ -16,27 +16,12 @@ #define TOP() (_stack._vals[_top-1]) -#define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); } -void SQVM::ClearStack(SQInteger last_top) -{ - SQObjectType tOldType; - SQObjectValue unOldVal; - while (last_top >= _top) { - SQObjectPtr &o = _stack._vals[last_top--]; - tOldType = o._type; - unOldVal = o._unVal; - o._type = OT_NULL; - o._unVal.pUserPointer = NULL; - __Release(tOldType,unOldVal); - } -} - bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) { SQInteger res; - SQInteger i1 = _integer(o1), i2 = _integer(o2); - if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) + if((type(o1)|type(o2)) == OT_INTEGER) { + SQInteger i1 = _integer(o1), i2 = _integer(o2); switch(op) { case BW_AND: res = i1 & i2; break; case BW_OR: res = i1 | i2; break; @@ -52,80 +37,111 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,con return true; } +#define _ARITH_(op,trg,o1,o2) \ +{ \ + SQInteger tmask = type(o1)|type(o2); \ + switch(tmask) { \ + case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \ + case (OT_FLOAT|OT_INTEGER): \ + case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ + default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ + } \ +} + +#define _ARITH_NOZERO(op,trg,o1,o2,err) \ +{ \ + SQInteger tmask = type(o1)|type(o2); \ + switch(tmask) { \ + case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\ + case (OT_FLOAT|OT_INTEGER): \ + case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ + default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ + } \ +} + bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) { - if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) { - SQInteger res, i1 = _integer(o1), i2 = _integer(o2); - switch(op) { - case '+': res = i1 + i2; break; - case '-': res = i1 - i2; break; - case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } + SQInteger tmask = type(o1)|type(o2); + switch(tmask) { + case OT_INTEGER:{ + SQInteger res, i1 = _integer(o1), i2 = _integer(o2); + switch(op) { + case '+': res = i1 + i2; break; + case '-': res = i1 - i2; break; + case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } res = i1 / i2; break; - case '*': res = i1 * i2; break; - case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } + case '*': res = i1 * i2; break; + case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } res = i1 % i2; break; - default: res = 0xDEADBEEF; - } - trg = res; - }else{ - SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); - switch(op) { - case '+': res = f1 + f2; break; - case '-': res = f1 - f2; break; - case '/': res = f1 / f2; break; - case '*': res = f1 * f2; break; - case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; - default: res = 0x0f; - } - trg = res; - } - } else { - if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){ - if(!StringCat(o1, o2, trg)) return false; + default: res = 0xDEADBEEF; + } + trg = res; } + break; + case (OT_FLOAT|OT_INTEGER): + case (OT_FLOAT):{ + SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); + switch(op) { + case '+': res = f1 + f2; break; + case '-': res = f1 - f2; break; + case '/': res = f1 / f2; break; + case '*': res = f1 * f2; break; + case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; + default: res = 0x0f; + } + trg = res; } + break; + default: + if(op == '+' && (tmask & _RT_STRING)){ + if(!StringCat(o1, o2, trg)) return false; } else if(!ArithMetaMethod(op,o1,o2,trg)) { - Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; + return false; } - } - return true; + } + return true; } SQVM::SQVM(SQSharedState *ss) { _sharedstate=ss; _suspended = SQFalse; - _suspended_target=-1; + _suspended_target = -1; _suspended_root = SQFalse; - _suspended_traps=-1; - _foreignptr=NULL; - _nnativecalls=0; - _lasterror = _null_; - _errorhandler = _null_; - _debughook = _null_; + _suspended_traps = -1; + _foreignptr = NULL; + _nnativecalls = 0; + _nmetamethodscall = 0; + _lasterror.Null(); + _errorhandler.Null(); + _debughook = false; + _debughook_native = NULL; + _debughook_closure.Null(); + _openouters = NULL; ci = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } void SQVM::Finalize() { - _roottable = _null_; - _lasterror = _null_; - _errorhandler = _null_; - _debughook = _null_; - temp_reg = _null_; + if(_openouters) CloseOuters(&_stack._vals[0]); + _roottable.Null(); + _lasterror.Null(); + _errorhandler.Null(); + _debughook = false; + _debughook_native = NULL; + _debughook_closure.Null(); + temp_reg.Null(); _callstackdata.resize(0); SQInteger size=_stack.size(); for(SQInteger i=0;i_gc_chain,this); } @@ -141,9 +157,14 @@ bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr default: mm = MT_ADD; assert(0); break; //shutup compiler } if(is_delegable(o1) && _delegable(o1)->_delegate) { - Push(o1);Push(o2); - return CallMetaMethod(_delegable(o1),mm,2,dest); + + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, mm, closure)) { + Push(o1);Push(o2); + return CallMetaMethod(closure,mm,2,dest); + } } + Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; } @@ -161,10 +182,13 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) case OT_USERDATA: case OT_INSTANCE: if(_delegable(o)->_delegate) { - Push(o); - if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) { - trg = temp_reg; + SQObjectPtr closure; + if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) { + Push(o); + if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false; + _Swap(trg,temp_reg); return true; + } } default:break; //shutup compiler @@ -176,34 +200,46 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) #define _RET_SUCCEED(exp) { result = (exp); return true; } bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) { - if(type(o1)==type(o2)){ - if(_rawval(o1)==_rawval(o2))_RET_SUCCEED(0); + SQObjectType t1 = type(o1), t2 = type(o2); + if(t1 == t2) { + if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0); SQObjectPtr res; - switch(type(o1)){ + switch(t1){ case OT_STRING: _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); case OT_INTEGER: - _RET_SUCCEED(_integer(o1)-_integer(o2)); + _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1); case OT_FLOAT: _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); case OT_TABLE: case OT_USERDATA: case OT_INSTANCE: if(_delegable(o1)->_delegate) { - Push(o1);Push(o2); - if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break; + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) { + Push(o1);Push(o2); + if(CallMetaMethod(closure,MT_CMP,2,res)) { + if(type(res) != OT_INTEGER) { + Raise_Error(_SC("_cmp must return an integer")); + return false; + } + _RET_SUCCEED(_integer(res)) + } + return false; + } } //continues through (no break needed) default: _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); } - if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } - _RET_SUCCEED(_integer(res)); + assert(0); + //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } + // _RET_SUCCEED(_integer(res)); } else{ if(sq_isnumeric(o1) && sq_isnumeric(o2)){ - if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { + if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } _RET_SUCCEED(1); @@ -214,8 +250,8 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) _RET_SUCCEED(1); } } - else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);} - else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);} + else if(t1==OT_NULL) {_RET_SUCCEED(-1);} + else if(t2==OT_NULL) {_RET_SUCCEED(1);} else { Raise_CompareError(o1,o2); return false; } } @@ -228,28 +264,28 @@ bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObject SQInteger r; if(ObjCmp(o1,o2,r)) { switch(op) { - case CMP_G: res = (r > 0)?_true_:_false_; return true; - case CMP_GE: res = (r >= 0)?_true_:_false_; return true; - case CMP_L: res = (r < 0)?_true_:_false_; return true; - case CMP_LE: res = (r <= 0)?_true_:_false_; return true; - + case CMP_G: res = (r > 0); return true; + case CMP_GE: res = (r >= 0); return true; + case CMP_L: res = (r < 0); return true; + case CMP_LE: res = (r <= 0); return true; + case CMP_3W: res = r; return true; } assert(0); } return false; } -void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) +bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) { switch(type(o)) { case OT_STRING: res = o; - return; + return true; case OT_FLOAT: scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); break; case OT_INTEGER: - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o)); + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_PRINT_INT_FMT,_integer(o)); break; case OT_BOOL: scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); @@ -258,25 +294,31 @@ void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) case OT_USERDATA: case OT_INSTANCE: if(_delegable(o)->_delegate) { - Push(o); - if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) { - if(type(res) == OT_STRING) - return; - //else keeps going to the default + SQObjectPtr closure; + if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) { + Push(o); + if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {; + if(type(res) == OT_STRING) + return true; + } + else { + return false; + } } } default: scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); } res = SQString::Create(_ss(this),_spval); + return true; } bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) { SQObjectPtr a, b; - ToString(str, a); - ToString(obj, b); + if(!ToString(str, a)) return false; + if(!ToString(obj, b)) return false; SQInteger l = _string(a)->_len , ol = _string(b)->_len; SQChar *s = _sp(rsl(l + ol + 1)); memcpy(s, _stringval(a), rsl(l)); @@ -285,14 +327,17 @@ bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr & return true; } -void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) +bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) { if(is_delegable(obj1) && _delegable(obj1)->_delegate) { - Push(obj1); - if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest)) - return; + SQObjectPtr closure; + if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) { + Push(obj1); + return CallMetaMethod(closure,MT_TYPEOF,1,dest); + } } dest = SQString::Create(_ss(this),GetTypeName(obj1)); + return true; } bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) @@ -310,22 +355,44 @@ bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) _roottable = friendvm->_roottable; _errorhandler = friendvm->_errorhandler; _debughook = friendvm->_debughook; + _debughook_native = friendvm->_debughook_native; + _debughook_closure = friendvm->_debughook_closure; } sq_base_register(this); return true; } -extern SQInstructionDesc g_InstrDesc[]; bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall) { - SQFunctionProto *func = _funcproto(closure->_function); - - const SQInteger paramssize = func->_nparameters; + SQFunctionProto *func = closure->_function; + + SQInteger paramssize = func->_nparameters; const SQInteger newtop = stackbase + func->_stacksize; SQInteger nargs = args; - if (paramssize != nargs) { + if(func->_varparams) + { + paramssize--; + if (nargs < paramssize) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + + //dumpstack(stackbase); + SQInteger nvargs = nargs - paramssize; + SQArray *arr = SQArray::Create(_ss(this),nvargs); + SQInteger pbase = stackbase+paramssize; + for(SQInteger n = 0; n < nvargs; n++) { + arr->_values[n] = _stack._vals[pbase]; + _stack._vals[pbase].Null(); + pbase++; + + } + _stack._vals[stackbase+paramssize] = arr; + //dumpstack(stackbase); + } + else if (paramssize != nargs) { SQInteger ndef = func->_ndefaultparams; SQInteger diff; if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) { @@ -333,99 +400,75 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; } } - else if(func->_varparams) - { - if (nargs < paramssize) { - Raise_Error(_SC("wrong number of parameters")); - return false; - } - for(SQInteger n = 0; n < nargs - paramssize; n++) { - _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]); - _stack._vals[stackbase+paramssize+n] = _null_; - } - } else { Raise_Error(_SC("wrong number of parameters")); return false; } } - if(type(closure->_env) == OT_WEAKREF) { - _stack._vals[stackbase] = _weakref(closure->_env)->_obj; + if(closure->_env) { + _stack._vals[stackbase] = closure->_env->_obj; } - if (!tailcall) { - CallInfo lc; - lc._generator = NULL; - lc._etraps = 0; - lc._prevstkbase = (SQInt32) ( stackbase - _stackbase ); - lc._target = (SQInt32) target; - lc._prevtop = (SQInt32) (_top - _stackbase); - lc._ncalls = 1; - lc._root = SQFalse; - PUSH_CALLINFO(this, lc); - } - else { - ci->_ncalls++; - } - ci->_vargs.size = (SQInt32)(nargs - paramssize); - ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size)); - ci->_closure = closure; + if(!EnterFrame(stackbase, newtop, tailcall)) return false; + + ci->_closure = closure; ci->_literals = func->_literals; - ci->_ip = func->_instructions; - //grows the stack if needed - if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) { - _stack.resize(_stack.size() + (func->_stacksize<<1)); - } - - _top = newtop; - _stackbase = stackbase; - if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + ci->_ip = func->_instructions; + ci->_target = (SQInt32)target; + + if (_debughook) { CallDebugHook(_SC('c')); + } + + if (closure->_function->_bgenerator) { + SQFunctionProto *f = closure->_function; + SQGenerator *gen = SQGenerator::Create(_ss(this), closure); + if(!gen->Yield(this,f->_stacksize)) + return false; + SQObjectPtr temp; + Return(1, target, temp); + STK(target) = gen; + } + + return true; } bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) { - if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - for(SQInteger i=0;i_ncalls;i++) + SQBool _isroot = ci->_root; + SQInteger callerbase = _stackbase - ci->_prevstkbase; + + if (_debughook) { + for(SQInteger i=0; i_ncalls; i++) { CallDebugHook(_SC('r')); - - SQBool broot = ci->_root; - SQInteger last_top = _top; - SQInteger target = ci->_target; - SQInteger oldstackbase = _stackbase; - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - if (broot) { - if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1]; - else retval = _null_; - } - else { - if(target != -1) { //-1 is when a class contructor ret value has to be ignored - if (_arg0 != MAX_FUNC_STACKSIZE) - STK(target) = _stack._vals[oldstackbase+_arg1]; - else - STK(target) = _null_; } } - CLEARSTACK(last_top); - assert(oldstackbase >= _stackbase); - return broot?true:false; + SQObjectPtr *dest; + if (_isroot) { + dest = &(retval); + } else if (ci->_target == -1) { + dest = NULL; + } else { + dest = &_stack._vals[callerbase + ci->_target]; + } + if (dest) { + if(_arg0 != 0xFF) { + *dest = _stack._vals[_stackbase+_arg1]; + } + else { + dest->Null(); + } + //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_; + } + LeaveFrame(); + return _isroot ? true : false; } #define _RET_ON_FAIL(exp) { if(!exp) return false; } -bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) -{ - _RET_ON_FAIL(ARITH_OP( op , target, a, incr)); - a = target; - return true; -} - bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) { SQObjectPtr trg; @@ -435,17 +478,18 @@ bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObject return true; } -bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix) +bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx) { SQObjectPtr tmp, tself = self, tkey = key; - if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; } + if (!Get(tself, tkey, tmp, false, selfidx)) { return false; } _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) - Set(tself, tkey, target,true); + if (!Set(tself, tkey, target,selfidx)) { return false; } if (postfix) target = tmp; return true; } #define arg0 (_i_._arg0) +#define sarg0 ((SQInteger)*((signed char *)&_i_._arg0)) #define arg1 (_i_._arg1) #define sarg1 (*((SQInt32 *)&_i_._arg1)) #define arg2 (_i_._arg2) @@ -461,11 +505,6 @@ SQRESULT SQVM::Suspend() return SQ_SUSPEND_FLAG; } -void SQVM::PopVarArgs(VarArgs &vargs) -{ - for(SQInteger n = 0; n< vargs.size; n++) - _vargsstack.pop_back(); -} #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; } bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr @@ -489,16 +528,22 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr case OT_INSTANCE: if(_delegable(o1)->_delegate) { SQObjectPtr itr; - Push(o1); - Push(o4); - if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){ - o4 = o2 = itr; - if(type(itr) == OT_NULL) _FINISH(exitpos); - if(!Get(o1, itr, o3, false,false)) { - Raise_Error(_SC("_nexti returned an invalid idx")); + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) { + Push(o1); + Push(o4); + if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) { + o4 = o2 = itr; + if(type(itr) == OT_NULL) _FINISH(exitpos); + if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) { + Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed + return false; + } + _FINISH(1); + } + else { return false; } - _FINISH(1); } Raise_Error(_SC("_nexti failed")); return false; @@ -513,7 +558,7 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr } o2 = idx; o4 = idx; - _generator(o1)->Resume(this, arg_2+1); + _generator(o1)->Resume(this, o3); _FINISH(0); } default: @@ -522,62 +567,34 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr return false; //cannot be hit(just to avoid warnings) } -bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2) -{ - if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; } - switch(type(o2)) { - case OT_TABLE: - if(!_table(o1)->SetDelegate(_table(o2))){ - Raise_Error(_SC("delegate cycle detected")); - return false; - } - break; - case OT_NULL: - _table(o1)->SetDelegate(NULL); - break; - default: - Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2)); - return false; - break; - } - trg = o1; - return true; -} #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1)) -#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} } - #define SQ_THROW() { goto exception_trap; } +#define _GUARD(exp) { if(!exp) { SQ_THROW();} } + bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) { SQInteger nouters; SQClosure *closure = SQClosure::Create(_ss(this), func); if((nouters = func->_noutervalues)) { - closure->_outervalues.reserve(nouters); for(SQInteger i = 0; i_outervalues[i]; switch(v._type){ - case otSYMBOL: - closure->_outervalues.push_back(_null_); - if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true)) - {Raise_IdxError(v._src); return false; } - break; case otLOCAL: - closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]); + FindOuter(closure->_outervalues[i], &STK(_integer(v._src))); break; case otOUTER: - closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]); + closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)]; break; } } } SQInteger ndefparams; if((ndefparams = func->_ndefaultparams)) { - closure->_defaultparams.reserve(ndefparams); for(SQInteger i = 0; i < ndefparams; i++) { SQInteger spos = func->_defaultparams[i]; - closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]); + closure->_defaultparams[i] = _stack._vals[_stackbase + spos]; } } target = closure; @@ -585,21 +602,6 @@ bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) } -bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci) -{ - if(ci->_vargs.size == 0) { - Raise_Error(_SC("the function doesn't have var args")); - return false; - } - if(!sq_isnumeric(index)){ - Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index)); - return false; - } - SQInteger idx = tointeger(index); - if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; } - target = _vargsstack[ci->_vargs.base+idx]; - return true; -} bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) { @@ -624,18 +626,14 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes return true; } - - -bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) +bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res) { if(type(o1) == type(o2)) { - res = ((_rawval(o1) == _rawval(o2)?true:false)); + res = (_rawval(o1) == _rawval(o2)); } else { if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - SQInteger cmpres; - if(!ObjCmp(o1, o2,cmpres)) return false; - res = (cmpres == 0); + res = (tofloat(o1) == tofloat(o2)); } else { res = false; @@ -646,65 +644,47 @@ bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) bool SQVM::IsFalse(SQObjectPtr &o) { - if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) ) - || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL + if(((type(o) & SQOBJECT_CANBEFALSE) + && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )) +#if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64)) + || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL +#else + || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL +#endif + { return true; } return false; } -bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target) -{ - switch(type(o)) { - case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_; - break; - case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_; - break; - default: - Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o)); - return false; - } - return true; -} - -bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) +bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) { if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } _nnativecalls++; AutoDec ad(&_nnativecalls); SQInteger traps = 0; - //temp_reg vars for OP_CALL - SQInteger ct_target; - SQInteger ct_stackbase; - bool ct_tailcall; - + CallInfo *prevci = ci; + switch(et) { case ET_CALL: { - SQInteger last_top = _top; temp_reg = closure; if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { //call the handler if there are no calls in the stack, if not relies on the previous node if(ci == NULL) CallErrorHandler(_lasterror); return false; } - if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) { - SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function); - SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg)); - _GUARD(gen->Yield(this)); - Return(1, ci->_target, temp_reg); - outres = gen; - CLEARSTACK(last_top); + if(ci == prevci) { + outres = STK(_top-nargs); return true; } ci->_root = SQTrue; } break; - case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break; + case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break; case ET_RESUME_VM: case ET_RESUME_THROW_VM: traps = _suspended_traps; ci->_root = _suspended_root; - ci->_vargs = _suspend_varargs; _suspended = SQFalse; if(et == ET_RESUME_THROW_VM) { SQ_THROW(); } break; @@ -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); switch(_i_.op) { - case _OP_LINE: - if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - CallDebugHook(_SC('l'),arg1); - continue; + case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue; case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; - case _OP_LOADINT: TARGET = (SQInteger)arg1; continue; + case _OP_LOADINT: +#ifndef _SQ64 + TARGET = (SQInteger)arg1; continue; +#else + TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue; +#endif case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue; case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; - case _OP_TAILCALL: - temp_reg = STK(arg1); - if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){ - ct_tailcall = true; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); + case _OP_TAILCALL:{ + SQObjectPtr &t = STK(arg1); + if (type(t) == OT_CLOSURE + && (!_closure(t)->_function->_bgenerator)){ + SQObjectPtr clo = t; + if(_openouters) CloseOuters(&(_stack._vals[_stackbase])); for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); - ct_target = ci->_target; - ct_stackbase = _stackbase; - goto common_call; + _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true)); + continue; } + } case _OP_CALL: { - ct_tailcall = false; - ct_target = arg0; - temp_reg = STK(arg1); - ct_stackbase = _stackbase+arg2; - -common_call: - SQObjectPtr clo = temp_reg; - SQInteger last_top = _top; + SQObjectPtr clo = STK(arg1); switch (type(clo)) { - case OT_CLOSURE:{ - _GUARD(StartCall(_closure(clo), ct_target, arg3, ct_stackbase, ct_tailcall)); - if (_funcproto(_closure(clo)->_function)->_bgenerator) { - SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(clo)); - _GUARD(gen->Yield(this)); - Return(1, ct_target, clo); - STK(ct_target) = gen; - CLEARSTACK(last_top); - continue; - } - } + case OT_CLOSURE: + _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false)); continue; case OT_NATIVECLOSURE: { bool suspend; - _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend)); + _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend)); if(suspend){ _suspended = SQTrue; - _suspended_target = ct_target; + _suspended_target = sarg0; _suspended_root = ci->_root; _suspended_traps = traps; - _suspend_varargs = ci->_vargs; outres = clo; return true; } - if(ct_target != -1) { //skip return value for constructors - STK(ct_target) = clo; + if(sarg0 != -1) { + STK(arg0) = clo; } } continue; case OT_CLASS:{ SQObjectPtr inst; - _GUARD(CreateClassInstance(_class(clo),inst,temp_reg)); - STK(ct_target) = inst; - ct_target = -1; //fakes return value target so that is not overwritten by the constructor - if(type(temp_reg) != OT_NULL) { - _stack._vals[ct_stackbase] = inst; - goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor) + _GUARD(CreateClassInstance(_class(clo),inst,clo)); + if(sarg0 != -1) { + STK(arg0) = inst; + } + SQInteger stkbase; + switch(type(clo)) { + case OT_CLOSURE: + stkbase = _stackbase+arg2; + _stack._vals[stkbase] = inst; + _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false)); + break; + case OT_NATIVECLOSURE: + bool suspend; + stkbase = _stackbase+arg2; + _stack._vals[stkbase] = inst; + _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend)); + break; + default: break; //shutup GCC 4.x } } break; case OT_TABLE: case OT_USERDATA: - case OT_INSTANCE: - { - Push(clo); - for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); - if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){ - STK(ct_target) = clo; + case OT_INSTANCE:{ + SQObjectPtr closure; + if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) { + Push(clo); + for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); + if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW(); + if(sarg0 != -1) { + STK(arg0) = clo; + } break; } - Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); - SQ_THROW(); + + //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); + //SQ_THROW(); } default: Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); @@ -808,93 +790,158 @@ common_call: } continue; case _OP_PREPCALL: - case _OP_PREPCALLK: - { + case _OP_PREPCALLK: { SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); SQObjectPtr &o = STK(arg2); - if (!Get(o, key, temp_reg,false,true)) { - if(type(o) == OT_CLASS) { //hack? - if(_class_ddel->Get(key,temp_reg)) { - STK(arg3) = o; - TARGET = temp_reg; - continue; - } - } - { Raise_IdxError(key); SQ_THROW();} + if (!Get(o, key, temp_reg,false,arg2)) { + SQ_THROW(); } - - STK(arg3) = type(o) == OT_CLASS?STK(0):o; - TARGET = temp_reg; + STK(arg3) = o; + _Swap(TARGET,temp_reg);//TARGET = temp_reg; } continue; case _OP_GETK: - if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,true)) { Raise_IdxError(ci->_literals[arg1]); SQ_THROW();} - TARGET = temp_reg; + if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();} + _Swap(TARGET,temp_reg);//TARGET = temp_reg; continue; case _OP_MOVE: TARGET = STK(arg1); continue; case _OP_NEWSLOT: _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); - if(arg0 != arg3) TARGET = STK(arg3); + if(arg0 != 0xFF) TARGET = STK(arg3); continue; case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; case _OP_SET: - if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } - if (arg0 != arg3) TARGET = STK(arg3); + if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); } + if (arg0 != 0xFF) TARGET = STK(arg3); continue; case _OP_GET: - if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } - TARGET = temp_reg; + if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); } + _Swap(TARGET,temp_reg);//TARGET = temp_reg; continue; case _OP_EQ:{ bool res; if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = res?_true_:_false_; + TARGET = res?true:false; }continue; case _OP_NE:{ bool res; if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = (!res)?_true_:_false_; + TARGET = (!res)?true:false; } continue; - case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue; + case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue; + case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue; case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; case _OP_RETURN: - if(ci->_generator) { - ci->_generator->Kill(); + if((ci)->_generator) { + (ci)->_generator->Kill(); } if(Return(arg0, arg1, temp_reg)){ assert(traps==0); - outres = temp_reg; + //outres = temp_reg; + _Swap(outres,temp_reg); return true; } continue; - case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n) = _null_; }continue; - case _OP_LOADROOTTABLE: TARGET = _roottable; continue; - case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue; + case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue; + case _OP_LOADROOT: TARGET = _roottable; continue; + case _OP_LOADBOOL: TARGET = arg1?true:false; continue; case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; case _OP_JMP: ci->_ip += (sarg1); continue; - case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_JCMP: + _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg)); + if(IsFalse(temp_reg)) ci->_ip+=(sarg1); + continue; case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; - case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue; - case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue; - case _OP_GETVARGV: - if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } + case _OP_GETOUTER: { + SQClosure *cur_cls = _closure(ci->_closure); + SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); + TARGET = *(otr->_valptr); + } + continue; + case _OP_SETOUTER: { + SQClosure *cur_cls = _closure(ci->_closure); + SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); + *(otr->_valptr) = STK(arg2); + if(arg0 != 0xFF) { + TARGET = STK(arg2); + } + } + continue; + case _OP_NEWOBJ: + switch(arg3) { + case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; + case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; + case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; + default: assert(0); continue; + } + case _OP_APPENDARRAY: + { + SQObject val; + val._unVal.raw = 0; + switch(arg2) { + case AAT_STACK: + val = STK(arg1); break; + case AAT_LITERAL: + val = ci->_literals[arg1]; break; + case AAT_INT: + val._type = OT_INTEGER; +#ifndef _SQ64 + val._unVal.nInteger = (SQInteger)arg1; +#else + val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1); +#endif + break; + case AAT_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = *((SQFloat *)&arg1); + break; + case AAT_BOOL: + val._type = OT_BOOL; + val._unVal.nInteger = arg1; + break; + default: assert(0); break; + + } + _array(STK(arg0))->Append(val); continue; + } + case _OP_COMPARITH: { + SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16); + _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); + } continue; - case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; - case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; - case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue; - case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue; - case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue; - case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue; - case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue; - case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue; - case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue; - case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue; + case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue; + case _OP_INCL: { + SQObjectPtr &a = STK(arg1); + if(type(a) == OT_INTEGER) { + a._unVal.nInteger = _integer(a) + sarg3; + } + else { + SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o)); + _ARITH_(+,a,a,o); + } + } continue; + case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue; + case _OP_PINCL: { + SQObjectPtr &a = STK(arg1); + if(type(a) == OT_INTEGER) { + TARGET = a; + a._unVal.nInteger = _integer(a) + sarg3; + } + else { + SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o)); + } + + } continue; case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; - case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue; + case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue; case _OP_INSTANCEOF: - if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE) + if(type(STK(arg1)) != OT_CLASS) {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} - TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_; + TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false; continue; case _OP_AND: if(IsFalse(STK(arg2))) { @@ -909,7 +956,7 @@ common_call: } continue; case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; - case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue; + case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue; case _OP_BWNOT: if(type(STK(arg1)) == OT_INTEGER) { SQInteger t = _integer(STK(arg1)); @@ -920,16 +967,16 @@ common_call: SQ_THROW(); case _OP_CLOSURE: { SQClosure *c = ci->_closure._unVal.pClosure; - SQFunctionProto *fp = c->_function._unVal.pFunctionProto; + SQFunctionProto *fp = c->_function; if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } continue; } case _OP_YIELD:{ if(ci->_generator) { if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); - _GUARD(ci->_generator->Yield(this)); + _GUARD(ci->_generator->Yield(this,arg2)); traps -= ci->_etraps; - if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg; + if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg; } else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} if(Return(arg0, arg1, temp_reg)){ @@ -942,7 +989,7 @@ common_call: continue; case _OP_RESUME: if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} - _GUARD(_generator(STK(arg1))->Resume(this, arg0)); + _GUARD(_generator(STK(arg1))->Resume(this, TARGET)); traps += ci->_etraps; continue; case _OP_FOREACH:{ int tojump; @@ -954,14 +1001,10 @@ common_call: if(_generator(STK(arg0))->_state == SQGenerator::eDead) ci->_ip += (sarg1 - 1); continue; - case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue; - case _OP_CLONE: - if(!Clone(STK(arg1), TARGET)) - { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();} - continue; - case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue; + case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue; + case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue; case _OP_PUSHTRAP:{ - SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions; + SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions; _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; ci->_etraps++; } @@ -974,27 +1017,23 @@ common_call: } continue; case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; - case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; case _OP_NEWSLOTA: - bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false; - if(type(STK(arg1)) == OT_CLASS) { - if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) { - Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3)); - Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_); - Push(bstatic); - int nparams = 5; - if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) { - Pop(nparams); - continue; - } - } + _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false)); + continue; + case _OP_GETBASE:{ + SQClosure *clo = _closure(ci->_closure); + if(clo->_base) { + TARGET = clo->_base; } - _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic)); - if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) { - _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1)); + else { + TARGET.Null(); } continue; } + case _OP_CLOSE: + if(_openouters) CloseOuters(&(STK(arg1))); + continue; + } } } @@ -1002,50 +1041,35 @@ exception_trap: { SQObjectPtr currerror = _lasterror; // dumpstack(_stackbase); - SQInteger n = 0; +// SQInteger n = 0; SQInteger last_top = _top; - if(ci) { - if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror); - - if(traps) { - do { - if(ci->_etraps > 0) { - SQExceptionTrap &et = _etraps.top(); - ci->_ip = et._ip; - _top = et._stacksize; - _stackbase = et._stackbase; - _stack._vals[_stackbase+et._extarget] = currerror; - _etraps.pop_back(); traps--; ci->_etraps--; - CLEARSTACK(last_top); - goto exception_restore; - } - //if is a native closure - if(type(ci->_closure) != OT_CLOSURE && n) - break; - if(ci->_generator) ci->_generator->Kill(); - PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - n++; - } while(_callsstacksize); + + if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror); + + while( ci ) { + if(ci->_etraps > 0) { + SQExceptionTrap &et = _etraps.top(); + ci->_ip = et._ip; + _top = et._stacksize; + _stackbase = et._stackbase; + _stack._vals[_stackbase + et._extarget] = currerror; + _etraps.pop_back(); traps--; ci->_etraps--; + while(last_top >= _top) _stack._vals[last_top--].Null(); + goto exception_restore; } - else { - //call the hook - if(raiseerror && !_ss(this)->_notifyallexceptions) - CallErrorHandler(currerror); + else if (_debughook) { + //notify debugger of a "return" + //even if it really an exception unwinding the stack + for(SQInteger i = 0; i < ci->_ncalls; i++) { + CallDebugHook(_SC('r')); + } } - //remove call stack until a C function is found or the cstack is empty - if(ci) do { - SQBool exitafterthisone = ci->_root; - if(ci->_generator) ci->_generator->Kill(); - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break; - } while(_callsstacksize); - - CLEARSTACK(last_top); + if(ci->_generator) ci->_generator->Kill(); + bool mustbreak = ci && ci->_root; + LeaveFrame(); + if(mustbreak) break; } + _lasterror = currerror; return false; } @@ -1055,8 +1079,8 @@ exception_trap: bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) { inst = theclass->CreateInstance(); - if(!theclass->Get(_ss(this)->_constructoridx,constructor)) { - constructor = _null_; + if(!theclass->GetConstructor(constructor)) { + constructor.Null(); } return true; } @@ -1071,219 +1095,270 @@ void SQVM::CallErrorHandler(SQObjectPtr &error) } } + void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) { - SQObjectPtr temp_reg; - SQInteger nparams=5; - SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function); - Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); - Call(_debughook,nparams,_top-nparams,temp_reg,SQFalse); - Pop(nparams); + _debughook = false; + SQFunctionProto *func=_closure(ci->_closure)->_function; + if(_debughook_native) { + const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL; + const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL; + SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip); + _debughook_native(this,type,src,line,fname); + } + else { + SQObjectPtr temp_reg; + SQInteger nparams=5; + Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); + Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse); + Pop(nparams); + } + _debughook = true; } -bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend) +bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend) { - if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } SQInteger nparamscheck = nclosure->_nparamscheck; - if(((nparamscheck > 0) && (nparamscheck != nargs)) - || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) { + SQInteger newtop = newbase + nargs + nclosure->_noutervalues; + + if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { + Raise_Error(_SC("Native stack overflow")); + return false; + } + + if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) || + ((nparamscheck < 0) && (nargs < (-nparamscheck))))) + { Raise_Error(_SC("wrong number of parameters")); return false; - } + } SQInteger tcs; - if((tcs = nclosure->_typecheck.size())) { - for(SQInteger i = 0; i < nargs && i < tcs; i++) - if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) { - Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i])); + SQIntVec &tc = nclosure->_typecheck; + if((tcs = tc.size())) { + for(SQInteger i = 0; i < nargs && i < tcs; i++) { + if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) { + Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i])); return false; } + } } - _nnativecalls++; - if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) { - _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1)); - } - SQInteger oldtop = _top; - SQInteger oldstackbase = _stackbase; - _top = stackbase + nargs; - CallInfo lci; - lci._closure = nclosure; - lci._generator = NULL; - lci._etraps = 0; - lci._prevstkbase = (SQInt32) (stackbase - _stackbase); - lci._ncalls = 1; - lci._prevtop = (SQInt32) (oldtop - oldstackbase); - PUSH_CALLINFO(this, lci); - _stackbase = stackbase; - //push free variables - SQInteger outers = nclosure->_outervalues.size(); + + if(!EnterFrame(newbase, newtop, false)) return false; + ci->_closure = nclosure; + + SQInteger outers = nclosure->_noutervalues; for (SQInteger i = 0; i < outers; i++) { - Push(nclosure->_outervalues[i]); + _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i]; } - - if(type(nclosure->_env) == OT_WEAKREF) { - _stack[stackbase] = _weakref(nclosure->_env)->_obj; + if(nclosure->_env) { + _stack._vals[newbase] = nclosure->_env->_obj; } - + _nnativecalls++; SQInteger ret = (nclosure->_function)(this); _nnativecalls--; + suspend = false; - if( ret == SQ_SUSPEND_FLAG) suspend = true; - else if (ret < 0) { - _stackbase = oldstackbase; - _top = oldtop; - POP_CALLINFO(this); + if (ret == SQ_SUSPEND_FLAG) { + suspend = true; + } + else if (ret < 0) { + LeaveFrame(); Raise_Error(_lasterror); return false; } - - if (ret != 0){ retval = TOP(); TOP().Null(); } - else { retval = _null_; } - _stackbase = oldstackbase; - _top = oldtop; - POP_CALLINFO(this); + if(ret) { + retval = _stack._vals[_top-1]; + } + else { + retval.Null(); + } + //retval = ret ? _stack._vals[_top-1] : _null_; + LeaveFrame(); return true; } -bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot) +#define FALLBACK_OK 0 +#define FALLBACK_NO_MATCH 1 +#define FALLBACK_ERROR 2 + +bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx) { switch(type(self)){ case OT_TABLE: if(_table(self)->Get(key,dest))return true; break; case OT_ARRAY: - if(sq_isnumeric(key)){ - return _array(self)->Get(tointeger(key),dest); - } + if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; } break; case OT_INSTANCE: if(_instance(self)->Get(key,dest)) return true; break; + case OT_CLASS: + if(_class(self)->Get(key,dest)) return true; + break; + case OT_STRING: + if(sq_isnumeric(key)){ + SQInteger n = tointeger(key); + if(abs((int)n) < _string(self)->_len) { + if(n < 0) n = _string(self)->_len - n; + dest = SQInteger(_stringval(self)[n]); + return true; + } + Raise_IdxError(key); + return false; + } + break; default:break; //shut up compiler } - if(FallBackGet(self,key,dest,raw)) return true; - - if(fetchroot) { - if(_rawval(STK(0)) == _rawval(self) && - type(STK(0)) == type(self)) { - return _table(_roottable)->Get(key,dest); + if(!raw) { + switch(FallBackGet(self,key,dest)) { + case FALLBACK_OK: return true; //okie + case FALLBACK_NO_MATCH: break; //keep falling back + case FALLBACK_ERROR: return false; // the metamethod failed + } + if(InvokeDefaultDelegate(self,key,dest)) { + return true; } } +//#ifdef ROOT_FALLBACK + if(selfidx == 0) { + if(_table(_roottable)->Get(key,dest)) return true; + } +//#endif + Raise_IdxError(key); return false; } -bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw) +bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) +{ + SQTable *ddel = NULL; + switch(type(self)) { + case OT_CLASS: ddel = _class_ddel; break; + case OT_TABLE: ddel = _table_ddel; break; + case OT_ARRAY: ddel = _array_ddel; break; + case OT_STRING: ddel = _string_ddel; break; + case OT_INSTANCE: ddel = _instance_ddel; break; + case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break; + case OT_GENERATOR: ddel = _generator_ddel; break; + case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break; + case OT_THREAD: ddel = _thread_ddel; break; + case OT_WEAKREF: ddel = _weakref_ddel; break; + default: return false; + } + return ddel->Get(key,dest); +} + + +SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) { switch(type(self)){ - case OT_CLASS: - return _class(self)->Get(key,dest); - break; case OT_TABLE: case OT_USERDATA: //delegation if(_delegable(self)->_delegate) { - if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false)) - return true; - if(raw)return false; - Push(self);Push(key); - if(CallMetaMethod(_delegable(self),MT_GET,2,dest)) - return true; + if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK; } - if(type(self) == OT_TABLE) { - if(raw) return false; - return _table_ddel->Get(key,dest); + else { + return FALLBACK_NO_MATCH; } - return false; - break; - case OT_ARRAY: - if(raw)return false; - return _array_ddel->Get(key,dest); - case OT_STRING: - if(sq_isnumeric(key)){ - SQInteger n=tointeger(key); - if(abs((int)n)<_string(self)->_len){ - if(n<0)n=_string(self)->_len-n; - dest=SQInteger(_stringval(self)[n]); - return true; + //go through + case OT_INSTANCE: { + SQObjectPtr closure; + if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) { + Push(self);Push(key); + _nmetamethodscall++; + AutoDec ad(&_nmetamethodscall); + if(Call(closure, 2, _top - 2, dest, SQFalse)) { + Pop(2); + return FALLBACK_OK; + } + else { + Pop(2); + if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) + return FALLBACK_ERROR; + } } - return false; - } - else { - if(raw)return false; - return _string_ddel->Get(key,dest); } + } break; - case OT_INSTANCE: - if(raw)return false; - Push(self);Push(key); - if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) { - return _instance_ddel->Get(key,dest); - } - return true; - case OT_INTEGER:case OT_FLOAT:case OT_BOOL: - if(raw)return false; - return _number_ddel->Get(key,dest); - case OT_GENERATOR: - if(raw)return false; - return _generator_ddel->Get(key,dest); - case OT_CLOSURE: case OT_NATIVECLOSURE: - if(raw)return false; - return _closure_ddel->Get(key,dest); - case OT_THREAD: - if(raw)return false; - return _thread_ddel->Get(key,dest); - case OT_WEAKREF: - if(raw)return false; - return _weakref_ddel->Get(key,dest); - default:return false; + default: break;//shutup GCC 4.x } - return false; + // no metamethod or no fallback type + return FALLBACK_NO_MATCH; } -bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot) +bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx) { switch(type(self)){ case OT_TABLE: - if(_table(self)->Set(key,val)) - return true; - if(_table(self)->_delegate) { - if(Set(_table(self)->_delegate,key,val,false)) { - return true; - } - } - //keeps going - case OT_USERDATA: - if(_delegable(self)->_delegate) { - SQObjectPtr t; - Push(self);Push(key);Push(val); - if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; - } + if(_table(self)->Set(key,val)) return true; break; - case OT_INSTANCE:{ - if(_instance(self)->Set(key,val)) - return true; - SQObjectPtr t; - Push(self);Push(key);Push(val); - if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; - } + case OT_INSTANCE: + if(_instance(self)->Set(key,val)) return true; break; case OT_ARRAY: - if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } - return _array(self)->Set(tointeger(key),val); + if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } + if(!_array(self)->Set(tointeger(key),val)) { + Raise_IdxError(key); + return false; + } + return true; default: Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); return false; } - if(fetchroot) { - if(_rawval(STK(0)) == _rawval(self) && - type(STK(0)) == type(self)) { - return _table(_roottable)->Set(key,val); - } + + switch(FallBackSet(self,key,val)) { + case FALLBACK_OK: return true; //okie + case FALLBACK_NO_MATCH: break; //keep falling back + case FALLBACK_ERROR: return false; // the metamethod failed + } + if(selfidx == 0) { + if(_table(_roottable)->Set(key,val)) + return true; } + Raise_IdxError(key); return false; } +SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val) +{ + switch(type(self)) { + case OT_TABLE: + if(_table(self)->_delegate) { + if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK; + } + //keps on going + case OT_INSTANCE: + case OT_USERDATA:{ + SQObjectPtr closure; + SQObjectPtr t; + if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) { + Push(self);Push(key);Push(val); + _nmetamethodscall++; + AutoDec ad(&_nmetamethodscall); + if(Call(closure, 3, _top - 3, t, SQFalse)) { + Pop(3); + return FALLBACK_OK; + } + else { + if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) + //error + Pop(3); + return FALLBACK_ERROR; + } + } + } + } + break; + default: break;//shutup GCC 4.x + } + // no metamethod or no fallback type + return FALLBACK_NO_MATCH; +} + bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) { SQObjectPtr temp_reg; @@ -1292,21 +1367,50 @@ bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) case OT_TABLE: newobj = _table(self)->Clone(); goto cloned_mt; - case OT_INSTANCE: + case OT_INSTANCE: { newobj = _instance(self)->Clone(_ss(this)); cloned_mt: - if(_delegable(newobj)->_delegate){ + SQObjectPtr closure; + if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) { Push(newobj); Push(self); - CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg); + if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg)) + return false; + } } target = newobj; return true; case OT_ARRAY: target = _array(self)->Clone(); return true; - default: return false; + default: + Raise_Error(_SC("cloning a %s"), GetTypeName(self)); + return false; + } +} + +bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw) +{ + if(type(self) != OT_CLASS) { + Raise_Error(_SC("object must be a class")); + return false; } + SQClass *c = _class(self); + if(!raw) { + SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; + if(type(mm) != OT_NULL ) { + Push(self); Push(key); Push(val); + Push(attrs); + Push(bstatic); + return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg); + } + } + if(!NewSlot(self, key, val,bstatic)) + return false; + if(type(attrs) != OT_NULL) { + c->SetAttributes(key,attrs); + } + return true; } bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) @@ -1318,8 +1422,17 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject if(_table(self)->_delegate) { SQObjectPtr res; if(!_table(self)->Get(key,res)) { - Push(self);Push(key);Push(val); - rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res); + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { + Push(self);Push(key);Push(val); + if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { + return false; + } + rawcall = false; + } + else { + rawcall = true; + } } } if(rawcall) _table(self)->NewSlot(key,val); //cannot fail @@ -1327,11 +1440,16 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject break;} case OT_INSTANCE: { SQObjectPtr res; - Push(self);Push(key);Push(val); - if(!CallMetaMethod(_instance(self),MT_NEWSLOT,3,res)) { - Raise_Error(_SC("class instances do not support the new slot operator")); - return false; + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { + Push(self);Push(key);Push(val); + if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { + return false; + } + break; } + Raise_Error(_SC("class instances do not support the new slot operator")); + return false; break;} case OT_CLASS: if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { @@ -1354,6 +1472,8 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject return true; } + + bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) { switch(type(self)) { @@ -1361,13 +1481,13 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr case OT_INSTANCE: case OT_USERDATA: { SQObjectPtr t; - bool handled = false; - if(_delegable(self)->_delegate) { + //bool handled = false; + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) { Push(self);Push(key); - handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t); + return CallMetaMethod(closure,MT_DELSLOT,2,res); } - - if(!handled) { + else { if(type(self) == OT_TABLE) { if(_table(self)->Get(key,t)) { _table(self)->Remove(key); @@ -1399,7 +1519,7 @@ SQInteger prevstackbase = _stackbase; #endif switch(type(closure)) { case OT_CLOSURE: - return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror); + return Execute(closure, nparams, stackbase, outres, raiseerror); break; case OT_NATIVECLOSURE:{ bool suspend; @@ -1429,38 +1549,130 @@ SQInteger prevstackbase = _stackbase; return true; } -bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) +bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) { - SQObjectPtr closure; - if(del->GetMetaMethod(this, mm, closure)) { - if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { - Pop(nparams); - return true; - } + //SQObjectPtr closure; + + _nmetamethodscall++; + if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { + _nmetamethodscall--; + Pop(nparams); + return true; } + _nmetamethodscall--; + //} Pop(nparams); return false; } +void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex) +{ + SQOuter **pp = &_openouters; + SQOuter *p; + SQOuter *otr; + + while ((p = *pp) != NULL && p->_valptr >= stackindex) { + if (p->_valptr == stackindex) { + target = SQObjectPtr(p); + return; + } + pp = &p->_next; + } + otr = SQOuter::Create(_ss(this), stackindex); + otr->_next = *pp; + otr->_idx = (stackindex - _stack._vals); + __ObjAddRef(otr); + *pp = otr; + target = SQObjectPtr(otr); +} + +bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall) +{ + if( !tailcall ) { + if( _callsstacksize == _alloccallsstacksize ) { + GrowCallStack(); + } + ci = &_callsstack[_callsstacksize++]; + ci->_prevstkbase = (SQInt32)(newbase - _stackbase); + ci->_prevtop = (SQInt32)(_top - _stackbase); + ci->_etraps = 0; + ci->_ncalls = 1; + ci->_generator = NULL; + ci->_root = SQFalse; + } + else { + ci->_ncalls++; + } + + _stackbase = newbase; + _top = newtop; + if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) { + if(_nmetamethodscall) { + Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod")); + return false; + } + _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2)); + RelocateOuters(); + } + return true; +} + +void SQVM::LeaveFrame() { + SQInteger last_top = _top; + SQInteger last_stackbase = _stackbase; + SQInteger css = --_callsstacksize; + + /* First clean out the call stack frame */ + ci->_closure.Null(); + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + ci = (css) ? &_callsstack[css-1] : NULL; + + if(_openouters) CloseOuters(&(_stack._vals[last_stackbase])); + while (last_top >= _top) { + _stack._vals[last_top--].Null(); + } +} + +void SQVM::RelocateOuters() +{ + SQOuter *p = _openouters; + while (p) { + p->_valptr = _stack._vals + p->_idx; + p = p->_next; + } +} + +void SQVM::CloseOuters(SQObjectPtr *stackindex) { + SQOuter *p; + while ((p = _openouters) != NULL && p->_valptr >= stackindex) { + p->_value = *(p->_valptr); + p->_valptr = &p->_value; + _openouters = p->_next; + __ObjRelease(p); + } +} + void SQVM::Remove(SQInteger n) { n = (n >= 0)?n + _stackbase - 1:_top + n; for(SQInteger i = n; i < _top; i++){ _stack[i] = _stack[i+1]; } - _stack[_top] = _null_; + _stack[_top].Null(); _top--; } void SQVM::Pop() { - _stack[--_top] = _null_; + _stack[--_top].Null(); } void SQVM::Pop(SQInteger n) { for(SQInteger i = 0; i < n; i++){ - _stack[--_top] = _null_; + _stack[--_top].Null(); } } +void SQVM::PushNull() { _stack[_top++].Null(); } void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } diff --git a/external/squirrel/squirrel/sqvm.h b/external/squirrel/squirrel/sqvm.h old mode 100755 new mode 100644 index 202a7a1b5..13b370681 --- a/external/squirrel/squirrel/sqvm.h +++ b/external/squirrel/squirrel/sqvm.h @@ -5,9 +5,10 @@ #include "sqopcodes.h" #include "sqobject.h" #define MAX_NATIVE_CALLS 100 -#define MIN_STACK_OVERHEAD 10 +#define MIN_STACK_OVERHEAD 15 #define SQ_SUSPEND_FLAG -666 +#define DONT_FALL_BACK 666 //base lib void sq_base_register(HSQUIRRELVM v); @@ -30,14 +31,8 @@ typedef sqvector ExceptionsTraps; struct SQVM : public CHAINABLE_OBJ { - struct VarArgs { - VarArgs() { size = 0; base = 0; } - unsigned short size; - unsigned short base; - }; - struct CallInfo{ - //CallInfo() { _generator._type = OT_NULL;} + //CallInfo() { _generator = NULL;} SQInstruction *_ip; SQObjectPtr *_literals; SQObjectPtr _closure; @@ -48,18 +43,19 @@ struct SQVM : public CHAINABLE_OBJ SQInt32 _target; SQInt32 _ncalls; SQBool _root; - VarArgs _vargs; }; typedef sqvector CallInfoVec; public: - enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_THROW_VM }; + void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); + static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); + enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM }; SQVM(SQSharedState *ss); ~SQVM(); bool Init(SQVM *friendvm, SQInteger stacksize); - bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); + bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); //starts a native call return when the NATIVE closure returns - bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend); + bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend); //starts a SQUIRREL call in the same "Execution loop" bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); @@ -69,27 +65,34 @@ public: void CallDebugHook(SQInteger type,SQInteger forcedline=0); void CallErrorHandler(SQObjectPtr &e); - bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot); - bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw); - bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot); + bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, SQInteger selfidx); + SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); + bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); + bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx); + SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val); bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); + bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw); bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); bool Clone(const SQObjectPtr &self, SQObjectPtr &target); bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); - bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res); - void ToString(const SQObjectPtr &o,SQObjectPtr &res); - SQString *PrintObjVal(const SQObject &o); + static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res); + bool ToString(const SQObjectPtr &o,SQObjectPtr &res); + SQString *PrintObjVal(const SQObjectPtr &o); void Raise_Error(const SQChar *s, ...); - void Raise_Error(SQObjectPtr &desc); - void Raise_IdxError(SQObject &o); + void Raise_Error(const SQObjectPtr &desc); + void Raise_IdxError(const SQObjectPtr &o); void Raise_CompareError(const SQObject &o1, const SQObject &o2); void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); - void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); - bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); + void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex); + void RelocateOuters(); + void CloseOuters(SQObjectPtr *stackindex); + + bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); + bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); //new stuff @@ -98,23 +101,19 @@ public: _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); - bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci); bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); - bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target); //return true if the loop is finished bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump); - bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2); - _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); - _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix); - void PopVarArgs(VarArgs &vargs); - void ClearStack(SQInteger last_top); + _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0); #ifdef _DEBUG_DUMP void dumpstack(SQInteger stackbase=-1, bool dumpall = false); #endif #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); + SQObjectType GetType() {return OT_THREAD;} #endif void Finalize(); void GrowCallStack() { @@ -123,29 +122,36 @@ public: _callsstack = &_callstackdata[0]; _alloccallsstacksize = newsize; } - void Release(){ sq_delete(this,SQVM); } //does nothing + bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall); + void LeaveFrame(); + void Release(){ sq_delete(this,SQVM); } //////////////////////////////////////////////////////////////////////////// //stack functions for the api void Remove(SQInteger n); - bool IsFalse(SQObjectPtr &o); + static bool IsFalse(SQObjectPtr &o); void Pop(); void Pop(SQInteger n); void Push(const SQObjectPtr &o); + void PushNull(); SQObjectPtr &Top(); SQObjectPtr &PopGet(); SQObjectPtr &GetUp(SQInteger n); SQObjectPtr &GetAt(SQInteger n); SQObjectPtrVec _stack; - SQObjectPtrVec _vargsstack; + SQInteger _top; SQInteger _stackbase; + SQOuter *_openouters; SQObjectPtr _roottable; SQObjectPtr _lasterror; SQObjectPtr _errorhandler; - SQObjectPtr _debughook; + + bool _debughook; + SQDEBUGHOOK _debughook_native; + SQObjectPtr _debughook_closure; SQObjectPtr temp_reg; @@ -161,12 +167,12 @@ public: //VMs sharing the same state SQSharedState *_sharedstate; SQInteger _nnativecalls; + SQInteger _nmetamethodscall; //suspend infos SQBool _suspended; SQBool _suspended_root; SQInteger _suspended_target; SQInteger _suspended_traps; - VarArgs _suspend_varargs; }; struct AutoDec{ @@ -186,20 +192,18 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v-> #endif #define PUSH_CALLINFO(v,nci){ \ - if(v->_callsstacksize == v->_alloccallsstacksize) { \ + SQInteger css = v->_callsstacksize; \ + if(css == v->_alloccallsstacksize) { \ v->GrowCallStack(); \ } \ - v->ci = &v->_callsstack[v->_callsstacksize]; \ + v->ci = &v->_callsstack[css]; \ *(v->ci) = nci; \ v->_callsstacksize++; \ } #define POP_CALLINFO(v){ \ - v->_callsstacksize--; \ + SQInteger css = --v->_callsstacksize; \ v->ci->_closure.Null(); \ - if(v->_callsstacksize) \ - v->ci = &v->_callsstack[v->_callsstacksize-1] ; \ - else \ - v->ci = NULL; \ + v->ci = css?&v->_callsstack[css-1]:NULL; \ } #endif //_SQVM_H_ diff --git a/src/scripting/squirrel_util.cpp b/src/scripting/squirrel_util.cpp index d3e50e07b..5743f75ff 100644 --- a/src/scripting/squirrel_util.cpp +++ b/src/scripting/squirrel_util.cpp @@ -89,7 +89,7 @@ void init_squirrel(bool enable_debugger) sq_pop(global_vm, 1); // register print function - sq_setprintfunc(global_vm, printfunc); + sq_setprintfunc(global_vm, printfunc, printfunc); // register default error handlers sqstd_seterrorhandlers(global_vm); -- 2.11.0