diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-07-30 19:00:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-07-30 19:00:50 -0300 |
commit | 0892f0e5b75c51f1fee07276a3ba13301b83409e (patch) | |
tree | 9f3b9ec92f26c05a85c826ffc5f803fda2f48867 /lua.stx | |
parent | 1d7857bc635c0bfe7c5b1f325d31feb7660e9a5a (diff) | |
download | lua-0892f0e5b75c51f1fee07276a3ba13301b83409e.tar.gz lua-0892f0e5b75c51f1fee07276a3ba13301b83409e.tar.bz2 lua-0892f0e5b75c51f1fee07276a3ba13301b83409e.zip |
BIG CHANGE: functions have their own "constant table".
Diffstat (limited to 'lua.stx')
-rw-r--r-- | lua.stx | 281 |
1 files changed, 156 insertions, 125 deletions
@@ -1,10 +1,8 @@ | |||
1 | %{ | 1 | %{ |
2 | 2 | ||
3 | char *rcs_luastx = "$Id: lua.stx,v 3.47 1997/06/19 17:46:12 roberto Exp roberto $"; | 3 | char *rcs_luastx = "$Id: lua.stx,v 3.48 1997/07/29 20:38:45 roberto Exp roberto $"; |
4 | 4 | ||
5 | #include <stdio.h> | ||
6 | #include <stdlib.h> | 5 | #include <stdlib.h> |
7 | #include <string.h> | ||
8 | 6 | ||
9 | #include "luadebug.h" | 7 | #include "luadebug.h" |
10 | #include "luamem.h" | 8 | #include "luamem.h" |
@@ -40,6 +38,7 @@ struct State { | |||
40 | int pc; /* next position to code */ | 38 | int pc; /* next position to code */ |
41 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | 39 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ |
42 | int nlocalvar; /* number of active local variables */ | 40 | int nlocalvar; /* number of active local variables */ |
41 | int maxconsts; /* size of consts vector */ | ||
43 | int nvars; /* total number of local variables (for debugging information) */ | 42 | int nvars; /* total number of local variables (for debugging information) */ |
44 | int maxvars; /* = -1 if no debug information */ | 43 | int maxvars; /* = -1 if no debug information */ |
45 | } stateMain, stateFunc, *currState; | 44 | } stateMain, stateFunc, *currState; |
@@ -69,41 +68,106 @@ static void check_space (int i) | |||
69 | Byte, codeEM, MAX_INT); | 68 | Byte, codeEM, MAX_INT); |
70 | } | 69 | } |
71 | 70 | ||
71 | |||
72 | static void code_byte (Byte c) | 72 | static void code_byte (Byte c) |
73 | { | 73 | { |
74 | check_space(1); | 74 | check_space(1); |
75 | currState->f->code[currState->pc++] = c; | 75 | currState->f->code[currState->pc++] = c; |
76 | } | 76 | } |
77 | 77 | ||
78 | static void code_float (real n) | 78 | |
79 | static void code_word_at (int pc, int n) | ||
79 | { | 80 | { |
80 | check_space(sizeof(real)); | 81 | Word w = n; |
81 | memcpy(currState->f->code+currState->pc, &n, sizeof(real)); | 82 | if (w != n) |
82 | currState->pc += sizeof(real); | 83 | yyerror("block too big"); |
84 | currState->f->code[pc] = n&0xFF; | ||
85 | currState->f->code[pc+1] = n>>8; | ||
83 | } | 86 | } |
84 | 87 | ||
85 | static void code_code (TFunc *tf) | 88 | static void code_word (int n) |
86 | { | 89 | { |
87 | check_space(sizeof(TFunc *)); | 90 | code_byte(n&0xFF); |
88 | memcpy(currState->f->code+currState->pc, &tf, sizeof(TFunc *)); | 91 | code_byte(n>>8); |
89 | currState->pc += sizeof(TFunc *); | ||
90 | } | 92 | } |
91 | 93 | ||
92 | static void code_word_at (int pc, int n) | 94 | static void code_constant (int c) |
93 | { | 95 | { |
94 | Word w = n; | 96 | if (c <= 255) { |
95 | if (w != n) | 97 | code_byte(PUSHCONSTANTB); |
96 | yyerror("block too big"); | 98 | code_byte(c); |
97 | memcpy(currState->f->code+pc, &w, sizeof(Word)); | 99 | } |
100 | else { | ||
101 | code_byte(PUSHCONSTANT); | ||
102 | code_word(c); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
107 | static int next_constant (void) | ||
108 | { | ||
109 | if (currState->f->nconsts >= currState->maxconsts) { | ||
110 | currState->maxconsts = | ||
111 | growvector(&currState->f->consts, currState->maxconsts, | ||
112 | TObject, constantEM, MAX_WORD); | ||
113 | } | ||
114 | return currState->f->nconsts++; | ||
115 | } | ||
116 | |||
117 | |||
118 | static int string_constant (TaggedString *s) | ||
119 | { | ||
120 | int c = s->u.s.constindex; | ||
121 | if (!(0 <= c && c < currState->f->nconsts && | ||
122 | ttype(&currState->f->consts[c]) == LUA_T_STRING && | ||
123 | tsvalue(&currState->f->consts[c]) == s)) { | ||
124 | c = next_constant(); | ||
125 | ttype(&currState->f->consts[c]) = LUA_T_STRING; | ||
126 | tsvalue(&currState->f->consts[c]) = s; | ||
127 | s->u.s.constindex = c; /* hint for next time */ | ||
128 | luaI_releasestring(s); | ||
129 | } | ||
130 | return c; | ||
98 | } | 131 | } |
99 | 132 | ||
100 | static void code_word (Word n) | 133 | |
134 | static void code_string (TaggedString *s) | ||
101 | { | 135 | { |
102 | check_space(sizeof(Word)); | 136 | int c = string_constant(s); |
103 | memcpy(currState->f->code+currState->pc, &n, sizeof(Word)); | 137 | code_constant(c); |
104 | currState->pc += sizeof(Word); | ||
105 | } | 138 | } |
106 | 139 | ||
140 | static void code_float (real n) | ||
141 | { | ||
142 | int c = next_constant(); | ||
143 | ttype(&currState->f->consts[c]) = LUA_T_NUMBER; | ||
144 | nvalue(&currState->f->consts[c]) = n; | ||
145 | code_constant(c); | ||
146 | } | ||
147 | |||
148 | |||
149 | static void code_number (float f) | ||
150 | { | ||
151 | Word i; | ||
152 | if (f >= 0 && f <= (float)MAX_WORD && (float)(i=(Word)f) == f) { | ||
153 | /* f has an (short) integer value */ | ||
154 | if (i <= 2) code_byte(PUSH0 + i); | ||
155 | else if (i <= 255) | ||
156 | { | ||
157 | code_byte(PUSHBYTE); | ||
158 | code_byte(i); | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | code_byte(PUSHWORD); | ||
163 | code_word(i); | ||
164 | } | ||
165 | } | ||
166 | else | ||
167 | code_float(f); | ||
168 | } | ||
169 | |||
170 | |||
107 | static void flush_record (int n) | 171 | static void flush_record (int n) |
108 | { | 172 | { |
109 | if (n == 0) return; | 173 | if (n == 0) return; |
@@ -149,6 +213,7 @@ static void luaI_unregisterlocalvar (int line) | |||
149 | 213 | ||
150 | static void store_localvar (TaggedString *name, int n) | 214 | static void store_localvar (TaggedString *name, int n) |
151 | { | 215 | { |
216 | luaI_fixstring(name); /* local var names cannot be GC */ | ||
152 | if (currState->nlocalvar+n < MAXLOCALS) | 217 | if (currState->nlocalvar+n < MAXLOCALS) |
153 | currState->localvar[currState->nlocalvar+n] = name; | 218 | currState->localvar[currState->nlocalvar+n] = name; |
154 | else | 219 | else |
@@ -170,40 +235,6 @@ static void add_varbuffer (Long var) | |||
170 | yyerror ("variable buffer overflow"); | 235 | yyerror ("variable buffer overflow"); |
171 | } | 236 | } |
172 | 237 | ||
173 | static void code_string (Word w) | ||
174 | { | ||
175 | code_byte(PUSHSTRING); | ||
176 | code_word(w); | ||
177 | } | ||
178 | |||
179 | static void code_constant (TaggedString *s) | ||
180 | { | ||
181 | code_string(luaI_findconstant(s)); | ||
182 | } | ||
183 | |||
184 | static void code_number (float f) | ||
185 | { | ||
186 | Word i; | ||
187 | if (f >= 0 && f <= (float)MAX_WORD && (float)(i=(Word)f) == f) { | ||
188 | /* f has an (short) integer value */ | ||
189 | if (i <= 2) code_byte(PUSH0 + i); | ||
190 | else if (i <= 255) | ||
191 | { | ||
192 | code_byte(PUSHBYTE); | ||
193 | code_byte(i); | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | code_byte(PUSHWORD); | ||
198 | code_word(i); | ||
199 | } | ||
200 | } | ||
201 | else | ||
202 | { | ||
203 | code_byte(PUSHFLOAT); | ||
204 | code_float(f); | ||
205 | } | ||
206 | } | ||
207 | 238 | ||
208 | /* | 239 | /* |
209 | ** Search a local name and if find return its index. If do not find return -1 | 240 | ** Search a local name and if find return its index. If do not find return -1 |
@@ -256,55 +287,6 @@ static void lua_codeadjust (int n) | |||
256 | } | 287 | } |
257 | 288 | ||
258 | 289 | ||
259 | static void init_state (TFunc *f) | ||
260 | { | ||
261 | luaI_initTFunc(f); | ||
262 | currState->nlocalvar = 0; | ||
263 | currState->f = f; | ||
264 | currState->pc = 0; | ||
265 | currState->codesize = CODE_BLOCK; | ||
266 | f->code = newvector(CODE_BLOCK, Byte); | ||
267 | if (lua_debug) { | ||
268 | currState->nvars = 0; | ||
269 | currState->maxvars = 0; | ||
270 | } | ||
271 | else | ||
272 | currState->maxvars = -1; /* flag no debug information */ | ||
273 | } | ||
274 | |||
275 | |||
276 | static void init_func (void) | ||
277 | { | ||
278 | currState = &stateFunc; | ||
279 | init_state(new(TFunc)); | ||
280 | luaI_codedebugline(lua_linenumber); | ||
281 | } | ||
282 | |||
283 | |||
284 | static void codereturn (void) | ||
285 | { | ||
286 | if (currState->nlocalvar == 0) | ||
287 | code_byte(RETCODE0); | ||
288 | else | ||
289 | { | ||
290 | code_byte(RETCODE); | ||
291 | code_byte(currState->nlocalvar); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | |||
296 | static void close_func (void) | ||
297 | { | ||
298 | codereturn(); | ||
299 | code_byte(ENDCODE); | ||
300 | currState->f->code = shrinkvector(currState->f->code, currState->pc, Byte); | ||
301 | if (currState->maxvars != -1) { /* debug information? */ | ||
302 | luaI_registerlocalvar(NULL, -1); /* flag end of vector */ | ||
303 | currState->f->locvars = shrinkvector(currState->f->locvars, | ||
304 | currState->nvars, LocVar); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | 290 | ||
309 | void luaI_codedebugline (int line) | 291 | void luaI_codedebugline (int line) |
310 | { | 292 | { |
@@ -350,7 +332,7 @@ static int close_parlist (int dots) | |||
350 | else { | 332 | else { |
351 | code_byte(VARARGS); | 333 | code_byte(VARARGS); |
352 | code_byte(currState->nlocalvar); | 334 | code_byte(currState->nlocalvar); |
353 | add_localvar(luaI_createfixedstring("arg")); | 335 | add_localvar(luaI_createstring("arg")); |
354 | } | 336 | } |
355 | return lua_linenumber; | 337 | return lua_linenumber; |
356 | } | 338 | } |
@@ -423,6 +405,65 @@ static void code_shortcircuit (int pc, Byte jmp) | |||
423 | } | 405 | } |
424 | 406 | ||
425 | 407 | ||
408 | static void init_state (TFunc *f) | ||
409 | { | ||
410 | currState->nlocalvar = 0; | ||
411 | currState->f = f; | ||
412 | currState->pc = 0; | ||
413 | currState->codesize = CODE_BLOCK; | ||
414 | f->code = newvector(CODE_BLOCK, Byte); | ||
415 | currState->maxconsts = 0; | ||
416 | if (lua_debug) { | ||
417 | currState->nvars = 0; | ||
418 | currState->maxvars = 0; | ||
419 | } | ||
420 | else | ||
421 | currState->maxvars = -1; /* flag no debug information */ | ||
422 | } | ||
423 | |||
424 | |||
425 | static void init_func (Long v) | ||
426 | { | ||
427 | TFunc *f = new(TFunc); | ||
428 | int c = next_constant(); | ||
429 | ttype(&currState->f->consts[c]) = LUA_T_FUNCTION; | ||
430 | currState->f->consts[c].value.tf = f; | ||
431 | code_constant(c); | ||
432 | storesinglevar(v); | ||
433 | currState = &stateFunc; | ||
434 | luaI_initTFunc(f); | ||
435 | init_state(f); | ||
436 | luaI_codedebugline(lua_linenumber); | ||
437 | } | ||
438 | |||
439 | |||
440 | static void codereturn (void) | ||
441 | { | ||
442 | if (currState->nlocalvar == 0) | ||
443 | code_byte(RETCODE0); | ||
444 | else | ||
445 | { | ||
446 | code_byte(RETCODE); | ||
447 | code_byte(currState->nlocalvar); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | |||
452 | static void close_func (void) | ||
453 | { | ||
454 | codereturn(); | ||
455 | code_byte(ENDCODE); | ||
456 | currState->f->code = shrinkvector(currState->f->code, currState->pc, Byte); | ||
457 | currState->f->consts = shrinkvector(currState->f->consts, | ||
458 | currState->f->nconsts, TObject); | ||
459 | if (currState->maxvars != -1) { /* debug information? */ | ||
460 | luaI_registerlocalvar(NULL, -1); /* flag end of vector */ | ||
461 | currState->f->locvars = shrinkvector(currState->f->locvars, | ||
462 | currState->nvars, LocVar); | ||
463 | } | ||
464 | } | ||
465 | |||
466 | |||
426 | /* | 467 | /* |
427 | ** Parse LUA code. | 468 | ** Parse LUA code. |
428 | */ | 469 | */ |
@@ -444,9 +485,7 @@ void lua_parse (TFunc *tf) | |||
444 | int vInt; | 485 | int vInt; |
445 | float vFloat; | 486 | float vFloat; |
446 | char *pChar; | 487 | char *pChar; |
447 | Word vWord; | ||
448 | Long vLong; | 488 | Long vLong; |
449 | TFunc *pFunc; | ||
450 | TaggedString *pTStr; | 489 | TaggedString *pTStr; |
451 | } | 490 | } |
452 | 491 | ||
@@ -460,8 +499,7 @@ void lua_parse (TFunc *tf) | |||
460 | %token FUNCTION | 499 | %token FUNCTION |
461 | %token DOTS | 500 | %token DOTS |
462 | %token <vFloat> NUMBER | 501 | %token <vFloat> NUMBER |
463 | %token <vWord> STRING | 502 | %token <pTStr> NAME STRING |
464 | %token <pTStr> NAME | ||
465 | 503 | ||
466 | %type <vLong> PrepJump | 504 | %type <vLong> PrepJump |
467 | %type <vLong> exprlist, exprlist1 /* if > 0, points to function return | 505 | %type <vLong> exprlist, exprlist1 /* if > 0, points to function return |
@@ -473,8 +511,7 @@ void lua_parse (TFunc *tf) | |||
473 | %type <vInt> ffieldlist, ffieldlist1, semicolonpart | 511 | %type <vInt> ffieldlist, ffieldlist1, semicolonpart |
474 | %type <vInt> lfieldlist, lfieldlist1 | 512 | %type <vInt> lfieldlist, lfieldlist1 |
475 | %type <vInt> parlist, parlist1, par | 513 | %type <vInt> parlist, parlist1, par |
476 | %type <vLong> var, singlevar, funcname | 514 | %type <vLong> var, singlevar |
477 | %type <pFunc> body | ||
478 | 515 | ||
479 | %left AND OR | 516 | %left AND OR |
480 | %left EQ NE '>' '<' LE GE | 517 | %left EQ NE '>' '<' LE GE |
@@ -495,28 +532,21 @@ chunklist : /* empty */ | |||
495 | ; | 532 | ; |
496 | 533 | ||
497 | function : FUNCTION funcname body | 534 | function : FUNCTION funcname body |
498 | { | ||
499 | code_byte(PUSHFUNCTION); | ||
500 | code_code($3); | ||
501 | storesinglevar($2); | ||
502 | } | ||
503 | ; | 535 | ; |
504 | 536 | ||
505 | funcname : var { $$ =$1; init_func(); } | 537 | funcname : var { init_func($1); } |
506 | | varexp ':' NAME | 538 | | varexp ':' NAME |
507 | { | 539 | { |
508 | code_constant($3); | 540 | code_string($3); |
509 | $$ = 0; /* indexed variable */ | 541 | init_func(0); /* indexed variable */ |
510 | init_func(); | 542 | add_localvar(luaI_createstring("self")); |
511 | add_localvar(luaI_createfixedstring("self")); | ||
512 | } | 543 | } |
513 | ; | 544 | ; |
514 | 545 | ||
515 | body : '(' parlist ')' block END | 546 | body : '(' parlist ')' block END |
516 | { | 547 | { |
517 | close_func(); | 548 | close_func(); |
518 | $$ = currState->f; | 549 | currState->f->lineDefined = $2; |
519 | $$->lineDefined = $2; | ||
520 | currState = &stateMain; /* change back to main code */ | 550 | currState = &stateMain; /* change back to main code */ |
521 | } | 551 | } |
522 | ; | 552 | ; |
@@ -658,7 +688,7 @@ funcvalue : varexp { $$ = 0; } | |||
658 | | varexp ':' NAME | 688 | | varexp ':' NAME |
659 | { | 689 | { |
660 | code_byte(PUSHSELF); | 690 | code_byte(PUSHSELF); |
661 | code_word(luaI_findconstant($3)); | 691 | code_word(string_constant($3)); |
662 | $$ = 1; | 692 | $$ = 1; |
663 | } | 693 | } |
664 | ; | 694 | ; |
@@ -735,7 +765,7 @@ ffield : ffieldkey '=' expr1 | |||
735 | ; | 765 | ; |
736 | 766 | ||
737 | ffieldkey : '[' expr1 ']' | 767 | ffieldkey : '[' expr1 ']' |
738 | | NAME { code_constant($1); } | 768 | | NAME { code_string($1); } |
739 | ; | 769 | ; |
740 | 770 | ||
741 | lfieldlist : /* empty */ { $$ = 0; } | 771 | lfieldlist : /* empty */ { $$ = 0; } |
@@ -771,7 +801,7 @@ var : singlevar { $$ = $1; } | |||
771 | } | 801 | } |
772 | | varexp '.' NAME | 802 | | varexp '.' NAME |
773 | { | 803 | { |
774 | code_constant($3); | 804 | code_string($3); |
775 | $$ = 0; /* indexed variable */ | 805 | $$ = 0; /* indexed variable */ |
776 | } | 806 | } |
777 | ; | 807 | ; |
@@ -783,6 +813,7 @@ singlevar : NAME | |||
783 | $$ = luaI_findsymbol($1)+1; /* return positive value */ | 813 | $$ = luaI_findsymbol($1)+1; /* return positive value */ |
784 | else | 814 | else |
785 | $$ = -(local+1); /* return negative value */ | 815 | $$ = -(local+1); /* return negative value */ |
816 | luaI_fixstring($1); /* cannot GC variable names */ | ||
786 | } | 817 | } |
787 | ; | 818 | ; |
788 | 819 | ||