The Squirrel interpreter. See http://www.squirrel-lang.org/

Dependents:   Squirrel

Committer:
jhnwkmn
Date:
Tue Dec 16 11:39:42 2014 +0000
Revision:
3:7268a3ceaffc
Parent:
0:97a4f8cc534c
Accepts \r as line terminator as well.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jhnwkmn 0:97a4f8cc534c 1 /*
jhnwkmn 0:97a4f8cc534c 2 see copyright notice in squirrel.h
jhnwkmn 0:97a4f8cc534c 3 */
jhnwkmn 0:97a4f8cc534c 4 #include "sqpcheader.h"
jhnwkmn 0:97a4f8cc534c 5 #ifndef NO_COMPILER
jhnwkmn 0:97a4f8cc534c 6 #include <stdarg.h>
jhnwkmn 0:97a4f8cc534c 7 #include <setjmp.h>
jhnwkmn 0:97a4f8cc534c 8 #include "sqopcodes.h"
jhnwkmn 0:97a4f8cc534c 9 #include "sqstring.h"
jhnwkmn 0:97a4f8cc534c 10 #include "sqfuncproto.h"
jhnwkmn 0:97a4f8cc534c 11 #include "sqcompiler.h"
jhnwkmn 0:97a4f8cc534c 12 #include "sqfuncstate.h"
jhnwkmn 0:97a4f8cc534c 13 #include "sqlexer.h"
jhnwkmn 0:97a4f8cc534c 14 #include "sqvm.h"
jhnwkmn 0:97a4f8cc534c 15 #include "sqtable.h"
jhnwkmn 0:97a4f8cc534c 16
jhnwkmn 0:97a4f8cc534c 17 #define EXPR 1
jhnwkmn 0:97a4f8cc534c 18 #define OBJECT 2
jhnwkmn 0:97a4f8cc534c 19 #define BASE 3
jhnwkmn 0:97a4f8cc534c 20 #define LOCAL 4
jhnwkmn 0:97a4f8cc534c 21 #define OUTER 5
jhnwkmn 0:97a4f8cc534c 22
jhnwkmn 0:97a4f8cc534c 23 struct SQExpState {
jhnwkmn 0:97a4f8cc534c 24 SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */
jhnwkmn 0:97a4f8cc534c 25 SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */
jhnwkmn 0:97a4f8cc534c 26 bool donot_get; /* signal not to deref the next value */
jhnwkmn 0:97a4f8cc534c 27 };
jhnwkmn 0:97a4f8cc534c 28
jhnwkmn 0:97a4f8cc534c 29 #define MAX_COMPILER_ERROR_LEN 256
jhnwkmn 0:97a4f8cc534c 30
jhnwkmn 0:97a4f8cc534c 31 struct SQScope {
jhnwkmn 0:97a4f8cc534c 32 SQInteger outers;
jhnwkmn 0:97a4f8cc534c 33 SQInteger stacksize;
jhnwkmn 0:97a4f8cc534c 34 };
jhnwkmn 0:97a4f8cc534c 35
jhnwkmn 0:97a4f8cc534c 36 #define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
jhnwkmn 0:97a4f8cc534c 37 _scope.outers = _fs->_outers; \
jhnwkmn 0:97a4f8cc534c 38 _scope.stacksize = _fs->GetStackSize();
jhnwkmn 0:97a4f8cc534c 39
jhnwkmn 0:97a4f8cc534c 40 #define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \
jhnwkmn 0:97a4f8cc534c 41 if(_fs->CountOuters(_scope.stacksize)) { \
jhnwkmn 0:97a4f8cc534c 42 _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
jhnwkmn 0:97a4f8cc534c 43 } \
jhnwkmn 0:97a4f8cc534c 44 }
jhnwkmn 0:97a4f8cc534c 45
jhnwkmn 0:97a4f8cc534c 46 #define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \
jhnwkmn 0:97a4f8cc534c 47 _fs->SetStackSize(_scope.stacksize); \
jhnwkmn 0:97a4f8cc534c 48 } \
jhnwkmn 0:97a4f8cc534c 49 _scope = __oldscope__; \
jhnwkmn 0:97a4f8cc534c 50 }
jhnwkmn 0:97a4f8cc534c 51
jhnwkmn 0:97a4f8cc534c 52 #define END_SCOPE() { SQInteger oldouters = _fs->_outers;\
jhnwkmn 0:97a4f8cc534c 53 if(_fs->GetStackSize() != _scope.stacksize) { \
jhnwkmn 0:97a4f8cc534c 54 _fs->SetStackSize(_scope.stacksize); \
jhnwkmn 0:97a4f8cc534c 55 if(oldouters != _fs->_outers) { \
jhnwkmn 0:97a4f8cc534c 56 _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
jhnwkmn 0:97a4f8cc534c 57 } \
jhnwkmn 0:97a4f8cc534c 58 } \
jhnwkmn 0:97a4f8cc534c 59 _scope = __oldscope__; \
jhnwkmn 0:97a4f8cc534c 60 }
jhnwkmn 0:97a4f8cc534c 61
jhnwkmn 0:97a4f8cc534c 62 #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
jhnwkmn 0:97a4f8cc534c 63 SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \
jhnwkmn 0:97a4f8cc534c 64 _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
jhnwkmn 0:97a4f8cc534c 65
jhnwkmn 0:97a4f8cc534c 66 #define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
jhnwkmn 0:97a4f8cc534c 67 __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
jhnwkmn 0:97a4f8cc534c 68 if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
jhnwkmn 0:97a4f8cc534c 69 if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
jhnwkmn 0:97a4f8cc534c 70 _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
jhnwkmn 0:97a4f8cc534c 71
jhnwkmn 0:97a4f8cc534c 72 class SQCompiler
jhnwkmn 0:97a4f8cc534c 73 {
jhnwkmn 0:97a4f8cc534c 74 public:
jhnwkmn 0:97a4f8cc534c 75 SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
jhnwkmn 0:97a4f8cc534c 76 {
jhnwkmn 0:97a4f8cc534c 77 _vm=v;
jhnwkmn 0:97a4f8cc534c 78 _lex.Init(_ss(v), rg, up,ThrowError,this);
jhnwkmn 0:97a4f8cc534c 79 _sourcename = SQString::Create(_ss(v), sourcename);
jhnwkmn 0:97a4f8cc534c 80 _lineinfo = lineinfo;_raiseerror = raiseerror;
jhnwkmn 0:97a4f8cc534c 81 _scope.outers = 0;
jhnwkmn 0:97a4f8cc534c 82 _scope.stacksize = 0;
jhnwkmn 0:97a4f8cc534c 83 _compilererror[0] = NULL;
jhnwkmn 0:97a4f8cc534c 84 }
jhnwkmn 0:97a4f8cc534c 85 static void ThrowError(void *ud, const SQChar *s) {
jhnwkmn 0:97a4f8cc534c 86 SQCompiler *c = (SQCompiler *)ud;
jhnwkmn 0:97a4f8cc534c 87 c->Error(s);
jhnwkmn 0:97a4f8cc534c 88 }
jhnwkmn 0:97a4f8cc534c 89 void Error(const SQChar *s, ...)
jhnwkmn 0:97a4f8cc534c 90 {
jhnwkmn 0:97a4f8cc534c 91 va_list vl;
jhnwkmn 0:97a4f8cc534c 92 va_start(vl, s);
jhnwkmn 0:97a4f8cc534c 93 scvsprintf(_compilererror, s, vl);
jhnwkmn 0:97a4f8cc534c 94 va_end(vl);
jhnwkmn 0:97a4f8cc534c 95 longjmp(_errorjmp,1);
jhnwkmn 0:97a4f8cc534c 96 }
jhnwkmn 0:97a4f8cc534c 97 void Lex(){ _token = _lex.Lex();}
jhnwkmn 0:97a4f8cc534c 98 SQObject Expect(SQInteger tok)
jhnwkmn 0:97a4f8cc534c 99 {
jhnwkmn 0:97a4f8cc534c 100
jhnwkmn 0:97a4f8cc534c 101 if(_token != tok) {
jhnwkmn 0:97a4f8cc534c 102 if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
jhnwkmn 0:97a4f8cc534c 103 //do nothing
jhnwkmn 0:97a4f8cc534c 104 }
jhnwkmn 0:97a4f8cc534c 105 else {
jhnwkmn 0:97a4f8cc534c 106 const SQChar *etypename;
jhnwkmn 0:97a4f8cc534c 107 if(tok > 255) {
jhnwkmn 0:97a4f8cc534c 108 switch(tok)
jhnwkmn 0:97a4f8cc534c 109 {
jhnwkmn 0:97a4f8cc534c 110 case TK_IDENTIFIER:
jhnwkmn 0:97a4f8cc534c 111 etypename = _SC("IDENTIFIER");
jhnwkmn 0:97a4f8cc534c 112 break;
jhnwkmn 0:97a4f8cc534c 113 case TK_STRING_LITERAL:
jhnwkmn 0:97a4f8cc534c 114 etypename = _SC("STRING_LITERAL");
jhnwkmn 0:97a4f8cc534c 115 break;
jhnwkmn 0:97a4f8cc534c 116 case TK_INTEGER:
jhnwkmn 0:97a4f8cc534c 117 etypename = _SC("INTEGER");
jhnwkmn 0:97a4f8cc534c 118 break;
jhnwkmn 0:97a4f8cc534c 119 case TK_FLOAT:
jhnwkmn 0:97a4f8cc534c 120 etypename = _SC("FLOAT");
jhnwkmn 0:97a4f8cc534c 121 break;
jhnwkmn 0:97a4f8cc534c 122 default:
jhnwkmn 0:97a4f8cc534c 123 etypename = _lex.Tok2Str(tok);
jhnwkmn 0:97a4f8cc534c 124 }
jhnwkmn 0:97a4f8cc534c 125 Error(_SC("expected '%s'"), etypename);
jhnwkmn 0:97a4f8cc534c 126 }
jhnwkmn 0:97a4f8cc534c 127 Error(_SC("expected '%c'"), tok);
jhnwkmn 0:97a4f8cc534c 128 }
jhnwkmn 0:97a4f8cc534c 129 }
jhnwkmn 0:97a4f8cc534c 130 SQObjectPtr ret;
jhnwkmn 0:97a4f8cc534c 131 switch(tok)
jhnwkmn 0:97a4f8cc534c 132 {
jhnwkmn 0:97a4f8cc534c 133 case TK_IDENTIFIER:
jhnwkmn 0:97a4f8cc534c 134 ret = _fs->CreateString(_lex._svalue);
jhnwkmn 0:97a4f8cc534c 135 break;
jhnwkmn 0:97a4f8cc534c 136 case TK_STRING_LITERAL:
jhnwkmn 0:97a4f8cc534c 137 ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
jhnwkmn 0:97a4f8cc534c 138 break;
jhnwkmn 0:97a4f8cc534c 139 case TK_INTEGER:
jhnwkmn 0:97a4f8cc534c 140 ret = SQObjectPtr(_lex._nvalue);
jhnwkmn 0:97a4f8cc534c 141 break;
jhnwkmn 0:97a4f8cc534c 142 case TK_FLOAT:
jhnwkmn 0:97a4f8cc534c 143 ret = SQObjectPtr(_lex._fvalue);
jhnwkmn 0:97a4f8cc534c 144 break;
jhnwkmn 0:97a4f8cc534c 145 }
jhnwkmn 0:97a4f8cc534c 146 Lex();
jhnwkmn 0:97a4f8cc534c 147 return ret;
jhnwkmn 0:97a4f8cc534c 148 }
jhnwkmn 0:97a4f8cc534c 149 bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
jhnwkmn 0:97a4f8cc534c 150 void OptionalSemicolon()
jhnwkmn 0:97a4f8cc534c 151 {
jhnwkmn 0:97a4f8cc534c 152 if(_token == _SC(';')) { Lex(); return; }
jhnwkmn 0:97a4f8cc534c 153 if(!IsEndOfStatement()) {
jhnwkmn 0:97a4f8cc534c 154 Error(_SC("end of statement expected (; or lf)"));
jhnwkmn 0:97a4f8cc534c 155 }
jhnwkmn 0:97a4f8cc534c 156 }
jhnwkmn 0:97a4f8cc534c 157 void MoveIfCurrentTargetIsLocal() {
jhnwkmn 0:97a4f8cc534c 158 SQInteger trg = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 159 if(_fs->IsLocal(trg)) {
jhnwkmn 0:97a4f8cc534c 160 trg = _fs->PopTarget(); //no pops the target and move it
jhnwkmn 0:97a4f8cc534c 161 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
jhnwkmn 0:97a4f8cc534c 162 }
jhnwkmn 0:97a4f8cc534c 163 }
jhnwkmn 0:97a4f8cc534c 164 bool Compile(SQObjectPtr &o)
jhnwkmn 0:97a4f8cc534c 165 {
jhnwkmn 0:97a4f8cc534c 166 _debugline = 1;
jhnwkmn 0:97a4f8cc534c 167 _debugop = 0;
jhnwkmn 0:97a4f8cc534c 168
jhnwkmn 0:97a4f8cc534c 169 SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
jhnwkmn 0:97a4f8cc534c 170 funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
jhnwkmn 0:97a4f8cc534c 171 _fs = &funcstate;
jhnwkmn 0:97a4f8cc534c 172 _fs->AddParameter(_fs->CreateString(_SC("this")));
jhnwkmn 0:97a4f8cc534c 173 _fs->AddParameter(_fs->CreateString(_SC("vargv")));
jhnwkmn 0:97a4f8cc534c 174 _fs->_varparams = true;
jhnwkmn 0:97a4f8cc534c 175 _fs->_sourcename = _sourcename;
jhnwkmn 0:97a4f8cc534c 176 SQInteger stacksize = _fs->GetStackSize();
jhnwkmn 0:97a4f8cc534c 177 if(setjmp(_errorjmp) == 0) {
jhnwkmn 0:97a4f8cc534c 178 Lex();
jhnwkmn 0:97a4f8cc534c 179 while(_token > 0){
jhnwkmn 0:97a4f8cc534c 180 Statement();
jhnwkmn 0:97a4f8cc534c 181 if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
jhnwkmn 0:97a4f8cc534c 182 }
jhnwkmn 0:97a4f8cc534c 183 _fs->SetStackSize(stacksize);
jhnwkmn 0:97a4f8cc534c 184 _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
jhnwkmn 0:97a4f8cc534c 185 _fs->AddInstruction(_OP_RETURN, 0xFF);
jhnwkmn 0:97a4f8cc534c 186 _fs->SetStackSize(0);
jhnwkmn 0:97a4f8cc534c 187 o =_fs->BuildProto();
jhnwkmn 0:97a4f8cc534c 188 #ifdef _DEBUG_DUMP
jhnwkmn 0:97a4f8cc534c 189 _fs->Dump(_funcproto(o));
jhnwkmn 0:97a4f8cc534c 190 #endif
jhnwkmn 0:97a4f8cc534c 191 }
jhnwkmn 0:97a4f8cc534c 192 else {
jhnwkmn 0:97a4f8cc534c 193 if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
jhnwkmn 0:97a4f8cc534c 194 _ss(_vm)->_compilererrorhandler(_vm, _compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
jhnwkmn 0:97a4f8cc534c 195 _lex._currentline, _lex._currentcolumn);
jhnwkmn 0:97a4f8cc534c 196 }
jhnwkmn 0:97a4f8cc534c 197 _vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1);
jhnwkmn 0:97a4f8cc534c 198 return false;
jhnwkmn 0:97a4f8cc534c 199 }
jhnwkmn 0:97a4f8cc534c 200 return true;
jhnwkmn 0:97a4f8cc534c 201 }
jhnwkmn 0:97a4f8cc534c 202 void Statements()
jhnwkmn 0:97a4f8cc534c 203 {
jhnwkmn 0:97a4f8cc534c 204 while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
jhnwkmn 0:97a4f8cc534c 205 Statement();
jhnwkmn 0:97a4f8cc534c 206 if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
jhnwkmn 0:97a4f8cc534c 207 }
jhnwkmn 0:97a4f8cc534c 208 }
jhnwkmn 0:97a4f8cc534c 209 void Statement(bool closeframe = true)
jhnwkmn 0:97a4f8cc534c 210 {
jhnwkmn 0:97a4f8cc534c 211 _fs->AddLineInfos(_lex._currentline, _lineinfo);
jhnwkmn 0:97a4f8cc534c 212 switch(_token){
jhnwkmn 0:97a4f8cc534c 213 case _SC(';'): Lex(); break;
jhnwkmn 0:97a4f8cc534c 214 case TK_IF: IfStatement(); break;
jhnwkmn 0:97a4f8cc534c 215 case TK_WHILE: WhileStatement(); break;
jhnwkmn 0:97a4f8cc534c 216 case TK_DO: DoWhileStatement(); break;
jhnwkmn 0:97a4f8cc534c 217 case TK_FOR: ForStatement(); break;
jhnwkmn 0:97a4f8cc534c 218 case TK_FOREACH: ForEachStatement(); break;
jhnwkmn 0:97a4f8cc534c 219 case TK_SWITCH: SwitchStatement(); break;
jhnwkmn 0:97a4f8cc534c 220 case TK_LOCAL: LocalDeclStatement(); break;
jhnwkmn 0:97a4f8cc534c 221 case TK_RETURN:
jhnwkmn 0:97a4f8cc534c 222 case TK_YIELD: {
jhnwkmn 0:97a4f8cc534c 223 SQOpcode op;
jhnwkmn 0:97a4f8cc534c 224 if(_token == TK_RETURN) {
jhnwkmn 0:97a4f8cc534c 225 op = _OP_RETURN;
jhnwkmn 0:97a4f8cc534c 226 }
jhnwkmn 0:97a4f8cc534c 227 else {
jhnwkmn 0:97a4f8cc534c 228 op = _OP_YIELD;
jhnwkmn 0:97a4f8cc534c 229 _fs->_bgenerator = true;
jhnwkmn 0:97a4f8cc534c 230 }
jhnwkmn 0:97a4f8cc534c 231 Lex();
jhnwkmn 0:97a4f8cc534c 232 if(!IsEndOfStatement()) {
jhnwkmn 0:97a4f8cc534c 233 SQInteger retexp = _fs->GetCurrentPos()+1;
jhnwkmn 0:97a4f8cc534c 234 CommaExpr();
jhnwkmn 0:97a4f8cc534c 235 if(op == _OP_RETURN && _fs->_traps > 0)
jhnwkmn 0:97a4f8cc534c 236 _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
jhnwkmn 0:97a4f8cc534c 237 _fs->_returnexp = retexp;
jhnwkmn 0:97a4f8cc534c 238 _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize());
jhnwkmn 0:97a4f8cc534c 239 }
jhnwkmn 0:97a4f8cc534c 240 else{
jhnwkmn 0:97a4f8cc534c 241 if(op == _OP_RETURN && _fs->_traps > 0)
jhnwkmn 0:97a4f8cc534c 242 _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
jhnwkmn 0:97a4f8cc534c 243 _fs->_returnexp = -1;
jhnwkmn 0:97a4f8cc534c 244 _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize());
jhnwkmn 0:97a4f8cc534c 245 }
jhnwkmn 0:97a4f8cc534c 246 break;}
jhnwkmn 0:97a4f8cc534c 247 case TK_BREAK:
jhnwkmn 0:97a4f8cc534c 248 if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
jhnwkmn 0:97a4f8cc534c 249 if(_fs->_breaktargets.top() > 0){
jhnwkmn 0:97a4f8cc534c 250 _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
jhnwkmn 0:97a4f8cc534c 251 }
jhnwkmn 0:97a4f8cc534c 252 RESOLVE_OUTERS();
jhnwkmn 0:97a4f8cc534c 253 _fs->AddInstruction(_OP_JMP, 0, -1234);
jhnwkmn 0:97a4f8cc534c 254 _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
jhnwkmn 0:97a4f8cc534c 255 Lex();
jhnwkmn 0:97a4f8cc534c 256 break;
jhnwkmn 0:97a4f8cc534c 257 case TK_CONTINUE:
jhnwkmn 0:97a4f8cc534c 258 if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
jhnwkmn 0:97a4f8cc534c 259 if(_fs->_continuetargets.top() > 0) {
jhnwkmn 0:97a4f8cc534c 260 _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
jhnwkmn 0:97a4f8cc534c 261 }
jhnwkmn 0:97a4f8cc534c 262 RESOLVE_OUTERS();
jhnwkmn 0:97a4f8cc534c 263 _fs->AddInstruction(_OP_JMP, 0, -1234);
jhnwkmn 0:97a4f8cc534c 264 _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
jhnwkmn 0:97a4f8cc534c 265 Lex();
jhnwkmn 0:97a4f8cc534c 266 break;
jhnwkmn 0:97a4f8cc534c 267 case TK_FUNCTION:
jhnwkmn 0:97a4f8cc534c 268 FunctionStatement();
jhnwkmn 0:97a4f8cc534c 269 break;
jhnwkmn 0:97a4f8cc534c 270 case TK_CLASS:
jhnwkmn 0:97a4f8cc534c 271 ClassStatement();
jhnwkmn 0:97a4f8cc534c 272 break;
jhnwkmn 0:97a4f8cc534c 273 case TK_ENUM:
jhnwkmn 0:97a4f8cc534c 274 EnumStatement();
jhnwkmn 0:97a4f8cc534c 275 break;
jhnwkmn 0:97a4f8cc534c 276 case _SC('{'):{
jhnwkmn 0:97a4f8cc534c 277 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 278 Lex();
jhnwkmn 0:97a4f8cc534c 279 Statements();
jhnwkmn 0:97a4f8cc534c 280 Expect(_SC('}'));
jhnwkmn 0:97a4f8cc534c 281 if(closeframe) {
jhnwkmn 0:97a4f8cc534c 282 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 283 }
jhnwkmn 0:97a4f8cc534c 284 else {
jhnwkmn 0:97a4f8cc534c 285 END_SCOPE_NO_CLOSE();
jhnwkmn 0:97a4f8cc534c 286 }
jhnwkmn 0:97a4f8cc534c 287 }
jhnwkmn 0:97a4f8cc534c 288 break;
jhnwkmn 0:97a4f8cc534c 289 case TK_TRY:
jhnwkmn 0:97a4f8cc534c 290 TryCatchStatement();
jhnwkmn 0:97a4f8cc534c 291 break;
jhnwkmn 0:97a4f8cc534c 292 case TK_THROW:
jhnwkmn 0:97a4f8cc534c 293 Lex();
jhnwkmn 0:97a4f8cc534c 294 CommaExpr();
jhnwkmn 0:97a4f8cc534c 295 _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
jhnwkmn 0:97a4f8cc534c 296 break;
jhnwkmn 0:97a4f8cc534c 297 case TK_CONST:
jhnwkmn 0:97a4f8cc534c 298 {
jhnwkmn 0:97a4f8cc534c 299 Lex();
jhnwkmn 0:97a4f8cc534c 300 SQObject id = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 301 Expect('=');
jhnwkmn 0:97a4f8cc534c 302 SQObject val = ExpectScalar();
jhnwkmn 0:97a4f8cc534c 303 OptionalSemicolon();
jhnwkmn 0:97a4f8cc534c 304 SQTable *enums = _table(_ss(_vm)->_consts);
jhnwkmn 0:97a4f8cc534c 305 SQObjectPtr strongid = id;
jhnwkmn 0:97a4f8cc534c 306 enums->NewSlot(strongid,SQObjectPtr(val));
jhnwkmn 0:97a4f8cc534c 307 strongid.Null();
jhnwkmn 0:97a4f8cc534c 308 }
jhnwkmn 0:97a4f8cc534c 309 break;
jhnwkmn 0:97a4f8cc534c 310 default:
jhnwkmn 0:97a4f8cc534c 311 CommaExpr();
jhnwkmn 0:97a4f8cc534c 312 _fs->DiscardTarget();
jhnwkmn 0:97a4f8cc534c 313 //_fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 314 break;
jhnwkmn 0:97a4f8cc534c 315 }
jhnwkmn 0:97a4f8cc534c 316 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 317 }
jhnwkmn 0:97a4f8cc534c 318 void EmitDerefOp(SQOpcode op)
jhnwkmn 0:97a4f8cc534c 319 {
jhnwkmn 0:97a4f8cc534c 320 SQInteger val = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 321 SQInteger key = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 322 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 323 _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
jhnwkmn 0:97a4f8cc534c 324 }
jhnwkmn 0:97a4f8cc534c 325 void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
jhnwkmn 0:97a4f8cc534c 326 {
jhnwkmn 0:97a4f8cc534c 327 SQInteger p2 = _fs->PopTarget(); //src in OP_GET
jhnwkmn 0:97a4f8cc534c 328 SQInteger p1 = _fs->PopTarget(); //key in OP_GET
jhnwkmn 0:97a4f8cc534c 329 _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
jhnwkmn 0:97a4f8cc534c 330 }
jhnwkmn 0:97a4f8cc534c 331 void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos)
jhnwkmn 0:97a4f8cc534c 332 {
jhnwkmn 0:97a4f8cc534c 333 /* Generate code depending on the expression type */
jhnwkmn 0:97a4f8cc534c 334 switch(etype) {
jhnwkmn 0:97a4f8cc534c 335 case LOCAL:{
jhnwkmn 0:97a4f8cc534c 336 SQInteger p2 = _fs->PopTarget(); //src in OP_GET
jhnwkmn 0:97a4f8cc534c 337 SQInteger p1 = _fs->PopTarget(); //key in OP_GET
jhnwkmn 0:97a4f8cc534c 338 _fs->PushTarget(p1);
jhnwkmn 0:97a4f8cc534c 339 //EmitCompArithLocal(tok, p1, p1, p2);
jhnwkmn 0:97a4f8cc534c 340 _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);
jhnwkmn 0:97a4f8cc534c 341 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 342 }
jhnwkmn 0:97a4f8cc534c 343 break;
jhnwkmn 0:97a4f8cc534c 344 case OBJECT:
jhnwkmn 0:97a4f8cc534c 345 case BASE:
jhnwkmn 0:97a4f8cc534c 346 {
jhnwkmn 0:97a4f8cc534c 347 SQInteger val = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 348 SQInteger key = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 349 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 350 /* _OP_COMPARITH mixes dest obj and source val in the arg1 */
jhnwkmn 0:97a4f8cc534c 351 _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));
jhnwkmn 0:97a4f8cc534c 352 }
jhnwkmn 0:97a4f8cc534c 353 break;
jhnwkmn 0:97a4f8cc534c 354 case OUTER:
jhnwkmn 0:97a4f8cc534c 355 {
jhnwkmn 0:97a4f8cc534c 356 SQInteger val = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 357 SQInteger tmp = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 358 _fs->AddInstruction(_OP_GETOUTER, tmp, pos);
jhnwkmn 0:97a4f8cc534c 359 _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);
jhnwkmn 0:97a4f8cc534c 360 _fs->AddInstruction(_OP_SETOUTER, tmp, pos, tmp);
jhnwkmn 0:97a4f8cc534c 361 }
jhnwkmn 0:97a4f8cc534c 362 break;
jhnwkmn 0:97a4f8cc534c 363 }
jhnwkmn 0:97a4f8cc534c 364 }
jhnwkmn 0:97a4f8cc534c 365 void CommaExpr()
jhnwkmn 0:97a4f8cc534c 366 {
jhnwkmn 0:97a4f8cc534c 367 for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
jhnwkmn 0:97a4f8cc534c 368 }
jhnwkmn 0:97a4f8cc534c 369 void Expression()
jhnwkmn 0:97a4f8cc534c 370 {
jhnwkmn 0:97a4f8cc534c 371 SQExpState es = _es;
jhnwkmn 0:97a4f8cc534c 372 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 373 _es.epos = -1;
jhnwkmn 0:97a4f8cc534c 374 _es.donot_get = false;
jhnwkmn 0:97a4f8cc534c 375 LogicalOrExp();
jhnwkmn 0:97a4f8cc534c 376 switch(_token) {
jhnwkmn 0:97a4f8cc534c 377 case _SC('='):
jhnwkmn 0:97a4f8cc534c 378 case TK_NEWSLOT:
jhnwkmn 0:97a4f8cc534c 379 case TK_MINUSEQ:
jhnwkmn 0:97a4f8cc534c 380 case TK_PLUSEQ:
jhnwkmn 0:97a4f8cc534c 381 case TK_MULEQ:
jhnwkmn 0:97a4f8cc534c 382 case TK_DIVEQ:
jhnwkmn 0:97a4f8cc534c 383 case TK_MODEQ:{
jhnwkmn 0:97a4f8cc534c 384 SQInteger op = _token;
jhnwkmn 0:97a4f8cc534c 385 SQInteger ds = _es.etype;
jhnwkmn 0:97a4f8cc534c 386 SQInteger pos = _es.epos;
jhnwkmn 0:97a4f8cc534c 387 if(ds == EXPR) Error(_SC("can't assign expression"));
jhnwkmn 0:97a4f8cc534c 388 else if(ds == BASE) Error(_SC("'base' cannot be modified"));
jhnwkmn 0:97a4f8cc534c 389
jhnwkmn 0:97a4f8cc534c 390 Lex(); Expression();
jhnwkmn 0:97a4f8cc534c 391
jhnwkmn 0:97a4f8cc534c 392 switch(op){
jhnwkmn 0:97a4f8cc534c 393 case TK_NEWSLOT:
jhnwkmn 0:97a4f8cc534c 394 if(ds == OBJECT || ds == BASE)
jhnwkmn 0:97a4f8cc534c 395 EmitDerefOp(_OP_NEWSLOT);
jhnwkmn 0:97a4f8cc534c 396 else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
jhnwkmn 0:97a4f8cc534c 397 Error(_SC("can't 'create' a local slot"));
jhnwkmn 0:97a4f8cc534c 398 break;
jhnwkmn 0:97a4f8cc534c 399 case _SC('='): //ASSIGN
jhnwkmn 0:97a4f8cc534c 400 switch(ds) {
jhnwkmn 0:97a4f8cc534c 401 case LOCAL:
jhnwkmn 0:97a4f8cc534c 402 {
jhnwkmn 0:97a4f8cc534c 403 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 404 SQInteger dst = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 405 _fs->AddInstruction(_OP_MOVE, dst, src);
jhnwkmn 0:97a4f8cc534c 406 }
jhnwkmn 0:97a4f8cc534c 407 break;
jhnwkmn 0:97a4f8cc534c 408 case OBJECT:
jhnwkmn 0:97a4f8cc534c 409 case BASE:
jhnwkmn 0:97a4f8cc534c 410 EmitDerefOp(_OP_SET);
jhnwkmn 0:97a4f8cc534c 411 break;
jhnwkmn 0:97a4f8cc534c 412 case OUTER:
jhnwkmn 0:97a4f8cc534c 413 {
jhnwkmn 0:97a4f8cc534c 414 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 415 SQInteger dst = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 416 _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);
jhnwkmn 0:97a4f8cc534c 417 }
jhnwkmn 0:97a4f8cc534c 418 }
jhnwkmn 0:97a4f8cc534c 419 break;
jhnwkmn 0:97a4f8cc534c 420 case TK_MINUSEQ:
jhnwkmn 0:97a4f8cc534c 421 case TK_PLUSEQ:
jhnwkmn 0:97a4f8cc534c 422 case TK_MULEQ:
jhnwkmn 0:97a4f8cc534c 423 case TK_DIVEQ:
jhnwkmn 0:97a4f8cc534c 424 case TK_MODEQ:
jhnwkmn 0:97a4f8cc534c 425 EmitCompoundArith(op, ds, pos);
jhnwkmn 0:97a4f8cc534c 426 break;
jhnwkmn 0:97a4f8cc534c 427 }
jhnwkmn 0:97a4f8cc534c 428 }
jhnwkmn 0:97a4f8cc534c 429 break;
jhnwkmn 0:97a4f8cc534c 430 case _SC('?'): {
jhnwkmn 0:97a4f8cc534c 431 Lex();
jhnwkmn 0:97a4f8cc534c 432 _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
jhnwkmn 0:97a4f8cc534c 433 SQInteger jzpos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 434 SQInteger trg = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 435 Expression();
jhnwkmn 0:97a4f8cc534c 436 SQInteger first_exp = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 437 if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
jhnwkmn 0:97a4f8cc534c 438 SQInteger endfirstexp = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 439 _fs->AddInstruction(_OP_JMP, 0, 0);
jhnwkmn 0:97a4f8cc534c 440 Expect(_SC(':'));
jhnwkmn 0:97a4f8cc534c 441 SQInteger jmppos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 442 Expression();
jhnwkmn 0:97a4f8cc534c 443 SQInteger second_exp = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 444 if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
jhnwkmn 0:97a4f8cc534c 445 _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
jhnwkmn 0:97a4f8cc534c 446 _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
jhnwkmn 0:97a4f8cc534c 447 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 448 }
jhnwkmn 0:97a4f8cc534c 449 break;
jhnwkmn 0:97a4f8cc534c 450 }
jhnwkmn 0:97a4f8cc534c 451 _es = es;
jhnwkmn 0:97a4f8cc534c 452 }
jhnwkmn 0:97a4f8cc534c 453 template<typename T> void INVOKE_EXP(T f)
jhnwkmn 0:97a4f8cc534c 454 {
jhnwkmn 0:97a4f8cc534c 455 SQExpState es = _es;
jhnwkmn 0:97a4f8cc534c 456 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 457 _es.epos = -1;
jhnwkmn 0:97a4f8cc534c 458 _es.donot_get = false;
jhnwkmn 0:97a4f8cc534c 459 (this->*f)();
jhnwkmn 0:97a4f8cc534c 460 _es = es;
jhnwkmn 0:97a4f8cc534c 461 }
jhnwkmn 0:97a4f8cc534c 462 template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)
jhnwkmn 0:97a4f8cc534c 463 {
jhnwkmn 0:97a4f8cc534c 464 Lex();
jhnwkmn 0:97a4f8cc534c 465 INVOKE_EXP(f);
jhnwkmn 0:97a4f8cc534c 466 SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 467 _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
jhnwkmn 0:97a4f8cc534c 468 }
jhnwkmn 0:97a4f8cc534c 469 void LogicalOrExp()
jhnwkmn 0:97a4f8cc534c 470 {
jhnwkmn 0:97a4f8cc534c 471 LogicalAndExp();
jhnwkmn 0:97a4f8cc534c 472 for(;;) if(_token == TK_OR) {
jhnwkmn 0:97a4f8cc534c 473 SQInteger first_exp = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 474 SQInteger trg = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 475 _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
jhnwkmn 0:97a4f8cc534c 476 SQInteger jpos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 477 if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
jhnwkmn 0:97a4f8cc534c 478 Lex(); INVOKE_EXP(&SQCompiler::LogicalOrExp);
jhnwkmn 0:97a4f8cc534c 479 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 480 SQInteger second_exp = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 481 if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
jhnwkmn 0:97a4f8cc534c 482 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 483 _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
jhnwkmn 0:97a4f8cc534c 484 break;
jhnwkmn 0:97a4f8cc534c 485 }else return;
jhnwkmn 0:97a4f8cc534c 486 }
jhnwkmn 0:97a4f8cc534c 487 void LogicalAndExp()
jhnwkmn 0:97a4f8cc534c 488 {
jhnwkmn 0:97a4f8cc534c 489 BitwiseOrExp();
jhnwkmn 0:97a4f8cc534c 490 for(;;) switch(_token) {
jhnwkmn 0:97a4f8cc534c 491 case TK_AND: {
jhnwkmn 0:97a4f8cc534c 492 SQInteger first_exp = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 493 SQInteger trg = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 494 _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
jhnwkmn 0:97a4f8cc534c 495 SQInteger jpos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 496 if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
jhnwkmn 0:97a4f8cc534c 497 Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp);
jhnwkmn 0:97a4f8cc534c 498 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 499 SQInteger second_exp = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 500 if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
jhnwkmn 0:97a4f8cc534c 501 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 502 _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
jhnwkmn 0:97a4f8cc534c 503 break;
jhnwkmn 0:97a4f8cc534c 504 }
jhnwkmn 0:97a4f8cc534c 505
jhnwkmn 0:97a4f8cc534c 506 default:
jhnwkmn 0:97a4f8cc534c 507 return;
jhnwkmn 0:97a4f8cc534c 508 }
jhnwkmn 0:97a4f8cc534c 509 }
jhnwkmn 0:97a4f8cc534c 510 void BitwiseOrExp()
jhnwkmn 0:97a4f8cc534c 511 {
jhnwkmn 0:97a4f8cc534c 512 BitwiseXorExp();
jhnwkmn 0:97a4f8cc534c 513 for(;;) if(_token == _SC('|'))
jhnwkmn 0:97a4f8cc534c 514 {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
jhnwkmn 0:97a4f8cc534c 515 }else return;
jhnwkmn 0:97a4f8cc534c 516 }
jhnwkmn 0:97a4f8cc534c 517 void BitwiseXorExp()
jhnwkmn 0:97a4f8cc534c 518 {
jhnwkmn 0:97a4f8cc534c 519 BitwiseAndExp();
jhnwkmn 0:97a4f8cc534c 520 for(;;) if(_token == _SC('^'))
jhnwkmn 0:97a4f8cc534c 521 {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
jhnwkmn 0:97a4f8cc534c 522 }else return;
jhnwkmn 0:97a4f8cc534c 523 }
jhnwkmn 0:97a4f8cc534c 524 void BitwiseAndExp()
jhnwkmn 0:97a4f8cc534c 525 {
jhnwkmn 0:97a4f8cc534c 526 EqExp();
jhnwkmn 0:97a4f8cc534c 527 for(;;) if(_token == _SC('&'))
jhnwkmn 0:97a4f8cc534c 528 {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);
jhnwkmn 0:97a4f8cc534c 529 }else return;
jhnwkmn 0:97a4f8cc534c 530 }
jhnwkmn 0:97a4f8cc534c 531 void EqExp()
jhnwkmn 0:97a4f8cc534c 532 {
jhnwkmn 0:97a4f8cc534c 533 CompExp();
jhnwkmn 0:97a4f8cc534c 534 for(;;) switch(_token) {
jhnwkmn 0:97a4f8cc534c 535 case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;
jhnwkmn 0:97a4f8cc534c 536 case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;
jhnwkmn 0:97a4f8cc534c 537 case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;
jhnwkmn 0:97a4f8cc534c 538 default: return;
jhnwkmn 0:97a4f8cc534c 539 }
jhnwkmn 0:97a4f8cc534c 540 }
jhnwkmn 0:97a4f8cc534c 541 void CompExp()
jhnwkmn 0:97a4f8cc534c 542 {
jhnwkmn 0:97a4f8cc534c 543 ShiftExp();
jhnwkmn 0:97a4f8cc534c 544 for(;;) switch(_token) {
jhnwkmn 0:97a4f8cc534c 545 case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
jhnwkmn 0:97a4f8cc534c 546 case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
jhnwkmn 0:97a4f8cc534c 547 case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
jhnwkmn 0:97a4f8cc534c 548 case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
jhnwkmn 0:97a4f8cc534c 549 case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break;
jhnwkmn 0:97a4f8cc534c 550 case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::ShiftExp); break;
jhnwkmn 0:97a4f8cc534c 551 default: return;
jhnwkmn 0:97a4f8cc534c 552 }
jhnwkmn 0:97a4f8cc534c 553 }
jhnwkmn 0:97a4f8cc534c 554 void ShiftExp()
jhnwkmn 0:97a4f8cc534c 555 {
jhnwkmn 0:97a4f8cc534c 556 PlusExp();
jhnwkmn 0:97a4f8cc534c 557 for(;;) switch(_token) {
jhnwkmn 0:97a4f8cc534c 558 case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
jhnwkmn 0:97a4f8cc534c 559 case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
jhnwkmn 0:97a4f8cc534c 560 case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
jhnwkmn 0:97a4f8cc534c 561 default: return;
jhnwkmn 0:97a4f8cc534c 562 }
jhnwkmn 0:97a4f8cc534c 563 }
jhnwkmn 0:97a4f8cc534c 564 SQOpcode ChooseArithOpByToken(SQInteger tok)
jhnwkmn 0:97a4f8cc534c 565 {
jhnwkmn 0:97a4f8cc534c 566 switch(tok) {
jhnwkmn 0:97a4f8cc534c 567 case TK_PLUSEQ: case '+': return _OP_ADD;
jhnwkmn 0:97a4f8cc534c 568 case TK_MINUSEQ: case '-': return _OP_SUB;
jhnwkmn 0:97a4f8cc534c 569 case TK_MULEQ: case '*': return _OP_MUL;
jhnwkmn 0:97a4f8cc534c 570 case TK_DIVEQ: case '/': return _OP_DIV;
jhnwkmn 0:97a4f8cc534c 571 case TK_MODEQ: case '%': return _OP_MOD;
jhnwkmn 0:97a4f8cc534c 572 default: assert(0);
jhnwkmn 0:97a4f8cc534c 573 }
jhnwkmn 0:97a4f8cc534c 574 return _OP_ADD;
jhnwkmn 0:97a4f8cc534c 575 }
jhnwkmn 0:97a4f8cc534c 576 SQInteger ChooseCompArithCharByToken(SQInteger tok)
jhnwkmn 0:97a4f8cc534c 577 {
jhnwkmn 0:97a4f8cc534c 578 SQInteger oper;
jhnwkmn 0:97a4f8cc534c 579 switch(tok){
jhnwkmn 0:97a4f8cc534c 580 case TK_MINUSEQ: oper = '-'; break;
jhnwkmn 0:97a4f8cc534c 581 case TK_PLUSEQ: oper = '+'; break;
jhnwkmn 0:97a4f8cc534c 582 case TK_MULEQ: oper = '*'; break;
jhnwkmn 0:97a4f8cc534c 583 case TK_DIVEQ: oper = '/'; break;
jhnwkmn 0:97a4f8cc534c 584 case TK_MODEQ: oper = '%'; break;
jhnwkmn 0:97a4f8cc534c 585 default: oper = 0; //shut up compiler
jhnwkmn 0:97a4f8cc534c 586 assert(0); break;
jhnwkmn 0:97a4f8cc534c 587 };
jhnwkmn 0:97a4f8cc534c 588 return oper;
jhnwkmn 0:97a4f8cc534c 589 }
jhnwkmn 0:97a4f8cc534c 590 void PlusExp()
jhnwkmn 0:97a4f8cc534c 591 {
jhnwkmn 0:97a4f8cc534c 592 MultExp();
jhnwkmn 0:97a4f8cc534c 593 for(;;) switch(_token) {
jhnwkmn 0:97a4f8cc534c 594 case _SC('+'): case _SC('-'):
jhnwkmn 0:97a4f8cc534c 595 BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;
jhnwkmn 0:97a4f8cc534c 596 default: return;
jhnwkmn 0:97a4f8cc534c 597 }
jhnwkmn 0:97a4f8cc534c 598 }
jhnwkmn 0:97a4f8cc534c 599
jhnwkmn 0:97a4f8cc534c 600 void MultExp()
jhnwkmn 0:97a4f8cc534c 601 {
jhnwkmn 0:97a4f8cc534c 602 PrefixedExpr();
jhnwkmn 0:97a4f8cc534c 603 for(;;) switch(_token) {
jhnwkmn 0:97a4f8cc534c 604 case _SC('*'): case _SC('/'): case _SC('%'):
jhnwkmn 0:97a4f8cc534c 605 BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;
jhnwkmn 0:97a4f8cc534c 606 default: return;
jhnwkmn 0:97a4f8cc534c 607 }
jhnwkmn 0:97a4f8cc534c 608 }
jhnwkmn 0:97a4f8cc534c 609 //if 'pos' != -1 the previous variable is a local variable
jhnwkmn 0:97a4f8cc534c 610 void PrefixedExpr()
jhnwkmn 0:97a4f8cc534c 611 {
jhnwkmn 0:97a4f8cc534c 612 SQInteger pos = Factor();
jhnwkmn 0:97a4f8cc534c 613 for(;;) {
jhnwkmn 0:97a4f8cc534c 614 switch(_token) {
jhnwkmn 0:97a4f8cc534c 615 case _SC('.'):
jhnwkmn 0:97a4f8cc534c 616 pos = -1;
jhnwkmn 0:97a4f8cc534c 617 Lex();
jhnwkmn 0:97a4f8cc534c 618
jhnwkmn 0:97a4f8cc534c 619 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
jhnwkmn 0:97a4f8cc534c 620 if(_es.etype==BASE) {
jhnwkmn 0:97a4f8cc534c 621 Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 622 pos = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 623 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 624 _es.epos = pos;
jhnwkmn 0:97a4f8cc534c 625 }
jhnwkmn 0:97a4f8cc534c 626 else {
jhnwkmn 0:97a4f8cc534c 627 if(NeedGet()) {
jhnwkmn 0:97a4f8cc534c 628 Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 629 }
jhnwkmn 0:97a4f8cc534c 630 _es.etype = OBJECT;
jhnwkmn 0:97a4f8cc534c 631 }
jhnwkmn 0:97a4f8cc534c 632 break;
jhnwkmn 0:97a4f8cc534c 633 case _SC('['):
jhnwkmn 0:97a4f8cc534c 634 if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
jhnwkmn 0:97a4f8cc534c 635 Lex(); Expression(); Expect(_SC(']'));
jhnwkmn 0:97a4f8cc534c 636 pos = -1;
jhnwkmn 0:97a4f8cc534c 637 if(_es.etype==BASE) {
jhnwkmn 0:97a4f8cc534c 638 Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 639 pos = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 640 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 641 _es.epos = pos;
jhnwkmn 0:97a4f8cc534c 642 }
jhnwkmn 0:97a4f8cc534c 643 else {
jhnwkmn 0:97a4f8cc534c 644 if(NeedGet()) {
jhnwkmn 0:97a4f8cc534c 645 Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 646 }
jhnwkmn 0:97a4f8cc534c 647 _es.etype = OBJECT;
jhnwkmn 0:97a4f8cc534c 648 }
jhnwkmn 0:97a4f8cc534c 649 break;
jhnwkmn 0:97a4f8cc534c 650 case TK_MINUSMINUS:
jhnwkmn 0:97a4f8cc534c 651 case TK_PLUSPLUS:
jhnwkmn 0:97a4f8cc534c 652 {
jhnwkmn 0:97a4f8cc534c 653 if(IsEndOfStatement()) return;
jhnwkmn 0:97a4f8cc534c 654 SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;
jhnwkmn 0:97a4f8cc534c 655 Lex();
jhnwkmn 0:97a4f8cc534c 656 switch(_es.etype)
jhnwkmn 0:97a4f8cc534c 657 {
jhnwkmn 0:97a4f8cc534c 658 case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
jhnwkmn 0:97a4f8cc534c 659 case OBJECT:
jhnwkmn 0:97a4f8cc534c 660 case BASE:
jhnwkmn 0:97a4f8cc534c 661 Emit2ArgsOP(_OP_PINC, diff);
jhnwkmn 0:97a4f8cc534c 662 break;
jhnwkmn 0:97a4f8cc534c 663 case LOCAL: {
jhnwkmn 0:97a4f8cc534c 664 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 665 _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);
jhnwkmn 0:97a4f8cc534c 666 }
jhnwkmn 0:97a4f8cc534c 667 break;
jhnwkmn 0:97a4f8cc534c 668 case OUTER: {
jhnwkmn 0:97a4f8cc534c 669 SQInteger tmp1 = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 670 SQInteger tmp2 = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 671 _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);
jhnwkmn 0:97a4f8cc534c 672 _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff);
jhnwkmn 0:97a4f8cc534c 673 _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);
jhnwkmn 0:97a4f8cc534c 674 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 675 }
jhnwkmn 0:97a4f8cc534c 676 }
jhnwkmn 0:97a4f8cc534c 677 }
jhnwkmn 0:97a4f8cc534c 678 return;
jhnwkmn 0:97a4f8cc534c 679 break;
jhnwkmn 0:97a4f8cc534c 680 case _SC('('):
jhnwkmn 0:97a4f8cc534c 681 switch(_es.etype) {
jhnwkmn 0:97a4f8cc534c 682 case OBJECT: {
jhnwkmn 0:97a4f8cc534c 683 SQInteger key = _fs->PopTarget(); /* location of the key */
jhnwkmn 0:97a4f8cc534c 684 SQInteger table = _fs->PopTarget(); /* location of the object */
jhnwkmn 0:97a4f8cc534c 685 SQInteger closure = _fs->PushTarget(); /* location for the closure */
jhnwkmn 0:97a4f8cc534c 686 SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */
jhnwkmn 0:97a4f8cc534c 687 _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
jhnwkmn 0:97a4f8cc534c 688 }
jhnwkmn 0:97a4f8cc534c 689 break;
jhnwkmn 0:97a4f8cc534c 690 case BASE:
jhnwkmn 0:97a4f8cc534c 691 //Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 692 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
jhnwkmn 0:97a4f8cc534c 693 break;
jhnwkmn 0:97a4f8cc534c 694 case OUTER:
jhnwkmn 0:97a4f8cc534c 695 _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);
jhnwkmn 0:97a4f8cc534c 696 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
jhnwkmn 0:97a4f8cc534c 697 break;
jhnwkmn 0:97a4f8cc534c 698 default:
jhnwkmn 0:97a4f8cc534c 699 _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
jhnwkmn 0:97a4f8cc534c 700 }
jhnwkmn 0:97a4f8cc534c 701 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 702 Lex();
jhnwkmn 0:97a4f8cc534c 703 FunctionCallArgs();
jhnwkmn 0:97a4f8cc534c 704 break;
jhnwkmn 0:97a4f8cc534c 705 default: return;
jhnwkmn 0:97a4f8cc534c 706 }
jhnwkmn 0:97a4f8cc534c 707 }
jhnwkmn 0:97a4f8cc534c 708 }
jhnwkmn 0:97a4f8cc534c 709 SQInteger Factor()
jhnwkmn 0:97a4f8cc534c 710 {
jhnwkmn 0:97a4f8cc534c 711 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 712 switch(_token)
jhnwkmn 0:97a4f8cc534c 713 {
jhnwkmn 0:97a4f8cc534c 714 case TK_STRING_LITERAL:
jhnwkmn 0:97a4f8cc534c 715 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
jhnwkmn 0:97a4f8cc534c 716 Lex();
jhnwkmn 0:97a4f8cc534c 717 break;
jhnwkmn 0:97a4f8cc534c 718 case TK_BASE:
jhnwkmn 0:97a4f8cc534c 719 Lex();
jhnwkmn 0:97a4f8cc534c 720 _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());
jhnwkmn 0:97a4f8cc534c 721 _es.etype = BASE;
jhnwkmn 0:97a4f8cc534c 722 _es.epos = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 723 return (_es.epos);
jhnwkmn 0:97a4f8cc534c 724 break;
jhnwkmn 0:97a4f8cc534c 725 case TK_IDENTIFIER:
jhnwkmn 0:97a4f8cc534c 726 case TK_CONSTRUCTOR:
jhnwkmn 0:97a4f8cc534c 727 case TK_THIS:{
jhnwkmn 0:97a4f8cc534c 728 SQObject id;
jhnwkmn 0:97a4f8cc534c 729 SQObject constant;
jhnwkmn 0:97a4f8cc534c 730
jhnwkmn 0:97a4f8cc534c 731 switch(_token) {
jhnwkmn 0:97a4f8cc534c 732 case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
jhnwkmn 0:97a4f8cc534c 733 case TK_THIS: id = _fs->CreateString(_SC("this")); break;
jhnwkmn 0:97a4f8cc534c 734 case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;
jhnwkmn 0:97a4f8cc534c 735 }
jhnwkmn 0:97a4f8cc534c 736
jhnwkmn 0:97a4f8cc534c 737 SQInteger pos = -1;
jhnwkmn 0:97a4f8cc534c 738 Lex();
jhnwkmn 0:97a4f8cc534c 739 if((pos = _fs->GetLocalVariable(id)) != -1) {
jhnwkmn 0:97a4f8cc534c 740 /* Handle a local variable (includes 'this') */
jhnwkmn 0:97a4f8cc534c 741 _fs->PushTarget(pos);
jhnwkmn 0:97a4f8cc534c 742 _es.etype = LOCAL;
jhnwkmn 0:97a4f8cc534c 743 _es.epos = pos;
jhnwkmn 0:97a4f8cc534c 744 }
jhnwkmn 0:97a4f8cc534c 745
jhnwkmn 0:97a4f8cc534c 746 else if((pos = _fs->GetOuterVariable(id)) != -1) {
jhnwkmn 0:97a4f8cc534c 747 /* Handle a free var */
jhnwkmn 0:97a4f8cc534c 748 if(NeedGet()) {
jhnwkmn 0:97a4f8cc534c 749 _es.epos = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 750 _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);
jhnwkmn 0:97a4f8cc534c 751 /* _es.etype = EXPR; already default value */
jhnwkmn 0:97a4f8cc534c 752 }
jhnwkmn 0:97a4f8cc534c 753 else {
jhnwkmn 0:97a4f8cc534c 754 _es.etype = OUTER;
jhnwkmn 0:97a4f8cc534c 755 _es.epos = pos;
jhnwkmn 0:97a4f8cc534c 756 }
jhnwkmn 0:97a4f8cc534c 757 }
jhnwkmn 0:97a4f8cc534c 758
jhnwkmn 0:97a4f8cc534c 759 else if(_fs->IsConstant(id, constant)) {
jhnwkmn 0:97a4f8cc534c 760 /* Handle named constant */
jhnwkmn 0:97a4f8cc534c 761 SQObjectPtr constval;
jhnwkmn 0:97a4f8cc534c 762 SQObject constid;
jhnwkmn 0:97a4f8cc534c 763 if(type(constant) == OT_TABLE) {
jhnwkmn 0:97a4f8cc534c 764 Expect('.');
jhnwkmn 0:97a4f8cc534c 765 constid = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 766 if(!_table(constant)->Get(constid, constval)) {
jhnwkmn 0:97a4f8cc534c 767 constval.Null();
jhnwkmn 0:97a4f8cc534c 768 Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));
jhnwkmn 0:97a4f8cc534c 769 }
jhnwkmn 0:97a4f8cc534c 770 }
jhnwkmn 0:97a4f8cc534c 771 else {
jhnwkmn 0:97a4f8cc534c 772 constval = constant;
jhnwkmn 0:97a4f8cc534c 773 }
jhnwkmn 0:97a4f8cc534c 774 _es.epos = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 775
jhnwkmn 0:97a4f8cc534c 776 /* generate direct or literal function depending on size */
jhnwkmn 0:97a4f8cc534c 777 SQObjectType ctype = type(constval);
jhnwkmn 0:97a4f8cc534c 778 switch(ctype) {
jhnwkmn 0:97a4f8cc534c 779 case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;
jhnwkmn 0:97a4f8cc534c 780 case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;
jhnwkmn 0:97a4f8cc534c 781 default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;
jhnwkmn 0:97a4f8cc534c 782 }
jhnwkmn 0:97a4f8cc534c 783 _es.etype = EXPR;
jhnwkmn 0:97a4f8cc534c 784 }
jhnwkmn 0:97a4f8cc534c 785 else {
jhnwkmn 0:97a4f8cc534c 786 /* Handle a non-local variable, aka a field. Push the 'this' pointer on
jhnwkmn 0:97a4f8cc534c 787 * the virtual stack (always found in offset 0, so no instruction needs to
jhnwkmn 0:97a4f8cc534c 788 * be generated), and push the key next. Generate an _OP_LOAD instruction
jhnwkmn 0:97a4f8cc534c 789 * for the latter. If we are not using the variable as a dref expr, generate
jhnwkmn 0:97a4f8cc534c 790 * the _OP_GET instruction.
jhnwkmn 0:97a4f8cc534c 791 */
jhnwkmn 0:97a4f8cc534c 792 _fs->PushTarget(0);
jhnwkmn 0:97a4f8cc534c 793 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
jhnwkmn 0:97a4f8cc534c 794 if(NeedGet()) {
jhnwkmn 0:97a4f8cc534c 795 Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 796 }
jhnwkmn 0:97a4f8cc534c 797 _es.etype = OBJECT;
jhnwkmn 0:97a4f8cc534c 798 }
jhnwkmn 0:97a4f8cc534c 799 return _es.epos;
jhnwkmn 0:97a4f8cc534c 800 }
jhnwkmn 0:97a4f8cc534c 801 break;
jhnwkmn 0:97a4f8cc534c 802 case TK_DOUBLE_COLON: // "::"
jhnwkmn 0:97a4f8cc534c 803 _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());
jhnwkmn 0:97a4f8cc534c 804 _es.etype = OBJECT;
jhnwkmn 0:97a4f8cc534c 805 _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/
jhnwkmn 0:97a4f8cc534c 806 _es.epos = -1;
jhnwkmn 0:97a4f8cc534c 807 return _es.epos;
jhnwkmn 0:97a4f8cc534c 808 break;
jhnwkmn 0:97a4f8cc534c 809 case TK_NULL:
jhnwkmn 0:97a4f8cc534c 810 _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
jhnwkmn 0:97a4f8cc534c 811 Lex();
jhnwkmn 0:97a4f8cc534c 812 break;
jhnwkmn 0:97a4f8cc534c 813 case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break;
jhnwkmn 0:97a4f8cc534c 814 case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break;
jhnwkmn 0:97a4f8cc534c 815 case TK_TRUE: case TK_FALSE:
jhnwkmn 0:97a4f8cc534c 816 _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
jhnwkmn 0:97a4f8cc534c 817 Lex();
jhnwkmn 0:97a4f8cc534c 818 break;
jhnwkmn 0:97a4f8cc534c 819 case _SC('['): {
jhnwkmn 0:97a4f8cc534c 820 _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);
jhnwkmn 0:97a4f8cc534c 821 SQInteger apos = _fs->GetCurrentPos(),key = 0;
jhnwkmn 0:97a4f8cc534c 822 Lex();
jhnwkmn 0:97a4f8cc534c 823 while(_token != _SC(']')) {
jhnwkmn 0:97a4f8cc534c 824 Expression();
jhnwkmn 0:97a4f8cc534c 825 if(_token == _SC(',')) Lex();
jhnwkmn 0:97a4f8cc534c 826 SQInteger val = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 827 SQInteger array = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 828 _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);
jhnwkmn 0:97a4f8cc534c 829 key++;
jhnwkmn 0:97a4f8cc534c 830 }
jhnwkmn 0:97a4f8cc534c 831 _fs->SetIntructionParam(apos, 1, key);
jhnwkmn 0:97a4f8cc534c 832 Lex();
jhnwkmn 0:97a4f8cc534c 833 }
jhnwkmn 0:97a4f8cc534c 834 break;
jhnwkmn 0:97a4f8cc534c 835 case _SC('{'):
jhnwkmn 0:97a4f8cc534c 836 _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
jhnwkmn 0:97a4f8cc534c 837 Lex();ParseTableOrClass(_SC(','),_SC('}'));
jhnwkmn 0:97a4f8cc534c 838 break;
jhnwkmn 0:97a4f8cc534c 839 case TK_FUNCTION: FunctionExp(_token);break;
jhnwkmn 0:97a4f8cc534c 840 case _SC('@'): FunctionExp(_token,true);break;
jhnwkmn 0:97a4f8cc534c 841 case TK_CLASS: Lex(); ClassExp();break;
jhnwkmn 0:97a4f8cc534c 842 case _SC('-'):
jhnwkmn 0:97a4f8cc534c 843 Lex();
jhnwkmn 0:97a4f8cc534c 844 switch(_token) {
jhnwkmn 0:97a4f8cc534c 845 case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;
jhnwkmn 0:97a4f8cc534c 846 case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;
jhnwkmn 0:97a4f8cc534c 847 default: UnaryOP(_OP_NEG);
jhnwkmn 0:97a4f8cc534c 848 }
jhnwkmn 0:97a4f8cc534c 849 break;
jhnwkmn 0:97a4f8cc534c 850 case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;
jhnwkmn 0:97a4f8cc534c 851 case _SC('~'):
jhnwkmn 0:97a4f8cc534c 852 Lex();
jhnwkmn 0:97a4f8cc534c 853 if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }
jhnwkmn 0:97a4f8cc534c 854 UnaryOP(_OP_BWNOT);
jhnwkmn 0:97a4f8cc534c 855 break;
jhnwkmn 0:97a4f8cc534c 856 case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;
jhnwkmn 0:97a4f8cc534c 857 case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;
jhnwkmn 0:97a4f8cc534c 858 case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;
jhnwkmn 0:97a4f8cc534c 859 case TK_MINUSMINUS :
jhnwkmn 0:97a4f8cc534c 860 case TK_PLUSPLUS :PrefixIncDec(_token); break;
jhnwkmn 0:97a4f8cc534c 861 case TK_DELETE : DeleteExpr(); break;
jhnwkmn 0:97a4f8cc534c 862 case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 863 break;
jhnwkmn 0:97a4f8cc534c 864 default: Error(_SC("expression expected"));
jhnwkmn 0:97a4f8cc534c 865 }
jhnwkmn 0:97a4f8cc534c 866 return -1;
jhnwkmn 0:97a4f8cc534c 867 }
jhnwkmn 0:97a4f8cc534c 868 void EmitLoadConstInt(SQInteger value,SQInteger target)
jhnwkmn 0:97a4f8cc534c 869 {
jhnwkmn 0:97a4f8cc534c 870 if(target < 0) {
jhnwkmn 0:97a4f8cc534c 871 target = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 872 }
jhnwkmn 0:97a4f8cc534c 873 if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits?
jhnwkmn 0:97a4f8cc534c 874 _fs->AddInstruction(_OP_LOADINT, target,value);
jhnwkmn 0:97a4f8cc534c 875 }
jhnwkmn 0:97a4f8cc534c 876 else {
jhnwkmn 0:97a4f8cc534c 877 _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
jhnwkmn 0:97a4f8cc534c 878 }
jhnwkmn 0:97a4f8cc534c 879 }
jhnwkmn 0:97a4f8cc534c 880 void EmitLoadConstFloat(SQFloat value,SQInteger target)
jhnwkmn 0:97a4f8cc534c 881 {
jhnwkmn 0:97a4f8cc534c 882 if(target < 0) {
jhnwkmn 0:97a4f8cc534c 883 target = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 884 }
jhnwkmn 0:97a4f8cc534c 885 if(sizeof(SQFloat) == sizeof(SQInt32)) {
jhnwkmn 0:97a4f8cc534c 886 _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));
jhnwkmn 0:97a4f8cc534c 887 }
jhnwkmn 0:97a4f8cc534c 888 else {
jhnwkmn 0:97a4f8cc534c 889 _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
jhnwkmn 0:97a4f8cc534c 890 }
jhnwkmn 0:97a4f8cc534c 891 }
jhnwkmn 0:97a4f8cc534c 892 void UnaryOP(SQOpcode op)
jhnwkmn 0:97a4f8cc534c 893 {
jhnwkmn 0:97a4f8cc534c 894 PrefixedExpr();
jhnwkmn 0:97a4f8cc534c 895 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 896 _fs->AddInstruction(op, _fs->PushTarget(), src);
jhnwkmn 0:97a4f8cc534c 897 }
jhnwkmn 0:97a4f8cc534c 898 bool NeedGet()
jhnwkmn 0:97a4f8cc534c 899 {
jhnwkmn 0:97a4f8cc534c 900 switch(_token) {
jhnwkmn 0:97a4f8cc534c 901 case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:
jhnwkmn 0:97a4f8cc534c 902 case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS:
jhnwkmn 0:97a4f8cc534c 903 return false;
jhnwkmn 0:97a4f8cc534c 904 }
jhnwkmn 0:97a4f8cc534c 905 return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));
jhnwkmn 0:97a4f8cc534c 906 }
jhnwkmn 0:97a4f8cc534c 907 void FunctionCallArgs()
jhnwkmn 0:97a4f8cc534c 908 {
jhnwkmn 0:97a4f8cc534c 909 SQInteger nargs = 1;//this
jhnwkmn 0:97a4f8cc534c 910 while(_token != _SC(')')) {
jhnwkmn 0:97a4f8cc534c 911 Expression();
jhnwkmn 0:97a4f8cc534c 912 MoveIfCurrentTargetIsLocal();
jhnwkmn 0:97a4f8cc534c 913 nargs++;
jhnwkmn 0:97a4f8cc534c 914 if(_token == _SC(',')){
jhnwkmn 0:97a4f8cc534c 915 Lex();
jhnwkmn 0:97a4f8cc534c 916 if(_token == ')') Error(_SC("expression expected, found ')'"));
jhnwkmn 0:97a4f8cc534c 917 }
jhnwkmn 0:97a4f8cc534c 918 }
jhnwkmn 0:97a4f8cc534c 919 Lex();
jhnwkmn 0:97a4f8cc534c 920 for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 921 SQInteger stackbase = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 922 SQInteger closure = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 923 _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
jhnwkmn 0:97a4f8cc534c 924 }
jhnwkmn 0:97a4f8cc534c 925 void ParseTableOrClass(SQInteger separator,SQInteger terminator)
jhnwkmn 0:97a4f8cc534c 926 {
jhnwkmn 0:97a4f8cc534c 927 SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
jhnwkmn 0:97a4f8cc534c 928 while(_token != terminator) {
jhnwkmn 0:97a4f8cc534c 929 bool hasattrs = false;
jhnwkmn 0:97a4f8cc534c 930 bool isstatic = false;
jhnwkmn 0:97a4f8cc534c 931 //check if is an attribute
jhnwkmn 0:97a4f8cc534c 932 if(separator == ';') {
jhnwkmn 0:97a4f8cc534c 933 if(_token == TK_ATTR_OPEN) {
jhnwkmn 0:97a4f8cc534c 934 _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();
jhnwkmn 0:97a4f8cc534c 935 ParseTableOrClass(',',TK_ATTR_CLOSE);
jhnwkmn 0:97a4f8cc534c 936 hasattrs = true;
jhnwkmn 0:97a4f8cc534c 937 }
jhnwkmn 0:97a4f8cc534c 938 if(_token == TK_STATIC) {
jhnwkmn 0:97a4f8cc534c 939 isstatic = true;
jhnwkmn 0:97a4f8cc534c 940 Lex();
jhnwkmn 0:97a4f8cc534c 941 }
jhnwkmn 0:97a4f8cc534c 942 }
jhnwkmn 0:97a4f8cc534c 943 switch(_token) {
jhnwkmn 0:97a4f8cc534c 944 case TK_FUNCTION:
jhnwkmn 0:97a4f8cc534c 945 case TK_CONSTRUCTOR:{
jhnwkmn 0:97a4f8cc534c 946 SQInteger tk = _token;
jhnwkmn 0:97a4f8cc534c 947 Lex();
jhnwkmn 0:97a4f8cc534c 948 SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
jhnwkmn 0:97a4f8cc534c 949 Expect(_SC('('));
jhnwkmn 0:97a4f8cc534c 950 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
jhnwkmn 0:97a4f8cc534c 951 CreateFunction(id);
jhnwkmn 0:97a4f8cc534c 952 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
jhnwkmn 0:97a4f8cc534c 953 }
jhnwkmn 0:97a4f8cc534c 954 break;
jhnwkmn 0:97a4f8cc534c 955 case _SC('['):
jhnwkmn 0:97a4f8cc534c 956 Lex(); CommaExpr(); Expect(_SC(']'));
jhnwkmn 0:97a4f8cc534c 957 Expect(_SC('=')); Expression();
jhnwkmn 0:97a4f8cc534c 958 break;
jhnwkmn 0:97a4f8cc534c 959 case TK_STRING_LITERAL: //JSON
jhnwkmn 0:97a4f8cc534c 960 if(separator == ',') { //only works for tables
jhnwkmn 0:97a4f8cc534c 961 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL)));
jhnwkmn 0:97a4f8cc534c 962 Expect(_SC(':')); Expression();
jhnwkmn 0:97a4f8cc534c 963 break;
jhnwkmn 0:97a4f8cc534c 964 }
jhnwkmn 0:97a4f8cc534c 965 default :
jhnwkmn 0:97a4f8cc534c 966 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
jhnwkmn 0:97a4f8cc534c 967 Expect(_SC('=')); Expression();
jhnwkmn 0:97a4f8cc534c 968 }
jhnwkmn 0:97a4f8cc534c 969 if(_token == separator) Lex();//optional comma/semicolon
jhnwkmn 0:97a4f8cc534c 970 nkeys++;
jhnwkmn 0:97a4f8cc534c 971 SQInteger val = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 972 SQInteger key = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 973 SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
jhnwkmn 0:97a4f8cc534c 974 assert((hasattrs && (attrs == key-1)) || !hasattrs);
jhnwkmn 0:97a4f8cc534c 975 unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
jhnwkmn 0:97a4f8cc534c 976 SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
jhnwkmn 0:97a4f8cc534c 977 if(separator == _SC(',')) { //hack recognizes a table from the separator
jhnwkmn 0:97a4f8cc534c 978 _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
jhnwkmn 0:97a4f8cc534c 979 }
jhnwkmn 0:97a4f8cc534c 980 else {
jhnwkmn 0:97a4f8cc534c 981 _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember
jhnwkmn 0:97a4f8cc534c 982 }
jhnwkmn 0:97a4f8cc534c 983 }
jhnwkmn 0:97a4f8cc534c 984 if(separator == _SC(',')) //hack recognizes a table from the separator
jhnwkmn 0:97a4f8cc534c 985 _fs->SetIntructionParam(tpos, 1, nkeys);
jhnwkmn 0:97a4f8cc534c 986 Lex();
jhnwkmn 0:97a4f8cc534c 987 }
jhnwkmn 0:97a4f8cc534c 988 void LocalDeclStatement()
jhnwkmn 0:97a4f8cc534c 989 {
jhnwkmn 0:97a4f8cc534c 990 SQObject varname;
jhnwkmn 0:97a4f8cc534c 991 Lex();
jhnwkmn 0:97a4f8cc534c 992 if( _token == TK_FUNCTION) {
jhnwkmn 0:97a4f8cc534c 993 Lex();
jhnwkmn 0:97a4f8cc534c 994 varname = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 995 Expect(_SC('('));
jhnwkmn 0:97a4f8cc534c 996 CreateFunction(varname,false);
jhnwkmn 0:97a4f8cc534c 997 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
jhnwkmn 0:97a4f8cc534c 998 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 999 _fs->PushLocalVariable(varname);
jhnwkmn 0:97a4f8cc534c 1000 return;
jhnwkmn 0:97a4f8cc534c 1001 }
jhnwkmn 0:97a4f8cc534c 1002
jhnwkmn 0:97a4f8cc534c 1003 do {
jhnwkmn 0:97a4f8cc534c 1004 varname = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1005 if(_token == _SC('=')) {
jhnwkmn 0:97a4f8cc534c 1006 Lex(); Expression();
jhnwkmn 0:97a4f8cc534c 1007 SQInteger src = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1008 SQInteger dest = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 1009 if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
jhnwkmn 0:97a4f8cc534c 1010 }
jhnwkmn 0:97a4f8cc534c 1011 else{
jhnwkmn 0:97a4f8cc534c 1012 _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
jhnwkmn 0:97a4f8cc534c 1013 }
jhnwkmn 0:97a4f8cc534c 1014 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1015 _fs->PushLocalVariable(varname);
jhnwkmn 0:97a4f8cc534c 1016 if(_token == _SC(',')) Lex(); else break;
jhnwkmn 0:97a4f8cc534c 1017 } while(1);
jhnwkmn 0:97a4f8cc534c 1018 }
jhnwkmn 0:97a4f8cc534c 1019 void IfStatement()
jhnwkmn 0:97a4f8cc534c 1020 {
jhnwkmn 0:97a4f8cc534c 1021 SQInteger jmppos;
jhnwkmn 0:97a4f8cc534c 1022 bool haselse = false;
jhnwkmn 0:97a4f8cc534c 1023 Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1024 _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
jhnwkmn 0:97a4f8cc534c 1025 SQInteger jnepos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1026 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1027
jhnwkmn 0:97a4f8cc534c 1028 Statement();
jhnwkmn 0:97a4f8cc534c 1029 //
jhnwkmn 0:97a4f8cc534c 1030 if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
jhnwkmn 0:97a4f8cc534c 1031
jhnwkmn 0:97a4f8cc534c 1032 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1033 SQInteger endifblock = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1034 if(_token == TK_ELSE){
jhnwkmn 0:97a4f8cc534c 1035 haselse = true;
jhnwkmn 0:97a4f8cc534c 1036 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1037 _fs->AddInstruction(_OP_JMP);
jhnwkmn 0:97a4f8cc534c 1038 jmppos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1039 Lex();
jhnwkmn 0:97a4f8cc534c 1040 Statement(); if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
jhnwkmn 0:97a4f8cc534c 1041 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1042 _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
jhnwkmn 0:97a4f8cc534c 1043 }
jhnwkmn 0:97a4f8cc534c 1044 _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
jhnwkmn 0:97a4f8cc534c 1045 }
jhnwkmn 0:97a4f8cc534c 1046 void WhileStatement()
jhnwkmn 0:97a4f8cc534c 1047 {
jhnwkmn 0:97a4f8cc534c 1048 SQInteger jzpos, jmppos;
jhnwkmn 0:97a4f8cc534c 1049 jmppos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1050 Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1051
jhnwkmn 0:97a4f8cc534c 1052 BEGIN_BREAKBLE_BLOCK();
jhnwkmn 0:97a4f8cc534c 1053 _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
jhnwkmn 0:97a4f8cc534c 1054 jzpos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1055 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1056
jhnwkmn 0:97a4f8cc534c 1057 Statement();
jhnwkmn 0:97a4f8cc534c 1058
jhnwkmn 0:97a4f8cc534c 1059 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1060 _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
jhnwkmn 0:97a4f8cc534c 1061 _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
jhnwkmn 0:97a4f8cc534c 1062
jhnwkmn 0:97a4f8cc534c 1063 END_BREAKBLE_BLOCK(jmppos);
jhnwkmn 0:97a4f8cc534c 1064 }
jhnwkmn 0:97a4f8cc534c 1065 void DoWhileStatement()
jhnwkmn 0:97a4f8cc534c 1066 {
jhnwkmn 0:97a4f8cc534c 1067 Lex();
jhnwkmn 0:97a4f8cc534c 1068 SQInteger jmptrg = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1069 BEGIN_BREAKBLE_BLOCK()
jhnwkmn 0:97a4f8cc534c 1070 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1071 Statement();
jhnwkmn 0:97a4f8cc534c 1072 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1073 Expect(TK_WHILE);
jhnwkmn 0:97a4f8cc534c 1074 SQInteger continuetrg = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1075 Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1076 _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);
jhnwkmn 0:97a4f8cc534c 1077 _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);
jhnwkmn 0:97a4f8cc534c 1078 END_BREAKBLE_BLOCK(continuetrg);
jhnwkmn 0:97a4f8cc534c 1079 }
jhnwkmn 0:97a4f8cc534c 1080 void ForStatement()
jhnwkmn 0:97a4f8cc534c 1081 {
jhnwkmn 0:97a4f8cc534c 1082 Lex();
jhnwkmn 0:97a4f8cc534c 1083 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1084 Expect(_SC('('));
jhnwkmn 0:97a4f8cc534c 1085 if(_token == TK_LOCAL) LocalDeclStatement();
jhnwkmn 0:97a4f8cc534c 1086 else if(_token != _SC(';')){
jhnwkmn 0:97a4f8cc534c 1087 CommaExpr();
jhnwkmn 0:97a4f8cc534c 1088 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1089 }
jhnwkmn 0:97a4f8cc534c 1090 Expect(_SC(';'));
jhnwkmn 0:97a4f8cc534c 1091 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 1092 SQInteger jmppos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1093 SQInteger jzpos = -1;
jhnwkmn 0:97a4f8cc534c 1094 if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
jhnwkmn 0:97a4f8cc534c 1095 Expect(_SC(';'));
jhnwkmn 0:97a4f8cc534c 1096 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 1097 SQInteger expstart = _fs->GetCurrentPos() + 1;
jhnwkmn 0:97a4f8cc534c 1098 if(_token != _SC(')')) {
jhnwkmn 0:97a4f8cc534c 1099 CommaExpr();
jhnwkmn 0:97a4f8cc534c 1100 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1101 }
jhnwkmn 0:97a4f8cc534c 1102 Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1103 _fs->SnoozeOpt();
jhnwkmn 0:97a4f8cc534c 1104 SQInteger expend = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1105 SQInteger expsize = (expend - expstart) + 1;
jhnwkmn 0:97a4f8cc534c 1106 SQInstructionVec exp;
jhnwkmn 0:97a4f8cc534c 1107 if(expsize > 0) {
jhnwkmn 0:97a4f8cc534c 1108 for(SQInteger i = 0; i < expsize; i++)
jhnwkmn 0:97a4f8cc534c 1109 exp.push_back(_fs->GetInstruction(expstart + i));
jhnwkmn 0:97a4f8cc534c 1110 _fs->PopInstructions(expsize);
jhnwkmn 0:97a4f8cc534c 1111 }
jhnwkmn 0:97a4f8cc534c 1112 BEGIN_BREAKBLE_BLOCK()
jhnwkmn 0:97a4f8cc534c 1113 Statement();
jhnwkmn 0:97a4f8cc534c 1114 SQInteger continuetrg = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1115 if(expsize > 0) {
jhnwkmn 0:97a4f8cc534c 1116 for(SQInteger i = 0; i < expsize; i++)
jhnwkmn 0:97a4f8cc534c 1117 _fs->AddInstruction(exp[i]);
jhnwkmn 0:97a4f8cc534c 1118 }
jhnwkmn 0:97a4f8cc534c 1119 _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
jhnwkmn 0:97a4f8cc534c 1120 if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
jhnwkmn 0:97a4f8cc534c 1121 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1122
jhnwkmn 0:97a4f8cc534c 1123 END_BREAKBLE_BLOCK(continuetrg);
jhnwkmn 0:97a4f8cc534c 1124 }
jhnwkmn 0:97a4f8cc534c 1125 void ForEachStatement()
jhnwkmn 0:97a4f8cc534c 1126 {
jhnwkmn 0:97a4f8cc534c 1127 SQObject idxname, valname;
jhnwkmn 0:97a4f8cc534c 1128 Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1129 if(_token == _SC(',')) {
jhnwkmn 0:97a4f8cc534c 1130 idxname = valname;
jhnwkmn 0:97a4f8cc534c 1131 Lex(); valname = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1132 }
jhnwkmn 0:97a4f8cc534c 1133 else{
jhnwkmn 0:97a4f8cc534c 1134 idxname = _fs->CreateString(_SC("@INDEX@"));
jhnwkmn 0:97a4f8cc534c 1135 }
jhnwkmn 0:97a4f8cc534c 1136 Expect(TK_IN);
jhnwkmn 0:97a4f8cc534c 1137
jhnwkmn 0:97a4f8cc534c 1138 //save the stack size
jhnwkmn 0:97a4f8cc534c 1139 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1140 //put the table in the stack(evaluate the table expression)
jhnwkmn 0:97a4f8cc534c 1141 Expression(); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1142 SQInteger container = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 1143 //push the index local var
jhnwkmn 0:97a4f8cc534c 1144 SQInteger indexpos = _fs->PushLocalVariable(idxname);
jhnwkmn 0:97a4f8cc534c 1145 _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
jhnwkmn 0:97a4f8cc534c 1146 //push the value local var
jhnwkmn 0:97a4f8cc534c 1147 SQInteger valuepos = _fs->PushLocalVariable(valname);
jhnwkmn 0:97a4f8cc534c 1148 _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
jhnwkmn 0:97a4f8cc534c 1149 //push reference index
jhnwkmn 0:97a4f8cc534c 1150 SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
jhnwkmn 0:97a4f8cc534c 1151 _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
jhnwkmn 0:97a4f8cc534c 1152 SQInteger jmppos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1153 _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
jhnwkmn 0:97a4f8cc534c 1154 SQInteger foreachpos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1155 _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
jhnwkmn 0:97a4f8cc534c 1156 //generate the statement code
jhnwkmn 0:97a4f8cc534c 1157 BEGIN_BREAKBLE_BLOCK()
jhnwkmn 0:97a4f8cc534c 1158 Statement();
jhnwkmn 0:97a4f8cc534c 1159 _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
jhnwkmn 0:97a4f8cc534c 1160 _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
jhnwkmn 0:97a4f8cc534c 1161 _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
jhnwkmn 0:97a4f8cc534c 1162 END_BREAKBLE_BLOCK(foreachpos - 1);
jhnwkmn 0:97a4f8cc534c 1163 //restore the local variable stack(remove index,val and ref idx)
jhnwkmn 0:97a4f8cc534c 1164 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1165 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1166 }
jhnwkmn 0:97a4f8cc534c 1167 void SwitchStatement()
jhnwkmn 0:97a4f8cc534c 1168 {
jhnwkmn 0:97a4f8cc534c 1169 Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1170 Expect(_SC('{'));
jhnwkmn 0:97a4f8cc534c 1171 SQInteger expr = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 1172 bool bfirst = true;
jhnwkmn 0:97a4f8cc534c 1173 SQInteger tonextcondjmp = -1;
jhnwkmn 0:97a4f8cc534c 1174 SQInteger skipcondjmp = -1;
jhnwkmn 0:97a4f8cc534c 1175 SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
jhnwkmn 0:97a4f8cc534c 1176 _fs->_breaktargets.push_back(0);
jhnwkmn 0:97a4f8cc534c 1177 while(_token == TK_CASE) {
jhnwkmn 0:97a4f8cc534c 1178 if(!bfirst) {
jhnwkmn 0:97a4f8cc534c 1179 _fs->AddInstruction(_OP_JMP, 0, 0);
jhnwkmn 0:97a4f8cc534c 1180 skipcondjmp = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1181 _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
jhnwkmn 0:97a4f8cc534c 1182 }
jhnwkmn 0:97a4f8cc534c 1183 //condition
jhnwkmn 0:97a4f8cc534c 1184 Lex(); Expression(); Expect(_SC(':'));
jhnwkmn 0:97a4f8cc534c 1185 SQInteger trg = _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1186 SQInteger eqtarget = trg;
jhnwkmn 0:97a4f8cc534c 1187 bool local = _fs->IsLocal(trg);
jhnwkmn 0:97a4f8cc534c 1188 if(local) {
jhnwkmn 0:97a4f8cc534c 1189 eqtarget = _fs->PushTarget(); //we need to allocate a extra reg
jhnwkmn 0:97a4f8cc534c 1190 }
jhnwkmn 0:97a4f8cc534c 1191 _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);
jhnwkmn 0:97a4f8cc534c 1192 _fs->AddInstruction(_OP_JZ, eqtarget, 0);
jhnwkmn 0:97a4f8cc534c 1193 if(local) {
jhnwkmn 0:97a4f8cc534c 1194 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1195 }
jhnwkmn 0:97a4f8cc534c 1196
jhnwkmn 0:97a4f8cc534c 1197 //end condition
jhnwkmn 0:97a4f8cc534c 1198 if(skipcondjmp != -1) {
jhnwkmn 0:97a4f8cc534c 1199 _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
jhnwkmn 0:97a4f8cc534c 1200 }
jhnwkmn 0:97a4f8cc534c 1201 tonextcondjmp = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1202 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1203 Statements();
jhnwkmn 0:97a4f8cc534c 1204 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1205 bfirst = false;
jhnwkmn 0:97a4f8cc534c 1206 }
jhnwkmn 0:97a4f8cc534c 1207 if(tonextcondjmp != -1)
jhnwkmn 0:97a4f8cc534c 1208 _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
jhnwkmn 0:97a4f8cc534c 1209 if(_token == TK_DEFAULT) {
jhnwkmn 0:97a4f8cc534c 1210 Lex(); Expect(_SC(':'));
jhnwkmn 0:97a4f8cc534c 1211 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1212 Statements();
jhnwkmn 0:97a4f8cc534c 1213 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1214 }
jhnwkmn 0:97a4f8cc534c 1215 Expect(_SC('}'));
jhnwkmn 0:97a4f8cc534c 1216 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1217 __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
jhnwkmn 0:97a4f8cc534c 1218 if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
jhnwkmn 0:97a4f8cc534c 1219 _fs->_breaktargets.pop_back();
jhnwkmn 0:97a4f8cc534c 1220 }
jhnwkmn 0:97a4f8cc534c 1221 void FunctionStatement()
jhnwkmn 0:97a4f8cc534c 1222 {
jhnwkmn 0:97a4f8cc534c 1223 SQObject id;
jhnwkmn 0:97a4f8cc534c 1224 Lex(); id = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1225 _fs->PushTarget(0);
jhnwkmn 0:97a4f8cc534c 1226 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
jhnwkmn 0:97a4f8cc534c 1227 if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 1228
jhnwkmn 0:97a4f8cc534c 1229 while(_token == TK_DOUBLE_COLON) {
jhnwkmn 0:97a4f8cc534c 1230 Lex();
jhnwkmn 0:97a4f8cc534c 1231 id = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1232 _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
jhnwkmn 0:97a4f8cc534c 1233 if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
jhnwkmn 0:97a4f8cc534c 1234 }
jhnwkmn 0:97a4f8cc534c 1235 Expect(_SC('('));
jhnwkmn 0:97a4f8cc534c 1236 CreateFunction(id);
jhnwkmn 0:97a4f8cc534c 1237 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
jhnwkmn 0:97a4f8cc534c 1238 EmitDerefOp(_OP_NEWSLOT);
jhnwkmn 0:97a4f8cc534c 1239 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1240 }
jhnwkmn 0:97a4f8cc534c 1241 void ClassStatement()
jhnwkmn 0:97a4f8cc534c 1242 {
jhnwkmn 0:97a4f8cc534c 1243 SQExpState es;
jhnwkmn 0:97a4f8cc534c 1244 Lex();
jhnwkmn 0:97a4f8cc534c 1245 es = _es;
jhnwkmn 0:97a4f8cc534c 1246 _es.donot_get = true;
jhnwkmn 0:97a4f8cc534c 1247 PrefixedExpr();
jhnwkmn 0:97a4f8cc534c 1248 if(_es.etype == EXPR) {
jhnwkmn 0:97a4f8cc534c 1249 Error(_SC("invalid class name"));
jhnwkmn 0:97a4f8cc534c 1250 }
jhnwkmn 0:97a4f8cc534c 1251 else if(_es.etype == OBJECT || _es.etype == BASE) {
jhnwkmn 0:97a4f8cc534c 1252 ClassExp();
jhnwkmn 0:97a4f8cc534c 1253 EmitDerefOp(_OP_NEWSLOT);
jhnwkmn 0:97a4f8cc534c 1254 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1255 }
jhnwkmn 0:97a4f8cc534c 1256 else {
jhnwkmn 0:97a4f8cc534c 1257 Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
jhnwkmn 0:97a4f8cc534c 1258 }
jhnwkmn 0:97a4f8cc534c 1259 _es = es;
jhnwkmn 0:97a4f8cc534c 1260 }
jhnwkmn 0:97a4f8cc534c 1261 SQObject ExpectScalar()
jhnwkmn 0:97a4f8cc534c 1262 {
jhnwkmn 0:97a4f8cc534c 1263 SQObject val;
jhnwkmn 0:97a4f8cc534c 1264 val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x
jhnwkmn 0:97a4f8cc534c 1265 switch(_token) {
jhnwkmn 0:97a4f8cc534c 1266 case TK_INTEGER:
jhnwkmn 0:97a4f8cc534c 1267 val._type = OT_INTEGER;
jhnwkmn 0:97a4f8cc534c 1268 val._unVal.nInteger = _lex._nvalue;
jhnwkmn 0:97a4f8cc534c 1269 break;
jhnwkmn 0:97a4f8cc534c 1270 case TK_FLOAT:
jhnwkmn 0:97a4f8cc534c 1271 val._type = OT_FLOAT;
jhnwkmn 0:97a4f8cc534c 1272 val._unVal.fFloat = _lex._fvalue;
jhnwkmn 0:97a4f8cc534c 1273 break;
jhnwkmn 0:97a4f8cc534c 1274 case TK_STRING_LITERAL:
jhnwkmn 0:97a4f8cc534c 1275 val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
jhnwkmn 0:97a4f8cc534c 1276 break;
jhnwkmn 0:97a4f8cc534c 1277 case TK_TRUE:
jhnwkmn 0:97a4f8cc534c 1278 case TK_FALSE:
jhnwkmn 0:97a4f8cc534c 1279 val._type = OT_BOOL;
jhnwkmn 0:97a4f8cc534c 1280 val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;
jhnwkmn 0:97a4f8cc534c 1281 break;
jhnwkmn 0:97a4f8cc534c 1282 case '-':
jhnwkmn 0:97a4f8cc534c 1283 Lex();
jhnwkmn 0:97a4f8cc534c 1284 switch(_token)
jhnwkmn 0:97a4f8cc534c 1285 {
jhnwkmn 0:97a4f8cc534c 1286 case TK_INTEGER:
jhnwkmn 0:97a4f8cc534c 1287 val._type = OT_INTEGER;
jhnwkmn 0:97a4f8cc534c 1288 val._unVal.nInteger = -_lex._nvalue;
jhnwkmn 0:97a4f8cc534c 1289 break;
jhnwkmn 0:97a4f8cc534c 1290 case TK_FLOAT:
jhnwkmn 0:97a4f8cc534c 1291 val._type = OT_FLOAT;
jhnwkmn 0:97a4f8cc534c 1292 val._unVal.fFloat = -_lex._fvalue;
jhnwkmn 0:97a4f8cc534c 1293 break;
jhnwkmn 0:97a4f8cc534c 1294 default:
jhnwkmn 0:97a4f8cc534c 1295 Error(_SC("scalar expected : integer,float"));
jhnwkmn 0:97a4f8cc534c 1296 }
jhnwkmn 0:97a4f8cc534c 1297 break;
jhnwkmn 0:97a4f8cc534c 1298 default:
jhnwkmn 0:97a4f8cc534c 1299 Error(_SC("scalar expected : integer,float or string"));
jhnwkmn 0:97a4f8cc534c 1300 }
jhnwkmn 0:97a4f8cc534c 1301 Lex();
jhnwkmn 0:97a4f8cc534c 1302 return val;
jhnwkmn 0:97a4f8cc534c 1303 }
jhnwkmn 0:97a4f8cc534c 1304 void EnumStatement()
jhnwkmn 0:97a4f8cc534c 1305 {
jhnwkmn 0:97a4f8cc534c 1306 Lex();
jhnwkmn 0:97a4f8cc534c 1307 SQObject id = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1308 Expect(_SC('{'));
jhnwkmn 0:97a4f8cc534c 1309
jhnwkmn 0:97a4f8cc534c 1310 SQObject table = _fs->CreateTable();
jhnwkmn 0:97a4f8cc534c 1311 SQInteger nval = 0;
jhnwkmn 0:97a4f8cc534c 1312 while(_token != _SC('}')) {
jhnwkmn 0:97a4f8cc534c 1313 SQObject key = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1314 SQObject val;
jhnwkmn 0:97a4f8cc534c 1315 if(_token == _SC('=')) {
jhnwkmn 0:97a4f8cc534c 1316 Lex();
jhnwkmn 0:97a4f8cc534c 1317 val = ExpectScalar();
jhnwkmn 0:97a4f8cc534c 1318 }
jhnwkmn 0:97a4f8cc534c 1319 else {
jhnwkmn 0:97a4f8cc534c 1320 val._type = OT_INTEGER;
jhnwkmn 0:97a4f8cc534c 1321 val._unVal.nInteger = nval++;
jhnwkmn 0:97a4f8cc534c 1322 }
jhnwkmn 0:97a4f8cc534c 1323 _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
jhnwkmn 0:97a4f8cc534c 1324 if(_token == ',') Lex();
jhnwkmn 0:97a4f8cc534c 1325 }
jhnwkmn 0:97a4f8cc534c 1326 SQTable *enums = _table(_ss(_vm)->_consts);
jhnwkmn 0:97a4f8cc534c 1327 SQObjectPtr strongid = id;
jhnwkmn 0:97a4f8cc534c 1328 enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
jhnwkmn 0:97a4f8cc534c 1329 strongid.Null();
jhnwkmn 0:97a4f8cc534c 1330 Lex();
jhnwkmn 0:97a4f8cc534c 1331 }
jhnwkmn 0:97a4f8cc534c 1332 void TryCatchStatement()
jhnwkmn 0:97a4f8cc534c 1333 {
jhnwkmn 0:97a4f8cc534c 1334 SQObject exid;
jhnwkmn 0:97a4f8cc534c 1335 Lex();
jhnwkmn 0:97a4f8cc534c 1336 _fs->AddInstruction(_OP_PUSHTRAP,0,0);
jhnwkmn 0:97a4f8cc534c 1337 _fs->_traps++;
jhnwkmn 0:97a4f8cc534c 1338 if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
jhnwkmn 0:97a4f8cc534c 1339 if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
jhnwkmn 0:97a4f8cc534c 1340 SQInteger trappos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1341 {
jhnwkmn 0:97a4f8cc534c 1342 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1343 Statement();
jhnwkmn 0:97a4f8cc534c 1344 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1345 }
jhnwkmn 0:97a4f8cc534c 1346 _fs->_traps--;
jhnwkmn 0:97a4f8cc534c 1347 _fs->AddInstruction(_OP_POPTRAP, 1, 0);
jhnwkmn 0:97a4f8cc534c 1348 if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
jhnwkmn 0:97a4f8cc534c 1349 if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
jhnwkmn 0:97a4f8cc534c 1350 _fs->AddInstruction(_OP_JMP, 0, 0);
jhnwkmn 0:97a4f8cc534c 1351 SQInteger jmppos = _fs->GetCurrentPos();
jhnwkmn 0:97a4f8cc534c 1352 _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
jhnwkmn 0:97a4f8cc534c 1353 Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1354 {
jhnwkmn 0:97a4f8cc534c 1355 BEGIN_SCOPE();
jhnwkmn 0:97a4f8cc534c 1356 SQInteger ex_target = _fs->PushLocalVariable(exid);
jhnwkmn 0:97a4f8cc534c 1357 _fs->SetIntructionParam(trappos, 0, ex_target);
jhnwkmn 0:97a4f8cc534c 1358 Statement();
jhnwkmn 0:97a4f8cc534c 1359 _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
jhnwkmn 0:97a4f8cc534c 1360 END_SCOPE();
jhnwkmn 0:97a4f8cc534c 1361 }
jhnwkmn 0:97a4f8cc534c 1362 }
jhnwkmn 0:97a4f8cc534c 1363 void FunctionExp(SQInteger ftype,bool lambda = false)
jhnwkmn 0:97a4f8cc534c 1364 {
jhnwkmn 0:97a4f8cc534c 1365 Lex(); Expect(_SC('('));
jhnwkmn 0:97a4f8cc534c 1366 SQObjectPtr dummy;
jhnwkmn 0:97a4f8cc534c 1367 CreateFunction(dummy,lambda);
jhnwkmn 0:97a4f8cc534c 1368 _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
jhnwkmn 0:97a4f8cc534c 1369 }
jhnwkmn 0:97a4f8cc534c 1370 void ClassExp()
jhnwkmn 0:97a4f8cc534c 1371 {
jhnwkmn 0:97a4f8cc534c 1372 SQInteger base = -1;
jhnwkmn 0:97a4f8cc534c 1373 SQInteger attrs = -1;
jhnwkmn 0:97a4f8cc534c 1374 if(_token == TK_EXTENDS) {
jhnwkmn 0:97a4f8cc534c 1375 Lex(); Expression();
jhnwkmn 0:97a4f8cc534c 1376 base = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 1377 }
jhnwkmn 0:97a4f8cc534c 1378 if(_token == TK_ATTR_OPEN) {
jhnwkmn 0:97a4f8cc534c 1379 Lex();
jhnwkmn 0:97a4f8cc534c 1380 _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
jhnwkmn 0:97a4f8cc534c 1381 ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
jhnwkmn 0:97a4f8cc534c 1382 attrs = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 1383 }
jhnwkmn 0:97a4f8cc534c 1384 Expect(_SC('{'));
jhnwkmn 0:97a4f8cc534c 1385 if(attrs != -1) _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1386 if(base != -1) _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1387 _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
jhnwkmn 0:97a4f8cc534c 1388 ParseTableOrClass(_SC(';'),_SC('}'));
jhnwkmn 0:97a4f8cc534c 1389 }
jhnwkmn 0:97a4f8cc534c 1390 void DeleteExpr()
jhnwkmn 0:97a4f8cc534c 1391 {
jhnwkmn 0:97a4f8cc534c 1392 SQExpState es;
jhnwkmn 0:97a4f8cc534c 1393 Lex();
jhnwkmn 0:97a4f8cc534c 1394 es = _es;
jhnwkmn 0:97a4f8cc534c 1395 _es.donot_get = true;
jhnwkmn 0:97a4f8cc534c 1396 PrefixedExpr();
jhnwkmn 0:97a4f8cc534c 1397 if(_es.etype==EXPR) Error(_SC("can't delete an expression"));
jhnwkmn 0:97a4f8cc534c 1398 if(_es.etype==OBJECT || _es.etype==BASE) {
jhnwkmn 0:97a4f8cc534c 1399 Emit2ArgsOP(_OP_DELETE);
jhnwkmn 0:97a4f8cc534c 1400 }
jhnwkmn 0:97a4f8cc534c 1401 else {
jhnwkmn 0:97a4f8cc534c 1402 Error(_SC("cannot delete an (outer) local"));
jhnwkmn 0:97a4f8cc534c 1403 }
jhnwkmn 0:97a4f8cc534c 1404 _es = es;
jhnwkmn 0:97a4f8cc534c 1405 }
jhnwkmn 0:97a4f8cc534c 1406 void PrefixIncDec(SQInteger token)
jhnwkmn 0:97a4f8cc534c 1407 {
jhnwkmn 0:97a4f8cc534c 1408 SQExpState es;
jhnwkmn 0:97a4f8cc534c 1409 SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;
jhnwkmn 0:97a4f8cc534c 1410 Lex();
jhnwkmn 0:97a4f8cc534c 1411 es = _es;
jhnwkmn 0:97a4f8cc534c 1412 _es.donot_get = true;
jhnwkmn 0:97a4f8cc534c 1413 PrefixedExpr();
jhnwkmn 0:97a4f8cc534c 1414 if(_es.etype==EXPR) {
jhnwkmn 0:97a4f8cc534c 1415 Error(_SC("can't '++' or '--' an expression"));
jhnwkmn 0:97a4f8cc534c 1416 }
jhnwkmn 0:97a4f8cc534c 1417 else if(_es.etype==OBJECT || _es.etype==BASE) {
jhnwkmn 0:97a4f8cc534c 1418 Emit2ArgsOP(_OP_INC, diff);
jhnwkmn 0:97a4f8cc534c 1419 }
jhnwkmn 0:97a4f8cc534c 1420 else if(_es.etype==LOCAL) {
jhnwkmn 0:97a4f8cc534c 1421 SQInteger src = _fs->TopTarget();
jhnwkmn 0:97a4f8cc534c 1422 _fs->AddInstruction(_OP_INCL, src, src, 0, diff);
jhnwkmn 0:97a4f8cc534c 1423
jhnwkmn 0:97a4f8cc534c 1424 }
jhnwkmn 0:97a4f8cc534c 1425 else if(_es.etype==OUTER) {
jhnwkmn 0:97a4f8cc534c 1426 SQInteger tmp = _fs->PushTarget();
jhnwkmn 0:97a4f8cc534c 1427 _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);
jhnwkmn 0:97a4f8cc534c 1428 _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff);
jhnwkmn 0:97a4f8cc534c 1429 _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);
jhnwkmn 0:97a4f8cc534c 1430 }
jhnwkmn 0:97a4f8cc534c 1431 _es = es;
jhnwkmn 0:97a4f8cc534c 1432 }
jhnwkmn 0:97a4f8cc534c 1433 void CreateFunction(SQObject &name,bool lambda = false)
jhnwkmn 0:97a4f8cc534c 1434 {
jhnwkmn 0:97a4f8cc534c 1435 SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
jhnwkmn 0:97a4f8cc534c 1436 funcstate->_name = name;
jhnwkmn 0:97a4f8cc534c 1437 SQObject paramname;
jhnwkmn 0:97a4f8cc534c 1438 funcstate->AddParameter(_fs->CreateString(_SC("this")));
jhnwkmn 0:97a4f8cc534c 1439 funcstate->_sourcename = _sourcename;
jhnwkmn 0:97a4f8cc534c 1440 SQInteger defparams = 0;
jhnwkmn 0:97a4f8cc534c 1441 while(_token!=_SC(')')) {
jhnwkmn 0:97a4f8cc534c 1442 if(_token == TK_VARPARAMS) {
jhnwkmn 0:97a4f8cc534c 1443 if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
jhnwkmn 0:97a4f8cc534c 1444 funcstate->AddParameter(_fs->CreateString(_SC("vargv")));
jhnwkmn 0:97a4f8cc534c 1445 funcstate->_varparams = true;
jhnwkmn 0:97a4f8cc534c 1446 Lex();
jhnwkmn 0:97a4f8cc534c 1447 if(_token != _SC(')')) Error(_SC("expected ')'"));
jhnwkmn 0:97a4f8cc534c 1448 break;
jhnwkmn 0:97a4f8cc534c 1449 }
jhnwkmn 0:97a4f8cc534c 1450 else {
jhnwkmn 0:97a4f8cc534c 1451 paramname = Expect(TK_IDENTIFIER);
jhnwkmn 0:97a4f8cc534c 1452 funcstate->AddParameter(paramname);
jhnwkmn 0:97a4f8cc534c 1453 if(_token == _SC('=')) {
jhnwkmn 0:97a4f8cc534c 1454 Lex();
jhnwkmn 0:97a4f8cc534c 1455 Expression();
jhnwkmn 0:97a4f8cc534c 1456 funcstate->AddDefaultParam(_fs->TopTarget());
jhnwkmn 0:97a4f8cc534c 1457 defparams++;
jhnwkmn 0:97a4f8cc534c 1458 }
jhnwkmn 0:97a4f8cc534c 1459 else {
jhnwkmn 0:97a4f8cc534c 1460 if(defparams > 0) Error(_SC("expected '='"));
jhnwkmn 0:97a4f8cc534c 1461 }
jhnwkmn 0:97a4f8cc534c 1462 if(_token == _SC(',')) Lex();
jhnwkmn 0:97a4f8cc534c 1463 else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
jhnwkmn 0:97a4f8cc534c 1464 }
jhnwkmn 0:97a4f8cc534c 1465 }
jhnwkmn 0:97a4f8cc534c 1466 Expect(_SC(')'));
jhnwkmn 0:97a4f8cc534c 1467 for(SQInteger n = 0; n < defparams; n++) {
jhnwkmn 0:97a4f8cc534c 1468 _fs->PopTarget();
jhnwkmn 0:97a4f8cc534c 1469 }
jhnwkmn 0:97a4f8cc534c 1470
jhnwkmn 0:97a4f8cc534c 1471 SQFuncState *currchunk = _fs;
jhnwkmn 0:97a4f8cc534c 1472 _fs = funcstate;
jhnwkmn 0:97a4f8cc534c 1473 if(lambda) {
jhnwkmn 0:97a4f8cc534c 1474 Expression();
jhnwkmn 0:97a4f8cc534c 1475 _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}
jhnwkmn 0:97a4f8cc534c 1476 else {
jhnwkmn 0:97a4f8cc534c 1477 Statement(false);
jhnwkmn 0:97a4f8cc534c 1478 }
jhnwkmn 0:97a4f8cc534c 1479 funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
jhnwkmn 0:97a4f8cc534c 1480 funcstate->AddInstruction(_OP_RETURN, -1);
jhnwkmn 0:97a4f8cc534c 1481 funcstate->SetStackSize(0);
jhnwkmn 0:97a4f8cc534c 1482
jhnwkmn 0:97a4f8cc534c 1483 SQFunctionProto *func = funcstate->BuildProto();
jhnwkmn 0:97a4f8cc534c 1484 #ifdef _DEBUG_DUMP
jhnwkmn 0:97a4f8cc534c 1485 funcstate->Dump(func);
jhnwkmn 0:97a4f8cc534c 1486 #endif
jhnwkmn 0:97a4f8cc534c 1487 _fs = currchunk;
jhnwkmn 0:97a4f8cc534c 1488 _fs->_functions.push_back(func);
jhnwkmn 0:97a4f8cc534c 1489 _fs->PopChildState();
jhnwkmn 0:97a4f8cc534c 1490 }
jhnwkmn 0:97a4f8cc534c 1491 void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
jhnwkmn 0:97a4f8cc534c 1492 {
jhnwkmn 0:97a4f8cc534c 1493 while(ntoresolve > 0) {
jhnwkmn 0:97a4f8cc534c 1494 SQInteger pos = funcstate->_unresolvedbreaks.back();
jhnwkmn 0:97a4f8cc534c 1495 funcstate->_unresolvedbreaks.pop_back();
jhnwkmn 0:97a4f8cc534c 1496 //set the jmp instruction
jhnwkmn 0:97a4f8cc534c 1497 funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
jhnwkmn 0:97a4f8cc534c 1498 ntoresolve--;
jhnwkmn 0:97a4f8cc534c 1499 }
jhnwkmn 0:97a4f8cc534c 1500 }
jhnwkmn 0:97a4f8cc534c 1501 void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
jhnwkmn 0:97a4f8cc534c 1502 {
jhnwkmn 0:97a4f8cc534c 1503 while(ntoresolve > 0) {
jhnwkmn 0:97a4f8cc534c 1504 SQInteger pos = funcstate->_unresolvedcontinues.back();
jhnwkmn 0:97a4f8cc534c 1505 funcstate->_unresolvedcontinues.pop_back();
jhnwkmn 0:97a4f8cc534c 1506 //set the jmp instruction
jhnwkmn 0:97a4f8cc534c 1507 funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
jhnwkmn 0:97a4f8cc534c 1508 ntoresolve--;
jhnwkmn 0:97a4f8cc534c 1509 }
jhnwkmn 0:97a4f8cc534c 1510 }
jhnwkmn 0:97a4f8cc534c 1511 private:
jhnwkmn 0:97a4f8cc534c 1512 SQInteger _token;
jhnwkmn 0:97a4f8cc534c 1513 SQFuncState *_fs;
jhnwkmn 0:97a4f8cc534c 1514 SQObjectPtr _sourcename;
jhnwkmn 0:97a4f8cc534c 1515 SQLexer _lex;
jhnwkmn 0:97a4f8cc534c 1516 bool _lineinfo;
jhnwkmn 0:97a4f8cc534c 1517 bool _raiseerror;
jhnwkmn 0:97a4f8cc534c 1518 SQInteger _debugline;
jhnwkmn 0:97a4f8cc534c 1519 SQInteger _debugop;
jhnwkmn 0:97a4f8cc534c 1520 SQExpState _es;
jhnwkmn 0:97a4f8cc534c 1521 SQScope _scope;
jhnwkmn 0:97a4f8cc534c 1522 SQChar _compilererror[MAX_COMPILER_ERROR_LEN];
jhnwkmn 0:97a4f8cc534c 1523 jmp_buf _errorjmp;
jhnwkmn 0:97a4f8cc534c 1524 SQVM *_vm;
jhnwkmn 0:97a4f8cc534c 1525 };
jhnwkmn 0:97a4f8cc534c 1526
jhnwkmn 0:97a4f8cc534c 1527 bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
jhnwkmn 0:97a4f8cc534c 1528 {
jhnwkmn 0:97a4f8cc534c 1529 SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
jhnwkmn 0:97a4f8cc534c 1530 return p.Compile(out);
jhnwkmn 0:97a4f8cc534c 1531 }
jhnwkmn 0:97a4f8cc534c 1532
jhnwkmn 0:97a4f8cc534c 1533 #endif