aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-07-12 13:16:43 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1998-07-12 13:16:43 -0300
commitafb5ef72e1974ba6d0fc336637c71f3ee8fb03a2 (patch)
tree9e7c9bf902a86ae79a0eecb413dfb00ad1250665
parent1d8edd347d728ba6b0160359f3c0391e7b1a8a44 (diff)
downloadlua-afb5ef72e1974ba6d0fc336637c71f3ee8fb03a2.tar.gz
lua-afb5ef72e1974ba6d0fc336637c71f3ee8fb03a2.tar.bz2
lua-afb5ef72e1974ba6d0fc336637c71f3ee8fb03a2.zip
new function "sort" + many small changes
-rw-r--r--lbuiltin.c169
-rw-r--r--lvm.c29
-rw-r--r--lvm.h5
3 files changed, 142 insertions, 61 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}
diff --git a/lvm.c b/lvm.c
index 44416b0a..ace249ed 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.29 1998/05/31 22:18:24 roberto Exp roberto $ 2** $Id: lvm.c,v 1.30 1998/06/11 18:21:37 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -112,7 +112,7 @@ void luaV_gettable (void)
112 im = luaT_getim(tg, IM_GETTABLE); 112 im = luaT_getim(tg, IM_GETTABLE);
113 if (ttype(im) == LUA_T_NIL) { /* and does not have a "gettable" method */ 113 if (ttype(im) == LUA_T_NIL) { /* and does not have a "gettable" method */
114 TObject *h = luaH_get(avalue(S->top-2), S->top-1); 114 TObject *h = luaH_get(avalue(S->top-2), S->top-1);
115 if (h != NULL && ttype(h) != LUA_T_NIL) { 115 if (ttype(h) != LUA_T_NIL) {
116 --S->top; 116 --S->top;
117 *(S->top-1) = *h; 117 *(S->top-1) = *h;
118 } 118 }
@@ -242,8 +242,8 @@ static int strcomp (char *l, long ll, char *r, long lr)
242 } 242 }
243} 243}
244 244
245static void comparison (lua_Type ttype_less, lua_Type ttype_equal, 245void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal,
246 lua_Type ttype_great, IMS op) 246 lua_Type ttype_great, IMS op)
247{ 247{
248 struct Stack *S = &L->stack; 248 struct Stack *S = &L->stack;
249 TObject *l = S->top-2; 249 TObject *l = S->top-2;
@@ -269,22 +269,19 @@ void luaV_pack (StkId firstel, int nvararg, TObject *tab)
269{ 269{
270 TObject *firstelem = L->stack.stack+firstel; 270 TObject *firstelem = L->stack.stack+firstel;
271 int i; 271 int i;
272 Hash *htab;
272 if (nvararg < 0) nvararg = 0; 273 if (nvararg < 0) nvararg = 0;
273 avalue(tab) = luaH_new(nvararg+1); /* +1 for field 'n' */ 274 htab = avalue(tab) = luaH_new(nvararg+1); /* +1 for field 'n' */
274 ttype(tab) = LUA_T_ARRAY; 275 ttype(tab) = LUA_T_ARRAY;
275 for (i=0; i<nvararg; i++) { 276 for (i=0; i<nvararg; i++)
276 TObject index; 277 luaH_setint(htab, i+1, firstelem+i);
277 ttype(&index) = LUA_T_NUMBER;
278 nvalue(&index) = i+1;
279 *(luaH_set(avalue(tab), &index)) = *(firstelem+i);
280 }
281 /* store counter in field "n" */ { 278 /* store counter in field "n" */ {
282 TObject index, extra; 279 TObject index, extra;
283 ttype(&index) = LUA_T_STRING; 280 ttype(&index) = LUA_T_STRING;
284 tsvalue(&index) = luaS_new("n"); 281 tsvalue(&index) = luaS_new("n");
285 ttype(&extra) = LUA_T_NUMBER; 282 ttype(&extra) = LUA_T_NUMBER;
286 nvalue(&extra) = nvararg; 283 nvalue(&extra) = nvararg;
287 *(luaH_set(avalue(tab), &index)) = extra; 284 *(luaH_set(htab, &index)) = extra;
288 } 285 }
289} 286}
290 287
@@ -528,19 +525,19 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base)
528 } 525 }
529 526
530 case LTOP: 527 case LTOP:
531 comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT); 528 luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
532 break; 529 break;
533 530
534 case LEOP: 531 case LEOP:
535 comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE); 532 luaV_comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE);
536 break; 533 break;
537 534
538 case GTOP: 535 case GTOP:
539 comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT); 536 luaV_comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT);
540 break; 537 break;
541 538
542 case GEOP: 539 case GEOP:
543 comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE); 540 luaV_comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE);
544 break; 541 break;
545 542
546 case ADDOP: { 543 case ADDOP: {
diff --git a/lvm.h b/lvm.h
index a371326f..38db19aa 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 1.3 1997/10/16 10:59:34 roberto Exp roberto $ 2** $Id: lvm.h,v 1.4 1997/12/15 16:17:20 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -10,6 +10,7 @@
10 10
11#include "ldo.h" 11#include "ldo.h"
12#include "lobject.h" 12#include "lobject.h"
13#include "ltm.h"
13 14
14 15
15#define tonumber(o) ((ttype(o) != LUA_T_NUMBER) && (luaV_tonumber(o) != 0)) 16#define tonumber(o) ((ttype(o) != LUA_T_NUMBER) && (luaV_tonumber(o) != 0))
@@ -25,5 +26,7 @@ void luaV_getglobal (TaggedString *ts);
25void luaV_setglobal (TaggedString *ts); 26void luaV_setglobal (TaggedString *ts);
26StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base); 27StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base);
27void luaV_closure (int nelems); 28void luaV_closure (int nelems);
29void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal,
30 lua_Type ttype_great, IMS op);
28 31
29#endif 32#endif