diff options
| author | Mistivia <i@mistivia.com> | 2025-06-27 21:21:42 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-06-27 21:21:42 +0800 |
| commit | 878a056f3accafaa797446eb3a3b1a66b36d0d07 (patch) | |
| tree | f56330127b96bdff11f2bd37b7229a94d02fcacc /src | |
| parent | 0ba662762023b7e3788690d9990ab39e89fd6f34 (diff) | |
add more funcs
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.c | 127 | ||||
| -rw-r--r-- | src/builtins.h | 6 | ||||
| -rw-r--r-- | src/interp.c | 18 | ||||
| -rw-r--r-- | src/parser.c | 12 |
4 files changed, 158 insertions, 5 deletions
diff --git a/src/builtins.c b/src/builtins.c index 9dcf497..591dc97 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -7,6 +7,127 @@ #include <float.h> #include <math.h> +SExpRef builtin_setnth(Interp *interp, SExpRef args) { + if (LENGTH(args) != 3) { + return new_error(interp, "set-nth: args num error.\n"); + } + SExpRef n = CAR(args), lst = CADR(args), elem = CADDR(args); + if (VALTYPE(n) != kIntegerSExp) return new_error(interp, "set-nth: type error.\n"); + if (VALTYPE(lst) == kPairSExp) { + if (REF(n)->integer >= LENGTH(lst)) { + return new_error(interp, "nth: out of bound.\n"); + } + for (int i = 0; i < REF(n)->integer; i++) { + lst = CDR(lst); + } + return REF(lst)->pair.car = elem; + return NIL; + } else if (VALTYPE(lst) == kStringSExp) { + if (REF(n)->integer >= strlen(REF(lst)->str)) { + return new_error(interp, "nth: out of bound\n"); + } + if (VALTYPE(elem) != kCharSExp) { + return new_error(interp, "set-nth: type error.\n"); + } + ((char*)REF(lst)->str)[REF(n)->integer] = REF(elem)->character; + return NIL; + } else { + return new_error(interp, "nth: type error.\n"); + } +} + +SExpRef builtin_setnthcdr(Interp *interp, SExpRef args) { + if (LENGTH(args) != 3) { + return new_error(interp, "set-nthcdr: args num error.\n"); + } + SExpRef n = CAR(args), lst = CADR(args), elem = CADDR(args); + if (VALTYPE(n) != kIntegerSExp) return new_error(interp, "set-nthcdr: type error.\n"); + if (VALTYPE(lst) == kPairSExp) { + if (REF(n)->integer >= LENGTH(lst)) { + return new_error(interp, "set-nthcdr: out of bound.\n"); + } + for (int i = 0; i < REF(n)->integer; i++) { + lst = CDR(lst); + } + return REF(lst)->pair.cdr = elem; + return NIL; + } + return new_error(interp, "set-nthcdr: type error.\n"); + +} + +SExpRef builtin_foldl(Interp *interp, SExpRef args) { + if (LENGTH(args) != 3) { + return new_error(interp, "foldl: args num error.\n"); + } + SExpRef fn = CAR(args), init = CADR(args), lst = CADDR(args); + SExpRef ret = init; + if (VALTYPE(fn) != kUserFuncSExp && VALTYPE(fn) != kFuncSExp) { + return new_error(interp, "foldl: type error.\n"); + } + if (!lisp_check_list(interp, lst)) { + return new_error(interp, "foldl: type error.\n"); + } + for (SExpRef i = lst ; !NILP(i); i = CDR(i)) { + SExpRef x = CAR(i); + ret = lisp_call(interp, fn, new_list2(interp, ret, x)); + if (CTL_FL(ret)) { + return ret; + } + } + return ret; +} + +SExpRef builtin_append(Interp *interp, SExpRef args) { + for (SExpRef l = args; !NILP(l); l = CDR(l)) { + if (!lisp_check_list(interp, l)) { + return new_error(interp, "append: type error.\n"); + } + } + SExpRef newlst = NIL; + for (SExpRef i = args; !NILP(i); i = CDR(i)) { + for (SExpRef j = CAR(i); !NILP(j); j = CDR(j)) { + newlst = CONS(CAR(j), newlst); + } + } + return lisp_nreverse(interp, newlst); +} + +SExpRef builtin_nconc(Interp *interp, SExpRef args) { + if (LENGTH(args) != 2) { + return new_error(interp, "nconc: args num error.\n"); + } + SExpRef l1 = CAR(args), l2= CADR(args); + if (!lisp_check_list(interp, l1) || !lisp_check_list(interp, l2)) { + return new_error(interp, "nconc: type error.\n"); + } + SExpRef last = NIL; + for (SExpRef i = l1; !NILP(i); i = CDR(i)) { + if (NILP(CDR(i))) { + last = i; + } + } + if (NILP(last)) return l2; + REF(last)->pair.cdr = l2; + return l1; +} + +SExpRef builtin_logand(Interp *interp, SExpRef args) { + if (LENGTH(args) < 1) { + return new_error(interp, "nconc: args num error.\n"); + } + for (SExpRef l = args; !NILP(l); l = CDR(l)) { + if (VALTYPE(CAR(l)) != kIntegerSExp) { + return new_error(interp, "append: type error.\n"); + } + } + uint64_t res = 0xffffffffffffffffULL; + for (SExpRef l = args; !NILP(l); l = CDR(l)) { + res = res & (REF(CAR(l))->integer); + } + return new_integer(interp, res); +} + SExpRef builtin_charp(Interp *interp, SExpRef args) { if (LENGTH(args) != 1) return new_error(interp, "char?: arg num error.\n"); return new_boolean(interp, VALTYPE(CAR(args)) == kCharSExp); @@ -151,7 +272,7 @@ SExpRef builtin_floatp(Interp *interp, SExpRef args) { } SExpRef builtin_nreverse(Interp *interp, SExpRef args) { - if (LENGTH(args) != 1) return new_error(interp, "number?: arg num error.\n"); + if (LENGTH(args) != 1) return new_error(interp, "nreverse: arg num error.\n"); SExpRef lst = CAR(args); if (lisp_check_list(interp, lst)) { return lisp_nreverse(interp, lst); @@ -160,12 +281,12 @@ SExpRef builtin_nreverse(Interp *interp, SExpRef args) { } SExpRef builtin_reverse(Interp *interp, SExpRef args) { - if (LENGTH(args) != 1) return new_error(interp, "number?: arg num error.\n"); + if (LENGTH(args) != 1) return new_error(interp, "reverse: arg num error.\n"); SExpRef lst = CAR(args); if (lisp_check_list(interp, lst)) { return lisp_reverse(interp, lst); } - return new_error(interp, "nreverse: type error.\n"); + return new_error(interp, "reverse: type error.\n"); } SExpRef builtin_last(Interp *interp, SExpRef args) { diff --git a/src/builtins.h b/src/builtins.h index 673db23..0d3c5cc 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -3,6 +3,12 @@ #include "interp.h" +SExpRef builtin_setnth(Interp *interp, SExpRef args); +SExpRef builtin_setnthcdr(Interp *interp, SExpRef args); +SExpRef builtin_foldl(Interp *interp, SExpRef args); +SExpRef builtin_append(Interp *interp, SExpRef args); +SExpRef builtin_nconc(Interp *interp, SExpRef args); +SExpRef builtin_logand(Interp *interp, SExpRef args); SExpRef builtin_charp(Interp *interp, SExpRef args); SExpRef builtin_char_eq(Interp *interp, SExpRef args); SExpRef builtin_char_gt(Interp *interp, SExpRef args); diff --git a/src/interp.c b/src/interp.c index 5a4c9b6..e6e9f2a 100644 --- a/src/interp.c +++ b/src/interp.c @@ -215,6 +215,12 @@ void Interp_init(Interp *self) { Interp_add_userfunc(self, "alphabetic?", builtin_alphabeticp); Interp_add_userfunc(self, "numeric?", builtin_numericp); Interp_add_userfunc(self, "alphanum?", builtin_alphanump); + Interp_add_userfunc(self, "set-nth", builtin_setnth); + Interp_add_userfunc(self, "set-nthcdr", builtin_setnthcdr); + Interp_add_userfunc(self, "foldl", builtin_foldl); + Interp_add_userfunc(self, "append", builtin_append); + Interp_add_userfunc(self, "nconc", builtin_nconc); + Interp_add_userfunc(self, "logand", builtin_logand); Interp_add_userfunc(self, "_gcstat", builtin_gcstat); Interp_add_userfunc(self, "_alwaysgc", builtin_alwaysgc); @@ -752,6 +758,11 @@ SExpRef lisp_call(Interp *interp, SExpRef fn, SExpRef args) { POP_REG(); if (CTL_FL(ret)) break; } + if (VALTYPE(ret) == kBreakSignal + || VALTYPE(ret) == kContinueSignal + || VALTYPE(ret) == kReturnSignal) { + return new_error(interp, "call: unexpected control flow signal.\n"); + } return ret; } @@ -1062,3 +1073,10 @@ SExpRef new_primitive(Interp *interp, LispPrimitive val) { return ret; } +SExpRef new_list2(Interp *interp, SExpRef e1, SExpRef e2) { + return CONS(e1, CONS(e2, NIL)); +} +SExpRef new_list3(Interp *interp, SExpRef e1, SExpRef e2, SExpRef e3); +SExpRef new_list4(Interp *interp, SExpRef e1, SExpRef e2, SExpRef e3, SExpRef e4); +SExpRef new_list5(Interp *interp, SExpRef e1, SExpRef e2, SExpRef e3, SExpRef e4, SExpRef e5); + diff --git a/src/parser.c b/src/parser.c index d8fda82..ec21b44 100644 --- a/src/parser.c +++ b/src/parser.c @@ -350,12 +350,20 @@ static ParseResult parse_token(Parser *parser, const char *token) { if (len < 2) return ParseErr(parser, "Expect boolean or character.\n"); if (token[1] == '\'') { if (len < 3) return ParseErr(parser, "Expect a symbol.\n"); + if (len == 3) { + if (token[2] == '+' || token[2] == '-') { + goto funcmacro; + } + } if (!is_symbol_init(token[2])) return ParseErr(parser, "Expect a symbol.\n"); for (int i = 3; i < len; i++) { if (!is_symbol_subsequent(token[i])) return ParseErr(parser, "Expect a symbol.\n"); } - SExpRef funcsym = new_symbol(parser->ctx, "function"); - SExpRef sym = new_symbol(parser->ctx, token+2); + SExpRef funcsym; + SExpRef sym; + funcmacro: + funcsym = new_symbol(parser->ctx, "function"); + sym = new_symbol(parser->ctx, token+2); return ParseOk(lisp_cons(parser->ctx, funcsym, lisp_cons(parser->ctx, sym, parser->ctx->nil))); } if (token[1] == 't') return ParseOk(new_boolean(parser->ctx, true)); |
