1 /* Copyright(C) 2006-2007 Brazil
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Lesser General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Lesser General Public License for more details.
13 You should have received a copy of the GNU Lesser General Public
14 License along with this library; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 /* Senna Query Language is based on Mini-Scheme, original credits follow */
21 * ---------- Mini-Scheme Interpreter Version 0.85 ----------
23 * coded by Atsushi Moriwaki (11/5/1989)
25 * E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
27 * THIS SOFTWARE IS IN THE PUBLIC DOMAIN
28 * ------------------------------------
29 * This software is completely free to copy, modify and/or re-distribute.
30 * But I would appreciate it if you left my name on the code as the author.
35 * This version has been modified by R.C. Secrist.
37 * Mini-Scheme is now maintained by Akira KIDA.
39 * This is a revised and modified version by Akira KIDA.
40 * current version is 0.85k4 (15 May 1994)
42 * Please send suggestions, bug reports and/or requests to:
43 * <SDI00379@niftyserve.or.jp>
51 #include <sys/types.h>
54 #define InitFile "init.scm"
56 /* global variables */
58 sen_obj *sen_ql_nil; /* special cell representing empty cell */
59 sen_obj *sen_ql_t; /* special cell representing #t */
60 sen_obj *sen_ql_f; /* special cell representing #f */
62 /* sen query language */
64 /* todo : update set-car! set-cdr!
69 if (o->nrefs < 0xffff) { o->nrefs++; }
70 if (PAIRP(o)) { // todo : check cycle
71 if (CAR(o) != NIL) { obj_ref(CAR(o)); }
72 if (CDR(o) != NIL) { obj_ref(CDR(o)); }
80 SEN_LOG(sen_log_error, "o->nrefs corrupt");
83 if (o->nrefs < 0xffff) { o->nrefs--; }
84 if (PAIRP(o)) { // todo : check cycle
85 if (CAR(o) != NIL) { obj_unref(CAR(o)); }
86 if (CDR(o) != NIL) { obj_unref(CDR(o)); }
91 rplaca(sen_ctx *ctx, sen_obj *a, sen_obj *b)
97 obj_unref(a->u.l.car);
99 if (b) { obj_ref(b); }
105 rplacd(sen_ctx *ctx, sen_obj *a, sen_obj *b)
111 obj_unref(a->u.l.cdr);
113 if (b) { obj_ref(b); }
121 sen_obj2int(sen_ctx *ctx, sen_obj *o)
123 sen_rc rc = sen_invalid_argument;
128 const char *end = o->u.b.value + o->u.b.size, *rest;
129 int64_t i = sen_atoll(o->u.b.value, end, &rest);
131 sen_obj_clear(ctx, o);
149 sen_ql_mk_symbol(sen_ctx *ctx, const char *name)
152 if (!sen_set_get(ctx->symbols, name, (void **) &x)) { return F; }
154 x->flags |= SEN_OBJ_SYMBOL;
155 x->type = sen_ql_void;
157 if (x->type == sen_ql_void && ctx->db) {
158 sen_db_store *slot = sen_db_store_open(ctx->db, SYMNAME(x));
159 if (slot) { sen_ql_bind_symbol(slot, x); }
165 sen_ql_at(sen_ctx *ctx, const char *key)
168 if (!sen_set_at(ctx->symbols, key, (void **) &o)) {
175 sen_ql_def_native_func(sen_ctx *ctx, const char *name, sen_ql_native_func *func)
177 sen_obj *o = INTERN(name);
179 o->type = sen_ql_void;
180 o->flags |= SEN_OBJ_NATIVE;
186 sen_ctx_igc(sen_ctx *ctx)
191 for (i = ctx->lseqno; i != ctx->seqno; i++) {
192 if ((ep = sen_set_at(ctx->objects, &i, (void **) &o))) {
195 (BULKP(o) && (o->flags & SEN_OBJ_ALLOCATED)))) { continue; }
196 sen_obj_clear(ctx, o);
197 sen_set_del(ctx->objects, ep);
200 ctx->lseqno = ctx->seqno;
204 #define MARKP(p) ((p)->flags & SEN_OBJ_MARKED)
205 #define REFERERP(p) ((p)->flags & SEN_OBJ_REFERER)
206 #define SETREFERER(p) ((p)->flags |= SEN_OBJ_REFERER)
207 #define UNSETREFERER(p) ((p)->flags &= ~SEN_OBJ_REFERER)
210 * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
211 * sec.3.5) for marking.
214 obj_mark(sen_ctx *ctx, sen_obj *o)
219 // if (MARKP(o)) { return; }
221 p->flags |= SEN_OBJ_MARKED;
222 // if (!o->nrefs) { SEN_LOG(sen_log_error, "obj->nrefs corrupt"); }
223 if (BULKP(o) && !(o->flags & SEN_OBJ_ALLOCATED)) {
224 char *b = SEN_MALLOC(o->u.b.size + 1);
226 memcpy(b, o->u.b.value, o->u.b.size);
227 b[o->u.b.size] = '\0';
229 o->flags |= SEN_OBJ_ALLOCATED;
232 if (!REFERERP(p)) { goto E6; }
234 if (q && !MARKP(q)) {
243 if (q && !MARKP(q)) {
267 sen_ctx_mgc(sen_ctx *ctx)
271 if (!(sc = sen_set_cursor_open(ctx->symbols))) { return sen_memory_exhausted; }
274 while (sen_set_cursor_next(sc, NULL, (void **) &o)) { obj_mark(o); }
275 sen_set_cursor_close(sc);
278 obj_mark(ctx, ctx->global_env);
280 /* mark current registers */
281 obj_mark(ctx, ctx->args);
282 obj_mark(ctx, ctx->envir);
283 obj_mark(ctx, ctx->code);
284 obj_mark(ctx, ctx->dump);
285 obj_mark(ctx, ctx->value);
286 obj_mark(ctx, ctx->phs);
288 if (!(sc = sen_set_cursor_open(ctx->objects))) { return sen_memory_exhausted; }
292 while ((ep = sen_set_cursor_next(sc, NULL, (void **) &o))) {
293 if (o->flags & SEN_OBJ_MARKED) {
294 o->flags &= ~SEN_OBJ_MARKED;
296 sen_obj_clear(ctx, o);
297 sen_set_del(ctx->objects, ep);
301 sen_set_cursor_close(sc);
302 ctx->lseqno = ctx->seqno;
308 inline static void Eval_Cycle(sen_ctx *ctx);
310 /* ========== Evaluation Cycle ========== */
315 OP_T0LVL = SEN_OP_T0LVL,
316 OP_ERR0 = SEN_OP_ERR0,
383 sen_ql_feed(sen_ctx *ctx, char *str, uint32_t str_size, int mode)
385 if (SEN_QL_WAITINGP(ctx)) {
386 SEN_RBUF_REWIND(&ctx->outbuf);
387 SEN_RBUF_REWIND(&ctx->subbuf);
392 case SEN_QL_TOPLEVEL :
393 ctx->co.mode &= ~SEN_CTX_HEAD;
396 case SEN_QL_WAIT_EXPR :
399 ctx->str_end = str + str_size;
402 case SEN_QL_WAIT_ARG :
404 if ((mode & SEN_CTX_HEAD)) {
406 ctx->str_end = str + str_size;
409 sen_obj *ph = CAR(ctx->phs);
410 if (!(buf = SEN_MALLOC(str_size + 1))) {
413 memcpy(buf, str, str_size);
414 buf[str_size] = '\0';
415 ph->flags |= SEN_OBJ_ALLOCATED;
417 ph->u.b.size = str_size;
418 ctx->phs = CDR(ctx->phs);
420 if ((ctx->phs == NIL) || (mode & (SEN_CTX_HEAD|SEN_CTX_TAIL))) {
421 ctx->stat = SEN_QL_EVAL;
427 case SEN_QL_WAIT_DATA :
429 if ((mode & SEN_CTX_HEAD)) {
432 ctx->str_end = str + str_size;
434 ctx->arg.u.b.value = str;
435 ctx->arg.u.b.size = str_size;
436 ctx->arg.type = sen_ql_bulk;
437 ctx->args = &ctx->arg;
441 SEN_ASSERT(ctx->co.func);
442 ctx->value = ctx->co.func(ctx, ctx->args, &ctx->co);
443 if (ERRP(ctx, SEN_ERROR)) { ctx->stat = SEN_QL_QUITTING; return F; }
445 if (ctx->co.last && !(ctx->co.mode & (SEN_CTX_HEAD|SEN_CTX_TAIL))) {
446 ctx->stat = SEN_QL_WAIT_DATA;
452 case SEN_QL_QUITTING:
455 if (ERRP(ctx, SEN_ERROR)) { ctx->stat = SEN_QL_QUITTING; return F; }
456 if (SEN_QL_WAITINGP(ctx)) { /* waiting input data */
458 SEN_FREE(ctx->inbuf);
463 if ((ctx->stat & 0x40) && SEN_QL_GET_MODE(ctx) == sen_ql_step) {
470 /**** sexp parser ****/
472 typedef sen_obj cell;
475 skipline(sen_ctx *ctx)
477 while (ctx->cur < ctx->str_end) {
478 if (*ctx->cur++ == '\n') { break; }
482 /*************** scheme interpreter ***************/
484 # define BACKQUOTE '`'
489 /* macros for cell operations */
490 #define HASPROP(p) ((p)->flags & SEN_OBJ_SYMBOL)
491 #define SYMPROP(p) CDR(p)
492 #define SYNTAXP(p) ((p)->type == sen_ql_syntax)
493 #define PROCP(p) ((p)->type == sen_ql_proc)
494 #define SYNTAXNAME(p) SYMNAME(p)
495 #define SYNTAXNUM(p) ((p)->class)
496 #define PROCNUM(p) IVALUE(p)
497 #define CLOSUREP(p) ((p)->type == sen_ql_closure)
498 #define MACROP(p) ((p)->flags & SEN_OBJ_MACRO)
499 #define CLOSURE_CODE(p) CAR(p)
500 #define CLOSURE_ENV(p) CDR(p)
501 #define CONTINUATIONP(p) ((p)->type == sen_ql_continuation)
502 #define CONT_DUMP(p) CDR(p)
503 #define PROMISEP(p) ((p)->flags & SEN_OBJ_PROMISE)
504 #define SETPROMISE(p) (p)->flags |= SEN_OBJ_PROMISE
505 #define LAMBDA (INTERN("lambda"))
506 #define QUOTE (INTERN("quote"))
507 #define QQUOTE (INTERN("quasiquote"))
508 #define UNQUOTE (INTERN("unquote"))
509 #define UNQUOTESP (INTERN("unquote-splicing"))
511 /* get new cell. parameter a, b is marked by gc. */
512 #define GET_CELL(ctx,a,b,o) SEN_OBJ_NEW(ctx, o)
514 /* get number atom */
516 mk_number(sen_ctx *ctx, int64_t num)
526 sen_ql_mk_string(sen_ctx *ctx, const char *str, unsigned int len)
528 cell *x = sen_obj_alloc(ctx, len);
529 if (!x) { return F; }
530 memcpy(x->u.b.value, str, len);
531 x->u.b.value[len] = '\0';
536 mk_const_string(sen_ctx *ctx, const char *str)
541 x->type = sen_ql_bulk;
542 x->u.b.value = (char *)str;
543 x->u.b.size = strlen(str);
548 sen_ql_mk_symbol2(sen_ctx *ctx, const char *q, unsigned int len, int kwdp)
550 char buf[SEN_SYM_MAX_KEY_SIZE], *p = buf;
551 if (len + 1 >= SEN_SYM_MAX_KEY_SIZE) { QLERR("too long symbol"); }
552 if (kwdp) { *p++ = ':'; }
559 str2num(sen_ctx *ctx, char *str, unsigned int len)
561 const char *cur, *str_end = str + len;
562 int64_t i = sen_atoll(str, str_end, &cur);
563 if (cur == str_end) { return mk_number(ctx, i); }
564 if (cur != str) { /* todo : support #i notation */
565 char *end, buf0[128], *buf = len < 128 ? buf0 : SEN_MALLOC(len + 1);
568 memcpy(buf, str, len);
571 d = strtod(buf, &end);
572 if (!(len < 128)) { SEN_FREE(buf); }
573 if (!errno && buf + len == end) {
584 /* make symbol or number atom from string */
586 mk_atom(sen_ctx *ctx, char *str, unsigned int len, cell *v)
589 const char *cur, *last, *str_end = str + len;
590 if ((p = str2num(ctx, str, len)) != NIL) { return p; }
591 for (last = cur = str; cur < str_end; cur += len) {
592 if (!(len = sen_str_charlen_nonnull(cur, str_end, ctx->encoding))) { break; }
594 if (last < cur) { *vp = sen_ql_mk_symbol2(ctx, last, cur - last, str != last); }
595 v = CONS(v, CONS(NIL, NIL));
600 if (last < cur) { *vp = sen_ql_mk_symbol2(ctx, last, cur - last, str != last); }
606 mk_const(sen_ctx *ctx, char *name, unsigned int len)
611 /* todo : rewirte with sen_str_* functions */
615 } else if (*name == 'f') {
618 } else if (len > 1) {
619 if (*name == 'p' && name[1] == '<' && name[12] == '>') {/* #p (sen_ql_object) */
620 sen_id cls = sen_str_btoi(name + 2);
622 sen_id self = sen_str_btoi(name + 7);
624 cell * v = sen_ql_mk_obj(ctx, cls, self);
625 if (len > 13 && name[13] == '.') {
626 return mk_atom(ctx, name + 13, len - 13, v);
632 } else if (*name == ':' && name[1] == '<') {/* #: (sen_ql_time) */
636 tv.tv_sec = sen_atoi(name + 2, name + len, &cur);
637 if (cur >= name + len || *cur != '.') {
638 QLERR("illegal time format '%s'", name);
640 tv.tv_usec = sen_atoi(cur + 1, name + len, &cur);
641 if (cur >= name + len || *cur != '>') {
642 QLERR("illegal time format '%s'", name);
647 } else if (*name == 'o') {/* #o (octal) */
648 len = (len > 255) ? 255 : len - 1;
649 memcpy(tmp2, name + 1, len);
651 sprintf(tmp, "0%s", tmp2);
652 sscanf(tmp, "%Lo", &x);
653 return mk_number(ctx, x);
654 } else if (*name == 'd') { /* #d (decimal) */
655 sscanf(&name[1], "%Ld", &x);
656 return mk_number(ctx, x);
657 } else if (*name == 'x') { /* #x (hex) */
658 len = (len > 255) ? 255 : len - 1;
659 memcpy(tmp2, name + 1, len);
661 sprintf(tmp, "0x%s", tmp2);
662 sscanf(tmp, "%Lx", &x);
663 return mk_number(ctx, x);
670 sen_ctx_load(sen_ctx *ctx, const char *filename)
672 if (!filename) { filename = InitFile; }
673 ctx->args = CONS(mk_const_string(ctx, filename), NIL);
674 ctx->stat = SEN_QL_TOPLEVEL;
676 return sen_ql_feed(ctx, "init", 4, 0) == F ? sen_success : sen_internal_error;
679 /* ========== Routines for Reading ========== */
686 #define TOK_COMMENT 5
693 #define TOK_QUESTION 12
695 #define lparenp(c) ((c) == '(' || (c) == '[')
696 #define rparenp(c) ((c) == ')' || (c) == ']')
698 /* read chacters to delimiter */
700 readstr(sen_ctx *ctx, char **str, unsigned int *size)
703 for (start = end = ctx->cur;;) {
705 /* null check and length check */
706 if (!(len = sen_str_charlen_nonnull(end, ctx->str_end, ctx->encoding))) {
707 ctx->cur = ctx->str_end;
710 if (sen_isspace(end, ctx->encoding) ||
711 *end == ';' || lparenp(*end) || rparenp(*end)) {
717 if (start < end || ctx->cur < ctx->str_end) {
719 *size = (unsigned int)(end - start);
726 /* read string expression "xxx...xxx" */
728 readstrexp(sen_ctx *ctx, char **str, unsigned int *size)
730 char *start, *src, *dest;
731 for (start = src = dest = ctx->cur;;) {
733 /* null check and length check */
734 if (!(len = sen_str_charlen_nonnull(src, ctx->str_end, ctx->encoding))) {
735 ctx->cur = ctx->str_end;
738 *size = (unsigned int)(dest - start);
743 if (src[0] == '"' && len == 1) {
746 *size = (unsigned int)(dest - start);
748 } else if (src[0] == '\\' && src + 1 < ctx->str_end && len == 1) {
752 while (len--) { *dest++ = *src++; }
762 if (ctx->cur >= ctx->str_end) { return TOK_EOS; }
774 if (ctx->cur == ctx->str_end ||
775 sen_isspace(ctx->cur, ctx->encoding) ||
776 *ctx->cur == ';' || lparenp(*ctx->cur) || rparenp(*ctx->cur)) {
796 if (ctx->cur < ctx->str_end && *ctx->cur == '@') {
813 /* ========== Routines for Printing ========== */
814 #define ok_abbrev(x) (PAIRP(x) && CDR(x) == NIL)
817 sen_obj_inspect(sen_ctx *ctx, sen_obj *obj, sen_rbuf *buf, int flags)
820 SEN_RBUF_PUTS(buf, "NULL");
821 } else if (obj == NIL) {
822 SEN_RBUF_PUTS(buf, "()");
823 } else if (obj == T) {
824 SEN_RBUF_PUTS(buf, "#t");
825 } else if (obj == F) {
826 SEN_RBUF_PUTS(buf, "#f");
829 const char *sym = SYMNAME(obj);
831 if (flags & SEN_OBJ_INSPECT_SYM_AS_STR) {
832 sen_rbuf_str_esc(buf, (*sym == ':') ? sym + 1 : sym, -1, ctx->encoding);
834 SEN_RBUF_PUTS(buf, sym);
841 SEN_RBUF_PUTS(buf, SYMBOLP(obj) ? SYMNAME(obj) : "#<VOID>");
844 if (flags & SEN_OBJ_INSPECT_ESC) {
845 SEN_RBUF_PUTS(buf, "#p<");
846 sen_rbuf_itob(buf, obj->class);
847 sen_rbuf_itob(buf, obj->u.o.self);
848 SEN_RBUF_PUTC(buf, '>');
850 const char *key = _sen_obj_key(ctx, obj);
851 SEN_RBUF_PUTS(buf, key ? key : "");
855 SEN_RBUF_PUTS(buf, "#<SNIP>");
857 case sen_ql_records :
858 SEN_RBUF_PUTS(buf, "#<RECORDS>");
861 if (flags & SEN_OBJ_INSPECT_ESC) {
862 sen_rbuf_str_esc(buf, obj->u.b.value, obj->u.b.size, ctx->encoding);
864 sen_rbuf_write(buf, obj->u.b.value, obj->u.b.size);
868 sen_rbuf_lltoa(buf, IVALUE(obj));
871 sen_rbuf_ftoa(buf, FVALUE(obj));
874 SEN_RBUF_PUTS(buf, "#:<");
875 sen_rbuf_itoa(buf, obj->u.tv.tv_sec);
876 SEN_RBUF_PUTS(buf, ".");
877 sen_rbuf_itoa(buf, obj->u.tv.tv_usec);
878 SEN_RBUF_PUTC(buf, '>');
881 SEN_RBUF_PUTS(buf, "#<QUERY>");
884 SEN_RBUF_PUTS(buf, "#<OP>");
887 SEN_RBUF_PUTS(buf, "#<SYNTAX>");
890 SEN_RBUF_PUTS(buf, "#<PROCEDURE ");
891 sen_rbuf_itoa(buf, PROCNUM(obj));
892 SEN_RBUF_PUTS(buf, ">");
894 case sen_ql_closure :
896 SEN_RBUF_PUTS(buf, "#<MACRO>");
898 SEN_RBUF_PUTS(buf, "#<CLOSURE>");
901 case sen_ql_continuation :
902 SEN_RBUF_PUTS(buf, "#<CONTINUATION>");
904 case sen_db_raw_class :
905 SEN_RBUF_PUTS(buf, "#<RAW_CLASS>");
908 SEN_RBUF_PUTS(buf, "#<CLASS>");
910 case sen_db_obj_slot :
911 SEN_RBUF_PUTS(buf, "#<OBJ_SLOT>");
913 case sen_db_ra_slot :
914 SEN_RBUF_PUTS(buf, "#<RA_SLOT>");
916 case sen_db_ja_slot :
917 SEN_RBUF_PUTS(buf, "#<JA_SLOT>");
919 case sen_db_idx_slot :
920 SEN_RBUF_PUTS(buf, "#<IDX_SLOT>");
923 /* todo : detect loop */
924 if (CAR(obj) == QUOTE && ok_abbrev(CDR(obj))) {
925 SEN_RBUF_PUTC(buf, '\'');
926 sen_obj_inspect(ctx, CADR(obj), buf, flags);
927 } else if (CAR(obj) == QQUOTE && ok_abbrev(CDR(obj))) {
928 SEN_RBUF_PUTC(buf, '`');
929 sen_obj_inspect(ctx, CADR(obj), buf, flags);
930 } else if (CAR(obj) == UNQUOTE && ok_abbrev(CDR(obj))) {
931 SEN_RBUF_PUTC(buf, ',');
932 sen_obj_inspect(ctx, CADR(obj), buf, flags);
933 } else if (CAR(obj) == UNQUOTESP && ok_abbrev(CDR(obj))) {
934 SEN_RBUF_PUTS(buf, ",@");
935 sen_obj_inspect(ctx, CADR(obj), buf, flags);
937 SEN_RBUF_PUTC(buf, '(');
939 sen_obj_inspect(ctx, CAR(obj), buf, flags);
940 if ((obj = CDR(obj)) && (obj != NIL)) {
942 SEN_RBUF_PUTC(buf, ' ');
944 SEN_RBUF_PUTS(buf, " . ");
945 sen_obj_inspect(ctx, obj, buf, flags);
946 SEN_RBUF_PUTC(buf, ')');
950 SEN_RBUF_PUTC(buf, ')');
958 SEN_RBUF_PUTS(buf, SYMNAME(obj));
960 SEN_RBUF_PUTS(buf, "#<?(");
961 sen_rbuf_itoa(buf, obj->type);
962 SEN_RBUF_PUTS(buf, ")?>");
969 /* ========== Routines for Evaluation Cycle ========== */
971 /* make closure. c is code. e is environment */
973 mk_closure(sen_ctx *ctx, cell *c, cell *e)
976 GET_CELL(ctx, c, e, x);
977 x->type = sen_ql_closure;
978 x->flags = SEN_OBJ_REFERER;
984 /* make continuation. */
986 mk_continuation(sen_ctx *ctx, cell *d)
989 GET_CELL(ctx, NIL, d, x);
990 x->type = sen_ql_continuation;
991 x->flags = SEN_OBJ_REFERER;
996 /* reverse list -- make new cells */
998 reverse(sen_ctx *ctx, cell *a) /* a must be checked by gc */
1001 for ( ; PAIRP(a); a = CDR(a)) {
1002 p = CONS(CAR(a), p);
1003 if (ERRP(ctx, SEN_ERROR)) { return F; }
1008 /* reverse list --- no make new cells */
1009 inline static cell *
1010 non_alloc_rev(cell *term, cell *list)
1012 cell *p = list, *result = term, *q;
1022 /* append list -- make new cells */
1023 inline static cell *
1024 append(sen_ctx *ctx, cell *a, cell *b)
1028 a = reverse(ctx, a);
1029 if (ERRP(ctx, SEN_ERROR)) { return F; }
1040 /* equivalence of atoms */
1042 eqv(sen_obj *a, sen_obj *b)
1044 if (a == b) { return 1; }
1045 if (a->type != b->type) { return 0; }
1047 case sen_ql_object :
1048 return (a->class == b->class && a->u.o.self == b->u.o.self);
1051 return (a->u.b.size == b->u.b.size &&
1052 !memcmp(a->u.b.value, b->u.b.value, a->u.b.size));
1055 return (IVALUE(a) == IVALUE(b));
1058 return !islessgreater(FVALUE(a), FVALUE(b));
1061 return (!memcmp(&a->u.tv, &b->u.tv, sizeof(sen_timeval)));
1064 /* todo : support other types */
1070 /* true or false value macro */
1071 #define istrue(p) ((p) != NIL && (p) != F)
1072 #define isfalse(p) ((p) == F)
1074 /* control macros for Eval_Cycle */
1075 #define s_goto(ctx,a) do {\
1080 #define s_save(ctx,a,b,args) (\
1081 ctx->dump = CONS(ctx->envir, CONS((args), ctx->dump)),\
1082 ctx->dump = CONS((b), ctx->dump),\
1083 ctx->dump = CONS(mk_number(ctx, (int64_t)(a)), ctx->dump))
1085 #define s_return(ctx,a) do {\
1087 ctx->op = IVALUE(CAR(ctx->dump));\
1088 ctx->args = CADR(ctx->dump);\
1089 ctx->envir = CADDR(ctx->dump);\
1090 ctx->code = CADDDR(ctx->dump);\
1091 ctx->dump = CDDDDR(ctx->dump);\
1095 #define RTN_NIL_IF_HEAD(ctx) do {\
1096 if (((ctx)->co.mode & SEN_CTX_HEAD)) { s_goto(ctx, OP_T0LVL); }\
1099 #define RTN_NIL_IF_TAIL(ctx) do {\
1100 if (((ctx)->co.mode & SEN_CTX_TAIL)) { s_return((ctx), NIL); } else { return NIL; }\
1104 list_deep_copy(sen_ctx *ctx, cell *c) {
1105 /* NOTE: only list is copied */
1107 /* TODO: convert recursion to loop */
1108 return CONS(list_deep_copy(ctx, CAR(c)), list_deep_copy(ctx, CDR(c)));
1115 qquote_uquotelist(sen_ctx *ctx, cell *cl, cell *pcl, int level) {
1124 qquote_uquotelist(ctx, CDR(x), x, level - 1);
1126 CDR(ctx->args) = CONS(cl, CDR(ctx->args)); /* save (unquote ...) cell */
1128 } else if (y == UNQUOTESP) {
1130 qquote_uquotelist(ctx, CDR(x), x, level - 1);
1132 CDR(ctx->args) = CONS(pcl, CDR(ctx->args)); /* save pre (unquote-splicing) cell */
1135 qquote_uquotelist(ctx, x, cl, level);
1137 } else if (x == QQUOTE) {
1138 qquote_uquotelist(ctx, CDR(cl), cl, level + 1);
1141 if (!level && CADR(cl) == UNQUOTE) {
1142 CDR(ctx->args) = CONS(cl, CDR(ctx->args)); /* save (a . ,b) cell */
1150 #define GC_THRESHOLD 1000000
1152 inline static cell *
1155 register cell *x, *y;
1156 if (ctx->op == OP_T0LVL || ctx->objects->n_entries > ctx->ncells + GC_THRESHOLD) {
1157 if (ctx->gc_verbose) {
1159 sen_rbuf_init(&buf, 0);
1160 sen_obj_inspect(ctx, ctx->envir, &buf, SEN_OBJ_INSPECT_ESC);
1162 SEN_LOG(sen_log_notice, "mgc > ncells=%d envir=<%s>", ctx->objects->n_entries, buf.head);
1166 if (ctx->gc_verbose) {
1167 SEN_LOG(sen_log_notice, "mgc < ncells=%d", ctx->objects->n_entries);
1169 ctx->ncells = ctx->objects->n_entries;
1172 case OP_LOAD: /* load */
1173 if (BULKP(CAR(ctx->args))) {
1175 char *fname = STRVALUE(CAR(ctx->args));
1176 if (fname && !stat(fname, &st)) {
1177 if (ctx->inbuf) { SEN_FREE(ctx->inbuf); }
1178 if ((ctx->inbuf = SEN_MALLOC(st.st_size))) {
1180 if ((fd = open(fname, O_RDONLY)) != -1) {
1181 if (read(fd, ctx->inbuf, st.st_size) == st.st_size) {
1182 SEN_RBUF_PUTS(&ctx->outbuf, "loading ");
1183 SEN_RBUF_PUTS(&ctx->outbuf, STRVALUE(CAR(ctx->args)));
1184 ctx->cur = ctx->inbuf;
1185 ctx->str_end = ctx->inbuf + st.st_size;
1189 if (ctx->cur != ctx->inbuf) {
1190 SEN_FREE(ctx->inbuf);
1196 s_goto(ctx, OP_T0LVL);
1198 case OP_T0LVL: /* top level */
1200 ctx->envir = ctx->global_env;
1201 if (ctx->batchmode) {
1202 s_save(ctx, OP_T0LVL, NIL, NIL);
1204 s_save(ctx, OP_VALUEPRINT, NIL, NIL);
1206 s_save(ctx, OP_T1LVL, NIL, NIL);
1207 // if (infp == stdin) printf("hoge>\n");
1208 ctx->pht = &ctx->phs;
1210 s_goto(ctx, OP_READ);
1212 case OP_T1LVL: /* top level */
1214 if (ctx->phs != NIL &&
1215 !(ctx->co.mode & (SEN_CTX_HEAD|SEN_CTX_TAIL))) { RTN_NIL_IF_TAIL(ctx); }
1216 // SEN_RBUF_PUTC(&ctx->outbuf, '\n');
1217 ctx->code = ctx->value;
1218 s_goto(ctx, OP_EVAL);
1220 case OP_READ: /* read */
1221 RTN_NIL_IF_HEAD(ctx);
1222 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1223 s_goto(ctx, OP_RDSEXPR);
1225 case OP_VALUEPRINT: /* print evalution result */
1226 ctx->args = ctx->value;
1227 s_save(ctx, OP_T0LVL, NIL, NIL);
1228 sen_obj_inspect(ctx, ctx->args, &ctx->outbuf, SEN_OBJ_INSPECT_ESC);
1231 case OP_EVAL: /* main part of evalution */
1232 // fixme : quick hack.
1233 if (SYMBOLP(ctx->code)) { /* symbol */
1234 if (KEYWORDP(ctx->code)) { s_return(ctx, ctx->code); }
1235 for (x = ctx->envir; x != NIL; x = CDR(x)) {
1236 for (y = CAR(x); y != NIL; y = CDR(y))
1237 if (CAAR(y) == ctx->code)
1243 s_return(ctx, CDAR(y));
1245 if (PROCP(ctx->code)) { s_return(ctx, ctx->code); }
1246 if (NATIVE_FUNCP(ctx->code)) { s_return(ctx, ctx->code); }
1247 QLERR("Unbounded variable %s", SYMNAME(ctx->code));
1249 } else if (PAIRP(ctx->code)) {
1250 if (SYNTAXP(x = CAR(ctx->code))) { /* SYNTAX */
1251 ctx->code = CDR(ctx->code);
1252 s_goto(ctx, SYNTAXNUM(x));
1253 } else {/* first, eval top element and eval arguments */
1254 s_save(ctx, OP_E0ARGS, NIL, ctx->code);
1255 ctx->code = CAR(ctx->code);
1256 // if (NATIVE_FUNCP(ctx->code)) { s_return(ctx, ctx->code); } /* call native funcs. fast */
1257 s_goto(ctx, OP_EVAL);
1260 s_return(ctx, ctx->code);
1263 case OP_E0ARGS: /* eval arguments */
1264 if (MACROP(ctx->value)) { /* macro expansion */
1265 s_save(ctx, OP_DOMACRO, NIL, NIL);
1266 ctx->args = CONS(ctx->code, NIL);
1267 ctx->code = ctx->value;
1268 s_goto(ctx, OP_APPLY);
1270 ctx->code = CDR(ctx->code);
1271 s_goto(ctx, OP_E1ARGS);
1274 case OP_E1ARGS: /* eval arguments */
1275 ctx->args = CONS(ctx->value, ctx->args);
1276 if (PAIRP(ctx->code)) { /* continue */
1277 s_save(ctx, OP_E1ARGS, ctx->args, CDR(ctx->code));
1278 ctx->code = CAR(ctx->code);
1280 s_goto(ctx, OP_EVAL);
1282 ctx->args = non_alloc_rev(NIL, ctx->args);
1283 ctx->code = CAR(ctx->args);
1284 ctx->args = CDR(ctx->args);
1285 s_goto(ctx, OP_APPLY);
1288 case OP_APPLY: /* apply 'code' to 'args' */
1289 if (NATIVE_FUNCP(ctx->code)) {
1290 ctx->co.func = ctx->code->u.o.func;
1291 s_goto(ctx, OP_NATIVE);
1292 } else if (PROCP(ctx->code)) {
1293 s_goto(ctx, PROCNUM(ctx->code)); /* PROCEDURE */
1294 } else if (CLOSUREP(ctx->code)) { /* CLOSURE */
1295 /* make environment */
1296 ctx->envir = CONS(NIL, CLOSURE_ENV(ctx->code));
1297 for (x = CAR(CLOSURE_CODE(ctx->code)), y = ctx->args;
1298 PAIRP(x); x = CDR(x), y = CDR(y)) {
1300 QLERR("Few arguments");
1302 CAR(ctx->envir) = CONS(CONS(CAR(x), CAR(y)), CAR(ctx->envir));
1308 * QLERR("Many arguments");
1311 } else if (SYMBOLP(x))
1312 CAR(ctx->envir) = CONS(CONS(x, y), CAR(ctx->envir));
1314 QLERR("Syntax error in closure");
1316 ctx->code = CDR(CLOSURE_CODE(ctx->code));
1318 s_goto(ctx, OP_BEGIN);
1319 } else if (CONTINUATIONP(ctx->code)) { /* CONTINUATION */
1320 ctx->dump = CONT_DUMP(ctx->code);
1321 s_return(ctx, ctx->args != NIL ? CAR(ctx->args) : NIL);
1323 QLERR("Illegal function");
1326 case OP_DOMACRO: /* do macro */
1327 ctx->code = ctx->value;
1328 s_goto(ctx, OP_EVAL);
1330 case OP_LAMBDA: /* lambda */
1331 s_return(ctx, mk_closure(ctx, ctx->code, ctx->envir));
1333 case OP_QUOTE: /* quote */
1334 s_return(ctx, CAR(ctx->code));
1336 case OP_DEF0: /* define */
1337 if (PAIRP(CAR(ctx->code))) {
1338 x = CAAR(ctx->code);
1339 ctx->code = CONS(LAMBDA, CONS(CDAR(ctx->code), CDR(ctx->code)));
1342 ctx->code = CADR(ctx->code);
1345 QLERR("Variable is not symbol");
1347 s_save(ctx, OP_DEF1, NIL, x);
1348 s_goto(ctx, OP_EVAL);
1350 case OP_DEF1: /* define */
1351 for (x = CAR(ctx->envir); x != NIL; x = CDR(x))
1352 if (CAAR(x) == ctx->code)
1355 CDAR(x) = ctx->value;
1357 CAR(ctx->envir) = CONS(CONS(ctx->code, ctx->value), CAR(ctx->envir));
1358 s_return(ctx, ctx->code);
1360 case OP_SET0: /* set! */
1361 s_save(ctx, OP_SET1, NIL, CAR(ctx->code));
1362 ctx->code = CADR(ctx->code);
1363 s_goto(ctx, OP_EVAL);
1365 case OP_SET1: /* set! */
1366 for (x = ctx->envir; x != NIL; x = CDR(x)) {
1367 for (y = CAR(x); y != NIL; y = CDR(y))
1368 if (CAAR(y) == ctx->code)
1374 CDAR(y) = ctx->value;
1375 s_return(ctx, ctx->value);
1377 QLERR("Unbounded variable %s", SYMBOLP(ctx->code) ? SYMNAME(ctx->code) : "");
1380 case OP_BEGIN: /* begin */
1381 if (!PAIRP(ctx->code)) {
1382 s_return(ctx, ctx->code);
1384 if (CDR(ctx->code) != NIL) {
1385 s_save(ctx, OP_BEGIN, NIL, CDR(ctx->code));
1387 ctx->code = CAR(ctx->code);
1388 s_goto(ctx, OP_EVAL);
1390 case OP_IF0: /* if */
1391 s_save(ctx, OP_IF1, NIL, CDR(ctx->code));
1392 ctx->code = CAR(ctx->code);
1393 s_goto(ctx, OP_EVAL);
1395 case OP_IF1: /* if */
1396 if (istrue(ctx->value))
1397 ctx->code = CAR(ctx->code);
1399 ctx->code = CADR(ctx->code); /* (if #f 1) ==> () because
1401 s_goto(ctx, OP_EVAL);
1403 case OP_LET0: /* let */
1405 ctx->value = ctx->code;
1406 ctx->code = SYMBOLP(CAR(ctx->code)) ? CADR(ctx->code) : CAR(ctx->code);
1407 s_goto(ctx, OP_LET1);
1409 case OP_LET1: /* let (caluculate parameters) */
1410 ctx->args = CONS(ctx->value, ctx->args);
1411 if (PAIRP(ctx->code)) { /* continue */
1412 QLASSERT(LISTP(CAR(ctx->code)) && LISTP(CDAR(ctx->code)));
1413 s_save(ctx, OP_LET1, ctx->args, CDR(ctx->code));
1414 ctx->code = CADAR(ctx->code);
1416 s_goto(ctx, OP_EVAL);
1418 ctx->args = non_alloc_rev(NIL, ctx->args);
1419 ctx->code = CAR(ctx->args);
1420 ctx->args = CDR(ctx->args);
1421 s_goto(ctx, OP_LET2);
1424 case OP_LET2: /* let */
1425 ctx->envir = CONS(NIL, ctx->envir);
1426 for (x = SYMBOLP(CAR(ctx->code)) ? CADR(ctx->code) : CAR(ctx->code), y = ctx->args;
1427 y != NIL; x = CDR(x), y = CDR(y))
1428 CAR(ctx->envir) = CONS(CONS(CAAR(x), CAR(y)), CAR(ctx->envir));
1429 if (SYMBOLP(CAR(ctx->code))) { /* named let */
1430 for (x = CADR(ctx->code), ctx->args = NIL; PAIRP(x); x = CDR(x))
1431 ctx->args = CONS(CAAR(x), ctx->args);
1432 x = mk_closure(ctx, CONS(non_alloc_rev(NIL, ctx->args), CDDR(ctx->code)),
1434 CAR(ctx->envir) = CONS(CONS(CAR(ctx->code), x), CAR(ctx->envir));
1435 ctx->code = CDDR(ctx->code);
1438 ctx->code = CDR(ctx->code);
1441 s_goto(ctx, OP_BEGIN);
1443 case OP_LET0AST: /* let* */
1444 if (CAR(ctx->code) == NIL) {
1445 ctx->envir = CONS(NIL, ctx->envir);
1446 ctx->code = CDR(ctx->code);
1447 s_goto(ctx, OP_BEGIN);
1449 s_save(ctx, OP_LET1AST, CDR(ctx->code), CAR(ctx->code));
1450 QLASSERT(LISTP(CAR(ctx->code)) &&
1451 LISTP(CAAR(ctx->code)) && LISTP((CDR(CAAR(ctx->code)))));
1452 ctx->code = CADAAR(ctx->code);
1453 s_goto(ctx, OP_EVAL);
1455 case OP_LET1AST: /* let* (make new frame) */
1456 ctx->envir = CONS(NIL, ctx->envir);
1457 s_goto(ctx, OP_LET2AST);
1459 case OP_LET2AST: /* let* (caluculate parameters) */
1460 CAR(ctx->envir) = CONS(CONS(CAAR(ctx->code), ctx->value), CAR(ctx->envir));
1461 ctx->code = CDR(ctx->code);
1462 if (PAIRP(ctx->code)) { /* continue */
1463 QLASSERT(LISTP(CAR(ctx->code)) && LISTP(CDAR(ctx->code)));
1464 s_save(ctx, OP_LET2AST, ctx->args, ctx->code);
1465 ctx->code = CADAR(ctx->code);
1467 s_goto(ctx, OP_EVAL);
1469 ctx->code = ctx->args;
1471 s_goto(ctx, OP_BEGIN);
1474 case OP_LET0REC: /* letrec */
1475 ctx->envir = CONS(NIL, ctx->envir);
1477 ctx->value = ctx->code;
1478 ctx->code = CAR(ctx->code);
1479 s_goto(ctx, OP_LET1REC);
1481 case OP_LET1REC: /* letrec (caluculate parameters) */
1482 ctx->args = CONS(ctx->value, ctx->args);
1483 if (PAIRP(ctx->code)) { /* continue */
1484 QLASSERT(LISTP(CAR(ctx->code)) && LISTP(CDAR(ctx->code)));
1485 s_save(ctx, OP_LET1REC, ctx->args, CDR(ctx->code));
1486 ctx->code = CADAR(ctx->code);
1488 s_goto(ctx, OP_EVAL);
1490 ctx->args = non_alloc_rev(NIL, ctx->args);
1491 ctx->code = CAR(ctx->args);
1492 ctx->args = CDR(ctx->args);
1493 s_goto(ctx, OP_LET2REC);
1496 case OP_LET2REC: /* letrec */
1497 for (x = CAR(ctx->code), y = ctx->args; y != NIL; x = CDR(x), y = CDR(y))
1498 CAR(ctx->envir) = CONS(CONS(CAAR(x), CAR(y)), CAR(ctx->envir));
1499 ctx->code = CDR(ctx->code);
1501 s_goto(ctx, OP_BEGIN);
1503 case OP_COND0: /* cond */
1504 if (!PAIRP(ctx->code)) {
1505 QLERR("Syntax error in cond");
1507 s_save(ctx, OP_COND1, NIL, ctx->code);
1508 ctx->code = CAAR(ctx->code);
1509 s_goto(ctx, OP_EVAL);
1511 case OP_COND1: /* cond */
1512 if (istrue(ctx->value)) {
1513 if ((ctx->code = CDAR(ctx->code)) == NIL) {
1514 s_return(ctx, ctx->value);
1516 s_goto(ctx, OP_BEGIN);
1518 if ((ctx->code = CDR(ctx->code)) == NIL) {
1521 s_save(ctx, OP_COND1, NIL, ctx->code);
1522 ctx->code = CAAR(ctx->code);
1523 s_goto(ctx, OP_EVAL);
1527 case OP_DELAY: /* delay */
1528 x = mk_closure(ctx, CONS(NIL, ctx->code), ctx->envir);
1529 if (ERRP(ctx, SEN_ERROR)) { return F; }
1533 case OP_AND0: /* and */
1534 if (ctx->code == NIL) {
1537 s_save(ctx, OP_AND1, NIL, CDR(ctx->code));
1538 ctx->code = CAR(ctx->code);
1539 s_goto(ctx, OP_EVAL);
1541 case OP_AND1: /* and */
1542 if (isfalse(ctx->value)) {
1543 s_return(ctx, ctx->value);
1544 } else if (ctx->code == NIL) {
1545 s_return(ctx, ctx->value);
1547 s_save(ctx, OP_AND1, NIL, CDR(ctx->code));
1548 ctx->code = CAR(ctx->code);
1549 s_goto(ctx, OP_EVAL);
1552 case OP_OR0: /* or */
1553 if (ctx->code == NIL) {
1556 s_save(ctx, OP_OR1, NIL, CDR(ctx->code));
1557 ctx->code = CAR(ctx->code);
1558 s_goto(ctx, OP_EVAL);
1560 case OP_OR1: /* or */
1561 if (istrue(ctx->value)) {
1562 s_return(ctx, ctx->value);
1563 } else if (ctx->code == NIL) {
1564 s_return(ctx, ctx->value);
1566 s_save(ctx, OP_OR1, NIL, CDR(ctx->code));
1567 ctx->code = CAR(ctx->code);
1568 s_goto(ctx, OP_EVAL);
1571 case OP_C0STREAM: /* cons-stream */
1572 s_save(ctx, OP_C1STREAM, NIL, CDR(ctx->code));
1573 ctx->code = CAR(ctx->code);
1574 s_goto(ctx, OP_EVAL);
1576 case OP_C1STREAM: /* cons-stream */
1577 ctx->args = ctx->value; /* save ctx->value to register ctx->args for gc */
1578 x = mk_closure(ctx, CONS(NIL, ctx->code), ctx->envir);
1579 if (ERRP(ctx, SEN_ERROR)) { return F; }
1581 s_return(ctx, CONS(ctx->args, x));
1583 case OP_0MACRO: /* macro */
1585 ctx->code = CADR(ctx->code);
1587 QLERR("Variable is not symbol");
1589 s_save(ctx, OP_1MACRO, NIL, x);
1590 s_goto(ctx, OP_EVAL);
1592 case OP_1MACRO: /* macro */
1593 ctx->value->flags |= SEN_OBJ_MACRO;
1594 for (x = CAR(ctx->envir); x != NIL; x = CDR(x))
1595 if (CAAR(x) == ctx->code)
1598 CDAR(x) = ctx->value;
1600 CAR(ctx->envir) = CONS(CONS(ctx->code, ctx->value), CAR(ctx->envir));
1601 s_return(ctx, ctx->code);
1603 case OP_CASE0: /* case */
1604 s_save(ctx, OP_CASE1, NIL, CDR(ctx->code));
1605 ctx->code = CAR(ctx->code);
1606 s_goto(ctx, OP_EVAL);
1608 case OP_CASE1: /* case */
1609 for (x = ctx->code; x != NIL; x = CDR(x)) {
1610 if (!PAIRP(y = CAAR(x)))
1612 for ( ; y != NIL; y = CDR(y))
1613 if (eqv(CAR(y), ctx->value))
1619 if (PAIRP(CAAR(x))) {
1620 ctx->code = CDAR(x);
1621 s_goto(ctx, OP_BEGIN);
1623 s_save(ctx, OP_CASE2, NIL, CDAR(x));
1624 ctx->code = CAAR(x);
1625 s_goto(ctx, OP_EVAL);
1631 case OP_CASE2: /* case */
1632 if (istrue(ctx->value)) {
1633 s_goto(ctx, OP_BEGIN);
1637 case OP_PAPPLY: /* apply */
1638 ctx->code = CAR(ctx->args);
1639 ctx->args = CADR(ctx->args);
1640 s_goto(ctx, OP_APPLY);
1642 case OP_PEVAL: /* eval */
1643 ctx->code = CAR(ctx->args);
1645 s_goto(ctx, OP_EVAL);
1647 case OP_CONTINUATION: /* call-with-current-continuation */
1648 ctx->code = CAR(ctx->args);
1649 ctx->args = CONS(mk_continuation(ctx, ctx->dump), NIL);
1650 s_goto(ctx, OP_APPLY);
1652 case OP_SETCAR: /* set-car! */
1653 if (PAIRP(CAR(ctx->args))) {
1654 CAAR(ctx->args) = CADR(ctx->args);
1655 s_return(ctx, CAR(ctx->args));
1657 QLERR("Unable to set-car! for non-cons cell");
1660 case OP_SETCDR: /* set-cdr! */
1661 if (PAIRP(CAR(ctx->args))) {
1662 CDAR(ctx->args) = CADR(ctx->args);
1663 s_return(ctx, CAR(ctx->args));
1665 QLERR("Unable to set-cdr! for non-cons cell");
1668 case OP_FORCE: /* force */
1669 ctx->code = CAR(ctx->args);
1670 if (PROMISEP(ctx->code)) {
1672 s_goto(ctx, OP_APPLY);
1674 s_return(ctx, ctx->code);
1677 case OP_ERR0: /* error */
1678 SEN_RBUF_PUTS(&ctx->outbuf, "*** ERROR: ");
1679 SEN_RBUF_PUTS(&ctx->outbuf, ctx->errbuf);
1680 SEN_RBUF_PUTC(&ctx->outbuf, '\n');
1682 s_goto(ctx, OP_T0LVL);
1684 case OP_ERR1: /* error */
1685 SEN_RBUF_PUTS(&ctx->outbuf, "*** ERROR:");
1686 while (ctx->args != NIL) {
1687 SEN_RBUF_PUTC(&ctx->outbuf, ' ');
1688 sen_obj_inspect(ctx, CAR(ctx->args), &ctx->outbuf, SEN_OBJ_INSPECT_ESC);
1689 ctx->args = CDR(ctx->args);
1691 SEN_RBUF_PUTC(&ctx->outbuf, '\n');
1692 s_goto(ctx, OP_T0LVL);
1694 case OP_PUT: /* put */
1695 if (!HASPROP(CAR(ctx->args)) || !HASPROP(CADR(ctx->args))) {
1696 QLERR("Illegal use of put");
1698 for (x = SYMPROP(CAR(ctx->args)), y = CADR(ctx->args); x != NIL; x = CDR(x))
1702 CDAR(x) = CADDR(ctx->args);
1704 SYMPROP(CAR(ctx->args)) = CONS(CONS(y, CADDR(ctx->args)),
1705 SYMPROP(CAR(ctx->args)));
1708 case OP_GET: /* get */
1709 if (!HASPROP(CAR(ctx->args)) || !HASPROP(CADR(ctx->args))) {
1710 QLERR("Illegal use of get");
1712 for (x = SYMPROP(CAR(ctx->args)), y = CADR(ctx->args); x != NIL; x = CDR(x))
1716 s_return(ctx, CDAR(x));
1721 case OP_SDOWN: /* shutdown */
1722 SEN_LOG(sen_log_notice, "shutting down..");
1723 sen_gctx.stat = SEN_CTX_QUIT;
1724 s_goto(ctx, OP_QUIT);
1730 RTN_NIL_IF_HEAD(ctx);
1734 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1735 s_goto(ctx, OP_RDSEXPR);
1737 if ((tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1739 if (ctx->tok == TOK_RPAREN) {
1741 } else if (ctx->tok == TOK_DOT) {
1742 QLERR("syntax error: illegal dot expression");
1744 s_save(ctx, OP_RDLIST, NIL, NIL);
1745 s_goto(ctx, OP_RDSEXPR);
1748 s_save(ctx, OP_RDQUOTE, NIL, NIL);
1749 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1750 s_goto(ctx, OP_RDSEXPR);
1752 s_save(ctx, OP_RDQQUOTE, NIL, NIL);
1753 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1754 s_goto(ctx, OP_RDSEXPR);
1756 s_save(ctx, OP_RDUNQUOTE, NIL, NIL);
1757 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1758 s_goto(ctx, OP_RDSEXPR);
1760 s_save(ctx, OP_RDUQTSP, NIL, NIL);
1761 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1762 s_goto(ctx, OP_RDSEXPR);
1764 if (readstr(ctx, &str, &len) == TOK_EOS) { ctx->tok = TOK_EOS; RTN_NIL_IF_TAIL(ctx); }
1765 s_return(ctx, mk_atom(ctx, str, len, NIL));
1767 if (readstrexp(ctx, &str, &len) == TOK_EOS) {
1768 QLERR("unterminated string");
1770 s_return(ctx, sen_ql_mk_string(ctx, str, len));
1772 if ((readstr(ctx, &str, &len) == TOK_EOS) ||
1773 (x = mk_const(ctx, str, len)) == NIL) {
1774 QLERR("Undefined sharp expression");
1779 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1780 s_goto(ctx, OP_RDSEXPR);
1784 SEN_OBJ_NEW(ctx, o);
1786 o->type = sen_ql_bulk;
1795 QLERR("syntax error: illegal token");
1801 RTN_NIL_IF_HEAD(ctx);
1802 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1803 if (ctx->tok == TOK_COMMENT) {
1805 s_goto(ctx, OP_RDLIST);
1807 ctx->args = CONS(ctx->value, ctx->args);
1808 if (ctx->tok == TOK_RPAREN) {
1809 cell *v = non_alloc_rev(NIL, ctx->args);
1810 if (ctx->cur < ctx->str_end && *ctx->cur == '.') {
1813 if (readstr(ctx, &str, &len) != TOK_ATOM) { /* error */ }
1814 s_return(ctx, mk_atom(ctx, str, len, v));
1818 } else if (ctx->tok == TOK_DOT) {
1819 s_save(ctx, OP_RDDOT, ctx->args, NIL);
1820 if ((ctx->tok = token(ctx)) == TOK_EOS) {
1821 ctx->op = OP_RDSEXPR; RTN_NIL_IF_TAIL(ctx);
1823 s_goto(ctx, OP_RDSEXPR);
1825 s_save(ctx, OP_RDLIST, ctx->args, NIL);;
1826 s_goto(ctx, OP_RDSEXPR);
1830 RTN_NIL_IF_HEAD(ctx);
1831 if ((ctx->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
1832 if (ctx->tok != TOK_RPAREN) {
1833 QLERR("syntax error: illegal dot expression");
1835 cell *v = non_alloc_rev(ctx->value, ctx->args);
1836 if (ctx->cur < ctx->str_end && *ctx->cur == '.') {
1839 if (readstr(ctx, &str, &len) != TOK_ATOM) { /* error */ }
1840 s_return(ctx, mk_atom(ctx, str, len, v));
1847 s_return(ctx, CONS(QUOTE, CONS(ctx->value, NIL)));
1850 s_return(ctx, CONS(QQUOTE, CONS(ctx->value, NIL)));
1853 s_return(ctx, CONS(UNQUOTE, CONS(ctx->value, NIL)));
1856 s_return(ctx, CONS(UNQUOTESP, CONS(ctx->value, NIL)));
1859 s_return(ctx, ctx->value);
1861 ctx->code = list_deep_copy(ctx, ctx->code);
1862 ctx->args = CONS(ctx->code, NIL);
1863 qquote_uquotelist(ctx, ctx->code, ctx->code, 0);
1864 ctx->code = CDR(ctx->args);
1865 s_goto(ctx, OP_QQUOTE1);
1867 while (PAIRP(ctx->code)) {
1869 if (PAIRP(x) && LISTP(CDR(x))) {
1870 s_save(ctx, OP_QQUOTE2, ctx->args, ctx->code);
1873 QLASSERT(LISTP(CDDR(x)));
1874 ctx->code = CADDR(x);
1875 } else if (CAR(y) == UNQUOTESP) {
1876 QLASSERT(LISTP(CDR(y)));
1877 ctx->code = CADR(y);
1880 if (CAR(y) == UNQUOTE) {
1881 ctx->code = CADR(y);
1882 } else if (CAAR(y) == UNQUOTESP) {
1883 ctx->code = CADAR(y);
1888 s_goto(ctx, OP_EVAL);
1890 ctx->code = CDR(ctx->code);
1892 s_return(ctx, CAAR(ctx->args));
1897 CDR(x) = ctx->value;
1898 } else if (CAR(y) == UNQUOTESP) {
1899 if (ctx->value == NIL) {
1901 } else if (!PAIRP(ctx->value) ) {
1904 ctx->value = list_deep_copy(ctx, ctx->value);
1905 for (y = ctx->value; CDR(y) != NIL; y = CDR(y)) {}
1907 CDR(x) = ctx->value;
1912 CAR(x) = ctx->value;
1913 } else if (CAR(y) == UNQUOTESP) {
1914 if (ctx->value == NIL) {
1916 } else if (!PAIRP(ctx->value) ) {
1919 ctx->value = list_deep_copy(ctx, ctx->value);
1920 for (y = ctx->value; CDR(y) != NIL; y = CDR(y)) {}
1922 CAR(x) = ctx->value;
1928 ctx->code = CDR(ctx->code);
1929 s_goto(ctx, OP_QQUOTE1);
1931 SEN_LOG(sen_log_error, "illegal op (%d)", ctx->op);
1935 /* kernel of this intepreter */
1937 Eval_Cycle(sen_ctx *ctx)
1939 ctx->co.func = NULL;
1941 while (opexe(ctx) != NIL) {
1944 ctx->stat = SEN_QL_NATIVE;
1947 ctx->stat = SEN_QL_TOPLEVEL;
1950 ctx->stat = (ctx->phs != NIL) ? SEN_QL_WAIT_ARG : SEN_QL_EVAL;
1953 ctx->stat = SEN_QL_QUITTING;
1958 if (ERRP(ctx, SEN_ERROR)) { return; }
1960 ctx->stat = SEN_QL_WAIT_EXPR;
1964 sen_ql_eval(sen_ctx *ctx, sen_obj *code, sen_obj *objs)
1967 uint8_t op = ctx->op;
1968 uint8_t stat = ctx->stat;
1969 uint8_t feed_mode = ctx->feed_mode;
1970 sen_obj *o, *code_ = ctx->code;
1971 o = CONS(objs, ctx->envir);
1972 memcpy(&co, &ctx->co, sizeof(sen_ql_co));
1973 s_save(ctx, OP_QUIT, ctx->args, o);
1975 ctx->stat = SEN_QL_EVAL;
1977 ctx->feed_mode = sen_ql_atonce;
1978 sen_ql_feed(ctx, NULL, 0, 0);
1979 ctx->feed_mode = feed_mode;
1982 ctx->envir = CDR(o);
1984 memcpy(&ctx->co, &co, sizeof(sen_ql_co));
1988 /* ========== native functions ========== */
1990 #define s_retbool(tf) do { return (tf) ? T : F; } while (0)
1992 #define do_op(x,y,op) do {\
1993 switch ((x)->type) {\
1995 switch ((y)->type) {\
1997 IVALUE(x) = IVALUE(x) op IVALUE(y);\
1999 case sen_ql_float :\
2000 SETFLOAT(x, ((double) IVALUE(x)) op FVALUE(y));\
2003 if (sen_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
2004 IVALUE(x) = IVALUE(x) op IVALUE(y);\
2007 case sen_ql_float :\
2008 switch ((y)->type) {\
2010 FVALUE(x) = FVALUE(x) op IVALUE(y);\
2012 case sen_ql_float :\
2013 FVALUE(x) = FVALUE(x) op FVALUE(y);\
2016 if (sen_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
2017 FVALUE(x) = FVALUE(x) op IVALUE(y);\
2021 QLERR("can't convert into numeric");\
2025 #define do_compare(x,y,r,op) do {\
2030 r = (IVALUE(x) op IVALUE(y));\
2032 case sen_ql_float :\
2033 r = (IVALUE(x) op FVALUE(y));\
2036 if (sen_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
2037 r = (IVALUE(x) op IVALUE(y));\
2040 case sen_ql_float :\
2043 r = (FVALUE(x) op IVALUE(y));\
2045 case sen_ql_float :\
2046 r = (FVALUE(x) op FVALUE(y));\
2049 if (sen_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
2050 r = (FVALUE(x) op IVALUE(y));\
2054 if (y->type == sen_ql_bulk) {\
2056 uint32_t la = x->u.b.size, lb = y->u.b.size;\
2058 if (!(r_ = memcmp(x->u.b.value, y->u.b.value, lb))) {\
2062 if (!(r_ = memcmp(x->u.b.value, y->u.b.value, la))) {\
2063 r_ = la == lb ? 0 : -1;\
2068 QLERR("can't compare");\
2072 if (y->type == sen_ql_time) {\
2073 if (x->u.tv.tv_sec != y->u.tv.tv_sec) {\
2074 r = (x->u.tv.tv_sec op y->u.tv.tv_sec);\
2076 r = (x->u.tv.tv_usec op y->u.tv.tv_usec);\
2079 QLERR("can't compare");\
2082 r = (memcmp(&x->u.tv, &y->u.tv, sizeof(sen_timeval)) op 0);\
2086 #define time_op(x,y,v,op) {\
2090 double dv= x->u.tv.tv_sec op y->u.tv.tv_sec;\
2091 dv += (x->u.tv.tv_usec op y->u.tv.tv_usec) / 1000000.0;\
2098 int64_t sec = x->u.tv.tv_sec op IVALUE(y);\
2099 if (sec < INT32_MIN || INT32_MAX < sec) { QLERR("time val overflow"); }\
2100 tv.tv_sec = (int)sec;\
2101 tv.tv_usec = x->u.tv.tv_usec;\
2105 case sen_ql_float :\
2108 double sec = x->u.tv.tv_sec op (int)FVALUE(y);\
2109 int32_t usec = x->u.tv.tv_usec op (int)((FVALUE(y) - (int)FVALUE(y)) * 1000000);\
2110 if (sec < INT32_MIN || INT32_MAX < sec) { QLERR("time val overflow"); }\
2111 tv.tv_sec = (int)sec;\
2115 } else if (usec >= 1000000) {\
2124 QLERR("can't convert into numeric value");\
2130 nf_add(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2132 register cell *x, *v;
2133 if (!PAIRP(args)) { QLERR("list required"); }
2134 switch (CAR(args)->type) {
2138 sen_rbuf_init(&buf, 0);
2139 while (PAIRP(args)) {
2141 sen_obj_inspect(ctx, x, &buf, 0);
2143 SEN_RBUF2OBJ(ctx, &buf, v);
2147 if (PAIRP(CDR(args)) && NUMBERP(CADR(args))) {
2148 SEN_OBJ_NEW(ctx, v);
2149 time_op(CAR(args), CADR(args), v, +);
2151 QLERR("can't convert into numeric value");
2155 v = mk_number(ctx, 0);
2156 while (PAIRP(args)) {
2166 nf_sub(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2168 register cell *v = mk_number(ctx, 0);
2170 if (PAIRP(args) && CDR(args) != NIL) {
2171 if (CAR(args)->type == sen_ql_time) {
2172 time_op(CAR(args), CADR(args), v, -);
2178 while (PAIRP(args)) {
2186 nf_mul(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2188 register cell *v, *x;
2189 if (CAR(args)->type == sen_ql_bulk && CADR(args)->type == sen_ql_int) {
2190 int i, n = (int)IVALUE(CADR(args));
2192 sen_rbuf_init(&buf, 0);
2194 for (i = 0; i < n; i++) {
2195 sen_obj_inspect(ctx, x, &buf, 0);
2197 SEN_RBUF2OBJ(ctx, &buf, v);
2199 v = mk_number(ctx, 1);
2200 while (PAIRP(args)) {
2209 nf_div(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2213 if (PAIRP(args) && CDR(args) != NIL) {
2214 v = mk_number(ctx, 0);
2218 v = mk_number(ctx, 1);
2220 while (PAIRP(args)) {
2222 if (x->type == sen_ql_int && IVALUE(x) == 0 && v->type == sen_ql_int) {
2223 SETFLOAT(v, (double)IVALUE(v));
2230 nf_rem(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2235 if (sen_obj2int(ctx, CAR(x))) {
2236 QLERR("can't convert into integer");
2239 while (CDR(x) != NIL) {
2241 if (sen_obj2int(ctx, CAR(x))) {
2242 QLERR("can't convert into integer");
2244 if (IVALUE(CAR(x)) != 0)
2245 v %= IVALUE(CAR(x));
2247 QLERR("Divided by zero");
2250 return mk_number(ctx, v);
2253 nf_car(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2255 if (PAIRP(CAR(args))) {
2258 QLERR("Unable to car for non-cons cell");
2262 nf_cdr(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2264 if (PAIRP(CAR(args))) {
2267 QLERR("Unable to cdr for non-cons cell");
2271 nf_cons(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2273 CDR(args) = CADR(args);
2277 nf_not(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2279 s_retbool(isfalse(CAR(args)));
2282 nf_bool(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2284 s_retbool(CAR(args) == F || CAR(args) == T);
2287 nf_null(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2289 s_retbool(CAR(args) == NIL);
2292 nf_zerop(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2294 register cell *x = CAR(args);
2297 s_retbool(IVALUE(x) == 0);
2300 s_retbool(!(islessgreater(FVALUE(x), 0.0)));
2303 QLERR("can't convert into numeric value");
2307 nf_posp(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2309 register cell *x = CAR(args);
2312 s_retbool(IVALUE(x) > 0);
2315 s_retbool(!(isgreater(FVALUE(x), 0.0)));
2318 QLERR("can't convert into numeric value");
2322 nf_negp(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2324 register cell *x = CAR(args);
2327 s_retbool(IVALUE(x) < 0);
2330 s_retbool(!(isless(FVALUE(x), 0.0)));
2333 QLERR("can't convert into numeric value");
2337 nf_neq(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2340 register cell *x, *y;
2342 if (!PAIRP(args)) { QLERR("Few arguments"); }
2349 r = (IVALUE(x) == IVALUE(y));
2352 r = (IVALUE(x) <= FVALUE(y) && IVALUE(x) >= FVALUE(y));
2355 if (sen_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }
2356 r = (IVALUE(x) == IVALUE(y));
2362 r = (FVALUE(x) <= IVALUE(y) && FVALUE(x) >= IVALUE(y));
2365 r = (FVALUE(x) <= FVALUE(y) && FVALUE(x) >= FVALUE(y));
2368 if (sen_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }
2369 r = (FVALUE(x) <= IVALUE(y) && FVALUE(x) >= IVALUE(y));
2373 if (y->type == sen_ql_bulk) {
2375 uint32_t la = x->u.b.size, lb = y->u.b.size;
2377 if (!(r_ = memcmp(x->u.b.value, y->u.b.value, lb))) {
2381 if (!(r_ = memcmp(x->u.b.value, y->u.b.value, la))) {
2382 r_ = la == lb ? 0 : -1;
2387 QLERR("can't compare");
2391 if (y->type == sen_ql_time) {
2392 if (x->u.tv.tv_sec != y->u.tv.tv_sec) {
2393 r = (x->u.tv.tv_sec == y->u.tv.tv_sec);
2395 r = (x->u.tv.tv_usec == y->u.tv.tv_usec);
2398 QLERR("can't compare");
2401 r = (memcmp(&x->u.tv, &y->u.tv, sizeof(sen_timeval)) == 0);
2404 } while (PAIRP(args) && r);
2408 nf_less(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2411 register cell *x, *y;
2413 if (!PAIRP(args)) { QLERR("Few arguments"); }
2416 do_compare(x, y, r, <);
2418 } while (PAIRP(args) && r);
2422 nf_gre(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2425 register cell *x, *y;
2427 if (!PAIRP(args)) { QLERR("Few arguments"); }
2430 do_compare(x, y, r, >);
2432 } while (PAIRP(args) && r);
2436 nf_leq(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2439 register cell *x, *y;
2441 if (!PAIRP(args)) { QLERR("Few arguments"); }
2444 do_compare(x, y, r, <=);
2446 } while (PAIRP(args) && r);
2450 nf_geq(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2453 register cell *x, *y;
2455 if (!PAIRP(args)) { QLERR("Few arguments"); }
2458 do_compare(x, y, r, >=);
2460 } while (PAIRP(args) && r);
2464 nf_symbol(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2466 s_retbool(SYMBOLP(CAR(args)));
2469 nf_number(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2471 s_retbool(NUMBERP(CAR(args)));
2474 nf_string(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2476 s_retbool(BULKP(CAR(args)));
2479 nf_proc(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2482 * continuation should be procedure by the example
2483 * (call-with-current-continuation procedure?) ==> #t
2484 * in R^3 report sec. 6.9
2486 s_retbool(PROCP(CAR(args)) || CLOSUREP(CAR(args)) || CONTINUATIONP(CAR(args)));
2489 nf_pair(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2491 s_retbool(PAIRP(CAR(args)));
2494 nf_eq(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2496 s_retbool(CAR(args) == CADR(args));
2499 nf_eqv(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2501 s_retbool(eqv(CAR(args), CADR(args)));
2504 nf_write(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2507 sen_obj_inspect(ctx, args, &ctx->outbuf, SEN_OBJ_INSPECT_ESC);
2511 nf_display(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2514 sen_obj_inspect(ctx, args, &ctx->outbuf, 0);
2518 nf_newline(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2520 SEN_RBUF_PUTC(&ctx->outbuf, '\n');
2524 nf_reverse(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2526 return reverse(ctx, CAR(args));
2529 nf_append(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2531 return append(ctx, CAR(args), CADR(args));
2534 nf_gc(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2542 nf_gcverb(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2544 int was = ctx->gc_verbose;
2545 ctx->gc_verbose = (CAR(args) != F);
2549 nf_nativep(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2551 s_retbool(NATIVE_FUNCP(CAR(args)));
2554 nf_length(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2558 for (x = CAR(args), v = 0; PAIRP(x); x = CDR(x)) { ++v; }
2559 return mk_number(ctx, v);
2562 nf_assq(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2564 register cell *x, *y;
2566 for (y = CADR(args); PAIRP(y); y = CDR(y)) {
2567 if (!PAIRP(CAR(y))) {
2568 QLERR("Unable to handle non pair element");
2580 nf_get_closure(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2585 } else if (CLOSUREP(args)) {
2586 return CONS(LAMBDA, CLOSURE_CODE(ctx->value));
2587 } else if (MACROP(args)) {
2588 return CONS(LAMBDA, CLOSURE_CODE(ctx->value));
2594 nf_closurep(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2597 * Note, macro object is also a closure.
2598 * Therefore, (closure? <#MACRO>) ==> #t
2600 if (CAR(args) == NIL) {
2603 s_retbool(CLOSUREP(CAR(args)));
2606 nf_macrop(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2608 if (CAR(args) == NIL) {
2611 s_retbool(MACROP(CAR(args)));
2614 nf_voidp(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2616 s_retbool(CAR(args)->type == sen_ql_void);
2619 nf_list(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2624 QLERR("Unable to handle non-cons argument");
2628 nf_batchmode(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2630 if (CAR(args) == F) {
2639 nf_loglevel(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2641 static sen_logger_info info;
2642 cell *x = CAR(args);
2643 if (sen_obj2int(ctx, x)) { QLERR("can't convert into integer"); }
2644 info.max_level = IVALUE(x);
2645 info.flags = SEN_LOG_TIME|SEN_LOG_MESSAGE;
2647 info.func_arg = NULL;
2648 return (sen_logger_info_set(&info)) ? F : T;
2651 nf_now(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2655 if (sen_timeval_now(&tv)) { QLERR("sysdate failed"); }
2656 SEN_OBJ_NEW(ctx, x);
2661 nf_timestr(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2664 char buf[SEN_TIMEVAL_STR_SIZE];
2665 cell *x = CAR(args);
2668 if (sen_obj2int(ctx, x)) { QLERR("can't convert into integer"); }
2671 tv.tv_sec = IVALUE(x);
2675 tv.tv_sec = (int32_t) FVALUE(x);
2676 tv.tv_usec = (int32_t) ((FVALUE(x) - tv.tv_sec) * 1000000);
2679 memcpy(&tv, &x->u.tv, sizeof(sen_timeval));
2682 QLERR("can't convert into time");
2684 if (sen_timeval2str(&tv, buf)) { QLERR("timeval2str failed"); }
2685 return sen_ql_mk_string(ctx, buf, strlen(buf));
2688 nf_tonumber(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2691 if (!PAIRP(args)) { QLERR("list required"); }
2695 if ((v = str2num(ctx, STRVALUE(x), x->u.b.size)) == NIL) { v = mk_number(ctx, 0); }
2703 double dv= x->u.tv.tv_sec;
2704 dv += x->u.tv.tv_usec / 1000000.0;
2705 SEN_OBJ_NEW(ctx, v);
2710 QLERR("can't convert into number");
2715 nf_totime(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2719 if (!PAIRP(args)) { QLERR("list required"); }
2725 if (PAIRP(CDR(args)) && BULKP(CADR(args))) { fmt = STRVALUE(CADR(args)); }
2727 if (sen_str2timeval(STRVALUE(x), x->u.b.size, &tv)) {
2728 QLERR("cast error");
2730 SEN_OBJ_NEW(ctx, v);
2735 tv.tv_sec = (int32_t) IVALUE(x);
2737 SEN_OBJ_NEW(ctx, v);
2741 tv.tv_sec = (int32_t) FVALUE(x);
2742 tv.tv_usec = (int32_t) ((FVALUE(x) - tv.tv_sec) * 1000000);
2743 SEN_OBJ_NEW(ctx, v);
2750 QLERR("can't convert into number");
2755 nf_substrb(sen_ctx *ctx, sen_obj *args, sen_ql_co *co)
2757 sen_obj *str, *s, *e;
2759 if (!PAIRP(args)) { QLERR("list required"); }
2761 if (!BULKP(str)) { QLERR("string required"); }
2763 if (!INTP(s)) { QLERR("integer required"); }
2765 if (!INTP(e)) { QLERR("integer required"); }
2769 ie = str->u.b.size + ie;
2770 if (ie < 0) { ie = 0; }
2771 } else if (ie > str->u.b.size) {
2775 is = str->u.b.size + is + 1;
2776 if (is < 0) { is = 0; }
2777 } else if (is > str->u.b.size) {
2781 return sen_ql_mk_string(ctx, STRVALUE(str) + is, ie - is);
2784 SEN_OBJ_NEW(ctx, o);
2786 o->type = sen_ql_bulk;
2788 o->u.b.value = NULL;
2793 /* ========== Initialization of internal keywords ========== */
2796 mk_syntax(sen_ctx *ctx, uint8_t op, char *name)
2799 if ((x = INTERN(name)) != F) {
2800 x->type = sen_ql_syntax;
2806 mk_proc(sen_ctx *ctx, uint8_t op, char *name)
2809 if ((x = INTERN(name)) != F) {
2810 x->type = sen_ql_proc;
2811 IVALUE(x) = (int64_t) op;
2816 sen_ql_init_const(void)
2818 static sen_obj _NIL, _T, _F;
2821 NIL->type = sen_ql_void;
2822 CAR(NIL) = CDR(NIL) = NIL;
2825 T->type = sen_ql_void;
2826 CAR(T) = CDR(T) = T;
2829 F->type = sen_ql_void;
2830 CAR(F) = CDR(F) = F;
2834 init_vars_global(sen_ctx *ctx)
2837 /* init global_env */
2838 ctx->global_env = CONS(NIL, NIL);
2840 if ((x = INTERN("else")) != F) {
2841 CAR(ctx->global_env) = CONS(CONS(x, T), CAR(ctx->global_env));
2846 init_syntax(sen_ctx *ctx)
2849 mk_syntax(ctx, OP_LAMBDA, "lambda");
2850 mk_syntax(ctx, OP_QUOTE, "quote");
2851 mk_syntax(ctx, OP_DEF0, "define");
2852 mk_syntax(ctx, OP_IF0, "if");
2853 mk_syntax(ctx, OP_BEGIN, "begin");
2854 mk_syntax(ctx, OP_SET0, "set!");
2855 mk_syntax(ctx, OP_LET0, "let");
2856 mk_syntax(ctx, OP_LET0AST, "let*");
2857 mk_syntax(ctx, OP_LET0REC, "letrec");
2858 mk_syntax(ctx, OP_COND0, "cond");
2859 mk_syntax(ctx, OP_DELAY, "delay");
2860 mk_syntax(ctx, OP_AND0, "and");
2861 mk_syntax(ctx, OP_OR0, "or");
2862 mk_syntax(ctx, OP_C0STREAM, "cons-stream");
2863 mk_syntax(ctx, OP_0MACRO, "define-macro");
2864 mk_syntax(ctx, OP_CASE0, "case");
2865 mk_syntax(ctx, OP_QQUOTE0, "quasiquote");
2869 init_procs(sen_ctx *ctx)
2871 /* init procedure */
2872 mk_proc(ctx, OP_PEVAL, "eval");
2873 mk_proc(ctx, OP_PAPPLY, "apply");
2874 mk_proc(ctx, OP_CONTINUATION, "call-with-current-continuation");
2875 mk_proc(ctx, OP_FORCE, "force");
2876 mk_proc(ctx, OP_SETCAR, "set-car!");
2877 mk_proc(ctx, OP_SETCDR, "set-cdr!");
2878 mk_proc(ctx, OP_READ, "read");
2879 mk_proc(ctx, OP_LOAD, "load");
2880 mk_proc(ctx, OP_ERR1, "error");
2881 mk_proc(ctx, OP_PUT, "put");
2882 mk_proc(ctx, OP_GET, "get");
2883 mk_proc(ctx, OP_QUIT, "quit");
2884 mk_proc(ctx, OP_SDOWN, "shutdown");
2885 sen_ql_def_native_func(ctx, "+", nf_add);
2886 sen_ql_def_native_func(ctx, "-", nf_sub);
2887 sen_ql_def_native_func(ctx, "*", nf_mul);
2888 sen_ql_def_native_func(ctx, "/", nf_div);
2889 sen_ql_def_native_func(ctx, "remainder", nf_rem);
2890 sen_ql_def_native_func(ctx, "car", nf_car);
2891 sen_ql_def_native_func(ctx, "cdr", nf_cdr);
2892 sen_ql_def_native_func(ctx, "cons", nf_cons);
2893 sen_ql_def_native_func(ctx, "not", nf_not);
2894 sen_ql_def_native_func(ctx, "boolean?", nf_bool);
2895 sen_ql_def_native_func(ctx, "symbol?", nf_symbol);
2896 sen_ql_def_native_func(ctx, "number?", nf_number);
2897 sen_ql_def_native_func(ctx, "string?", nf_string);
2898 sen_ql_def_native_func(ctx, "procedure?", nf_proc);
2899 sen_ql_def_native_func(ctx, "pair?", nf_pair);
2900 sen_ql_def_native_func(ctx, "eqv?", nf_eqv);
2901 sen_ql_def_native_func(ctx, "eq?", nf_eq);
2902 sen_ql_def_native_func(ctx, "null?", nf_null);
2903 sen_ql_def_native_func(ctx, "zero?", nf_zerop);
2904 sen_ql_def_native_func(ctx, "positive?", nf_posp);
2905 sen_ql_def_native_func(ctx, "negative?", nf_negp);
2906 sen_ql_def_native_func(ctx, "=", nf_neq);
2907 sen_ql_def_native_func(ctx, "<", nf_less);
2908 sen_ql_def_native_func(ctx, ">", nf_gre);
2909 sen_ql_def_native_func(ctx, "<=", nf_leq);
2910 sen_ql_def_native_func(ctx, ">=", nf_geq);
2911 sen_ql_def_native_func(ctx, "write", nf_write);
2912 sen_ql_def_native_func(ctx, "display", nf_display);
2913 sen_ql_def_native_func(ctx, "newline", nf_newline);
2914 sen_ql_def_native_func(ctx, "reverse", nf_reverse);
2915 sen_ql_def_native_func(ctx, "append", nf_append);
2916 sen_ql_def_native_func(ctx, "gc", nf_gc);
2917 sen_ql_def_native_func(ctx, "gc-verbose", nf_gcverb);
2918 sen_ql_def_native_func(ctx, "native?", nf_nativep);
2919 sen_ql_def_native_func(ctx, "length", nf_length); /* a.k */
2920 sen_ql_def_native_func(ctx, "assq", nf_assq); /* a.k */
2921 sen_ql_def_native_func(ctx, "get-closure-code", nf_get_closure); /* a.k */
2922 sen_ql_def_native_func(ctx, "closure?", nf_closurep); /* a.k */
2923 sen_ql_def_native_func(ctx, "macro?", nf_macrop); /* a.k */
2924 sen_ql_def_native_func(ctx, "void?", nf_voidp);
2925 sen_ql_def_native_func(ctx, "list", nf_list);
2926 sen_ql_def_native_func(ctx, "batchmode", nf_batchmode);
2927 sen_ql_def_native_func(ctx, "loglevel", nf_loglevel);
2928 sen_ql_def_native_func(ctx, "now", nf_now);
2929 sen_ql_def_native_func(ctx, "timestr", nf_timestr);
2930 sen_ql_def_native_func(ctx, "x->time", nf_totime);
2931 sen_ql_def_native_func(ctx, "x->number", nf_tonumber);
2932 sen_ql_def_native_func(ctx, "substrb", nf_substrb);
2935 /* initialize several globals */
2937 sen_ql_init_globals(sen_ctx *ctx)
2939 init_vars_global(ctx);
2942 ctx->output = sen_ctx_concat_func;
2943 /* intialization of global pointers to special symbols */