diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-29 14:31:15 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-29 14:31:15 -0200 |
commit | 298d0abff7f292fa4bfbdb40979f41bc8f80f9c2 (patch) | |
tree | 457d98c07a17f99a6fee012d49d5191c4c4bf665 /lparser.c | |
parent | 4fbe775154ff281bf9c04cf92d68824a82593402 (diff) | |
download | lua-298d0abff7f292fa4bfbdb40979f41bc8f80f9c2.tar.gz lua-298d0abff7f292fa4bfbdb40979f41bc8f80f9c2.tar.bz2 lua-298d0abff7f292fa4bfbdb40979f41bc8f80f9c2.zip |
first version of extra debug information (NAME)
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 1035 |
1 files changed, 549 insertions, 486 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.49 1999/12/22 16:58:36 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.50 1999/12/23 18:19:57 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 | */ |
@@ -63,6 +63,8 @@ typedef enum { | |||
63 | typedef struct vardesc { | 63 | typedef struct vardesc { |
64 | varkind k; | 64 | varkind k; |
65 | int info; | 65 | int info; |
66 | varkind prev_k; /* for debug information (NAMEs) */ | ||
67 | int prev_info; | ||
66 | } vardesc; | 68 | } vardesc; |
67 | 69 | ||
68 | 70 | ||
@@ -70,7 +72,7 @@ typedef struct vardesc { | |||
70 | ** Expression List descriptor: | 72 | ** Expression List descriptor: |
71 | ** tells number of expressions in the list, | 73 | ** tells number of expressions in the list, |
72 | ** and, if last expression is open (a function call), | 74 | ** and, if last expression is open (a function call), |
73 | ** where is its pc index of "nparam" | 75 | ** where is its pc index of `nparam' |
74 | */ | 76 | */ |
75 | typedef struct listdesc { | 77 | typedef struct listdesc { |
76 | int n; | 78 | int n; |
@@ -93,7 +95,7 @@ typedef struct constdesc { | |||
93 | /* state needed to generate code for a given function */ | 95 | /* state needed to generate code for a given function */ |
94 | typedef struct FuncState { | 96 | typedef struct FuncState { |
95 | TProtoFunc *f; /* current function header */ | 97 | TProtoFunc *f; /* current function header */ |
96 | struct FuncState *prev; /* enclosuring function */ | 98 | struct FuncState *prev; /* enclosing function */ |
97 | int pc; /* next position to code */ | 99 | int pc; /* next position to code */ |
98 | int stacksize; /* number of values on activation register */ | 100 | int stacksize; /* number of values on activation register */ |
99 | int maxstacksize; /* maximum number of values on activation register */ | 101 | int maxstacksize; /* maximum number of values on activation register */ |
@@ -107,34 +109,13 @@ typedef struct FuncState { | |||
107 | 109 | ||
108 | 110 | ||
109 | /* | 111 | /* |
110 | ** prototypes for non-terminal functions | 112 | ** prototypes for recursive non-terminal functions |
111 | */ | 113 | */ |
112 | static int assignment (LexState *ls, vardesc *v, int nvars); | ||
113 | static int cond (LexState *ls); | ||
114 | static int funcname (LexState *ls, vardesc *v); | ||
115 | static int funcparams (LexState *ls, int slf); | ||
116 | static int listfields (LexState *ls); | ||
117 | static int localnamelist (LexState *ls); | ||
118 | static int optional (LexState *ls, int c); | ||
119 | static int recfields (LexState *ls); | ||
120 | static int stat (LexState *ls); | ||
121 | static void block (LexState *ls); | ||
122 | static void body (LexState *ls, int needself, int line); | 114 | static void body (LexState *ls, int needself, int line); |
123 | static void chunk (LexState *ls); | 115 | static void chunk (LexState *ls); |
124 | static void constructor (LexState *ls); | 116 | static void constructor (LexState *ls); |
125 | static void decinit (LexState *ls, listdesc *d); | 117 | static void exp (LexState *ls, vardesc *v); |
126 | static void exp0 (LexState *ls, vardesc *v); | ||
127 | static void exp1 (LexState *ls); | 118 | static void exp1 (LexState *ls); |
128 | static void exp2 (LexState *ls, vardesc *v); | ||
129 | static void explist (LexState *ls, listdesc *e); | ||
130 | static void explist1 (LexState *ls, listdesc *e); | ||
131 | static void ifpart (LexState *ls, int line); | ||
132 | static void parlist (LexState *ls); | ||
133 | static void part (LexState *ls, constdesc *cd); | ||
134 | static void recfield (LexState *ls); | ||
135 | static void ret (LexState *ls); | ||
136 | static void var_or_func (LexState *ls, vardesc *v); | ||
137 | static void var_or_func_tail (LexState *ls, vardesc *v); | ||
138 | 119 | ||
139 | 120 | ||
140 | 121 | ||
@@ -268,7 +249,7 @@ static void code_string (LexState *ls, TaggedString *s) { | |||
268 | 249 | ||
269 | #define LIM 20 | 250 | #define LIM 20 |
270 | static int real_constant (LexState *ls, real r) { | 251 | static int real_constant (LexState *ls, real r) { |
271 | /* check whether 'r' has appeared within the last LIM entries */ | 252 | /* check whether `r' has appeared within the last LIM entries */ |
272 | TProtoFunc *f = ls->fs->f; | 253 | TProtoFunc *f = ls->fs->f; |
273 | TObject *cnt = f->consts; | 254 | TObject *cnt = f->consts; |
274 | int c = f->nconsts; | 255 | int c = f->nconsts; |
@@ -279,7 +260,7 @@ static int real_constant (LexState *ls, real r) { | |||
279 | } | 260 | } |
280 | /* not found; create a new entry */ | 261 | /* not found; create a new entry */ |
281 | c = next_constant(ls, f); | 262 | c = next_constant(ls, f); |
282 | cnt = f->consts; /* 'next_constant' may reallocate this vector */ | 263 | cnt = f->consts; /* `next_constant' may reallocate this vector */ |
283 | ttype(&cnt[c]) = LUA_T_NUMBER; | 264 | ttype(&cnt[c]) = LUA_T_NUMBER; |
284 | nvalue(&cnt[c]) = r; | 265 | nvalue(&cnt[c]) = r; |
285 | return c; | 266 | return c; |
@@ -412,6 +393,31 @@ static void check_debugline (LexState *ls) { | |||
412 | } | 393 | } |
413 | 394 | ||
414 | 395 | ||
396 | static void code_setname (LexState *ls, const vardesc *v) { | ||
397 | if (ls->L->debug) { | ||
398 | switch (v->prev_k) { | ||
399 | case VGLOBAL: | ||
400 | code_oparg(ls, SETNAME, v->prev_info, 0); | ||
401 | code_byte(ls, -LUA_T_NGLOBAL); | ||
402 | break; | ||
403 | case VLOCAL: { | ||
404 | TaggedString *varname = ls->fs->localvar[v->prev_info]; | ||
405 | code_oparg(ls, SETNAME, string_constant(ls, ls->fs, varname), 0); | ||
406 | code_byte(ls, -LUA_T_NLOCAL); | ||
407 | break; | ||
408 | } | ||
409 | case VDOT: | ||
410 | code_oparg(ls, SETNAME, v->prev_info, 0); | ||
411 | code_byte(ls, -LUA_T_NDOT); | ||
412 | break; | ||
413 | default: /* VINDEXED or VEXP: no debug information */ | ||
414 | code_oparg(ls, SETNAME, 0, 0); | ||
415 | code_byte(ls, -LUA_T_NIL); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | |||
420 | |||
415 | static void adjuststack (LexState *ls, int n) { | 421 | static void adjuststack (LexState *ls, int n) { |
416 | if (n > 0) | 422 | if (n > 0) |
417 | code_oparg(ls, POP, n, -n); | 423 | code_oparg(ls, POP, n, -n); |
@@ -468,7 +474,7 @@ static void code_args (LexState *ls, int nparams, int dots) { | |||
468 | 474 | ||
469 | 475 | ||
470 | static void unloaddot (LexState *ls, vardesc *v) { | 476 | static void unloaddot (LexState *ls, vardesc *v) { |
471 | /* dotted variables <a.x> must be stored like regular indexed vars <a["x"]> */ | 477 | /* dotted variables <a.x> must be stored as regular indexed vars <a["x"]> */ |
472 | if (v->k == VDOT) { | 478 | if (v->k == VDOT) { |
473 | code_constant(ls, v->info); | 479 | code_constant(ls, v->info); |
474 | v->k = VINDEXED; | 480 | v->k = VINDEXED; |
@@ -486,15 +492,19 @@ static void lua_pushvar (LexState *ls, vardesc *var) { | |||
486 | assertglobal(ls, var->info); /* make sure that there is a global */ | 492 | assertglobal(ls, var->info); /* make sure that there is a global */ |
487 | break; | 493 | break; |
488 | case VDOT: | 494 | case VDOT: |
495 | code_setname(ls, var); | ||
489 | code_oparg(ls, GETDOTTED, var->info, 0); | 496 | code_oparg(ls, GETDOTTED, var->info, 0); |
490 | break; | 497 | break; |
491 | case VINDEXED: | 498 | case VINDEXED: |
499 | code_setname(ls, var); | ||
492 | code_opcode(ls, GETTABLE, -1); | 500 | code_opcode(ls, GETTABLE, -1); |
493 | break; | 501 | break; |
494 | case VEXP: | 502 | case VEXP: |
495 | close_exp(ls, var->info, 1); /* function must return 1 value */ | 503 | close_exp(ls, var->info, 1); /* function must return 1 value */ |
496 | break; | 504 | break; |
497 | } | 505 | } |
506 | var->prev_k = var->k; /* save previous var kind and info */ | ||
507 | var->prev_info = var->info; | ||
498 | var->k = VEXP; | 508 | var->k = VEXP; |
499 | var->info = 0; /* now this is a closed expression */ | 509 | var->info = 0; /* now this is a closed expression */ |
500 | } | 510 | } |
@@ -510,6 +520,7 @@ static void storevar (LexState *ls, const vardesc *var) { | |||
510 | assertglobal(ls, var->info); /* make sure that there is a global */ | 520 | assertglobal(ls, var->info); /* make sure that there is a global */ |
511 | break; | 521 | break; |
512 | case VINDEXED: | 522 | case VINDEXED: |
523 | code_setname(ls, var); | ||
513 | code_opcode(ls, SETTABLEPOP, -3); | 524 | code_opcode(ls, SETTABLEPOP, -3); |
514 | break; | 525 | break; |
515 | default: | 526 | default: |
@@ -656,7 +667,7 @@ static void check (LexState *ls, int c) { | |||
656 | static void check_match (LexState *ls, int what, int who, int where) { | 667 | static void check_match (LexState *ls, int what, int who, int where) { |
657 | if (ls->token != what) | 668 | if (ls->token != what) |
658 | error_unmatched(ls, what, who, where); | 669 | error_unmatched(ls, what, who, where); |
659 | check_debugline(ls); /* to 'mark' the 'what' */ | 670 | check_debugline(ls); /* to `mark' the `what' */ |
660 | next(ls); | 671 | next(ls); |
661 | } | 672 | } |
662 | 673 | ||
@@ -705,241 +716,298 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { | |||
705 | /*============================================================*/ | 716 | /*============================================================*/ |
706 | 717 | ||
707 | 718 | ||
708 | static void chunk (LexState *ls) { | ||
709 | /* chunk -> { stat [;] } ret */ | ||
710 | while (stat(ls)) { | ||
711 | LUA_ASSERT(ls->L, ls->fs->stacksize == ls->fs->nlocalvar, | ||
712 | "stack size != # local vars"); | ||
713 | optional(ls, ';'); | ||
714 | } | ||
715 | ret(ls); /* optional return */ | ||
716 | } | ||
717 | |||
718 | 719 | ||
719 | static void whilestat (LexState *ls, int line) { | 720 | static int SaveWord (LexState *ls) { |
720 | /* whilestat -> WHILE cond DO block END */ | 721 | int res = ls->fs->pc; |
721 | FuncState *fs = ls->fs; | 722 | check_pc(ls, JMPSIZE); |
722 | TProtoFunc *f = fs->f; | 723 | ls->fs->pc += JMPSIZE; /* open space */ |
723 | int while_init = fs->pc; | 724 | return res; |
724 | int cond_end, cond_size; | ||
725 | next(ls); | ||
726 | cond_end = cond(ls); | ||
727 | check(ls, DO); | ||
728 | block(ls); | ||
729 | check_match(ls, END, WHILE, line); | ||
730 | cond_size = cond_end-while_init; | ||
731 | check_pc(ls, cond_size); | ||
732 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | ||
733 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); | ||
734 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); | ||
735 | fix_upjmp(ls, IFTUPJMP, while_init); | ||
736 | } | 725 | } |
737 | 726 | ||
738 | 727 | ||
739 | static void repeatstat (LexState *ls, int line) { | 728 | static int SaveWordPop (LexState *ls) { |
740 | /* repeatstat -> REPEAT block UNTIL exp1 */ | 729 | deltastack(ls, -1); /* pop condition */ |
741 | FuncState *fs = ls->fs; | 730 | return SaveWord(ls); |
742 | int repeat_init = fs->pc; | ||
743 | next(ls); | ||
744 | block(ls); | ||
745 | check_match(ls, UNTIL, REPEAT, line); | ||
746 | exp1(ls); | ||
747 | fix_upjmp(ls, IFFUPJMP, repeat_init); | ||
748 | deltastack(ls, -1); /* pops condition */ | ||
749 | } | 731 | } |
750 | 732 | ||
751 | 733 | ||
752 | static void localstat (LexState *ls) { | 734 | static int cond (LexState *ls) { |
753 | /* stat -> LOCAL localnamelist decinit */ | 735 | /* cond -> exp1 */ |
754 | FuncState *fs = ls->fs; | 736 | exp1(ls); |
755 | listdesc d; | 737 | return SaveWordPop(ls); |
756 | int nvars; | ||
757 | check_debugline(ls); | ||
758 | next(ls); | ||
759 | nvars = localnamelist(ls); | ||
760 | decinit(ls, &d); | ||
761 | adjustlocalvars(ls, nvars, fs->lastsetline); | ||
762 | adjust_mult_assign(ls, nvars, &d); | ||
763 | } | 738 | } |
764 | 739 | ||
765 | 740 | ||
766 | static int funcstat (LexState *ls, int line) { | 741 | static void explist1 (LexState *ls, listdesc *d) { |
767 | /* funcstat -> FUNCTION funcname body */ | ||
768 | int needself; | ||
769 | vardesc v; | 742 | vardesc v; |
770 | if (ls->fs->prev) /* inside other function? */ | 743 | exp(ls, &v); |
771 | return 0; | 744 | d->n = 1; |
772 | check_debugline(ls); | 745 | while (ls->token == ',') { |
773 | next(ls); | 746 | d->n++; |
774 | needself = funcname(ls, &v); | 747 | lua_pushvar(ls, &v); |
775 | body(ls, needself, line); | 748 | next(ls); |
776 | storevar(ls, &v); | 749 | exp(ls, &v); |
777 | return 1; | 750 | } |
751 | if (v.k == VEXP) | ||
752 | d->pc = v.info; | ||
753 | else { | ||
754 | lua_pushvar(ls, &v); | ||
755 | d->pc = 0; | ||
756 | } | ||
778 | } | 757 | } |
779 | 758 | ||
780 | 759 | ||
781 | static void namestat (LexState *ls) { | 760 | static void explist (LexState *ls, listdesc *d) { |
782 | /* stat -> func | ['%'] NAME assignment */ | 761 | switch (ls->token) { |
783 | vardesc v; | 762 | case ELSE: case ELSEIF: case END: case UNTIL: |
784 | check_debugline(ls); | 763 | case EOS: case ';': case ')': |
785 | var_or_func(ls, &v); | 764 | d->pc = 0; |
786 | if (v.k == VEXP) { /* stat -> func */ | 765 | d->n = 0; |
787 | if (v.info == 0) /* is just an upper value? */ | 766 | break; |
788 | luaX_error(ls, "syntax error"); | 767 | |
789 | close_exp(ls, v.info, 0); | 768 | default: |
790 | } | 769 | explist1(ls, d); |
791 | else { /* stat -> ['%'] NAME assignment */ | ||
792 | int left = assignment(ls, &v, 1); | ||
793 | adjuststack(ls, left); /* remove eventual garbage left on stack */ | ||
794 | } | 770 | } |
795 | } | 771 | } |
796 | 772 | ||
797 | 773 | ||
798 | static int stat (LexState *ls) { | 774 | static int funcparams (LexState *ls, int slf, vardesc *v) { |
799 | int line = ls->linenumber; /* may be needed for error messages */ | 775 | FuncState *fs = ls->fs; |
776 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ | ||
800 | switch (ls->token) { | 777 | switch (ls->token) { |
801 | case IF: /* stat -> IF ifpart END */ | 778 | case '(': { /* funcparams -> '(' explist ')' */ |
802 | ifpart(ls, line); | 779 | int line = ls->linenumber; |
803 | return 1; | 780 | listdesc e; |
781 | next(ls); | ||
782 | explist(ls, &e); | ||
783 | check_match(ls, ')', '(', line); | ||
784 | close_exp(ls, e.pc, MULT_RET); /* close 1 for old semantics */ | ||
785 | break; | ||
786 | } | ||
804 | 787 | ||
805 | case WHILE: /* stat -> whilestat */ | 788 | case '{': /* funcparams -> constructor */ |
806 | whilestat(ls, line); | 789 | constructor(ls); |
807 | return 1; | 790 | break; |
808 | 791 | ||
809 | case DO: { /* stat -> DO block END */ | 792 | case STRING: /* funcparams -> STRING */ |
793 | code_string(ls, ls->seminfo.ts); /* must use 'seminfo' before `next' */ | ||
810 | next(ls); | 794 | next(ls); |
811 | block(ls); | 795 | break; |
812 | check_match(ls, END, DO, line); | ||
813 | return 1; | ||
814 | } | ||
815 | 796 | ||
816 | case REPEAT: /* stat -> repeatstat */ | 797 | default: |
817 | repeatstat(ls, line); | 798 | luaX_error(ls, "function arguments expected"); |
818 | return 1; | 799 | break; |
800 | } | ||
801 | code_setname(ls, v); | ||
802 | code_byte(ls, CALL); | ||
803 | code_byte(ls, 0); /* save space for nresult */ | ||
804 | code_byte(ls, (Byte)slevel); | ||
805 | fs->stacksize = slevel; /* call will remove func and params */ | ||
806 | return fs->pc-1; | ||
807 | } | ||
819 | 808 | ||
820 | case FUNCTION: /* stat -> funcstat */ | ||
821 | return funcstat(ls, line); | ||
822 | 809 | ||
823 | case LOCAL: /* stat -> localstat */ | 810 | static void var_or_func_tail (LexState *ls, vardesc *v) { |
824 | localstat(ls); | 811 | for (;;) { |
825 | return 1; | 812 | switch (ls->token) { |
813 | case '.': /* var_or_func_tail -> '.' NAME */ | ||
814 | next(ls); | ||
815 | lua_pushvar(ls, v); /* `v' must be on stack */ | ||
816 | v->k = VDOT; | ||
817 | v->info = checkname(ls); | ||
818 | break; | ||
826 | 819 | ||
827 | case NAME: case '%': /* stat -> namestat */ | 820 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ |
828 | namestat(ls); | 821 | next(ls); |
829 | return 1; | 822 | lua_pushvar(ls, v); /* `v' must be on stack */ |
823 | exp1(ls); | ||
824 | check(ls, ']'); | ||
825 | v->k = VINDEXED; | ||
826 | break; | ||
830 | 827 | ||
831 | case RETURN: case ';': case ELSE: case ELSEIF: | 828 | case ':': { /* var_or_func_tail -> ':' NAME funcparams */ |
832 | case END: case UNTIL: case EOS: /* 'stat' follow */ | 829 | int name; |
833 | return 0; | 830 | next(ls); |
831 | name = checkname(ls); | ||
832 | lua_pushvar(ls, v); /* `v' must be on stack */ | ||
833 | code_setname(ls, v); | ||
834 | code_oparg(ls, PUSHSELF, name, 1); | ||
835 | v->prev_k = VDOT; /* ':' is syntactic sugar for '.' */ | ||
836 | v->prev_info = name; | ||
837 | v->k = VEXP; | ||
838 | v->info = funcparams(ls, 1, v); | ||
839 | break; | ||
840 | } | ||
834 | 841 | ||
835 | default: | 842 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ |
836 | error_unexpected(ls); | 843 | lua_pushvar(ls, v); /* `v' must be on stack */ |
837 | return 0; /* to avoid warnings */ | 844 | v->k = VEXP; |
845 | v->info = funcparams(ls, 0, v); | ||
846 | break; | ||
847 | |||
848 | default: return; /* should be follow... */ | ||
849 | } | ||
838 | } | 850 | } |
839 | } | 851 | } |
840 | 852 | ||
841 | static int SaveWord (LexState *ls) { | ||
842 | int res = ls->fs->pc; | ||
843 | check_pc(ls, JMPSIZE); | ||
844 | ls->fs->pc += JMPSIZE; /* open space */ | ||
845 | return res; | ||
846 | } | ||
847 | 853 | ||
848 | static int SaveWordPop (LexState *ls) { | 854 | static void var_or_func (LexState *ls, vardesc *v) { |
849 | deltastack(ls, -1); /* pop condition */ | 855 | /* var_or_func -> ['%'] NAME var_or_func_tail */ |
850 | return SaveWord(ls); | 856 | if (optional(ls, '%')) { /* upvalue? */ |
857 | pushupvalue(ls, str_checkname(ls)); | ||
858 | v->k = VEXP; | ||
859 | v->info = 0; /* closed expression */ | ||
860 | } | ||
861 | else /* variable name */ | ||
862 | singlevar(ls, str_checkname(ls), v, 0); | ||
863 | var_or_func_tail(ls, v); | ||
851 | } | 864 | } |
852 | 865 | ||
853 | static int cond (LexState *ls) { | 866 | |
854 | /* cond -> exp1 */ | 867 | |
868 | /* | ||
869 | ** {====================================================================== | ||
870 | ** Rules for Constructors | ||
871 | ** ======================================================================= | ||
872 | */ | ||
873 | |||
874 | static void recfield (LexState *ls) { | ||
875 | /* recfield -> (NAME | '['exp1']') = exp1 */ | ||
876 | switch (ls->token) { | ||
877 | case NAME: | ||
878 | code_constant(ls, checkname(ls)); | ||
879 | break; | ||
880 | |||
881 | case '[': | ||
882 | next(ls); | ||
883 | exp1(ls); | ||
884 | check(ls, ']'); | ||
885 | break; | ||
886 | |||
887 | default: luaX_error(ls, "NAME or `[' expected"); | ||
888 | } | ||
889 | check(ls, '='); | ||
855 | exp1(ls); | 890 | exp1(ls); |
856 | return SaveWordPop(ls); | ||
857 | } | 891 | } |
858 | 892 | ||
859 | static void block (LexState *ls) { | ||
860 | /* block -> chunk */ | ||
861 | FuncState *fs = ls->fs; | ||
862 | int nlocalvar = fs->nlocalvar; | ||
863 | chunk(ls); | ||
864 | adjuststack(ls, fs->nlocalvar - nlocalvar); | ||
865 | for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) | ||
866 | luaI_unregisterlocalvar(ls, fs->lastsetline); | ||
867 | } | ||
868 | 893 | ||
869 | static int funcname (LexState *ls, vardesc *v) { | 894 | static int recfields (LexState *ls) { |
870 | /* funcname -> NAME [':' NAME | '.' NAME] */ | 895 | /* recfields -> { ',' recfield } [','] */ |
871 | int needself = 0; | 896 | int n = 1; /* one has been read before */ |
872 | singlevar(ls, str_checkname(ls), v, 0); | 897 | while (ls->token == ',') { |
873 | if (ls->token == ':' || ls->token == '.') { | ||
874 | needself = (ls->token == ':'); | ||
875 | next(ls); | 898 | next(ls); |
876 | lua_pushvar(ls, v); | 899 | if (ls->token == ';' || ls->token == '}') |
877 | code_constant(ls, checkname(ls)); | 900 | break; |
878 | v->k = VINDEXED; | 901 | recfield(ls); |
902 | n++; | ||
903 | if (n%RFIELDS_PER_FLUSH == 0) | ||
904 | flush_record(ls, RFIELDS_PER_FLUSH); | ||
879 | } | 905 | } |
880 | return needself; | 906 | flush_record(ls, n%RFIELDS_PER_FLUSH); |
907 | return n; | ||
881 | } | 908 | } |
882 | 909 | ||
883 | static void body (LexState *ls, int needself, int line) { | 910 | |
884 | /* body -> '(' parlist ')' chunk END */ | 911 | static int listfields (LexState *ls) { |
885 | FuncState newfs; | 912 | /* listfields -> { ',' exp1 } [','] */ |
886 | init_state(ls, &newfs, ls->fs->f->source); | 913 | int n = 1; /* one has been read before */ |
887 | newfs.f->lineDefined = line; | 914 | while (ls->token == ',') { |
888 | check(ls, '('); | 915 | next(ls); |
889 | if (needself) | 916 | if (ls->token == ';' || ls->token == '}') |
890 | add_localvar(ls, luaS_newfixed(ls->L, "self")); | 917 | break; |
891 | parlist(ls); | 918 | exp1(ls); |
892 | check(ls, ')'); | 919 | n++; |
893 | chunk(ls); | 920 | if (n%LFIELDS_PER_FLUSH == 0) |
894 | check_match(ls, END, FUNCTION, line); | 921 | flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); |
895 | close_func(ls); | 922 | } |
896 | func_onstack(ls, &newfs); | 923 | flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); |
924 | return n; | ||
897 | } | 925 | } |
898 | 926 | ||
899 | 927 | ||
900 | static void ifpart (LexState *ls, int line) { | 928 | |
901 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ | 929 | static void constructor_part (LexState *ls, constdesc *cd) { |
902 | int c; | 930 | switch (ls->token) { |
903 | int e; | 931 | case ';': case '}': /* constructor_part -> empty */ |
904 | next(ls); /* skip IF or ELSEIF */ | 932 | cd->n = 0; |
905 | c = cond(ls); | 933 | cd->k = ls->token; |
906 | check(ls, THEN); | 934 | return; |
907 | block(ls); | 935 | |
908 | e = SaveWord(ls); | 936 | case NAME: { |
909 | if (ls->token == ELSEIF) | 937 | vardesc v; |
910 | ifpart(ls, line); | 938 | exp(ls, &v); |
911 | else { | 939 | if (ls->token == '=') { |
912 | if (optional(ls, ELSE)) | 940 | switch (v.k) { |
913 | block(ls); | 941 | case VGLOBAL: |
914 | check_match(ls, END, IF, line); | 942 | code_constant(ls, v.info); |
943 | break; | ||
944 | case VLOCAL: | ||
945 | code_string(ls, ls->fs->localvar[v.info]); | ||
946 | break; | ||
947 | default: | ||
948 | error_unexpected(ls); | ||
949 | } | ||
950 | next(ls); | ||
951 | exp1(ls); | ||
952 | cd->n = recfields(ls); | ||
953 | cd->k = 1; /* record */ | ||
954 | } | ||
955 | else { | ||
956 | lua_pushvar(ls, &v); | ||
957 | cd->n = listfields(ls); | ||
958 | cd->k = 0; /* list */ | ||
959 | } | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | case '[': /* constructor_part -> recfield recfields */ | ||
964 | recfield(ls); | ||
965 | cd->n = recfields(ls); | ||
966 | cd->k = 1; /* record */ | ||
967 | break; | ||
968 | |||
969 | default: /* constructor_part -> exp1 listfields */ | ||
970 | exp1(ls); | ||
971 | cd->n = listfields(ls); | ||
972 | cd->k = 0; /* list */ | ||
973 | break; | ||
915 | } | 974 | } |
916 | codeIf(ls, c, e); | ||
917 | } | 975 | } |
918 | 976 | ||
919 | 977 | ||
920 | static void ret (LexState *ls) { | 978 | static void constructor (LexState *ls) { |
921 | /* ret -> [RETURN explist sc] */ | 979 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ |
922 | if (optional(ls, RETURN)) { | 980 | int line = ls->linenumber; |
923 | listdesc e; | 981 | int pc = SaveWord(ls); |
924 | check_debugline(ls); | 982 | int nelems; |
925 | explist(ls, &e); | 983 | constdesc cd; |
926 | if (e.pc > 0) { /* expression is an open function call? */ | 984 | deltastack(ls, 1); |
927 | Byte *code = ls->fs->f->code; | 985 | check(ls, '{'); |
928 | code[e.pc-2] = TAILCALL; /* instead of a conventional CALL */ | 986 | constructor_part(ls, &cd); |
929 | code[e.pc-1] = (Byte)ls->fs->nlocalvar; | 987 | nelems = cd.n; |
930 | } | 988 | if (ls->token == ';') { |
931 | else | 989 | constdesc other_cd; |
932 | code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0); | 990 | next(ls); |
933 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | 991 | constructor_part(ls, &other_cd); |
934 | optional(ls, ';'); | 992 | if (cd.k == other_cd.k) /* repeated parts? */ |
993 | luaX_error(ls, "invalid constructor syntax"); | ||
994 | nelems += other_cd.n; | ||
935 | } | 995 | } |
996 | check_match(ls, '}', '{', line); | ||
997 | fix_opcode(ls, pc, CREATEARRAY, nelems); | ||
936 | } | 998 | } |
937 | 999 | ||
1000 | /* }====================================================================== */ | ||
1001 | |||
1002 | |||
1003 | |||
938 | 1004 | ||
939 | /* | 1005 | /* |
1006 | ** {====================================================================== | ||
940 | ** For parsing expressions, we use a classic stack with priorities. | 1007 | ** For parsing expressions, we use a classic stack with priorities. |
941 | ** Each binary operator is represented by its index in "binop" + FIRSTBIN | 1008 | ** Each binary operator is represented by its index in `binop' + FIRSTBIN |
942 | ** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1. | 1009 | ** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1. |
1010 | ** ======================================================================= | ||
943 | */ | 1011 | */ |
944 | 1012 | ||
945 | #define INDNOT 0 | 1013 | #define INDNOT 0 |
@@ -969,30 +1037,6 @@ typedef struct stack_op { | |||
969 | } stack_op; | 1037 | } stack_op; |
970 | 1038 | ||
971 | 1039 | ||
972 | static void exp1 (LexState *ls) { | ||
973 | vardesc v; | ||
974 | exp0(ls, &v); | ||
975 | lua_pushvar(ls, &v); | ||
976 | if (is_in(ls->token, expfollow) < 0) | ||
977 | luaX_error(ls, "malformed expression"); | ||
978 | } | ||
979 | |||
980 | |||
981 | static void exp0 (LexState *ls, vardesc *v) { | ||
982 | /* exp0 -> exp2 {(AND | OR) exp2} */ | ||
983 | exp2(ls, v); | ||
984 | while (ls->token == AND || ls->token == OR) { | ||
985 | int op = (ls->token == AND) ? ONFJMP : ONTJMP; | ||
986 | int pc; | ||
987 | lua_pushvar(ls, v); | ||
988 | next(ls); | ||
989 | pc = SaveWordPop(ls); | ||
990 | exp2(ls, v); | ||
991 | lua_pushvar(ls, v); | ||
992 | fix_jump(ls, pc, op, ls->fs->pc); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | 1040 | ||
997 | static void push (LexState *ls, stack_op *s, int op) { | 1041 | static void push (LexState *ls, stack_op *s, int op) { |
998 | if (s->top >= MAXOPS) | 1042 | if (s->top >= MAXOPS) |
@@ -1015,8 +1059,8 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) { | |||
1015 | case NUMBER: { /* simpleexp -> NUMBER */ | 1059 | case NUMBER: { /* simpleexp -> NUMBER */ |
1016 | real r = ls->seminfo.r; | 1060 | real r = ls->seminfo.r; |
1017 | next(ls); | 1061 | next(ls); |
1018 | /* dirty trick: check whether it is a -NUMBER not followed by '^' */ | 1062 | /* dirty trick: check whether it is a -NUMBER not followed by '^' */ |
1019 | /* (because the priority of '^' is higher than '-'...) */ | 1063 | /* (because the priority of '^' is higher than the priority of '-') */ |
1020 | if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') { | 1064 | if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') { |
1021 | s->top--; /* remove '-' from stack */ | 1065 | s->top--; /* remove '-' from stack */ |
1022 | r = -r; | 1066 | r = -r; |
@@ -1044,9 +1088,9 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) { | |||
1044 | body(ls, 0, ls->linenumber); | 1088 | body(ls, 0, ls->linenumber); |
1045 | break; | 1089 | break; |
1046 | 1090 | ||
1047 | case '(': /* simpleexp -> '(' exp0 ')' */ | 1091 | case '(': /* simpleexp -> '(' exp ')' */ |
1048 | next(ls); | 1092 | next(ls); |
1049 | exp0(ls, v); | 1093 | exp(ls, v); |
1050 | check(ls, ')'); | 1094 | check(ls, ')'); |
1051 | return; | 1095 | return; |
1052 | 1096 | ||
@@ -1072,7 +1116,7 @@ static void prefixexp (LexState *ls, vardesc *v, stack_op *s) { | |||
1072 | } | 1116 | } |
1073 | 1117 | ||
1074 | 1118 | ||
1075 | static void exp2 (LexState *ls, vardesc *v) { | 1119 | static void arith_exp (LexState *ls, vardesc *v) { |
1076 | stack_op s; | 1120 | stack_op s; |
1077 | int op; | 1121 | int op; |
1078 | s.top = 0; | 1122 | s.top = 0; |
@@ -1094,156 +1138,118 @@ static void exp2 (LexState *ls, vardesc *v) { | |||
1094 | } | 1138 | } |
1095 | 1139 | ||
1096 | 1140 | ||
1097 | static void var_or_func (LexState *ls, vardesc *v) { | 1141 | static void exp1 (LexState *ls) { |
1098 | /* var_or_func -> ['%'] NAME var_or_func_tail */ | 1142 | vardesc v; |
1099 | if (optional(ls, '%')) { /* upvalue? */ | 1143 | exp(ls, &v); |
1100 | pushupvalue(ls, str_checkname(ls)); | 1144 | lua_pushvar(ls, &v); |
1101 | v->k = VEXP; | 1145 | if (is_in(ls->token, expfollow) < 0) |
1102 | v->info = 0; /* closed expression */ | 1146 | luaX_error(ls, "malformed expression"); |
1103 | } | ||
1104 | else /* variable name */ | ||
1105 | singlevar(ls, str_checkname(ls), v, 0); | ||
1106 | var_or_func_tail(ls, v); | ||
1107 | } | 1147 | } |
1108 | 1148 | ||
1109 | 1149 | ||
1110 | static void var_or_func_tail (LexState *ls, vardesc *v) { | 1150 | static void exp (LexState *ls, vardesc *v) { |
1111 | for (;;) { | 1151 | /* exp -> arith_exp {(AND | OR) arith_exp} */ |
1112 | switch (ls->token) { | 1152 | arith_exp(ls, v); |
1113 | case '.': /* var_or_func_tail -> '.' NAME */ | 1153 | while (ls->token == AND || ls->token == OR) { |
1114 | next(ls); | 1154 | OpCode op = (ls->token == AND) ? ONFJMP : ONTJMP; |
1115 | lua_pushvar(ls, v); /* `v' must be on stack */ | 1155 | int pc; |
1116 | v->k = VDOT; | 1156 | lua_pushvar(ls, v); |
1117 | v->info = checkname(ls); | 1157 | next(ls); |
1118 | break; | 1158 | pc = SaveWordPop(ls); |
1119 | 1159 | arith_exp(ls, v); | |
1120 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | 1160 | lua_pushvar(ls, v); |
1121 | next(ls); | 1161 | fix_jump(ls, pc, op, ls->fs->pc); |
1122 | lua_pushvar(ls, v); /* `v' must be on stack */ | ||
1123 | exp1(ls); | ||
1124 | check(ls, ']'); | ||
1125 | v->k = VINDEXED; | ||
1126 | break; | ||
1127 | |||
1128 | case ':': /* var_or_func_tail -> ':' NAME funcparams */ | ||
1129 | next(ls); | ||
1130 | lua_pushvar(ls, v); /* `v' must be on stack */ | ||
1131 | code_oparg(ls, PUSHSELF, checkname(ls), 1); | ||
1132 | v->k = VEXP; | ||
1133 | v->info = funcparams(ls, 1); | ||
1134 | break; | ||
1135 | |||
1136 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ | ||
1137 | lua_pushvar(ls, v); /* `v' must be on stack */ | ||
1138 | v->k = VEXP; | ||
1139 | v->info = funcparams(ls, 0); | ||
1140 | break; | ||
1141 | |||
1142 | default: return; /* should be follow... */ | ||
1143 | } | ||
1144 | } | 1162 | } |
1145 | } | 1163 | } |
1146 | 1164 | ||
1147 | static int funcparams (LexState *ls, int slf) { | ||
1148 | FuncState *fs = ls->fs; | ||
1149 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ | ||
1150 | switch (ls->token) { | ||
1151 | case '(': { /* funcparams -> '(' explist ')' */ | ||
1152 | int line = ls->linenumber; | ||
1153 | listdesc e; | ||
1154 | next(ls); | ||
1155 | explist(ls, &e); | ||
1156 | check_match(ls, ')', '(', line); | ||
1157 | close_exp(ls, e.pc, MULT_RET); /* close 1 for old semantics */ | ||
1158 | break; | ||
1159 | } | ||
1160 | 1165 | ||
1161 | case '{': /* funcparams -> constructor */ | 1166 | /* }==================================================================== */ |
1162 | constructor(ls); | ||
1163 | break; | ||
1164 | 1167 | ||
1165 | case STRING: /* funcparams -> STRING */ | ||
1166 | code_string(ls, ls->seminfo.ts); /* must use 'seminfo' before `next' */ | ||
1167 | next(ls); | ||
1168 | break; | ||
1169 | 1168 | ||
1170 | default: | 1169 | /* |
1171 | luaX_error(ls, "function arguments expected"); | 1170 | ** {====================================================================== |
1172 | break; | 1171 | ** Rules for Statements |
1173 | } | 1172 | ** ======================================================================= |
1174 | code_byte(ls, CALL); | 1173 | */ |
1175 | code_byte(ls, 0); /* save space for nresult */ | ||
1176 | code_byte(ls, (Byte)slevel); | ||
1177 | fs->stacksize = slevel; /* call will remove func and params */ | ||
1178 | return fs->pc-1; | ||
1179 | } | ||
1180 | 1174 | ||
1181 | static void explist (LexState *ls, listdesc *d) { | ||
1182 | switch (ls->token) { | ||
1183 | case ELSE: case ELSEIF: case END: case UNTIL: | ||
1184 | case EOS: case ';': case ')': | ||
1185 | d->pc = 0; | ||
1186 | d->n = 0; | ||
1187 | break; | ||
1188 | 1175 | ||
1189 | default: | 1176 | static void block (LexState *ls) { |
1190 | explist1(ls, d); | 1177 | /* block -> chunk */ |
1191 | } | 1178 | FuncState *fs = ls->fs; |
1179 | int nlocalvar = fs->nlocalvar; | ||
1180 | chunk(ls); | ||
1181 | adjuststack(ls, fs->nlocalvar - nlocalvar); | ||
1182 | for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) | ||
1183 | luaI_unregisterlocalvar(ls, fs->lastsetline); | ||
1192 | } | 1184 | } |
1193 | 1185 | ||
1194 | static void explist1 (LexState *ls, listdesc *d) { | 1186 | |
1195 | vardesc v; | 1187 | static int assignment (LexState *ls, vardesc *v, int nvars) { |
1196 | exp0(ls, &v); | 1188 | int left = 0; |
1197 | d->n = 1; | 1189 | checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); |
1198 | while (ls->token == ',') { | 1190 | unloaddot(ls, v); |
1199 | d->n++; | 1191 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ |
1200 | lua_pushvar(ls, &v); | 1192 | vardesc nv; |
1201 | next(ls); | 1193 | next(ls); |
1202 | exp0(ls, &v); | 1194 | var_or_func(ls, &nv); |
1195 | if (nv.k == VEXP) | ||
1196 | luaX_error(ls, "syntax error"); | ||
1197 | left = assignment(ls, &nv, nvars+1); | ||
1203 | } | 1198 | } |
1204 | if (v.k == VEXP) | 1199 | else { /* assignment -> '=' explist1 */ |
1205 | d->pc = v.info; | 1200 | listdesc d; |
1206 | else { | 1201 | if (ls->token != '=') |
1207 | lua_pushvar(ls, &v); | 1202 | error_unexpected(ls); |
1208 | d->pc = 0; | 1203 | next(ls); |
1204 | explist1(ls, &d); | ||
1205 | adjust_mult_assign(ls, nvars, &d); | ||
1206 | } | ||
1207 | if (v->k != VINDEXED || left+(nvars-1) == 0) { | ||
1208 | /* global/local var or indexed var without values in between */ | ||
1209 | storevar(ls, v); | ||
1210 | } | ||
1211 | else { /* indexed var with values in between*/ | ||
1212 | code_setname(ls, v); | ||
1213 | code_oparg(ls, SETTABLE, left+(nvars-1), -1); | ||
1214 | left += 2; /* table&index are not popped, because they aren't on top */ | ||
1209 | } | 1215 | } |
1216 | return left; | ||
1210 | } | 1217 | } |
1211 | 1218 | ||
1212 | static void parlist (LexState *ls) { | ||
1213 | int nparams = 0; | ||
1214 | int dots = 0; | ||
1215 | switch (ls->token) { | ||
1216 | case DOTS: /* parlist -> DOTS */ | ||
1217 | next(ls); | ||
1218 | dots = 1; | ||
1219 | break; | ||
1220 | 1219 | ||
1221 | case NAME: /* parlist, tailparlist -> NAME [',' tailparlist] */ | 1220 | static void whilestat (LexState *ls, int line) { |
1222 | init: | 1221 | /* whilestat -> WHILE cond DO block END */ |
1223 | store_localvar(ls, str_checkname(ls), nparams++); | 1222 | FuncState *fs = ls->fs; |
1224 | if (ls->token == ',') { | 1223 | TProtoFunc *f = fs->f; |
1225 | next(ls); | 1224 | int while_init = fs->pc; |
1226 | switch (ls->token) { | 1225 | int cond_end, cond_size; |
1227 | case DOTS: /* tailparlist -> DOTS */ | 1226 | next(ls); |
1228 | next(ls); | 1227 | cond_end = cond(ls); |
1229 | dots = 1; | 1228 | check(ls, DO); |
1230 | break; | 1229 | block(ls); |
1231 | 1230 | check_match(ls, END, WHILE, line); | |
1232 | case NAME: /* tailparlist -> NAME [',' tailparlist] */ | 1231 | cond_size = cond_end-while_init; |
1233 | goto init; | 1232 | check_pc(ls, cond_size); |
1234 | 1233 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | |
1235 | default: luaX_error(ls, "NAME or `...' expected"); | 1234 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); |
1236 | } | 1235 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); |
1237 | } | 1236 | fix_upjmp(ls, IFTUPJMP, while_init); |
1238 | break; | 1237 | } |
1239 | 1238 | ||
1240 | case ')': break; /* parlist -> empty */ | ||
1241 | 1239 | ||
1242 | default: luaX_error(ls, "NAME or `...' expected"); | 1240 | static void repeatstat (LexState *ls, int line) { |
1243 | } | 1241 | /* repeatstat -> REPEAT block UNTIL exp1 */ |
1244 | code_args(ls, nparams, dots); | 1242 | FuncState *fs = ls->fs; |
1243 | int repeat_init = fs->pc; | ||
1244 | next(ls); | ||
1245 | block(ls); | ||
1246 | check_match(ls, UNTIL, REPEAT, line); | ||
1247 | exp1(ls); | ||
1248 | fix_upjmp(ls, IFFUPJMP, repeat_init); | ||
1249 | deltastack(ls, -1); /* pops condition */ | ||
1245 | } | 1250 | } |
1246 | 1251 | ||
1252 | |||
1247 | static int localnamelist (LexState *ls) { | 1253 | static int localnamelist (LexState *ls) { |
1248 | /* localnamelist -> NAME {',' NAME} */ | 1254 | /* localnamelist -> NAME {',' NAME} */ |
1249 | int i = 1; | 1255 | int i = 1; |
@@ -1255,6 +1261,7 @@ static int localnamelist (LexState *ls) { | |||
1255 | return i; | 1261 | return i; |
1256 | } | 1262 | } |
1257 | 1263 | ||
1264 | |||
1258 | static void decinit (LexState *ls, listdesc *d) { | 1265 | static void decinit (LexState *ls, listdesc *d) { |
1259 | /* decinit -> ['=' explist1] */ | 1266 | /* decinit -> ['=' explist1] */ |
1260 | if (ls->token == '=') { | 1267 | if (ls->token == '=') { |
@@ -1268,156 +1275,212 @@ static void decinit (LexState *ls, listdesc *d) { | |||
1268 | } | 1275 | } |
1269 | 1276 | ||
1270 | 1277 | ||
1271 | static int assignment (LexState *ls, vardesc *v, int nvars) { | 1278 | static void localstat (LexState *ls) { |
1272 | int left = 0; | 1279 | /* stat -> LOCAL localnamelist decinit */ |
1273 | checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); | 1280 | FuncState *fs = ls->fs; |
1274 | unloaddot(ls, v); | 1281 | listdesc d; |
1275 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ | 1282 | int nvars; |
1276 | vardesc nv; | 1283 | check_debugline(ls); |
1284 | next(ls); | ||
1285 | nvars = localnamelist(ls); | ||
1286 | decinit(ls, &d); | ||
1287 | adjustlocalvars(ls, nvars, fs->lastsetline); | ||
1288 | adjust_mult_assign(ls, nvars, &d); | ||
1289 | } | ||
1290 | |||
1291 | |||
1292 | static int funcname (LexState *ls, vardesc *v) { | ||
1293 | /* funcname -> NAME [':' NAME | '.' NAME] */ | ||
1294 | int needself = 0; | ||
1295 | singlevar(ls, str_checkname(ls), v, 0); | ||
1296 | if (ls->token == ':' || ls->token == '.') { | ||
1297 | needself = (ls->token == ':'); | ||
1277 | next(ls); | 1298 | next(ls); |
1278 | var_or_func(ls, &nv); | 1299 | lua_pushvar(ls, v); |
1279 | if (nv.k == VEXP) | 1300 | code_constant(ls, checkname(ls)); |
1280 | luaX_error(ls, "syntax error"); | 1301 | v->k = VINDEXED; |
1281 | left = assignment(ls, &nv, nvars+1); | ||
1282 | } | 1302 | } |
1283 | else { /* assignment -> '=' explist1 */ | 1303 | return needself; |
1284 | listdesc d; | 1304 | } |
1285 | if (ls->token != '=') | 1305 | |
1286 | error_unexpected(ls); | 1306 | |
1287 | next(ls); | 1307 | static int funcstat (LexState *ls, int line) { |
1288 | explist1(ls, &d); | 1308 | /* funcstat -> FUNCTION funcname body */ |
1289 | adjust_mult_assign(ls, nvars, &d); | 1309 | int needself; |
1310 | vardesc v; | ||
1311 | if (ls->fs->prev) /* inside other function? */ | ||
1312 | return 0; | ||
1313 | check_debugline(ls); | ||
1314 | next(ls); | ||
1315 | needself = funcname(ls, &v); | ||
1316 | body(ls, needself, line); | ||
1317 | storevar(ls, &v); | ||
1318 | return 1; | ||
1319 | } | ||
1320 | |||
1321 | |||
1322 | static void namestat (LexState *ls) { | ||
1323 | /* stat -> func | ['%'] NAME assignment */ | ||
1324 | vardesc v; | ||
1325 | check_debugline(ls); | ||
1326 | var_or_func(ls, &v); | ||
1327 | if (v.k == VEXP) { /* stat -> func */ | ||
1328 | if (v.info == 0) /* is just an upper value? */ | ||
1329 | luaX_error(ls, "syntax error"); | ||
1330 | close_exp(ls, v.info, 0); | ||
1290 | } | 1331 | } |
1291 | if (v->k != VINDEXED || left+(nvars-1) == 0) { | 1332 | else { /* stat -> ['%'] NAME assignment */ |
1292 | /* global/local var or indexed var without values in between */ | 1333 | int left = assignment(ls, &v, 1); |
1293 | storevar(ls, v); | 1334 | adjuststack(ls, left); /* remove eventual garbage left on stack */ |
1294 | } | 1335 | } |
1295 | else { /* indexed var with values in between*/ | 1336 | } |
1296 | code_oparg(ls, SETTABLE, left+(nvars-1), -1); | 1337 | |
1297 | left += 2; /* table&index are not popped, because they aren't on top */ | 1338 | |
1339 | static void ifpart (LexState *ls, int line) { | ||
1340 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ | ||
1341 | int c; | ||
1342 | int e; | ||
1343 | next(ls); /* skip IF or ELSEIF */ | ||
1344 | c = cond(ls); | ||
1345 | check(ls, THEN); | ||
1346 | block(ls); | ||
1347 | e = SaveWord(ls); | ||
1348 | if (ls->token == ELSEIF) | ||
1349 | ifpart(ls, line); | ||
1350 | else { | ||
1351 | if (optional(ls, ELSE)) | ||
1352 | block(ls); | ||
1353 | check_match(ls, END, IF, line); | ||
1298 | } | 1354 | } |
1299 | return left; | 1355 | codeIf(ls, c, e); |
1300 | } | 1356 | } |
1301 | 1357 | ||
1302 | 1358 | ||
1303 | static void constructor (LexState *ls) { | 1359 | static int stat (LexState *ls) { |
1304 | /* constructor -> '{' part [';' part] '}' */ | 1360 | int line = ls->linenumber; /* may be needed for error messages */ |
1305 | int line = ls->linenumber; | 1361 | switch (ls->token) { |
1306 | int pc = SaveWord(ls); | 1362 | case IF: /* stat -> IF ifpart END */ |
1307 | int nelems; | 1363 | ifpart(ls, line); |
1308 | constdesc cd; | 1364 | return 1; |
1309 | deltastack(ls, 1); | 1365 | |
1310 | check(ls, '{'); | 1366 | case WHILE: /* stat -> whilestat */ |
1311 | part(ls, &cd); | 1367 | whilestat(ls, line); |
1312 | nelems = cd.n; | 1368 | return 1; |
1313 | if (ls->token == ';') { | 1369 | |
1314 | constdesc other_cd; | 1370 | case DO: { /* stat -> DO block END */ |
1315 | next(ls); | 1371 | next(ls); |
1316 | part(ls, &other_cd); | 1372 | block(ls); |
1317 | if (cd.k == other_cd.k) /* repeated parts? */ | 1373 | check_match(ls, END, DO, line); |
1318 | luaX_error(ls, "invalid constructor syntax"); | 1374 | return 1; |
1319 | nelems += other_cd.n; | 1375 | } |
1376 | |||
1377 | case REPEAT: /* stat -> repeatstat */ | ||
1378 | repeatstat(ls, line); | ||
1379 | return 1; | ||
1380 | |||
1381 | case FUNCTION: /* stat -> funcstat */ | ||
1382 | return funcstat(ls, line); | ||
1383 | |||
1384 | case LOCAL: /* stat -> localstat */ | ||
1385 | localstat(ls); | ||
1386 | return 1; | ||
1387 | |||
1388 | case NAME: case '%': /* stat -> namestat */ | ||
1389 | namestat(ls); | ||
1390 | return 1; | ||
1391 | |||
1392 | case RETURN: case ';': case ELSE: case ELSEIF: | ||
1393 | case END: case UNTIL: case EOS: /* 'stat' follow */ | ||
1394 | return 0; | ||
1395 | |||
1396 | default: | ||
1397 | error_unexpected(ls); | ||
1398 | return 0; /* to avoid warnings */ | ||
1320 | } | 1399 | } |
1321 | check_match(ls, '}', '{', line); | ||
1322 | fix_opcode(ls, pc, CREATEARRAY, nelems); | ||
1323 | } | 1400 | } |
1324 | 1401 | ||
1325 | static void part (LexState *ls, constdesc *cd) { | 1402 | |
1403 | static void parlist (LexState *ls) { | ||
1404 | int nparams = 0; | ||
1405 | int dots = 0; | ||
1326 | switch (ls->token) { | 1406 | switch (ls->token) { |
1327 | case ';': case '}': /* part -> empty */ | 1407 | case DOTS: /* parlist -> DOTS */ |
1328 | cd->n = 0; | 1408 | next(ls); |
1329 | cd->k = ls->token; | 1409 | dots = 1; |
1330 | return; | 1410 | break; |
1331 | 1411 | ||
1332 | case NAME: { | 1412 | case NAME: /* parlist, tailparlist -> NAME [',' tailparlist] */ |
1333 | vardesc v; | 1413 | init: |
1334 | exp0(ls, &v); | 1414 | store_localvar(ls, str_checkname(ls), nparams++); |
1335 | if (ls->token == '=') { | 1415 | if (ls->token == ',') { |
1336 | switch (v.k) { | 1416 | next(ls); |
1337 | case VGLOBAL: | 1417 | switch (ls->token) { |
1338 | code_constant(ls, v.info); | 1418 | case DOTS: /* tailparlist -> DOTS */ |
1339 | break; | 1419 | next(ls); |
1340 | case VLOCAL: | 1420 | dots = 1; |
1341 | code_string(ls, ls->fs->localvar[v.info]); | ||
1342 | break; | 1421 | break; |
1343 | default: | 1422 | |
1344 | error_unexpected(ls); | 1423 | case NAME: /* tailparlist -> NAME [',' tailparlist] */ |
1424 | goto init; | ||
1425 | |||
1426 | default: luaX_error(ls, "NAME or `...' expected"); | ||
1345 | } | 1427 | } |
1346 | next(ls); | ||
1347 | exp1(ls); | ||
1348 | cd->n = recfields(ls); | ||
1349 | cd->k = 1; /* record */ | ||
1350 | } | ||
1351 | else { | ||
1352 | lua_pushvar(ls, &v); | ||
1353 | cd->n = listfields(ls); | ||
1354 | cd->k = 0; /* list */ | ||
1355 | } | 1428 | } |
1356 | break; | 1429 | break; |
1357 | } | ||
1358 | 1430 | ||
1359 | case '[': /* part -> recfield recfields */ | 1431 | case ')': break; /* parlist -> empty */ |
1360 | recfield(ls); | ||
1361 | cd->n = recfields(ls); | ||
1362 | cd->k = 1; /* record */ | ||
1363 | break; | ||
1364 | 1432 | ||
1365 | default: /* part -> exp1 listfields */ | 1433 | default: luaX_error(ls, "NAME or `...' expected"); |
1366 | exp1(ls); | ||
1367 | cd->n = listfields(ls); | ||
1368 | cd->k = 0; /* list */ | ||
1369 | break; | ||
1370 | } | 1434 | } |
1435 | code_args(ls, nparams, dots); | ||
1371 | } | 1436 | } |
1372 | 1437 | ||
1373 | static int recfields (LexState *ls) { | 1438 | |
1374 | /* recfields -> { ',' recfield } [','] */ | 1439 | static void body (LexState *ls, int needself, int line) { |
1375 | int n = 1; /* one has been read before */ | 1440 | /* body -> '(' parlist ')' chunk END */ |
1376 | while (ls->token == ',') { | 1441 | FuncState newfs; |
1377 | next(ls); | 1442 | init_state(ls, &newfs, ls->fs->f->source); |
1378 | if (ls->token == ';' || ls->token == '}') | 1443 | newfs.f->lineDefined = line; |
1379 | break; | 1444 | check(ls, '('); |
1380 | recfield(ls); | 1445 | if (needself) |
1381 | n++; | 1446 | add_localvar(ls, luaS_newfixed(ls->L, "self")); |
1382 | if (n%RFIELDS_PER_FLUSH == 0) | 1447 | parlist(ls); |
1383 | flush_record(ls, RFIELDS_PER_FLUSH); | 1448 | check(ls, ')'); |
1384 | } | 1449 | chunk(ls); |
1385 | flush_record(ls, n%RFIELDS_PER_FLUSH); | 1450 | check_match(ls, END, FUNCTION, line); |
1386 | return n; | 1451 | close_func(ls); |
1452 | func_onstack(ls, &newfs); | ||
1387 | } | 1453 | } |
1388 | 1454 | ||
1389 | static int listfields (LexState *ls) { | 1455 | |
1390 | /* listfields -> { ',' exp1 } [','] */ | 1456 | static void ret (LexState *ls) { |
1391 | int n = 1; /* one has been read before */ | 1457 | /* ret -> [RETURN explist sc] */ |
1392 | while (ls->token == ',') { | 1458 | if (optional(ls, RETURN)) { |
1393 | next(ls); | 1459 | listdesc e; |
1394 | if (ls->token == ';' || ls->token == '}') | 1460 | check_debugline(ls); |
1395 | break; | 1461 | explist(ls, &e); |
1396 | exp1(ls); | 1462 | if (e.pc > 0) { /* expression is an open function call? */ |
1397 | n++; | 1463 | Byte *code = ls->fs->f->code; |
1398 | if (n%LFIELDS_PER_FLUSH == 0) | 1464 | code[e.pc-2] = TAILCALL; /* instead of a conventional CALL */ |
1399 | flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); | 1465 | code[e.pc-1] = (Byte)ls->fs->nlocalvar; |
1466 | } | ||
1467 | else | ||
1468 | code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0); | ||
1469 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | ||
1470 | optional(ls, ';'); | ||
1400 | } | 1471 | } |
1401 | flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); | ||
1402 | return n; | ||
1403 | } | 1472 | } |
1404 | 1473 | ||
1405 | static void recfield (LexState *ls) { | 1474 | /* }====================================================================== */ |
1406 | /* recfield -> (NAME | '['exp1']') = exp1 */ | ||
1407 | switch (ls->token) { | ||
1408 | case NAME: | ||
1409 | code_constant(ls, checkname(ls)); | ||
1410 | break; | ||
1411 | 1475 | ||
1412 | case '[': | ||
1413 | next(ls); | ||
1414 | exp1(ls); | ||
1415 | check(ls, ']'); | ||
1416 | break; | ||
1417 | 1476 | ||
1418 | default: luaX_error(ls, "NAME or `[' expected"); | 1477 | static void chunk (LexState *ls) { |
1478 | /* chunk -> { stat [;] } ret */ | ||
1479 | while (stat(ls)) { | ||
1480 | LUA_ASSERT(ls->L, ls->fs->stacksize == ls->fs->nlocalvar, | ||
1481 | "stack size != # local vars"); | ||
1482 | optional(ls, ';'); | ||
1419 | } | 1483 | } |
1420 | check(ls, '='); | 1484 | ret(ls); /* optional return */ |
1421 | exp1(ls); | ||
1422 | } | 1485 | } |
1423 | 1486 | ||