The Squirrel interpreter. See http://www.squirrel-lang.org/
squirrel/sqcompiler.cpp@3:7268a3ceaffc, 2014-12-16 (annotated)
- 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?
User | Revision | Line number | New 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 |