diff options
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 | ||
