zombiezen.com/go/lua@v0.0.0-20231013005828-290725fb9140/internal/lua54/lfunc.c (about)

     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  
    27  CClosure *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  
    35  LClosure *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  */
    48  void 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  **/
    65  static 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  */
    87  UpVal *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  */
   107  static 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  */
   125  static 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  */
   143  static 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  */
   168  void 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  
   182  void 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  */
   193  void 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  */
   213  static 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  */
   227  StkId 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  
   240  Proto *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  
   267  void 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  */
   283  const 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