aboutsummaryrefslogtreecommitdiff
path: root/lbuiltin.c
diff options
context:
space:
mode:
Diffstat (limited to 'lbuiltin.c')
-rw-r--r--lbuiltin.c169
1 files changed, 125 insertions, 44 deletions
diff --git a/lbuiltin.c b/lbuiltin.c
index 512ec631..43023e8e 100644
--- a/lbuiltin.c
+++ b/lbuiltin.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbuiltin.c,v 1.31 1998/06/19 18:47:06 roberto Exp roberto $ 2** $Id: lbuiltin.c,v 1.32 1998/06/29 18:24:06 roberto Exp roberto $
3** Built-in functions 3** Built-in functions
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -23,6 +23,7 @@
23#include "ltm.h" 23#include "ltm.h"
24#include "lua.h" 24#include "lua.h"
25#include "lundump.h" 25#include "lundump.h"
26#include "lvm.h"
26 27
27 28
28 29
@@ -35,18 +36,17 @@ static void pushstring (TaggedString *s)
35} 36}
36 37
37 38
38static void nextvar (void) 39static void nextvar (void) {
39{
40 TObject *o = luaA_Address(luaL_nonnullarg(1)); 40 TObject *o = luaA_Address(luaL_nonnullarg(1));
41 TaggedString *g; 41 TaggedString *g;
42 if (ttype(o) == LUA_T_NIL) 42 if (ttype(o) == LUA_T_NIL)
43 g = (TaggedString *)L->rootglobal.next; 43 g = (TaggedString *)L->rootglobal.next; /* first variable */
44 else { 44 else {
45 luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "variable name expected"); 45 luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "variable name expected");
46 g = tsvalue(o); 46 g = tsvalue(o); /* find given variable name */
47 /* check whether name is in global var list */ 47 /* check whether name is in global var list */
48 luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected"); 48 luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected");
49 g = (TaggedString *)g->head.next; 49 g = (TaggedString *)g->head.next; /* get next */
50 } 50 }
51 while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */ 51 while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */
52 g = (TaggedString *)g->head.next; 52 g = (TaggedString *)g->head.next;
@@ -54,26 +54,26 @@ static void nextvar (void)
54 pushstring(g); 54 pushstring(g);
55 luaA_pushobject(&g->u.s.globalval); 55 luaA_pushobject(&g->u.s.globalval);
56 } 56 }
57 else lua_pushnil(); 57 else lua_pushnil(); /* no more globals */
58} 58}
59 59
60 60
61static void foreachvar (void) 61static void foreachvar (void) {
62{
63 TObject f = *luaA_Address(luaL_functionarg(1)); 62 TObject f = *luaA_Address(luaL_functionarg(1));
64 GCnode *g; 63 GCnode *g;
65 StkId name = L->Cstack.base++; /* place to keep var name (to avoid GC) */ 64 StkId name = L->Cstack.base++; /* place to keep var name (to avoid GC) */
65 luaD_checkstack(4); /* for var name, f, s, and globalvar */
66 ttype(L->stack.stack+name) = LUA_T_NIL; 66 ttype(L->stack.stack+name) = LUA_T_NIL;
67 L->stack.top++; 67 L->stack.top++; /* top == base */
68 for (g = L->rootglobal.next; g; g = g->next) { 68 for (g = L->rootglobal.next; g; g = g->next) {
69 TaggedString *s = (TaggedString *)g; 69 TaggedString *s = (TaggedString *)g;
70 if (s->u.s.globalval.ttype != LUA_T_NIL) { 70 if (s->u.s.globalval.ttype != LUA_T_NIL) {
71 ttype(L->stack.stack+name) = LUA_T_STRING; 71 ttype(L->stack.stack+name) = LUA_T_STRING;
72 tsvalue(L->stack.stack+name) = s; /* keep s on stack to avoid GC */ 72 tsvalue(L->stack.stack+name) = s; /* keep s on stack to avoid GC */
73 luaA_pushobject(&f); 73 *(L->stack.top++) = f;
74 pushstring(s); 74 pushstring(s);
75 luaA_pushobject(&s->u.s.globalval); 75 *(L->stack.top++) = s->u.s.globalval;
76 luaD_call((L->stack.top-L->stack.stack)-2, 1); 76 luaD_calln(2, 1);
77 if (ttype(L->stack.top-1) != LUA_T_NIL) 77 if (ttype(L->stack.top-1) != LUA_T_NIL)
78 return; 78 return;
79 L->stack.top--; 79 L->stack.top--;
@@ -82,11 +82,9 @@ static void foreachvar (void)
82} 82}
83 83
84 84
85static void next (void) 85static void next (void) {
86{ 86 Node *n = luaH_next(luaA_Address(luaL_tablearg(1)),
87 lua_Object o = luaL_tablearg(1); 87 luaA_Address(luaL_nonnullarg(2)));
88 lua_Object r = luaL_nonnullarg(2);
89 Node *n = luaH_next(luaA_Address(o), luaA_Address(r));
90 if (n) { 88 if (n) {
91 luaA_pushobject(&n->ref); 89 luaA_pushobject(&n->ref);
92 luaA_pushobject(&n->val); 90 luaA_pushobject(&n->val);
@@ -95,18 +93,18 @@ static void next (void)
95} 93}
96 94
97 95
98static void foreach (void) 96static void foreach (void) {
99{
100 TObject t = *luaA_Address(luaL_tablearg(1)); 97 TObject t = *luaA_Address(luaL_tablearg(1));
101 TObject f = *luaA_Address(luaL_functionarg(2)); 98 TObject f = *luaA_Address(luaL_functionarg(2));
102 int i; 99 int i;
100 luaD_checkstack(3); /* for f, ref, and val */
103 for (i=0; i<avalue(&t)->nhash; i++) { 101 for (i=0; i<avalue(&t)->nhash; i++) {
104 Node *nd = &(avalue(&t)->node[i]); 102 Node *nd = &(avalue(&t)->node[i]);
105 if (ttype(ref(nd)) != LUA_T_NIL && ttype(val(nd)) != LUA_T_NIL) { 103 if (ttype(ref(nd)) != LUA_T_NIL && ttype(val(nd)) != LUA_T_NIL) {
106 luaA_pushobject(&f); 104 *(L->stack.top++) = f;
107 luaA_pushobject(ref(nd)); 105 *(L->stack.top++) = *ref(nd);
108 luaA_pushobject(val(nd)); 106 *(L->stack.top++) = *val(nd);
109 luaD_call((L->stack.top-L->stack.stack)-2, 1); 107 luaD_calln(2, 1);
110 if (ttype(L->stack.top-1) != LUA_T_NIL) 108 if (ttype(L->stack.top-1) != LUA_T_NIL)
111 return; 109 return;
112 L->stack.top--; 110 L->stack.top--;
@@ -138,8 +136,8 @@ static void internaldofile (void)
138 136
139static void to_string (void) { 137static void to_string (void) {
140 lua_Object obj = lua_getparam(1); 138 lua_Object obj = lua_getparam(1);
141 char *buff = luaL_openspace(30);
142 TObject *o = luaA_Address(obj); 139 TObject *o = luaA_Address(obj);
140 char buff[32];
143 switch (ttype(o)) { 141 switch (ttype(o)) {
144 case LUA_T_NUMBER: 142 case LUA_T_NUMBER:
145 lua_pushstring(lua_getstring(obj)); 143 lua_pushstring(lua_getstring(obj));
@@ -184,10 +182,10 @@ static void luaI_print (void) {
184 while ((obj = lua_getparam(i++)) != LUA_NOOBJECT) { 182 while ((obj = lua_getparam(i++)) != LUA_NOOBJECT) {
185 luaA_pushobject(&ts->u.s.globalval); 183 luaA_pushobject(&ts->u.s.globalval);
186 lua_pushobject(obj); 184 lua_pushobject(obj);
187 luaD_call((L->stack.top-L->stack.stack)-1, 1); 185 luaD_calln(1, 1);
188 if (ttype(L->stack.top-1) != LUA_T_STRING) 186 if (ttype(L->stack.top-1) != LUA_T_STRING)
189 lua_error("`tostring' must return a string to `print'"); 187 lua_error("`tostring' must return a string to `print'");
190 printf("%s\t", svalue(L->stack.top-1)); 188 printf("%.200s\t", svalue(L->stack.top-1));
191 L->stack.top--; 189 L->stack.top--;
192 } 190 }
193 printf("\n"); 191 printf("\n");
@@ -197,12 +195,12 @@ static void luaI_print (void) {
197static void luaI_type (void) 195static void luaI_type (void)
198{ 196{
199 lua_Object o = luaL_nonnullarg(1); 197 lua_Object o = luaL_nonnullarg(1);
200 lua_pushstring(luaO_typenames[-ttype(luaA_Address(o))]); 198 lua_pushstring(luaO_typename(luaA_Address(o)));
201 lua_pushnumber(lua_tag(o)); 199 lua_pushnumber(lua_tag(o));
202} 200}
203 201
204 202
205static void tonumber (void) 203static void luaB_tonumber (void)
206{ 204{
207 int base = luaL_opt_number(2, 10); 205 int base = luaL_opt_number(2, 10);
208 if (base == 10) { /* standard conversion */ 206 if (base == 10) { /* standard conversion */
@@ -270,16 +268,30 @@ static void luatag (void)
270} 268}
271 269
272 270
273static int getnarg (lua_Object table) 271static int getsize (TObject *t) {
274{ 272 int max = 0;
273 int i;
274 Hash *h = avalue(t);
275 LUA_ASSERT(ttype(t) == LUA_T_ARRAY, "table expected");
276 for (i = 0; i<nhash(h); i++) {
277 Node *n = h->node+i;
278 if (ttype(ref(n)) == LUA_T_NUMBER && ttype(val(n)) != LUA_T_NIL &&
279 (int)nvalue(ref(n)) > max)
280 max = nvalue(ref(n));
281 }
282 return max;
283}
284
285
286static int getnarg (lua_Object table) {
275 lua_Object temp; 287 lua_Object temp;
276 /* temp = table.n */ 288 /* temp = table.n */
277 lua_pushobject(table); lua_pushstring("n"); temp = lua_rawgettable(); 289 lua_pushobject(table); lua_pushstring("n"); temp = lua_rawgettable();
278 return (lua_isnumber(temp) ? lua_getnumber(temp) : MAX_INT); 290 return (lua_isnumber(temp) ? lua_getnumber(temp) :
291 getsize(luaA_Address(table)));
279} 292}
280 293
281static void luaI_call (void) 294static void luaI_call (void) {
282{
283 lua_Object f = luaL_nonnullarg(1); 295 lua_Object f = luaL_nonnullarg(1);
284 lua_Object arg = luaL_tablearg(2); 296 lua_Object arg = luaL_tablearg(2);
285 char *options = luaL_opt_string(3, ""); 297 char *options = luaL_opt_string(3, "");
@@ -291,14 +303,9 @@ static void luaI_call (void)
291 err = lua_seterrormethod(); 303 err = lua_seterrormethod();
292 } 304 }
293 /* push arg[1...n] */ 305 /* push arg[1...n] */
294 for (i=0; i<narg; i++) { 306 luaD_checkstack(narg);
295 lua_Object temp; 307 for (i=0; i<narg; i++)
296 /* temp = arg[i+1] */ 308 *(L->stack.top++) = *luaH_getint(avalue(luaA_Address(arg)), i+1);
297 lua_pushobject(arg); lua_pushnumber(i+1); temp = lua_rawgettable();
298 if (narg == MAX_INT && lua_isnil(temp))
299 break;
300 lua_pushobject(temp);
301 }
302 status = lua_callfunction(f); 309 status = lua_callfunction(f);
303 if (err != LUA_NOOBJECT) { /* restore old error method */ 310 if (err != LUA_NOOBJECT) { /* restore old error method */
304 lua_pushobject(err); 311 lua_pushobject(err);
@@ -312,7 +319,7 @@ static void luaI_call (void)
312 else 319 else
313 lua_error(NULL); 320 lua_error(NULL);
314 } 321 }
315 else { /* no errors */ 322 else { /* no errors */
316 if (strchr(options, 'p')) 323 if (strchr(options, 'p'))
317 luaA_packresults(); 324 luaA_packresults();
318 else 325 else
@@ -390,6 +397,79 @@ static void luaI_collectgarbage (void)
390} 397}
391 398
392 399
400
401static void swap (Hash *a, int i, int j) {
402 /* notice: must use two temporary vars, because luaH_setint may cause a
403 rehash and change the addresses of values in the array */
404 TObject ai = *luaH_getint(a, i);
405 TObject aj = *luaH_getint(a, j);
406 luaH_setint(a, i, &aj);
407 luaH_setint(a, j, &ai);
408}
409
410static int sort_comp (TObject *f, TObject *a, TObject *b) {
411 /* notice: the caller (auxsort) must check stack space */
412 if (f) {
413 *(L->stack.top++) = *f;
414 *(L->stack.top++) = *a;
415 *(L->stack.top++) = *b;
416 luaD_calln(2, 1);
417 }
418 else { /* a < b? */
419 *(L->stack.top++) = *a;
420 *(L->stack.top++) = *b;
421 luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
422 }
423 return ttype(--(L->stack.top)) != LUA_T_NIL;
424}
425
426/*
427** quicksort algorithm from "Programming Pearls", pg. 112
428*/
429static void auxsort (Hash *a, int l, int u, TObject *f) {
430 if (u <= l) return; /* 0 or 1 element */
431 luaD_checkstack(4); /* for pivot, f, a, b (sort_comp) */
432 if (u-l == 1) { /* only two elements? */
433 if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[u] < a[l]? */
434 swap(a, l, u);
435 }
436 else {
437 int i;
438 int m = l;
439 swap(a, l, (l+u)/2); /* put middle element as pivot (a[l]) */
440 *(L->stack.top++) = *luaH_getint(a, l); /* save pivot on stack (for GC) */
441 for (i=l+1; i<=u; i++) {
442 /* invariant: a[l+1..m] < P <= a[m+1..i-1] */
443 if (sort_comp(f, luaH_getint(a, i), L->stack.top-1)) { /* a[i] < P? */
444 m++;
445 swap(a, m, i);
446 }
447 }
448 L->stack.top--; /* remove pivot from stack */
449 swap(a, l, m);
450 /* a[l..m-1] < a[m] <= a[m+1..u] */
451 auxsort(a, l, m-1, f);
452 auxsort(a, m+1, u, f);
453 }
454}
455
456static void luaB_sort (void) {
457 lua_Object t = luaL_tablearg(1);
458 int n = getnarg(t);
459 Hash *a = avalue(luaA_Address(t));
460 lua_Object func = lua_getparam(2);
461 TObject *f;
462 if (func == LUA_NOOBJECT)
463 f = NULL;
464 else {
465 luaL_arg_check(lua_isfunction(func), 2, "function expected");
466 f = luaA_Address(func);
467 }
468 auxsort(a, 1, n, f);
469 lua_pushobject(t);
470}
471
472
393/* 473/*
394** ======================================================= 474** =======================================================
395** some DEBUG functions 475** some DEBUG functions
@@ -504,7 +584,8 @@ static struct luaL_reg int_funcs[] = {
504 {"settagmethod", settagmethod}, 584 {"settagmethod", settagmethod},
505 {"gettagmethod", gettagmethod}, 585 {"gettagmethod", gettagmethod},
506 {"settag", settag}, 586 {"settag", settag},
507 {"tonumber", tonumber}, 587 {"sort", luaB_sort},
588 {"tonumber", luaB_tonumber},
508 {"tostring", to_string}, 589 {"tostring", to_string},
509 {"tag", luatag}, 590 {"tag", luatag},
510 {"type", luaI_type} 591 {"type", luaI_type}