diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 37 |
1 files changed, 26 insertions, 11 deletions
@@ -811,16 +811,16 @@ static void yindex (LexState *ls, expdesc *v) { | |||
811 | */ | 811 | */ |
812 | 812 | ||
813 | 813 | ||
814 | struct ConsControl { | 814 | typedef struct ConsControl { |
815 | expdesc v; /* last list item read */ | 815 | expdesc v; /* last list item read */ |
816 | expdesc *t; /* table descriptor */ | 816 | expdesc *t; /* table descriptor */ |
817 | int nh; /* total number of 'record' elements */ | 817 | int nh; /* total number of 'record' elements */ |
818 | int na; /* total number of array elements */ | 818 | int na; /* total number of array elements */ |
819 | int tostore; /* number of array elements pending to be stored */ | 819 | int tostore; /* number of array elements pending to be stored */ |
820 | }; | 820 | } ConsControl; |
821 | 821 | ||
822 | 822 | ||
823 | static void recfield (LexState *ls, struct ConsControl *cc) { | 823 | static void recfield (LexState *ls, ConsControl *cc) { |
824 | /* recfield -> (NAME | '['exp']') = exp */ | 824 | /* recfield -> (NAME | '['exp']') = exp */ |
825 | FuncState *fs = ls->fs; | 825 | FuncState *fs = ls->fs; |
826 | int reg = ls->fs->freereg; | 826 | int reg = ls->fs->freereg; |
@@ -841,7 +841,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
841 | } | 841 | } |
842 | 842 | ||
843 | 843 | ||
844 | static void closelistfield (FuncState *fs, struct ConsControl *cc) { | 844 | static void closelistfield (FuncState *fs, ConsControl *cc) { |
845 | if (cc->v.k == VVOID) return; /* there is no list item */ | 845 | if (cc->v.k == VVOID) return; /* there is no list item */ |
846 | luaK_exp2nextreg(fs, &cc->v); | 846 | luaK_exp2nextreg(fs, &cc->v); |
847 | cc->v.k = VVOID; | 847 | cc->v.k = VVOID; |
@@ -852,7 +852,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { | |||
852 | } | 852 | } |
853 | 853 | ||
854 | 854 | ||
855 | static void lastlistfield (FuncState *fs, struct ConsControl *cc) { | 855 | static void lastlistfield (FuncState *fs, ConsControl *cc) { |
856 | if (cc->tostore == 0) return; | 856 | if (cc->tostore == 0) return; |
857 | if (hasmultret(cc->v.k)) { | 857 | if (hasmultret(cc->v.k)) { |
858 | luaK_setmultret(fs, &cc->v); | 858 | luaK_setmultret(fs, &cc->v); |
@@ -867,16 +867,15 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) { | |||
867 | } | 867 | } |
868 | 868 | ||
869 | 869 | ||
870 | static void listfield (LexState *ls, struct ConsControl *cc) { | 870 | static void listfield (LexState *ls, ConsControl *cc) { |
871 | /* listfield -> exp */ | 871 | /* listfield -> exp */ |
872 | expr(ls, &cc->v); | 872 | expr(ls, &cc->v); |
873 | checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); | ||
874 | cc->na++; | 873 | cc->na++; |
875 | cc->tostore++; | 874 | cc->tostore++; |
876 | } | 875 | } |
877 | 876 | ||
878 | 877 | ||
879 | static void field (LexState *ls, struct ConsControl *cc) { | 878 | static void field (LexState *ls, ConsControl *cc) { |
880 | /* field -> listfield | recfield */ | 879 | /* field -> listfield | recfield */ |
881 | switch(ls->t.token) { | 880 | switch(ls->t.token) { |
882 | case TK_NAME: { /* may be 'listfield' or 'recfield' */ | 881 | case TK_NAME: { /* may be 'listfield' or 'recfield' */ |
@@ -898,13 +897,30 @@ static void field (LexState *ls, struct ConsControl *cc) { | |||
898 | } | 897 | } |
899 | 898 | ||
900 | 899 | ||
900 | static void settablesize (FuncState *fs, ConsControl *cc, int pc) { | ||
901 | Instruction *inst = &fs->f->code[pc]; | ||
902 | int rc = (cc->nh == 0) ? 0 : luaO_ceillog2(cc->nh) + 1; | ||
903 | int rb = cc->na; | ||
904 | int extra = 0; | ||
905 | if (rb >= LIMTABSZ) { | ||
906 | extra = rb / LFIELDS_PER_FLUSH; | ||
907 | rb = rb % LFIELDS_PER_FLUSH + LIMTABSZ; | ||
908 | checklimit(fs, extra, MAXARG_Ax, "items in a constructor"); | ||
909 | } | ||
910 | SETARG_C(*inst, rc); /* set initial table size */ | ||
911 | SETARG_B(*inst, rb); /* set initial array size */ | ||
912 | SETARG_Ax(*(inst + 1), extra); | ||
913 | } | ||
914 | |||
915 | |||
901 | static void constructor (LexState *ls, expdesc *t) { | 916 | static void constructor (LexState *ls, expdesc *t) { |
902 | /* constructor -> '{' [ field { sep field } [sep] ] '}' | 917 | /* constructor -> '{' [ field { sep field } [sep] ] '}' |
903 | sep -> ',' | ';' */ | 918 | sep -> ',' | ';' */ |
904 | FuncState *fs = ls->fs; | 919 | FuncState *fs = ls->fs; |
905 | int line = ls->linenumber; | 920 | int line = ls->linenumber; |
906 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); | 921 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); |
907 | struct ConsControl cc; | 922 | ConsControl cc; |
923 | luaK_codeextraarg(fs, 0); | ||
908 | cc.na = cc.nh = cc.tostore = 0; | 924 | cc.na = cc.nh = cc.tostore = 0; |
909 | cc.t = t; | 925 | cc.t = t; |
910 | init_exp(t, VRELOC, pc); | 926 | init_exp(t, VRELOC, pc); |
@@ -919,8 +935,7 @@ static void constructor (LexState *ls, expdesc *t) { | |||
919 | } while (testnext(ls, ',') || testnext(ls, ';')); | 935 | } while (testnext(ls, ',') || testnext(ls, ';')); |
920 | check_match(ls, '}', '{', line); | 936 | check_match(ls, '}', '{', line); |
921 | lastlistfield(fs, &cc); | 937 | lastlistfield(fs, &cc); |
922 | SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ | 938 | settablesize(fs, &cc, pc); |
923 | SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ | ||
924 | } | 939 | } |
925 | 940 | ||
926 | /* }====================================================================== */ | 941 | /* }====================================================================== */ |