mirror of
https://github.com/lua/lua.git
synced 2024-11-27 04:03:54 +08:00
first implementation of unrestricted static scoping
This commit is contained in:
parent
4d0935ec0f
commit
abdbe883a8
11
lapi.c
11
lapi.c
@ -248,7 +248,7 @@ LUA_API size_t lua_strlen (lua_State *L, int index) {
|
||||
|
||||
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) {
|
||||
StkId o = luaA_indexAcceptable(L, index);
|
||||
return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->f.c;
|
||||
return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->u.c.f;
|
||||
}
|
||||
|
||||
|
||||
@ -310,9 +310,16 @@ LUA_API void lua_pushstring (lua_State *L, const l_char *s) {
|
||||
|
||||
|
||||
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
|
||||
Closure *cl;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
luaV_Cclosure(L, fn, n);
|
||||
cl = luaF_newCclosure(L, n);
|
||||
cl->u.c.f = fn;
|
||||
L->top -= n;
|
||||
while (n--)
|
||||
setobj(&cl->u.c.upvalue[n], L->top+n);
|
||||
setclvalue(L->top, cl);
|
||||
incr_top;
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
11
lcode.c
11
lcode.c
@ -273,6 +273,11 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
||||
e->k = VNONRELOC;
|
||||
break;
|
||||
}
|
||||
case VUPVAL: {
|
||||
e->u.i.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.i.info, 0);
|
||||
e->k = VRELOCABLE;
|
||||
break;
|
||||
}
|
||||
case VGLOBAL: {
|
||||
e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info);
|
||||
e->k = VRELOCABLE;
|
||||
@ -437,6 +442,12 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
|
||||
luaK_exp2reg(fs, exp, var->u.i.info);
|
||||
break;
|
||||
}
|
||||
case VUPVAL: {
|
||||
int e = luaK_exp2anyreg(fs, exp);
|
||||
freereg(fs, e);
|
||||
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.i.info, 0);
|
||||
break;
|
||||
}
|
||||
case VGLOBAL: {
|
||||
int e = luaK_exp2anyreg(fs, exp);
|
||||
freereg(fs, e);
|
||||
|
28
ldebug.c
28
ldebug.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.c,v 1.86 2001/06/28 19:58:57 roberto Exp roberto $
|
||||
** $Id: ldebug.c,v 1.87 2001/07/03 17:01:34 roberto Exp $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -117,7 +117,7 @@ int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) {
|
||||
static int currentpc (CallInfo *ci) {
|
||||
lua_assert(isLmark(ci));
|
||||
if (ci->pc)
|
||||
return (*ci->pc - ci_func(ci)->f.l->code) - 1;
|
||||
return (*ci->pc - ci_func(ci)->u.l.p->code) - 1;
|
||||
else
|
||||
return -1; /* function is not active */
|
||||
}
|
||||
@ -127,7 +127,7 @@ static int currentline (CallInfo *ci) {
|
||||
if (!isLmark(ci))
|
||||
return -1; /* only active lua functions have current-line information */
|
||||
else {
|
||||
int *lineinfo = ci_func(ci)->f.l->lineinfo;
|
||||
int *lineinfo = ci_func(ci)->u.l.p->lineinfo;
|
||||
return luaG_getline(lineinfo, currentpc(ci), 1, NULL);
|
||||
}
|
||||
}
|
||||
@ -135,7 +135,7 @@ static int currentline (CallInfo *ci) {
|
||||
|
||||
|
||||
static Proto *getluaproto (CallInfo *ci) {
|
||||
return (isLmark(ci) ? ci_func(ci)->f.l : NULL);
|
||||
return (isLmark(ci) ? ci_func(ci)->u.l.p : NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) {
|
||||
ar->what = l_s("C");
|
||||
}
|
||||
else
|
||||
infoLproto(ar, cl->f.l);
|
||||
infoLproto(ar, cl->u.l.p);
|
||||
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
|
||||
if (ar->linedefined == 0)
|
||||
ar->what = l_s("main");
|
||||
@ -323,14 +323,15 @@ static int precheck (const Proto *pt) {
|
||||
}
|
||||
|
||||
|
||||
static int checkopenop (Instruction i) {
|
||||
OpCode op = GET_OPCODE(i);
|
||||
switch (op) {
|
||||
static int checkopenop (const Proto *pt, int pc) {
|
||||
Instruction i = pt->code[pc+1];
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_CALL:
|
||||
case OP_RETURN: {
|
||||
check(GETARG_B(i) == NO_REG);
|
||||
return 1;
|
||||
}
|
||||
case OP_CLOSE: return checkopenop(pt, pc+1);
|
||||
case OP_SETLISTO: return 1;
|
||||
default: return 0; /* invalid instruction after an open call */
|
||||
}
|
||||
@ -382,7 +383,8 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
last = pc; /* set registers from `a' to `b' */
|
||||
break;
|
||||
}
|
||||
case OP_LOADUPVAL: {
|
||||
case OP_GETUPVAL:
|
||||
case OP_SETUPVAL: {
|
||||
check(b < pt->nupvalues);
|
||||
break;
|
||||
}
|
||||
@ -419,7 +421,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
checkreg(pt, a+b);
|
||||
}
|
||||
if (c == NO_REG) {
|
||||
check(checkopenop(pt->code[pc+1]));
|
||||
check(checkopenop(pt, pc));
|
||||
}
|
||||
else if (c != 0)
|
||||
checkreg(pt, a+c-1);
|
||||
@ -452,7 +454,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
}
|
||||
case OP_CLOSURE: {
|
||||
check(b < pt->sizep);
|
||||
checkreg(pt, a + pt->p[b]->nupvalues - 1);
|
||||
check(pc + pt->p[b]->nupvalues < pt->sizecode);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@ -472,7 +474,7 @@ int luaG_checkcode (const Proto *pt) {
|
||||
static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) {
|
||||
CallInfo *ci = ci_stack(L, obj);
|
||||
if (isLmark(ci)) { /* an active Lua function? */
|
||||
Proto *p = ci_func(ci)->f.l;
|
||||
Proto *p = ci_func(ci)->u.l.p;
|
||||
int pc = currentpc(ci);
|
||||
int stackpos = obj - ci->base;
|
||||
Instruction i;
|
||||
@ -516,7 +518,7 @@ static const l_char *getfuncname (lua_State *L, CallInfo *ci,
|
||||
if (ci == &L->basefunc || !isLmark(ci))
|
||||
return NULL; /* not an active Lua function */
|
||||
else {
|
||||
Proto *p = ci_func(ci)->f.l;
|
||||
Proto *p = ci_func(ci)->u.l.p;
|
||||
int pc = currentpc(ci);
|
||||
Instruction i;
|
||||
if (pc == -1) return NULL; /* function is not activated */
|
||||
|
28
ldo.c
28
ldo.c
@ -15,6 +15,7 @@
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
@ -122,9 +123,9 @@ static StkId callCclosure (lua_State *L, const struct Closure *cl) {
|
||||
int n;
|
||||
luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */
|
||||
for (n=0; n<nup; n++) /* copy upvalues as extra arguments */
|
||||
setobj(L->top++, &cl->upvalue[n]);
|
||||
setobj(L->top++, &cl->u.c.upvalue[n]);
|
||||
lua_unlock(L);
|
||||
n = (*cl->f.c)(L); /* do the actual call */
|
||||
n = (*cl->u.c.f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
return L->top - n; /* return index of first result */
|
||||
}
|
||||
@ -209,7 +210,12 @@ struct SParser { /* data to `f_parser' */
|
||||
static void f_parser (lua_State *L, void *ud) {
|
||||
struct SParser *p = cast(struct SParser *, ud);
|
||||
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
|
||||
luaV_Lclosure(L, tf, 0);
|
||||
Closure *cl = luaF_newLclosure(L, 0);
|
||||
cl->u.l.p = tf;
|
||||
luaF_LConlist(L, cl);
|
||||
setclvalue(L->top, cl);
|
||||
incr_top;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -286,6 +292,9 @@ struct lua_longjmp {
|
||||
jmp_buf b;
|
||||
struct lua_longjmp *previous;
|
||||
volatile int status; /* error code */
|
||||
CallInfo *ci; /* call info of active function that set protection */
|
||||
StkId top; /* top stack when protection was set */
|
||||
int allowhooks; /* `allowhook' state when protection was set */
|
||||
};
|
||||
|
||||
|
||||
@ -325,19 +334,20 @@ void luaD_breakrun (lua_State *L, int errcode) {
|
||||
|
||||
|
||||
int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) {
|
||||
CallInfo *oldci = L->ci;
|
||||
StkId oldtop = L->top;
|
||||
struct lua_longjmp lj;
|
||||
int allowhooks = L->allowhooks;
|
||||
lj.ci = L->ci;
|
||||
lj.top = L->top;
|
||||
lj.allowhooks = L->allowhooks;
|
||||
lj.status = 0;
|
||||
lj.previous = L->errorJmp; /* chain new error handler */
|
||||
L->errorJmp = &lj;
|
||||
if (setjmp(lj.b) == 0)
|
||||
(*f)(L, ud);
|
||||
else { /* an error occurred: restore the state */
|
||||
L->allowhooks = allowhooks;
|
||||
L->ci = oldci;
|
||||
L->top = oldtop;
|
||||
luaF_close(L, lj.top); /* close eventual pending closures */
|
||||
L->ci = lj.ci;
|
||||
L->top = lj.top;
|
||||
L->allowhooks = lj.allowhooks;
|
||||
restore_stack_limit(L);
|
||||
}
|
||||
L->errorJmp = lj.previous; /* restore old error handler */
|
||||
|
100
lfunc.c
100
lfunc.c
@ -12,15 +12,20 @@
|
||||
|
||||
#include "lfunc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
#define sizeclosure(n) (cast(int, sizeof(Closure)) + \
|
||||
#define sizeCclosure(n) (cast(int, sizeof(Closure)) + \
|
||||
cast(int, sizeof(TObject)*((n)-1)))
|
||||
|
||||
#define sizeLclosure(n) (cast(int, sizeof(Closure)) + \
|
||||
cast(int, sizeof(TObject *)*((n)-1)))
|
||||
|
||||
Closure *luaF_newclosure (lua_State *L, int nelems) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeclosure(nelems)));
|
||||
|
||||
Closure *luaF_newCclosure (lua_State *L, int nelems) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
|
||||
c->isC = 1;
|
||||
c->next = G(L)->rootcl;
|
||||
G(L)->rootcl = c;
|
||||
c->mark = c;
|
||||
@ -29,6 +34,90 @@ Closure *luaF_newclosure (lua_State *L, int nelems) {
|
||||
}
|
||||
|
||||
|
||||
Closure *luaF_newLclosure (lua_State *L, int nelems) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
|
||||
c->isC = 0;
|
||||
c->mark = c;
|
||||
c->u.l.isopen = 0;
|
||||
c->nupvalues = nelems;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** returns the open pointer in a closure that points higher into the stack
|
||||
*/
|
||||
static StkId uppoint (Closure *cl) {
|
||||
StkId lp = NULL;
|
||||
int i;
|
||||
lua_assert(cl->u.l.isopen);
|
||||
for (i=0; i<cl->nupvalues; i++) {
|
||||
if (!luaF_isclosed(cl, i))
|
||||
if (lp == NULL || cl->u.l.upvals[i] > lp)
|
||||
lp = cl->u.l.upvals[i];
|
||||
}
|
||||
lua_assert(lp != NULL);
|
||||
return lp;
|
||||
}
|
||||
|
||||
|
||||
void luaF_LConlist (lua_State *L, Closure *cl) {
|
||||
lua_assert(!cl->isC);
|
||||
if (cl->u.l.isopen == 0) { /* no more open entries? */
|
||||
cl->next = G(L)->rootcl; /* insert in final list */
|
||||
G(L)->rootcl = cl;
|
||||
}
|
||||
else { /* insert in list of open closures, ordered by decreasing uppoints */
|
||||
StkId cli = uppoint(cl);
|
||||
Closure **p = &L->opencl;
|
||||
while (*p != NULL && uppoint(*p) > cli) p = &(*p)->next;
|
||||
cl->next = *p;
|
||||
*p = cl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int closeCl (lua_State *L, Closure *cl, StkId level) {
|
||||
int got = 0; /* flag: 1 if some pointer in the closure was corrected */
|
||||
int i;
|
||||
for (i=0; i<cl->nupvalues; i++) {
|
||||
StkId var;
|
||||
if (!luaF_isclosed(cl, i) && (var=cl->u.l.upvals[i]) >= level) {
|
||||
if (ttype(var) != LUA_TUPVAL) {
|
||||
UpVal *v = luaM_new(L, UpVal);
|
||||
v->val = *var;
|
||||
v->marked = 0;
|
||||
v->next = G(L)->rootupval;
|
||||
G(L)->rootupval = v;
|
||||
setupvalue(var, v);
|
||||
}
|
||||
cl->u.l.upvals[i] = cast(TObject *, vvalue(var));
|
||||
luaF_closeentry(cl, i);
|
||||
got = 1;
|
||||
}
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
|
||||
void luaF_close (lua_State *L, StkId level) {
|
||||
Closure *affected = NULL; /* closures with open pointers >= level */
|
||||
Closure *cl;
|
||||
while ((cl=L->opencl) != NULL) {
|
||||
if (!closeCl(L, cl, level)) break;
|
||||
/* some pointer in `cl' changed; will re-insert it in original list */
|
||||
L->opencl = cl->next; /* remove from original list */
|
||||
cl->next = affected;
|
||||
affected = cl; /* insert in affected list */
|
||||
}
|
||||
/* re-insert all affected closures in original list */
|
||||
while ((cl=affected) != NULL) {
|
||||
affected = cl->next;
|
||||
luaF_LConlist(L, cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Proto *luaF_newproto (lua_State *L) {
|
||||
Proto *f = luaM_new(L, Proto);
|
||||
f->k = NULL;
|
||||
@ -60,12 +149,13 @@ void luaF_freeproto (lua_State *L, Proto *f) {
|
||||
luaM_freearray(L, f->k, f->sizek, TObject);
|
||||
luaM_freearray(L, f->p, f->sizep, Proto *);
|
||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
|
||||
luaM_freelem(L, f, Proto);
|
||||
luaM_freelem(L, f);
|
||||
}
|
||||
|
||||
|
||||
void luaF_freeclosure (lua_State *L, Closure *c) {
|
||||
luaM_free(L, c, sizeclosure(c->nupvalues));
|
||||
int size = (c->isC) ? sizeCclosure(c->nupvalues) : sizeLclosure(c->nupvalues);
|
||||
luaM_free(L, c, size);
|
||||
}
|
||||
|
||||
|
||||
|
11
lfunc.h
11
lfunc.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lfunc.h,v 1.14 2000/12/28 12:55:41 roberto Exp roberto $
|
||||
** $Id: lfunc.h,v 1.15 2001/02/23 17:17:25 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -11,9 +11,16 @@
|
||||
#include "lobject.h"
|
||||
|
||||
|
||||
#define luaF_isclosed(c, i) (!((c)->u.l.isopen & (1 << (i))))
|
||||
#define luaF_openentry(c, i) ((c)->u.l.isopen |= (1 << (i)))
|
||||
#define luaF_closeentry(c, i) ((c)->u.l.isopen &= ~(1 << (i)))
|
||||
|
||||
|
||||
Proto *luaF_newproto (lua_State *L);
|
||||
Closure *luaF_newclosure (lua_State *L, int nelems);
|
||||
Closure *luaF_newCclosure (lua_State *L, int nelems);
|
||||
Closure *luaF_newLclosure (lua_State *L, int nelems);
|
||||
void luaF_LConlist (lua_State *L, Closure *cl);
|
||||
void luaF_close (lua_State *L, StkId level);
|
||||
void luaF_freeproto (lua_State *L, Proto *f);
|
||||
void luaF_freeclosure (lua_State *L, Closure *c);
|
||||
|
||||
|
73
lgc.c
73
lgc.c
@ -7,6 +7,7 @@
|
||||
#define LUA_PRIVATE
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
@ -45,15 +46,12 @@ static void protomark (Proto *f) {
|
||||
for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
|
||||
strmark(f->locvars[i].varname);
|
||||
}
|
||||
lua_assert(luaG_checkcode(f));
|
||||
}
|
||||
|
||||
|
||||
static void markclosure (GCState *st, Closure *cl) {
|
||||
if (!ismarked(cl)) {
|
||||
if (!cl->isC) {
|
||||
lua_assert(cl->nupvalues == cl->f.l->nupvalues);
|
||||
protomark(cl->f.l);
|
||||
}
|
||||
cl->mark = st->cmark; /* chain it for later traversal */
|
||||
st->cmark = cl;
|
||||
}
|
||||
@ -84,7 +82,10 @@ static void markobject (GCState *st, TObject *o) {
|
||||
marktable(st, hvalue(o));
|
||||
break;
|
||||
}
|
||||
default: break; /* numbers, etc */
|
||||
default: {
|
||||
lua_assert(0 <= ttype(o) && ttype(o) <= LUA_TUPVAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,10 +120,26 @@ static void marktagmethods (global_State *G, GCState *st) {
|
||||
}
|
||||
|
||||
|
||||
static void traverseclosure (GCState *st, Closure *f) {
|
||||
int i;
|
||||
for (i=0; i<f->nupvalues; i++) /* mark its upvalues */
|
||||
markobject(st, &f->upvalue[i]);
|
||||
static void traverseclosure (GCState *st, Closure *cl) {
|
||||
if (cl->isC) {
|
||||
int i;
|
||||
for (i=0; i<cl->nupvalues; i++) /* mark its upvalues */
|
||||
markobject(st, &cl->u.c.upvalue[i]);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
lua_assert(cl->nupvalues == cl->u.l.p->nupvalues);
|
||||
protomark(cl->u.l.p);
|
||||
for (i=0; i<cl->nupvalues; i++) { /* mark its upvalues */
|
||||
if (luaF_isclosed(cl, i)) {
|
||||
UpVal *u = cast(UpVal *, cl->u.l.upvals[i]);
|
||||
if (!u->marked) {
|
||||
u->marked = 1;
|
||||
markobject(st, &u->val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -164,9 +181,9 @@ static void markall (lua_State *L) {
|
||||
marktable(&st, G(L)->weakregistry);
|
||||
for (;;) { /* mark tables and closures */
|
||||
if (st.cmark) {
|
||||
Closure *f = st.cmark; /* get first closure from list */
|
||||
st.cmark = f->mark; /* remove it from list */
|
||||
traverseclosure(&st, f);
|
||||
Closure *cl = st.cmark; /* get first closure from list */
|
||||
st.cmark = cl->mark; /* remove it from list */
|
||||
traverseclosure(&st, cl);
|
||||
}
|
||||
else if (st.tmark) {
|
||||
Hash *h = st.tmark; /* get first table from list */
|
||||
@ -232,8 +249,7 @@ static void collectproto (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static void collectclosure (lua_State *L) {
|
||||
Closure **p = &G(L)->rootcl;
|
||||
static void collectclosure (lua_State *L, Closure **p) {
|
||||
Closure *curr;
|
||||
while ((curr = *p) != NULL) {
|
||||
if (ismarked(curr)) {
|
||||
@ -248,6 +264,16 @@ static void collectclosure (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static void collectclosures (lua_State *L) {
|
||||
lua_State *L1 = L;
|
||||
do { /* for each thread */
|
||||
collectclosure(L1, &L1->opencl);
|
||||
L1 = L1->next;
|
||||
} while (L1 != L);
|
||||
collectclosure(L, &G(L)->rootcl);
|
||||
}
|
||||
|
||||
|
||||
static void collecttable (lua_State *L) {
|
||||
Hash **p = &G(L)->roottable;
|
||||
Hash *curr;
|
||||
@ -264,6 +290,22 @@ static void collecttable (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static void collectupval (lua_State *L) {
|
||||
UpVal **v = &G(L)->rootupval;
|
||||
UpVal *curr;
|
||||
while ((curr = *v) != NULL) {
|
||||
if (curr->marked) {
|
||||
curr->marked = 0;
|
||||
v = &curr->next;
|
||||
}
|
||||
else {
|
||||
*v = curr->next;
|
||||
luaM_freelem(L, curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void collectudata (lua_State *L, int keep) {
|
||||
Udata **p = &G(L)->rootudata;
|
||||
Udata *curr;
|
||||
@ -370,7 +412,8 @@ void luaC_collect (lua_State *L, int all) {
|
||||
collectstrings(L, all);
|
||||
collecttable(L);
|
||||
collectproto(L);
|
||||
collectclosure(L);
|
||||
collectupval(L);
|
||||
collectclosures(L);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llimits.h,v 1.30 2001/06/05 20:01:09 roberto Exp roberto $
|
||||
** $Id: llimits.h,v 1.31 2001/08/27 15:16:28 roberto Exp $
|
||||
** Limits, basic types, and some other `installation-dependent' definitions
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -51,6 +51,9 @@ typedef unsigned long lu_mem;
|
||||
/* an integer big enough to count the number of strings in use */
|
||||
typedef long ls_nstr;
|
||||
|
||||
/* a bitmap with one bit for each upvalue used by a function */
|
||||
typedef unsigned long ls_bitup;
|
||||
|
||||
|
||||
/* chars used as small naturals (so that `char' is reserved for characteres) */
|
||||
typedef unsigned char lu_byte;
|
||||
@ -108,7 +111,7 @@ typedef unsigned long Instruction;
|
||||
|
||||
/* maximum number of upvalues */
|
||||
#ifndef MAXUPVALUES
|
||||
#define MAXUPVALUES 32 /* arbitrary limit (<MAXSTACK) */
|
||||
#define MAXUPVALUES (sizeof(ls_bitup)*CHAR_BIT)
|
||||
#endif
|
||||
|
||||
|
||||
|
44
lobject.h
44
lobject.h
@ -27,15 +27,20 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* tags for values visible from Lua == first user-created tag */
|
||||
/* tags for values visible from Lua */
|
||||
#define NUM_TAGS 6
|
||||
|
||||
|
||||
/* extra tag: used locally when moving an upvalue from the stack to the heap */
|
||||
#define LUA_TUPVAL 6
|
||||
|
||||
|
||||
typedef union {
|
||||
union TString *ts;
|
||||
union Udata *u;
|
||||
struct Closure *cl;
|
||||
struct Hash *h;
|
||||
struct UpVal *v;
|
||||
lua_Number n; /* LUA_TNUMBER */
|
||||
} Value;
|
||||
|
||||
@ -53,6 +58,7 @@ typedef struct lua_TObject {
|
||||
#define uvalue(o) ((o)->value.u)
|
||||
#define clvalue(o) ((o)->value.cl)
|
||||
#define hvalue(o) ((o)->value.h)
|
||||
#define vvalue(o) ((o)->value.v)
|
||||
|
||||
|
||||
/* Macros to set values */
|
||||
@ -75,6 +81,9 @@ typedef struct lua_TObject {
|
||||
|
||||
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
|
||||
|
||||
#define setupvalue(obj,x) \
|
||||
{ TObject *_o=(obj); _o->tt=LUA_TUPVAL; _o->value.v=(x); }
|
||||
|
||||
#define setobj(obj1,obj2) \
|
||||
{ TObject *o1=(obj1); const TObject *o2=(obj2); \
|
||||
o1->tt=o2->tt; o1->value = o2->value; }
|
||||
@ -154,25 +163,48 @@ typedef struct LocVar {
|
||||
} LocVar;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Upvalues in the heap
|
||||
*/
|
||||
typedef struct UpVal {
|
||||
TObject val;
|
||||
struct UpVal *next;
|
||||
int marked;
|
||||
} UpVal;
|
||||
|
||||
|
||||
/*
|
||||
** Closures
|
||||
*/
|
||||
typedef struct Closure {
|
||||
int isC; /* 0 for Lua functions, 1 for C functions */
|
||||
int nupvalues;
|
||||
union {
|
||||
lua_CFunction c; /* C functions */
|
||||
struct Proto *l; /* Lua functions */
|
||||
} f;
|
||||
struct Closure *next;
|
||||
struct Closure *mark; /* marked closures (point to itself when not marked) */
|
||||
TObject upvalue[1];
|
||||
union {
|
||||
struct { /* C functions */
|
||||
lua_CFunction f;
|
||||
TObject upvalue[1];
|
||||
} c;
|
||||
struct { /* Lua functions */
|
||||
struct Proto *p;
|
||||
ls_bitup isopen; /* bitmap: bit==1 when upvals point to the stack */
|
||||
TObject *upvals[1]; /* may point to the stack or to an UpVal */
|
||||
} l;
|
||||
} u;
|
||||
} Closure;
|
||||
|
||||
|
||||
#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Hash Tables
|
||||
*/
|
||||
|
||||
typedef struct Node {
|
||||
struct Node *next; /* for chaining */
|
||||
TObject key;
|
||||
|
@ -20,10 +20,11 @@ const l_char *const luaP_opnames[] = {
|
||||
l_s("LOADK"),
|
||||
l_s("LOADINT"),
|
||||
l_s("LOADNIL"),
|
||||
l_s("LOADUPVAL"),
|
||||
l_s("GETUPVAL"),
|
||||
l_s("GETGLOBAL"),
|
||||
l_s("GETTABLE"),
|
||||
l_s("SETGLOBAL"),
|
||||
l_s("SETUPVAL"),
|
||||
l_s("SETTABLE"),
|
||||
l_s("NEWTABLE"),
|
||||
l_s("SELF"),
|
||||
@ -54,6 +55,7 @@ const l_char *const luaP_opnames[] = {
|
||||
l_s("TFORLOOP"),
|
||||
l_s("SETLIST"),
|
||||
l_s("SETLISTO"),
|
||||
l_s("CLOSE"),
|
||||
l_s("CLOSURE")
|
||||
};
|
||||
|
||||
@ -69,10 +71,11 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||
,opmode(0,0,0,0, 1,1,iABc) /* OP_LOADK */
|
||||
,opmode(0,0,0,0, 1,0,iAsBc) /* OP_LOADINT */
|
||||
,opmode(0,0,1,0, 1,0,iABC) /* OP_LOADNIL */
|
||||
,opmode(0,0,0,0, 1,0,iABc) /* OP_LOADUPVAL */
|
||||
,opmode(0,0,0,0, 1,0,iABC) /* OP_GETUPVAL */
|
||||
,opmode(0,0,0,0, 1,1,iABc) /* OP_GETGLOBAL */
|
||||
,opmode(0,0,1,1, 1,0,iABC) /* OP_GETTABLE */
|
||||
,opmode(0,0,0,0, 0,1,iABc) /* OP_SETGLOBAL */
|
||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_SETUPVAL */
|
||||
,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */
|
||||
,opmode(0,0,0,0, 1,0,iABc) /* OP_NEWTABLE */
|
||||
,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */
|
||||
@ -103,6 +106,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||
,opmode(0,0,0,0, 0,0,iAsBc) /* OP_TFORLOOP */
|
||||
,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */
|
||||
,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */
|
||||
,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */
|
||||
,opmode(0,0,0,0, 1,0,iABc) /* OP_CLOSURE */
|
||||
};
|
||||
|
||||
|
@ -131,12 +131,13 @@ OP_MOVE,/* A B R(A) := R(B) */
|
||||
OP_LOADK,/* A Bc R(A) := Kst(Bc) */
|
||||
OP_LOADINT,/* A sBc R(A) := (Number)sBc */
|
||||
OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
|
||||
OP_LOADUPVAL,/* A Bc R(A) := UpValue[Bc] */
|
||||
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
|
||||
|
||||
OP_GETGLOBAL,/* A Bc R(A) := Gbl[Kst(Bc)] */
|
||||
OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */
|
||||
|
||||
OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */
|
||||
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
|
||||
OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */
|
||||
|
||||
OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */
|
||||
@ -180,6 +181,7 @@ OP_TFORLOOP,/* A sBc */
|
||||
OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */
|
||||
OP_SETLISTO,/* A Bc */
|
||||
|
||||
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
|
||||
OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */
|
||||
} OpCode;
|
||||
|
||||
|
147
lparser.c
147
lparser.c
@ -41,6 +41,7 @@ typedef struct Constdesc {
|
||||
typedef struct Breaklabel {
|
||||
struct Breaklabel *previous; /* chain */
|
||||
int breaklist; /* list of jumps out of this loop */
|
||||
int nactloc; /* # of active local variables outside the breakable structure */
|
||||
} Breaklabel;
|
||||
|
||||
|
||||
@ -163,13 +164,29 @@ static void new_localvar (LexState *ls, TString *name, int n) {
|
||||
|
||||
static void adjustlocalvars (LexState *ls, int nvars) {
|
||||
FuncState *fs = ls->fs;
|
||||
while (nvars--)
|
||||
fs->f->locvars[fs->actloc[fs->nactloc++]].startpc = fs->pc;
|
||||
while (nvars--) {
|
||||
fs->f->locvars[fs->actloc[fs->nactloc]].startpc = fs->pc;
|
||||
resetbit(fs->wasup, fs->nactloc);
|
||||
fs->nactloc++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void closelevel (LexState *ls, int level) {
|
||||
FuncState *fs = ls->fs;
|
||||
int i;
|
||||
for (i=level; i<fs->nactloc; i++)
|
||||
if (testbit(fs->wasup, i)) {
|
||||
luaK_codeABC(fs, OP_CLOSE, level, 0, 0);
|
||||
return;
|
||||
}
|
||||
return; /* nothing to close */
|
||||
}
|
||||
|
||||
|
||||
static void removelocalvars (LexState *ls, int nvars) {
|
||||
FuncState *fs = ls->fs;
|
||||
closelevel(ls, fs->nactloc - nvars);
|
||||
while (nvars--)
|
||||
fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc;
|
||||
}
|
||||
@ -180,68 +197,47 @@ static void new_localvarstr (LexState *ls, const l_char *name, int n) {
|
||||
}
|
||||
|
||||
|
||||
static int search_local (LexState *ls, TString *n, expdesc *var) {
|
||||
FuncState *fs;
|
||||
int level = 0;
|
||||
for (fs=ls->fs; fs; fs=fs->prev) {
|
||||
int i;
|
||||
for (i=fs->nactloc-1; i >= 0; i--) {
|
||||
if (n == fs->f->locvars[fs->actloc[i]].varname) {
|
||||
init_exp(var, VLOCAL, i);
|
||||
return level;
|
||||
}
|
||||
}
|
||||
level++; /* `var' not found; check outer level */
|
||||
}
|
||||
init_exp(var, VGLOBAL, 0); /* not found in any level; must be global */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void singlevar (LexState *ls, TString *n, expdesc *var) {
|
||||
int level = search_local(ls, n, var);
|
||||
if (level >= 1) /* neither local (0) nor global (-1)? */
|
||||
luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"),
|
||||
getstr(n));
|
||||
else if (level == -1) /* global? */
|
||||
var->u.i.info = luaK_stringk(ls->fs, n);
|
||||
}
|
||||
|
||||
|
||||
static int indexupvalue (LexState *ls, expdesc *v) {
|
||||
FuncState *fs = ls->fs;
|
||||
static int indexupvalue (FuncState *fs, expdesc *v) {
|
||||
int i;
|
||||
for (i=0; i<fs->f->nupvalues; i++) {
|
||||
if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info)
|
||||
return i;
|
||||
}
|
||||
/* new one */
|
||||
luaX_checklimit(ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues"));
|
||||
luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues"));
|
||||
fs->upvalues[fs->f->nupvalues] = *v;
|
||||
return fs->f->nupvalues++;
|
||||
}
|
||||
|
||||
|
||||
static void codeupvalue (LexState *ls, expdesc *v, TString *n) {
|
||||
FuncState *fs = ls->fs;
|
||||
int level;
|
||||
level = search_local(ls, n, v);
|
||||
if (level == -1) { /* global? */
|
||||
if (fs->prev == NULL)
|
||||
luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"),
|
||||
getstr(n));
|
||||
v->u.i.info = luaK_stringk(fs->prev, n);
|
||||
static void singlevar (FuncState *fs, TString *n, expdesc *var, int baselevel) {
|
||||
if (fs == NULL)
|
||||
init_exp(var, VGLOBAL, 0); /* not local in any level; global variable */
|
||||
else { /* look up at current level */
|
||||
int i;
|
||||
for (i=fs->nactloc-1; i >= 0; i--) {
|
||||
if (n == fs->f->locvars[fs->actloc[i]].varname) {
|
||||
if (!baselevel)
|
||||
setbit(fs->wasup, i); /* will be upvalue in some other level */
|
||||
init_exp(var, VLOCAL, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* not found at current level; try upper one */
|
||||
singlevar(fs->prev, n, var, 0);
|
||||
if (var->k == VGLOBAL) {
|
||||
if (baselevel)
|
||||
var->u.i.info = luaK_stringk(fs, n); /* info points to global name */
|
||||
}
|
||||
else { /* local variable in some upper level? */
|
||||
var->u.i.info = indexupvalue(fs, var);
|
||||
var->k = VUPVAL; /* upvalue in this level */
|
||||
}
|
||||
}
|
||||
else if (level != 1) {
|
||||
luaX_syntaxerror(ls,
|
||||
l_s("upvalue must be global or local to immediately outer function"),
|
||||
getstr(n));
|
||||
}
|
||||
init_exp(v, VRELOCABLE,
|
||||
luaK_codeABc(fs, OP_LOADUPVAL, 0, indexupvalue(ls, v)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
|
||||
FuncState *fs = ls->fs;
|
||||
int extra = nvars - nexps;
|
||||
@ -278,6 +274,7 @@ static void code_params (LexState *ls, int nparams, short dots) {
|
||||
|
||||
static void enterbreak (FuncState *fs, Breaklabel *bl) {
|
||||
bl->breaklist = NO_JUMP;
|
||||
bl->nactloc = fs->nactloc;
|
||||
bl->previous = fs->bl;
|
||||
fs->bl = bl;
|
||||
}
|
||||
@ -286,6 +283,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) {
|
||||
static void leavebreak (FuncState *fs, Breaklabel *bl) {
|
||||
fs->bl = bl->previous;
|
||||
luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs));
|
||||
lua_assert(bl->nactloc == fs->nactloc);
|
||||
}
|
||||
|
||||
|
||||
@ -293,16 +291,14 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
|
||||
FuncState *fs = ls->fs;
|
||||
Proto *f = fs->f;
|
||||
int i;
|
||||
int reg = fs->freereg;
|
||||
for (i=0; i<func->f->nupvalues; i++)
|
||||
luaK_exp2nextreg(fs, &func->upvalues[i]);
|
||||
luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
|
||||
MAXARG_Bc, l_s("constant table overflow"));
|
||||
f->p[fs->np++] = func->f;
|
||||
fs->freereg = reg; /* CLOSURE will consume those values */
|
||||
init_exp(v, VNONRELOC, reg);
|
||||
luaK_reserveregs(fs, 1);
|
||||
luaK_codeABc(fs, OP_CLOSURE, v->u.i.info, fs->np-1);
|
||||
init_exp(v, VRELOCABLE, luaK_codeABc(fs, OP_CLOSURE, 0, fs->np-1));
|
||||
for (i=0; i<func->f->nupvalues; i++) {
|
||||
luaK_exp2nextreg(fs, &func->upvalues[i]);
|
||||
fs->freereg--; /* CLOSURE will use these values */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -337,9 +333,9 @@ static void close_func (LexState *ls) {
|
||||
lua_State *L = ls->L;
|
||||
FuncState *fs = ls->fs;
|
||||
Proto *f = fs->f;
|
||||
removelocalvars(ls, fs->nactloc);
|
||||
luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */
|
||||
luaK_getlabel(fs); /* close eventual list of pending jumps */
|
||||
removelocalvars(ls, fs->nactloc);
|
||||
lua_assert(G(L)->roottable == fs->h);
|
||||
G(L)->roottable = fs->h->next;
|
||||
luaH_free(L, fs->h);
|
||||
@ -644,16 +640,18 @@ static void primaryexp (LexState *ls, expdesc *v) {
|
||||
return;
|
||||
}
|
||||
case TK_NAME: {
|
||||
singlevar(ls, str_checkname(ls), v);
|
||||
singlevar(ls->fs, str_checkname(ls), v, 1);
|
||||
next(ls);
|
||||
return;
|
||||
}
|
||||
case l_c('%'): {
|
||||
case l_c('%'): { /* for compatibility only */
|
||||
next(ls); /* skip `%' */
|
||||
codeupvalue(ls, v, str_checkname(ls));
|
||||
singlevar(ls->fs, str_checkname(ls), v, 1);
|
||||
check_condition(ls, v->k == VUPVAL, l_s("global upvalues are deprecated"));
|
||||
next(ls);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
luaK_error(ls, l_s("unexpected symbol"));
|
||||
return;
|
||||
@ -812,7 +810,7 @@ static void block (LexState *ls) {
|
||||
*/
|
||||
struct LHS_assign {
|
||||
struct LHS_assign *prev;
|
||||
expdesc v; /* variable (global, local, or indexed) */
|
||||
expdesc v; /* variable (global, local, upvalue, or indexed) */
|
||||
};
|
||||
|
||||
|
||||
@ -847,9 +845,8 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
|
||||
|
||||
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
|
||||
expdesc e;
|
||||
check_condition(ls, lh->v.k == VLOCAL || lh->v.k == VGLOBAL ||
|
||||
lh->v.k == VINDEXED,
|
||||
l_s("syntax error"));
|
||||
check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
|
||||
l_s("syntax error!!"));
|
||||
if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */
|
||||
struct LHS_assign nv;
|
||||
nv.prev = lh;
|
||||
@ -1054,7 +1051,7 @@ static void localstat (LexState *ls) {
|
||||
static int funcname (LexState *ls, expdesc *v) {
|
||||
/* funcname -> NAME {field} [`:' NAME] */
|
||||
int needself = 0;
|
||||
singlevar(ls, str_checkname(ls), v);
|
||||
singlevar(ls->fs, str_checkname(ls), v, 1);
|
||||
next(ls); /* skip var name */
|
||||
while (ls->t.token == l_c('.')) {
|
||||
luaY_field(ls, v);
|
||||
@ -1102,25 +1099,19 @@ static void retstat (LexState *ls) {
|
||||
if (block_follow(ls->t.token) || ls->t.token == l_c(';'))
|
||||
first = nret = 0; /* return no values */
|
||||
else {
|
||||
int n = explist1(ls, &e); /* optional return values */
|
||||
explist1(ls, &e); /* optional return values */
|
||||
if (e.k == VCALL) {
|
||||
luaK_setcallreturns(fs, &e, LUA_MULTRET);
|
||||
first = fs->nactloc;
|
||||
nret = NO_REG; /* return all values */
|
||||
}
|
||||
else {
|
||||
if (n == 1) { /* only one value? */
|
||||
luaK_exp2anyreg(fs, &e);
|
||||
first = e.u.i.info;
|
||||
nret = 1; /* return only this value */
|
||||
}
|
||||
else {
|
||||
luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
|
||||
first = fs->nactloc;
|
||||
nret = fs->freereg - first; /* return all `active' values */
|
||||
}
|
||||
luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
|
||||
first = fs->nactloc;
|
||||
nret = fs->freereg - first; /* return all `active' values */
|
||||
}
|
||||
}
|
||||
closelevel(ls, 0);
|
||||
luaK_codeABC(fs, OP_RETURN, first, nret, 0);
|
||||
fs->freereg = fs->nactloc; /* removes all temp values */
|
||||
}
|
||||
@ -1133,8 +1124,8 @@ static void breakstat (LexState *ls) {
|
||||
if (!bl)
|
||||
luaK_error(ls, l_s("no loop to break"));
|
||||
next(ls); /* skip BREAK */
|
||||
closelevel(ls, bl->nactloc);
|
||||
luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
|
||||
/* correct stack for compiler and symbolic execution */
|
||||
}
|
||||
|
||||
|
||||
|
20
lparser.h
20
lparser.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.h,v 1.33 2001/08/10 20:53:03 roberto Exp roberto $
|
||||
** $Id: lparser.h,v 1.34 2001/08/27 15:16:28 roberto Exp $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -7,11 +7,24 @@
|
||||
#ifndef lparser_h
|
||||
#define lparser_h
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lobject.h"
|
||||
#include "ltable.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
|
||||
/* small implementation of bit arrays */
|
||||
|
||||
#define BPW (CHAR_BIT*sizeof(unsigned int)) /* bits per word */
|
||||
|
||||
#define words2bits(b) (((b)-1)/BPW + 1)
|
||||
|
||||
#define setbit(a, b) ((a)[(b)/BPW] |= (1 << (b)%BPW))
|
||||
#define resetbit(a, b) ((a)[(b)/BPW] &= ~((1 << (b)%BPW)))
|
||||
#define testbit(a, b) ((a)[(b)/BPW] & (1 << (b)%BPW))
|
||||
|
||||
|
||||
/*
|
||||
** Expression descriptor
|
||||
*/
|
||||
@ -21,8 +34,9 @@ typedef enum {
|
||||
VNIL,
|
||||
VNUMBER, /* n = value */
|
||||
VK, /* info = index of constant in `k' */
|
||||
VGLOBAL, /* info = index of global name in `k' */
|
||||
VLOCAL, /* info = local register */
|
||||
VUPVAL, /* info = index of upvalue in `upvalues' */
|
||||
VGLOBAL, /* info = index of global name in `k' */
|
||||
VINDEXED, /* info = table register; aux = index register (or `k') */
|
||||
VRELOCABLE, /* info = instruction pc */
|
||||
VNONRELOC, /* info = result register */
|
||||
@ -63,6 +77,8 @@ typedef struct FuncState {
|
||||
struct Breaklabel *bl; /* chain of breakable blocks */
|
||||
expdesc upvalues[MAXUPVALUES]; /* upvalues */
|
||||
int actloc[MAXLOCALS]; /* local-variable stack (indices to locvars) */
|
||||
unsigned int wasup[words2bits(MAXLOCALS)]; /* bit array to mark whether a
|
||||
local variable was used as upvalue at some level */
|
||||
} FuncState;
|
||||
|
||||
|
||||
|
6
lstate.c
6
lstate.c
@ -58,6 +58,7 @@ static void f_luaopen (lua_State *L, void *ud) {
|
||||
G(L)->rootcl = NULL;
|
||||
G(L)->roottable = NULL;
|
||||
G(L)->rootudata = NULL;
|
||||
G(L)->rootupval = NULL;
|
||||
G(L)->TMtable = NULL;
|
||||
G(L)->sizeTM = 0;
|
||||
G(L)->ntag = 0;
|
||||
@ -91,6 +92,7 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
|
||||
L->errorJmp = NULL;
|
||||
L->callhook = NULL;
|
||||
L->linehook = NULL;
|
||||
L->opencl = NULL;
|
||||
L->allowhooks = 1;
|
||||
L->next = L->previous = L;
|
||||
so.stacksize = stacksize;
|
||||
@ -122,10 +124,10 @@ static void close_state (lua_State *L, lua_State *OL) {
|
||||
luaS_freeall(L);
|
||||
luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
|
||||
luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char);
|
||||
luaM_freelem(NULL, L->G, global_State);
|
||||
luaM_freelem(NULL, L->G);
|
||||
}
|
||||
luaM_freearray(OL, L->stack, L->stacksize, TObject);
|
||||
luaM_freelem(OL, L, lua_State);
|
||||
luaM_freelem(OL, L);
|
||||
}
|
||||
|
||||
LUA_API void lua_close (lua_State *L) {
|
||||
|
12
lstate.h
12
lstate.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstate.h,v 1.57 2001/06/06 18:00:19 roberto Exp roberto $
|
||||
** $Id: lstate.h,v 1.58 2001/06/15 19:16:41 roberto Exp $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -56,10 +56,6 @@ typedef struct stringtable {
|
||||
typedef struct global_State {
|
||||
void *Mbuffer; /* global buffer */
|
||||
size_t Mbuffsize; /* size of Mbuffer */
|
||||
Proto *rootproto; /* list of all prototypes */
|
||||
Closure *rootcl; /* list of all closures */
|
||||
Hash *roottable; /* list of all tables */
|
||||
Udata *rootudata; /* list of all userdata */
|
||||
stringtable strt; /* hash table for strings */
|
||||
Hash *type2tag; /* hash table from type names to tags */
|
||||
Hash *registry; /* (strong) registry table */
|
||||
@ -69,6 +65,11 @@ typedef struct global_State {
|
||||
int ntag; /* number of tags in TMtable */
|
||||
lu_mem GCthreshold;
|
||||
lu_mem nblocks; /* number of `bytes' currently allocated */
|
||||
Proto *rootproto; /* list of all prototypes */
|
||||
Closure *rootcl; /* list of all closed closures */
|
||||
Hash *roottable; /* list of all tables */
|
||||
Udata *rootudata; /* list of all userdata */
|
||||
UpVal *rootupval; /* list of all up values */
|
||||
} global_State;
|
||||
|
||||
|
||||
@ -88,6 +89,7 @@ struct lua_State {
|
||||
lua_Hook linehook;
|
||||
int allowhooks;
|
||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||
Closure *opencl; /* list of closures still pointing to this stack */
|
||||
lua_State *next; /* circular double linked list of states */
|
||||
lua_State *previous;
|
||||
CallInfo basefunc;
|
||||
|
6
ltests.c
6
ltests.c
@ -165,7 +165,7 @@ static int listcode (lua_State *L) {
|
||||
Proto *p;
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
1, l_s("Lua function expected"));
|
||||
p = clvalue(luaA_index(L, 1))->f.l;
|
||||
p = clvalue(luaA_index(L, 1))->u.l.p;
|
||||
lua_newtable(L);
|
||||
setnameval(L, l_s("maxstack"), p->maxstacksize);
|
||||
setnameval(L, l_s("numparams"), p->numparams);
|
||||
@ -184,7 +184,7 @@ static int listk (lua_State *L) {
|
||||
int i;
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
1, l_s("Lua function expected"));
|
||||
p = clvalue(luaA_index(L, 1))->f.l;
|
||||
p = clvalue(luaA_index(L, 1))->u.l.p;
|
||||
lua_newtable(L);
|
||||
for (i=0; i<p->sizek; i++) {
|
||||
lua_pushnumber(L, i+1);
|
||||
@ -202,7 +202,7 @@ static int listlocals (lua_State *L) {
|
||||
const l_char *name;
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
1, l_s("Lua function expected"));
|
||||
p = clvalue(luaA_index(L, 1))->f.l;
|
||||
p = clvalue(luaA_index(L, 1))->u.l.p;
|
||||
while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
|
||||
lua_pushstring(L, name);
|
||||
return i-1;
|
||||
|
79
lvm.c
79
lvm.c
@ -64,8 +64,8 @@ int luaV_tostring (lua_State *L, TObject *obj) {
|
||||
|
||||
static void traceexec (lua_State *L, lua_Hook linehook) {
|
||||
CallInfo *ci = L->ci;
|
||||
int *lineinfo = ci_func(ci)->f.l->lineinfo;
|
||||
int pc = (*ci->pc - ci_func(ci)->f.l->code) - 1;
|
||||
int *lineinfo = ci_func(ci)->u.l.p->lineinfo;
|
||||
int pc = (*ci->pc - ci_func(ci)->u.l.p->code) - 1;
|
||||
int newline;
|
||||
if (pc == 0) { /* may be first time? */
|
||||
ci->line = 1;
|
||||
@ -82,30 +82,6 @@ static void traceexec (lua_State *L, lua_Hook linehook) {
|
||||
}
|
||||
|
||||
|
||||
static Closure *luaV_closure (lua_State *L, int nelems) {
|
||||
Closure *c = luaF_newclosure(L, nelems);
|
||||
L->top -= nelems;
|
||||
while (nelems--)
|
||||
setobj(&c->upvalue[nelems], L->top+nelems);
|
||||
setclvalue(L->top, c);
|
||||
incr_top;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems) {
|
||||
Closure *cl = luaV_closure(L, nelems);
|
||||
cl->f.c = c;
|
||||
cl->isC = 1;
|
||||
}
|
||||
|
||||
|
||||
void luaV_Lclosure (lua_State *L, Proto *l, int nelems) {
|
||||
Closure *cl = luaV_closure(L, nelems);
|
||||
cl->f.l = l;
|
||||
cl->isC = 0;
|
||||
}
|
||||
|
||||
|
||||
/* maximum stack used by a call to a tag method (func + args) */
|
||||
#define MAXSTACK_TM 4
|
||||
@ -376,7 +352,7 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
|
||||
** Returns n such that the the results are between [n,top).
|
||||
*/
|
||||
StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
|
||||
const Proto *const tf = cl->f.l;
|
||||
const Proto *const tf = cl->u.l.p;
|
||||
const Instruction *pc;
|
||||
lua_Hook linehook;
|
||||
if (tf->is_vararg) /* varargs? */
|
||||
@ -406,10 +382,6 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
|
||||
setnvalue(ra, (lua_Number)GETARG_sBc(i));
|
||||
break;
|
||||
}
|
||||
case OP_LOADUPVAL: {
|
||||
setobj(ra, cl->upvalue+GETARG_Bc(i));
|
||||
break;
|
||||
}
|
||||
case OP_LOADNIL: {
|
||||
TObject *rb = RB(i);
|
||||
do {
|
||||
@ -417,6 +389,12 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
|
||||
} while (rb >= ra);
|
||||
break;
|
||||
}
|
||||
case OP_GETUPVAL: {
|
||||
int b = GETARG_B(i);
|
||||
lua_assert(luaF_isclosed(cl, b) || cl->u.l.upvals[b] < base);
|
||||
setobj(ra, cl->u.l.upvals[b]);
|
||||
break;
|
||||
}
|
||||
case OP_GETGLOBAL: {
|
||||
lua_assert(ttype(KBc(i)) == LUA_TSTRING);
|
||||
luaV_getglobal(L, tsvalue(KBc(i)), ra);
|
||||
@ -431,6 +409,12 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
|
||||
luaV_setglobal(L, tsvalue(KBc(i)), ra);
|
||||
break;
|
||||
}
|
||||
case OP_SETUPVAL: {
|
||||
int b = GETARG_B(i);
|
||||
lua_assert(luaF_isclosed(cl, b) || cl->u.l.upvals[b] < base);
|
||||
setobj(cl->u.l.upvals[b], ra);
|
||||
break;
|
||||
}
|
||||
case OP_SETTABLE: {
|
||||
luaV_settable(L, RB(i), RKC(i), ra);
|
||||
break;
|
||||
@ -646,13 +630,34 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
|
||||
luaH_setnum(L, h, bc+n, ra+n);
|
||||
break;
|
||||
}
|
||||
case OP_CLOSE: {
|
||||
luaF_close(L, ra);
|
||||
break;
|
||||
}
|
||||
case OP_CLOSURE: {
|
||||
Proto *p = tf->p[GETARG_Bc(i)];
|
||||
int nup = p->nupvalues;
|
||||
luaV_checkGC(L, ra+nup);
|
||||
L->top = ra+nup;
|
||||
luaV_Lclosure(L, p, nup);
|
||||
L->top = base + tf->maxstacksize;
|
||||
Proto *p;
|
||||
Closure *ncl;
|
||||
int nup, j;
|
||||
luaV_checkGC(L, L->top);
|
||||
p = tf->p[GETARG_Bc(i)];
|
||||
nup = p->nupvalues;
|
||||
ncl = luaF_newLclosure(L, nup);
|
||||
ncl->u.l.p = p;
|
||||
for (j=0; j<nup; j++, pc++) {
|
||||
if (GET_OPCODE(*pc) == OP_GETUPVAL) {
|
||||
int n = GETARG_B(*pc);
|
||||
if (!luaF_isclosed(cl, n))
|
||||
luaF_openentry(ncl, j);
|
||||
ncl->u.l.upvals[j] = cl->u.l.upvals[n];
|
||||
}
|
||||
else {
|
||||
lua_assert(GET_OPCODE(*pc) == OP_MOVE);
|
||||
luaF_openentry(ncl, j);
|
||||
ncl->u.l.upvals[j] = base + GETARG_B(*pc);
|
||||
}
|
||||
}
|
||||
luaF_LConlist(L, ncl);
|
||||
setclvalue(ra, ncl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
4
lvm.h
4
lvm.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.h,v 1.29 2001/02/07 18:13:49 roberto Exp roberto $
|
||||
** $Id: lvm.h,v 1.30 2001/06/05 18:17:01 roberto Exp $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -23,8 +23,6 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val);
|
||||
void luaV_getglobal (lua_State *L, TString *s, StkId res);
|
||||
void luaV_setglobal (lua_State *L, TString *s, StkId val);
|
||||
StkId luaV_execute (lua_State *L, const Closure *cl, StkId base);
|
||||
void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems);
|
||||
void luaV_Lclosure (lua_State *L, Proto *l, int nelems);
|
||||
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
|
||||
void luaV_strconc (lua_State *L, int total, StkId top);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user