1*8e3e3a7aSWarner Losh /* 2*8e3e3a7aSWarner Losh ** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ 3*8e3e3a7aSWarner Losh ** Auxiliary functions to manipulate prototypes and closures 4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 5*8e3e3a7aSWarner Losh */ 6*8e3e3a7aSWarner Losh 7*8e3e3a7aSWarner Losh #define lfunc_c 8*8e3e3a7aSWarner Losh #define LUA_CORE 9*8e3e3a7aSWarner Losh 10*8e3e3a7aSWarner Losh #include "lprefix.h" 11*8e3e3a7aSWarner Losh 12*8e3e3a7aSWarner Losh 13*8e3e3a7aSWarner Losh #include <stddef.h> 14*8e3e3a7aSWarner Losh 15*8e3e3a7aSWarner Losh #include "lua.h" 16*8e3e3a7aSWarner Losh 17*8e3e3a7aSWarner Losh #include "lfunc.h" 18*8e3e3a7aSWarner Losh #include "lgc.h" 19*8e3e3a7aSWarner Losh #include "lmem.h" 20*8e3e3a7aSWarner Losh #include "lobject.h" 21*8e3e3a7aSWarner Losh #include "lstate.h" 22*8e3e3a7aSWarner Losh 23*8e3e3a7aSWarner Losh 24*8e3e3a7aSWarner Losh 25*8e3e3a7aSWarner Losh CClosure *luaF_newCclosure (lua_State *L, int n) { 26*8e3e3a7aSWarner Losh GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); 27*8e3e3a7aSWarner Losh CClosure *c = gco2ccl(o); 28*8e3e3a7aSWarner Losh c->nupvalues = cast_byte(n); 29*8e3e3a7aSWarner Losh return c; 30*8e3e3a7aSWarner Losh } 31*8e3e3a7aSWarner Losh 32*8e3e3a7aSWarner Losh 33*8e3e3a7aSWarner Losh LClosure *luaF_newLclosure (lua_State *L, int n) { 34*8e3e3a7aSWarner Losh GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); 35*8e3e3a7aSWarner Losh LClosure *c = gco2lcl(o); 36*8e3e3a7aSWarner Losh c->p = NULL; 37*8e3e3a7aSWarner Losh c->nupvalues = cast_byte(n); 38*8e3e3a7aSWarner Losh while (n--) c->upvals[n] = NULL; 39*8e3e3a7aSWarner Losh return c; 40*8e3e3a7aSWarner Losh } 41*8e3e3a7aSWarner Losh 42*8e3e3a7aSWarner Losh /* 43*8e3e3a7aSWarner Losh ** fill a closure with new closed upvalues 44*8e3e3a7aSWarner Losh */ 45*8e3e3a7aSWarner Losh void luaF_initupvals (lua_State *L, LClosure *cl) { 46*8e3e3a7aSWarner Losh int i; 47*8e3e3a7aSWarner Losh for (i = 0; i < cl->nupvalues; i++) { 48*8e3e3a7aSWarner Losh UpVal *uv = luaM_new(L, UpVal); 49*8e3e3a7aSWarner Losh uv->refcount = 1; 50*8e3e3a7aSWarner Losh uv->v = &uv->u.value; /* make it closed */ 51*8e3e3a7aSWarner Losh setnilvalue(uv->v); 52*8e3e3a7aSWarner Losh cl->upvals[i] = uv; 53*8e3e3a7aSWarner Losh } 54*8e3e3a7aSWarner Losh } 55*8e3e3a7aSWarner Losh 56*8e3e3a7aSWarner Losh 57*8e3e3a7aSWarner Losh UpVal *luaF_findupval (lua_State *L, StkId level) { 58*8e3e3a7aSWarner Losh UpVal **pp = &L->openupval; 59*8e3e3a7aSWarner Losh UpVal *p; 60*8e3e3a7aSWarner Losh UpVal *uv; 61*8e3e3a7aSWarner Losh lua_assert(isintwups(L) || L->openupval == NULL); 62*8e3e3a7aSWarner Losh while (*pp != NULL && (p = *pp)->v >= level) { 63*8e3e3a7aSWarner Losh lua_assert(upisopen(p)); 64*8e3e3a7aSWarner Losh if (p->v == level) /* found a corresponding upvalue? */ 65*8e3e3a7aSWarner Losh return p; /* return it */ 66*8e3e3a7aSWarner Losh pp = &p->u.open.next; 67*8e3e3a7aSWarner Losh } 68*8e3e3a7aSWarner Losh /* not found: create a new upvalue */ 69*8e3e3a7aSWarner Losh uv = luaM_new(L, UpVal); 70*8e3e3a7aSWarner Losh uv->refcount = 0; 71*8e3e3a7aSWarner Losh uv->u.open.next = *pp; /* link it to list of open upvalues */ 72*8e3e3a7aSWarner Losh uv->u.open.touched = 1; 73*8e3e3a7aSWarner Losh *pp = uv; 74*8e3e3a7aSWarner Losh uv->v = level; /* current value lives in the stack */ 75*8e3e3a7aSWarner Losh if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 76*8e3e3a7aSWarner Losh L->twups = G(L)->twups; /* link it to the list */ 77*8e3e3a7aSWarner Losh G(L)->twups = L; 78*8e3e3a7aSWarner Losh } 79*8e3e3a7aSWarner Losh return uv; 80*8e3e3a7aSWarner Losh } 81*8e3e3a7aSWarner Losh 82*8e3e3a7aSWarner Losh 83*8e3e3a7aSWarner Losh void luaF_close (lua_State *L, StkId level) { 84*8e3e3a7aSWarner Losh UpVal *uv; 85*8e3e3a7aSWarner Losh while (L->openupval != NULL && (uv = L->openupval)->v >= level) { 86*8e3e3a7aSWarner Losh lua_assert(upisopen(uv)); 87*8e3e3a7aSWarner Losh L->openupval = uv->u.open.next; /* remove from 'open' list */ 88*8e3e3a7aSWarner Losh if (uv->refcount == 0) /* no references? */ 89*8e3e3a7aSWarner Losh luaM_free(L, uv); /* free upvalue */ 90*8e3e3a7aSWarner Losh else { 91*8e3e3a7aSWarner Losh setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ 92*8e3e3a7aSWarner Losh uv->v = &uv->u.value; /* now current value lives here */ 93*8e3e3a7aSWarner Losh luaC_upvalbarrier(L, uv); 94*8e3e3a7aSWarner Losh } 95*8e3e3a7aSWarner Losh } 96*8e3e3a7aSWarner Losh } 97*8e3e3a7aSWarner Losh 98*8e3e3a7aSWarner Losh 99*8e3e3a7aSWarner Losh Proto *luaF_newproto (lua_State *L) { 100*8e3e3a7aSWarner Losh GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); 101*8e3e3a7aSWarner Losh Proto *f = gco2p(o); 102*8e3e3a7aSWarner Losh f->k = NULL; 103*8e3e3a7aSWarner Losh f->sizek = 0; 104*8e3e3a7aSWarner Losh f->p = NULL; 105*8e3e3a7aSWarner Losh f->sizep = 0; 106*8e3e3a7aSWarner Losh f->code = NULL; 107*8e3e3a7aSWarner Losh f->cache = NULL; 108*8e3e3a7aSWarner Losh f->sizecode = 0; 109*8e3e3a7aSWarner Losh f->lineinfo = NULL; 110*8e3e3a7aSWarner Losh f->sizelineinfo = 0; 111*8e3e3a7aSWarner Losh f->upvalues = NULL; 112*8e3e3a7aSWarner Losh f->sizeupvalues = 0; 113*8e3e3a7aSWarner Losh f->numparams = 0; 114*8e3e3a7aSWarner Losh f->is_vararg = 0; 115*8e3e3a7aSWarner Losh f->maxstacksize = 0; 116*8e3e3a7aSWarner Losh f->locvars = NULL; 117*8e3e3a7aSWarner Losh f->sizelocvars = 0; 118*8e3e3a7aSWarner Losh f->linedefined = 0; 119*8e3e3a7aSWarner Losh f->lastlinedefined = 0; 120*8e3e3a7aSWarner Losh f->source = NULL; 121*8e3e3a7aSWarner Losh return f; 122*8e3e3a7aSWarner Losh } 123*8e3e3a7aSWarner Losh 124*8e3e3a7aSWarner Losh 125*8e3e3a7aSWarner Losh void luaF_freeproto (lua_State *L, Proto *f) { 126*8e3e3a7aSWarner Losh luaM_freearray(L, f->code, f->sizecode); 127*8e3e3a7aSWarner Losh luaM_freearray(L, f->p, f->sizep); 128*8e3e3a7aSWarner Losh luaM_freearray(L, f->k, f->sizek); 129*8e3e3a7aSWarner Losh luaM_freearray(L, f->lineinfo, f->sizelineinfo); 130*8e3e3a7aSWarner Losh luaM_freearray(L, f->locvars, f->sizelocvars); 131*8e3e3a7aSWarner Losh luaM_freearray(L, f->upvalues, f->sizeupvalues); 132*8e3e3a7aSWarner Losh luaM_free(L, f); 133*8e3e3a7aSWarner Losh } 134*8e3e3a7aSWarner Losh 135*8e3e3a7aSWarner Losh 136*8e3e3a7aSWarner Losh /* 137*8e3e3a7aSWarner Losh ** Look for n-th local variable at line 'line' in function 'func'. 138*8e3e3a7aSWarner Losh ** Returns NULL if not found. 139*8e3e3a7aSWarner Losh */ 140*8e3e3a7aSWarner Losh const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { 141*8e3e3a7aSWarner Losh int i; 142*8e3e3a7aSWarner Losh for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { 143*8e3e3a7aSWarner Losh if (pc < f->locvars[i].endpc) { /* is variable active? */ 144*8e3e3a7aSWarner Losh local_number--; 145*8e3e3a7aSWarner Losh if (local_number == 0) 146*8e3e3a7aSWarner Losh return getstr(f->locvars[i].varname); 147*8e3e3a7aSWarner Losh } 148*8e3e3a7aSWarner Losh } 149*8e3e3a7aSWarner Losh return NULL; /* not found */ 150*8e3e3a7aSWarner Losh } 151*8e3e3a7aSWarner Losh 152