1/*
  2** $Id: lfunc.c $
  3** Auxiliary functions to manipulate prototypes and closures
  4** See Copyright Notice in lua.h
  5*/
  6
  7#define lfunc_c
  8#define LUA_CORE
  9
 10#include "lprefix.h"
 11
 12
 13#include <stddef.h>
 14
 15#include "lua.h"
 16
 17#include "ldebug.h"
 18#include "ldo.h"
 19#include "lfunc.h"
 20#include "lgc.h"
 21#include "lmem.h"
 22#include "lobject.h"
 23#include "lstate.h"
 24
 25
 26
 27CClosure *luaF_newCclosure (lua_State *L, int nupvals) {
 28  GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals));
 29  CClosure *c = gco2ccl(o);
 30  c->nupvalues = cast_byte(nupvals);
 31  return c;
 32}
 33
 34
 35LClosure *luaF_newLclosure (lua_State *L, int nupvals) {
 36  GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals));
 37  LClosure *c = gco2lcl(o);
 38  c->p = NULL;
 39  c->nupvalues = cast_byte(nupvals);
 40  while (nupvals--) c->upvals[nupvals] = NULL;
 41  return c;
 42}
 43
 44
 45/*
 46** fill a closure with new closed upvalues
 47*/
 48void luaF_initupvals (lua_State *L, LClosure *cl) {
 49  int i;
 50  for (i = 0; i < cl->nupvalues; i++) {
 51    GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
 52    UpVal *uv = gco2upv(o);
 53    uv->v.p = &uv->u.value;  /* make it closed */
 54    setnilvalue(uv->v.p);
 55    cl->upvals[i] = uv;
 56    luaC_objbarrier(L, cl, uv);
 57  }
 58}
 59
 60
 61/*
 62** Create a new upvalue at the given level, and link it to the list of
 63** open upvalues of 'L' after entry 'prev'.
 64**/
 65static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) {
 66  GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
 67  UpVal *uv = gco2upv(o);
 68  UpVal *next = *prev;
 69  uv->v.p = s2v(level);  /* current value lives in the stack */
 70  uv->u.open.next = next;  /* link it to list of open upvalues */
 71  uv->u.open.previous = prev;
 72  if (next)
 73    next->u.open.previous = &uv->u.open.next;
 74  *prev = uv;
 75  if (!isintwups(L)) {  /* thread not in list of threads with upvalues? */
 76    L->twups = G(L)->twups;  /* link it to the list */
 77    G(L)->twups = L;
 78  }
 79  return uv;
 80}
 81
 82
 83/*
 84** Find and reuse, or create if it does not exist, an upvalue
 85** at the given level.
 86*/
 87UpVal *luaF_findupval (lua_State *L, StkId level) {
 88  UpVal **pp = &L->openupval;
 89  UpVal *p;
 90  lua_assert(isintwups(L) || L->openupval == NULL);
 91  while ((p = *pp) != NULL && uplevel(p) >= level) {  /* search for it */
 92    lua_assert(!isdead(G(L), p));
 93    if (uplevel(p) == level)  /* corresponding upvalue? */
 94      return p;  /* return it */
 95    pp = &p->u.open.next;
 96  }
 97  /* not found: create a new upvalue after 'pp' */
 98  return newupval(L, level, pp);
 99}
