| %{ |
| |
| char *rcs_luastx = "$Id: lua.stx,v 3.24 1995/10/26 14:21:56 roberto Exp roberto $"; |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "mem.h" |
| #include "opcode.h" |
| #include "hash.h" |
| #include "inout.h" |
| #include "tree.h" |
| #include "table.h" |
| #include "lua.h" |
| #include "func.h" |
| |
| /* to avoid warnings generated by yacc */ |
| int yyparse (void); |
| #define malloc luaI_malloc |
| #define realloc luaI_realloc |
| #define free luaI_free |
| |
| #ifndef LISTING |
| #define LISTING 0 |
| #endif |
| |
| #ifndef CODE_BLOCK |
| #define CODE_BLOCK 256 |
| #endif |
| static int maxcode; |
| static int maxmain; |
| static Long maxcurr; /* to allow maxcurr *= 2 without overflow */ |
| static Byte *funcCode = NULL; |
| static Byte **initcode; |
| static Byte *basepc; |
| static int maincode; |
| static int pc; |
| |
| |
| #define MAXVAR 32 |
| static Long varbuffer[MAXVAR]; /* variables in an assignment list; |
| it's long to store negative Word values */ |
| static int nvarbuffer=0; /* number of variables at a list */ |
| |
| #define MAXLOCALS 32 |
| static Word localvar[MAXLOCALS]; /* store local variable names */ |
| static int nlocalvar=0; /* number of local variables */ |
| |
| #define MAXFIELDS FIELDS_PER_FLUSH*2 |
| static Word fields[MAXFIELDS]; /* fieldnames to be flushed */ |
| static int nfields=0; |
| |
| |
| /* Internal functions */ |
| |
| static void yyerror (char *s) |
| { |
| static char msg[256]; |
| sprintf (msg,"%s near \"%s\" at line %d in file `%s'", |
| s, lua_lasttext (), lua_linenumber, lua_parsedfile); |
| lua_error (msg); |
| } |
| |
| static void code_byte (Byte c) |
| { |
| if (pc>maxcurr-2) /* 1 byte free to code HALT of main code */ |
| { |
| if (maxcurr >= MAX_INT) |
| lua_error("code size overflow"); |
| maxcurr *= 2; |
| if (maxcurr >= MAX_INT) |
| maxcurr = MAX_INT; |
| basepc = growvector(basepc, maxcurr, Byte); |
| } |
| basepc[pc++] = c; |
| } |
| |
| static void code_word (Word n) |
| { |
| CodeWord code; |
| code.w = n; |
| code_byte(code.m.c1); |
| code_byte(code.m.c2); |
| } |
| |
| static void code_float (float n) |
| { |
| CodeFloat code; |
| code.f = n; |
| code_byte(code.m.c1); |
| code_byte(code.m.c2); |
| code_byte(code.m.c3); |
| code_byte(code.m.c4); |
| } |
| |
| static void code_code (TFunc *tf) |
| { |
| CodeCode code; |
| code.tf = tf; |
| code_byte(code.m.c1); |
| code_byte(code.m.c2); |
| code_byte(code.m.c3); |
| code_byte(code.m.c4); |
| } |
| |
| static void code_word_at (Byte *p, Word n) |
| { |
| CodeWord code; |
| code.w = n; |
| *p++ = code.m.c1; |
| *p++ = code.m.c2; |
| } |
| |
| static void push_field (Word name) |
| { |
| if (nfields < MAXFIELDS) |
| fields[nfields++] = name; |
| else |
| lua_error ("too many fields in nested constructors"); |
| } |
| |
| static void flush_record (int n) |
| { |
| int i; |
| if (n == 0) return; |
| code_byte(STORERECORD); |
| code_byte(n); |
| for (i=0; i<n; i++) |
| code_word(fields[--nfields]); |
| } |
| |
| static void flush_list (int m, int n) |
| { |
| if (n == 0) return; |
| if (m == 0) |
| code_byte(STORELIST0); |
| else |
| if (m < 255) |
| { |
| code_byte(STORELIST); |
| code_byte(m); |
| } |
| else |
| lua_error ("list constructor too long"); |
| code_byte(n); |
| } |
| |
| static void add_localvar (Word name) |
| { |
| if (nlocalvar < MAXLOCALS) |
| localvar[nlocalvar++] = name; |
| else |
| lua_error ("too many local variables"); |
| } |
| |
| static void store_localvar (Word name, int n) |
| { |
| if (nlocalvar+n < MAXLOCALS) |
| localvar[nlocalvar+n] = name; |
| else |
| lua_error ("too many local variables"); |
| } |
| |
| static void add_varbuffer (Long var) |
| { |
| if (nvarbuffer < MAXVAR) |
| varbuffer[nvarbuffer++] = var; |
| else |
| lua_error ("variable buffer overflow"); |
| } |
| |
| static void code_number (float f) |
| { |
| Word i = (Word)f; |
| if (f == (float)i) /* f has an (short) integer value */ |
| { |
| if (i <= 2) code_byte(PUSH0 + i); |
| else if (i <= 255) |
| { |
| code_byte(PUSHBYTE); |
| code_byte(i); |
| } |
| else |
| { |
| code_byte(PUSHWORD); |
| code_word(i); |
| } |
| } |
| else |
| { |
| code_byte(PUSHFLOAT); |
| code_float(f); |
| } |
| } |
| |
| /* |
| ** Search a local name and if find return its index. If do not find return -1 |
| */ |
| static int lua_localname (Word n) |
| { |
| int i; |
| for (i=nlocalvar-1; i >= 0; i--) |
| if (n == localvar[i]) return i; /* local var */ |
| return -1; /* global var */ |
| } |
| |
| /* |
| ** Push a variable given a number. If number is positive, push global variable |
| ** indexed by (number -1). If negative, push local indexed by ABS(number)-1. |
| ** Otherwise, if zero, push indexed variable (record). |
| */ |
| static void lua_pushvar (Long number) |
| { |
| if (number > 0) /* global var */ |
| { |
| code_byte(PUSHGLOBAL); |
| code_word(number-1); |
| } |
| else if (number < 0) /* local var */ |
| { |
| number = (-number) - 1; |
| if (number < 10) code_byte(PUSHLOCAL0 + number); |
| else |
| { |
| code_byte(PUSHLOCAL); |
| code_byte(number); |
| } |
| } |
| else |
| { |
| code_byte(PUSHINDEXED); |
| } |
| } |
| |
| static void lua_codeadjust (int n) |
| { |
| if (n+nlocalvar == 0) |
| code_byte(ADJUST0); |
| else |
| { |
| code_byte(ADJUST); |
| code_byte(n+nlocalvar); |
| } |
| } |
| |
| static void change2main (void) |
| { |
| /* (re)store main values */ |
| pc=maincode; basepc=*initcode; maxcurr=maxmain; |
| nlocalvar=0; |
| } |
| |
| static void savemain (void) |
| { |
| /* save main values */ |
| maincode=pc; *initcode=basepc; maxmain=maxcurr; |
| } |
| |
| static void init_func (void) |
| { |
| if (funcCode == NULL) /* first function */ |
| { |
| funcCode = newvector(CODE_BLOCK, Byte); |
| maxcode = CODE_BLOCK; |
| } |
| savemain(); /* save main values */ |
| /* set func values */ |
| pc=0; basepc=funcCode; maxcurr=maxcode; |
| nlocalvar = 0; |
| luaI_codedebugline(lua_linenumber); |
| } |
| |
| static void codereturn (void) |
| { |
| if (nlocalvar == 0) |
| code_byte(RETCODE0); |
| else |
| { |
| code_byte(RETCODE); |
| code_byte(nlocalvar); |
| } |
| } |
| |
| void luaI_codedebugline (int line) |
| { |
| static int lastline = 0; |
| if (lua_debug && line != lastline) |
| { |
| code_byte(SETLINE); |
| code_word(line); |
| lastline = line; |
| } |
| } |
| |
| static int adjust_functioncall (Long exp, int i) |
| { |
| if (exp <= 0) |
| return -exp; /* exp is -list length */ |
| else |
| { |
| int temp = basepc[exp]; |
| basepc[exp] = i; |
| return temp+i; |
| } |
| } |
| |
| static void adjust_mult_assign (int vars, Long exps, int temps) |
| { |
| if (exps > 0) |
| { /* must correct function call */ |
| int diff = vars - basepc[exps]; |
| if (diff >= 0) |
| adjust_functioncall(exps, diff); |
| else |
| { |
| adjust_functioncall(exps, 0); |
| lua_codeadjust(temps); |
| } |
| } |
| else if (vars != -exps) |
| lua_codeadjust(temps); |
| } |
| |
| static void storesinglevar (Long v) |
| { |
| if (v > 0) /* global var */ |
| { |
| code_byte(STOREGLOBAL); |
| code_word(v-1); |
| } |
| else if (v < 0) /* local var */ |
| { |
| int number = (-v) - 1; |
| if (number < 10) code_byte(STORELOCAL0 + number); |
| else |
| { |
| code_byte(STORELOCAL); |
| code_byte(number); |
| } |
| } |
| else |
| code_byte(STOREINDEXED0); |
| } |
| |
| static void lua_codestore (int i) |
| { |
| if (varbuffer[i] != 0) /* global or local var */ |
| storesinglevar(varbuffer[i]); |
| else /* indexed var */ |
| { |
| int j; |
| int upper=0; /* number of indexed variables upper */ |
| int param; /* number of itens until indexed expression */ |
| for (j=i+1; j <nvarbuffer; j++) |
| if (varbuffer[j] == 0) upper++; |
| param = upper*2 + i; |
| if (param == 0) |
| code_byte(STOREINDEXED0); |
| else |
| { |
| code_byte(STOREINDEXED); |
| code_byte(param); |
| } |
| } |
| } |
| |
| static void codeIf (Long thenAdd, Long elseAdd) |
| { |
| Long elseinit = elseAdd+sizeof(Word)+1; |
| if (pc == elseinit) /* no else */ |
| { |
| pc -= sizeof(Word)+1; |
| elseinit = pc; |
| } |
| else |
| { |
| basepc[elseAdd] = JMP; |
| code_word_at(basepc+elseAdd+1, pc-elseinit); |
| } |
| basepc[thenAdd] = IFFJMP; |
| code_word_at(basepc+thenAdd+1,elseinit-(thenAdd+sizeof(Word)+1)); |
| } |
| |
| |
| /* |
| ** Parse LUA code. |
| */ |
| void lua_parse (TFunc *tf) |
| { |
| lua_debug = 0; |
| initcode = &(tf->code); |
| *initcode = newvector(CODE_BLOCK, Byte); |
| maincode = 0; |
| maxmain = CODE_BLOCK; |
| change2main(); |
| if (yyparse ()) lua_error("parse error"); |
| savemain(); |
| (*initcode)[maincode++] = RETCODE0; |
| tf->size = maincode; |
| #if LISTING |
| { static void PrintCode (Byte *c, Byte *end); |
| PrintCode(*initcode,*initcode+maincode); } |
| #endif |
| } |
| |
| |
| %} |
| |
| |
| %union |
| { |
| int vInt; |
| float vFloat; |
| char *pChar; |
| Word vWord; |
| Long vLong; |
| TFunc *pFunc; |
| TreeNode *pNode; |
| } |
| |
| %start functionlist |
| |
| %token WRONGTOKEN |
| %token NIL |
| %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL END |
| %token RETURN |
| %token LOCAL |
| %token FUNCTION |
| %token <vFloat> NUMBER |
| %token <vWord> STRING |
| %token <pNode> NAME |
| %token <vInt> DEBUG |
| |
| %type <vLong> PrepJump |
| %type <vLong> exprlist, exprlist1 /* if > 0, points to function return |
| counter (which has list length); if <= 0, -list lenght */ |
| %type <vLong> functioncall, expr /* if != 0, points to function return |
| counter */ |
| %type <vInt> varlist1, funcParams, funcvalue |
| %type <vInt> fieldlist, localdeclist, decinit |
| %type <vInt> ffieldlist, ffieldlist1, semicolonpart |
| %type <vInt> lfieldlist, lfieldlist1 |
| %type <vInt> parlist |
| %type <vLong> var, singlevar, funcname |
| %type <pFunc> body |
| |
| %left AND OR |
| %left EQ NE '>' '<' LE GE |
| %left CONC |
| %left '+' '-' |
| %left '*' '/' |
| %left UNARY NOT |
| %right '^' |
| |
| |
| %% /* beginning of rules section */ |
| |
| |
| functionlist : /* empty */ |
| | functionlist globalstat |
| | functionlist function |
| ; |
| |
| globalstat : stat sc |
| | setdebug |
| ; |
| |
| function : FUNCTION funcname body |
| { |
| code_byte(PUSHFUNCTION); |
| code_code($3); |
| storesinglevar($2); |
| } |
| ; |
| |
| funcname : var { $$ =$1; init_func(); } |
| | varexp ':' NAME |
| { |
| code_byte(PUSHSTRING); |
| code_word(luaI_findconstant($3)); |
| $$ = 0; /* indexed variable */ |
| init_func(); |
| add_localvar(luaI_findsymbolbyname("self")); |
| } |
| ; |
| |
| body : '(' parlist ')' block END |
| { |
| codereturn(); |
| $$ = new(TFunc); |
| $$->size = pc; |
| $$->code = newvector(pc, Byte); |
| $$->fileName = lua_parsedfile; |
| $$->lineDefined = $2; |
| memcpy($$->code, basepc, pc*sizeof(Byte)); |
| /* save func values */ |
| funcCode = basepc; maxcode=maxcurr; |
| #if LISTING |
| PrintCode(funcCode,funcCode+pc); |
| #endif |
| change2main(); /* change back to main code */ |
| } |
| ; |
| |
| statlist : /* empty */ |
| | statlist stat sc |
| ; |
| |
| sc : /* empty */ | ';' ; |
| |
| stat : IF expr1 THEN PrepJump block PrepJump elsepart END |
| { codeIf($4, $6); } |
| |
| | WHILE {$<vLong>$=pc;} expr1 DO PrepJump block PrepJump END |
| { |
| basepc[$5] = IFFJMP; |
| code_word_at(basepc+$5+1, pc - ($5 + sizeof(Word)+1)); |
| basepc[$7] = UPJMP; |
| code_word_at(basepc+$7+1, pc - ($<vLong>2)); |
| } |
| |
| | REPEAT {$<vLong>$=pc;} block UNTIL expr1 PrepJump |
| { |
| basepc[$6] = IFFUPJMP; |
| code_word_at(basepc+$6+1, pc - ($<vLong>2)); |
| } |
| |
| | varlist1 '=' exprlist1 |
| { |
| { |
| int i; |
| adjust_mult_assign(nvarbuffer, $3, $1 * 2 + nvarbuffer); |
| for (i=nvarbuffer-1; i>=0; i--) |
| lua_codestore (i); |
| if ($1 > 1 || ($1 == 1 && varbuffer[0] != 0)) |
| lua_codeadjust (0); |
| } |
| } |
| | functioncall |
| | LOCAL localdeclist decinit |
| { nlocalvar += $2; |
| adjust_mult_assign($2, $3, 0); |
| } |
| ; |
| |
| elsepart : /* empty */ |
| | ELSE block |
| | ELSEIF expr1 THEN PrepJump block PrepJump elsepart |
| { codeIf($4, $6); } |
| ; |
| |
| block : {$<vInt>$ = nlocalvar;} statlist ret |
| { |
| if (nlocalvar != $<vInt>1) |
| { |
| nlocalvar = $<vInt>1; |
| lua_codeadjust (0); |
| } |
| } |
| ; |
| |
| ret : /* empty */ |
| | RETURN exprlist sc |
| { |
| adjust_functioncall($2, MULT_RET); |
| codereturn(); |
| } |
| ; |
| |
| PrepJump : /* empty */ |
| { |
| $$ = pc; |
| code_byte(0); /* open space */ |
| code_word (0); |
| } |
| |
| expr1 : expr { adjust_functioncall($1, 1); } |
| ; |
| |
| expr : '(' expr ')' { $$ = $2; } |
| | expr1 EQ expr1 { code_byte(EQOP); $$ = 0; } |
| | expr1 '<' expr1 { code_byte(LTOP); $$ = 0; } |
| | expr1 '>' expr1 { code_byte(GTOP); $$ = 0; } |
| | expr1 NE expr1 { code_byte(EQOP); code_byte(NOTOP); $$ = 0; } |
| | expr1 LE expr1 { code_byte(LEOP); $$ = 0; } |
| | expr1 GE expr1 { code_byte(GEOP); $$ = 0; } |
| | expr1 '+' expr1 { code_byte(ADDOP); $$ = 0; } |
| | expr1 '-' expr1 { code_byte(SUBOP); $$ = 0; } |
| | expr1 '*' expr1 { code_byte(MULTOP); $$ = 0; } |
| | expr1 '/' expr1 { code_byte(DIVOP); $$ = 0; } |
| | expr1 '^' expr1 { code_byte(POWOP); $$ = 0; } |
| | expr1 CONC expr1 { code_byte(CONCOP); $$ = 0; } |
| | '-' expr1 %prec UNARY { code_byte(MINUSOP); $$ = 0;} |
| | table { $$ = 0; } |
| | varexp { $$ = 0;} |
| | NUMBER { code_number($1); $$ = 0; } |
| | STRING |
| { |
| code_byte(PUSHSTRING); |
| code_word($1); |
| $$ = 0; |
| } |
| | NIL {code_byte(PUSHNIL); $$ = 0; } |
| | functioncall { $$ = $1; } |
| | NOT expr1 { code_byte(NOTOP); $$ = 0;} |
| | expr1 AND PrepJump {code_byte(POP); } expr1 |
| { |
| basepc[$3] = ONFJMP; |
| code_word_at(basepc+$3+1, pc - ($3 + sizeof(Word)+1)); |
| $$ = 0; |
| } |
| | expr1 OR PrepJump {code_byte(POP); } expr1 |
| { |
| basepc[$3] = ONTJMP; |
| code_word_at(basepc+$3+1, pc - ($3 + sizeof(Word)+1)); |
| $$ = 0; |
| } |
| ; |
| |
| table : |
| { |
| code_byte(CREATEARRAY); |
| $<vLong>$ = pc; code_word(0); |
| } |
| '{' fieldlist '}' |
| { |
| code_word_at(basepc+$<vLong>1, $3); |
| } |
| ; |
| |
| functioncall : funcvalue funcParams |
| { |
| code_byte(CALLFUNC); |
| code_byte($1+$2); |
| $$ = pc; |
| code_byte(0); /* may be modified by other rules */ |
| } |
| ; |
| |
| funcvalue : varexp { $$ = 0; } |
| | varexp ':' NAME |
| { |
| code_byte(PUSHSELF); |
| code_word(luaI_findconstant($3)); |
| $$ = 1; |
| } |
| ; |
| |
| funcParams : '(' exprlist ')' |
| { $$ = adjust_functioncall($2, 1); } |
| | table { $$ = 1; } |
| ; |
| |
| exprlist : /* empty */ { $$ = 0; } |
| | exprlist1 { $$ = $1; } |
| ; |
| |
| exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } |
| | exprlist1 ',' { $<vLong>$ = adjust_functioncall($1, 1); } expr |
| { |
| if ($4 == 0) $$ = -($<vLong>3 + 1); /* -length */ |
| else |
| { |
| adjust_functioncall($4, $<vLong>3); |
| $$ = $4; |
| } |
| } |
| ; |
| |
| parlist : /* empty */ { lua_codeadjust(0); $$ = lua_linenumber; } |
| | parlist1 { lua_codeadjust(0); $$ = lua_linenumber; } |
| ; |
| |
| parlist1 : NAME |
| { |
| add_localvar(luaI_findsymbol($1)); |
| } |
| | parlist1 ',' NAME |
| { |
| add_localvar(luaI_findsymbol($3)); |
| } |
| ; |
| |
| fieldlist : lfieldlist |
| { flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); } |
| semicolonpart |
| { $$ = $1+$3; } |
| | ffieldlist1 lastcomma |
| { $$ = $1; flush_record($1%FIELDS_PER_FLUSH); } |
| ; |
| |
| semicolonpart : /* empty */ |
| { $$ = 0; } |
| | ';' ffieldlist |
| { $$ = $2; flush_record($2%FIELDS_PER_FLUSH); } |
| ; |
| |
| lastcomma : /* empty */ |
| | ',' |
| ; |
| |
| ffieldlist : /* empty */ { $$ = 0; } |
| | ffieldlist1 lastcomma { $$ = $1; } |
| ; |
| |
| ffieldlist1 : ffield {$$=1;} |
| | ffieldlist1 ',' ffield |
| { |
| $$=$1+1; |
| if ($$%FIELDS_PER_FLUSH == 0) flush_record(FIELDS_PER_FLUSH); |
| } |
| ; |
| |
| ffield : NAME '=' expr1 |
| { |
| push_field(luaI_findconstant($1)); |
| } |
| ; |
| |
| lfieldlist : /* empty */ { $$ = 0; } |
| | lfieldlist1 lastcomma { $$ = $1; } |
| ; |
| |
| lfieldlist1 : expr1 {$$=1;} |
| | lfieldlist1 ',' expr1 |
| { |
| $$=$1+1; |
| if ($$%FIELDS_PER_FLUSH == 0) |
| flush_list($$/FIELDS_PER_FLUSH - 1, FIELDS_PER_FLUSH); |
| } |
| ; |
| |
| varlist1 : var |
| { |
| nvarbuffer = 0; |
| add_varbuffer($1); |
| $$ = ($1 == 0) ? 1 : 0; |
| } |
| | varlist1 ',' var |
| { |
| add_varbuffer($3); |
| $$ = ($3 == 0) ? $1 + 1 : $1; |
| } |
| ; |
| |
| var : singlevar { $$ = $1; } |
| | varexp '[' expr1 ']' |
| { |
| $$ = 0; /* indexed variable */ |
| } |
| | varexp '.' NAME |
| { |
| code_byte(PUSHSTRING); |
| code_word(luaI_findconstant($3)); |
| $$ = 0; /* indexed variable */ |
| } |
| ; |
| |
| singlevar : NAME |
| { |
| Word s = luaI_findsymbol($1); |
| int local = lua_localname (s); |
| if (local == -1) /* global var */ |
| $$ = s + 1; /* return positive value */ |
| else |
| $$ = -(local+1); /* return negative value */ |
| } |
| ; |
| |
| varexp : var { lua_pushvar($1); } |
| ; |
| |
| localdeclist : NAME {store_localvar(luaI_findsymbol($1), 0); $$ = 1;} |
| | localdeclist ',' NAME |
| { |
| store_localvar(luaI_findsymbol($3), $1); |
| $$ = $1+1; |
| } |
| ; |
| |
| decinit : /* empty */ { $$ = 0; } |
| | '=' exprlist1 { $$ = $2; } |
| ; |
| |
| setdebug : DEBUG { lua_debug = $1; } |
| ; |
| |
| %% |
| |
| #if LISTING |
| |
| static void PrintCode (Byte *code, Byte *end) |
| { |
| Byte *p = code; |
| printf ("\n\nCODE\n"); |
| while (p != end) |
| { |
| switch ((OpCode)*p) |
| { |
| case PUSHNIL: printf ("%d PUSHNIL\n", (p++)-code); break; |
| case PUSH0: case PUSH1: case PUSH2: |
| printf ("%d PUSH%c\n", p-code, *p-PUSH0+'0'); |
| p++; |
| break; |
| case PUSHBYTE: |
| printf ("%d PUSHBYTE %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case PUSHWORD: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d PUSHWORD %d\n", n, c.w); |
| } |
| break; |
| case PUSHFLOAT: |
| { |
| CodeFloat c; |
| int n = p-code; |
| p++; |
| get_float(c,p); |
| printf ("%d PUSHFLOAT %f\n", n, c.f); |
| } |
| break; |
| case PUSHSTRING: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d PUSHSTRING %d\n", n, c.w); |
| } |
| break; |
| case PUSHFUNCTION: |
| { |
| CodeCode c; |
| int n = p-code; |
| p++; |
| get_code(c,p); |
| printf ("%d PUSHFUNCTION %p\n", n, c.tf); |
| } |
| break; |
| |
| case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3: |
| case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7: |
| case PUSHLOCAL8: case PUSHLOCAL9: |
| printf ("%d PUSHLOCAL%c\n", p-code, *p-PUSHLOCAL0+'0'); |
| p++; |
| break; |
| case PUSHLOCAL: printf ("%d PUSHLOCAL %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case PUSHGLOBAL: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d PUSHGLOBAL %d\n", n, c.w); |
| } |
| break; |
| case PUSHINDEXED: printf ("%d PUSHINDEXED\n", (p++)-code); break; |
| case STORELOCAL0: case STORELOCAL1: case STORELOCAL2: case STORELOCAL3: |
| case STORELOCAL4: case STORELOCAL5: case STORELOCAL6: case STORELOCAL7: |
| case STORELOCAL8: case STORELOCAL9: |
| printf ("%d STORELOCAL%c\n", p-code, *p-STORELOCAL0+'0'); |
| p++; |
| break; |
| case STORELOCAL: |
| printf ("%d STORELOCAL %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case STOREGLOBAL: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d STOREGLOBAL %d\n", n, c.w); |
| } |
| break; |
| case PUSHSELF: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d PUSHSELF %d\n", n, c.w); |
| } |
| break; |
| case STOREINDEXED0: printf ("%d STOREINDEXED0\n", (p++)-code); break; |
| case STOREINDEXED: printf ("%d STOREINDEXED %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case STORELIST0: |
| printf("%d STORELIST0 %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case STORELIST: |
| printf("%d STORELIST %d %d\n", p-code, *(p+1), *(p+2)); |
| p+=3; |
| break; |
| case STORERECORD: |
| printf("%d STORERECORD %d\n", p-code, *(++p)); |
| p += *p*sizeof(Word) + 1; |
| break; |
| case ADJUST0: printf ("%d ADJUST0\n", (p++)-code); break; |
| case ADJUST: |
| printf ("%d ADJUST %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case CREATEARRAY: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d CREATEARRAY %d\n", n, c.w); |
| break; |
| } |
| case EQOP: printf ("%d EQOP\n", (p++)-code); break; |
| case LTOP: printf ("%d LTOP\n", (p++)-code); break; |
| case LEOP: printf ("%d LEOP\n", (p++)-code); break; |
| case ADDOP: printf ("%d ADDOP\n", (p++)-code); break; |
| case SUBOP: printf ("%d SUBOP\n", (p++)-code); break; |
| case MULTOP: printf ("%d MULTOP\n", (p++)-code); break; |
| case DIVOP: printf ("%d DIVOP\n", (p++)-code); break; |
| case POWOP: printf ("%d POWOP\n", (p++)-code); break; |
| case CONCOP: printf ("%d CONCOP\n", (p++)-code); break; |
| case MINUSOP: printf ("%d MINUSOP\n", (p++)-code); break; |
| case NOTOP: printf ("%d NOTOP\n", (p++)-code); break; |
| case ONTJMP: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d ONTJMP %d\n", n, c.w); |
| } |
| break; |
| case ONFJMP: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d ONFJMP %d\n", n, c.w); |
| } |
| break; |
| case JMP: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d JMP %d\n", n, c.w); |
| } |
| break; |
| case UPJMP: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d UPJMP %d\n", n, c.w); |
| } |
| break; |
| case IFFJMP: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d IFFJMP %d\n", n, c.w); |
| } |
| break; |
| case IFFUPJMP: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d IFFUPJMP %d\n", n, c.w); |
| } |
| break; |
| case POP: printf ("%d POP\n", (p++)-code); break; |
| case CALLFUNC: |
| printf ("%d CALLFUNC %d %d\n", p-code, *(p+1), *(p+2)); |
| p+=3; |
| break; |
| case RETCODE0: printf ("%d RETCODE0\n", (p++)-code); break; |
| case RETCODE: |
| printf ("%d RETCODE %d\n", p-code, *(++p)); |
| p++; |
| break; |
| case SETLINE: |
| { |
| CodeWord c; |
| int n = p-code; |
| p++; |
| get_word(c,p); |
| printf ("%d SETLINE %d\n", n, c.w); |
| } |
| break; |
| |
| default: printf ("%d Cannot happen: code %d\n", (p++)-code, *(p-1)); break; |
| } |
| } |
| } |
| #endif |
| |