diff options
| author | Mike Pall <mike> | 2026-07-20 10:20:49 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2026-07-20 10:20:49 +0200 |
| commit | a2ce8114f107464473070427e69e84f4923bd08a (patch) | |
| tree | 41fb420f360bf1446ae253dda360af5300e401a6 /src/lj_parse.c | |
| parent | 14d8a7a27dc8c626ab9e7c7e9e50b6df6def4f03 (diff) | |
| download | luajit-a2ce8114f107464473070427e69e84f4923bd08a.tar.gz luajit-a2ce8114f107464473070427e69e84f4923bd08a.tar.bz2 luajit-a2ce8114f107464473070427e69e84f4923bd08a.zip | |
Backport some v3.0 syntax extensions.
Documentation in #1475. Backport discussion in #1476.
Thanks to Appla, slashOwO, Sergey Kaplun, CppCXY.
Diffstat (limited to 'src/lj_parse.c')
| -rw-r--r-- | src/lj_parse.c | 781 |
1 files changed, 580 insertions, 201 deletions
diff --git a/src/lj_parse.c b/src/lj_parse.c index 66e5a0341..00a64382c 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c | |||
| @@ -49,6 +49,7 @@ typedef enum { | |||
| 49 | VRELOCABLE, /* info = instruction PC */ | 49 | VRELOCABLE, /* info = instruction PC */ |
| 50 | VNONRELOC, /* info = result register */ | 50 | VNONRELOC, /* info = result register */ |
| 51 | VCALL, /* info = instruction PC, aux = base */ | 51 | VCALL, /* info = instruction PC, aux = base */ |
| 52 | VCALLNAV, /* info = instruction PC, aux = base */ | ||
| 52 | VVOID | 53 | VVOID |
| 53 | } ExpKind; | 54 | } ExpKind; |
| 54 | 55 | ||
| @@ -79,6 +80,18 @@ typedef struct ExpDesc { | |||
| 79 | #define expr_numtv(e) check_exp(expr_isnumk((e)), &(e)->u.nval) | 80 | #define expr_numtv(e) check_exp(expr_isnumk((e)), &(e)->u.nval) |
| 80 | #define expr_numberV(e) numberVnum(expr_numtv((e))) | 81 | #define expr_numberV(e) numberVnum(expr_numtv((e))) |
| 81 | 82 | ||
| 83 | /* Expression flags. */ | ||
| 84 | #define EXPR_F_NORES 0x01 /* Result will not be used. */ | ||
| 85 | #define EXPR_F_NOCOLON 0x02 /* Disallow colon for method call.*/ | ||
| 86 | #define EXPR_F_NONAV 0x04 /* Disallow safe navigation. */ | ||
| 87 | #define EXPR_F_RET1 0x08 /* Return a single expr. */ | ||
| 88 | |||
| 89 | static LJ_AINLINE int32_t expr_bitV(ExpDesc *e) | ||
| 90 | { | ||
| 91 | TValue *o = expr_numtv(e); | ||
| 92 | return tvisint(o) ? intV(o) : lj_num2bit(numV(o)); | ||
| 93 | } | ||
| 94 | |||
| 82 | /* Initialize expression. */ | 95 | /* Initialize expression. */ |
| 83 | static LJ_AINLINE void expr_init(ExpDesc *e, ExpKind k, uint32_t info) | 96 | static LJ_AINLINE void expr_init(ExpDesc *e, ExpKind k, uint32_t info) |
| 84 | { | 97 | { |
| @@ -107,17 +120,22 @@ typedef struct FuncScope { | |||
| 107 | #define FSCOPE_GOLA 0x04 /* Goto or label used in scope. */ | 120 | #define FSCOPE_GOLA 0x04 /* Goto or label used in scope. */ |
| 108 | #define FSCOPE_UPVAL 0x08 /* Upvalue in scope. */ | 121 | #define FSCOPE_UPVAL 0x08 /* Upvalue in scope. */ |
| 109 | #define FSCOPE_NOCLOSE 0x10 /* Do not close upvalues. */ | 122 | #define FSCOPE_NOCLOSE 0x10 /* Do not close upvalues. */ |
| 123 | #define FSCOPE_CONT 0x20 /* Continue used in scope. */ | ||
| 110 | 124 | ||
| 111 | #define NAME_BREAK ((GCstr *)(uintptr_t)1) | 125 | #define NAME_BREAK ((GCstr *)(uintptr_t)1) |
| 126 | #define NAME_CONT ((GCstr *)(uintptr_t)2) | ||
| 112 | 127 | ||
| 113 | /* Index into variable stack. */ | 128 | /* Index into variable stack. See VarIndex in lj_lex.h. */ |
| 114 | typedef uint16_t VarIndex; | 129 | #define VINDEX_NONE 0xffff |
| 115 | #define LJ_MAX_VSTACK (65536 - LJ_MAX_UPVAL) | 130 | #define LJ_MAX_VSTACK (65536 - LJ_MAX_UPVAL) |
| 116 | 131 | ||
| 132 | #define LJ_HASH_VSTACK 0x20 /* Must be a power of 2. */ | ||
| 133 | |||
| 117 | /* Variable/goto/label info. */ | 134 | /* Variable/goto/label info. */ |
| 118 | #define VSTACK_VAR_RW 0x01 /* R/W variable. */ | 135 | #define VSTACK_VAR_RW 0x01 /* R/W variable. */ |
| 119 | #define VSTACK_GOTO 0x02 /* Pending goto. */ | 136 | #define VSTACK_GOTO 0x02 /* Pending goto. */ |
| 120 | #define VSTACK_LABEL 0x04 /* Label. */ | 137 | #define VSTACK_LABEL 0x04 /* Label. */ |
| 138 | #define VSTACK_CONST 0x08 /* Constant variable. */ | ||
| 121 | 139 | ||
| 122 | /* Per-function state. */ | 140 | /* Per-function state. */ |
| 123 | typedef struct FuncState { | 141 | typedef struct FuncState { |
| @@ -148,10 +166,11 @@ typedef struct FuncState { | |||
| 148 | /* Binary and unary operators. ORDER OPR */ | 166 | /* Binary and unary operators. ORDER OPR */ |
| 149 | typedef enum BinOpr { | 167 | typedef enum BinOpr { |
| 150 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, /* ORDER ARITH */ | 168 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, /* ORDER ARITH */ |
| 169 | OPR_BAND, OPR_BOR, OPR_BXOR, OPR_BSHL, OPR_BSHR, OPR_BSAR, /* ORDER BIT */ | ||
| 151 | OPR_CONCAT, | 170 | OPR_CONCAT, |
| 152 | OPR_NE, OPR_EQ, | 171 | OPR_NE, OPR_EQ, |
| 153 | OPR_LT, OPR_GE, OPR_LE, OPR_GT, | 172 | OPR_LT, OPR_GE, OPR_LE, OPR_GT, |
| 154 | OPR_AND, OPR_OR, | 173 | OPR_AND, OPR_OR, OPR_COAL, |
| 155 | OPR_NOBINOPR | 174 | OPR_NOBINOPR |
| 156 | } BinOpr; | 175 | } BinOpr; |
| 157 | 176 | ||
| @@ -458,7 +477,7 @@ static void expr_discharge(FuncState *fs, ExpDesc *e) | |||
| 458 | ins = BCINS_ABC(BC_TGETV, 0, e->u.s.info, rc); | 477 | ins = BCINS_ABC(BC_TGETV, 0, e->u.s.info, rc); |
| 459 | } | 478 | } |
| 460 | bcreg_free(fs, e->u.s.info); | 479 | bcreg_free(fs, e->u.s.info); |
| 461 | } else if (e->k == VCALL) { | 480 | } else if (e->k == VCALL || e->k == VCALLNAV) { |
| 462 | e->u.s.info = e->u.s.aux; | 481 | e->u.s.info = e->u.s.aux; |
| 463 | e->k = VNONRELOC; | 482 | e->k = VNONRELOC; |
| 464 | return; | 483 | return; |
| @@ -623,11 +642,13 @@ static void bcemit_store(FuncState *fs, ExpDesc *var, ExpDesc *e) | |||
| 623 | { | 642 | { |
| 624 | BCIns ins; | 643 | BCIns ins; |
| 625 | if (var->k == VLOCAL) { | 644 | if (var->k == VLOCAL) { |
| 645 | lj_assertFS(!(fs->ls->vstack[var->u.s.aux].info & VSTACK_CONST), "unchecked const assignment"); | ||
| 626 | fs->ls->vstack[var->u.s.aux].info |= VSTACK_VAR_RW; | 646 | fs->ls->vstack[var->u.s.aux].info |= VSTACK_VAR_RW; |
| 627 | expr_free(fs, e); | 647 | expr_free(fs, e); |
| 628 | expr_toreg(fs, e, var->u.s.info); | 648 | expr_toreg(fs, e, var->u.s.info); |
| 629 | return; | 649 | return; |
| 630 | } else if (var->k == VUPVAL) { | 650 | } else if (var->k == VUPVAL) { |
| 651 | lj_assertFS(!(fs->ls->vstack[var->u.s.aux].info & VSTACK_CONST), "unchecked const assignment"); | ||
| 631 | fs->ls->vstack[var->u.s.aux].info |= VSTACK_VAR_RW; | 652 | fs->ls->vstack[var->u.s.aux].info |= VSTACK_VAR_RW; |
| 632 | expr_toval(fs, e); | 653 | expr_toval(fs, e); |
| 633 | if (e->k <= VKTRUE) | 654 | if (e->k <= VKTRUE) |
| @@ -793,17 +814,39 @@ static int foldarith(BinOpr opr, ExpDesc *e1, ExpDesc *e2) | |||
| 793 | return 1; | 814 | return 1; |
| 794 | } | 815 | } |
| 795 | 816 | ||
| 817 | /* Try constant-folding of bit operators. */ | ||
| 818 | static int foldbitop(BinOpr opr, ExpDesc *e1, ExpDesc *e2) | ||
| 819 | { | ||
| 820 | if (expr_isnumk_nojump(e1) && expr_isnumk_nojump(e2)) { | ||
| 821 | int32_t k1 = expr_bitV(e1), k2 = expr_bitV(e2); | ||
| 822 | switch (opr) { | ||
| 823 | case OPR_BAND: k1 &= k2; break; | ||
| 824 | case OPR_BOR: k1 |= k2; break; | ||
| 825 | case OPR_BXOR: k1 ^= k2; break; | ||
| 826 | case OPR_BSHL: k1 <<= (k2 & 31); break; | ||
| 827 | case OPR_BSHR: k1 = (int32_t)((uint32_t)k1 >> (k2 & 31)); break; | ||
| 828 | case OPR_BSAR: k1 >>= (k2 & 31); break; | ||
| 829 | default: lj_assertX(0, "bad OPR %d", opr); break; | ||
| 830 | } | ||
| 831 | setintV(&e1->u.nval, k1); | ||
| 832 | return 1; | ||
| 833 | } | ||
| 834 | return 0; | ||
| 835 | } | ||
| 836 | |||
| 796 | /* Emit arithmetic operator. */ | 837 | /* Emit arithmetic operator. */ |
| 797 | static void bcemit_arith(FuncState *fs, BinOpr opr, ExpDesc *e1, ExpDesc *e2) | 838 | static void bcemit_arith(FuncState *fs, BinOpr opr, ExpDesc *e1, ExpDesc *e2) |
| 798 | { | 839 | { |
| 799 | BCReg rb, rc, t; | 840 | BCReg rb, rc, t; |
| 800 | uint32_t op; | 841 | uint32_t op; |
| 801 | if (foldarith(opr, e1, e2)) | ||
| 802 | return; | ||
| 803 | if (opr == OPR_POW) { | 842 | if (opr == OPR_POW) { |
| 804 | op = BC_POW; | 843 | op = BC_POW; |
| 805 | rc = expr_toanyreg(fs, e2); | 844 | rc = expr_toanyreg(fs, e2); |
| 806 | rb = expr_toanyreg(fs, e1); | 845 | rb = expr_toanyreg(fs, e1); |
| 846 | } else if (opr >= OPR_BAND) { | ||
| 847 | op = opr-OPR_BAND+BC_BAND; | ||
| 848 | rc = expr_toanyreg(fs, e2); | ||
| 849 | rb = expr_toanyreg(fs, e1); | ||
| 807 | } else { | 850 | } else { |
| 808 | op = opr-OPR_ADD+BC_ADDVV; | 851 | op = opr-OPR_ADD+BC_ADDVV; |
| 809 | /* Must discharge 2nd operand first since VINDEXED might free regs. */ | 852 | /* Must discharge 2nd operand first since VINDEXED might free regs. */ |
| @@ -887,6 +930,13 @@ static void bcemit_binop_left(FuncState *fs, BinOpr op, ExpDesc *e) | |||
| 887 | bcemit_branch_t(fs, e); | 930 | bcemit_branch_t(fs, e); |
| 888 | } else if (op == OPR_OR) { | 931 | } else if (op == OPR_OR) { |
| 889 | bcemit_branch_f(fs, e); | 932 | bcemit_branch_f(fs, e); |
| 933 | } else if (op == OPR_COAL) { | ||
| 934 | BCReg reg; | ||
| 935 | expr_tonextreg(fs, e); | ||
| 936 | reg = e->u.s.info; | ||
| 937 | bcemit_INS(fs, BCINS_AD(BC_ISNEP, reg, VKNIL)); | ||
| 938 | e->u.s.aux = bcemit_jmp(fs); | ||
| 939 | bcreg_free(fs, reg); | ||
| 890 | } else if (op == OPR_CONCAT) { | 940 | } else if (op == OPR_CONCAT) { |
| 891 | expr_tonextreg(fs, e); | 941 | expr_tonextreg(fs, e); |
| 892 | } else if (op == OPR_EQ || op == OPR_NE) { | 942 | } else if (op == OPR_EQ || op == OPR_NE) { |
| @@ -900,7 +950,12 @@ static void bcemit_binop_left(FuncState *fs, BinOpr op, ExpDesc *e) | |||
| 900 | static void bcemit_binop(FuncState *fs, BinOpr op, ExpDesc *e1, ExpDesc *e2) | 950 | static void bcemit_binop(FuncState *fs, BinOpr op, ExpDesc *e1, ExpDesc *e2) |
| 901 | { | 951 | { |
| 902 | if (op <= OPR_POW) { | 952 | if (op <= OPR_POW) { |
| 903 | bcemit_arith(fs, op, e1, e2); | 953 | if (!foldarith(op, e1, e2)) bcemit_arith(fs, op, e1, e2); |
| 954 | } else if (op <= OPR_BSAR) { | ||
| 955 | if (!foldbitop(op, e1, e2)) { | ||
| 956 | fs->flags |= PROTO_BITOP; | ||
| 957 | bcemit_arith(fs, op, e1, e2); | ||
| 958 | } | ||
| 904 | } else if (op == OPR_AND) { | 959 | } else if (op == OPR_AND) { |
| 905 | lj_assertFS(e1->t == NO_JMP, "jump list not closed"); | 960 | lj_assertFS(e1->t == NO_JMP, "jump list not closed"); |
| 906 | expr_discharge(fs, e2); | 961 | expr_discharge(fs, e2); |
| @@ -911,6 +966,9 @@ static void bcemit_binop(FuncState *fs, BinOpr op, ExpDesc *e1, ExpDesc *e2) | |||
| 911 | expr_discharge(fs, e2); | 966 | expr_discharge(fs, e2); |
| 912 | jmp_append(fs, &e2->t, e1->t); | 967 | jmp_append(fs, &e2->t, e1->t); |
| 913 | *e1 = *e2; | 968 | *e1 = *e2; |
| 969 | } else if (op == OPR_COAL) { | ||
| 970 | expr_tonextreg(fs, e2); | ||
| 971 | jmp_tohere(fs, e1->u.s.aux); | ||
| 914 | } else if (op == OPR_CONCAT) { | 972 | } else if (op == OPR_CONCAT) { |
| 915 | expr_toval(fs, e2); | 973 | expr_toval(fs, e2); |
| 916 | if (e2->k == VRELOCABLE && bc_op(*bcptr(fs, e2)) == BC_CAT) { | 974 | if (e2->k == VRELOCABLE && bc_op(*bcptr(fs, e2)) == BC_CAT) { |
| @@ -961,34 +1019,41 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e) | |||
| 961 | lj_assertFS(e->k == VNONRELOC, "bad expr type %d", e->k); | 1019 | lj_assertFS(e->k == VNONRELOC, "bad expr type %d", e->k); |
| 962 | } | 1020 | } |
| 963 | } else { | 1021 | } else { |
| 964 | lj_assertFS(op == BC_UNM || op == BC_LEN, "bad unop %d", op); | 1022 | lj_assertFS(op == BC_UNM || op == BC_LEN || op == BC_BNOT, "bad unop %d", op); |
| 965 | if (op == BC_UNM && !expr_hasjump(e)) { /* Constant-fold negations. */ | 1023 | if (!expr_hasjump(e)) { |
| 1024 | if (op == BC_UNM) { /* Constant-fold negations. */ | ||
| 966 | #if LJ_HASFFI | 1025 | #if LJ_HASFFI |
| 967 | if (e->k == VKCDATA) { /* Fold in-place since cdata is not interned. */ | 1026 | if (e->k == VKCDATA) { /* Fold in-place since cdata is not interned. */ |
| 968 | GCcdata *cd = cdataV(&e->u.nval); | 1027 | GCcdata *cd = cdataV(&e->u.nval); |
| 969 | uint64_t *p = (uint64_t *)cdataptr(cd); | 1028 | uint64_t *p = (uint64_t *)cdataptr(cd); |
| 970 | if (cd->ctypeid == CTID_COMPLEX_DOUBLE) | 1029 | if (cd->ctypeid == CTID_COMPLEX_DOUBLE) |
| 971 | p[1] ^= U64x(80000000,00000000); | 1030 | p[1] ^= U64x(80000000,00000000); |
| 972 | else | ||
| 973 | *p = ~*p+1u; | ||
| 974 | return; | ||
| 975 | } else | ||
| 976 | #endif | ||
| 977 | if (expr_isnumk(e) && !expr_numiszero(e)) { /* Avoid folding to -0. */ | ||
| 978 | TValue *o = expr_numtv(e); | ||
| 979 | if (tvisint(o)) { | ||
| 980 | int32_t k = intV(o), negk = (int32_t)(~(uint32_t)k+1u); | ||
| 981 | if (k == negk) | ||
| 982 | setnumV(o, -(lua_Number)k); | ||
| 983 | else | 1031 | else |
| 984 | setintV(o, negk); | 1032 | *p = ~*p+1u; |
| 985 | return; | ||
| 986 | } else { | ||
| 987 | o->u64 ^= U64x(80000000,00000000); | ||
| 988 | return; | 1033 | return; |
| 1034 | } else | ||
| 1035 | #endif | ||
| 1036 | if (expr_isnumk(e) && !expr_numiszero(e)) { /* Avoid folding to -0. */ | ||
| 1037 | TValue *o = expr_numtv(e); | ||
| 1038 | if (tvisint(o)) { | ||
| 1039 | int32_t k = intV(o), negk = (int32_t)(~(uint32_t)k+1u); | ||
| 1040 | if (k == negk) | ||
| 1041 | setnumV(o, -(lua_Number)k); | ||
| 1042 | else | ||
| 1043 | setintV(o, negk); | ||
| 1044 | return; | ||
| 1045 | } else { | ||
| 1046 | o->u64 ^= U64x(80000000,00000000); | ||
| 1047 | return; | ||
| 1048 | } | ||
| 989 | } | 1049 | } |
| 1050 | } else if (op == BC_BNOT && expr_isnumk(e)) { | ||
| 1051 | /* Constant-fold bitwise not. */ | ||
| 1052 | setintV(&e->u.nval, (int32_t)~(uint32_t)expr_bitV(e)); | ||
| 1053 | return; | ||
| 990 | } | 1054 | } |
| 991 | } | 1055 | } |
| 1056 | if (op == BC_BNOT) fs->flags |= PROTO_BITOP; | ||
| 992 | expr_toanyreg(fs, e); | 1057 | expr_toanyreg(fs, e); |
| 993 | } | 1058 | } |
| 994 | expr_free(fs, e); | 1059 | expr_free(fs, e); |
| @@ -1030,11 +1095,20 @@ static void lex_match(LexState *ls, LexToken what, LexToken who, BCLine line) | |||
| 1030 | } | 1095 | } |
| 1031 | } | 1096 | } |
| 1032 | 1097 | ||
| 1098 | /* Check for a name, including soft keywords. */ | ||
| 1099 | static LJ_AINLINE int lex_isname(LexToken tok) | ||
| 1100 | { | ||
| 1101 | return (tok == TK_name || | ||
| 1102 | (!LJ_52 && tok == TK_goto) || | ||
| 1103 | tok == TK_continue || | ||
| 1104 | tok == TK_const); | ||
| 1105 | } | ||
| 1106 | |||
| 1033 | /* Check for string token. */ | 1107 | /* Check for string token. */ |
| 1034 | static GCstr *lex_str(LexState *ls) | 1108 | static GCstr *lex_str(LexState *ls) |
| 1035 | { | 1109 | { |
| 1036 | GCstr *s; | 1110 | GCstr *s; |
| 1037 | if (ls->tok != TK_name && (LJ_52 || ls->tok != TK_goto)) | 1111 | if (!lex_isname(ls->tok)) |
| 1038 | err_token(ls, TK_name); | 1112 | err_token(ls, TK_name); |
| 1039 | s = strV(&ls->tokval); | 1113 | s = strV(&ls->tokval); |
| 1040 | lj_lex_next(ls); | 1114 | lj_lex_next(ls); |
| @@ -1045,11 +1119,31 @@ static GCstr *lex_str(LexState *ls) | |||
| 1045 | 1119 | ||
| 1046 | #define var_get(ls, fs, i) ((ls)->vstack[(fs)->varmap[(i)]]) | 1120 | #define var_get(ls, fs, i) ((ls)->vstack[(fs)->varmap[(i)]]) |
| 1047 | 1121 | ||
| 1122 | typedef intptr_t VarHash; /* For performance reasons. */ | ||
| 1123 | |||
| 1124 | /* Hash of a variable name. */ | ||
| 1125 | static LJ_AINLINE VarHash var_hash(GCstr *name) | ||
| 1126 | { | ||
| 1127 | if ((uintptr_t)name < VARNAME__MAX) | ||
| 1128 | return -1; | ||
| 1129 | else | ||
| 1130 | return (name->sid & LJ_VINDEX_MASK); /* Immutable id, not name->hash! */ | ||
| 1131 | } | ||
| 1132 | |||
| 1048 | /* Define a new local variable. */ | 1133 | /* Define a new local variable. */ |
| 1049 | static void var_new(LexState *ls, BCReg n, GCstr *name) | 1134 | static MSize var_new(LexState *ls, BCReg n, GCstr *name) |
| 1050 | { | 1135 | { |
| 1051 | FuncState *fs = ls->fs; | 1136 | FuncState *fs = ls->fs; |
| 1052 | MSize vtop = ls->vtop; | 1137 | MSize vtop = ls->vtop; |
| 1138 | if ((uintptr_t)name >= VARNAME__MAX) { /* Check for const re-declaration. */ | ||
| 1139 | MSize vidx = ls->vhash[var_hash(name)]; | ||
| 1140 | while (vidx != VINDEX_NONE) { | ||
| 1141 | VarInfo *v = &ls->vstack[vidx]; | ||
| 1142 | if (strref(v->name) == name && (v->info & VSTACK_CONST)) | ||
| 1143 | lj_lex_error(ls, 0, LJ_ERR_XCONSTR, strdata(name)); | ||
| 1144 | vidx = v->prev; | ||
| 1145 | } | ||
| 1146 | } | ||
| 1053 | checklimit(fs, fs->nactvar+n, LJ_MAX_LOCVAR, "local variables"); | 1147 | checklimit(fs, fs->nactvar+n, LJ_MAX_LOCVAR, "local variables"); |
| 1054 | if (LJ_UNLIKELY(vtop >= ls->sizevstack)) { | 1148 | if (LJ_UNLIKELY(vtop >= ls->sizevstack)) { |
| 1055 | if (ls->sizevstack >= LJ_MAX_VSTACK) | 1149 | if (ls->sizevstack >= LJ_MAX_VSTACK) |
| @@ -1061,8 +1155,11 @@ static void var_new(LexState *ls, BCReg n, GCstr *name) | |||
| 1061 | "unanchored variable name"); | 1155 | "unanchored variable name"); |
| 1062 | /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ | 1156 | /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ |
| 1063 | setgcref(ls->vstack[vtop].name, obj2gco(name)); | 1157 | setgcref(ls->vstack[vtop].name, obj2gco(name)); |
| 1158 | ls->vstack[vtop].info = 0; | ||
| 1159 | /* The other VarInfo fields are filled in by var_add and var_remove. */ | ||
| 1064 | fs->varmap[fs->nactvar+n] = (uint16_t)vtop; | 1160 | fs->varmap[fs->nactvar+n] = (uint16_t)vtop; |
| 1065 | ls->vtop = vtop+1; | 1161 | ls->vtop = vtop+1; |
| 1162 | return vtop; | ||
| 1066 | } | 1163 | } |
| 1067 | 1164 | ||
| 1068 | #define var_new_lit(ls, n, v) \ | 1165 | #define var_new_lit(ls, n, v) \ |
| @@ -1077,10 +1174,15 @@ static void var_add(LexState *ls, BCReg nvars) | |||
| 1077 | FuncState *fs = ls->fs; | 1174 | FuncState *fs = ls->fs; |
| 1078 | BCReg nactvar = fs->nactvar; | 1175 | BCReg nactvar = fs->nactvar; |
| 1079 | while (nvars--) { | 1176 | while (nvars--) { |
| 1080 | VarInfo *v = &var_get(ls, fs, nactvar); | 1177 | intptr_t vidx = fs->varmap[nactvar]; |
| 1178 | VarInfo *v = &ls->vstack[vidx]; | ||
| 1179 | VarHash hash = var_hash(strref(v->name)); | ||
| 1081 | v->startpc = fs->pc; | 1180 | v->startpc = fs->pc; |
| 1082 | v->slot = nactvar++; | 1181 | v->slot = nactvar++; |
| 1083 | v->info = 0; | 1182 | if (hash != -1) { |
| 1183 | v->prev = ls->vhash[hash]; | ||
| 1184 | ls->vhash[hash] = vidx; | ||
| 1185 | } | ||
| 1084 | } | 1186 | } |
| 1085 | fs->nactvar = nactvar; | 1187 | fs->nactvar = nactvar; |
| 1086 | } | 1188 | } |
| @@ -1089,70 +1191,86 @@ static void var_add(LexState *ls, BCReg nvars) | |||
| 1089 | static void var_remove(LexState *ls, BCReg tolevel) | 1191 | static void var_remove(LexState *ls, BCReg tolevel) |
| 1090 | { | 1192 | { |
| 1091 | FuncState *fs = ls->fs; | 1193 | FuncState *fs = ls->fs; |
| 1092 | while (fs->nactvar > tolevel) | 1194 | while (fs->nactvar > tolevel) { |
| 1093 | var_get(ls, fs, --fs->nactvar).endpc = fs->pc; | 1195 | VarInfo *v = &var_get(ls, fs, --fs->nactvar); |
| 1094 | } | 1196 | VarHash hash = var_hash(strref(v->name)); |
| 1095 | 1197 | v->endpc = fs->pc; | |
| 1096 | /* Lookup local variable name. */ | 1198 | if (hash != -1) { |
| 1097 | static BCReg var_lookup_local(FuncState *fs, GCstr *n) | 1199 | ls->vhash[hash] = v->prev; |
| 1098 | { | 1200 | } |
| 1099 | int i; | ||
| 1100 | for (i = fs->nactvar-1; i >= 0; i--) { | ||
| 1101 | if (n == strref(var_get(fs->ls, fs, i).name)) | ||
| 1102 | return (BCReg)i; | ||
| 1103 | } | 1201 | } |
| 1104 | return (BCReg)-1; /* Not found. */ | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | /* Lookup or add upvalue index. */ | ||
| 1108 | static MSize var_lookup_uv(FuncState *fs, MSize vidx, ExpDesc *e) | ||
| 1109 | { | ||
| 1110 | MSize i, n = fs->nuv; | ||
| 1111 | for (i = 0; i < n; i++) | ||
| 1112 | if (fs->uvmap[i] == vidx) | ||
| 1113 | return i; /* Already exists. */ | ||
| 1114 | /* Otherwise create a new one. */ | ||
| 1115 | checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues"); | ||
| 1116 | lj_assertFS(e->k == VLOCAL || e->k == VUPVAL, "bad expr type %d", e->k); | ||
| 1117 | fs->uvmap[n] = (uint16_t)vidx; | ||
| 1118 | fs->uvtmp[n] = (uint16_t)(e->k == VLOCAL ? vidx : LJ_MAX_VSTACK+e->u.s.info); | ||
| 1119 | fs->nuv = n+1; | ||
| 1120 | return n; | ||
| 1121 | } | 1202 | } |
| 1122 | 1203 | ||
| 1123 | /* Forward declaration. */ | 1204 | /* Forward declaration. */ |
| 1124 | static void fscope_uvmark(FuncState *fs, BCReg level); | 1205 | static void fscope_uvmark(FuncState *fs, BCReg level); |
| 1125 | 1206 | ||
| 1126 | /* Recursively lookup variables in enclosing functions. */ | 1207 | /* Lookup variable name. */ |
| 1127 | static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) | 1208 | static MSize var_lookup(LexState *ls, ExpDesc *e, GCstr *name) |
| 1128 | { | 1209 | { |
| 1129 | if (fs) { | 1210 | MSize vidx = ls->vhash[var_hash(name)]; |
| 1130 | BCReg reg = var_lookup_local(fs, name); | 1211 | while (vidx != VINDEX_NONE) { |
| 1131 | if ((int32_t)reg >= 0) { /* Local in this function? */ | 1212 | VarInfo *v = &ls->vstack[vidx]; |
| 1132 | expr_init(e, VLOCAL, reg); | 1213 | if (strref(v->name) == name) { |
| 1133 | if (!first) | 1214 | FuncState *fs = ls->fs; |
| 1134 | fscope_uvmark(fs, reg); /* Scope now has an upvalue. */ | 1215 | if (vidx >= fs->vbase) { |
| 1135 | return (MSize)(e->u.s.aux = (uint32_t)fs->varmap[reg]); | 1216 | expr_init(e, VLOCAL, v->slot); |
| 1136 | } else { | 1217 | e->u.s.aux = vidx; |
| 1137 | MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer func? */ | 1218 | } else { |
| 1138 | if ((int32_t)vidx >= 0) { /* Yes, make it an upvalue here. */ | 1219 | MSize uvidx, nuv = fs->nuv; |
| 1139 | e->u.s.info = (uint8_t)var_lookup_uv(fs, vidx, e); | 1220 | e->u.s.aux = vidx; |
| 1140 | e->k = VUPVAL; | 1221 | for (uvidx = 0; uvidx < nuv; uvidx++) { |
| 1141 | return vidx; | 1222 | if (fs->uvmap[uvidx] == vidx) { /* Upvalue already exists. */ |
| 1223 | expr_init(e, VUPVAL, uvidx); | ||
| 1224 | return vidx; | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | expr_init(e, VUPVAL, nuv); | ||
| 1228 | for (;;) { | ||
| 1229 | /* Create a new upvalue. */ | ||
| 1230 | VarIndex *puvtmp; | ||
| 1231 | checklimit(fs, nuv, LJ_MAX_UPVAL, "upvalues"); | ||
| 1232 | fs->uvmap[nuv] = (uint16_t)vidx; | ||
| 1233 | fs->nuv = nuv + 1; | ||
| 1234 | puvtmp = &fs->uvtmp[nuv]; /* Set below. */ | ||
| 1235 | fs = fs->prev; /* Continue in parent. */ | ||
| 1236 | lj_assertLS(fs != NULL, "variable hash chain broken"); | ||
| 1237 | if (vidx >= fs->vbase) { /* Local in that function. */ | ||
| 1238 | *puvtmp = vidx; | ||
| 1239 | fscope_uvmark(fs, v->slot); | ||
| 1240 | return vidx; | ||
| 1241 | } | ||
| 1242 | /* Not a local in that function. Find or create upvalue. */ | ||
| 1243 | nuv = fs->nuv; | ||
| 1244 | for (uvidx = 0; uvidx < nuv; uvidx++) { | ||
| 1245 | if (fs->uvmap[uvidx] == vidx) { /* Upvalue already exists. */ | ||
| 1246 | *puvtmp = LJ_MAX_VSTACK + uvidx; | ||
| 1247 | return vidx; | ||
| 1248 | } | ||
| 1249 | } | ||
| 1250 | /* Not yet an upvalue. Create it and continue. */ | ||
| 1251 | *puvtmp = LJ_MAX_VSTACK + nuv; | ||
| 1252 | } | ||
| 1142 | } | 1253 | } |
| 1254 | return vidx; | ||
| 1143 | } | 1255 | } |
| 1144 | } else { /* Not found in any function, must be a global. */ | 1256 | vidx = v->prev; |
| 1145 | expr_init(e, VGLOBAL, 0); | ||
| 1146 | e->u.sval = name; | ||
| 1147 | } | 1257 | } |
| 1148 | return (MSize)-1; /* Global. */ | 1258 | expr_init(e, VGLOBAL, 0); |
| 1259 | e->u.sval = name; | ||
| 1260 | return vidx; | ||
| 1149 | } | 1261 | } |
| 1150 | 1262 | ||
| 1151 | /* Lookup variable name. */ | 1263 | /* Check for const variable assignment. */ |
| 1152 | #define var_lookup(ls, e) \ | 1264 | static void var_assign(LexState *ls, ExpDesc *e) |
| 1153 | var_lookup_((ls)->fs, lex_str(ls), (e), 1) | 1265 | { |
| 1266 | if (e->k == VLOCAL || e->k == VUPVAL) { | ||
| 1267 | VarInfo *v = &ls->vstack[e->u.s.aux]; | ||
| 1268 | if ((v->info & VSTACK_CONST)) | ||
| 1269 | lj_lex_error(ls, 0, LJ_ERR_XCONSTA, strdata(strref(v->name))); | ||
| 1270 | } | ||
| 1271 | } | ||
| 1154 | 1272 | ||
| 1155 | /* -- Goto an label handling ---------------------------------------------- */ | 1273 | /* -- Goto and label handling --------------------------------------------- */ |
| 1156 | 1274 | ||
| 1157 | /* Add a new goto or label. */ | 1275 | /* Add a new goto or label. */ |
| 1158 | static MSize gola_new(LexState *ls, GCstr *name, uint8_t info, BCPos pc) | 1276 | static MSize gola_new(LexState *ls, GCstr *name, uint8_t info, BCPos pc) |
| @@ -1164,7 +1282,8 @@ static MSize gola_new(LexState *ls, GCstr *name, uint8_t info, BCPos pc) | |||
| 1164 | lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK); | 1282 | lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK); |
| 1165 | lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo); | 1283 | lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo); |
| 1166 | } | 1284 | } |
| 1167 | lj_assertFS(name == NAME_BREAK || lj_tab_getstr(fs->kt, name) != NULL, | 1285 | lj_assertFS(name == NAME_BREAK || name == NAME_CONT || |
| 1286 | lj_tab_getstr(fs->kt, name) != NULL, | ||
| 1168 | "unanchored label name"); | 1287 | "unanchored label name"); |
| 1169 | /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ | 1288 | /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ |
| 1170 | setgcref(ls->vstack[vtop].name, obj2gco(name)); | 1289 | setgcref(ls->vstack[vtop].name, obj2gco(name)); |
| @@ -1219,8 +1338,12 @@ static void gola_resolve(LexState *ls, FuncScope *bl, MSize idx) | |||
| 1219 | lj_assertLS((uintptr_t)name >= VARNAME__MAX, "expected goto name"); | 1338 | lj_assertLS((uintptr_t)name >= VARNAME__MAX, "expected goto name"); |
| 1220 | ls->linenumber = ls->fs->bcbase[vg->startpc].line; | 1339 | ls->linenumber = ls->fs->bcbase[vg->startpc].line; |
| 1221 | lj_assertLS(strref(vg->name) != NAME_BREAK, "unexpected break"); | 1340 | lj_assertLS(strref(vg->name) != NAME_BREAK, "unexpected break"); |
| 1222 | lj_lex_error(ls, 0, LJ_ERR_XGSCOPE, | 1341 | if (strref(vg->name) == NAME_CONT) { |
| 1223 | strdata(strref(vg->name)), strdata(name)); | 1342 | lj_lex_error(ls, 0, LJ_ERR_XCSCOPE, strdata(name)); |
| 1343 | } else { | ||
| 1344 | lj_lex_error(ls, 0, LJ_ERR_XGSCOPE, | ||
| 1345 | strdata(strref(vg->name)), strdata(name)); | ||
| 1346 | } | ||
| 1224 | } | 1347 | } |
| 1225 | gola_patch(ls, vg, vl); | 1348 | gola_patch(ls, vg, vl); |
| 1226 | } | 1349 | } |
| @@ -1244,8 +1367,10 @@ static void gola_fixup(LexState *ls, FuncScope *bl) | |||
| 1244 | gola_patch(ls, vg, v); | 1367 | gola_patch(ls, vg, v); |
| 1245 | } | 1368 | } |
| 1246 | } else if (gola_isgoto(v)) { | 1369 | } else if (gola_isgoto(v)) { |
| 1247 | if (bl->prev) { /* Propagate goto or break to outer scope. */ | 1370 | if (bl->prev) { /* Propagate goto, break or continue to outer scope. */ |
| 1248 | bl->prev->flags |= name == NAME_BREAK ? FSCOPE_BREAK : FSCOPE_GOLA; | 1371 | bl->prev->flags |= name == NAME_BREAK ? FSCOPE_BREAK : |
| 1372 | name == NAME_CONT ? FSCOPE_CONT : | ||
| 1373 | FSCOPE_GOLA; | ||
| 1249 | v->slot = bl->nactvar; | 1374 | v->slot = bl->nactvar; |
| 1250 | if ((bl->flags & FSCOPE_UPVAL)) | 1375 | if ((bl->flags & FSCOPE_UPVAL)) |
| 1251 | gola_close(ls, v); | 1376 | gola_close(ls, v); |
| @@ -1253,6 +1378,8 @@ static void gola_fixup(LexState *ls, FuncScope *bl) | |||
| 1253 | ls->linenumber = ls->fs->bcbase[v->startpc].line; | 1378 | ls->linenumber = ls->fs->bcbase[v->startpc].line; |
| 1254 | if (name == NAME_BREAK) | 1379 | if (name == NAME_BREAK) |
| 1255 | lj_lex_error(ls, 0, LJ_ERR_XBREAK); | 1380 | lj_lex_error(ls, 0, LJ_ERR_XBREAK); |
| 1381 | else if (name == NAME_CONT) | ||
| 1382 | lj_lex_error(ls, 0, LJ_ERR_XCONT); | ||
| 1256 | else | 1383 | else |
| 1257 | lj_lex_error(ls, 0, LJ_ERR_XLUNDEF, strdata(name)); | 1384 | lj_lex_error(ls, 0, LJ_ERR_XLUNDEF, strdata(name)); |
| 1258 | } | 1385 | } |
| @@ -1296,21 +1423,33 @@ static void fscope_end(FuncState *fs) | |||
| 1296 | lj_assertFS(bl->nactvar == fs->nactvar, "bad regalloc"); | 1423 | lj_assertFS(bl->nactvar == fs->nactvar, "bad regalloc"); |
| 1297 | if ((bl->flags & (FSCOPE_UPVAL|FSCOPE_NOCLOSE)) == FSCOPE_UPVAL) | 1424 | if ((bl->flags & (FSCOPE_UPVAL|FSCOPE_NOCLOSE)) == FSCOPE_UPVAL) |
| 1298 | bcemit_AJ(fs, BC_UCLO, bl->nactvar, 0); | 1425 | bcemit_AJ(fs, BC_UCLO, bl->nactvar, 0); |
| 1299 | if ((bl->flags & FSCOPE_BREAK)) { | 1426 | lj_assertFS((bl->flags & (FSCOPE_LOOP|FSCOPE_CONT)) != (FSCOPE_LOOP|FSCOPE_CONT), "dangling continue"); |
| 1300 | if ((bl->flags & FSCOPE_LOOP)) { | 1427 | if ((bl->flags & (FSCOPE_LOOP|FSCOPE_BREAK)) == (FSCOPE_LOOP|FSCOPE_BREAK)) { |
| 1301 | MSize idx = gola_new(ls, NAME_BREAK, VSTACK_LABEL, fs->pc); | 1428 | MSize idx; |
| 1302 | ls->vtop = idx; /* Drop break label immediately. */ | 1429 | bl->flags &= ~FSCOPE_BREAK; |
| 1303 | gola_resolve(ls, bl, idx); | 1430 | idx = gola_new(ls, NAME_BREAK, VSTACK_LABEL, fs->pc); |
| 1304 | } else { /* Need the fixup step to propagate the breaks. */ | 1431 | ls->vtop = idx; /* Drop break label immediately. */ |
| 1305 | gola_fixup(ls, bl); | 1432 | gola_resolve(ls, bl, idx); |
| 1306 | return; | 1433 | } |
| 1307 | } | 1434 | if ((bl->flags & (FSCOPE_GOLA|FSCOPE_BREAK|FSCOPE_CONT))) { |
| 1308 | } | ||
| 1309 | if ((bl->flags & FSCOPE_GOLA)) { | ||
| 1310 | gola_fixup(ls, bl); | 1435 | gola_fixup(ls, bl); |
| 1311 | } | 1436 | } |
| 1312 | } | 1437 | } |
| 1313 | 1438 | ||
| 1439 | /* Add continue label. */ | ||
| 1440 | static void fscope_continue(FuncState *fs, BCPos cont) | ||
| 1441 | { | ||
| 1442 | FuncScope *bl = fs->bl; | ||
| 1443 | if ((bl->flags & FSCOPE_CONT)) { | ||
| 1444 | LexState *ls = fs->ls; | ||
| 1445 | MSize idx; | ||
| 1446 | bl->flags &= ~FSCOPE_CONT; | ||
| 1447 | idx = gola_new(ls, NAME_CONT, VSTACK_LABEL, cont); | ||
| 1448 | ls->vtop = idx; /* Drop continue label immediately. */ | ||
| 1449 | gola_resolve(ls, bl, idx); | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | |||
| 1314 | /* Mark scope as having an upvalue. */ | 1453 | /* Mark scope as having an upvalue. */ |
| 1315 | static void fscope_uvmark(FuncState *fs, BCReg level) | 1454 | static void fscope_uvmark(FuncState *fs, BCReg level) |
| 1316 | { | 1455 | { |
| @@ -1460,7 +1599,7 @@ static void fs_fixup_line(FuncState *fs, GCproto *pt, | |||
| 1460 | /* Prepare variable info for prototype. */ | 1599 | /* Prepare variable info for prototype. */ |
| 1461 | static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) | 1600 | static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) |
| 1462 | { | 1601 | { |
| 1463 | VarInfo *vs =ls->vstack, *ve; | 1602 | VarInfo *vs = ls->vstack, *ve; |
| 1464 | MSize i, n; | 1603 | MSize i, n; |
| 1465 | BCPos lastpc; | 1604 | BCPos lastpc; |
| 1466 | lj_buf_reset(&ls->sb); /* Copy to temp. string buffer. */ | 1605 | lj_buf_reset(&ls->sb); /* Copy to temp. string buffer. */ |
| @@ -1633,7 +1772,7 @@ static void fs_init(LexState *ls, FuncState *fs) | |||
| 1633 | /* -- Expressions --------------------------------------------------------- */ | 1772 | /* -- Expressions --------------------------------------------------------- */ |
| 1634 | 1773 | ||
| 1635 | /* Forward declaration. */ | 1774 | /* Forward declaration. */ |
| 1636 | static void expr(LexState *ls, ExpDesc *v); | 1775 | static void expr(LexState *ls, ExpDesc *v, int nocolon); |
| 1637 | 1776 | ||
| 1638 | /* Return string expression. */ | 1777 | /* Return string expression. */ |
| 1639 | static void expr_str(LexState *ls, ExpDesc *e) | 1778 | static void expr_str(LexState *ls, ExpDesc *e) |
| @@ -1680,7 +1819,6 @@ static void expr_field(LexState *ls, ExpDesc *v) | |||
| 1680 | FuncState *fs = ls->fs; | 1819 | FuncState *fs = ls->fs; |
| 1681 | ExpDesc key; | 1820 | ExpDesc key; |
| 1682 | expr_toanyreg(fs, v); | 1821 | expr_toanyreg(fs, v); |
| 1683 | lj_lex_next(ls); /* Skip dot or colon. */ | ||
| 1684 | expr_str(ls, &key); | 1822 | expr_str(ls, &key); |
| 1685 | expr_index(fs, v, &key); | 1823 | expr_index(fs, v, &key); |
| 1686 | } | 1824 | } |
| @@ -1689,7 +1827,7 @@ static void expr_field(LexState *ls, ExpDesc *v) | |||
| 1689 | static void expr_bracket(LexState *ls, ExpDesc *v) | 1827 | static void expr_bracket(LexState *ls, ExpDesc *v) |
| 1690 | { | 1828 | { |
| 1691 | lj_lex_next(ls); /* Skip '['. */ | 1829 | lj_lex_next(ls); /* Skip '['. */ |
| 1692 | expr(ls, v); | 1830 | expr(ls, v, 0); |
| 1693 | expr_toval(ls->fs, v); | 1831 | expr_toval(ls->fs, v); |
| 1694 | lex_check(ls, ']'); | 1832 | lex_check(ls, ']'); |
| 1695 | } | 1833 | } |
| @@ -1731,8 +1869,7 @@ static void expr_table(LexState *ls, ExpDesc *e) | |||
| 1731 | if (!expr_isk(&key)) expr_index(fs, e, &key); | 1869 | if (!expr_isk(&key)) expr_index(fs, e, &key); |
| 1732 | if (expr_isnumk(&key) && expr_numiszero(&key)) needarr = 1; else nhash++; | 1870 | if (expr_isnumk(&key) && expr_numiszero(&key)) needarr = 1; else nhash++; |
| 1733 | lex_check(ls, '='); | 1871 | lex_check(ls, '='); |
| 1734 | } else if ((ls->tok == TK_name || (!LJ_52 && ls->tok == TK_goto)) && | 1872 | } else if (lex_isname(ls->tok) && lj_lex_lookahead(ls) == '=') { |
| 1735 | lj_lex_lookahead(ls) == '=') { | ||
| 1736 | expr_str(ls, &key); | 1873 | expr_str(ls, &key); |
| 1737 | lex_check(ls, '='); | 1874 | lex_check(ls, '='); |
| 1738 | nhash++; | 1875 | nhash++; |
| @@ -1742,7 +1879,7 @@ static void expr_table(LexState *ls, ExpDesc *e) | |||
| 1742 | narr++; | 1879 | narr++; |
| 1743 | needarr = vcall = 1; | 1880 | needarr = vcall = 1; |
| 1744 | } | 1881 | } |
| 1745 | expr(ls, &val); | 1882 | expr(ls, &val, 0); |
| 1746 | if (expr_isk(&key) && key.k != VKNIL && | 1883 | if (expr_isk(&key) && key.k != VKNIL && |
| 1747 | (key.k == VKSTR || expr_isk_nojump(&val))) { | 1884 | (key.k == VKSTR || expr_isk_nojump(&val))) { |
| 1748 | TValue k, *v; | 1885 | TValue k, *v; |
| @@ -1766,7 +1903,10 @@ static void expr_table(LexState *ls, ExpDesc *e) | |||
| 1766 | } | 1903 | } |
| 1767 | } else { | 1904 | } else { |
| 1768 | nonconst: | 1905 | nonconst: |
| 1769 | if (val.k != VCALL) { expr_toanyreg(fs, &val); vcall = 0; } | 1906 | if (val.k != VCALL) { |
| 1907 | expr_toanyreg(fs, &val); | ||
| 1908 | vcall = 0; | ||
| 1909 | } | ||
| 1770 | if (expr_isk(&key)) expr_index(fs, e, &key); | 1910 | if (expr_isk(&key)) expr_index(fs, e, &key); |
| 1771 | bcemit_store(fs, e, &val); | 1911 | bcemit_store(fs, e, &val); |
| 1772 | } | 1912 | } |
| @@ -1808,16 +1948,17 @@ static void expr_table(LexState *ls, ExpDesc *e) | |||
| 1808 | } | 1948 | } |
| 1809 | 1949 | ||
| 1810 | /* Parse function parameters. */ | 1950 | /* Parse function parameters. */ |
| 1811 | static BCReg parse_params(LexState *ls, int needself) | 1951 | static BCReg parse_params(LexState *ls, int needself, |
| 1952 | LexToken before, LexToken after) | ||
| 1812 | { | 1953 | { |
| 1813 | FuncState *fs = ls->fs; | 1954 | FuncState *fs = ls->fs; |
| 1814 | BCReg nparams = 0; | 1955 | BCReg nparams = 0; |
| 1815 | lex_check(ls, '('); | 1956 | lex_check(ls, before); |
| 1816 | if (needself) | 1957 | if (needself) |
| 1817 | var_new_lit(ls, nparams++, "self"); | 1958 | var_new_lit(ls, nparams++, "self"); |
| 1818 | if (ls->tok != ')') { | 1959 | if (ls->tok != after) { |
| 1819 | do { | 1960 | do { |
| 1820 | if (ls->tok == TK_name || (!LJ_52 && ls->tok == TK_goto)) { | 1961 | if (lex_isname(ls->tok)) { |
| 1821 | var_new(ls, nparams++, lex_str(ls)); | 1962 | var_new(ls, nparams++, lex_str(ls)); |
| 1822 | } else if (ls->tok == TK_dots) { | 1963 | } else if (ls->tok == TK_dots) { |
| 1823 | lj_lex_next(ls); | 1964 | lj_lex_next(ls); |
| @@ -1831,54 +1972,96 @@ static BCReg parse_params(LexState *ls, int needself) | |||
| 1831 | var_add(ls, nparams); | 1972 | var_add(ls, nparams); |
| 1832 | lj_assertFS(fs->nactvar == nparams, "bad regalloc"); | 1973 | lj_assertFS(fs->nactvar == nparams, "bad regalloc"); |
| 1833 | bcreg_reserve(fs, nparams); | 1974 | bcreg_reserve(fs, nparams); |
| 1834 | lex_check(ls, ')'); | 1975 | lex_check(ls, after); |
| 1835 | return nparams; | 1976 | return nparams; |
| 1836 | } | 1977 | } |
| 1837 | 1978 | ||
| 1838 | /* Forward declaration. */ | 1979 | /* Forward declarations. */ |
| 1839 | static void parse_chunk(LexState *ls); | 1980 | static void parse_chunk(LexState *ls); |
| 1981 | static void parse_return(LexState *ls, int eflags); | ||
| 1840 | 1982 | ||
| 1841 | /* Parse body of a function. */ | 1983 | /* Begin a new function prototype. */ |
| 1842 | static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) | 1984 | static void proto_begin(FuncState *fs, BCLine line, BCReg nparams) |
| 1843 | { | 1985 | { |
| 1844 | FuncState fs, *pfs = ls->fs; | 1986 | FuncState *pfs = fs->prev; |
| 1845 | FuncScope bl; | 1987 | fs->linedefined = line; |
| 1846 | GCproto *pt; | 1988 | fs->numparams = (uint8_t)nparams; |
| 1847 | ptrdiff_t oldbase = pfs->bcbase - ls->bcstack; | 1989 | fs->bcbase = pfs->bcbase + pfs->pc; |
| 1848 | fs_init(ls, &fs); | 1990 | fs->bclim = pfs->bclim - pfs->pc; |
| 1849 | fscope_begin(&fs, &bl, 0); | 1991 | bcemit_AD(fs, BC_FUNCF, 0, 0); /* Placeholder. */ |
| 1850 | fs.linedefined = line; | 1992 | } |
| 1851 | fs.numparams = (uint8_t)parse_params(ls, needself); | 1993 | |
| 1852 | fs.bcbase = pfs->bcbase + pfs->pc; | 1994 | /* Finish a function prototype. */ |
| 1853 | fs.bclim = pfs->bclim - pfs->pc; | 1995 | static void proto_finish(LexState *ls, ExpDesc *e, ptrdiff_t oldbase) |
| 1854 | bcemit_AD(&fs, BC_FUNCF, 0, 0); /* Placeholder. */ | 1996 | { |
| 1855 | parse_chunk(ls); | 1997 | MSize flags = (ls->fs->flags & (PROTO_FFI|PROTO_BITOP)); |
| 1856 | if (ls->tok != TK_end) lex_match(ls, TK_end, TK_function, line); | 1998 | GCproto *pt = fs_finish(ls, (ls->lastline = ls->linenumber)); |
| 1857 | pt = fs_finish(ls, (ls->lastline = ls->linenumber)); | 1999 | FuncState *pfs = ls->fs; |
| 1858 | pfs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */ | 2000 | pfs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */ |
| 1859 | pfs->bclim = (BCPos)(ls->sizebcstack - oldbase); | 2001 | pfs->bclim = (BCPos)(ls->sizebcstack - oldbase); |
| 1860 | /* Store new prototype in the constant array of the parent. */ | 2002 | /* Store new prototype in the constant array of the parent. */ |
| 1861 | expr_init(e, VRELOCABLE, | 2003 | expr_init(e, VRELOCABLE, |
| 1862 | bcemit_AD(pfs, BC_FNEW, 0, const_gc(pfs, obj2gco(pt), LJ_TPROTO))); | 2004 | bcemit_AD(pfs, BC_FNEW, 0, const_gc(pfs, obj2gco(pt), LJ_TPROTO))); |
| 1863 | #if LJ_HASFFI | 2005 | pfs->flags |= (uint8_t)flags; /* Inherited flags. */ |
| 1864 | pfs->flags |= (fs.flags & PROTO_FFI); | ||
| 1865 | #endif | ||
| 1866 | if (!(pfs->flags & PROTO_CHILD)) { | 2006 | if (!(pfs->flags & PROTO_CHILD)) { |
| 1867 | if (pfs->flags & PROTO_HAS_RETURN) | 2007 | if (pfs->flags & PROTO_HAS_RETURN) |
| 1868 | pfs->flags |= PROTO_FIXUP_RETURN; | 2008 | pfs->flags |= PROTO_FIXUP_RETURN; |
| 1869 | pfs->flags |= PROTO_CHILD; | 2009 | pfs->flags |= PROTO_CHILD; |
| 1870 | } | 2010 | } |
| 2011 | } | ||
| 2012 | |||
| 2013 | /* Parse body of a function. */ | ||
| 2014 | static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) | ||
| 2015 | { | ||
| 2016 | ptrdiff_t oldbase = ls->fs->bcbase - ls->bcstack; | ||
| 2017 | FuncState fs; | ||
| 2018 | FuncScope bl; | ||
| 2019 | fs_init(ls, &fs); | ||
| 2020 | fscope_begin(&fs, &bl, 0); | ||
| 2021 | proto_begin(&fs, line, parse_params(ls, needself, '(', ')')); | ||
| 2022 | parse_chunk(ls); | ||
| 2023 | if (ls->tok != TK_end) lex_match(ls, TK_end, TK_function, line); | ||
| 2024 | proto_finish(ls, e, oldbase); | ||
| 1871 | lj_lex_next(ls); | 2025 | lj_lex_next(ls); |
| 1872 | } | 2026 | } |
| 1873 | 2027 | ||
| 2028 | /* Parse short function. */ | ||
| 2029 | static void parse_shortfunc(LexState *ls, ExpDesc *e, GCstr *name, | ||
| 2030 | int eflags, BCLine line) | ||
| 2031 | { | ||
| 2032 | ptrdiff_t oldbase = ls->fs->bcbase - ls->bcstack; | ||
| 2033 | FuncState fs; | ||
| 2034 | FuncScope bl; | ||
| 2035 | BCReg nparams = 0; | ||
| 2036 | fs_init(ls, &fs); | ||
| 2037 | fscope_begin(&fs, &bl, 0); | ||
| 2038 | if (name != NULL) { | ||
| 2039 | setboolV(lj_tab_setstr(ls->L, fs.kt, name), 1); /* Anchor in new proto. */ | ||
| 2040 | var_new(ls, nparams++, name); | ||
| 2041 | var_add(ls, nparams); | ||
| 2042 | bcreg_reserve(&fs, 1); | ||
| 2043 | } else if (!lex_opt(ls, TK_or_)) { | ||
| 2044 | nparams = parse_params(ls, 0, '|', '|'); | ||
| 2045 | } | ||
| 2046 | lex_check(ls, TK_arrow); | ||
| 2047 | proto_begin(&fs, line, nparams); | ||
| 2048 | if (lex_opt(ls, TK_do)) { | ||
| 2049 | parse_chunk(ls); | ||
| 2050 | if (!lex_opt(ls, TK_end)) lex_match(ls, TK_end, TK_do, line); | ||
| 2051 | } else { | ||
| 2052 | parse_return(ls, (eflags | EXPR_F_RET1)); | ||
| 2053 | } | ||
| 2054 | proto_finish(ls, e, oldbase); | ||
| 2055 | } | ||
| 2056 | |||
| 1874 | /* Parse expression list. Last expression is left open. */ | 2057 | /* Parse expression list. Last expression is left open. */ |
| 1875 | static BCReg expr_list(LexState *ls, ExpDesc *v) | 2058 | static BCReg expr_list(LexState *ls, ExpDesc *v) |
| 1876 | { | 2059 | { |
| 1877 | BCReg n = 1; | 2060 | BCReg n = 1; |
| 1878 | expr(ls, v); | 2061 | expr(ls, v, 0); |
| 1879 | while (lex_opt(ls, ',')) { | 2062 | while (lex_opt(ls, ',')) { |
| 1880 | expr_tonextreg(ls->fs, v); | 2063 | expr_tonextreg(ls->fs, v); |
| 1881 | expr(ls, v); | 2064 | expr(ls, v, 0); |
| 1882 | n++; | 2065 | n++; |
| 1883 | } | 2066 | } |
| 1884 | return n; | 2067 | return n; |
| @@ -1931,48 +2114,102 @@ static void parse_args(LexState *ls, ExpDesc *e) | |||
| 1931 | fs->freereg = base+1; /* Leave one result by default. */ | 2114 | fs->freereg = base+1; /* Leave one result by default. */ |
| 1932 | } | 2115 | } |
| 1933 | 2116 | ||
| 1934 | /* Parse primary expression. */ | 2117 | /* Parse primary expression with safe navigation. */ |
| 1935 | static void expr_primary(LexState *ls, ExpDesc *v) | 2118 | static BCPos expr_primary_nav(LexState *ls, ExpDesc *v, int eflags) |
| 1936 | { | 2119 | { |
| 1937 | FuncState *fs = ls->fs; | 2120 | FuncState *fs = ls->fs; |
| 2121 | BCPos xpc = NO_JMP; | ||
| 1938 | /* Parse prefix expression. */ | 2122 | /* Parse prefix expression. */ |
| 1939 | if (ls->tok == '(') { | 2123 | if (ls->tok == '(') { |
| 1940 | BCLine line = ls->linenumber; | 2124 | BCLine line = ls->linenumber; |
| 1941 | lj_lex_next(ls); | 2125 | lj_lex_next(ls); |
| 1942 | expr(ls, v); | 2126 | expr(ls, v, 0); /* Don't propagate eflags. */ |
| 1943 | lex_match(ls, ')', '(', line); | 2127 | lex_match(ls, ')', '(', line); |
| 1944 | expr_discharge(ls->fs, v); | 2128 | expr_discharge(ls->fs, v); |
| 1945 | } else if (ls->tok == TK_name || (!LJ_52 && ls->tok == TK_goto)) { | 2129 | } else if (lex_isname(ls->tok)) { |
| 1946 | var_lookup(ls, v); | 2130 | BCLine line = ls->linenumber; |
| 2131 | GCstr *name = lex_str(ls); | ||
| 2132 | if (!(eflags & EXPR_F_NORES) && ls->tok == TK_arrow) { | ||
| 2133 | parse_shortfunc(ls, v, name, eflags, line); | ||
| 2134 | return xpc; | ||
| 2135 | } | ||
| 2136 | var_lookup(ls, v, name); | ||
| 1947 | } else { | 2137 | } else { |
| 2138 | err: | ||
| 1948 | err_syntax(ls, LJ_ERR_XSYMBOL); | 2139 | err_syntax(ls, LJ_ERR_XSYMBOL); |
| 1949 | } | 2140 | } |
| 1950 | for (;;) { /* Parse multiple expression suffixes. */ | 2141 | for (;;) { /* Parse multiple expression suffixes. */ |
| 1951 | if (ls->tok == '.') { | 2142 | int nav = 0; |
| 1952 | expr_field(ls, v); | 2143 | if (!(eflags & EXPR_F_NONAV) && lex_opt(ls, TK_nav)) { |
| 1953 | } else if (ls->tok == '[') { | 2144 | nav = 1; |
| 2145 | expr_toanyreg(fs, v); | ||
| 2146 | bcemit_INS(fs, BCINS_AD(BC_ISEQP, v->u.s.info, VKNIL)); | ||
| 2147 | jmp_append(fs, &xpc, bcemit_jmp(fs)); | ||
| 2148 | } | ||
| 2149 | if (ls->tok == '[') { | ||
| 1954 | ExpDesc key; | 2150 | ExpDesc key; |
| 1955 | expr_toanyreg(fs, v); | 2151 | expr_toanyreg(fs, v); |
| 1956 | expr_bracket(ls, &key); | 2152 | expr_bracket(ls, &key); |
| 1957 | expr_index(fs, v, &key); | 2153 | expr_index(fs, v, &key); |
| 1958 | } else if (ls->tok == ':') { | 2154 | } else if (ls->tok == ':') { |
| 1959 | ExpDesc key; | 2155 | ExpDesc key; |
| 1960 | lj_lex_next(ls); | 2156 | if ((eflags & EXPR_F_NOCOLON)) { |
| 2157 | if (nav) goto err; | ||
| 2158 | break; | ||
| 2159 | } | ||
| 2160 | lj_lex_next(ls); /* Skip ':'. */ | ||
| 1961 | expr_str(ls, &key); | 2161 | expr_str(ls, &key); |
| 1962 | bcemit_method(fs, v, &key); | 2162 | bcemit_method(fs, v, &key); |
| 1963 | parse_args(ls, v); | 2163 | nav = 0; |
| 2164 | if (lex_opt(ls, TK_nav)) { | ||
| 2165 | nav = 1; | ||
| 2166 | bcemit_INS(fs, BCINS_AD(BC_ISEQP, v->u.s.info, VKNIL)); | ||
| 2167 | jmp_append(fs, &xpc, bcemit_jmp(fs)); | ||
| 2168 | } | ||
| 2169 | goto call; | ||
| 1964 | } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { | 2170 | } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { |
| 1965 | expr_tonextreg(fs, v); | 2171 | expr_tonextreg(fs, v); |
| 1966 | if (ls->fr2) bcreg_reserve(fs, 1); | 2172 | if (ls->fr2) bcreg_reserve(fs, 1); |
| 2173 | call: | ||
| 1967 | parse_args(ls, v); | 2174 | parse_args(ls, v); |
| 2175 | /* Keep nav VCALL if no suffix follows. */ | ||
| 2176 | if (nav && !(eflags & EXPR_F_NORES) && | ||
| 2177 | !(ls->tok == TK_nav || ls->tok == '[' || ls->tok == ':' || | ||
| 2178 | ls->tok == '(' || ls->tok == TK_string || ls->tok == '{' || | ||
| 2179 | ls->tok == '.')) break; | ||
| 2180 | } else if (nav || lex_opt(ls, '.')) { | ||
| 2181 | expr_field(ls, v); | ||
| 1968 | } else { | 2182 | } else { |
| 1969 | break; | 2183 | break; |
| 1970 | } | 2184 | } |
| 2185 | if (nav && !(eflags & EXPR_F_NORES)) { | ||
| 2186 | expr_tonextreg(fs, v); | ||
| 2187 | } | ||
| 2188 | } | ||
| 2189 | return xpc; | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | /* Parse primary expression. */ | ||
| 2193 | static void expr_primary(LexState *ls, ExpDesc *v, int eflags) | ||
| 2194 | { | ||
| 2195 | BCPos xpc = expr_primary_nav(ls, v, eflags); | ||
| 2196 | if (xpc != NO_JMP) { | ||
| 2197 | FuncState *fs = ls->fs; | ||
| 2198 | BCPos around; | ||
| 2199 | around = bcemit_jmp(fs); | ||
| 2200 | jmp_tohere(fs, xpc); | ||
| 2201 | if (v->k == VCALL) { /* Change to VCALLNAV. Still points to CALL/CALLM. */ | ||
| 2202 | v->k = VCALLNAV; | ||
| 2203 | bcemit_AD(fs, BC_KPRI, v->u.s.aux, VKNIL); | ||
| 2204 | } else { | ||
| 2205 | bcemit_AD(fs, BC_KPRI, v->u.s.info, VKNIL); | ||
| 2206 | } | ||
| 2207 | jmp_tohere(fs, around); | ||
| 1971 | } | 2208 | } |
| 1972 | } | 2209 | } |
| 1973 | 2210 | ||
| 1974 | /* Parse simple expression. */ | 2211 | /* Parse simple expression. */ |
| 1975 | static void expr_simple(LexState *ls, ExpDesc *v) | 2212 | static void expr_simple(LexState *ls, ExpDesc *v, int eflags) |
| 1976 | { | 2213 | { |
| 1977 | switch (ls->tok) { | 2214 | switch (ls->tok) { |
| 1978 | case TK_number: | 2215 | case TK_number: |
| @@ -2009,8 +2246,11 @@ static void expr_simple(LexState *ls, ExpDesc *v) | |||
| 2009 | lj_lex_next(ls); | 2246 | lj_lex_next(ls); |
| 2010 | parse_body(ls, v, 0, ls->linenumber); | 2247 | parse_body(ls, v, 0, ls->linenumber); |
| 2011 | return; | 2248 | return; |
| 2249 | case '|': case TK_or_: | ||
| 2250 | parse_shortfunc(ls, v, NULL, eflags, ls->linenumber); | ||
| 2251 | return; | ||
| 2012 | default: | 2252 | default: |
| 2013 | expr_primary(ls, v); | 2253 | expr_primary(ls, v, eflags); |
| 2014 | return; | 2254 | return; |
| 2015 | } | 2255 | } |
| 2016 | lj_lex_next(ls); | 2256 | lj_lex_next(ls); |
| @@ -2035,15 +2275,22 @@ static BinOpr token2binop(LexToken tok) | |||
| 2035 | case '/': return OPR_DIV; | 2275 | case '/': return OPR_DIV; |
| 2036 | case '%': return OPR_MOD; | 2276 | case '%': return OPR_MOD; |
| 2037 | case '^': return OPR_POW; | 2277 | case '^': return OPR_POW; |
| 2278 | case '&': return OPR_BAND; | ||
| 2279 | case '|': return OPR_BOR; | ||
| 2280 | case '~': return OPR_BXOR; | ||
| 2281 | case TK_shl: return OPR_BSHL; | ||
| 2282 | case TK_shr: return OPR_BSHR; | ||
| 2283 | case TK_sar: return OPR_BSAR; | ||
| 2038 | case TK_concat: return OPR_CONCAT; | 2284 | case TK_concat: return OPR_CONCAT; |
| 2039 | case TK_ne: return OPR_NE; | 2285 | case TK_ne: case TK_ne_: return OPR_NE; |
| 2040 | case TK_eq: return OPR_EQ; | 2286 | case TK_eq: return OPR_EQ; |
| 2041 | case '<': return OPR_LT; | 2287 | case '<': return OPR_LT; |
| 2042 | case TK_le: return OPR_LE; | 2288 | case TK_le: return OPR_LE; |
| 2043 | case '>': return OPR_GT; | 2289 | case '>': return OPR_GT; |
| 2044 | case TK_ge: return OPR_GE; | 2290 | case TK_ge: return OPR_GE; |
| 2045 | case TK_and: return OPR_AND; | 2291 | case TK_and: case TK_and_: return OPR_AND; |
| 2046 | case TK_or: return OPR_OR; | 2292 | case TK_or: case TK_or_: return OPR_OR; |
| 2293 | case TK_coal: return OPR_COAL; | ||
| 2047 | default: return OPR_NOBINOPR; | 2294 | default: return OPR_NOBINOPR; |
| 2048 | } | 2295 | } |
| 2049 | } | 2296 | } |
| @@ -2053,69 +2300,91 @@ static const struct { | |||
| 2053 | uint8_t left; /* Left priority. */ | 2300 | uint8_t left; /* Left priority. */ |
| 2054 | uint8_t right; /* Right priority. */ | 2301 | uint8_t right; /* Right priority. */ |
| 2055 | } priority[] = { | 2302 | } priority[] = { |
| 2056 | {6,6}, {6,6}, {7,7}, {7,7}, {7,7}, /* ADD SUB MUL DIV MOD */ | 2303 | {10,10}, {10,10}, {11,11}, {11,11}, {11,11}, /* ADD SUB MUL DIV MOD */ |
| 2057 | {10,9}, {5,4}, /* POW CONCAT (right associative) */ | 2304 | {14,13}, /* POW (right associative) */ |
| 2305 | {6,6}, {4,4}, {5,5}, /* BAND BOR BXOR */ | ||
| 2306 | {7,7}, {7,7}, {7,7}, /* BSHL BSHR BSAR */ | ||
| 2307 | {9,8}, /* CONCAT (right associative) */ | ||
| 2058 | {3,3}, {3,3}, /* EQ NE */ | 2308 | {3,3}, {3,3}, /* EQ NE */ |
| 2059 | {3,3}, {3,3}, {3,3}, {3,3}, /* LT GE GT LE */ | 2309 | {3,3}, {3,3}, {3,3}, {3,3}, /* LT GE GT LE */ |
| 2060 | {2,2}, {1,1} /* AND OR */ | 2310 | {2,2}, {1,1}, {1,1} /* AND OR COAL */ |
| 2061 | }; | 2311 | }; |
| 2062 | 2312 | ||
| 2063 | #define UNARY_PRIORITY 8 /* Priority for unary operators. */ | 2313 | #define UNARY_PRIORITY 12 /* Priority for unary operators. */ |
| 2064 | 2314 | ||
| 2065 | /* Forward declaration. */ | 2315 | /* Forward declaration. */ |
| 2066 | static BinOpr expr_binop(LexState *ls, ExpDesc *v, uint32_t limit); | 2316 | static BinOpr expr_binop(LexState *ls, ExpDesc *v, uint32_t limit, int eflags); |
| 2067 | 2317 | ||
| 2068 | /* Parse unary expression. */ | 2318 | /* Parse unary expression. */ |
| 2069 | static void expr_unop(LexState *ls, ExpDesc *v) | 2319 | static void expr_unop(LexState *ls, ExpDesc *v, int eflags) |
| 2070 | { | 2320 | { |
| 2071 | BCOp op; | 2321 | BCOp op; |
| 2072 | if (ls->tok == TK_not) { | 2322 | if (ls->tok == TK_not || ls->tok == '!') { |
| 2073 | op = BC_NOT; | 2323 | op = BC_NOT; |
| 2074 | } else if (ls->tok == '-') { | 2324 | } else if (ls->tok == '-') { |
| 2075 | op = BC_UNM; | 2325 | op = BC_UNM; |
| 2076 | } else if (ls->tok == '#') { | 2326 | } else if (ls->tok == '#') { |
| 2077 | op = BC_LEN; | 2327 | op = BC_LEN; |
| 2328 | } else if (ls->tok == '~') { | ||
| 2329 | op = BC_BNOT; | ||
| 2078 | } else { | 2330 | } else { |
| 2079 | expr_simple(ls, v); | 2331 | expr_simple(ls, v, eflags); |
| 2080 | return; | 2332 | return; |
| 2081 | } | 2333 | } |
| 2082 | lj_lex_next(ls); | 2334 | lj_lex_next(ls); |
| 2083 | expr_binop(ls, v, UNARY_PRIORITY); | 2335 | expr_binop(ls, v, UNARY_PRIORITY, eflags); |
| 2084 | bcemit_unop(ls->fs, op, v); | 2336 | bcemit_unop(ls->fs, op, v); |
| 2085 | } | 2337 | } |
| 2086 | 2338 | ||
| 2087 | /* Parse binary expressions with priority higher than the limit. */ | 2339 | /* Parse binary expressions with priority higher than the limit. */ |
| 2088 | static BinOpr expr_binop(LexState *ls, ExpDesc *v, uint32_t limit) | 2340 | static BinOpr expr_binop(LexState *ls, ExpDesc *v, uint32_t limit, int eflags) |
| 2089 | { | 2341 | { |
| 2090 | BinOpr op; | 2342 | BinOpr opr; |
| 2091 | synlevel_begin(ls); | 2343 | synlevel_begin(ls); |
| 2092 | expr_unop(ls, v); | 2344 | expr_unop(ls, v, eflags); |
| 2093 | op = token2binop(ls->tok); | 2345 | opr = token2binop(ls->tok); |
| 2094 | while (op != OPR_NOBINOPR && priority[op].left > limit) { | 2346 | while (opr != OPR_NOBINOPR && priority[opr].left > limit) { |
| 2095 | ExpDesc v2; | 2347 | ExpDesc v2; |
| 2096 | BinOpr nextop; | 2348 | BinOpr nextop; |
| 2097 | lj_lex_next(ls); | 2349 | lj_lex_next(ls); |
| 2098 | bcemit_binop_left(ls->fs, op, v); | 2350 | bcemit_binop_left(ls->fs, opr, v); |
| 2099 | /* Parse binary expression with higher priority. */ | 2351 | /* Parse binary expression with higher priority. */ |
| 2100 | nextop = expr_binop(ls, &v2, priority[op].right); | 2352 | nextop = expr_binop(ls, &v2, priority[opr].right, eflags); |
| 2101 | bcemit_binop(ls->fs, op, v, &v2); | 2353 | bcemit_binop(ls->fs, opr, v, &v2); |
| 2102 | op = nextop; | 2354 | opr = nextop; |
| 2103 | } | 2355 | } |
| 2104 | synlevel_end(ls); | 2356 | synlevel_end(ls); |
| 2105 | return op; /* Return unconsumed binary operator (if any). */ | 2357 | return opr; /* Return unconsumed binary operator (if any). */ |
| 2106 | } | 2358 | } |
| 2107 | 2359 | ||
| 2108 | /* Parse expression. */ | 2360 | /* Parse expression. */ |
| 2109 | static void expr(LexState *ls, ExpDesc *v) | 2361 | static void expr(LexState *ls, ExpDesc *v, int eflags) |
| 2110 | { | 2362 | { |
| 2111 | expr_binop(ls, v, 0); /* Priority 0: parse whole expression. */ | 2363 | expr_binop(ls, v, 0, eflags); /* Priority 0: parse whole expression. */ |
| 2364 | if (lex_opt(ls, '?')) { /* Ternary ?: conditional operator. Right-assoc. */ | ||
| 2365 | FuncState *fs = ls->fs; | ||
| 2366 | BCPos escapelist = NO_JMP, cond; | ||
| 2367 | BCReg reg; | ||
| 2368 | bcemit_branch_t(fs, v); | ||
| 2369 | cond = v->f; | ||
| 2370 | expr(ls, v, EXPR_F_NOCOLON); /* Prevent method parsing. Use parentheses. */ | ||
| 2371 | expr_tonextreg(fs, v); | ||
| 2372 | reg = v->u.s.info; | ||
| 2373 | jmp_append(fs, &escapelist, bcemit_jmp(fs)); | ||
| 2374 | jmp_tohere(fs, cond); | ||
| 2375 | lex_check(ls, ':'); | ||
| 2376 | bcreg_free(fs, reg); | ||
| 2377 | expr(ls, v, 0); | ||
| 2378 | expr_tonextreg(fs, v); | ||
| 2379 | jmp_tohere(fs, escapelist); | ||
| 2380 | } | ||
| 2112 | } | 2381 | } |
| 2113 | 2382 | ||
| 2114 | /* Assign expression to the next register. */ | 2383 | /* Assign expression to the next register. */ |
| 2115 | static void expr_next(LexState *ls) | 2384 | static void expr_next(LexState *ls) |
| 2116 | { | 2385 | { |
| 2117 | ExpDesc e; | 2386 | ExpDesc e; |
| 2118 | expr(ls, &e); | 2387 | expr(ls, &e, 0); |
| 2119 | expr_tonextreg(ls->fs, &e); | 2388 | expr_tonextreg(ls->fs, &e); |
| 2120 | } | 2389 | } |
| 2121 | 2390 | ||
| @@ -2123,7 +2392,7 @@ static void expr_next(LexState *ls) | |||
| 2123 | static BCPos expr_cond(LexState *ls) | 2392 | static BCPos expr_cond(LexState *ls) |
| 2124 | { | 2393 | { |
| 2125 | ExpDesc v; | 2394 | ExpDesc v; |
| 2126 | expr(ls, &v); | 2395 | expr(ls, &v, 0); |
| 2127 | if (v.k == VKNIL) v.k = VKFALSE; | 2396 | if (v.k == VKNIL) v.k = VKFALSE; |
| 2128 | bcemit_branch_t(ls->fs, &v); | 2397 | bcemit_branch_t(ls->fs, &v); |
| 2129 | return v.f; | 2398 | return v.f; |
| @@ -2137,6 +2406,44 @@ typedef struct LHSVarList { | |||
| 2137 | struct LHSVarList *prev; /* Link to previous LHS variable. */ | 2406 | struct LHSVarList *prev; /* Link to previous LHS variable. */ |
| 2138 | } LHSVarList; | 2407 | } LHSVarList; |
| 2139 | 2408 | ||
| 2409 | /* Parse compound assignment. */ | ||
| 2410 | static int parse_compound(LexState *ls, ExpDesc *e) | ||
| 2411 | { | ||
| 2412 | FuncState *fs; | ||
| 2413 | ExpDesc estore, v; | ||
| 2414 | BinOpr opr; | ||
| 2415 | if (!(e->k >= VLOCAL && e->k <= VINDEXED)) return 0; | ||
| 2416 | opr = token2binop(ls->tok); | ||
| 2417 | /* '^=' aka exponentiation assignment is deliberately omitted to avoid | ||
| 2418 | ** confusion with xor assignment in other computer languages. | ||
| 2419 | ** Use 'a ~= b' for xor assignment. The unequal operator is only valid | ||
| 2420 | ** in expression contexts and assignments are statements. | ||
| 2421 | */ | ||
| 2422 | if (opr > OPR_NE || opr == OPR_POW) return 0; /* ORDER OPR */ | ||
| 2423 | var_assign(ls, e); | ||
| 2424 | if (opr == OPR_NE) { | ||
| 2425 | if (ls->tok != TK_ne) lj_lex_error(ls, '!', LJ_ERR_XTOKEN, "="); | ||
| 2426 | opr = OPR_BXOR; | ||
| 2427 | } else { /* Can't use lex_check() here. Only allow '+=', not '+ ='. */ | ||
| 2428 | if (ls->c != '=') err_token(ls, '='); | ||
| 2429 | lj_lex_next(ls); /* Skip operator. */ | ||
| 2430 | } | ||
| 2431 | lj_lex_next(ls); /* Skip '=' or '~=' aka TOK_ne. */ | ||
| 2432 | fs = ls->fs; | ||
| 2433 | estore = *e; | ||
| 2434 | if (e->k == VINDEXED) { /* Preserve the base and key for the store. */ | ||
| 2435 | BCReg freg = fs->freereg; | ||
| 2436 | expr_discharge(fs, e); | ||
| 2437 | fs->freereg = freg; /* Undo bcreg_free of info and/or aux. */ | ||
| 2438 | } | ||
| 2439 | if (opr == OPR_CONCAT) expr_tonextreg(fs, e); else expr_toanyreg(fs, e); | ||
| 2440 | expr(ls, &v, 0); | ||
| 2441 | bcemit_binop(fs, opr, e, &v); | ||
| 2442 | bcemit_store(fs, &estore, e); | ||
| 2443 | /* Don't bother to free VINDEXED info+aux. Done by parse_chunk(). */ | ||
| 2444 | return 1; | ||
| 2445 | } | ||
| 2446 | |||
| 2140 | /* Eliminate write-after-read hazards for local variable assignment. */ | 2447 | /* Eliminate write-after-read hazards for local variable assignment. */ |
| 2141 | static void assign_hazard(LexState *ls, LHSVarList *lh, const ExpDesc *v) | 2448 | static void assign_hazard(LexState *ls, LHSVarList *lh, const ExpDesc *v) |
| 2142 | { | 2449 | { |
| @@ -2167,11 +2474,23 @@ static void assign_adjust(LexState *ls, BCReg nvars, BCReg nexps, ExpDesc *e) | |||
| 2167 | { | 2474 | { |
| 2168 | FuncState *fs = ls->fs; | 2475 | FuncState *fs = ls->fs; |
| 2169 | int32_t extra = (int32_t)nvars - (int32_t)nexps; | 2476 | int32_t extra = (int32_t)nvars - (int32_t)nexps; |
| 2170 | if (e->k == VCALL) { | 2477 | if (e->k == VCALL || e->k == VCALLNAV) { |
| 2478 | BCInsLine *ilp = &fs->bcbase[e->u.s.info]; | ||
| 2171 | extra++; /* Compensate for the VCALL itself. */ | 2479 | extra++; /* Compensate for the VCALL itself. */ |
| 2172 | if (extra < 0) extra = 0; | 2480 | if (extra < 0) extra = 0; |
| 2173 | setbc_b(bcptr(fs, e), extra+1); /* Fixup call results. */ | 2481 | setbc_b(&ilp->ins, extra+1); /* Fixup call results. */ |
| 2174 | if (extra > 1) bcreg_reserve(fs, (BCReg)extra-1); | 2482 | if (extra > 1) bcreg_reserve(fs, (BCReg)extra-1); |
| 2483 | if (e->k == VCALLNAV) { /* Safe navigation result. */ | ||
| 2484 | BCPos base = e->u.s.aux; | ||
| 2485 | lj_assertFS((bc_op(ilp[0].ins) == BC_CALL || | ||
| 2486 | bc_op(ilp[0].ins) == BC_CALLM) && | ||
| 2487 | bc_op(ilp[1].ins) == BC_JMP && | ||
| 2488 | bc_op(ilp[2].ins) == BC_KPRI, | ||
| 2489 | "expected CALL|CALLM, JMP, KPRI inside safe navigation"); | ||
| 2490 | setbc_a(&ilp[1].ins, base + extra); /* Fixup JMP nactvar. */ | ||
| 2491 | if (extra > 1) /* Need more nils. Case extra == 0 is harmless. */ | ||
| 2492 | ilp[2].ins = BCINS_AD(BC_KNIL, base, base + extra-1); | ||
| 2493 | } | ||
| 2175 | } else { | 2494 | } else { |
| 2176 | if (e->k != VVOID) | 2495 | if (e->k != VVOID) |
| 2177 | expr_tonextreg(fs, e); /* Close last expression. */ | 2496 | expr_tonextreg(fs, e); /* Close last expression. */ |
| @@ -2190,10 +2509,11 @@ static void parse_assignment(LexState *ls, LHSVarList *lh, BCReg nvars) | |||
| 2190 | { | 2509 | { |
| 2191 | ExpDesc e; | 2510 | ExpDesc e; |
| 2192 | checkcond(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, LJ_ERR_XSYNTAX); | 2511 | checkcond(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, LJ_ERR_XSYNTAX); |
| 2512 | var_assign(ls, &lh->v); | ||
| 2193 | if (lex_opt(ls, ',')) { /* Collect LHS list and recurse upwards. */ | 2513 | if (lex_opt(ls, ',')) { /* Collect LHS list and recurse upwards. */ |
| 2194 | LHSVarList vl; | 2514 | LHSVarList vl; |
| 2195 | vl.prev = lh; | 2515 | vl.prev = lh; |
| 2196 | expr_primary(ls, &vl.v); | 2516 | expr_primary(ls, &vl.v, EXPR_F_NONAV); |
| 2197 | if (vl.v.k == VLOCAL) | 2517 | if (vl.v.k == VLOCAL) |
| 2198 | assign_hazard(ls, lh, &vl.v); | 2518 | assign_hazard(ls, lh, &vl.v); |
| 2199 | checklimit(ls->fs, ls->level + nvars, LJ_MAX_XLEVEL, "variable names"); | 2519 | checklimit(ls->fs, ls->level + nvars, LJ_MAX_XLEVEL, "variable names"); |
| @@ -2208,6 +2528,11 @@ static void parse_assignment(LexState *ls, LHSVarList *lh, BCReg nvars) | |||
| 2208 | ls->fs->freereg--; | 2528 | ls->fs->freereg--; |
| 2209 | e.k = VRELOCABLE; | 2529 | e.k = VRELOCABLE; |
| 2210 | } else { /* Multiple call results. */ | 2530 | } else { /* Multiple call results. */ |
| 2531 | lj_assertLS(bc_op(*bcptr(ls->fs, &e)) == BC_CALL || | ||
| 2532 | bc_op(*bcptr(ls->fs, &e)) == BC_CALLM || | ||
| 2533 | bc_op(*bcptr(ls->fs, &e)) == BC_KPRI, | ||
| 2534 | "unexpected call expression bytecode %d in assignment", | ||
| 2535 | bc_op(*bcptr(ls->fs, &e))); | ||
| 2211 | e.u.s.info = e.u.s.aux; /* Base of call is not relocatable. */ | 2536 | e.u.s.info = e.u.s.aux; /* Base of call is not relocatable. */ |
| 2212 | e.k = VNONRELOC; | 2537 | e.k = VNONRELOC; |
| 2213 | } | 2538 | } |
| @@ -2227,22 +2552,30 @@ static void parse_call_assign(LexState *ls) | |||
| 2227 | { | 2552 | { |
| 2228 | FuncState *fs = ls->fs; | 2553 | FuncState *fs = ls->fs; |
| 2229 | LHSVarList vl; | 2554 | LHSVarList vl; |
| 2230 | expr_primary(ls, &vl.v); | 2555 | BCReg xpc = expr_primary_nav(ls, &vl.v, EXPR_F_NORES); |
| 2231 | if (vl.v.k == VCALL) { /* Function call statement. */ | 2556 | if (vl.v.k == VCALL) { /* Function call statement. */ |
| 2232 | setbc_b(bcptr(fs, &vl.v), 1); /* No results. */ | 2557 | setbc_b(bcptr(fs, &vl.v), 1); /* No results. */ |
| 2233 | } else { /* Start of an assignment. */ | 2558 | } else { /* Start of an assignment. */ |
| 2234 | vl.prev = NULL; | 2559 | lj_assertFS(vl.v.k != VCALLNAV, "unexpected VCALLNAV in statement"); |
| 2235 | parse_assignment(ls, &vl, 1); | 2560 | /* Safe navigation is incompatible with parallel assignment. */ |
| 2561 | checkcond(ls, xpc == NO_JMP || ls->tok != ',', LJ_ERR_XSYNTAX); | ||
| 2562 | if (!parse_compound(ls, &vl.v)) { | ||
| 2563 | vl.prev = NULL; | ||
| 2564 | parse_assignment(ls, &vl, 1); | ||
| 2565 | } | ||
| 2236 | } | 2566 | } |
| 2567 | if (xpc != NO_JMP) jmp_tohere(fs, xpc); | ||
| 2237 | } | 2568 | } |
| 2238 | 2569 | ||
| 2239 | /* Parse 'local' statement. */ | 2570 | /* Parse 'local' or 'const' statement. */ |
| 2240 | static void parse_local(LexState *ls) | 2571 | static void parse_local(LexState *ls, int vinfo) |
| 2241 | { | 2572 | { |
| 2573 | lj_lex_next(ls); /* Skip local or const. */ | ||
| 2242 | if (lex_opt(ls, TK_function)) { /* Local function declaration. */ | 2574 | if (lex_opt(ls, TK_function)) { /* Local function declaration. */ |
| 2243 | ExpDesc v, b; | 2575 | ExpDesc v, b; |
| 2244 | FuncState *fs = ls->fs; | 2576 | FuncState *fs = ls->fs; |
| 2245 | var_new(ls, 0, lex_str(ls)); | 2577 | MSize vidx = var_new(ls, 0, lex_str(ls)); |
| 2578 | ls->vstack[vidx].info = (uint8_t)vinfo; | ||
| 2246 | expr_init(&v, VLOCAL, fs->freereg); | 2579 | expr_init(&v, VLOCAL, fs->freereg); |
| 2247 | v.u.s.aux = fs->varmap[fs->freereg]; | 2580 | v.u.s.aux = fs->varmap[fs->freereg]; |
| 2248 | bcreg_reserve(fs, 1); | 2581 | bcreg_reserve(fs, 1); |
| @@ -2256,9 +2589,23 @@ static void parse_local(LexState *ls) | |||
| 2256 | } else { /* Local variable declaration. */ | 2589 | } else { /* Local variable declaration. */ |
| 2257 | ExpDesc e; | 2590 | ExpDesc e; |
| 2258 | BCReg nexps, nvars = 0; | 2591 | BCReg nexps, nvars = 0; |
| 2259 | do { /* Collect LHS. */ | 2592 | if (vinfo) { /* Multiple consts need to be checked against each other. */ |
| 2260 | var_new(ls, nvars++, lex_str(ls)); | 2593 | VarIndex vhsave[LJ_VINDEX_HSIZE]; |
| 2261 | } while (lex_opt(ls, ',')); | 2594 | memcpy(vhsave, ls->vhash, sizeof(vhsave)); |
| 2595 | do { /* Collect LHS. */ | ||
| 2596 | MSize vidx = var_new(ls, nvars++, lex_str(ls)); | ||
| 2597 | VarInfo *v = &ls->vstack[vidx]; | ||
| 2598 | VarHash hash = var_hash(strref(v->name)); | ||
| 2599 | v->prev = ls->vhash[hash]; /* Temporarily add to hash. */ | ||
| 2600 | ls->vhash[hash] = vidx; | ||
| 2601 | v->info = (uint8_t)vinfo; | ||
| 2602 | } while (lex_opt(ls, ',')); | ||
| 2603 | memcpy(ls->vhash, vhsave, sizeof(vhsave)); /* Restore hash anchors. */ | ||
| 2604 | } else { | ||
| 2605 | do { /* Collect LHS. */ | ||
| 2606 | var_new(ls, nvars++, lex_str(ls)); | ||
| 2607 | } while (lex_opt(ls, ',')); | ||
| 2608 | } | ||
| 2262 | if (lex_opt(ls, '=')) { /* Optional RHS. */ | 2609 | if (lex_opt(ls, '=')) { /* Optional RHS. */ |
| 2263 | nexps = expr_list(ls, &e); | 2610 | nexps = expr_list(ls, &e); |
| 2264 | } else { /* Or implicitly set to nil. */ | 2611 | } else { /* Or implicitly set to nil. */ |
| @@ -2277,14 +2624,14 @@ static void parse_func(LexState *ls, BCLine line) | |||
| 2277 | ExpDesc v, b; | 2624 | ExpDesc v, b; |
| 2278 | int needself = 0; | 2625 | int needself = 0; |
| 2279 | lj_lex_next(ls); /* Skip 'function'. */ | 2626 | lj_lex_next(ls); /* Skip 'function'. */ |
| 2280 | /* Parse function name. */ | 2627 | var_lookup(ls, &v, lex_str(ls)); /* Parse function name. */ |
| 2281 | var_lookup(ls, &v); | 2628 | while (lex_opt(ls, '.')) /* Multiple dot-separated fields. */ |
| 2282 | while (ls->tok == '.') /* Multiple dot-separated fields. */ | ||
| 2283 | expr_field(ls, &v); | 2629 | expr_field(ls, &v); |
| 2284 | if (ls->tok == ':') { /* Optional colon to signify method call. */ | 2630 | if (lex_opt(ls, ':')) { /* Optional colon to signify method call. */ |
| 2285 | needself = 1; | 2631 | needself = 1; |
| 2286 | expr_field(ls, &v); | 2632 | expr_field(ls, &v); |
| 2287 | } | 2633 | } |
| 2634 | var_assign(ls, &v); | ||
| 2288 | parse_body(ls, &b, needself, line); | 2635 | parse_body(ls, &b, needself, line); |
| 2289 | fs = ls->fs; | 2636 | fs = ls->fs; |
| 2290 | bcemit_store(fs, &v, &b); | 2637 | bcemit_store(fs, &v, &b); |
| @@ -2305,19 +2652,25 @@ static int parse_isend(LexToken tok) | |||
| 2305 | } | 2652 | } |
| 2306 | 2653 | ||
| 2307 | /* Parse 'return' statement. */ | 2654 | /* Parse 'return' statement. */ |
| 2308 | static void parse_return(LexState *ls) | 2655 | static void parse_return(LexState *ls, int eflags) |
| 2309 | { | 2656 | { |
| 2310 | BCIns ins; | 2657 | BCIns ins; |
| 2311 | FuncState *fs = ls->fs; | 2658 | FuncState *fs = ls->fs; |
| 2312 | lj_lex_next(ls); /* Skip 'return'. */ | ||
| 2313 | fs->flags |= PROTO_HAS_RETURN; | 2659 | fs->flags |= PROTO_HAS_RETURN; |
| 2314 | if (parse_isend(ls->tok) || ls->tok == ';') { /* Bare return. */ | 2660 | if (!(eflags & EXPR_F_RET1) && (parse_isend(ls->tok) || ls->tok == ';')) { |
| 2315 | ins = BCINS_AD(BC_RET0, 0, 1); | 2661 | ins = BCINS_AD(BC_RET0, 0, 1); /* Bare return. */ |
| 2316 | } else { /* Return with one or more values. */ | 2662 | } else { /* Return with one or more values. */ |
| 2317 | ExpDesc e; /* Receives the _last_ expression in the list. */ | 2663 | ExpDesc e; /* Receives the _last_ expression in the list. */ |
| 2318 | BCReg nret = expr_list(ls, &e); | 2664 | BCReg nret; |
| 2665 | if ((eflags & EXPR_F_RET1)) { | ||
| 2666 | expr(ls, &e, eflags); | ||
| 2667 | nret = 1; | ||
| 2668 | } else { | ||
| 2669 | nret = expr_list(ls, &e); | ||
| 2670 | } | ||
| 2319 | if (nret == 1) { /* Return one result. */ | 2671 | if (nret == 1) { /* Return one result. */ |
| 2320 | if (e.k == VCALL) { /* Check for tail call. */ | 2672 | /* Check for tail call. */ |
| 2673 | if (e.k == VCALL) { | ||
| 2321 | #ifdef LUAJIT_DISABLE_TAILCALL | 2674 | #ifdef LUAJIT_DISABLE_TAILCALL |
| 2322 | goto notailcall; | 2675 | goto notailcall; |
| 2323 | #else | 2676 | #else |
| @@ -2331,7 +2684,8 @@ static void parse_return(LexState *ls) | |||
| 2331 | ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2); | 2684 | ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2); |
| 2332 | } | 2685 | } |
| 2333 | } else { | 2686 | } else { |
| 2334 | if (e.k == VCALL) { /* Append all results from a call. */ | 2687 | if (e.k == VCALL) { |
| 2688 | /* Append all results from a call. */ | ||
| 2335 | notailcall: | 2689 | notailcall: |
| 2336 | setbc_b(bcptr(fs, &e), 0); | 2690 | setbc_b(bcptr(fs, &e), 0); |
| 2337 | ins = BCINS_AD(BC_RETM, fs->nactvar, e.u.s.aux - fs->nactvar); | 2691 | ins = BCINS_AD(BC_RETM, fs->nactvar, e.u.s.aux - fs->nactvar); |
| @@ -2353,6 +2707,13 @@ static void parse_break(LexState *ls) | |||
| 2353 | gola_new(ls, NAME_BREAK, VSTACK_GOTO, bcemit_jmp(ls->fs)); | 2707 | gola_new(ls, NAME_BREAK, VSTACK_GOTO, bcemit_jmp(ls->fs)); |
| 2354 | } | 2708 | } |
| 2355 | 2709 | ||
| 2710 | /* Parse 'continue' statement. */ | ||
| 2711 | static void parse_continue(LexState *ls) | ||
| 2712 | { | ||
| 2713 | ls->fs->bl->flags |= FSCOPE_CONT; | ||
| 2714 | gola_new(ls, NAME_CONT, VSTACK_GOTO, bcemit_jmp(ls->fs)); | ||
| 2715 | } | ||
| 2716 | |||
| 2356 | /* Parse 'goto' statement. */ | 2717 | /* Parse 'goto' statement. */ |
| 2357 | static void parse_goto(LexState *ls) | 2718 | static void parse_goto(LexState *ls) |
| 2358 | { | 2719 | { |
| @@ -2424,6 +2785,7 @@ static void parse_while(LexState *ls, BCLine line) | |||
| 2424 | parse_block(ls); | 2785 | parse_block(ls); |
| 2425 | jmp_patch(fs, bcemit_jmp(fs), start); | 2786 | jmp_patch(fs, bcemit_jmp(fs), start); |
| 2426 | lex_match(ls, TK_end, TK_while, line); | 2787 | lex_match(ls, TK_end, TK_while, line); |
| 2788 | fscope_continue(fs, start); | ||
| 2427 | fscope_end(fs); | 2789 | fscope_end(fs); |
| 2428 | jmp_tohere(fs, condexit); | 2790 | jmp_tohere(fs, condexit); |
| 2429 | jmp_patchins(fs, loop, fs->pc); | 2791 | jmp_patchins(fs, loop, fs->pc); |
| @@ -2442,6 +2804,7 @@ static void parse_repeat(LexState *ls, BCLine line) | |||
| 2442 | bcemit_AD(fs, BC_LOOP, fs->nactvar, 0); | 2804 | bcemit_AD(fs, BC_LOOP, fs->nactvar, 0); |
| 2443 | parse_chunk(ls); | 2805 | parse_chunk(ls); |
| 2444 | lex_match(ls, TK_until, TK_repeat, line); | 2806 | lex_match(ls, TK_until, TK_repeat, line); |
| 2807 | fscope_continue(fs, fs->pc); | ||
| 2445 | condexit = expr_cond(ls); /* Parse condition (still inside inner scope). */ | 2808 | condexit = expr_cond(ls); /* Parse condition (still inside inner scope). */ |
| 2446 | if (!(bl2.flags & FSCOPE_UPVAL)) { /* No upvalues? Just end inner scope. */ | 2809 | if (!(bl2.flags & FSCOPE_UPVAL)) { /* No upvalues? Just end inner scope. */ |
| 2447 | fscope_end(fs); | 2810 | fscope_end(fs); |
| @@ -2487,6 +2850,7 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line) | |||
| 2487 | bcreg_reserve(fs, 1); | 2850 | bcreg_reserve(fs, 1); |
| 2488 | parse_block(ls); | 2851 | parse_block(ls); |
| 2489 | fscope_end(fs); | 2852 | fscope_end(fs); |
| 2853 | fscope_continue(fs, fs->pc); | ||
| 2490 | /* Perform loop inversion. Loop control instructions are at the end. */ | 2854 | /* Perform loop inversion. Loop control instructions are at the end. */ |
| 2491 | loopend = bcemit_AJ(fs, BC_FORL, base, NO_JMP); | 2855 | loopend = bcemit_AJ(fs, BC_FORL, base, NO_JMP); |
| 2492 | fs->bcbase[loopend].line = line; /* Fix line for control ins. */ | 2856 | fs->bcbase[loopend].line = line; /* Fix line for control ins. */ |
| @@ -2562,6 +2926,7 @@ static void parse_for_iter(LexState *ls, GCstr *indexname) | |||
| 2562 | fscope_end(fs); | 2926 | fscope_end(fs); |
| 2563 | /* Perform loop inversion. Loop control instructions are at the end. */ | 2927 | /* Perform loop inversion. Loop control instructions are at the end. */ |
| 2564 | jmp_patchins(fs, loop, fs->pc); | 2928 | jmp_patchins(fs, loop, fs->pc); |
| 2929 | fscope_continue(fs, fs->pc); | ||
| 2565 | bcemit_ABC(fs, isnext ? BC_ITERN : BC_ITERC, base, nvars-3+1, 2+1); | 2930 | bcemit_ABC(fs, isnext ? BC_ITERN : BC_ITERC, base, nvars-3+1, 2+1); |
| 2566 | loopend = bcemit_AJ(fs, BC_ITERL, base, NO_JMP); | 2931 | loopend = bcemit_AJ(fs, BC_ITERL, base, NO_JMP); |
| 2567 | fs->bcbase[loopend-1].line = line; /* Fix line for control ins. */ | 2932 | fs->bcbase[loopend-1].line = line; /* Fix line for control ins. */ |
| @@ -2651,16 +3016,28 @@ static int parse_stmt(LexState *ls) | |||
| 2651 | parse_func(ls, line); | 3016 | parse_func(ls, line); |
| 2652 | break; | 3017 | break; |
| 2653 | case TK_local: | 3018 | case TK_local: |
| 2654 | lj_lex_next(ls); | 3019 | parse_local(ls, 0); |
| 2655 | parse_local(ls); | 3020 | break; |
| 3021 | case TK_const: { | ||
| 3022 | LexToken tokx = lj_lex_lookahead(ls); | ||
| 3023 | if (!(lex_isname(tokx) || tokx == TK_function)) | ||
| 3024 | goto assign; /* Soft keyword. */ | ||
| 3025 | parse_local(ls, VSTACK_CONST); | ||
| 2656 | break; | 3026 | break; |
| 3027 | } | ||
| 2657 | case TK_return: | 3028 | case TK_return: |
| 2658 | parse_return(ls); | 3029 | lj_lex_next(ls); |
| 3030 | parse_return(ls, 0); | ||
| 2659 | return 1; /* Must be last. */ | 3031 | return 1; /* Must be last. */ |
| 2660 | case TK_break: | 3032 | case TK_break: |
| 2661 | lj_lex_next(ls); | 3033 | lj_lex_next(ls); |
| 2662 | parse_break(ls); | 3034 | parse_break(ls); |
| 2663 | return !LJ_52; /* Must be last in Lua 5.1. */ | 3035 | return !LJ_52; /* Must be last in Lua 5.1. */ |
| 3036 | case TK_continue: | ||
| 3037 | if (!parse_isend(lj_lex_lookahead(ls))) goto assign; /* Soft keyword. */ | ||
| 3038 | lj_lex_next(ls); | ||
| 3039 | parse_continue(ls); | ||
| 3040 | return 1; /* Must be last. */ | ||
| 2664 | #if LJ_52 | 3041 | #if LJ_52 |
| 2665 | case ';': | 3042 | case ';': |
| 2666 | lj_lex_next(ls); | 3043 | lj_lex_next(ls); |
| @@ -2670,13 +3047,14 @@ static int parse_stmt(LexState *ls) | |||
| 2670 | parse_label(ls); | 3047 | parse_label(ls); |
| 2671 | break; | 3048 | break; |
| 2672 | case TK_goto: | 3049 | case TK_goto: |
| 2673 | if (LJ_52 || lj_lex_lookahead(ls) == TK_name) { | 3050 | if (LJ_52 || lex_isname(lj_lex_lookahead(ls))) { /* 5.1 soft keyword. */ |
| 2674 | lj_lex_next(ls); | 3051 | lj_lex_next(ls); |
| 2675 | parse_goto(ls); | 3052 | parse_goto(ls); |
| 2676 | break; | 3053 | break; |
| 2677 | } | 3054 | } |
| 2678 | /* fallthrough */ | 3055 | /* fallthrough */ |
| 2679 | default: | 3056 | default: |
| 3057 | assign: | ||
| 2680 | parse_call_assign(ls); | 3058 | parse_call_assign(ls); |
| 2681 | break; | 3059 | break; |
| 2682 | } | 3060 | } |
| @@ -2714,6 +3092,7 @@ GCproto *lj_parse(LexState *ls) | |||
| 2714 | setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */ | 3092 | setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */ |
| 2715 | incr_top(L); | 3093 | incr_top(L); |
| 2716 | ls->level = 0; | 3094 | ls->level = 0; |
| 3095 | memset(ls->vhash, 0xff, sizeof(ls->vhash)); | ||
| 2717 | fs_init(ls, &fs); | 3096 | fs_init(ls, &fs); |
| 2718 | fs.linedefined = 0; | 3097 | fs.linedefined = 0; |
| 2719 | fs.numparams = 0; | 3098 | fs.numparams = 0; |
