diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-20 13:13:38 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-20 13:13:38 -0200 |
commit | 18afb90349fc1b698d179e29fdc014589c2e1145 (patch) | |
tree | 0ebee0d47aa91ce4bdf580baa2e5639c361c9a9a /ldo.c | |
parent | 22dd271cbba22c0765eb45296a957ecacf68755e (diff) | |
download | lua-18afb90349fc1b698d179e29fdc014589c2e1145.tar.gz lua-18afb90349fc1b698d179e29fdc014589c2e1145.tar.bz2 lua-18afb90349fc1b698d179e29fdc014589c2e1145.zip |
first version of stackless Lua
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 119 |
1 files changed, 72 insertions, 47 deletions
@@ -43,8 +43,15 @@ void luaD_init (lua_State *L, int stacksize) { | |||
43 | stacksize += EXTRA_STACK; | 43 | stacksize += EXTRA_STACK; |
44 | L->stack = luaM_newvector(L, stacksize, TObject); | 44 | L->stack = luaM_newvector(L, stacksize, TObject); |
45 | L->stacksize = stacksize; | 45 | L->stacksize = stacksize; |
46 | L->top = L->basefunc.base = L->stack + RESERVED_STACK_PREFIX; | 46 | L->top = L->stack + RESERVED_STACK_PREFIX; |
47 | restore_stack_limit(L); | 47 | restore_stack_limit(L); |
48 | luaM_reallocvector(L, L->base_ci, 0, 20, CallInfo); | ||
49 | L->ci = L->base_ci; | ||
50 | L->ci->base = L->top; | ||
51 | L->ci->savedpc = NULL; | ||
52 | L->ci->pc = NULL; | ||
53 | L->size_ci = 20; | ||
54 | L->end_ci = L->base_ci + L->size_ci; | ||
48 | } | 55 | } |
49 | 56 | ||
50 | 57 | ||
@@ -98,35 +105,81 @@ void luaD_lineHook (lua_State *L, int line, lua_Hook linehook) { | |||
98 | if (L->allowhooks) { | 105 | if (L->allowhooks) { |
99 | lua_Debug ar; | 106 | lua_Debug ar; |
100 | ar.event = "line"; | 107 | ar.event = "line"; |
101 | ar._ci = L->ci; | 108 | ar._ci = L->ci - L->base_ci; |
102 | ar.currentline = line; | 109 | ar.currentline = line; |
103 | dohook(L, &ar, linehook); | 110 | dohook(L, &ar, linehook); |
104 | } | 111 | } |
105 | } | 112 | } |
106 | 113 | ||
107 | 114 | ||
108 | static void luaD_callHook (lua_State *L, lua_Hook callhook, | 115 | void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) { |
109 | const char *event) { | ||
110 | if (L->allowhooks) { | 116 | if (L->allowhooks) { |
111 | lua_Debug ar; | 117 | lua_Debug ar; |
112 | ar.event = event; | 118 | ar.event = event; |
113 | ar._ci = L->ci; | 119 | ar._ci = L->ci - L->base_ci; |
114 | L->ci->pc = NULL; /* function is not active */ | ||
115 | dohook(L, &ar, callhook); | 120 | dohook(L, &ar, callhook); |
116 | } | 121 | } |
117 | } | 122 | } |
118 | 123 | ||
119 | 124 | ||
120 | static StkId callCclosure (lua_State *L, const struct CClosure *cl) { | 125 | #define newci(L) ((++L->ci == L->end_ci) ? growci(L) : L->ci) |
126 | |||
127 | static CallInfo *growci (lua_State *L) { | ||
128 | lua_assert(L->ci == L->end_ci); | ||
129 | luaM_reallocvector(L, L->base_ci, L->size_ci, 2*L->size_ci, CallInfo); | ||
130 | L->ci = L->base_ci + L->size_ci; | ||
131 | L->size_ci *= 2; | ||
132 | L->end_ci = L->base_ci + L->size_ci; | ||
133 | return L->ci; | ||
134 | } | ||
135 | |||
136 | |||
137 | StkId luaD_precall (lua_State *L, StkId func) { | ||
138 | CallInfo *ci; | ||
121 | int n; | 139 | int n; |
140 | if (ttype(func) != LUA_TFUNCTION) { | ||
141 | /* `func' is not a function; check the `function' tag method */ | ||
142 | const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); | ||
143 | if (ttype(tm) != LUA_TFUNCTION) | ||
144 | luaG_typeerror(L, func, "call"); | ||
145 | luaD_openstack(L, func); | ||
146 | setobj(func, tm); /* tag method is the new function to be called */ | ||
147 | } | ||
148 | lua_assert(ttype(func) == LUA_TFUNCTION); | ||
149 | ci = newci(L); | ||
150 | ci->base = func+1; | ||
151 | ci->savedpc = NULL; | ||
152 | ci->pc = NULL; | ||
153 | if (L->callhook) | ||
154 | luaD_callHook(L, L->callhook, "call"); | ||
155 | if (!clvalue(func)->c.isC) return NULL; | ||
156 | /* if is a C function, call it */ | ||
122 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 157 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
123 | lua_unlock(L); | 158 | lua_unlock(L); |
124 | #if LUA_COMPATUPVALUES | 159 | #if LUA_COMPATUPVALUES |
125 | lua_pushupvalues(L); | 160 | lua_pushupvalues(L); |
126 | #endif | 161 | #endif |
127 | n = (*cl->f)(L); /* do the actual call */ | 162 | n = (*clvalue(func)->c.f)(L); /* do the actual call */ |
128 | lua_lock(L); | 163 | lua_lock(L); |
129 | return L->top - n; /* return index of first result */ | 164 | return L->top - n; |
165 | } | ||
166 | |||
167 | |||
168 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | ||
169 | StkId res; | ||
170 | if (L->callhook) | ||
171 | luaD_callHook(L, L->callhook, "return"); | ||
172 | res = L->ci->base - 1; /* `func' = final position of 1st result */ | ||
173 | L->ci--; | ||
174 | /* move results to correct place */ | ||
175 | while (wanted != 0 && firstResult < L->top) { | ||
176 | setobj(res++, firstResult++); | ||
177 | wanted--; | ||
178 | } | ||
179 | while (wanted-- > 0) | ||
180 | setnilvalue(res++); | ||
181 | L->top = res; | ||
182 | luaC_checkGC(L); | ||
130 | } | 183 | } |
131 | 184 | ||
132 | 185 | ||
@@ -136,36 +189,11 @@ static StkId callCclosure (lua_State *L, const struct CClosure *cl) { | |||
136 | ** When returns, all the results are on the stack, starting at the original | 189 | ** When returns, all the results are on the stack, starting at the original |
137 | ** function position. | 190 | ** function position. |
138 | */ | 191 | */ |
139 | void luaD_call (lua_State *L, StkId func) { | 192 | void luaD_call (lua_State *L, StkId func, int nResults) { |
140 | lua_Hook callhook; | 193 | StkId firstResult = luaD_precall(L, func); |
141 | StkId firstResult; | 194 | if (firstResult == NULL) /* is a Lua function? */ |
142 | CallInfo ci; | 195 | firstResult = luaV_execute(L, &clvalue(func)->l, func+1); /* call it */ |
143 | if (ttype(func) != LUA_TFUNCTION) { | 196 | luaD_poscall(L, nResults, firstResult); |
144 | /* `func' is not a function; check the `function' tag method */ | ||
145 | const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); | ||
146 | if (ttype(tm) != LUA_TFUNCTION) | ||
147 | luaG_typeerror(L, func, "call"); | ||
148 | luaD_openstack(L, func); | ||
149 | setobj(func, tm); /* tag method is the new function to be called */ | ||
150 | } | ||
151 | lua_assert(ttype(func) == LUA_TFUNCTION); | ||
152 | ci.prev = L->ci; /* chain new callinfo */ | ||
153 | L->ci = &ci; | ||
154 | ci.base = func+1; | ||
155 | callhook = L->callhook; | ||
156 | if (callhook) | ||
157 | luaD_callHook(L, callhook, "call"); | ||
158 | firstResult = (clvalue(func)->c.isC ? | ||
159 | callCclosure(L, &clvalue(func)->c) : | ||
160 | luaV_execute(L, &clvalue(func)->l, func+1)); | ||
161 | if (callhook) /* same hook that was active at entry */ | ||
162 | luaD_callHook(L, callhook, "return"); | ||
163 | L->ci = ci.prev; /* unchain callinfo */ | ||
164 | /* move results to `func' (to erase parameters and function) */ | ||
165 | while (firstResult < L->top) | ||
166 | setobj(func++, firstResult++); | ||
167 | L->top = func; | ||
168 | luaC_checkGC(L); | ||
169 | } | 197 | } |
170 | 198 | ||
171 | 199 | ||
@@ -179,9 +207,7 @@ struct CallS { /* data to `f_call' */ | |||
179 | 207 | ||
180 | static void f_call (lua_State *L, void *ud) { | 208 | static void f_call (lua_State *L, void *ud) { |
181 | struct CallS *c = cast(struct CallS *, ud); | 209 | struct CallS *c = cast(struct CallS *, ud); |
182 | luaD_call(L, c->func); | 210 | luaD_call(L, c->func, c->nresults); |
183 | if (c->nresults != LUA_MULTRET) | ||
184 | luaD_adjusttop(L, c->func + c->nresults); | ||
185 | } | 211 | } |
186 | 212 | ||
187 | 213 | ||
@@ -291,7 +317,7 @@ struct lua_longjmp { | |||
291 | jmp_buf b; | 317 | jmp_buf b; |
292 | struct lua_longjmp *previous; | 318 | struct lua_longjmp *previous; |
293 | volatile int status; /* error code */ | 319 | volatile int status; /* error code */ |
294 | CallInfo *ci; /* call info of active function that set protection */ | 320 | int ci; /* index of call info of active function that set protection */ |
295 | StkId top; /* top stack when protection was set */ | 321 | StkId top; /* top stack when protection was set */ |
296 | int allowhooks; /* `allowhook' state when protection was set */ | 322 | int allowhooks; /* `allowhook' state when protection was set */ |
297 | }; | 323 | }; |
@@ -307,8 +333,7 @@ static void message (lua_State *L, const char *s) { | |||
307 | incr_top; | 333 | incr_top; |
308 | setsvalue(top+1, luaS_new(L, s)); | 334 | setsvalue(top+1, luaS_new(L, s)); |
309 | incr_top; | 335 | incr_top; |
310 | luaD_call(L, top); | 336 | luaD_call(L, top, 0); |
311 | L->top = top; | ||
312 | } | 337 | } |
313 | } | 338 | } |
314 | 339 | ||
@@ -337,7 +362,7 @@ void luaD_breakrun (lua_State *L, int errcode) { | |||
337 | 362 | ||
338 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | 363 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { |
339 | struct lua_longjmp lj; | 364 | struct lua_longjmp lj; |
340 | lj.ci = L->ci; | 365 | lj.ci = L->ci - L->base_ci; |
341 | lj.top = L->top; | 366 | lj.top = L->top; |
342 | lj.allowhooks = L->allowhooks; | 367 | lj.allowhooks = L->allowhooks; |
343 | lj.status = 0; | 368 | lj.status = 0; |
@@ -346,7 +371,7 @@ int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | |||
346 | if (setjmp(lj.b) == 0) | 371 | if (setjmp(lj.b) == 0) |
347 | (*f)(L, ud); | 372 | (*f)(L, ud); |
348 | else { /* an error occurred: restore the state */ | 373 | else { /* an error occurred: restore the state */ |
349 | L->ci = lj.ci; | 374 | L->ci = L->base_ci + lj.ci; |
350 | L->top = lj.top; | 375 | L->top = lj.top; |
351 | L->allowhooks = lj.allowhooks; | 376 | L->allowhooks = lj.allowhooks; |
352 | restore_stack_limit(L); | 377 | restore_stack_limit(L); |