X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fscheme%2Fao_scheme_builtin.c;h=0b84a89a2b366bdb67f2cf337fa4dc2a34eac24f;hb=036a5311cbc86dbc5a8f859778d52d588915e4e2;hp=9a823f6ab917812c80d27143b73c7c2f19bcfb62;hpb=32f6877288ea6b7eb1cae9a42fbe8e2c5dbb2f08;p=fw%2Faltos diff --git a/src/scheme/ao_scheme_builtin.c b/src/scheme/ao_scheme_builtin.c index 9a823f6a..0b84a89a 100644 --- a/src/scheme/ao_scheme_builtin.c +++ b/src/scheme/ao_scheme_builtin.c @@ -84,9 +84,10 @@ ao_scheme_args_name(uint8_t args) #endif void -ao_scheme_builtin_write(ao_poly b) +ao_scheme_builtin_write(ao_poly b, bool write) { struct ao_scheme_builtin *builtin = ao_scheme_poly_builtin(b); + (void) write; printf("%s", ao_scheme_builtin_name(builtin->func)); } @@ -104,17 +105,23 @@ ao_scheme_check_argc(ao_poly name, struct ao_scheme_cons *cons, int min, int max return _ao_scheme_bool_true; } -ao_poly -ao_scheme_arg(struct ao_scheme_cons *cons, int argc) +static ao_poly +ao_scheme_opt_arg(struct ao_scheme_cons *cons, int argc, ao_poly def) { - if (!cons) - return AO_SCHEME_NIL; - while (argc--) { + for (;;) { if (!cons) - return AO_SCHEME_NIL; + return def; + if (argc == 0) + return cons->car; cons = ao_scheme_cons_cdr(cons); + argc--; } - return cons->car; +} + +ao_poly +ao_scheme_arg(struct ao_scheme_cons *cons, int argc) +{ + return ao_scheme_opt_arg(cons, argc, AO_SCHEME_NIL); } ao_poly @@ -139,6 +146,18 @@ ao_scheme_arg_int(ao_poly name, struct ao_scheme_cons *cons, int argc) return i; } +static int32_t +ao_scheme_opt_arg_int(ao_poly name, struct ao_scheme_cons *cons, int argc, int def) +{ + ao_poly p = ao_scheme_opt_arg(cons, argc, ao_scheme_int_poly(def)); + bool fail = false; + int32_t i = ao_scheme_poly_integer(p, &fail); + + if (fail) + (void) ao_scheme_error(AO_SCHEME_INVALID, "%v: arg %d invalid type %v", name, argc, p); + return i; +} + ao_poly ao_scheme_do_car(struct ao_scheme_cons *cons) { @@ -167,7 +186,7 @@ ao_scheme_do_cons(struct ao_scheme_cons *cons) return AO_SCHEME_NIL; car = ao_scheme_arg(cons, 0); cdr = ao_scheme_arg(cons, 1); - return ao_scheme__cons(car, cdr); + return ao_scheme_cons(car, cdr); } ao_poly @@ -252,10 +271,10 @@ ao_scheme_do_setq(struct ao_scheme_cons *cons) return ao_scheme_error(AO_SCHEME_INVALID, "set! of non-atom %v", name); if (!ao_scheme_atom_ref(name, NULL)) return ao_scheme_error(AO_SCHEME_INVALID, "atom %v not defined", name); - return ao_scheme__cons(_ao_scheme_atom_set, - ao_scheme__cons(ao_scheme__cons(_ao_scheme_atom_quote, - ao_scheme__cons(name, AO_SCHEME_NIL)), - cons->cdr)); + return ao_scheme_cons(_ao_scheme_atom_set, + ao_scheme_cons(ao_scheme_cons(_ao_scheme_atom_quote, + ao_scheme_cons(name, AO_SCHEME_NIL)), + cons->cdr)); } ao_poly @@ -287,7 +306,7 @@ ao_scheme_do_write(struct ao_scheme_cons *cons) ao_poly val = AO_SCHEME_NIL; while (cons) { val = cons->car; - ao_scheme_poly_write(val); + ao_scheme_poly_write(val, true); cons = ao_scheme_cons_cdr(cons); if (cons) printf(" "); @@ -301,7 +320,7 @@ ao_scheme_do_display(struct ao_scheme_cons *cons) ao_poly val = AO_SCHEME_NIL; while (cons) { val = cons->car; - ao_scheme_poly_display(val); + ao_scheme_poly_write(val, false); cons = ao_scheme_cons_cdr(cons); } return _ao_scheme_bool_true; @@ -320,7 +339,7 @@ ao_scheme_math(struct ao_scheme_cons *orig_cons, enum ao_scheme_builtin_id op) if (cons == orig_cons) { ret = car; - ao_scheme_cons_stash(0, cons); + ao_scheme_cons_stash(cons); if (cons->cdr == AO_SCHEME_NIL) { switch (op) { case builtin_minus: @@ -348,7 +367,7 @@ ao_scheme_math(struct ao_scheme_cons *orig_cons, enum ao_scheme_builtin_id op) break; } } - cons = ao_scheme_cons_fetch(0); + cons = ao_scheme_cons_fetch(); } else if (ao_scheme_integer_typep(rt) && ao_scheme_integer_typep(ct)) { int32_t r = ao_scheme_poly_integer(ret, NULL); int32_t c = ao_scheme_poly_integer(car, NULL); @@ -392,6 +411,11 @@ ao_scheme_math(struct ao_scheme_cons *orig_cons, enum ao_scheme_builtin_id op) case builtin_quotient: if (c == 0) return ao_scheme_error(AO_SCHEME_DIVIDE_BY_ZERO, "quotient by zero"); + r = r / c; + break; + case builtin_floor_quotient: + if (c == 0) + return ao_scheme_error(AO_SCHEME_DIVIDE_BY_ZERO, "floor-quotient by zero"); if (r % c != 0 && (c < 0) != (r < 0)) r = r / c - 1; else @@ -412,9 +436,9 @@ ao_scheme_math(struct ao_scheme_cons *orig_cons, enum ao_scheme_builtin_id op) default: break; } - ao_scheme_cons_stash(0, cons); + ao_scheme_cons_stash(cons); ret = ao_scheme_integer_poly(r); - cons = ao_scheme_cons_fetch(0); + cons = ao_scheme_cons_fetch(); #ifdef AO_SCHEME_FEATURE_FLOAT } else if (ao_scheme_number_typep(rt) && ao_scheme_number_typep(ct)) { float r, c; @@ -435,22 +459,23 @@ ao_scheme_math(struct ao_scheme_cons *orig_cons, enum ao_scheme_builtin_id op) r /= c; break; case builtin_quotient: + case builtin_floor_quotient: case builtin_remainder: case builtin_modulo: return ao_scheme_error(AO_SCHEME_INVALID, "non-integer value in integer divide"); default: break; } - ao_scheme_cons_stash(0, cons); + ao_scheme_cons_stash(cons); ret = ao_scheme_float_get(r); - cons = ao_scheme_cons_fetch(0); + cons = ao_scheme_cons_fetch(); #endif } else if (rt == AO_SCHEME_STRING && ct == AO_SCHEME_STRING && op == builtin_plus) { - ao_scheme_cons_stash(0, cons); + ao_scheme_cons_stash(cons); ret = ao_scheme_string_poly(ao_scheme_string_cat(ao_scheme_poly_string(ret), ao_scheme_poly_string(car))); - cons = ao_scheme_cons_fetch(0); + cons = ao_scheme_cons_fetch(); if (!ret) return ret; } @@ -490,6 +515,12 @@ ao_scheme_do_quotient(struct ao_scheme_cons *cons) return ao_scheme_math(cons, builtin_quotient); } +ao_poly +ao_scheme_do_floor_quotient(struct ao_scheme_cons *cons) +{ + return ao_scheme_math(cons, builtin_floor_quotient); +} + ao_poly ao_scheme_do_modulo(struct ao_scheme_cons *cons) { @@ -731,17 +762,39 @@ ao_scheme_do_string_set(struct ao_scheme_cons *cons) val = ao_scheme_arg_int(_ao_scheme_atom_string2dset21, cons, 2); if (ao_scheme_exception) return AO_SCHEME_NIL; + if (!val) + goto fail; while (*string && ref) { ++string; --ref; } if (!*string) - return ao_scheme_error(AO_SCHEME_INVALID, "%v: string %v ref %v invalid", - _ao_scheme_atom_string2dset21, - ao_scheme_arg(cons, 0), - ao_scheme_arg(cons, 1)); + goto fail; *string = val; return ao_scheme_int_poly(*string); +fail: + return ao_scheme_error(AO_SCHEME_INVALID, "%v: %v[%v] = %v invalid", + _ao_scheme_atom_string2dset21, + ao_scheme_arg(cons, 0), + ao_scheme_arg(cons, 1), + ao_scheme_arg(cons, 2)); +} + +ao_poly +ao_scheme_do_make_string(struct ao_scheme_cons *cons) +{ + int32_t len; + char fill; + + if (!ao_scheme_check_argc(_ao_scheme_atom_make2dstring, cons, 1, 2)) + return AO_SCHEME_NIL; + len = ao_scheme_arg_int(_ao_scheme_atom_make2dstring, cons, 0); + if (ao_scheme_exception) + return AO_SCHEME_NIL; + fill = ao_scheme_opt_arg_int(_ao_scheme_atom_make2dstring, cons, 1, ' '); + if (ao_scheme_exception) + return AO_SCHEME_NIL; + return ao_scheme_string_poly(ao_scheme_make_string(len, fill)); } ao_poly @@ -855,7 +908,7 @@ ao_scheme_do_pairp(struct ao_scheme_cons *cons) if (!ao_scheme_check_argc(_ao_scheme_atom_led, cons, 1, 1)) return AO_SCHEME_NIL; v = ao_scheme_arg(cons, 0); - if (v != AO_SCHEME_NIL && ao_scheme_poly_type(v) == AO_SCHEME_CONS) + if (ao_scheme_is_pair(v)) return _ao_scheme_bool_true; return _ao_scheme_bool_false; } @@ -946,7 +999,7 @@ ao_scheme_do_listp(struct ao_scheme_cons *cons) for (;;) { if (v == AO_SCHEME_NIL) return _ao_scheme_bool_true; - if (ao_scheme_poly_type(v) != AO_SCHEME_CONS) + if (!ao_scheme_is_cons(v)) return _ao_scheme_bool_false; v = ao_scheme_poly_cons(v)->cdr; } @@ -1107,11 +1160,21 @@ ao_scheme_do_list_to_vector(struct ao_scheme_cons *cons) ao_poly ao_scheme_do_vector_to_list(struct ao_scheme_cons *cons) { - if (!ao_scheme_check_argc(_ao_scheme_atom_vector2d3elist, cons, 1, 1)) + int start, end; + + if (!ao_scheme_check_argc(_ao_scheme_atom_vector2d3elist, cons, 1, 3)) return AO_SCHEME_NIL; if (!ao_scheme_check_argt(_ao_scheme_atom_vector2d3elist, cons, 0, AO_SCHEME_VECTOR, 0)) return AO_SCHEME_NIL; - return ao_scheme_cons_poly(ao_scheme_vector_to_list(ao_scheme_poly_vector(ao_scheme_arg(cons, 0)))); + start = ao_scheme_opt_arg_int(_ao_scheme_atom_vector2d3elist, cons, 1, ao_scheme_int_poly(0)); + if (ao_scheme_exception) + return AO_SCHEME_NIL; + end = ao_scheme_opt_arg_int(_ao_scheme_atom_vector2d3elist, cons, 2, ao_scheme_int_poly(-1)); + if (ao_scheme_exception) + return AO_SCHEME_NIL; + return ao_scheme_cons_poly(ao_scheme_vector_to_list(ao_scheme_poly_vector(ao_scheme_arg(cons, 0)), + start, + end)); } ao_poly