diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-03-03 15:53:17 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-03-03 15:53:17 -0300 |
commit | d1ea38580ae35a3a34e7122c41682af7f9901030 (patch) | |
tree | ce7fa1568be9eb757805966b77ea1eac2bc604f6 | |
parent | 3c9d999424520c809e05bee11d81788b488434f6 (diff) | |
download | lua-d1ea38580ae35a3a34e7122c41682af7f9901030.tar.gz lua-d1ea38580ae35a3a34e7122c41682af7f9901030.tar.bz2 lua-d1ea38580ae35a3a34e7122c41682af7f9901030.zip |
change of code generation design (independent functions for each opcode)
-rw-r--r-- | lcode.c | 223 | ||||
-rw-r--r-- | lcode.h | 25 | ||||
-rw-r--r-- | lopcodes.h | 7 | ||||
-rw-r--r-- | lparser.c | 85 | ||||
-rw-r--r-- | lparser.h | 28 |
5 files changed, 180 insertions, 188 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.3 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,12 +20,10 @@ void luaK_error (LexState *ls, const char *msg) { | |||
20 | } | 20 | } |
21 | 21 | ||
22 | 22 | ||
23 | static Instruction *last_i (FuncState *fs) { | 23 | static Instruction *last_i (LexState *ls, expdesc *v) { |
24 | static Instruction dummy = SET_OPCODE(0, ENDCODE); | 24 | FuncState *fs = ls->fs; |
25 | if (fs->last_pc < 0) | 25 | int last_pc = (v->info != NOJUMPS) ? v->info : fs->pc-1; |
26 | return &dummy; | 26 | return &fs->f->code[last_pc]; |
27 | else | ||
28 | return &fs->f->code[fs->last_pc]; | ||
29 | } | 27 | } |
30 | 28 | ||
31 | 29 | ||
@@ -37,58 +35,64 @@ int luaK_primitivecode (LexState *ls, Instruction i) { | |||
37 | } | 35 | } |
38 | 36 | ||
39 | 37 | ||
38 | static void luaK_minus (LexState *ls, expdesc *v) { | ||
39 | Instruction *last = last_i(ls, v); | ||
40 | switch(GET_OPCODE(*last)) { | ||
41 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); return; | ||
42 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); return; | ||
43 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); return; | ||
44 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); | ||
45 | } | ||
46 | } | ||
40 | 47 | ||
41 | int luaK_code (LexState *ls, Instruction i) { | ||
42 | FuncState *fs = ls->fs; | ||
43 | Instruction *last = last_i(fs); | ||
44 | switch (GET_OPCODE(i)) { | ||
45 | |||
46 | case MINUSOP: | ||
47 | switch(GET_OPCODE(*last)) { | ||
48 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); break; | ||
49 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); break; | ||
50 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); break; | ||
51 | default: fs->last_pc = luaK_primitivecode(ls, i); | ||
52 | } | ||
53 | break; | ||
54 | 48 | ||
55 | case GETTABLE: | 49 | static void luaK_gettable (LexState *ls, expdesc *v) { |
56 | switch(GET_OPCODE(*last)) { | 50 | Instruction *last = last_i(ls, v); |
57 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; | 51 | luaK_deltastack(ls, -1); |
58 | default: fs->last_pc = luaK_primitivecode(ls, i); | 52 | switch(GET_OPCODE(*last)) { |
59 | } | 53 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; |
60 | break; | 54 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); |
55 | } | ||
56 | } | ||
61 | 57 | ||
62 | case RETCODE: | ||
63 | switch(GET_OPCODE(*last)) { | ||
64 | case CALL: | ||
65 | *last = SET_OPCODE(*last, TAILCALL); | ||
66 | *last = SETARG_B(*last, GETARG_U(i)); | ||
67 | break; | ||
68 | default: fs->last_pc = luaK_primitivecode(ls, i); | ||
69 | } | ||
70 | break; | ||
71 | 58 | ||
72 | case ADDOP: | 59 | static void luaK_add (LexState *ls, expdesc *v) { |
73 | switch(GET_OPCODE(*last)) { | 60 | Instruction *last = last_i(ls, v); |
74 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; | 61 | luaK_deltastack(ls, -1); |
75 | default: fs->last_pc = luaK_primitivecode(ls, i); | 62 | switch(GET_OPCODE(*last)) { |
76 | } | 63 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; |
77 | break; | 64 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); |
65 | } | ||
66 | } | ||
67 | |||
78 | 68 | ||
79 | case SUBOP: | 69 | static void luaK_sub (LexState *ls, expdesc *v) { |
80 | switch(GET_OPCODE(*last)) { | 70 | Instruction *last = last_i(ls, v); |
81 | case PUSHINT: | 71 | luaK_deltastack(ls, -1); |
82 | *last = SET_OPCODE(*last, ADDI); | 72 | switch(GET_OPCODE(*last)) { |
83 | *last = SETARG_S(*last, -GETARG_S(*last)); | 73 | case PUSHINT: |
84 | break; | 74 | *last = SET_OPCODE(*last, ADDI); |
85 | default: fs->last_pc = luaK_primitivecode(ls, i); | 75 | *last = SETARG_S(*last, -GETARG_S(*last)); |
86 | } | ||
87 | break; | 76 | break; |
77 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); | ||
78 | } | ||
79 | } | ||
88 | 80 | ||
89 | default: fs->last_pc = luaK_primitivecode(ls, i); | 81 | |
82 | void luaK_retcode (LexState *ls, int nlocals, listdesc *e) { | ||
83 | if (e->n > 0 && luaK_iscall(ls, e->info)) { | ||
84 | Instruction *last = &ls->fs->f->code[ls->fs->pc-1]; | ||
85 | *last = SET_OPCODE(*last, TAILCALL); | ||
86 | *last = SETARG_B(*last, nlocals); | ||
90 | } | 87 | } |
91 | return fs->last_pc; | 88 | else |
89 | luaK_U(ls, RETCODE, nlocals, 0); | ||
90 | } | ||
91 | |||
92 | |||
93 | int luaK_code (LexState *ls, Instruction i, int delta) { | ||
94 | luaK_deltastack(ls, delta); | ||
95 | return luaK_primitivecode(ls, i); | ||
92 | } | 96 | } |
93 | 97 | ||
94 | 98 | ||
@@ -97,7 +101,6 @@ void luaK_fixjump (LexState *ls, int pc, int dest) { | |||
97 | Instruction *jmp = &fs->f->code[pc]; | 101 | Instruction *jmp = &fs->f->code[pc]; |
98 | /* jump is relative to position following jump instruction */ | 102 | /* jump is relative to position following jump instruction */ |
99 | *jmp = SETARG_S(*jmp, dest-(pc+1)); | 103 | *jmp = SETARG_S(*jmp, dest-(pc+1)); |
100 | fs->last_pc = pc; | ||
101 | } | 104 | } |
102 | 105 | ||
103 | 106 | ||
@@ -112,38 +115,8 @@ void luaK_deltastack (LexState *ls, int delta) { | |||
112 | } | 115 | } |
113 | 116 | ||
114 | 117 | ||
115 | static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { | 118 | void luaK_kstr (LexState *ls, int c) { |
116 | luaK_deltastack(ls, delta); | 119 | luaK_U(ls, PUSHSTRING, c, 1); |
117 | return luaK_code(ls, SET_OPCODE(i, op)); | ||
118 | } | ||
119 | |||
120 | |||
121 | int luaK_0 (LexState *ls, OpCode op, int delta) { | ||
122 | return aux_code(ls, op, 0, delta); | ||
123 | } | ||
124 | |||
125 | |||
126 | int luaK_U (LexState *ls, OpCode op, int u, int delta) { | ||
127 | Instruction i = SETARG_U(0, u); | ||
128 | return aux_code(ls, op, i, delta); | ||
129 | } | ||
130 | |||
131 | |||
132 | int luaK_S (LexState *ls, OpCode op, int s, int delta) { | ||
133 | Instruction i = SETARG_S(0, s); | ||
134 | return aux_code(ls, op, i, delta); | ||
135 | } | ||
136 | |||
137 | |||
138 | int luaK_AB (LexState *ls, OpCode op, int a, int b, int delta) { | ||
139 | Instruction i = SETARG_A(0, a); | ||
140 | i = SETARG_B(i, b); | ||
141 | return aux_code(ls, op, i, delta); | ||
142 | } | ||
143 | |||
144 | |||
145 | int luaK_kstr (LexState *ls, int c) { | ||
146 | return luaK_U(ls, PUSHSTRING, c, 1); | ||
147 | } | 120 | } |
148 | 121 | ||
149 | 122 | ||
@@ -166,37 +139,40 @@ static int real_constant (LexState *ls, real r) { | |||
166 | } | 139 | } |
167 | 140 | ||
168 | 141 | ||
169 | int luaK_number (LexState *ls, real f) { | 142 | void luaK_number (LexState *ls, real f) { |
170 | if (f <= (real)MAXARG_S && (int)f == f) | 143 | if (f <= (real)MAXARG_S && (int)f == f) |
171 | return luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ | 144 | luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ |
172 | else | 145 | else |
173 | return luaK_U(ls, PUSHNUM, real_constant(ls, f), 1); | 146 | luaK_U(ls, PUSHNUM, real_constant(ls, f), 1); |
174 | } | 147 | } |
175 | 148 | ||
176 | 149 | ||
177 | int luaK_adjuststack (LexState *ls, int n) { | 150 | void luaK_adjuststack (LexState *ls, int n) { |
178 | if (n > 0) | 151 | if (n > 0) |
179 | return luaK_U(ls, POP, n, -n); | 152 | luaK_U(ls, POP, n, -n); |
180 | else if (n < 0) | 153 | else if (n < 0) |
181 | return luaK_U(ls, PUSHNIL, (-n)-1, -n); | 154 | luaK_U(ls, PUSHNIL, (-n)-1, -n); |
182 | else return 0; | ||
183 | } | 155 | } |
184 | 156 | ||
185 | 157 | ||
186 | int luaK_iscall (LexState *ls, int pc) { | 158 | int luaK_iscall (LexState *ls, int hasjumps) { |
187 | return (GET_OPCODE(ls->fs->f->code[pc]) == CALL); | 159 | if (hasjumps) return 0; /* a call cannot have internal jumps */ |
160 | else /* check whether last instruction is a function call */ | ||
161 | return (GET_OPCODE(ls->fs->f->code[ls->fs->pc-1]) == CALL); | ||
188 | } | 162 | } |
189 | 163 | ||
190 | 164 | ||
191 | void luaK_setcallreturns (LexState *ls, int pc, int nresults) { | 165 | void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) { |
192 | if (luaK_iscall(ls, pc)) { /* expression is a function call? */ | 166 | if (!hasjumps) { /* if `hasjumps' cannot be a function call */ |
193 | Instruction *i = &ls->fs->f->code[pc]; | 167 | Instruction *i = &ls->fs->f->code[ls->fs->pc-1]; |
194 | int old_nresults = GETARG_B(*i); | 168 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ |
195 | if (old_nresults != MULT_RET) | 169 | int old_nresults = GETARG_B(*i); |
196 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ | 170 | if (old_nresults != MULT_RET) |
197 | *i = SETARG_B(*i, nresults); /* set nresults */ | 171 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ |
198 | if (nresults != MULT_RET) | 172 | *i = SETARG_B(*i, nresults); /* set nresults */ |
199 | luaK_deltastack(ls, nresults); /* push results */ | 173 | if (nresults != MULT_RET) |
174 | luaK_deltastack(ls, nresults); /* push results */ | ||
175 | } | ||
200 | } | 176 | } |
201 | } | 177 | } |
202 | 178 | ||
@@ -209,20 +185,21 @@ static void assertglobal (LexState *ls, int index) { | |||
209 | void luaK_2stack (LexState *ls, expdesc *var) { | 185 | void luaK_2stack (LexState *ls, expdesc *var) { |
210 | switch (var->k) { | 186 | switch (var->k) { |
211 | case VLOCAL: | 187 | case VLOCAL: |
212 | var->info = luaK_U(ls, PUSHLOCAL, var->info, 1); | 188 | luaK_U(ls, PUSHLOCAL, var->info, 1); |
213 | break; | 189 | break; |
214 | case VGLOBAL: | 190 | case VGLOBAL: |
191 | luaK_U(ls, GETGLOBAL, var->info, 1); | ||
215 | assertglobal(ls, var->info); /* make sure that there is a global */ | 192 | assertglobal(ls, var->info); /* make sure that there is a global */ |
216 | var->info = luaK_U(ls, GETGLOBAL, var->info, 1); | ||
217 | break; | 193 | break; |
218 | case VINDEXED: | 194 | case VINDEXED: |
219 | var->info = luaK_0(ls, GETTABLE, -1); | 195 | luaK_gettable(ls, var); |
220 | break; | 196 | break; |
221 | case VEXP: | 197 | case VEXP: |
222 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ | 198 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ |
223 | break; | 199 | return; /* does not change var->info */ |
224 | } | 200 | } |
225 | var->k = VEXP; | 201 | var->k = VEXP; |
202 | var->info = NOJUMPS; | ||
226 | } | 203 | } |
227 | 204 | ||
228 | 205 | ||
@@ -246,10 +223,9 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
246 | 223 | ||
247 | void luaK_prefix (LexState *ls, int op, expdesc *v) { | 224 | void luaK_prefix (LexState *ls, int op, expdesc *v) { |
248 | luaK_2stack(ls, v); | 225 | luaK_2stack(ls, v); |
249 | if (op == '-') | 226 | if (op == '-') luaK_minus(ls, v); |
250 | v->info = luaK_0(ls, MINUSOP, 0); | 227 | else luaK_0(ls, NOTOP, 0); |
251 | else | 228 | v->info = NOJUMPS; |
252 | v->info = luaK_0(ls, NOTOP, 0); | ||
253 | } | 229 | } |
254 | 230 | ||
255 | 231 | ||
@@ -267,19 +243,20 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
267 | switch (op) { | 243 | switch (op) { |
268 | case AND: case OR: | 244 | case AND: case OR: |
269 | luaK_fixjump(ls, v1->info, ls->fs->pc); | 245 | luaK_fixjump(ls, v1->info, ls->fs->pc); |
270 | break; | 246 | return; /* keep v1->info != NOJUMPS */ |
271 | case '+': v1->info = luaK_0(ls, ADDOP, -1); break; | 247 | case '+': luaK_add(ls, v2); break; |
272 | case '-': v1->info = luaK_0(ls, SUBOP, -1); break; | 248 | case '-': luaK_sub(ls, v2); break; |
273 | case '*': v1->info = luaK_0(ls, MULTOP, -1); break; | 249 | case '*': luaK_0(ls, MULTOP, -1); break; |
274 | case '/': v1->info = luaK_0(ls, DIVOP, -1); break; | 250 | case '/': luaK_0(ls, DIVOP, -1); break; |
275 | case '^': v1->info = luaK_0(ls, POWOP, -1); break; | 251 | case '^': luaK_0(ls, POWOP, -1); break; |
276 | case CONC: v1->info = luaK_0(ls, CONCOP, -1); break; | 252 | case CONC: luaK_0(ls, CONCOP, -1); break; |
277 | case EQ: v1->info = luaK_0(ls, EQOP, -1); break; | 253 | case EQ: luaK_0(ls, EQOP, -1); break; |
278 | case NE: v1->info = luaK_0(ls, NEQOP, -1); break; | 254 | case NE: luaK_0(ls, NEQOP, -1); break; |
279 | case '>': v1->info = luaK_0(ls, GTOP, -1); break; | 255 | case '>': luaK_0(ls, GTOP, -1); break; |
280 | case '<': v1->info = luaK_0(ls, LTOP, -1); break; | 256 | case '<': luaK_0(ls, LTOP, -1); break; |
281 | case GE: v1->info = luaK_0(ls, GEOP, -1); break; | 257 | case GE: luaK_0(ls, GEOP, -1); break; |
282 | case LE: v1->info = luaK_0(ls, LEOP, -1); break; | 258 | case LE: luaK_0(ls, LEOP, -1); break; |
283 | } | 259 | } |
260 | v1->info = NOJUMPS; | ||
284 | } | 261 | } |
285 | 262 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.1 2000/02/22 13:31:19 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,20 +13,23 @@ | |||
13 | #include "lparser.h" | 13 | #include "lparser.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define luaK_0(ls,o,d) luaK_code(ls, CREATE_0(o), d) | ||
17 | #define luaK_U(ls,o,u,d) luaK_code(ls, CREATE_U(o,u), d) | ||
18 | #define luaK_S(ls,o,s,d) luaK_code(ls, CREATE_S(o,s), d) | ||
19 | #define luaK_AB(ls,o,a,b,d) luaK_code(ls, CREATE_AB(o,a,b), d) | ||
20 | |||
21 | |||
16 | void luaK_error (LexState *ls, const char *msg); | 22 | void luaK_error (LexState *ls, const char *msg); |
17 | int luaK_primitivecode (LexState *ls, Instruction i); | 23 | int luaK_primitivecode (LexState *ls, Instruction i); |
18 | int luaK_code (LexState *ls, Instruction i); | 24 | int luaK_code (LexState *ls, Instruction i, int delta); |
25 | void luaK_retcode (LexState *ls, int nlocals, listdesc *e); | ||
19 | void luaK_fixjump (LexState *ls, int pc, int dest); | 26 | void luaK_fixjump (LexState *ls, int pc, int dest); |
20 | void luaK_deltastack (LexState *ls, int delta); | 27 | void luaK_deltastack (LexState *ls, int delta); |
21 | int luaK_0 (LexState *ls, OpCode op, int delta); | 28 | void luaK_kstr (LexState *ls, int c); |
22 | int luaK_U (LexState *ls, OpCode op, int u, int delta); | 29 | void luaK_number (LexState *ls, real f); |
23 | int luaK_S (LexState *ls, OpCode op, int s, int delta); | 30 | void luaK_adjuststack (LexState *ls, int n); |
24 | int luaK_AB (LexState *ls, OpCode op, int a, int b, int delta); | 31 | int luaK_iscall (LexState *ls, int hasjumps); |
25 | int luaK_kstr (LexState *ls, int c); | 32 | void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults); |
26 | int luaK_number (LexState *ls, real f); | ||
27 | int luaK_adjuststack (LexState *ls, int n); | ||
28 | int luaK_iscall (LexState *ls, int pc); | ||
29 | void luaK_setcallreturns (LexState *ls, int pc, int nresults); | ||
30 | void luaK_2stack (LexState *ls, expdesc *var); | 33 | void luaK_2stack (LexState *ls, expdesc *var); |
31 | void luaK_storevar (LexState *ls, const expdesc *var); | 34 | void luaK_storevar (LexState *ls, const expdesc *var); |
32 | void luaK_prefix (LexState *ls, int op, expdesc *v); | 35 | void luaK_prefix (LexState *ls, int op, expdesc *v); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.42 2000/03/02 12:32:53 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.43 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -47,6 +47,11 @@ | |||
47 | #define SETARG_A(i,a) (((i)&0x0000FFFFu) | ((Instruction)(a)<<16)) | 47 | #define SETARG_A(i,a) (((i)&0x0000FFFFu) | ((Instruction)(a)<<16)) |
48 | #define SETARG_B(i,b) (((i)&0xFFFF00FFu) | ((Instruction)(b)<<8)) | 48 | #define SETARG_B(i,b) (((i)&0xFFFF00FFu) | ((Instruction)(b)<<8)) |
49 | 49 | ||
50 | #define CREATE_0(o) ((Instruction)(o)) | ||
51 | #define CREATE_U(o,u) ((Instruction)(o) | (Instruction)(u)<<8) | ||
52 | #define CREATE_S(o,s) ((Instruction)(o) | ((Instruction)(s)+EXCESS_S)<<8) | ||
53 | #define CREATE_AB(o,a,b) ((Instruction)(o) | ((Instruction)(a)<<16) \ | ||
54 | | ((Instruction)(b)<<8)) | ||
50 | 55 | ||
51 | 56 | ||
52 | /* | 57 | /* |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.61 2000/03/03 12:33:59 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.62 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,15 +23,13 @@ | |||
23 | 23 | ||
24 | 24 | ||
25 | /* | 25 | /* |
26 | ** Expression List descriptor: | 26 | ** check whether arbitrary limits fit in respective opcode types |
27 | ** tells number of expressions in the list, | ||
28 | ** and, if last expression is open (a function call), | ||
29 | ** where is the call pc index. | ||
30 | */ | 27 | */ |
31 | typedef struct listdesc { | 28 | #if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \ |
32 | int n; | 29 | MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B |
33 | int pc; /* 0 if last expression is closed */ | 30 | #error invalid limits |
34 | } listdesc; | 31 | #endif |
32 | |||
35 | 33 | ||
36 | 34 | ||
37 | /* | 35 | /* |
@@ -51,11 +49,11 @@ typedef struct constdesc { | |||
51 | /* | 49 | /* |
52 | ** prototypes for recursive non-terminal functions | 50 | ** prototypes for recursive non-terminal functions |
53 | */ | 51 | */ |
54 | static int body (LexState *ls, int needself, int line); | 52 | static void body (LexState *ls, int needself, int line); |
55 | static void chunk (LexState *ls); | 53 | static void chunk (LexState *ls); |
56 | static int constructor (LexState *ls); | 54 | static void constructor (LexState *ls); |
57 | static void expr (LexState *ls, expdesc *v); | 55 | static void expr (LexState *ls, expdesc *v); |
58 | static void exp1 (LexState *ls); | 56 | static int exp1 (LexState *ls); |
59 | 57 | ||
60 | 58 | ||
61 | static void next (LexState *ls) { | 59 | static void next (LexState *ls) { |
@@ -145,8 +143,8 @@ static int string_constant (LexState *ls, FuncState *fs, TaggedString *s) { | |||
145 | } | 143 | } |
146 | 144 | ||
147 | 145 | ||
148 | static int code_string (LexState *ls, TaggedString *s) { | 146 | static void code_string (LexState *ls, TaggedString *s) { |
149 | return luaK_kstr(ls, string_constant(ls, ls->fs, s)); | 147 | luaK_kstr(ls, string_constant(ls, ls->fs, s)); |
150 | } | 148 | } |
151 | 149 | ||
152 | 150 | ||
@@ -249,18 +247,18 @@ static int indexupvalue (LexState *ls, TaggedString *n) { | |||
249 | } | 247 | } |
250 | 248 | ||
251 | 249 | ||
252 | static int pushupvalue (LexState *ls, TaggedString *n) { | 250 | static void pushupvalue (LexState *ls, TaggedString *n) { |
253 | if (ls->fs->prev == NULL) | 251 | if (ls->fs->prev == NULL) |
254 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); | 252 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); |
255 | if (aux_localname(ls->fs, n) >= 0) | 253 | if (aux_localname(ls->fs, n) >= 0) |
256 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); | 254 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); |
257 | return luaK_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1); | 255 | luaK_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1); |
258 | } | 256 | } |
259 | 257 | ||
260 | 258 | ||
261 | static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | 259 | static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { |
262 | int diff = d->n - nvars; | 260 | int diff = d->n - nvars; |
263 | if (d->n == 0 || !luaK_iscall(ls, d->pc)) { /* list is empty or closed */ | 261 | if (d->n == 0 || !luaK_iscall(ls, d->info)) { /* list is empty or closed */ |
264 | /* push or pop eventual difference between list lengths */ | 262 | /* push or pop eventual difference between list lengths */ |
265 | luaK_adjuststack(ls, diff); | 263 | luaK_adjuststack(ls, diff); |
266 | } | 264 | } |
@@ -268,10 +266,10 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | |||
268 | diff--; /* do not count function call itself */ | 266 | diff--; /* do not count function call itself */ |
269 | if (diff <= 0) { /* more variables than values? */ | 267 | if (diff <= 0) { /* more variables than values? */ |
270 | /* function call must provide extra values */ | 268 | /* function call must provide extra values */ |
271 | luaK_setcallreturns(ls, d->pc, -diff); | 269 | luaK_setcallreturns(ls, d->info, -diff); |
272 | } | 270 | } |
273 | else { /* more values than variables */ | 271 | else { /* more values than variables */ |
274 | luaK_setcallreturns(ls, d->pc, 0); /* call should provide no value */ | 272 | luaK_setcallreturns(ls, d->info, 0); /* call should provide no value */ |
275 | luaK_adjuststack(ls, diff); /* pop eventual extra values */ | 273 | luaK_adjuststack(ls, diff); /* pop eventual extra values */ |
276 | } | 274 | } |
277 | } | 275 | } |
@@ -308,7 +306,7 @@ static int getvarname (LexState *ls, expdesc *var) { | |||
308 | } | 306 | } |
309 | 307 | ||
310 | 308 | ||
311 | static int func_onstack (LexState *ls, FuncState *func) { | 309 | static void func_onstack (LexState *ls, FuncState *func) { |
312 | TProtoFunc *f = ls->fs->f; | 310 | TProtoFunc *f = ls->fs->f; |
313 | int i; | 311 | int i; |
314 | for (i=0; i<func->nupvalues; i++) | 312 | for (i=0; i<func->nupvalues; i++) |
@@ -317,7 +315,7 @@ static int func_onstack (LexState *ls, FuncState *func) { | |||
317 | constantEM, MAXARG_A); | 315 | constantEM, MAXARG_A); |
318 | f->kproto[f->nkproto++] = func->f; | 316 | f->kproto[f->nkproto++] = func->f; |
319 | luaK_deltastack(ls, 1); /* CLOSURE puts one extra element before popping */ | 317 | luaK_deltastack(ls, 1); /* CLOSURE puts one extra element before popping */ |
320 | return luaK_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues); | 318 | luaK_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues); |
321 | } | 319 | } |
322 | 320 | ||
323 | 321 | ||
@@ -333,7 +331,6 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { | |||
333 | fs->f = f; | 331 | fs->f = f; |
334 | f->source = source; | 332 | f->source = source; |
335 | fs->pc = 0; | 333 | fs->pc = 0; |
336 | fs->last_pc = -1; /* invalid index to signal no last instruction */ | ||
337 | f->code = NULL; | 334 | f->code = NULL; |
338 | f->maxstacksize = 0; | 335 | f->maxstacksize = 0; |
339 | f->numparams = 0; /* default for main chunk */ | 336 | f->numparams = 0; /* default for main chunk */ |
@@ -395,7 +392,7 @@ static void explist1 (LexState *ls, listdesc *d) { | |||
395 | } | 392 | } |
396 | luaK_2stack(ls, &v); | 393 | luaK_2stack(ls, &v); |
397 | luaK_setcallreturns(ls, v.info, MULT_RET); /* default for explists */ | 394 | luaK_setcallreturns(ls, v.info, MULT_RET); /* default for explists */ |
398 | d->pc = v.info; | 395 | d->info = v.info; |
399 | } | 396 | } |
400 | 397 | ||
401 | 398 | ||
@@ -412,7 +409,7 @@ static void explist (LexState *ls, listdesc *d) { | |||
412 | } | 409 | } |
413 | 410 | ||
414 | 411 | ||
415 | static int funcparams (LexState *ls, int slf) { | 412 | static void funcparams (LexState *ls, int slf) { |
416 | FuncState *fs = ls->fs; | 413 | FuncState *fs = ls->fs; |
417 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ | 414 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ |
418 | switch (ls->token) { | 415 | switch (ls->token) { |
@@ -443,7 +440,7 @@ static int funcparams (LexState *ls, int slf) { | |||
443 | break; | 440 | break; |
444 | } | 441 | } |
445 | fs->stacksize = slevel; /* call will remove func and params */ | 442 | fs->stacksize = slevel; /* call will remove func and params */ |
446 | return luaK_AB(ls, CALL, slevel, 0, 0); | 443 | luaK_AB(ls, CALL, slevel, 0, 0); |
447 | } | 444 | } |
448 | 445 | ||
449 | 446 | ||
@@ -455,14 +452,15 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
455 | luaK_2stack(ls, v); /* `v' must be on stack */ | 452 | luaK_2stack(ls, v); /* `v' must be on stack */ |
456 | luaK_kstr(ls, checkname(ls)); | 453 | luaK_kstr(ls, checkname(ls)); |
457 | v->k = VINDEXED; | 454 | v->k = VINDEXED; |
455 | v->info = NOJUMPS; | ||
458 | break; | 456 | break; |
459 | 457 | ||
460 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | 458 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ |
461 | next(ls); | 459 | next(ls); |
462 | luaK_2stack(ls, v); /* `v' must be on stack */ | 460 | luaK_2stack(ls, v); /* `v' must be on stack */ |
463 | exp1(ls); | ||
464 | check(ls, ']'); | ||
465 | v->k = VINDEXED; | 461 | v->k = VINDEXED; |
462 | v->info = exp1(ls); | ||
463 | check(ls, ']'); | ||
466 | break; | 464 | break; |
467 | 465 | ||
468 | case ':': { /* var_or_func_tail -> ':' NAME funcparams */ | 466 | case ':': { /* var_or_func_tail -> ':' NAME funcparams */ |
@@ -471,15 +469,17 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
471 | name = checkname(ls); | 469 | name = checkname(ls); |
472 | luaK_2stack(ls, v); /* `v' must be on stack */ | 470 | luaK_2stack(ls, v); /* `v' must be on stack */ |
473 | luaK_U(ls, PUSHSELF, name, 1); | 471 | luaK_U(ls, PUSHSELF, name, 1); |
472 | funcparams(ls, 1); | ||
474 | v->k = VEXP; | 473 | v->k = VEXP; |
475 | v->info = funcparams(ls, 1); | 474 | v->info = NOJUMPS; |
476 | break; | 475 | break; |
477 | } | 476 | } |
478 | 477 | ||
479 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ | 478 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ |
480 | luaK_2stack(ls, v); /* `v' must be on stack */ | 479 | luaK_2stack(ls, v); /* `v' must be on stack */ |
480 | funcparams(ls, 0); | ||
481 | v->k = VEXP; | 481 | v->k = VEXP; |
482 | v->info = funcparams(ls, 0); | 482 | v->info = NOJUMPS; |
483 | break; | 483 | break; |
484 | 484 | ||
485 | default: return; /* should be follow... */ | 485 | default: return; /* should be follow... */ |
@@ -491,8 +491,9 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
491 | static void var_or_func (LexState *ls, expdesc *v) { | 491 | static void var_or_func (LexState *ls, expdesc *v) { |
492 | /* var_or_func -> ['%'] NAME var_or_func_tail */ | 492 | /* var_or_func -> ['%'] NAME var_or_func_tail */ |
493 | if (optional(ls, '%')) { /* upvalue? */ | 493 | if (optional(ls, '%')) { /* upvalue? */ |
494 | pushupvalue(ls, str_checkname(ls)); | ||
494 | v->k = VEXP; | 495 | v->k = VEXP; |
495 | v->info = pushupvalue(ls, str_checkname(ls)); | 496 | v->info = NOJUMPS; |
496 | } | 497 | } |
497 | else /* variable name */ | 498 | else /* variable name */ |
498 | singlevar(ls, str_checkname(ls), v, 0); | 499 | singlevar(ls, str_checkname(ls), v, 0); |
@@ -614,7 +615,7 @@ static void constructor_part (LexState *ls, constdesc *cd) { | |||
614 | } | 615 | } |
615 | 616 | ||
616 | 617 | ||
617 | static int constructor (LexState *ls) { | 618 | static void constructor (LexState *ls) { |
618 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ | 619 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ |
619 | int line = ls->linenumber; | 620 | int line = ls->linenumber; |
620 | int pc = luaK_U(ls, CREATETABLE, 0, 1); | 621 | int pc = luaK_U(ls, CREATETABLE, 0, 1); |
@@ -634,7 +635,6 @@ static int constructor (LexState *ls) { | |||
634 | check_match(ls, '}', '{', line); | 635 | check_match(ls, '}', '{', line); |
635 | /* set initial table size */ | 636 | /* set initial table size */ |
636 | ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems); | 637 | ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems); |
637 | return pc; | ||
638 | } | 638 | } |
639 | 639 | ||
640 | /* }====================================================================== */ | 640 | /* }====================================================================== */ |
@@ -655,28 +655,27 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
655 | case NUMBER: { /* simpleexp -> NUMBER */ | 655 | case NUMBER: { /* simpleexp -> NUMBER */ |
656 | real r = ls->seminfo.r; | 656 | real r = ls->seminfo.r; |
657 | next(ls); | 657 | next(ls); |
658 | v->info = luaK_number(ls, r); | 658 | luaK_number(ls, r); |
659 | break; | 659 | break; |
660 | } | 660 | } |
661 | 661 | ||
662 | case STRING: /* simpleexp -> STRING */ | 662 | case STRING: /* simpleexp -> STRING */ |
663 | /* must use `seminfo' before `next' */ | 663 | code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */ |
664 | v->info = code_string(ls, ls->seminfo.ts); | ||
665 | next(ls); | 664 | next(ls); |
666 | break; | 665 | break; |
667 | 666 | ||
668 | case NIL: /* simpleexp -> NIL */ | 667 | case NIL: /* simpleexp -> NIL */ |
669 | v->info = luaK_adjuststack(ls, -1); | 668 | luaK_adjuststack(ls, -1); |
670 | next(ls); | 669 | next(ls); |
671 | break; | 670 | break; |
672 | 671 | ||
673 | case '{': /* simpleexp -> constructor */ | 672 | case '{': /* simpleexp -> constructor */ |
674 | v->info = constructor(ls); | 673 | constructor(ls); |
675 | break; | 674 | break; |
676 | 675 | ||
677 | case FUNCTION: /* simpleexp -> FUNCTION body */ | 676 | case FUNCTION: /* simpleexp -> FUNCTION body */ |
678 | next(ls); | 677 | next(ls); |
679 | v->info = body(ls, 0, ls->linenumber); | 678 | body(ls, 0, ls->linenumber); |
680 | break; | 679 | break; |
681 | 680 | ||
682 | case '(': /* simpleexp -> '(' expr ')' */ | 681 | case '(': /* simpleexp -> '(' expr ')' */ |
@@ -694,13 +693,15 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
694 | return; | 693 | return; |
695 | } | 694 | } |
696 | v->k = VEXP; | 695 | v->k = VEXP; |
696 | v->info = NOJUMPS; | ||
697 | } | 697 | } |
698 | 698 | ||
699 | 699 | ||
700 | static void exp1 (LexState *ls) { | 700 | static int exp1 (LexState *ls) { |
701 | expdesc v; | 701 | expdesc v; |
702 | expr(ls, &v); | 702 | expr(ls, &v); |
703 | luaK_2stack(ls, &v); | 703 | luaK_2stack(ls, &v); |
704 | return v.info; | ||
704 | } | 705 | } |
705 | 706 | ||
706 | 707 | ||
@@ -1052,7 +1053,7 @@ static void parlist (LexState *ls) { | |||
1052 | } | 1053 | } |
1053 | 1054 | ||
1054 | 1055 | ||
1055 | static int body (LexState *ls, int needself, int line) { | 1056 | static void body (LexState *ls, int needself, int line) { |
1056 | /* body -> '(' parlist ')' chunk END */ | 1057 | /* body -> '(' parlist ')' chunk END */ |
1057 | FuncState new_fs; | 1058 | FuncState new_fs; |
1058 | init_state(ls, &new_fs, ls->fs->f->source); | 1059 | init_state(ls, &new_fs, ls->fs->f->source); |
@@ -1065,7 +1066,7 @@ static int body (LexState *ls, int needself, int line) { | |||
1065 | chunk(ls); | 1066 | chunk(ls); |
1066 | check_match(ls, END, FUNCTION, line); | 1067 | check_match(ls, END, FUNCTION, line); |
1067 | close_func(ls); | 1068 | close_func(ls); |
1068 | return func_onstack(ls, &new_fs); | 1069 | func_onstack(ls, &new_fs); |
1069 | } | 1070 | } |
1070 | 1071 | ||
1071 | 1072 | ||
@@ -1076,7 +1077,7 @@ static void ret (LexState *ls) { | |||
1076 | check_debugline(ls); | 1077 | check_debugline(ls); |
1077 | next(ls); | 1078 | next(ls); |
1078 | explist(ls, &e); | 1079 | explist(ls, &e); |
1079 | luaK_U(ls, RETCODE, ls->fs->nlocalvar, 0); | 1080 | luaK_retcode(ls, ls->fs->nlocalvar, &e); |
1080 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | 1081 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ |
1081 | optional(ls, ';'); | 1082 | optional(ls, ';'); |
1082 | } | 1083 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.7 2000/03/03 12:33:59 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.8 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -8,7 +8,6 @@ | |||
8 | #define lparser_h | 8 | #define lparser_h |
9 | 9 | ||
10 | #include "lobject.h" | 10 | #include "lobject.h" |
11 | #include "lopcodes.h" | ||
12 | #include "lzio.h" | 11 | #include "lzio.h" |
13 | 12 | ||
14 | 13 | ||
@@ -42,21 +41,18 @@ | |||
42 | #endif | 41 | #endif |
43 | 42 | ||
44 | 43 | ||
45 | #if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \ | ||
46 | MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B | ||
47 | #error invalid limits | ||
48 | #endif | ||
49 | |||
50 | |||
51 | 44 | ||
52 | /* | 45 | /* |
53 | ** Expression descriptor | 46 | ** Expression descriptor |
54 | */ | 47 | */ |
48 | |||
49 | #define NOJUMPS 0 | ||
50 | |||
55 | typedef enum { | 51 | typedef enum { |
56 | VGLOBAL, /* info is constant index of global name */ | 52 | VGLOBAL, /* info is constant index of global name */ |
57 | VLOCAL, /* info is stack index */ | 53 | VLOCAL, /* info is stack index */ |
58 | VINDEXED, /* no info (table and index are on the stack) */ | 54 | VINDEXED, /* info is info of the index expression */ |
59 | VEXP /* info is pc index of exp main operator */ | 55 | VEXP /* info is NOJUMPS if exp has no internal jumps */ |
60 | } expkind; | 56 | } expkind; |
61 | 57 | ||
62 | typedef struct expdesc { | 58 | typedef struct expdesc { |
@@ -65,12 +61,22 @@ typedef struct expdesc { | |||
65 | } expdesc; | 61 | } expdesc; |
66 | 62 | ||
67 | 63 | ||
64 | /* | ||
65 | ** Expression List descriptor: | ||
66 | ** tells number of expressions in the list, | ||
67 | ** and gives the `info' of last expression. | ||
68 | */ | ||
69 | typedef struct listdesc { | ||
70 | int n; | ||
71 | int info; /* 0 if last expression has no internal jumps */ | ||
72 | } listdesc; | ||
73 | |||
74 | |||
68 | /* state needed to generate code for a given function */ | 75 | /* state needed to generate code for a given function */ |
69 | typedef struct FuncState { | 76 | typedef struct FuncState { |
70 | TProtoFunc *f; /* current function header */ | 77 | TProtoFunc *f; /* current function header */ |
71 | struct FuncState *prev; /* enclosing function */ | 78 | struct FuncState *prev; /* enclosing function */ |
72 | int pc; /* next position to code */ | 79 | int pc; /* next position to code */ |
73 | int last_pc; /* last instruction coded (for optimizations) */ | ||
74 | int stacksize; /* number of values on activation register */ | 80 | int stacksize; /* number of values on activation register */ |
75 | int nlocalvar; /* number of active local variables */ | 81 | int nlocalvar; /* number of active local variables */ |
76 | int nupvalues; /* number of upvalues */ | 82 | int nupvalues; /* number of upvalues */ |