#include "sqfuncstate.h"
#include "sqlexer.h"
#include "sqvm.h"
+#include "sqtable.h"
#define DEREF_NO_DEREF -1
#define DEREF_FIELD -2
}
SQObject Expect(SQInteger tok)
{
-
+
if(_token != tok) {
if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
//ret = SQString::Create(_ss(_vm),_SC("constructor"));
SQOpcode op;
if(_token == TK_RETURN) {
op = _OP_RETURN;
-
+
}
else {
op = _OP_YIELD;
_fs->_returnexp = retexp;
_fs->AddInstruction(op, 1, _fs->PopTarget());
}
- else{
+ else{
if(op == _OP_RETURN && _fs->_traps > 0)
_fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
_fs->_returnexp = -1;
- _fs->AddInstruction(op, 0xFF);
+ _fs->AddInstruction(op, 0xFF);
}
break;}
case TK_BREAK:
case TK_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_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;
- default: return;
+ default: return;
}
}
void ShiftExp()
case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
- default: return;
+ default: return;
}
}
void PlusExp()
default: return;
}
}
-
+
void MultExp()
{
PrefixedExpr();
switch(_token) {
case _SC('.'): {
pos = -1;
- Lex();
+ Lex();
if(_token == TK_PARENT) {
Lex();
if(!NeedGet())
break;
case _SC('['):
if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
- Lex(); Expression(); Expect(_SC(']'));
+ Lex(); Expression(); Expect(_SC(']'));
pos = -1;
if(NeedGet()) Emit2ArgsOP(_OP_GET);
_exst._deref = DEREF_FIELD;
break;
case TK_MINUSMINUS:
case TK_PLUSPLUS:
- if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
+ if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
SQInteger tok = _token; Lex();
if(pos < 0)
Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);
SQInteger src = _fs->PopTarget();
_fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);
}
-
+
}
return;
- break;
- case _SC('('):
+ break;
+ case _SC('('):
{
if(_exst._deref != DEREF_NO_DEREF) {
if(pos<0) {
case TK_STRING_LITERAL: {
//SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
- Lex();
+ Lex();
}
break;
case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;
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;
//checks if is a free variable
if((pos = _fs->GetOuterVariable(id)) != -1) {
_exst._deref = _fs->PushTarget();
- _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
+ _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
_exst._freevar = true;
- } else {
+ }
+ 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;
_token = _SC('.'); //hack
return -1;
break;
- case TK_NULL:
+ case TK_NULL:
_fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
Lex();
break;
}
break;
case TK_FLOAT:
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
+ if(sizeof(SQFloat) == sizeof(SQInt32)) {
+ _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));
+ }
+ else {
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
+ }
Lex();
break;
case TK_TRUE: case TK_FALSE:
SQInteger apos = _fs->GetCurrentPos(),key = 0;
Lex();
while(_token != _SC(']')) {
- Expression();
+ Expression();
if(_token == _SC(',')) Lex();
SQInteger val = _fs->PopTarget();
SQInteger array = _fs->TopTarget();
case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;
case TK_RESUME : UnaryOP(_OP_RESUME); break;
case TK_CLONE : UnaryOP(_OP_CLONE); break;
- case TK_MINUSMINUS :
+ case TK_MINUSMINUS :
case TK_PLUSPLUS :PrefixIncDec(_token); break;
case TK_DELETE : DeleteExpr(); break;
case TK_DELEGATE : DelegateExpr(); break;
}
return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));
}
-
+
void FunctionCallArgs()
{
SQInteger nargs = 1;//this
while(_token != _SC(')')) {
Expression(true);
MoveIfCurrentTargetIsLocal();
- nargs++;
- if(_token == _SC(',')){
- Lex();
+ nargs++;
+ if(_token == _SC(',')){
+ Lex();
if(_token == ')') Error(_SC("expression expected, found ')'"));
}
}
void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')
{
SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
-
+
while(_token != terminator) {
bool hasattrs = false;
bool isstatic = false;
}
_fs->PopTarget();
_fs->PushLocalVariable(varname);
-
+
} while(_token == _SC(','));
}
void IfStatement()
_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
SQInteger jnepos = _fs->GetCurrentPos();
SQInteger stacksize = _fs->GetStackSize();
-
+
Statement();
//
if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
-
+
CleanStack(stacksize);
SQInteger endifblock = _fs->GetCurrentPos();
if(_token == TK_ELSE){
SQInteger stacksize = _fs->GetStackSize();
jmppos = _fs->GetCurrentPos();
Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
-
+
BEGIN_BREAKBLE_BLOCK();
_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
jzpos = _fs->GetCurrentPos();
stacksize = _fs->GetStackSize();
-
+
Statement();
-
+
CleanStack(stacksize);
_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
_fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
-
+
END_BREAKBLE_BLOCK(jmppos);
}
void DoWhileStatement()
_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
CleanStack(stacksize);
-
+
END_BREAKBLE_BLOCK(continuetrg);
}
void ForEachStatement()
idxname = _fs->CreateString(_SC("@INDEX@"));
}
Expect(TK_IN);
-
+
//save the stack size
SQInteger stacksize = _fs->GetStackSize();
//put the table in the stack(evaluate the table expression)
SQInteger jmppos = _fs->GetCurrentPos();
_fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
SQInteger foreachpos = _fs->GetCurrentPos();
+ _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
//generate the statement code
BEGIN_BREAKBLE_BLOCK()
Statement();
_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
_fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
+ _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
//restore the local variable stack(remove index,val and ref idx)
CleanStack(stacksize);
END_BREAKBLE_BLOCK(foreachpos - 1);
__nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
_fs->_breaktargets.pop_back();
-
+
}
void FunctionStatement()
{
_fs->PushTarget(0);
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
-
+
while(_token == TK_DOUBLE_COLON) {
Lex();
id = Expect(TK_IDENTIFIER);
}
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;
}
void CreateFunction(SQObject &name)
{
-
+
SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
funcstate->_name = name;
SQObject paramname;
funcstate->AddParameter(_fs->CreateString(_SC("this")));
funcstate->_sourcename = _sourcename;
+ SQInteger defparams = 0;
while(_token!=_SC(')')) {
if(_token == TK_VARPARAMS) {
+ if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
funcstate->_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('('));
}
Lex();
}
-
+
SQFuncState *currchunk = _fs;
_fs = funcstate;
Statement();