Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5205 | clevermous | 1 | /* |
2 | ** $Id: lfunc.c,v 2.27 2010/06/30 14:11:17 roberto Exp $ |
||
3 | ** Auxiliary functions to manipulate prototypes and closures |
||
4 | ** See Copyright Notice in lua.h |
||
5 | */ |
||
6 | |||
7 | |||
8 | #include |
||
9 | |||
10 | #define lfunc_c |
||
11 | #define LUA_CORE |
||
12 | |||
13 | #include "lua.h" |
||
14 | |||
15 | #include "lfunc.h" |
||
16 | #include "lgc.h" |
||
17 | #include "lmem.h" |
||
18 | #include "lobject.h" |
||
19 | #include "lstate.h" |
||
20 | |||
21 | |||
22 | |||
23 | Closure *luaF_newCclosure (lua_State *L, int n) { |
||
24 | Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeCclosure(n), NULL, 0)->cl; |
||
25 | c->c.isC = 1; |
||
26 | c->c.nupvalues = cast_byte(n); |
||
27 | return c; |
||
28 | } |
||
29 | |||
30 | |||
31 | Closure *luaF_newLclosure (lua_State *L, Proto *p) { |
||
32 | int n = p->sizeupvalues; |
||
33 | Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeLclosure(n), NULL, 0)->cl; |
||
34 | c->l.isC = 0; |
||
35 | c->l.p = p; |
||
36 | c->l.nupvalues = cast_byte(n); |
||
37 | while (n--) c->l.upvals[n] = NULL; |
||
38 | return c; |
||
39 | } |
||
40 | |||
41 | |||
42 | UpVal *luaF_newupval (lua_State *L) { |
||
43 | UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; |
||
44 | uv->v = &uv->u.value; |
||
45 | setnilvalue(uv->v); |
||
46 | return uv; |
||
47 | } |
||
48 | |||
49 | |||
50 | UpVal *luaF_findupval (lua_State *L, StkId level) { |
||
51 | global_State *g = G(L); |
||
52 | GCObject **pp = &L->openupval; |
||
53 | UpVal *p; |
||
54 | UpVal *uv; |
||
55 | while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { |
||
56 | GCObject *o = obj2gco(p); |
||
57 | lua_assert(p->v != &p->u.value); |
||
58 | if (p->v == level) { /* found a corresponding upvalue? */ |
||
59 | if (isdead(g, o)) /* is it dead? */ |
||
60 | changewhite(o); /* resurrect it */ |
||
61 | return p; |
||
62 | } |
||
63 | resetoldbit(o); /* may create a newer upval after this one */ |
||
64 | pp = &p->next; |
||
65 | } |
||
66 | /* not found: create a new one */ |
||
67 | uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; |
||
68 | uv->v = level; /* current value lives in the stack */ |
||
69 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ |
||
70 | uv->u.l.next = g->uvhead.u.l.next; |
||
71 | uv->u.l.next->u.l.prev = uv; |
||
72 | g->uvhead.u.l.next = uv; |
||
73 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); |
||
74 | return uv; |
||
75 | } |
||
76 | |||
77 | |||
78 | static void unlinkupval (UpVal *uv) { |
||
79 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); |
||
80 | uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ |
||
81 | uv->u.l.prev->u.l.next = uv->u.l.next; |
||
82 | } |
||
83 | |||
84 | |||
85 | void luaF_freeupval (lua_State *L, UpVal *uv) { |
||
86 | if (uv->v != &uv->u.value) /* is it open? */ |
||
87 | unlinkupval(uv); /* remove from open list */ |
||
88 | luaM_free(L, uv); /* free upvalue */ |
||
89 | } |
||
90 | |||
91 | |||
92 | void luaF_close (lua_State *L, StkId level) { |
||
93 | UpVal *uv; |
||
94 | global_State *g = G(L); |
||
95 | while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { |
||
96 | GCObject *o = obj2gco(uv); |
||
97 | lua_assert(!isblack(o) && uv->v != &uv->u.value); |
||
98 | L->openupval = uv->next; /* remove from `open' list */ |
||
99 | if (isdead(g, o)) |
||
100 | luaF_freeupval(L, uv); /* free upvalue */ |
||
101 | else { |
||
102 | unlinkupval(uv); /* remove upvalue from 'uvhead' list */ |
||
103 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ |
||
104 | uv->v = &uv->u.value; /* now current value lives here */ |
||
105 | gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ |
||
106 | g->allgc = o; |
||
107 | luaC_checkupvalcolor(g, uv); |
||
108 | } |
||
109 | } |
||
110 | } |
||
111 | |||
112 | |||
113 | Proto *luaF_newproto (lua_State *L) { |
||
114 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; |
||
115 | f->k = NULL; |
||
116 | f->sizek = 0; |
||
117 | f->p = NULL; |
||
118 | f->sizep = 0; |
||
119 | f->code = NULL; |
||
120 | f->cache = NULL; |
||
121 | f->sizecode = 0; |
||
122 | f->lineinfo = NULL; |
||
123 | f->sizelineinfo = 0; |
||
124 | f->upvalues = NULL; |
||
125 | f->sizeupvalues = 0; |
||
126 | f->numparams = 0; |
||
127 | f->is_vararg = 0; |
||
128 | f->maxstacksize = 0; |
||
129 | f->locvars = NULL; |
||
130 | f->sizelocvars = 0; |
||
131 | f->linedefined = 0; |
||
132 | f->lastlinedefined = 0; |
||
133 | f->source = NULL; |
||
134 | return f; |
||
135 | } |
||
136 | |||
137 | |||
138 | void luaF_freeproto (lua_State *L, Proto *f) { |
||
139 | luaM_freearray(L, f->code, f->sizecode); |
||
140 | luaM_freearray(L, f->p, f->sizep); |
||
141 | luaM_freearray(L, f->k, f->sizek); |
||
142 | luaM_freearray(L, f->lineinfo, f->sizelineinfo); |
||
143 | luaM_freearray(L, f->locvars, f->sizelocvars); |
||
144 | luaM_freearray(L, f->upvalues, f->sizeupvalues); |
||
145 | luaM_free(L, f); |
||
146 | } |
||
147 | |||
148 | |||
149 | void luaF_freeclosure (lua_State *L, Closure *c) { |
||
150 | int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : |
||
151 | sizeLclosure(c->l.nupvalues); |
||
152 | luaM_freemem(L, c, size); |
||
153 | } |
||
154 | |||
155 | |||
156 | /* |
||
157 | ** Look for n-th local variable at line `line' in function `func'. |
||
158 | ** Returns NULL if not found. |
||
159 | */ |
||
160 | const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { |
||
161 | int i; |
||
162 | for (i = 0; i |
||
163 | if (pc < f->locvars[i].endpc) { /* is variable active? */ |
||
164 | local_number--; |
||
165 | if (local_number == 0) |
||
166 | return getstr(f->locvars[i].varname); |
||
167 | } |
||
168 | } |
||
169 | return NULL; /* not found */ |
||
170 | }>=> |
||
171 |