100
101
102/*
103** Call closing method for object 'obj' with error message 'err'. The
104** boolean 'yy' controls whether the call is yieldable.
105** (This function assumes EXTRA_STACK.)
106*/
107static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) {
108  StkId top = L->top.p;
109  const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
110  setobj2s(L, top, tm);  /* will call metamethod... */
111  setobj2s(L, top + 1, obj);  /* with 'self' as the 1st argument */
112  setobj2s(L, top + 2, err);  /* and error msg. as 2nd argument */
113  L->top.p = top + 3;  /* add function and arguments */
114  if (yy)
115    luaD_call(L, top, 0);
116  else
117    luaD_callnoyield(L, top, 0);
118}
119
120
121/*
122** Check whether object at given level has a close metamethod and raise
123** an error if not.
124*/
125static void checkclosemth (lua_State *L, StkId level) {
126  const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE);
127  if (ttisnil(tm)) {  /* no metamethod? */
128    int idx = cast_int(level - L->ci->func.p);  /* variable index */
129    const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
130    if (vname == NULL) vname = "?";
131    luaG_runerror(L, "variable '%s' got a non-closable value", vname);
132  }
133}
134
135
136/*
137** Prepare and call a closing method.
138** If status is CLOSEKTOP, the call to the closing method will be pushed
139** at the top of the stack. Otherwise, values can be pushed right after
140** the 'level' of the upvalue being closed, as everything after that
141** won't be used again.
142*/
143static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) {
144  TValue *uv = s2v(level);  /* value being closed */
145  TValue *errobj;
146  if (status == CLOSEKTOP)
147    errobj = &G(L)->nilvalue;  /* error object is nil */
148  else {  /* 'luaD_seterrorobj' will set top to level + 2 */
149    errobj = s2v(level + 1);  /* error object goes after 'uv' */
150    luaD_seterrorobj(L, status, level + 1);  /* set error object */
151  }
152  callclosemethod(L, uv, errobj, yy);
153}
154
155
156/*
157** Maximum value for deltas in 'tbclist', dependent on the type
158** of delta. (This macro assumes that an 'L' is in scope where it
159** is used.)
160*/
161#define MAXDELTA  \
162	((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1)
163
164
165/*
166** Insert a variable in the list of to-be-closed variables.
167*/
168void luaF_newtbcupval (lua_State *L, StkId level) {
169  lua_assert(level > L->tbclist.p);
170  if (l_isfalse(s2v(level)))
171    return;  /* false doesn't need to be closed */
172  checkclosemth(L, level);  /* value must have a close method */
173  while (cast_uint(level - L->tbclist.p) > MAXDELTA) {
174    L->tbclist.p += MAXDELTA;  /* create a dummy node at maximum delta */
175    L->tbclist.p->tbclist.delta = 0;
176  }
177  level->tbclist.delta = cast(unsigned short, level - L->tbclist.p);
178  L->tbclist.p = level;
179}
180
181
182void luaF_unlinkupval (UpVal *uv) {
183  lua_assert(upisopen(uv));
184  *uv->u.open.previous = uv->u.open.next;
185  if (uv->u.open.next)
186    uv->u.open.next->u.open.previous = uv->u.open.previous;
187}
188
189
190/*
191** Close all upvalues up to the given stack level.
192*/
193void luaF_closeupval (lua_State *L, StkId level) {
194  UpVal *uv;
195  StkId upl;  /* stack index pointed by 'uv' */
196  while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) {
197    TValue *slot = &uv->u.value;  /* new position for value */
198    lua_assert(uplevel(uv) < L->top.p);
199    luaF_unlinkupval(uv);  /* remove upvalue from 'openupval' list */
200    setobj(L, slot, uv->v.p);  /* move value to upvalue slot */
201    uv->v.p = slot;  /* now current value lives here */
202    if (!iswhite(uv)) {  /* neither white nor dead? */
203      nw2black(uv);  /* closed upvalues cannot be gray */
204      luaC_barrier(L, uv, slot);
205    }
206  }
207}
208
209
210/*
211** Remove first element from the tbclist plus its dummy nodes.
212*/
213static void poptbclist (lua_State *L) {
214  StkId tbc = L->tbclist.p;
215  lua_assert(tbc->tbclist.delta > 0);  /* first element cannot be dummy */
216  tbc -= tbc->tbclist.delta;
217  while (tbc > L->stack.p && tbc->tbclist.delta == 0)
218    tbc -= MAXDELTA;  /* remove dummy nodes */
219  L->tbclist.p = tbc;
220}
221
222
223/*
224** Close all upvalues and to-be-closed variables up to the given stack
225** level. Return restored 'level'.
226*/
227StkId luaF_close (lua_State *L, StkId level, int status, int yy) {
228  ptrdiff_t levelrel = savestack(L, level);
229  luaF_closeupval(L, level);  /* first, close the upvalues */
230  while (L->tbclist.p >= level) {  /* traverse tbc's down to that level */
231    StkId tbc = L->tbclist.p;  /* get variable index */
232    poptbclist(L);  /* remove it from list */
233    prepcallclosemth(L, tbc, status, yy);  /* close variable */
234    level = restorestack(L, levelrel);
235  }
236  return level;
237}
238
239
240Proto *luaF_newproto (lua_State *L) {
241  GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto));
242  Proto *f = gco2p(o);
243  f->k = NULL;
244  f->sizek = 0;
245  f->p = NULL;
246  f->sizep = 0;
247  f->code = NULL;
248  f->sizecode = 0;
249  f->lineinfo = NULL;
250  f->sizelineinfo = 0;
251  f->abslineinfo = NULL;
252  f->sizeabslineinfo = 0;
253  f->upvalues = NULL;
254  f->sizeupvalues = 0;
255  f->numparams = 0;
256  f->is_vararg = 0;
257  f->maxstacksize = 0;
258  f->locvars = NULL;
259  f->sizelocvars = 0;
260  f->linedefined = 0;
261  f->lastlinedefined = 0;
262  f->source = NULL;
263  return f;
264}
265
266
267void luaF_freeproto (lua_State *L, Proto *f) {
268  luaM_freearray(L, f->code, f->sizecode);
269  luaM_freearray(L, f->p, f->sizep);
270  luaM_freearray(L, f->k, f->sizek);
271  luaM_freearray(L, f->lineinfo, f->sizelineinfo);
272  luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo);
273  luaM_freearray(L, f->locvars, f->sizelocvars);
274  luaM_freearray(L, f->upvalues, f->sizeupvalues);
275  luaM_free(L, f);
276}
277
278
279/*
280** Look for n-th local variable at line 'line' in function 'func'.
281** Returns NULL if not found.
282*/
283const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
284  int i;
285  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
286    if (pc < f->locvars[i].endpc) {  /* is variable active? */
287      local_number--;
288      if (local_number == 0)
289        return getstr(f->locvars[i].varname);
290    }
291  }
292  return NULL;  /* not found */
293}
294