Unified · Split
| @@ -7,7 +7,7 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | static sl_v iosym, rdsym, wrsym, apsym, crsym, truncsym; | 8 | static sl_v iosym, rdsym, wrsym, apsym, crsym, truncsym; |
| 9 | static sl_v linesym, blocksym, memorysym; | 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 | sl_v sl_iooutsym; | 11 | sl_v sl_iooutsym; |
| 12 | const sl_type *sl_iotype; | 12 | const sl_type *sl_iotype; |
| 13 | 13 | ||
| @@ -68,9 +68,9 @@ static bool · 54 unmodified lines | |||
| 68 | isflipped(sl_v v) | 68 | isflipped(sl_v v) |
| 69 | { | 69 | { |
| 70 | bool little; | 70 | bool little; |
| 71 | if(v == lendian) | 71 | if(v == lendiansym) |
| 72 | little = true; | 72 | little = true; |
| 73 | else if(v == bendian) | 73 | else if(v == bendiansym) |
| 74 | little = false; | 74 | little = false; |
| 75 | else | 75 | else |
| 76 | cthrow(error(sl_errarg, "invalid endian specifier"), v); | 76 | cthrow(error(sl_errarg, "invalid endian specifier"), v); |
| @@ -194,19 +194,12 @@ BUILTIN("buffer", buffer) · 117 unmodified lines | |||
| 194 | 194 | ||
| 195 | BUILTIN("read", read) | 195 | BUILTIN("read", read) |
| 196 | { | 196 | { |
| 197 | bool ws = false; | 197 | sl_v keys[] = {wssym}, values[1]; |
| 198 | if(sl_unlikely(nargs >= 2 && nargs <= 3)){ | 198 | nargs = sl_process_args(args, 0, nargs, keys, nelem(keys), values); |
| 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]; | ||
| 208 | if(sl_unlikely(nargs > 1)) | 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 | USED(toio(a, true, true, false)); | 203 | USED(toio(a, true, true, false)); |
| 211 | sl_gc_handle(&a); | 204 | sl_gc_handle(&a); |
| 212 | sl_v v = sl_read_sexpr(a, ws); | 205 | sl_v v = sl_read_sexpr(a, ws); |
| @@ -300,15 +293,11 @@ BUILTIN("io-peek", io_peek) · 87 unmodified lines | |||
| 300 | 293 | ||
| 301 | BUILTIN("io-skip", io_skip) | 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 | if(nargs != 2 && nargs != 4) | 299 | if(nargs != 2 && nargs != 4) |
| 304 | argcount(2); | 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 | ios *s = toio(args[0], true, false, false); | 301 | ios *s = toio(args[0], true, false, false); |
| 313 | soffset off = tooffset(args[1]); | 302 | soffset off = tooffset(args[1]); |
| 314 | soffset res = ios_skip(s, off, end); | 303 | soffset res = ios_skip(s, off, end); |
| @@ -616,8 +605,8 @@ io_init(void) · 301 unmodified lines | |||
| 616 | wssym = mk_csym(":whitespace"); | 605 | wssym = mk_csym(":whitespace"); |
| 617 | endsym = mk_csym(":end"); | 606 | endsym = mk_csym(":end"); |
| 618 | ioinsym = mk_csym("*io-in*"); | 607 | ioinsym = mk_csym("*io-in*"); |
| 619 | bendian = mk_csym(":big-endian"); | 608 | bendiansym = mk_csym(":big-endian"); |
| 620 | lendian = mk_csym(":little-endian"); | 609 | lendiansym = mk_csym(":little-endian"); |
| 621 | sl_iooutsym = mk_csym("*io-out*"); | 610 | sl_iooutsym = mk_csym("*io-out*"); |
| 622 | sl_iotype = define_opaque_type(iosym, sizeof(ios), &io_vtable, nil); | 611 | sl_iotype = define_opaque_type(iosym, sizeof(ios), &io_vtable, nil); |
| 623 | set(mk_csym("*stdout*"), cvalue_from_ref(sl_iotype, ios_stdout, sizeof(ios))); | 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 | return v; | 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 | argument layout on stack is | 827 | argument layout on stack is |
| 795 | |--required args--|--opt args--|--kw args--|--rest args... | 828 | |--required args--|--opt args--|--kw args--|--rest args... |
| @@ -140,6 +140,9 @@ enum { · 139 unmodified lines | |||
| 140 | #define vec_type(v) (vec_elt((v), -1) & VEC_TYPE_MASK) | 140 | #define vec_type(v) (vec_elt((v), -1) & VEC_TYPE_MASK) |
| 141 | #define isstruct(v) (vec_type(v) == VEC_STRUCT) | 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 | // functions ending in _ are unsafe, faster versions | 146 | // functions ending in _ are unsafe, faster versions |
| 144 | #define car_(v) (ptr(sl_cons, (v))->car) | 147 | #define car_(v) (ptr(sl_cons, (v))->car) |
| 145 | #define cdr_(v) (ptr(sl_cons, (v))->cdr) | 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 | sl_v sl_list(sl_v *args, int nargs, bool star) sl_hotfn sl_nonnull(1); | 228 | sl_v sl_list(sl_v *args, int nargs, bool star) sl_hotfn sl_nonnull(1); |
| 229 | sl_v sl_do_trycatch(void); | 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 | int sl_process_keys(sl_v kwtable, int nreq, int nkw, int nopt, usize bp, int nargs, int va); | 231 | int sl_process_keys(sl_v kwtable, int nreq, int nkw, int nopt, usize bp, int nargs, int va); |
| 231 | sl_v sl_vm_applyn(int n) sl_hotfn; | 232 | sl_v sl_vm_applyn(int n) sl_hotfn; |
| 232 | sl_v sl_vm_apply_cl(int nargs) sl_hotfn; | 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 | BUILTIN("str->num", str_2_num) | 720 | BUILTIN("str->num", str_2_num) |
| 721 | { | 721 | { |
| 722 | if(sl_unlikely(nargs != 1 && nargs != 3)) | 722 | sl_v keys[] = {basesym}, values[1]; |
| 723 | argcount(2); | 723 | nargs = sl_process_args(args, 1, nargs, keys, nelem(keys), values); |
| 724 | if(nargs != 1) | ||
| 725 | argcount(1); | ||
| 724 | char *s = tostr(args[0]), *e; | 726 | char *s = tostr(args[0]), *e; |
| 725 | sl_v n; | 727 | sl_v n; |
| 726 | int base = 10; | 728 | int base = 10; |
| 727 | if(nargs == 3 && sl_unlikely(args[1] != basesym)) | 729 | if(nonnil(values[0])) |
| 728 | bthrow(error(sl_errarg, "invalid argument at position %d", 1)); | 730 | base = get_radix_arg(values[0]); |
| 729 | if(nargs == 3 && args[2] != sl_nil){ | 731 | else if(s[0] == '#'){ |
| 730 | base = get_radix_arg(args[2]); | ||
| 731 | }else if(s[0] == '#'){ | ||
| 732 | int c = tolower((u8int)s[1]); | 732 | int c = tolower((u8int)s[1]); |
| 733 | if(((c == 'b' && (base = 2)) || | 733 | if(((c == 'b' && (base = 2)) || |
| 734 | (c == 'o' && (base = 8)) || | 734 | (c == 'o' && (base = 8)) || |