aboutsummaryrefslogtreecommitdiff
path: root/lua.stx
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-07-29 17:38:45 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-07-29 17:38:45 -0300
commit2c580a0afb8dbaf7070a9819b7e81ebde5737ff9 (patch)
tree6fd261bb3bd89e2b851cd1adaa290c17a6dcad67 /lua.stx
parent05e8b0ae80bbeaf41ea849e9eff5d05074093560 (diff)
downloadlua-2c580a0afb8dbaf7070a9819b7e81ebde5737ff9.tar.gz
lua-2c580a0afb8dbaf7070a9819b7e81ebde5737ff9.tar.bz2
lua-2c580a0afb8dbaf7070a9819b7e81ebde5737ff9.zip
new way to handle global state during compilation.
Diffstat (limited to 'lua.stx')
-rw-r--r--lua.stx309
1 files changed, 161 insertions, 148 deletions
diff --git a/lua.stx b/lua.stx
index eb988675..9f6e56f3 100644
--- a/lua.stx
+++ b/lua.stx
@@ -1,6 +1,6 @@
1%{ 1%{
2 2
3char *rcs_luastx = "$Id: lua.stx,v 3.46 1997/03/31 14:19:01 roberto Exp roberto $"; 3char *rcs_luastx = "$Id: lua.stx,v 3.47 1997/06/19 17:46:12 roberto Exp roberto $";
4 4
5#include <stdio.h> 5#include <stdio.h>
6#include <stdlib.h> 6#include <stdlib.h>
@@ -28,16 +28,21 @@ int yyparse (void);
28#endif 28#endif
29 29
30#ifndef CODE_BLOCK 30#ifndef CODE_BLOCK
31#define CODE_BLOCK 256 31#define CODE_BLOCK 1000
32#endif 32#endif
33static int maxcode; 33
34static int maxmain; 34#define MAXLOCALS 32
35static int maxcurr; 35
36static Byte *funcCode = NULL; 36/* state needed to generate code for a given function */
37static Byte **initcode; 37struct State {
38static Byte *basepc; 38 TFunc *f; /* current function header */
39static int maincode; 39 int codesize;
40static int pc; 40 int pc; /* next position to code */
41 TaggedString *localvar[MAXLOCALS]; /* store local variable names */
42 int nlocalvar; /* number of active local variables */
43 int nvars; /* total number of local variables (for debugging information) */
44 int maxvars; /* = -1 if no debug information */
45} stateMain, stateFunc, *currState;
41 46
42 47
43#define MAXVAR 32 48#define MAXVAR 32
@@ -45,9 +50,6 @@ static Long varbuffer[MAXVAR]; /* variables in an assignment list;
45 it's long to store negative Word values */ 50 it's long to store negative Word values */
46static int nvarbuffer=0; /* number of variables at a list */ 51static int nvarbuffer=0; /* number of variables at a list */
47 52
48#define MAXLOCALS 32
49static TaggedString *localvar[MAXLOCALS]; /* store local variable names */
50static int nlocalvar=0; /* number of local variables */
51 53
52#define MAXFIELDS FIELDS_PER_FLUSH*2 54#define MAXFIELDS FIELDS_PER_FLUSH*2
53 55
@@ -62,43 +64,44 @@ static void yyerror (char *s)
62 64
63static void check_space (int i) 65static void check_space (int i)
64{ 66{
65 if (pc+i>maxcurr-1) /* 1 byte free to code HALT of main code */ 67 if (currState->pc+i >= currState->codesize)
66 maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT); 68 currState->codesize = growvector(&currState->f->code, currState->codesize,
69 Byte, codeEM, MAX_INT);
67} 70}
68 71
69static void code_byte (Byte c) 72static void code_byte (Byte c)
70{ 73{
71 check_space(1); 74 check_space(1);
72 basepc[pc++] = c; 75 currState->f->code[currState->pc++] = c;
73}
74
75static void code_word (Word n)
76{
77 check_space(sizeof(Word));
78 memcpy(basepc+pc, &n, sizeof(Word));
79 pc += sizeof(Word);
80} 76}
81 77
82static void code_float (real n) 78static void code_float (real n)
83{ 79{
84 check_space(sizeof(real)); 80 check_space(sizeof(real));
85 memcpy(basepc+pc, &n, sizeof(real)); 81 memcpy(currState->f->code+currState->pc, &n, sizeof(real));
86 pc += sizeof(real); 82 currState->pc += sizeof(real);
87} 83}
88 84
89static void code_code (TFunc *tf) 85static void code_code (TFunc *tf)
90{ 86{
91 check_space(sizeof(TFunc *)); 87 check_space(sizeof(TFunc *));
92 memcpy(basepc+pc, &tf, sizeof(TFunc *)); 88 memcpy(currState->f->code+currState->pc, &tf, sizeof(TFunc *));
93 pc += sizeof(TFunc *); 89 currState->pc += sizeof(TFunc *);
94} 90}
95 91
96static void code_word_at (Byte *p, int n) 92static void code_word_at (int pc, int n)
97{ 93{
98 Word w = n; 94 Word w = n;
99 if (w != n) 95 if (w != n)
100 yyerror("block too big"); 96 yyerror("block too big");
101 memcpy(p, &w, sizeof(Word)); 97 memcpy(currState->f->code+pc, &w, sizeof(Word));
98}
99
100static void code_word (Word n)
101{
102 check_space(sizeof(Word));
103 memcpy(currState->f->code+currState->pc, &n, sizeof(Word));
104 currState->pc += sizeof(Word);
102} 105}
103 106
104static void flush_record (int n) 107static void flush_record (int n)
@@ -124,20 +127,39 @@ static void flush_list (int m, int n)
124 code_byte(n); 127 code_byte(n);
125} 128}
126 129
130
131static void luaI_registerlocalvar (TaggedString *varname, int line)
132{
133 if (currState->maxvars != -1) { /* debug information? */
134 if (currState->nvars >= currState->maxvars)
135 currState->maxvars = growvector(&currState->f->locvars,
136 currState->maxvars, LocVar, "", MAX_WORD);
137 currState->f->locvars[currState->nvars].varname = varname;
138 currState->f->locvars[currState->nvars].line = line;
139 currState->nvars++;
140 }
141}
142
143
144static void luaI_unregisterlocalvar (int line)
145{
146 luaI_registerlocalvar(NULL, line);
147}
148
149
127static void store_localvar (TaggedString *name, int n) 150static void store_localvar (TaggedString *name, int n)
128{ 151{
129 if (nlocalvar+n < MAXLOCALS) 152 if (currState->nlocalvar+n < MAXLOCALS)
130 localvar[nlocalvar+n] = name; 153 currState->localvar[currState->nlocalvar+n] = name;
131 else 154 else
132 yyerror ("too many local variables"); 155 yyerror ("too many local variables");
133 if (lua_debug) 156 luaI_registerlocalvar(name, lua_linenumber);
134 luaI_registerlocalvar(name, lua_linenumber);
135} 157}
136 158
137static void add_localvar (TaggedString *name) 159static void add_localvar (TaggedString *name)
138{ 160{
139 store_localvar(name, 0); 161 store_localvar(name, 0);
140 nlocalvar++; 162 currState->nlocalvar++;
141} 163}
142 164
143static void add_varbuffer (Long var) 165static void add_varbuffer (Long var)
@@ -189,9 +211,9 @@ static void code_number (float f)
189static int lua_localname (TaggedString *n) 211static int lua_localname (TaggedString *n)
190{ 212{
191 int i; 213 int i;
192 for (i=nlocalvar-1; i >= 0; i--) 214 for (i=currState->nlocalvar-1; i >= 0; i--)
193 if (n == localvar[i]) return i; /* local var */ 215 if (n == currState->localvar[i]) return i; /* local var */
194 return -1; /* global var */ 216 return -1; /* global var */
195} 217}
196 218
197/* 219/*
@@ -224,53 +246,66 @@ static void lua_pushvar (Long number)
224 246
225static void lua_codeadjust (int n) 247static void lua_codeadjust (int n)
226{ 248{
227 if (n+nlocalvar == 0) 249 n += currState->nlocalvar;
228 code_byte(ADJUST0); 250 if (n == 0)
229 else 251 code_byte(ADJUST0);
230 { 252 else {
231 code_byte(ADJUST); 253 code_byte(ADJUST);
232 code_byte(n+nlocalvar); 254 code_byte(n);
233 } 255 }
234} 256}
235 257
236static void change2main (void)
237{
238 /* (re)store main values */
239 pc=maincode; basepc=*initcode; maxcurr=maxmain;
240 nlocalvar=0;
241}
242 258
243static void savemain (void) 259static void init_state (TFunc *f)
244{ 260{
245 /* save main values */ 261 luaI_initTFunc(f);
246 maincode=pc; *initcode=basepc; maxmain=maxcurr; 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 */
247} 273}
248 274
275
249static void init_func (void) 276static void init_func (void)
250{ 277{
251 if (funcCode == NULL) /* first function */ 278 currState = &stateFunc;
252 { 279 init_state(new(TFunc));
253 funcCode = newvector(CODE_BLOCK, Byte);
254 maxcode = CODE_BLOCK;
255 }
256 savemain(); /* save main values */
257 /* set func values */
258 pc=0; basepc=funcCode; maxcurr=maxcode;
259 nlocalvar = 0;
260 luaI_codedebugline(lua_linenumber); 280 luaI_codedebugline(lua_linenumber);
261} 281}
262 282
283
263static void codereturn (void) 284static void codereturn (void)
264{ 285{
265 if (nlocalvar == 0) 286 if (currState->nlocalvar == 0)
266 code_byte(RETCODE0); 287 code_byte(RETCODE0);
267 else 288 else
268 { 289 {
269 code_byte(RETCODE); 290 code_byte(RETCODE);
270 code_byte(nlocalvar); 291 code_byte(currState->nlocalvar);
292 }
293}
294
295
296static 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);
271 } 305 }
272} 306}
273 307
308
274void luaI_codedebugline (int line) 309void luaI_codedebugline (int line)
275{ 310{
276 static int lastline = 0; 311 static int lastline = 0;
@@ -286,23 +321,20 @@ static int adjust_functioncall (Long exp, int i)
286{ 321{
287 if (exp <= 0) 322 if (exp <= 0)
288 return -exp; /* exp is -list length */ 323 return -exp; /* exp is -list length */
289 else 324 else {
290 { 325 int temp = currState->f->code[exp];
291 int temp = basepc[exp]; 326 currState->f->code[exp] = i;
292 basepc[exp] = i;
293 return temp+i; 327 return temp+i;
294 } 328 }
295} 329}
296 330
297static void adjust_mult_assign (int vars, Long exps, int temps) 331static void adjust_mult_assign (int vars, Long exps, int temps)
298{ 332{
299 if (exps > 0) 333 if (exps > 0) { /* must correct function call */
300 { /* must correct function call */ 334 int diff = vars - currState->f->code[exps];
301 int diff = vars - basepc[exps];
302 if (diff >= 0) 335 if (diff >= 0)
303 adjust_functioncall(exps, diff); 336 adjust_functioncall(exps, diff);
304 else 337 else {
305 {
306 adjust_functioncall(exps, 0); 338 adjust_functioncall(exps, 0);
307 lua_codeadjust(temps); 339 lua_codeadjust(temps);
308 } 340 }
@@ -315,15 +347,15 @@ static int close_parlist (int dots)
315{ 347{
316 if (!dots) 348 if (!dots)
317 lua_codeadjust(0); 349 lua_codeadjust(0);
318 else 350 else {
319 {
320 code_byte(VARARGS); 351 code_byte(VARARGS);
321 code_byte(nlocalvar); 352 code_byte(currState->nlocalvar);
322 add_localvar(luaI_createfixedstring("arg")); 353 add_localvar(luaI_createfixedstring("arg"));
323 } 354 }
324 return lua_linenumber; 355 return lua_linenumber;
325} 356}
326 357
358
327static void storesinglevar (Long v) 359static void storesinglevar (Long v)
328{ 360{
329 if (v > 0) /* global var */ 361 if (v > 0) /* global var */
@@ -345,6 +377,7 @@ static void storesinglevar (Long v)
345 code_byte(STOREINDEXED0); 377 code_byte(STOREINDEXED0);
346} 378}
347 379
380
348static void lua_codestore (int i) 381static void lua_codestore (int i)
349{ 382{
350 if (varbuffer[i] != 0) /* global or local var */ 383 if (varbuffer[i] != 0) /* global or local var */
@@ -370,18 +403,23 @@ static void lua_codestore (int i)
370static void codeIf (Long thenAdd, Long elseAdd) 403static void codeIf (Long thenAdd, Long elseAdd)
371{ 404{
372 Long elseinit = elseAdd+sizeof(Word)+1; 405 Long elseinit = elseAdd+sizeof(Word)+1;
373 if (pc == elseinit) /* no else */ 406 if (currState->pc == elseinit) { /* no else */
374 { 407 currState->pc -= sizeof(Word)+1;
375 pc -= sizeof(Word)+1; 408 elseinit = currState->pc;
376 elseinit = pc;
377 } 409 }
378 else 410 else {
379 { 411 currState->f->code[elseAdd] = JMP;
380 basepc[elseAdd] = JMP; 412 code_word_at(elseAdd+1, currState->pc-elseinit);
381 code_word_at(basepc+elseAdd+1, pc-elseinit);
382 } 413 }
383 basepc[thenAdd] = IFFJMP; 414 currState->f->code[thenAdd] = IFFJMP;
384 code_word_at(basepc+thenAdd+1,elseinit-(thenAdd+sizeof(Word)+1)); 415 code_word_at(thenAdd+1, elseinit-(thenAdd+sizeof(Word)+1));
416}
417
418
419static void code_shortcircuit (int pc, Byte jmp)
420{
421 currState->f->code[pc] = jmp;
422 code_word_at(pc+1, currState->pc - (pc + sizeof(Word)+1));
385} 423}
386 424
387 425
@@ -390,19 +428,11 @@ static void codeIf (Long thenAdd, Long elseAdd)
390*/ 428*/
391void lua_parse (TFunc *tf) 429void lua_parse (TFunc *tf)
392{ 430{
393 initcode = &(tf->code); 431 currState = &stateMain;
394 *initcode = newvector(CODE_BLOCK, Byte); 432 init_state(tf);
395 maincode = 0; 433 if (yyparse ()) lua_error("parse error");
396 maxmain = CODE_BLOCK; 434 currState = &stateMain;
397 change2main(); 435 close_func();
398 if (yyparse ()) lua_error("parse error");
399 savemain();
400 (*initcode)[maincode++] = RETCODE0;
401 tf->size = maincode;
402#if LISTING
403{ static void PrintCode (Byte *c, Byte *end);
404 PrintCode(*initcode,*initcode+maincode); }
405#endif
406} 436}
407 437
408 438
@@ -484,21 +514,10 @@ funcname : var { $$ =$1; init_func(); }
484 514
485body : '(' parlist ')' block END 515body : '(' parlist ')' block END
486 { 516 {
487 codereturn(); 517 close_func();
488 $$ = new(TFunc); 518 $$ = currState->f;
489 luaI_initTFunc($$);
490 $$->size = pc;
491 $$->code = newvector(pc, Byte);
492 $$->lineDefined = $2; 519 $$->lineDefined = $2;
493 memcpy($$->code, basepc, pc*sizeof(Byte)); 520 currState = &stateMain; /* change back to main code */
494 if (lua_debug)
495 luaI_closelocalvars($$);
496 /* save func values */
497 funcCode = basepc; maxcode=maxcurr;
498#if LISTING
499 PrintCode(funcCode,funcCode+pc);
500#endif
501 change2main(); /* change back to main code */
502 } 521 }
503 ; 522 ;
504 523
@@ -511,18 +530,18 @@ sc : /* empty */ | ';' ;
511stat : IF expr1 THEN PrepJump block PrepJump elsepart END 530stat : IF expr1 THEN PrepJump block PrepJump elsepart END
512 { codeIf($4, $6); } 531 { codeIf($4, $6); }
513 532
514 | WHILE {$<vLong>$=pc;} expr1 DO PrepJump block PrepJump END 533 | WHILE {$<vLong>$=currState->pc;} expr1 DO PrepJump block PrepJump END
515 { 534 {
516 basepc[$5] = IFFJMP; 535 currState->f->code[$5] = IFFJMP;
517 code_word_at(basepc+$5+1, pc - ($5 + sizeof(Word)+1)); 536 code_word_at($5+1, currState->pc - ($5+sizeof(Word)+1));
518 basepc[$7] = UPJMP; 537 currState->f->code[$7] = UPJMP;
519 code_word_at(basepc+$7+1, pc - ($<vLong>2)); 538 code_word_at($7+1, currState->pc - ($<vLong>2));
520 } 539 }
521 540
522 | REPEAT {$<vLong>$=pc;} block UNTIL expr1 PrepJump 541 | REPEAT {$<vLong>$=currState->pc;} block UNTIL expr1 PrepJump
523 { 542 {
524 basepc[$6] = IFFUPJMP; 543 currState->f->code[$6] = IFFUPJMP;
525 code_word_at(basepc+$6+1, pc - ($<vLong>2)); 544 code_word_at($6+1, currState->pc - ($<vLong>2));
526 } 545 }
527 546
528 | varlist1 '=' exprlist1 547 | varlist1 '=' exprlist1
@@ -531,14 +550,14 @@ stat : IF expr1 THEN PrepJump block PrepJump elsepart END
531 int i; 550 int i;
532 adjust_mult_assign(nvarbuffer, $3, $1 * 2 + nvarbuffer); 551 adjust_mult_assign(nvarbuffer, $3, $1 * 2 + nvarbuffer);
533 for (i=nvarbuffer-1; i>=0; i--) 552 for (i=nvarbuffer-1; i>=0; i--)
534 lua_codestore (i); 553 lua_codestore(i);
535 if ($1 > 1 || ($1 == 1 && varbuffer[0] != 0)) 554 if ($1 > 1 || ($1 == 1 && varbuffer[0] != 0))
536 lua_codeadjust (0); 555 lua_codeadjust(0);
537 } 556 }
538 } 557 }
539 | functioncall {;} 558 | functioncall {;}
540 | LOCAL localdeclist decinit 559 | LOCAL localdeclist decinit
541 { nlocalvar += $2; 560 { currState->nlocalvar += $2;
542 adjust_mult_assign($2, $3, 0); 561 adjust_mult_assign($2, $3, 0);
543 } 562 }
544 ; 563 ;
@@ -549,17 +568,13 @@ elsepart : /* empty */
549 { codeIf($4, $6); } 568 { codeIf($4, $6); }
550 ; 569 ;
551 570
552block : {$<vInt>$ = nlocalvar;} statlist ret 571block : {$<vInt>$ = currState->nlocalvar;} statlist ret
553 { 572 {
554 if (nlocalvar != $<vInt>1) 573 if (currState->nlocalvar != $<vInt>1) {
555 { 574 for (; currState->nlocalvar > $<vInt>1; currState->nlocalvar--)
556 if (lua_debug) 575 luaI_unregisterlocalvar(lua_linenumber);
557 for (; nlocalvar > $<vInt>1; nlocalvar--) 576 lua_codeadjust(0);
558 luaI_unregisterlocalvar(lua_linenumber); 577 }
559 else
560 nlocalvar = $<vInt>1;
561 lua_codeadjust (0);
562 }
563 } 578 }
564 ; 579 ;
565 580
@@ -573,9 +588,9 @@ ret : /* empty */
573 588
574PrepJump : /* empty */ 589PrepJump : /* empty */
575 { 590 {
576 $$ = pc; 591 $$ = currState->pc;
577 code_byte(0); /* open space */ 592 code_byte(0); /* open space */
578 code_word (0); 593 code_word(0);
579 } 594 }
580 ; 595 ;
581 596
@@ -609,26 +624,24 @@ expr : '(' expr ')' { $$ = $2; }
609 | NOT expr1 { code_byte(NOTOP); $$ = 0;} 624 | NOT expr1 { code_byte(NOTOP); $$ = 0;}
610 | expr1 AND PrepJump {code_byte(POP); } expr1 625 | expr1 AND PrepJump {code_byte(POP); } expr1
611 { 626 {
612 basepc[$3] = ONFJMP; 627 code_shortcircuit($3, ONFJMP);
613 code_word_at(basepc+$3+1, pc - ($3 + sizeof(Word)+1)); 628 $$ = 0;
614 $$ = 0;
615 } 629 }
616 | expr1 OR PrepJump {code_byte(POP); } expr1 630 | expr1 OR PrepJump {code_byte(POP); } expr1
617 { 631 {
618 basepc[$3] = ONTJMP; 632 code_shortcircuit($3, ONTJMP);
619 code_word_at(basepc+$3+1, pc - ($3 + sizeof(Word)+1)); 633 $$ = 0;
620 $$ = 0;
621 } 634 }
622 ; 635 ;
623 636
624table : 637table :
625 { 638 {
626 code_byte(CREATEARRAY); 639 code_byte(CREATEARRAY);
627 $<vLong>$ = pc; code_word(0); 640 $<vLong>$ = currState->pc; code_word(0);
628 } 641 }
629 '{' fieldlist '}' 642 '{' fieldlist '}'
630 { 643 {
631 code_word_at(basepc+$<vLong>1, $3); 644 code_word_at($<vLong>1, $3);
632 } 645 }
633 ; 646 ;
634 647
@@ -636,7 +649,7 @@ functioncall : funcvalue funcParams
636 { 649 {
637 code_byte(CALLFUNC); 650 code_byte(CALLFUNC);
638 code_byte($1+$2); 651 code_byte($1+$2);
639 $$ = pc; 652 $$ = currState->pc;
640 code_byte(0); /* may be modified by other rules */ 653 code_byte(0); /* may be modified by other rules */
641 } 654 }
642 ; 655 ;