-Copyright (c) 2003-2007 Alberto Demichelis\r
+Copyright (c) 2003-2008 Alberto Demichelis\r
\r
This software is provided 'as-is', without any \r
express or implied warranty. In no event will the \r
+***version 2.2 stable***\r
+-added _newslot metamethod in classes\r
+-added enums added constants\r
+-added sq_pushconsttable, sq_setconsttable\r
+-added default param\r
+-added octal literals(thx Dinosaur)\r
+-fixed debug hook, 'calls' and 'returns' are properly notified in the same number.\r
+-fixed a coroutine bug\r
+\r
+***2007-07-29 ***\r
***version 2.1.2 stable***\r
-new behaviour for generators iteration using foreach\r
now when a generator is iterated by foreach the value returned by a 'return val' statement\r
-The programming language SQUIRREL 2.1.2 stable\r
+The programming language SQUIRREL 2.2 stable\r
\r
--------------------------------------------------\r
The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and\r
project page - http://www.squirrel-lang.org\r
community forums - http://www.squirrel-lang.org/Forums\r
wiki - http://wiki.squirrel-lang.org\r
-author - alberto@ademichelis.com\r
+author - alberto@demichelis.net\r
\r
END OF README\r
\r
#define SQSTD_STREAM_TYPE_TAG 0x80000000
struct SQStream {
-
- // [SuperTux] Added virtual destructor to avoid compiler warnings
- virtual ~SQStream() { };
-
virtual SQInteger Read(void *buffer, SQInteger size) = 0;
virtual SQInteger Write(void *buffer, SQInteger size) = 0;
virtual SQInteger Flush() = 0;
/*
-Copyright (c) 2003-2007 Alberto Demichelis
+Copyright (c) 2003-2008 Alberto Demichelis
This software is provided 'as-is', without any
express or implied warranty. In no event will the
typedef unsigned int SQHash; /*should be the same size of a pointer*/
#endif
+
typedef float SQFloat;
typedef void* SQUserPointer;
typedef SQUnsignedInteger SQBool;
#define SQTrue (1)
#define SQFalse (0)
-
struct SQVM;
struct SQTable;
struct SQArray;
#define MAX_CHAR 0xFF
#endif
-#define SQUIRREL_VERSION _SC("Squirrel 2.1.2 stable")
-#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2007 Alberto Demichelis")
+#define SQUIRREL_VERSION _SC("Squirrel 2.2 stable")
+#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2008 Alberto Demichelis")
#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
#define SQ_VMSTATE_IDLE 0
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);
+SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx);
/*object manipulation*/
SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
+SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
break;
case OT_GENERATOR:
- pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
+ pf(v,_SC("[%s] GENERATOR\n"),name);
break;
case OT_USERDATA:
pf(v,_SC("[%s] USERDATA\n"),name);
//basic API
SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
{
-#ifndef _UNICODE
+#ifndef SQUNICODE
return (SQFILE)fopen(filename,mode);
#else
return (SQFILE)_wfopen(filename,mode);
static SQInteger math_srand(HSQUIRRELVM v)
{
SQInteger i;
- if(!sq_getinteger(v,2,&i))return sq_throwerror(v,_SC("invalid param"));
+ if(SQ_FAILED(sq_getinteger(v,2,&i)))
+ return sq_throwerror(v,_SC("invalid param"));
srand((unsigned int)i);
return 0;
}
#include <ctype.h>
#include <assert.h>
-#ifdef _UNICODE
+#ifdef SQUNICODE
#define scstrchr wcschr
#define scsnprintf wsnprintf
#define scatoi _wtoi
v->Push(_ss(v)->_registry);
}
+void sq_pushconsttable(HSQUIRRELVM v)
+{
+ v->Push(_ss(v)->_consts);
+}
+
SQRESULT sq_setroottable(HSQUIRRELVM v)
{
SQObject o = stack_get(v, -1);
return sq_throwerror(v, _SC("ivalid type"));
}
+SQRESULT sq_setconsttable(HSQUIRRELVM v)
+{
+ SQObject o = stack_get(v, -1);
+ if(sq_istable(o)) {
+ _ss(v)->_consts = o;
+ v->Pop();
+ return SQ_OK;
+ }
+ return sq_throwerror(v, _SC("ivalid type, expected table"));
+}
+
void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)
{
v->_foreignptr = p;
if(top > newtop)
sq_pop(v, top - newtop);
else
- while(top < newtop) sq_pushnull(v);
+ while(top++ < newtop) sq_pushnull(v);
}
void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
{
SQObjectPtr res;
if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){
- v->Pop(params);//pop closure and args
+ if(!v->_suspended) {
+ v->Pop(params);//pop closure and args
+ }
if(retval){
v->Push(res); return SQ_OK;
}
return 1;
}
+static SQInteger base_getconsttable(HSQUIRRELVM v)
+{
+ v->Push(_ss(v)->_consts);
+ return 1;
+}
+
+
static SQInteger base_setroottable(HSQUIRRELVM v)
{
SQObjectPtr &o=stack_get(v,2);
return 1;
}
+static SQInteger base_setconsttable(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,2);
+ if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;
+ v->Push(o);
+ return 1;
+}
+
static SQInteger base_seterrorhandler(HSQUIRRELVM v)
{
sq_seterrorhandler(v);
{_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
{_SC("getroottable"),base_getroottable,1, NULL},
{_SC("setroottable"),base_setroottable,2, NULL},
+ {_SC("getconsttable"),base_getconsttable,1, NULL},
+ {_SC("setconsttable"),base_setconsttable,2, NULL},
{_SC("assert"),base_assert,2, NULL},
{_SC("print"),base_print,2, NULL},
{_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
SQInteger sidx,eidx;
SQObjectPtr o;
if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
- if(sidx<0)sidx=_array(o)->Size()+sidx;
- if(eidx<0)eidx=_array(o)->Size()+eidx;
+ SQInteger alen = _array(o)->Size();
+ if(sidx < 0)sidx = alen + sidx;
+ if(eidx < 0)eidx = alen + eidx;
if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));
+ if(eidx > alen)return sq_throwerror(v,_SC("slice out of range"));
SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
SQObjectPtr t;
SQInteger count=0;
SQInteger sidx,eidx;
SQObjectPtr o;
if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
- if(sidx<0)sidx=_string(o)->_len+sidx;
- if(eidx<0)eidx=_string(o)->_len+eidx;
- if(eidx<sidx)
- return sq_throwerror(v,_SC("wrong indexes"));
+ SQInteger slen = _string(o)->_len;
+ if(sidx < 0)sidx = slen + sidx;
+ if(eidx < 0)eidx = slen + eidx;
+ if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));
+ if(eidx > slen) return sq_throwerror(v,_SC("slice out of range"));
v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
return 1;
}
SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function));
ret->_env = _env;
ret->_outervalues.copy(_outervalues);
+ ret->_defaultparams.copy(_defaultparams);
return ret;
}
~SQClosure()
SQObjectPtr _env;
SQObjectPtr _function;
SQObjectPtrVec _outervalues;
+ SQObjectPtrVec _defaultparams;
};
//////////////////////////////////////////////
struct SQGenerator : public CHAINABLE_OBJ
#include "sqfuncstate.h"
#include "sqlexer.h"
#include "sqvm.h"
+#include "sqtable.h"
#define DEREF_NO_DEREF -1
#define DEREF_FIELD -2
case TK_CLASS:
ClassStatement();
break;
+ case TK_ENUM:
+ EnumStatement();
+ break;
case _SC('{'):{
SQInteger stacksize = _fs->GetStackSize();
Lex();
CommaExpr();
_fs->AddInstruction(_OP_THROW, _fs->PopTarget());
break;
+ case TK_CONST:
+ {
+ Lex();
+ SQObject id = Expect(TK_IDENTIFIER);
+ Expect('=');
+ SQObject val = ExpectScalar();
+ OptionalSemicolon();
+ SQTable *enums = _table(_ss(_vm)->_consts);
+ SQObjectPtr strongid = id;
+ enums->NewSlot(strongid,SQObjectPtr(val));
+ strongid.Null();
+ }
+ break;
default:
CommaExpr();
_fs->PopTarget();
case TK_THIS:{
_exst._freevar = false;
SQObject id;
+ SQObject constant;
switch(_token) {
case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
case TK_THIS: id = _fs->CreateString(_SC("this")); break;
_exst._deref = _fs->PushTarget();
_fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
_exst._freevar = true;
- } else {
+ }
+ 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));
+ }
+
+ _exst._freevar = true;
+ }
+ else {
_fs->PushTarget(0);
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
if(NeedGet()) Emit2ArgsOP(_OP_GET);
_exst._deref = DEREF_FIELD;
}
}
+
else{
_fs->PushTarget(pos);
_exst._deref = pos;
}
else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
}
+ SQObject ExpectScalar()
+ {
+ SQObject val;
+ switch(_token) {
+ case TK_INTEGER:
+ val._type = OT_INTEGER;
+ val._unVal.nInteger = _lex._nvalue;
+ break;
+ case TK_FLOAT:
+ val._type = OT_FLOAT;
+ val._unVal.fFloat = _lex._fvalue;
+ break;
+ case TK_STRING_LITERAL:
+ val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
+ break;
+ default:
+ Error(_SC("scalar expected : integer,float or string"));
+ }
+ Lex();
+ return val;
+ }
+ void EnumStatement()
+ {
+
+ Lex();
+ SQObject id = Expect(TK_IDENTIFIER);
+ Expect(_SC('{'));
+
+ SQObject table = _fs->CreateTable();
+ SQInteger nval = 0;
+ while(_token != _SC('}')) {
+ SQObject key = Expect(TK_IDENTIFIER);
+ SQObject val;
+ if(_token == _SC('=')) {
+ Lex();
+ val = ExpectScalar();
+ }
+ else {
+ val._type = OT_INTEGER;
+ val._unVal.nInteger = nval++;
+ }
+ _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
+ if(_token == ',') Lex();
+ }
+ SQTable *enums = _table(_ss(_vm)->_consts);
+ SQObjectPtr strongid = id;
+ /*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()
{
SQObject exid;
SQObject paramname;
funcstate->AddParameter(_fs->CreateString(_SC("this")));
funcstate->_sourcename = _sourcename;
+ SQInteger defparams = 0;
while(_token!=_SC(')')) {
if(_token == TK_VARPARAMS) {
+ if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
funcstate->_varparams = true;
Lex();
if(_token != _SC(')')) Error(_SC("expected ')'"));
else {
paramname = Expect(TK_IDENTIFIER);
funcstate->AddParameter(paramname);
+ if(_token == _SC('=')) {
+ Lex();
+ Expression();
+ funcstate->AddDefaultParam(_fs->TopTarget());
+ defparams++;
+ }
+ else {
+ if(defparams > 0) Error(_SC("expected '='"));
+ }
if(_token == _SC(',')) Lex();
else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
}
}
Expect(_SC(')'));
+ for(SQInteger n = 0; n < defparams; n++) {
+ _fs->PopTarget();
+ }
//outer values
if(_token == _SC(':')) {
Lex(); Expect(_SC('('));
#define TK_ATTR_OPEN 320
#define TK_ATTR_CLOSE 321
#define TK_STATIC 322
+#define TK_ENUM 323
+#define TK_CONST 324
typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s);
typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
typedef sqvector<SQLineInfo> SQLineInfoVec;
-#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf) (sizeof(SQFunctionProto) \
+#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \
+((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
+(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \
+(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
- +(localinf*sizeof(SQLocalVarInfo)))
+ +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
#define _CONSTRUCT_VECTOR(type,size,ptr) { \
for(SQInteger n = 0; n < size; n++) { \
static SQFunctionProto *Create(SQInteger ninstructions,
SQInteger nliterals,SQInteger nparameters,
SQInteger nfunctions,SQInteger noutervalues,
- SQInteger nlineinfos,SQInteger nlocalvarinfos)
+ SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
{
SQFunctionProto *f;
//I compact the whole class and members in a single memory allocation
- f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos));
+ f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
new (f) SQFunctionProto;
f->_ninstructions = ninstructions;
f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
f->_nlineinfos = nlineinfos;
f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
f->_nlocalvarinfos = nlocalvarinfos;
+ f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
+ f->_ndefaultparams = ndefaultparams;
_CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
- SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos);
+ SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
this->~SQFunctionProto();
sq_vm_free(this,size);
}
SQInteger _noutervalues;
SQOuterVar *_outervalues;
+
+ SQInteger _ndefaultparams;
+ SQInteger *_defaultparams;
SQInteger _ninstructions;
SQInstruction _instructions[1];
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;
- default: assert(0); break; //shut up compiler
+ 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
}
}
}
}
+bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
+{
+ SQObjectPtr val;
+ if(_table(_sharedstate->_consts)->Get(name,val)) {
+ e = val;
+ return true;
+ }
+ return false;
+}
+
bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
{
if(stkpos>=_vlocals.size())return false;
return ns;
}
+SQObject SQFuncState::CreateTable()
+{
+ SQObjectPtr nt(SQTable::Create(_sharedstate,0));
+ _table(_strings)->NewSlot(nt,(SQInteger)1);
+ return nt;
+}
+
SQFunctionProto *SQFuncState::BuildProto()
{
SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
_nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
- _lineinfos.size(),_localvarinfos.size());
+ _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
SQObjectPtr refidx,key,val;
SQInteger idx;
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];
memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
void SetStackSize(SQInteger n);
void SnoozeOpt(){_optimization=false;}
+ void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
+ SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
SQInteger GetCurrentPos(){return _instructions.size()-1;}
SQInteger GetNumericConstant(const SQInteger cons);
SQInteger GetNumericConstant(const SQFloat cons);
SQInteger GetUpTarget(SQInteger n);
bool IsLocal(SQUnsignedInteger stkpos);
SQObject CreateString(const SQChar *s,SQInteger len = -1);
+ SQObject CreateTable();
+ bool IsConstant(const SQObject &name,SQObject &e);
SQInteger _returnexp;
SQLocalVarInfoVec _vlocals;
SQIntVec _targetstack;
SQFuncState *_parent;
SQIntVec _breaktargets;
SQIntVec _continuetargets;
+ SQIntVec _defaultparams;
SQInteger _lastline;
SQInteger _traps; //contains number of nested exception traps
bool _optimization;
ADD_KEYWORD(true,TK_TRUE);
ADD_KEYWORD(false,TK_FALSE);
ADD_KEYWORD(static,TK_STATIC);
+ ADD_KEYWORD(enum,TK_ENUM);
+ ADD_KEYWORD(const,TK_CONST);
_readf = rg;
_up = up;
}
}
+SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }
+
+void LexOctal(const SQChar *s,SQUnsignedInteger *res)
+{
+ *res = 0;
+ while(*s != 0)
+ {
+ if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
+ else { assert(0); }
+ }
+}
+
SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
+
+
#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)
SQInteger SQLexer::ReadNumber()
{
#define TFLOAT 2
#define THEX 3
#define TSCIENTIFIC 4
+#define TOCTAL 5
SQInteger type = TINT, firstchar = CUR_CHAR;
SQChar *sTemp;
INIT_TEMP_STRING();
NEXT();
- if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {
- NEXT();
- type = THEX;
- while(isxdigit(CUR_CHAR)) {
- APPEND_CHAR(CUR_CHAR);
+ if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {
+ if(scisodigit(CUR_CHAR)) {
+ type = TOCTAL;
+ while(scisodigit(CUR_CHAR)) {
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));
+ }
+ else {
NEXT();
+ type = THEX;
+ while(isxdigit(CUR_CHAR)) {
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
}
- if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
}
else {
APPEND_CHAR((int)firstchar);
case THEX:
LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
return TK_INTEGER;
+ case TOCTAL:
+ LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
+ return TK_INTEGER;
}
return 0;
}
#ifndef _SQLEXER_H_
#define _SQLEXER_H_
-#ifdef _UNICODE
+#ifdef SQUNICODE
typedef SQChar LexChar;
#else
typedef unsigned char LexChar;
#include "sqclass.h"
#include "sqclosure.h"
+
+const SQChar *IdType2Name(SQObjectType type)
+{
+ switch(_RAW_TYPE(type))
+ {
+ case _RT_NULL:return _SC("null");
+ case _RT_INTEGER:return _SC("integer");
+ case _RT_FLOAT:return _SC("float");
+ case _RT_BOOL:return _SC("bool");
+ case _RT_STRING:return _SC("string");
+ case _RT_TABLE:return _SC("table");
+ case _RT_ARRAY:return _SC("array");
+ case _RT_GENERATOR:return _SC("generator");
+ case _RT_CLOSURE:
+ case _RT_NATIVECLOSURE:
+ return _SC("function");
+ case _RT_USERDATA:
+ case _RT_USERPOINTER:
+ return _SC("userdata");
+ case _RT_THREAD: return _SC("thread");
+ case _RT_FUNCPROTO: return _SC("function");
+ case _RT_CLASS: return _SC("class");
+ case _RT_INSTANCE: return _SC("instance");
+ case _RT_WEAKREF: return _SC("weakref");
+ default:
+ return NULL;
+ }
+}
+
+const SQChar *GetTypeName(const SQObjectPtr &obj1)
+{
+ return IdType2Name(type(obj1));
+}
+
SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
{
SQString *str=ADD_STRING(ss,s,len);
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))
+ v->CallDebugHook(_SC('c'));
+
return true;
}
SQInteger i,nliterals = _nliterals,nparameters = _nparameters;
SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
+ SQInteger ndefaultparams = _ndefaultparams;
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(WriteObject(v,up,write,_sourcename));
_CHECK_IO(WriteObject(v,up,write,_name));
_CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
_CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
_CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
+ _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
_CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
_CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));
+
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
{
SQInteger i, nliterals,nparameters;
SQInteger noutervalues ,nlocalvarinfos ;
- SQInteger nlineinfos,ninstructions ,nfunctions ;
+ SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
SQObjectPtr sourcename, name;
SQObjectPtr o;
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
_CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
_CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
+ _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
_CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
_CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
+
- SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos);
+ SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,
+ nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
SQObjectPtr proto = f; //gets a ref in case of failure
f->_sourcename = sourcename;
f->_name = name;
_CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));
+
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
_CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
_CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
+
ret = f;
return true;
}
{
START_MARK()
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);
END_MARK()
}
SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
typedef sqvector<SQObjectPtr> SQObjectPtrVec;
typedef sqvector<SQInteger> SQIntVec;
+const SQChar *GetTypeName(const SQObjectPtr &obj1);
+const SQChar *IdType2Name(SQObjectType type);
+
#endif //_SQOBJECT_H_
_constructoridx = SQString::Create(this,_SC("constructor"));
_registry = SQTable::Create(this,0);
- _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);
- _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);
- _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz);
- _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz);
- _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz);
- _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz);
- _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);
- _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);
- _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);
- _weakref_default_delegate=CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
+ _consts = SQTable::Create(this,0);
+ _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
+ _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
+ _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
+ _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
+ _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
+ _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);
+ _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);
+ _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);
+ _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);
+ _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
}
SQSharedState::~SQSharedState()
{
_constructoridx = _null_;
- _refs_table.Finalize();
_table(_registry)->Finalize();
+ _table(_consts)->Finalize();
_table(_metamethodsmap)->Finalize();
_registry = _null_;
+ _consts = _null_;
_metamethodsmap = _null_;
while(!_systemstrings->empty()) {
_systemstrings->back()=_null_;
}
_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_;
-
+ _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;
- SQCollectable *nx=NULL;
+ SQCollectable *t = _gc_chain;
+ SQCollectable *nx = NULL;
while(t) {
t->_uiRef++;
t->Finalize();
- nx=t->_next;
+ nx = t->_next;
if(--t->_uiRef == 0)
t->Release();
t=nx;
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);
StringTable *_stringtable;
RefTable _refs_table;
SQObjectPtr _registry;
+ SQObjectPtr _consts;
SQObjectPtr _constructoridx;
#ifndef NO_GARBAGE_COLLECTOR
SQCollectable *_gc_chain;
return true;
}
-const SQChar *IdType2Name(SQObjectType type)
-{
- switch(_RAW_TYPE(type))
- {
- case _RT_NULL:return _SC("null");
- case _RT_INTEGER:return _SC("integer");
- case _RT_FLOAT:return _SC("float");
- case _RT_BOOL:return _SC("bool");
- case _RT_STRING:return _SC("string");
- case _RT_TABLE:return _SC("table");
- case _RT_ARRAY:return _SC("array");
- case _RT_GENERATOR:return _SC("generator");
- case _RT_CLOSURE:
- case _RT_NATIVECLOSURE:
- return _SC("function");
- case _RT_USERDATA:
- case _RT_USERPOINTER:
- return _SC("userdata");
- case _RT_THREAD: return _SC("thread");
- case _RT_FUNCPROTO: return _SC("function");
- case _RT_CLASS: return _SC("class");
- case _RT_INSTANCE: return _SC("instance");
- case _RT_WEAKREF: return _SC("weakref");
- default:
- return NULL;
- }
-}
-
-const SQChar *GetTypeName(const SQObjectPtr &obj1)
-{
- return IdType2Name(type(obj1));
-}
-
void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
{
if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
extern SQInstructionDesc g_InstrDesc[];
-bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger nargs,SQInteger stackbase,bool tailcall)
+bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)
{
SQFunctionProto *func = _funcproto(closure->_function);
const SQInteger paramssize = func->_nparameters;
const SQInteger newtop = stackbase + func->_stacksize;
-
-
+ SQInteger nargs = args;
if (paramssize != nargs) {
- if(func->_varparams)
+ SQInteger ndef = func->_ndefaultparams;
+ if(ndef && nargs < paramssize) {
+ SQInteger diff = paramssize - nargs;
+ for(SQInteger n = ndef - diff; n < ndef; n++) {
+ _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
+ }
+ }
+ else if(func->_varparams)
{
if (nargs < paramssize) {
Raise_Error(_SC("wrong number of parameters"));
ci->_ncalls++;
}
ci->_vargs.size = (SQInt32)(nargs - paramssize);
- ci->_vargs.base = (SQInt32) (_vargsstack.size()-(ci->_vargs.size));
+ ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size));
ci->_closure._unVal.pClosure = closure;
ci->_closure._type = OT_CLOSURE;
ci->_literals = func->_literals;
_top = newtop;
_stackbase = stackbase;
+ if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
+ CallDebugHook(_SC('c'));
return true;
}
}
}
}
+ 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]);
+ }
+ }
target = closure;
return true;
ct_stackbase = _stackbase+arg2;
common_call:
+ SQObjectPtr clo = temp_reg;
SQInteger last_top = _top;
- switch (type(temp_reg)) {
+ switch (type(clo)) {
case OT_CLOSURE:{
- _GUARD(StartCall(_closure(temp_reg), ct_target, arg3, ct_stackbase, ct_tailcall));
- if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
- SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));
+ _GUARD(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, temp_reg);
-
-
-
-
+ Return(1, ct_target, clo);
STK(ct_target) = gen;
while (last_top >= _top) _stack._vals[last_top--].Null();
continue;
}
- if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
- CallDebugHook(_SC('c'));
}
continue;
case OT_NATIVECLOSURE: {
bool suspend;
- _GUARD(CallNative(_nativeclosure(temp_reg), arg3, ct_stackbase, temp_reg,suspend));
+ _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend));
if(suspend){
_suspended = SQTrue;
_suspended_target = ct_target;
_suspended_root = ci->_root;
_suspended_traps = traps;
_suspend_varargs = ci->_vargs;
- outres = temp_reg;
+ outres = clo;
return true;
}
if(ct_target != -1) { //skip return value for constructors
- STK(ct_target) = temp_reg;
+ STK(ct_target) = clo;
}
}
continue;
case OT_CLASS:{
SQObjectPtr inst;
- _GUARD(CreateClassInstance(_class(temp_reg),inst,temp_reg));
+ _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) {
case OT_USERDATA:
case OT_INSTANCE:
{
- Push(temp_reg);
+ Push(clo);
for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
- if (_delegable(temp_reg) && CallMetaMethod(_delegable(temp_reg), MT_CALL, arg3+1, temp_reg)){
- STK(ct_target) = temp_reg;
+ if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){
+ STK(ct_target) = clo;
break;
}
- Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));
+ Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
SQ_THROW();
}
default:
- Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));
+ Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
SQ_THROW();
}
}
if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
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;
+ }
+ break;}
case OT_CLASS:
if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
if(_class(self)->_locked) {
case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break;
case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
- case OT_GENERATOR: scprintf(_SC("GENERATOR"));break;
+ case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break;
case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break;
case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break;
};
inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
-const SQChar *GetTypeName(const SQObjectPtr &obj1);
-const SQChar *IdType2Name(SQObjectType type);
#define _ss(_vm_) (_vm_)->_sharedstate