diff options
-rw-r--r-- | lbaselib.c | 296 | ||||
-rw-r--r-- | lua.c | 3 | ||||
-rw-r--r-- | lualib.h | 3 |
3 files changed, 5 insertions, 297 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.64 2002/04/05 18:54:31 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.65 2002/04/09 19:46:56 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -432,302 +432,8 @@ static void base_open (lua_State *L) { | |||
432 | } | 432 | } |
433 | 433 | ||
434 | 434 | ||
435 | /* | ||
436 | ** {====================================================== | ||
437 | ** Coroutine library | ||
438 | ** ======================================================= | ||
439 | */ | ||
440 | |||
441 | |||
442 | static int luaB_resume (lua_State *L) { | ||
443 | lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1)); | ||
444 | lua_settop(L, 0); | ||
445 | if (lua_resume(L, co) != 0) | ||
446 | lua_error(L, "error running co-routine"); | ||
447 | return lua_gettop(L); | ||
448 | } | ||
449 | |||
450 | |||
451 | |||
452 | static int gc_coroutine (lua_State *L) { | ||
453 | lua_State *co = (lua_State *)lua_getfrombox(L, 1); | ||
454 | lua_closethread(L, co); | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | |||
459 | static int luaB_coroutine (lua_State *L) { | ||
460 | lua_State *NL; | ||
461 | int ref; | ||
462 | int i; | ||
463 | int n = lua_gettop(L); | ||
464 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, | ||
465 | "Lua function expected"); | ||
466 | NL = lua_newthread(L); | ||
467 | if (NL == NULL) lua_error(L, "unable to create new thread"); | ||
468 | /* move function and arguments from L to NL */ | ||
469 | for (i=0; i<n; i++) { | ||
470 | ref = lua_ref(L, 1); | ||
471 | lua_getref(NL, ref); | ||
472 | lua_insert(NL, 1); | ||
473 | lua_unref(L, ref); | ||
474 | } | ||
475 | lua_cobegin(NL, n-1); | ||
476 | lua_newpointerbox(L, NL); | ||
477 | lua_pushliteral(L, "Coroutine"); | ||
478 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
479 | lua_setmetatable(L, -2); | ||
480 | lua_pushcclosure(L, luaB_resume, 1); | ||
481 | return 1; | ||
482 | } | ||
483 | |||
484 | |||
485 | static int luaB_yield (lua_State *L) { | ||
486 | return lua_yield(L, lua_gettop(L)); | ||
487 | } | ||
488 | |||
489 | static const luaL_reg co_funcs[] = { | ||
490 | {"create", luaB_coroutine}, | ||
491 | {"yield", luaB_yield}, | ||
492 | {NULL, NULL} | ||
493 | }; | ||
494 | |||
495 | |||
496 | static void co_open (lua_State *L) { | ||
497 | luaL_opennamedlib(L, "co", co_funcs, 0); | ||
498 | /* create metatable for coroutines */ | ||
499 | lua_pushliteral(L, "Coroutine"); | ||
500 | lua_newtable(L); | ||
501 | lua_pushliteral(L, "__gc"); | ||
502 | lua_pushcfunction(L, gc_coroutine); | ||
503 | lua_rawset(L, -3); | ||
504 | lua_rawset(L, LUA_REGISTRYINDEX); | ||
505 | } | ||
506 | |||
507 | /* }====================================================== */ | ||
508 | |||
509 | |||
510 | /* | ||
511 | ** {====================================================== | ||
512 | ** Auxiliar table-related functions | ||
513 | */ | ||
514 | |||
515 | static int luaB_foreachi (lua_State *L) { | ||
516 | int n, i; | ||
517 | luaL_check_type(L, 1, LUA_TTABLE); | ||
518 | luaL_check_type(L, 2, LUA_TFUNCTION); | ||
519 | n = lua_getn(L, 1); | ||
520 | for (i=1; i<=n; i++) { | ||
521 | lua_pushvalue(L, 2); /* function */ | ||
522 | lua_pushnumber(L, i); /* 1st argument */ | ||
523 | lua_rawgeti(L, 1, i); /* 2nd argument */ | ||
524 | lua_rawcall(L, 2, 1); | ||
525 | if (!lua_isnil(L, -1)) | ||
526 | return 1; | ||
527 | lua_pop(L, 1); /* remove nil result */ | ||
528 | } | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | |||
533 | static int luaB_foreach (lua_State *L) { | ||
534 | luaL_check_type(L, 1, LUA_TTABLE); | ||
535 | luaL_check_type(L, 2, LUA_TFUNCTION); | ||
536 | lua_pushnil(L); /* first key */ | ||
537 | for (;;) { | ||
538 | if (lua_next(L, 1) == 0) | ||
539 | return 0; | ||
540 | lua_pushvalue(L, 2); /* function */ | ||
541 | lua_pushvalue(L, -3); /* key */ | ||
542 | lua_pushvalue(L, -3); /* value */ | ||
543 | lua_rawcall(L, 2, 1); | ||
544 | if (!lua_isnil(L, -1)) | ||
545 | return 1; | ||
546 | lua_pop(L, 2); /* remove value and result */ | ||
547 | } | ||
548 | } | ||
549 | |||
550 | |||
551 | static void aux_setn (lua_State *L, int t, int n) { | ||
552 | lua_pushliteral(L, "n"); | ||
553 | lua_pushnumber(L, n); | ||
554 | lua_rawset(L, t); | ||
555 | } | ||
556 | |||
557 | |||
558 | static int luaB_getn (lua_State *L) { | ||
559 | luaL_check_type(L, 1, LUA_TTABLE); | ||
560 | lua_pushnumber(L, lua_getn(L, 1)); | ||
561 | return 1; | ||
562 | } | ||
563 | |||
564 | |||
565 | static int luaB_tinsert (lua_State *L) { | ||
566 | int v = lua_gettop(L); /* number of arguments */ | ||
567 | int n, pos; | ||
568 | luaL_check_type(L, 1, LUA_TTABLE); | ||
569 | n = lua_getn(L, 1); | ||
570 | if (v == 2) /* called with only 2 arguments */ | ||
571 | pos = n+1; | ||
572 | else { | ||
573 | v = 3; /* function may be called with more than 3 args */ | ||
574 | pos = luaL_check_int(L, 2); /* 2nd argument is the position */ | ||
575 | } | ||
576 | if (pos > n+1) n = pos-1; | ||
577 | aux_setn(L, 1, n+1); /* t.n = n+1 */ | ||
578 | for (; n>=pos; n--) { | ||
579 | lua_rawgeti(L, 1, n); | ||
580 | lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ | ||
581 | } | ||
582 | lua_pushvalue(L, v); | ||
583 | lua_rawseti(L, 1, pos); /* t[pos] = v */ | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | |||
588 | static int luaB_tremove (lua_State *L) { | ||
589 | int pos, n; | ||
590 | luaL_check_type(L, 1, LUA_TTABLE); | ||
591 | n = lua_getn(L, 1); | ||
592 | pos = luaL_opt_int(L, 2, n); | ||
593 | if (n <= 0) return 0; /* table is `empty' */ | ||
594 | aux_setn(L, 1, n-1); /* t.n = n-1 */ | ||
595 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ | ||
596 | for ( ;pos<n; pos++) { | ||
597 | lua_rawgeti(L, 1, pos+1); | ||
598 | lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */ | ||
599 | } | ||
600 | lua_pushnil(L); | ||
601 | lua_rawseti(L, 1, n); /* t[n] = nil */ | ||
602 | return 1; | ||
603 | } | ||
604 | |||
605 | |||
606 | |||
607 | /* | ||
608 | ** {====================================================== | ||
609 | ** Quicksort | ||
610 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; | ||
611 | ** Addison-Wesley, 1993.) | ||
612 | */ | ||
613 | |||
614 | |||
615 | static void set2 (lua_State *L, int i, int j) { | ||
616 | lua_rawseti(L, 1, i); | ||
617 | lua_rawseti(L, 1, j); | ||
618 | } | ||
619 | |||
620 | static int sort_comp (lua_State *L, int a, int b) { | ||
621 | /* WARNING: the caller (auxsort) must ensure stack space */ | ||
622 | if (!lua_isnoneornil(L, 2)) { /* function? */ | ||
623 | int res; | ||
624 | lua_pushvalue(L, 2); | ||
625 | lua_pushvalue(L, a-1); /* -1 to compensate function */ | ||
626 | lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ | ||
627 | lua_rawcall(L, 2, 1); | ||
628 | res = lua_toboolean(L, -1); | ||
629 | lua_pop(L, 1); | ||
630 | return res; | ||
631 | } | ||
632 | else /* a < b? */ | ||
633 | return lua_lessthan(L, a, b); | ||
634 | } | ||
635 | |||
636 | static void auxsort (lua_State *L, int l, int u) { | ||
637 | while (l < u) { /* for tail recursion */ | ||
638 | int i, j; | ||
639 | /* sort elements a[l], a[(l+u)/2] and a[u] */ | ||
640 | lua_rawgeti(L, 1, l); | ||
641 | lua_rawgeti(L, 1, u); | ||
642 | if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ | ||
643 | set2(L, l, u); /* swap a[l] - a[u] */ | ||
644 | else | ||
645 | lua_pop(L, 2); | ||
646 | if (u-l == 1) break; /* only 2 elements */ | ||
647 | i = (l+u)/2; | ||
648 | lua_rawgeti(L, 1, i); | ||
649 | lua_rawgeti(L, 1, l); | ||
650 | if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ | ||
651 | set2(L, i, l); | ||
652 | else { | ||
653 | lua_pop(L, 1); /* remove a[l] */ | ||
654 | lua_rawgeti(L, 1, u); | ||
655 | if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ | ||
656 | set2(L, i, u); | ||
657 | else | ||
658 | lua_pop(L, 2); | ||
659 | } | ||
660 | if (u-l == 2) break; /* only 3 elements */ | ||
661 | lua_rawgeti(L, 1, i); /* Pivot */ | ||
662 | lua_pushvalue(L, -1); | ||
663 | lua_rawgeti(L, 1, u-1); | ||
664 | set2(L, i, u-1); | ||
665 | /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ | ||
666 | i = l; j = u-1; | ||
667 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | ||
668 | /* repeat ++i until a[i] >= P */ | ||
669 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { | ||
670 | if (i>u) lua_error(L, "invalid order function for sorting"); | ||
671 | lua_pop(L, 1); /* remove a[i] */ | ||
672 | } | ||
673 | /* repeat --j until a[j] <= P */ | ||
674 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { | ||
675 | if (j<l) lua_error(L, "invalid order function for sorting"); | ||
676 | lua_pop(L, 1); /* remove a[j] */ | ||
677 | } | ||
678 | if (j<i) { | ||
679 | lua_pop(L, 3); /* pop pivot, a[i], a[j] */ | ||
680 | break; | ||
681 | } | ||
682 | set2(L, i, j); | ||
683 | } | ||
684 | lua_rawgeti(L, 1, u-1); | ||
685 | lua_rawgeti(L, 1, i); | ||
686 | set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | ||
687 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ | ||
688 | /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ | ||
689 | if (i-l < u-i) { | ||
690 | j=l; i=i-1; l=i+2; | ||
691 | } | ||
692 | else { | ||
693 | j=i+1; i=u; u=j-2; | ||
694 | } | ||
695 | auxsort(L, j, i); /* call recursively the smaller one */ | ||
696 | } /* repeat the routine for the larger one */ | ||
697 | } | ||
698 | |||
699 | static int luaB_sort (lua_State *L) { | ||
700 | int n; | ||
701 | luaL_check_type(L, 1, LUA_TTABLE); | ||
702 | n = lua_getn(L, 1); | ||
703 | if (!lua_isnone(L, 2)) /* is there a 2nd argument? */ | ||
704 | luaL_check_type(L, 2, LUA_TFUNCTION); | ||
705 | lua_settop(L, 2); /* make sure there is two arguments */ | ||
706 | auxsort(L, 1, n); | ||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | /* }====================================================== */ | ||
711 | |||
712 | |||
713 | static const luaL_reg array_funcs[] = { | ||
714 | {"foreach", luaB_foreach}, | ||
715 | {"foreachi", luaB_foreachi}, | ||
716 | {"getn", luaB_getn}, | ||
717 | {"sort", luaB_sort}, | ||
718 | {"insert", luaB_tinsert}, | ||
719 | {"remove", luaB_tremove}, | ||
720 | {NULL, NULL} | ||
721 | }; | ||
722 | |||
723 | /* }====================================================== */ | ||
724 | |||
725 | |||
726 | |||
727 | LUALIB_API int lua_baselibopen (lua_State *L) { | 435 | LUALIB_API int lua_baselibopen (lua_State *L) { |
728 | base_open(L); | 436 | base_open(L); |
729 | co_open(L); | ||
730 | luaL_opennamedlib(L, "tab", array_funcs, 0); | ||
731 | /* `require' needs an empty table as upvalue */ | 437 | /* `require' needs an empty table as upvalue */ |
732 | lua_newtable(L); | 438 | lua_newtable(L); |
733 | lua_pushcclosure(L, luaB_require, 1); | 439 | lua_pushcclosure(L, luaB_require, 1); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.c,v 1.80 2002/04/01 14:42:33 roberto Exp roberto $ | 2 | ** $Id: lua.c,v 1.81 2002/04/05 18:54:31 roberto Exp roberto $ |
3 | ** Lua stand-alone interpreter | 3 | ** Lua stand-alone interpreter |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -342,6 +342,7 @@ static void register_getargs (char *argv[]) { | |||
342 | 342 | ||
343 | static void openstdlibs (lua_State *l) { | 343 | static void openstdlibs (lua_State *l) { |
344 | lua_baselibopen(l); | 344 | lua_baselibopen(l); |
345 | lua_tablibopen(l); | ||
345 | lua_iolibopen(l); | 346 | lua_iolibopen(l); |
346 | lua_strlibopen(l); | 347 | lua_strlibopen(l); |
347 | lua_mathlibopen(l); | 348 | lua_mathlibopen(l); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lualib.h,v 1.20 2001/03/06 20:09:38 roberto Exp roberto $ | 2 | ** $Id: lualib.h,v 1.21 2001/03/26 14:31:49 roberto Exp roberto $ |
3 | ** Lua standard libraries | 3 | ** Lua standard libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -19,6 +19,7 @@ | |||
19 | #define LUA_ALERT "_ALERT" | 19 | #define LUA_ALERT "_ALERT" |
20 | 20 | ||
21 | LUALIB_API int lua_baselibopen (lua_State *L); | 21 | LUALIB_API int lua_baselibopen (lua_State *L); |
22 | LUALIB_API int lua_tablibopen (lua_State *L); | ||
22 | LUALIB_API int lua_iolibopen (lua_State *L); | 23 | LUALIB_API int lua_iolibopen (lua_State *L); |
23 | LUALIB_API int lua_strlibopen (lua_State *L); | 24 | LUALIB_API int lua_strlibopen (lua_State *L); |
24 | LUALIB_API int lua_mathlibopen (lua_State *L); | 25 | LUALIB_API int lua_mathlibopen (lua_State *L); |