Unified · Split
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | static sl_v iosym, rdsym, wrsym, apsym, crsym, truncsym; |
| 9 | 9 | static sl_v linesym, blocksym, memorysym; |
| 10 | −static sl_v ioinsym, wssym, endsym, bendian, lendian; | |
| 10 | +static sl_v ioinsym, wssym, endsym, bendiansym, lendiansym; | |
| 11 | 11 | sl_v sl_iooutsym; |
| 12 | 12 | const sl_type *sl_iotype; |
| 13 | 13 | |
| @@ -68,9 +68,9 @@ static bool · 54 unmodified lines | ||
| 68 | 68 | isflipped(sl_v v) |
| 69 | 69 | { |
| 70 | 70 | bool little; |
| 71 | − if(v == lendian) | |
| 71 | + if(v == lendiansym) | |
| 72 | 72 | little = true; |
| 73 | − else if(v == bendian) | |
| 73 | + else if(v == bendiansym) | |
| 74 | 74 | little = false; |
| 75 | 75 | else |
| 76 | 76 | cthrow(error(sl_errarg, "invalid endian specifier"), v); |
| @@ -194,19 +194,12 @@ BUILTIN("buffer", buffer) · 117 unmodified lines | ||
| 194 | 194 | |
| 195 | 195 | BUILTIN("read", read) |
| 196 | 196 | { |
| 197 | − bool ws = false; | |
| 198 | − if(sl_unlikely(nargs >= 2 && nargs <= 3)){ | |
| 199 | − int i; | |
| 200 | − if(args[i = 0] == wssym || (nargs > 2 && args[i = 1] == wssym)){ | |
| 201 | − ws = args[++i] != sl_nil; | |
| 202 | − if(i < 2) // (read :whitespace T io) | |
| 203 | − args[0] = args[2]; | |
| 204 | − nargs -= 2; | |
| 205 | − } | |
| 206 | − } | |
| 207 | − sl_v a = nargs == 0 ? sym_value(ioinsym) : args[0]; | |
| 197 | + sl_v keys[] = {wssym}, values[1]; | |
| 198 | + nargs = sl_process_args(args, 0, nargs, keys, nelem(keys), values); | |
| 208 | 199 | if(sl_unlikely(nargs > 1)) |
| 209 | − argcount(1); | |
| 200 | + bthrow(error(sl_errarg, "extra arguments")); | |
| 201 | + bool ws = nonnil(values[0]); | |
| 202 | + sl_v a = nargs == 0 ? sym_value(ioinsym) : args[0]; | |
| 210 | 203 | USED(toio(a, true, true, false)); |
| 211 | 204 | sl_gc_handle(&a); |
| 212 | 205 | sl_v v = sl_read_sexpr(a, ws); |
| @@ -300,15 +293,11 @@ BUILTIN("io-peek", io_peek) · 87 unmodified lines | ||
| 300 | 293 | |
| 301 | 294 | BUILTIN("io-skip", io_skip) |
| 302 | 295 | { |
| 296 | + sl_v keys[] = {endsym}, values[1]; | |
| 297 | + nargs = sl_process_args(args, 2, nargs, keys, nelem(keys), values); | |
| 298 | + bool end = nonnil(values[0]); | |
| 303 | 299 | if(nargs != 2 && nargs != 4) |
| 304 | 300 | argcount(2); |
| 305 | − bool end = false; | |
| 306 | − if(nargs == 4){ | |
| 307 | − if(args[2] == endsym) | |
| 308 | − end = args[3] != sl_nil; | |
| 309 | − else | |
| 310 | − bthrow(error(sl_errarg, "invalid arguments")); | |
| 311 | − } | |
| 312 | 301 | ios *s = toio(args[0], true, false, false); |
| 313 | 302 | soffset off = tooffset(args[1]); |
| 314 | 303 | soffset res = ios_skip(s, off, end); |
| @@ -616,8 +605,8 @@ io_init(void) · 301 unmodified lines | ||
| 616 | 605 | wssym = mk_csym(":whitespace"); |
| 617 | 606 | endsym = mk_csym(":end"); |
| 618 | 607 | ioinsym = mk_csym("*io-in*"); |
| 619 | − bendian = mk_csym(":big-endian"); | |
| 620 | − lendian = mk_csym(":little-endian"); | |
| 608 | + bendiansym = mk_csym(":big-endian"); | |
| 609 | + lendiansym = mk_csym(":little-endian"); | |
| 621 | 610 | sl_iooutsym = mk_csym("*io-out*"); |
| 622 | 611 | sl_iotype = define_opaque_type(iosym, sizeof(ios), &io_vtable, nil); |
| 623 | 612 | set(mk_csym("*stdout*"), cvalue_from_ref(sl_iotype, ios_stdout, sizeof(ios))); |
| @@ -790,6 +790,39 @@ sl_do_trycatch(void) · 789 unmodified lines | ||
| 790 | 790 | return v; |
| 791 | 791 | } |
| 792 | 792 | |
| 793 | +int | |
| 794 | +sl_process_args(sl_v *args, int nreq, int nargs, const sl_v *keys, int nkeys, sl_v *values) | |
| 795 | +{ | |
| 796 | + if(sl_unlikely(nargs < nreq)) | |
| 797 | + cthrow(arity_error(nargs, nreq), args); | |
| 798 | + for(int k = 0; k < nkeys; k++) | |
| 799 | + values[k] = sl_unbound; | |
| 800 | + int nn = 0; | |
| 801 | + for(int i = 0; i < nargs; i++){ | |
| 802 | + sl_v v = args[i]; | |
| 803 | + if(!issym(v) || !iskeyword(ptr(sl_sym, v))){ | |
| 804 | + args[nn++] = v; | |
| 805 | + continue; | |
| 806 | + } | |
| 807 | + int k; | |
| 808 | + for(k = 0; k < nkeys; k++){ | |
| 809 | + if(args[i] != keys[k]) | |
| 810 | + continue; | |
| 811 | + if(values[k] != sl_unbound) | |
| 812 | + cthrow(error(sl_errarg, "duplicate keyword %s ", sym_name(keys[k])), args); | |
| 813 | + if(i+1 >= nargs) | |
| 814 | + cthrow(error(sl_errarg, "keyword %s requires an argument", sym_name(keys[k])), args); | |
| 815 | + values[k] = args[++i]; | |
| 816 | + break; | |
| 817 | + } | |
| 818 | + if(k == nkeys) | |
| 819 | + args[nn++] = v; | |
| 820 | + } | |
| 821 | + if(sl_unlikely(nn < nreq)) | |
| 822 | + cthrow(error(sl_errarg, "required argument missing"), args); | |
| 823 | + return nn; | |
| 824 | +} | |
| 825 | + | |
| 793 | 826 | /* |
| 794 | 827 | argument layout on stack is |
| 795 | 828 | |--required args--|--opt args--|--kw args--|--rest args... |
| @@ -140,6 +140,9 @@ enum { · 139 unmodified lines | ||
| 140 | 140 | #define vec_type(v) (vec_elt((v), -1) & VEC_TYPE_MASK) |
| 141 | 141 | #define isstruct(v) (vec_type(v) == VEC_STRUCT) |
| 142 | 142 | |
| 143 | +// supplied and non-NIL | |
| 144 | +#define nonnil(v) ((v) != sl_unbound && (v) != sl_nil) | |
| 145 | + | |
| 143 | 146 | // functions ending in _ are unsafe, faster versions |
| 144 | 147 | #define car_(v) (ptr(sl_cons, (v))->car) |
| 145 | 148 | #define cdr_(v) (ptr(sl_cons, (v))->cdr) |
| @@ -227,6 +227,7 @@ _Noreturn void slmain(const u8int *boot, int bootsz, int argc, char **argv) sl_r · 226 unmodified lines | ||
| 227 | 227 | |
| 228 | 228 | sl_v sl_list(sl_v *args, int nargs, bool star) sl_hotfn sl_nonnull(1); |
| 229 | 229 | sl_v sl_do_trycatch(void); |
| 230 | +int sl_process_args(sl_v *args, int nreq, int nargs, const sl_v *keys, int nkeys, sl_v *values); | |
| 230 | 231 | int sl_process_keys(sl_v kwtable, int nreq, int nkw, int nopt, usize bp, int nargs, int va); |
| 231 | 232 | sl_v sl_vm_applyn(int n) sl_hotfn; |
| 232 | 233 | sl_v sl_vm_apply_cl(int nargs) sl_hotfn; |
| @@ -719,16 +719,16 @@ get_radix_arg(sl_v arg) · 718 unmodified lines | ||
| 719 | 719 | |
| 720 | 720 | BUILTIN("str->num", str_2_num) |
| 721 | 721 | { |
| 722 | − if(sl_unlikely(nargs != 1 && nargs != 3)) | |
| 723 | − argcount(2); | |
| 722 | + sl_v keys[] = {basesym}, values[1]; | |
| 723 | + nargs = sl_process_args(args, 1, nargs, keys, nelem(keys), values); | |
| 724 | + if(nargs != 1) | |
| 725 | + argcount(1); | |
| 724 | 726 | char *s = tostr(args[0]), *e; |
| 725 | 727 | sl_v n; |
| 726 | 728 | int base = 10; |
| 727 | − if(nargs == 3 && sl_unlikely(args[1] != basesym)) | |
| 728 | − bthrow(error(sl_errarg, "invalid argument at position %d", 1)); | |
| 729 | − if(nargs == 3 && args[2] != sl_nil){ | |
| 730 | − base = get_radix_arg(args[2]); | |
| 731 | − }else if(s[0] == '#'){ | |
| 729 | + if(nonnil(values[0])) | |
| 730 | + base = get_radix_arg(values[0]); | |
| 731 | + else if(s[0] == '#'){ | |
| 732 | 732 | int c = tolower((u8int)s[1]); |
| 733 | 733 | if(((c == 'b' && (base = 2)) || |
| 734 | 734 | (c == 'o' && (base = 8)) || |