static void whilestat (LexState *ls, int line) { /* whilestat -> WHILE cond DO block END */ FuncState *fs = ls->fs; int whileinit; int condexit; BlockCnt bl; luaX_next(ls); /* skip WHILE */ whileinit = luaK_getlabel(fs); condexit = cond(ls); enterblock(fs, &bl, 1); checknext(ls, TK_DO); block(ls); luaK_patchlist(fs, luaK_jump(fs), whileinit); check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ }
static void casestat (LexState *ls, expdesc *v) { FuncState *fs = ls->fs; expdesc v2; int nargs, base; /* do not set base to 0 for if case is used in (local) loops, it does not work properly */ base = fs->freereg; luaK_exp2nextreg(fs, v); nargs = explist1(ls, &v2); /* put every value into a register */ luaK_exp2nextreg(fs, &v2); codecompcase(fs, base, nargs+1, v); fs->freereg -= nargs+1; /* free all registers */ if (v->k == VNIL) v->k = VFALSE; luaK_goiftrue(fs, v); luaK_patchtohere(fs, v->t); checknext(ls, TK_THEN); block(ls); }
static void recfield (LexState *ls, struct ConsControl *cc) { /* recfield -> (NAME | `['exp1`]') = exp1 */ FuncState *fs = ls->fs; int reg = ls->fs->freereg; expdesc key, val; int rkkey; if (ls->t.token == TK_NAME) { luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); checkname(ls, &key); } else /* ls->t.token == '[' */ yindex(ls, &key); cc->nh++; checknext(ls, '='); rkkey = luaK_exp2RK(fs, &key); expr(ls, &val); luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); fs->freereg = reg; /* free registers */ }
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { /* forbody -> DO block */ BlockCnt bl; FuncState *fs = ls->fs; int prep, endfor; adjustlocalvars(ls, 3); /* control variables */ checknext(ls, TK_DO); prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); enterblock(fs, &bl, 0); /* scope for declared variables */ adjustlocalvars(ls, nvars); luaK_reserveregs(fs, nvars); block(ls); leaveblock(fs); /* end of scope for declared variables */ luaK_patchtohere(fs, prep); endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); }
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist1 */ int nexps; /* hook for inc_assignment */ if(nvars==1) { switch(ls->t.token) { case '+': case '-': case '*': case '/': case TK_CONCAT: inc_assignment(ls,lh); /* If you're using Shook's table unpack patch, return 0 here.*/ return; } } checknext(ls, '='); nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); }
static void inc_assignment(LexState *ls, struct LHS_assign *lh) { BinOpr op = getbinopr(ls->t.token); FuncState * fs=ls->fs; expdesc e, v2; /* reserve all registers needed by the lvalue */ luaK_reserveregs(fs,fs->freereg-fs->nactvar); luaX_next(ls); checknext(ls, '='); enterlevel(ls); e = lh->v; luaK_infix(fs,op,&e); /* we only match one expr(), not a full explist(), so "a+=2,2" will be a parse error. */ expr(ls,&v2); luaK_posfix(fs, op, &e, &v2); leavelevel(ls); luaK_exp2nextreg(fs,&e); luaK_setoneret(ls->fs, &e); luaK_storevar(ls->fs, &lh->v, &e); }
static void forlist (LexState *ls, TString *indexname) { /* forlist -> NAME {,NAME} IN explist1 forbody */ FuncState *fs = ls->fs; expdesc e; int nvars = 0; int line; int base = fs->freereg; /* create control variables */ new_localvarliteral(ls, "(for generator)", nvars++); new_localvarliteral(ls, "(for state)", nvars++); new_localvarliteral(ls, "(for control)", nvars++); /* create declared variables */ new_localvar(ls, indexname, nvars++); while (testnext(ls, ',')) new_localvar(ls, str_checkname(ls), nvars++); checknext(ls, TK_IN); line = ls->linenumber; adjust_assign(ls, 3, explist1(ls, &e), &e); luaK_checkstack(fs, 3); /* extra space to call generator */ forbody(ls, base, line, nvars - 3, 0); }
static void constructor (LexState *ls, expdesc *t) { /* constructor -> ?? */ FuncState *fs = ls->fs; int line = ls->linenumber; int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); struct ConsControl cc; cc.na = cc.nh = cc.tostore = 0; cc.t = t; init_exp(t, VRELOCABLE, pc); init_exp(&cc.v, VVOID, 0); /* no value (yet) */ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ checknext(ls, '{'); do { lua_assert(cc.v.k == VVOID || cc.tostore > 0); if (ls->t.token == '}') break; closelistfield(fs, &cc); switch(ls->t.token) { case TK_NAME: { /* may be listfields or recfields */ luaX_lookahead(ls); if (ls->lookahead.token != '=') /* expression? */ listfield(ls, &cc); else recfield(ls, &cc); break; } case '[': { /* constructor_item -> recfield */ recfield(ls, &cc); break; } default: { /* constructor_part -> listfield */ listfield(ls, &cc); break; } } } while (testnext(ls, ',') || testnext(ls, ';')); check_match(ls, '}', '{', line); lastlistfield(fs, &cc); SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ }
static void assignment(LexState* ls, struct LHS_assign* lh, int nvars) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) /* assignment -> `,' primaryexp assignment */ { struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); assignment(ls, &nv, nvars + 1); } else /* assignment -> `=' explist1 */ { int nexps; checknext(ls, '='); nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg - 1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); }
static void constructor (LexState *ls, expdesc *t) { /* constructor -> ?? */ FuncState *fs = ls->fs; int line = ls->linenumber; int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); struct ConsControl cc; cc.na = cc.nh = cc.tostore = 0; cc.t = t; init_exp(t, VRELOCABLE, pc); init_exp(&cc.v, VVOID, 0); /* no value (yet) */ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ checknext(ls, '{'); #if LUA_OPTIONAL_COMMA for (;;) { #else do { #endif /* LUA_OPTIONAL_COMMA */ lua_assert(cc.v.k == VVOID || cc.tostore > 0); if (ls->t.token == '}') break; closelistfield(fs, &cc); switch(ls->t.token) { case TK_NAME: { /* may be listfields or recfields */ luaX_lookahead(ls); if (ls->lookahead.token != '=') /* expression? */ listfield(ls, &cc); else recfield(ls, &cc); break; } case '[': { /* constructor_item -> recfield */ recfield(ls, &cc); break; } default: { /* constructor_part -> listfield */ listfield(ls, &cc); break; } } #if LUA_OPTIONAL_COMMA if (ls->t.token == ',' || ls->t.token == ';') next(ls); else if (ls->t.token == '}') break; } #else } while (testnext(ls, ',') || testnext(ls, ';')); #endif /* LUA_OPTIONAL_COMMA */ check_match(ls, '}', '{', line); lastlistfield(fs, &cc); SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ } /* }====================================================================== */ static void parlist (LexState *ls) { /* parlist -> [ param { `,' param } ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; f->is_vararg = 0; if (ls->t.token != ')') { /* is `parlist' not empty? */ do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ new_localvar(ls, str_checkname(ls), nparams++); break; } case TK_DOTS: { /* param -> `...' */ luaX_next(ls); #if defined(LUA_COMPAT_VARARG) /* use `arg' as default name */ new_localvarliteral(ls, "arg", nparams++); f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; #endif f->is_vararg |= VARARG_ISVARARG; break; } default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); } } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ }
static void trystat (LexState *ls, int line) { /* trystat -> TRY block CATCH err DO block END */ FuncState *fs = ls->fs; BlockCnt bl; int base, pc, escapelist = NO_JUMP; luaX_next(ls); enterblock(fs, &bl, 2); /* try block */ base = fs->freereg; new_localvarliteral(ls, "(error obj)", 0); adjustlocalvars(ls, 1); /* error object */ luaK_reserveregs(fs, 1); pc = luaK_codeAsBx(fs, OP_TRY, base, NO_JUMP); chunk(ls); if (ls->t.token == TK_CATCH) { TString *varname; int errobj; luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0); luaK_concat(fs, &escapelist, luaK_jump(fs)); SET_OPCODE(fs->f->code[pc], OP_TRYCATCH); /* change it to TRYCATCH */ luaK_patchtohere(fs, pc); bl.isbreakable = 0; // local err luaX_next(ls); /* skip `catch' */ varname = str_checkname(ls); /* first variable name */ // do checknext(ls, TK_DO); errobj = fs->freereg; new_localvar(ls, varname, 0); adjustlocalvars(ls, 1); luaK_reserveregs(fs, 1); luaK_codeABC(fs, OP_MOVE, errobj, base, 0); block(ls); } else if (ls->t.token == TK_FINALLY) { luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0); luaK_concat(fs, &escapelist, luaK_jump(fs)); SET_OPCODE(fs->f->code[pc], OP_TRYFIN); /* change it to TRYFIN */ luaK_patchtohere(fs, pc); bl.isbreakable = 3; luaX_next(ls); /* skip 'finally' */ block(ls); luaK_codeABC(fs, OP_RETFIN, base, 0, 0); /* OP_ENDFIN jump to the return point */ } else { luaK_codeABC(fs, OP_EXITTRY, 0, 0, 0); luaK_concat(fs, &escapelist, pc); } leaveblock(fs); luaK_patchtohere(fs, escapelist); check_match(ls, TK_END, TK_TRY, line); }
isearch(f, n) { int status; /* Search status */ int col; /* prompt column */ register int cpos; /* character number in search string */ register int c; /* current input character */ char pat_save[NPAT]; /* Saved copy of the old pattern str */ LINE *curline; /* Current line on entry */ int curoff; /* Current offset on entry */ int init_direction; /* The initial search direction */ /* Initialize starting conditions */ cmd_reexecute = -1; /* We're not re-executing (yet?) */ cmd_offset = 0; /* Start at the beginning of the buff */ cmd_buff[0] = '\0'; /* Init the command buffer */ strncpy (pat_save, pat, NPAT); /* Save the old pattern string */ curline = curwp->w_dotp; /* Save the current line pointer */ curoff = curwp->w_doto; /* Save the current offset */ init_direction = n; /* Save the initial search direction */ /* This is a good place to start a re-execution: */ start_over: /* ask the user for the text of a pattern */ col = promptpattern("ISearch: "); /* Prompt, remember the col */ cpos = 0; /* Start afresh */ status = TRUE; /* Assume everything's cool */ /* Get the first character in the pattern. If we get an initial Control-S or Control-R, re-use the old search string and find the first occurrence */ c = get_char(); /* Get the first character */ if ((c == IS_FORWARD) || (c == IS_REVERSE) || (c == IS_VMSFORW)) /* Reuse old search string? */ { for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */ col = echochar(pat[cpos],col); /* and re-echo the string */ if (c == IS_REVERSE) { /* forward search? */ n = -1; /* No, search in reverse */ backchar (TRUE, 1); /* Be defensive about EOB */ } else n = 1; /* Yes, search forward */ status = scanmore(pat,n,status); /* Do the search */ c = get_char (); /* Get another character */ } /* Top of the per character loop */ for (;;) /* ISearch per character loop */ { /* Check for magic characters first: */ /* Most cases here change the search */ switch (c) /* dispatch on the input char */ { case IS_ABORT: /* If abort search request */ return(FALSE); /* Quit searching again */ case IS_REVERSE: /* If backward search */ case IS_FORWARD: /* If forward search */ case IS_VMSFORW: /* of either flavor */ if (c == IS_REVERSE) /* If reverse search */ n = -1; /* Set the reverse direction */ else /* Otherwise, */ n = 1; /* go forward */ status = scanmore(pat,n,TRUE); /* Start the search again */ c = get_char (); /* Get the next char */ continue; /* Go continue with the search*/ case IS_QUIT: /* Want to quit searching? */ return (TRUE); /* Quit searching now */ case IS_NEWLINE: /* Carriage return */ c = '\n'; /* Make it a new line */ break; /* Make sure we use it */ case IS_QUOTE: /* Quote character */ case IS_VMSQUOTE: /* of either variety */ c = get_char (); /* Get the next char */ case IS_TAB: /* Generically allowed */ case '\n': /* controlled characters */ break; /* Make sure we use it */ case IS_BACKSP: /* If a backspace: */ case IS_RUBOUT: /* or if a Rubout: */ if (cmd_offset <= 1) /* Anything to delete? */ return (TRUE); /* No, just exit */ --cmd_offset; /* Back up over the Rubout */ cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */ curwp->w_dotp = curline; /* Reset the line pointer */ curwp->w_doto = curoff; /* and the offset */ n = init_direction; /* Reset the search direction */ strncpy (pat, pat_save, NPAT); /* Restore the old search str */ cmd_reexecute = 0; /* Start the whole mess over */ goto start_over; /* Let it take care of itself */ /* Presumably a quasi-normal character comes here */ default: /* All other chars */ if (c < ' ') /* Is it printable? */ { /* Nope. */ reeat (c); /* Re-eat the char */ return (TRUE); /* And return the last status */ } } /* Switch */ /* I guess we got something to search for, so search for it */ pat[cpos++] = c; /* put the char in the buffer */ if (cpos >= NPAT) /* too many chars in string? */ { /* Yup. Complain about it */ mlwrite("? Search string too long"); return(TRUE); /* Return an error */ } pat[cpos] = 0; /* null terminate the buffer */ col = echochar(c,col); /* Echo the character */ if (!status) { /* If we lost last time */ (*term.t_putchar)(BELL); /* Feep again */ (*term.t_flush)(); /* see that the feep feeps */ } else /* Otherwise, we must have won*/ if (!(status = checknext(c,pat,n,status))) /* See if match */ status = scanmore(pat,n,TRUE); /* or find the next match */ c = get_char (); /* Get the next char */ } /* for {;;} */ }