diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib_base.c | 560 |
1 files changed, 560 insertions, 0 deletions
diff --git a/src/lib_base.c b/src/lib_base.c new file mode 100644 index 00000000..6b9e8eef --- /dev/null +++ b/src/lib_base.c | |||
@@ -0,0 +1,560 @@ | |||
1 | /* | ||
2 | ** Base and coroutine library. | ||
3 | ** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h | ||
4 | ** | ||
5 | ** Major portions taken verbatim or adapted from the Lua interpreter. | ||
6 | ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h | ||
7 | */ | ||
8 | |||
9 | #include <stdio.h> | ||
10 | |||
11 | #define lib_base_c | ||
12 | #define LUA_LIB | ||
13 | |||
14 | #include "lua.h" | ||
15 | #include "lauxlib.h" | ||
16 | #include "lualib.h" | ||
17 | |||
18 | #include "lj_obj.h" | ||
19 | #include "lj_gc.h" | ||
20 | #include "lj_err.h" | ||
21 | #include "lj_str.h" | ||
22 | #include "lj_tab.h" | ||
23 | #include "lj_meta.h" | ||
24 | #include "lj_state.h" | ||
25 | #include "lj_ff.h" | ||
26 | #include "lj_ctype.h" | ||
27 | #include "lj_lib.h" | ||
28 | |||
29 | /* -- Base library: checks ------------------------------------------------ */ | ||
30 | |||
31 | #define LJLIB_MODULE_base | ||
32 | |||
33 | LJLIB_ASM(assert) LJLIB_REC(.) | ||
34 | { | ||
35 | GCstr *s; | ||
36 | lj_lib_checkany(L, 1); | ||
37 | s = lj_lib_optstr(L, 2); | ||
38 | if (s) | ||
39 | lj_err_callermsg(L, strdata(s)); | ||
40 | else | ||
41 | lj_err_caller(L, LJ_ERR_ASSERT); | ||
42 | return FFH_UNREACHABLE; | ||
43 | } | ||
44 | |||
45 | /* ORDER LJ_T */ | ||
46 | LJLIB_PUSH("nil") | ||
47 | LJLIB_PUSH("boolean") | ||
48 | LJLIB_PUSH(top-1) /* boolean */ | ||
49 | LJLIB_PUSH("userdata") | ||
50 | LJLIB_PUSH("string") | ||
51 | LJLIB_PUSH("upval") | ||
52 | LJLIB_PUSH("thread") | ||
53 | LJLIB_PUSH("proto") | ||
54 | LJLIB_PUSH("function") | ||
55 | LJLIB_PUSH("deadkey") | ||
56 | LJLIB_PUSH("table") | ||
57 | LJLIB_PUSH(top-8) /* userdata */ | ||
58 | LJLIB_PUSH("number") | ||
59 | LJLIB_ASM_(type) LJLIB_REC(.) | ||
60 | /* Recycle the lj_lib_checkany(L, 1) from assert. */ | ||
61 | |||
62 | /* -- Base library: getters and setters ----------------------------------- */ | ||
63 | |||
64 | LJLIB_ASM_(getmetatable) LJLIB_REC(.) | ||
65 | /* Recycle the lj_lib_checkany(L, 1) from assert. */ | ||
66 | |||
67 | LJLIB_ASM(setmetatable) LJLIB_REC(.) | ||
68 | { | ||
69 | GCtab *t = lj_lib_checktab(L, 1); | ||
70 | GCtab *mt = lj_lib_checktabornil(L, 2); | ||
71 | if (!tvisnil(lj_meta_lookup(L, L->base, MM_metatable))) | ||
72 | lj_err_caller(L, LJ_ERR_PROTMT); | ||
73 | setgcref(t->metatable, obj2gco(mt)); | ||
74 | if (mt) { lj_gc_objbarriert(L, t, mt); } | ||
75 | settabV(L, L->base-1, t); | ||
76 | return FFH_RES(1); | ||
77 | } | ||
78 | |||
79 | LJLIB_CF(getfenv) | ||
80 | { | ||
81 | GCfunc *fn; | ||
82 | cTValue *o = L->base; | ||
83 | if (!(o < L->top && tvisfunc(o))) { | ||
84 | int level = lj_lib_optint(L, 1, 1); | ||
85 | o = lj_err_getframe(L, level, &level); | ||
86 | if (o == NULL) | ||
87 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | ||
88 | } | ||
89 | fn = &gcval(o)->fn; | ||
90 | settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); | ||
91 | return 1; | ||
92 | } | ||
93 | |||
94 | LJLIB_CF(setfenv) | ||
95 | { | ||
96 | GCfunc *fn; | ||
97 | GCtab *t = lj_lib_checktab(L, 2); | ||
98 | cTValue *o = L->base; | ||
99 | if (!(o < L->top && tvisfunc(o))) { | ||
100 | int level = lj_lib_checkint(L, 1); | ||
101 | if (level == 0) { | ||
102 | /* NOBARRIER: A thread (i.e. L) is never black. */ | ||
103 | setgcref(L->env, obj2gco(t)); | ||
104 | return 0; | ||
105 | } | ||
106 | o = lj_err_getframe(L, level, &level); | ||
107 | if (o == NULL) | ||
108 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | ||
109 | } | ||
110 | fn = &gcval(o)->fn; | ||
111 | if (!isluafunc(fn)) | ||
112 | lj_err_caller(L, LJ_ERR_SETFENV); | ||
113 | setgcref(fn->l.env, obj2gco(t)); | ||
114 | lj_gc_objbarrier(L, obj2gco(fn), t); | ||
115 | setfuncV(L, L->top++, fn); | ||
116 | return 1; | ||
117 | } | ||
118 | |||
119 | LJLIB_ASM(rawget) LJLIB_REC(.) | ||
120 | { | ||
121 | lj_lib_checktab(L, 1); | ||
122 | lj_lib_checkany(L, 2); | ||
123 | return FFH_UNREACHABLE; | ||
124 | } | ||
125 | |||
126 | LJLIB_CF(rawset) LJLIB_REC(.) | ||
127 | { | ||
128 | lj_lib_checktab(L, 1); | ||
129 | lj_lib_checkany(L, 2); | ||
130 | L->top = 1+lj_lib_checkany(L, 3); | ||
131 | lua_rawset(L, 1); | ||
132 | return 1; | ||
133 | } | ||
134 | |||
135 | LJLIB_CF(rawequal) LJLIB_REC(.) | ||
136 | { | ||
137 | cTValue *o1 = lj_lib_checkany(L, 1); | ||
138 | cTValue *o2 = lj_lib_checkany(L, 2); | ||
139 | setboolV(L->top-1, lj_obj_equal(o1, o2)); | ||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | LJLIB_CF(unpack) | ||
144 | { | ||
145 | GCtab *t = lj_lib_checktab(L, 1); | ||
146 | int32_t n, i = lj_lib_optint(L, 2, 1); | ||
147 | int32_t e = (L->base+3-1 < L->top && !tvisnil(L->base+3-1)) ? | ||
148 | lj_lib_checkint(L, 3) : (int32_t)lj_tab_len(t); | ||
149 | if (i > e) return 0; | ||
150 | n = e - i + 1; | ||
151 | if (n <= 0 || !lua_checkstack(L, n)) | ||
152 | lj_err_caller(L, LJ_ERR_UNPACK); | ||
153 | do { | ||
154 | cTValue *tv = lj_tab_getint(t, i); | ||
155 | if (tv) { | ||
156 | copyTV(L, L->top++, tv); | ||
157 | } else { | ||
158 | setnilV(L->top++); | ||
159 | } | ||
160 | } while (i++ < e); | ||
161 | return n; | ||
162 | } | ||
163 | |||
164 | LJLIB_CF(select) | ||
165 | { | ||
166 | int32_t n = (int32_t)(L->top - L->base); | ||
167 | if (n >= 1 && tvisstr(L->base) && *strVdata(L->base) == '#') { | ||
168 | setintV(L->top-1, n-1); | ||
169 | return 1; | ||
170 | } else { | ||
171 | int32_t i = lj_lib_checkint(L, 1); | ||
172 | if (i < 0) i = n + i; else if (i > n) i = n; | ||
173 | if (i < 1) | ||
174 | lj_err_arg(L, 1, LJ_ERR_IDXRNG); | ||
175 | return n - i; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /* -- Base library: conversions ------------------------------------------- */ | ||
180 | |||
181 | LJLIB_ASM(tonumber) LJLIB_REC(.) | ||
182 | { | ||
183 | int32_t base = lj_lib_optint(L, 2, 10); | ||
184 | if (base == 10) { | ||
185 | TValue *o = lj_lib_checkany(L, 1); | ||
186 | if (tvisnum(o) || (tvisstr(o) && lj_str_numconv(strVdata(o), o))) { | ||
187 | setnumV(L->base-1, numV(o)); | ||
188 | return FFH_RES(1); | ||
189 | } | ||
190 | } else { | ||
191 | const char *p = strdata(lj_lib_checkstr(L, 1)); | ||
192 | char *ep; | ||
193 | unsigned long ul; | ||
194 | if (base < 2 || base > 36) | ||
195 | lj_err_arg(L, 2, LJ_ERR_BASERNG); | ||
196 | ul = strtoul(p, &ep, base); | ||
197 | if (p != ep) { | ||
198 | while (lj_ctype_isspace((unsigned char)(*ep))) ep++; | ||
199 | if (*ep == '\0') { | ||
200 | setnumV(L->base-1, cast_num(ul)); | ||
201 | return FFH_RES(1); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | setnilV(L->base-1); | ||
206 | return FFH_RES(1); | ||
207 | } | ||
208 | |||
209 | LJLIB_ASM(tostring) LJLIB_REC(.) | ||
210 | { | ||
211 | TValue *o = lj_lib_checkany(L, 1); | ||
212 | cTValue *mo; | ||
213 | L->top = o+1; /* Only keep one argument. */ | ||
214 | if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { | ||
215 | copyTV(L, L->base-1, mo); /* Replace callable. */ | ||
216 | return FFH_RETRY; | ||
217 | } else { | ||
218 | GCstr *s; | ||
219 | if (tvisnum(o)) { | ||
220 | s = lj_str_fromnum(L, &o->n); | ||
221 | } else if (tvisnil(o)) { | ||
222 | s = lj_str_newlit(L, "nil"); | ||
223 | } else if (tvisfalse(o)) { | ||
224 | s = lj_str_newlit(L, "false"); | ||
225 | } else if (tvistrue(o)) { | ||
226 | s = lj_str_newlit(L, "true"); | ||
227 | } else { | ||
228 | if (tvisfunc(o) && isffunc(funcV(o))) | ||
229 | lua_pushfstring(L, "function: fast#%d", funcV(o)->c.ffid); | ||
230 | else | ||
231 | lua_pushfstring(L, "%s: %p", typename(o), lua_topointer(L, 1)); | ||
232 | /* Note: lua_pushfstring calls the GC which may invalidate o. */ | ||
233 | s = strV(L->top-1); | ||
234 | } | ||
235 | setstrV(L, L->base-1, s); | ||
236 | return FFH_RES(1); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* -- Base library: iterators --------------------------------------------- */ | ||
241 | |||
242 | LJLIB_ASM(next) | ||
243 | { | ||
244 | lj_lib_checktab(L, 1); | ||
245 | lj_lib_checknum(L, 2); /* For ipairs_aux. */ | ||
246 | return FFH_UNREACHABLE; | ||
247 | } | ||
248 | |||
249 | LJLIB_PUSH(lastcl) | ||
250 | LJLIB_ASM_(pairs) | ||
251 | |||
252 | LJLIB_NOREGUV LJLIB_ASM_(ipairs_aux) LJLIB_REC(.) | ||
253 | |||
254 | LJLIB_PUSH(lastcl) | ||
255 | LJLIB_ASM_(ipairs) LJLIB_REC(.) | ||
256 | |||
257 | /* -- Base library: throw and catch errors -------------------------------- */ | ||
258 | |||
259 | LJLIB_CF(error) | ||
260 | { | ||
261 | int32_t level = lj_lib_optint(L, 2, 1); | ||
262 | lua_settop(L, 1); | ||
263 | if (lua_isstring(L, 1) && level > 0) { | ||
264 | luaL_where(L, level); | ||
265 | lua_pushvalue(L, 1); | ||
266 | lua_concat(L, 2); | ||
267 | } | ||
268 | return lua_error(L); | ||
269 | } | ||
270 | |||
271 | LJLIB_ASM(pcall) LJLIB_REC(.) | ||
272 | { | ||
273 | lj_lib_checkany(L, 1); | ||
274 | lj_lib_checkfunc(L, 2); /* For xpcall only. */ | ||
275 | return FFH_UNREACHABLE; | ||
276 | } | ||
277 | LJLIB_ASM_(xpcall) LJLIB_REC(.) | ||
278 | |||
279 | /* -- Base library: load Lua code ----------------------------------------- */ | ||
280 | |||
281 | static int load_aux(lua_State *L, int status) | ||
282 | { | ||
283 | if (status == 0) | ||
284 | return 1; | ||
285 | copyTV(L, L->top, L->top-1); | ||
286 | setnilV(L->top-1); | ||
287 | L->top++; | ||
288 | return 2; | ||
289 | } | ||
290 | |||
291 | LJLIB_CF(loadstring) | ||
292 | { | ||
293 | GCstr *s = lj_lib_checkstr(L, 1); | ||
294 | GCstr *name = lj_lib_optstr(L, 2); | ||
295 | return load_aux(L, | ||
296 | luaL_loadbuffer(L, strdata(s), s->len, strdata(name ? name : s))); | ||
297 | } | ||
298 | |||
299 | LJLIB_CF(loadfile) | ||
300 | { | ||
301 | GCstr *fname = lj_lib_optstr(L, 1); | ||
302 | return load_aux(L, luaL_loadfile(L, fname ? strdata(fname) : NULL)); | ||
303 | } | ||
304 | |||
305 | static const char *reader_func(lua_State *L, void *ud, size_t *size) | ||
306 | { | ||
307 | UNUSED(ud); | ||
308 | luaL_checkstack(L, 2, "too many nested functions"); | ||
309 | copyTV(L, L->top++, L->base); | ||
310 | lua_call(L, 0, 1); /* Call user-supplied function. */ | ||
311 | L->top--; | ||
312 | if (tvisnil(L->top)) { | ||
313 | *size = 0; | ||
314 | return NULL; | ||
315 | } else if (tvisstr(L->top) || tvisnum(L->top)) { | ||
316 | copyTV(L, L->base+2, L->top); /* Anchor string in reserved stack slot. */ | ||
317 | return lua_tolstring(L, 3, size); | ||
318 | } else { | ||
319 | lj_err_caller(L, LJ_ERR_RDRSTR); | ||
320 | return NULL; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | LJLIB_CF(load) | ||
325 | { | ||
326 | GCstr *name = lj_lib_optstr(L, 2); | ||
327 | lj_lib_checkfunc(L, 1); | ||
328 | lua_settop(L, 3); /* Reserve a slot for the string from the reader. */ | ||
329 | return load_aux(L, | ||
330 | lua_load(L, reader_func, NULL, name ? strdata(name) : "=(load)")); | ||
331 | } | ||
332 | |||
333 | LJLIB_CF(dofile) | ||
334 | { | ||
335 | GCstr *fname = lj_lib_optstr(L, 1); | ||
336 | setnilV(L->top); | ||
337 | L->top = L->base+1; | ||
338 | if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0) | ||
339 | lua_error(L); | ||
340 | lua_call(L, 0, LUA_MULTRET); | ||
341 | return (L->top - L->base) - 1; | ||
342 | } | ||
343 | |||
344 | /* -- Base library: GC control -------------------------------------------- */ | ||
345 | |||
346 | LJLIB_CF(gcinfo) | ||
347 | { | ||
348 | setintV(L->top++, (G(L)->gc.total >> 10)); | ||
349 | return 1; | ||
350 | } | ||
351 | |||
352 | LJLIB_CF(collectgarbage) | ||
353 | { | ||
354 | int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ | ||
355 | "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); | ||
356 | int32_t data = lj_lib_optint(L, 2, 0); | ||
357 | if (opt == LUA_GCCOUNT) { | ||
358 | setnumV(L->top-1, cast_num((int32_t)G(L)->gc.total)/1024.0); | ||
359 | } else { | ||
360 | int res = lua_gc(L, opt, data); | ||
361 | if (opt == LUA_GCSTEP) | ||
362 | setboolV(L->top-1, res); | ||
363 | else | ||
364 | setintV(L->top-1, res); | ||
365 | } | ||
366 | return 1; | ||
367 | } | ||
368 | |||
369 | /* -- Base library: miscellaneous functions ------------------------------- */ | ||
370 | |||
371 | LJLIB_PUSH(top-2) /* Upvalue holds weak table. */ | ||
372 | LJLIB_CF(newproxy) | ||
373 | { | ||
374 | lua_settop(L, 1); | ||
375 | lua_newuserdata(L, 0); | ||
376 | if (lua_toboolean(L, 1) == 0) { /* newproxy(): without metatable. */ | ||
377 | return 1; | ||
378 | } else if (lua_isboolean(L, 1)) { /* newproxy(true): with metatable. */ | ||
379 | lua_newtable(L); | ||
380 | lua_pushvalue(L, -1); | ||
381 | lua_pushboolean(L, 1); | ||
382 | lua_rawset(L, lua_upvalueindex(1)); /* Remember mt in weak table. */ | ||
383 | } else { /* newproxy(proxy): inherit metatable. */ | ||
384 | int validproxy = 0; | ||
385 | if (lua_getmetatable(L, 1)) { | ||
386 | lua_rawget(L, lua_upvalueindex(1)); | ||
387 | validproxy = lua_toboolean(L, -1); | ||
388 | lua_pop(L, 1); | ||
389 | } | ||
390 | if (!validproxy) | ||
391 | lj_err_arg(L, 1, LJ_ERR_NOPROXY); | ||
392 | lua_getmetatable(L, 1); | ||
393 | } | ||
394 | lua_setmetatable(L, 2); | ||
395 | return 1; | ||
396 | } | ||
397 | |||
398 | LJLIB_PUSH("tostring") | ||
399 | LJLIB_CF(print) | ||
400 | { | ||
401 | ptrdiff_t i, nargs = L->top - L->base; | ||
402 | cTValue *tv = lj_tab_getstr(tabref(L->env), strV(lj_lib_upvalue(L, 1))); | ||
403 | int shortcut = (tv && tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring); | ||
404 | copyTV(L, L->top++, tv ? tv : niltv(L)); | ||
405 | for (i = 0; i < nargs; i++) { | ||
406 | const char *str; | ||
407 | size_t size; | ||
408 | cTValue *o = &L->base[i]; | ||
409 | if (shortcut && tvisstr(o)) { | ||
410 | str = strVdata(o); | ||
411 | size = strV(o)->len; | ||
412 | } else if (shortcut && tvisnum(o)) { | ||
413 | char buf[LUAI_MAXNUMBER2STR]; | ||
414 | lua_Number n = numV(o); | ||
415 | size = (size_t)lua_number2str(buf, n); | ||
416 | str = buf; | ||
417 | } else { | ||
418 | copyTV(L, L->top+1, o); | ||
419 | copyTV(L, L->top, L->top-1); | ||
420 | L->top += 2; | ||
421 | lua_call(L, 1, 1); | ||
422 | str = lua_tolstring(L, -1, &size); | ||
423 | if (!str) | ||
424 | lj_err_caller(L, LJ_ERR_PRTOSTR); | ||
425 | L->top--; | ||
426 | } | ||
427 | if (i) | ||
428 | putchar('\t'); | ||
429 | fwrite(str, 1, size, stdout); | ||
430 | } | ||
431 | putchar('\n'); | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | LJLIB_PUSH(top-3) | ||
436 | LJLIB_SET(_VERSION) | ||
437 | |||
438 | #include "lj_libdef.h" | ||
439 | |||
440 | /* -- Coroutine library --------------------------------------------------- */ | ||
441 | |||
442 | #define LJLIB_MODULE_coroutine | ||
443 | |||
444 | LJLIB_CF(coroutine_status) | ||
445 | { | ||
446 | const char *s; | ||
447 | lua_State *co; | ||
448 | if (!(L->top > L->base && tvisthread(L->base))) | ||
449 | lj_err_arg(L, 1, LJ_ERR_NOCORO); | ||
450 | co = threadV(L->base); | ||
451 | if (co == L) s = "running"; | ||
452 | else if (co->status == LUA_YIELD) s = "suspended"; | ||
453 | else if (co->status != 0) s = "dead"; | ||
454 | else if (co->base > co->stack+1) s = "normal"; | ||
455 | else if (co->top == co->base) s = "dead"; | ||
456 | else s = "suspended"; | ||
457 | lua_pushstring(L, s); | ||
458 | return 1; | ||
459 | } | ||
460 | |||
461 | LJLIB_CF(coroutine_running) | ||
462 | { | ||
463 | if (lua_pushthread(L)) | ||
464 | setnilV(L->top++); | ||
465 | return 1; | ||
466 | } | ||
467 | |||
468 | LJLIB_CF(coroutine_create) | ||
469 | { | ||
470 | lua_State *L1 = lua_newthread(L); | ||
471 | if (!(L->top > L->base && tvisfunc(L->base) && isluafunc(funcV(L->base)))) | ||
472 | lj_err_arg(L, 1, LJ_ERR_NOLFUNC); | ||
473 | setfuncV(L, L1->top++, funcV(L->base)); | ||
474 | return 1; | ||
475 | } | ||
476 | |||
477 | LJLIB_ASM(coroutine_yield) | ||
478 | { | ||
479 | lj_err_caller(L, LJ_ERR_CYIELD); | ||
480 | return FFH_UNREACHABLE; | ||
481 | } | ||
482 | |||
483 | static int ffh_resume(lua_State *L, lua_State *co, int wrap) | ||
484 | { | ||
485 | if (co->cframe != NULL || co->status > LUA_YIELD || | ||
486 | (co->status == 0 && co->top == co->base)) { | ||
487 | ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; | ||
488 | if (wrap) lj_err_caller(L, em); | ||
489 | setboolV(L->base-1, 0); | ||
490 | setstrV(L, L->base, lj_err_str(L, em)); | ||
491 | return FFH_RES(2); | ||
492 | } | ||
493 | lj_state_growstack(co, (MSize)(L->top - L->base - 1)); | ||
494 | return FFH_RETRY; | ||
495 | } | ||
496 | |||
497 | LJLIB_ASM(coroutine_resume) | ||
498 | { | ||
499 | if (!(L->top > L->base && tvisthread(L->base))) | ||
500 | lj_err_arg(L, 1, LJ_ERR_NOCORO); | ||
501 | return ffh_resume(L, threadV(L->base), 0); | ||
502 | } | ||
503 | |||
504 | LJLIB_NOREG LJLIB_ASM(coroutine_wrap_aux) | ||
505 | { | ||
506 | return ffh_resume(L, threadV(lj_lib_upvalue(L, 1)), 1); | ||
507 | } | ||
508 | |||
509 | /* Inline declarations. */ | ||
510 | LJ_ASMF void lj_ff_coroutine_wrap_aux(void); | ||
511 | LJ_FUNCA_NORET void lj_ffh_coroutine_wrap_err(lua_State *L, lua_State *co); | ||
512 | |||
513 | /* Error handler, called from assembler VM. */ | ||
514 | void lj_ffh_coroutine_wrap_err(lua_State *L, lua_State *co) | ||
515 | { | ||
516 | co->top--; copyTV(L, L->top, co->top); L->top++; | ||
517 | if (tvisstr(L->top-1)) | ||
518 | lj_err_callermsg(L, strVdata(L->top-1)); | ||
519 | else | ||
520 | lj_err_run(L); | ||
521 | } | ||
522 | |||
523 | LJLIB_CF(coroutine_wrap) | ||
524 | { | ||
525 | GCfunc *fn; | ||
526 | lj_cf_coroutine_create(L); | ||
527 | lua_pushcclosure(L, lj_ffh_coroutine_wrap_aux, 1); | ||
528 | fn = funcV(L->top-1); | ||
529 | fn->c.gate = lj_ff_coroutine_wrap_aux; | ||
530 | fn->c.ffid = FF_coroutine_wrap_aux; | ||
531 | return 1; | ||
532 | } | ||
533 | |||
534 | #include "lj_libdef.h" | ||
535 | |||
536 | /* ------------------------------------------------------------------------ */ | ||
537 | |||
538 | static void newproxy_weaktable(lua_State *L) | ||
539 | { | ||
540 | /* NOBARRIER: The table is new (marked white). */ | ||
541 | GCtab *t = lj_tab_new(L, 0, 1); | ||
542 | settabV(L, L->top++, t); | ||
543 | setgcref(t->metatable, obj2gco(t)); | ||
544 | setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), | ||
545 | lj_str_newlit(L, "kv")); | ||
546 | t->nomm = cast_byte(~(1u<<MM_mode)); | ||
547 | } | ||
548 | |||
549 | LUALIB_API int luaopen_base(lua_State *L) | ||
550 | { | ||
551 | /* NOBARRIER: Table and value are the same. */ | ||
552 | GCtab *env = tabref(L->env); | ||
553 | settabV(L, lj_tab_setstr(L, env, lj_str_newlit(L, "_G")), env); | ||
554 | lua_pushliteral(L, LUA_VERSION); /* top-3. */ | ||
555 | newproxy_weaktable(L); /* top-2. */ | ||
556 | LJ_LIB_REG_(L, "_G", base); | ||
557 | LJ_LIB_REG(L, coroutine); | ||
558 | return 2; | ||
559 | } | ||
560 | |||