mirror of
https://github.com/lua/lua
synced 2024-11-22 12:51:30 +03:00
63295f1f7f
The parser were mixing compiler indices of variables with stack indices, so that when a to-be-closed variable was used inside the scope of compile-time constants (which may be optimized away), it might be closed in the wrong place. (See new tests for examples.) Besides fixing the bugs, this commit also changed comments and variable names to avoid that kind of confusion and added tests.
171 lines
5.8 KiB
C
171 lines
5.8 KiB
C
/*
|
|
** $Id: lparser.h $
|
|
** Lua Parser
|
|
** See Copyright Notice in lua.h
|
|
*/
|
|
|
|
#ifndef lparser_h
|
|
#define lparser_h
|
|
|
|
#include "llimits.h"
|
|
#include "lobject.h"
|
|
#include "lzio.h"
|
|
|
|
|
|
/*
|
|
** Expression and variable descriptor.
|
|
** Code generation for variables and expressions can be delayed to allow
|
|
** optimizations; An 'expdesc' structure describes a potentially-delayed
|
|
** variable/expression. It has a description of its "main" value plus a
|
|
** list of conditional jumps that can also produce its value (generated
|
|
** by short-circuit operators 'and'/'or').
|
|
*/
|
|
|
|
/* kinds of variables/expressions */
|
|
typedef enum {
|
|
VVOID, /* when 'expdesc' describes the last expression a list,
|
|
this kind means an empty list (so, no expression) */
|
|
VNIL, /* constant nil */
|
|
VTRUE, /* constant true */
|
|
VFALSE, /* constant false */
|
|
VK, /* constant in 'k'; info = index of constant in 'k' */
|
|
VKFLT, /* floating constant; nval = numerical float value */
|
|
VKINT, /* integer constant; ival = numerical integer value */
|
|
VKSTR, /* string constant; strval = TString address;
|
|
(string is fixed by the lexer) */
|
|
VNONRELOC, /* expression has its value in a fixed register;
|
|
info = result register */
|
|
VLOCAL, /* local variable; var.sidx = stack index (local register);
|
|
var.vidx = relative index in 'actvar.arr' */
|
|
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
|
VCONST, /* compile-time constant; info = absolute index in 'actvar.arr' */
|
|
VINDEXED, /* indexed variable;
|
|
ind.t = table register;
|
|
ind.idx = key's R index */
|
|
VINDEXUP, /* indexed upvalue;
|
|
ind.t = table upvalue;
|
|
ind.idx = key's K index */
|
|
VINDEXI, /* indexed variable with constant integer;
|
|
ind.t = table register;
|
|
ind.idx = key's value */
|
|
VINDEXSTR, /* indexed variable with literal string;
|
|
ind.t = table register;
|
|
ind.idx = key's K index */
|
|
VJMP, /* expression is a test/comparison;
|
|
info = pc of corresponding jump instruction */
|
|
VRELOC, /* expression can put result in any register;
|
|
info = instruction pc */
|
|
VCALL, /* expression is a function call; info = instruction pc */
|
|
VVARARG /* vararg expression; info = instruction pc */
|
|
} expkind;
|
|
|
|
|
|
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
|
|
#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
|
|
|
|
|
|
typedef struct expdesc {
|
|
expkind k;
|
|
union {
|
|
lua_Integer ival; /* for VKINT */
|
|
lua_Number nval; /* for VKFLT */
|
|
TString *strval; /* for VKSTR */
|
|
int info; /* for generic use */
|
|
struct { /* for indexed variables */
|
|
short idx; /* index (R or "long" K) */
|
|
lu_byte t; /* table (register or upvalue) */
|
|
} ind;
|
|
struct { /* for local variables */
|
|
lu_byte sidx; /* index in the stack */
|
|
unsigned short vidx; /* compiler index (in 'actvar.arr') */
|
|
} var;
|
|
} u;
|
|
int t; /* patch list of 'exit when true' */
|
|
int f; /* patch list of 'exit when false' */
|
|
} expdesc;
|
|
|
|
|
|
/* kinds of variables */
|
|
#define VDKREG 0 /* regular */
|
|
#define RDKCONST 1 /* constant */
|
|
#define RDKTOCLOSE 2 /* to-be-closed */
|
|
#define RDKCTC 3 /* compile-time constant */
|
|
|
|
/* description of an active local variable */
|
|
typedef union Vardesc {
|
|
struct {
|
|
TValuefields; /* constant value (if it is a compile-time constant) */
|
|
lu_byte kind;
|
|
lu_byte sidx; /* index of the variable in the stack */
|
|
short pidx; /* index of the variable in the Proto's 'locvars' array */
|
|
TString *name; /* variable name */
|
|
} vd;
|
|
TValue k; /* constant value (if any) */
|
|
} Vardesc;
|
|
|
|
|
|
|
|
/* description of pending goto statements and label statements */
|
|
typedef struct Labeldesc {
|
|
TString *name; /* label identifier */
|
|
int pc; /* position in code */
|
|
int line; /* line where it appeared */
|
|
lu_byte nactvar; /* number of active variables in that position */
|
|
lu_byte close; /* goto that escapes upvalues */
|
|
} Labeldesc;
|
|
|
|
|
|
/* list of labels or gotos */
|
|
typedef struct Labellist {
|
|
Labeldesc *arr; /* array */
|
|
int n; /* number of entries in use */
|
|
int size; /* array size */
|
|
} Labellist;
|
|
|
|
|
|
/* dynamic structures used by the parser */
|
|
typedef struct Dyndata {
|
|
struct { /* list of all active local variables */
|
|
Vardesc *arr;
|
|
int n;
|
|
int size;
|
|
} actvar;
|
|
Labellist gt; /* list of pending gotos */
|
|
Labellist label; /* list of active labels */
|
|
} Dyndata;
|
|
|
|
|
|
/* control of blocks */
|
|
struct BlockCnt; /* defined in lparser.c */
|
|
|
|
|
|
/* state needed to generate code for a given function */
|
|
typedef struct FuncState {
|
|
Proto *f; /* current function header */
|
|
struct FuncState *prev; /* enclosing function */
|
|
struct LexState *ls; /* lexical state */
|
|
struct BlockCnt *bl; /* chain of current blocks */
|
|
int pc; /* next position to code (equivalent to 'ncode') */
|
|
int lasttarget; /* 'label' of last 'jump label' */
|
|
int previousline; /* last line that was saved in 'lineinfo' */
|
|
int nk; /* number of elements in 'k' */
|
|
int np; /* number of elements in 'p' */
|
|
int nabslineinfo; /* number of elements in 'abslineinfo' */
|
|
int firstlocal; /* index of first local var (in Dyndata array) */
|
|
int firstlabel; /* index of first label (in 'dyd->label->arr') */
|
|
short ndebugvars; /* number of elements in 'f->locvars' */
|
|
lu_byte nactvar; /* number of active local variables */
|
|
lu_byte nups; /* number of upvalues */
|
|
lu_byte freereg; /* first free register */
|
|
lu_byte iwthabs; /* instructions issued since last absolute line info */
|
|
lu_byte needclose; /* function needs to close upvalues when returning */
|
|
} FuncState;
|
|
|
|
|
|
LUAI_FUNC int luaY_nvarstack (FuncState *fs);
|
|
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
|
|
Dyndata *dyd, const char *name, int firstchar);
|
|
|
|
|
|
#endif
|