diff --git a/Makefile b/Makefile index 6b2ce258..01e3647c 100644 --- a/Makefile +++ b/Makefile @@ -81,10 +81,9 @@ endif all: chibi-scheme$(EXE) libs COMPILED_LIBS := lib/srfi/27/rand$(SO) lib/srfi/33/bit$(SO) \ - lib/srfi/69/hash$(SO) lib/srfi/98/env$(SO) \ - lib/chibi/ast$(SO) lib/chibi/net$(SO) \ - lib/chibi/filesystem$(SO) lib/chibi/process$(SO) \ - lib/chibi/time$(SO) lib/chibi/heap-stats$(SO) + lib/srfi/69/hash$(SO) lib/srfi/98/env$(SO) lib/chibi/ast$(SO) \ + lib/chibi/net$(SO) lib/chibi/filesystem$(SO) lib/chibi/process$(SO) \ + lib/chibi/time$(SO) lib/chibi/system$(SO) lib/chibi/heap-stats$(SO) libs: $(COMPILED_LIBS) diff --git a/TODO b/TODO index 854cceb3..93f7c837 100644 --- a/TODO +++ b/TODO @@ -60,6 +60,7 @@ - State "DONE" [2009-07-07 Tue 14:42] ** TODO unicode ** TODO threads +** TODO virtual ports ** DONE dynamic-wind - State "DONE" [2009-12-26 Sat 01:51] Adapted a version from Scheme48. @@ -138,6 +139,7 @@ ** TODO overall cleanup ** TODO user documentation ** TODO thorough source documentation +** TODO full test suite for libraries * distribution ** TODO packaging format diff --git a/eval.c b/eval.c index 26f212a3..4546318f 100644 --- a/eval.c +++ b/eval.c @@ -1609,13 +1609,13 @@ sexp sexp_vm (sexp ctx, sexp proc) { break; case SEXP_OP_SLOT_REF: if (! sexp_check_tag(_ARG1, _UWORD0)) - sexp_raise("slot-ref: bad type", sexp_list2(ctx, sexp_c_string(ctx, sexp_type_name_by_index(_UWORD0), -1), _ARG1)); + sexp_raise("slot-ref: bad type", sexp_list2(ctx, sexp_c_string(ctx, sexp_type_name_by_index(ctx, _UWORD0), -1), _ARG1)); _ARG1 = sexp_slot_ref(_ARG1, _UWORD1); ip += sizeof(sexp)*2; break; case SEXP_OP_SLOT_SET: if (! sexp_check_tag(_ARG1, _UWORD0)) - sexp_raise("slot-set!: bad type", sexp_list2(ctx, sexp_c_string(ctx, sexp_type_name_by_index(_UWORD0), -1), _ARG1)); + sexp_raise("slot-set!: bad type", sexp_list2(ctx, sexp_c_string(ctx, sexp_type_name_by_index(ctx, _UWORD0), -1), _ARG1)); else if (sexp_immutablep(_ARG1)) sexp_raise("slot-set!: immutable object", sexp_list1(ctx, _ARG1)); sexp_slot_set(_ARG1, _UWORD1, _ARG2); @@ -2154,12 +2154,27 @@ define_math_op(sexp_tan, tan) define_math_op(sexp_asin, asin) define_math_op(sexp_acos, acos) define_math_op(sexp_atan, atan) -define_math_op(sexp_sqrt, sqrt) define_math_op(sexp_round, round) define_math_op(sexp_trunc, trunc) define_math_op(sexp_floor, floor) define_math_op(sexp_ceiling, ceil) +static sexp sexp_sqrt (sexp ctx, sexp z) { + double d, r; + if (sexp_flonump(z)) + d = sexp_flonum_value(z); + else if (sexp_fixnump(z)) + d = (double)sexp_unbox_fixnum(z); + maybe_convert_bignum(z) /* XXXX add bignum sqrt */ + else + return sexp_type_exception(ctx, "not a number", z); + r = sqrt(d); + if (sexp_fixnump(z) && ((r*r) == (double)sexp_unbox_fixnum(z))) + return sexp_make_fixnum(round(r)); + else + return sexp_make_flonum(ctx, r); +} + #endif static sexp sexp_expt (sexp ctx, sexp x, sexp e) { @@ -2354,7 +2369,7 @@ sexp sexp_make_constructor (sexp ctx, sexp name, sexp type) { sexp_uint_t type_size; if (! sexp_fixnump(type)) return sexp_type_exception(ctx, "make-constructor: bad type", type); - type_size = sexp_type_size_base(&(sexp_type_specs[sexp_unbox_fixnum(type)])); + type_size = sexp_type_size_base(sexp_type_by_index(ctx, sexp_unbox_fixnum(type))); return sexp_make_opcode(ctx, name, sexp_make_fixnum(SEXP_OPC_CONSTRUCTOR), sexp_make_fixnum(SEXP_OP_MAKE), SEXP_ZERO, SEXP_ZERO, SEXP_ZERO, SEXP_ZERO, SEXP_ZERO, type, diff --git a/gc.c b/gc.c index e53b83af..79ff4b87 100644 --- a/gc.c +++ b/gc.c @@ -44,17 +44,17 @@ static sexp_heap sexp_heap_last (sexp_heap h) { return h; } -sexp_uint_t sexp_allocated_bytes (sexp x) { +sexp_uint_t sexp_allocated_bytes (sexp ctx, sexp x) { sexp_uint_t res; sexp t; - if ((! sexp_pointerp(x)) || (sexp_pointer_tag(x) >= sexp_num_types)) + if ((! sexp_pointerp(x)) || (sexp_pointer_tag(x) >= sexp_context_num_types(ctx))) return sexp_heap_align(1); - t = &(sexp_type_specs[sexp_pointer_tag(x)]); + t = sexp_object_type(ctx, x); res = sexp_type_size_of_object(t, x); return res; } -void sexp_mark (sexp x) { +void sexp_mark (sexp ctx, sexp x) { sexp_sint_t i, len; sexp t, *p; struct sexp_gc_var_t *saves; @@ -64,13 +64,13 @@ void sexp_mark (sexp x) { sexp_gc_mark(x) = 1; if (sexp_contextp(x)) for (saves=sexp_context_saves(x); saves; saves=saves->next) - if (saves->var) sexp_mark(*(saves->var)); - t = &(sexp_type_specs[sexp_pointer_tag(x)]); + if (saves->var) sexp_mark(ctx, *(saves->var)); + t = sexp_object_type(ctx, x); p = (sexp*) (((char*)x) + sexp_type_field_base(t)); len = sexp_type_num_slots_of_object(t, x) - 1; if (len >= 0) { for (i=0; isize); continue; } - size = sexp_heap_align(sexp_allocated_bytes(p)); + size = sexp_heap_align(sexp_allocated_bytes(ctx, p)); if ((! sexp_gc_mark(p)) && (! stack_references_pointer_p(ctx, p))) { /* free p */ - finalizer = sexp_type_finalize(sexp_object_type(p)); + finalizer = sexp_type_finalize(sexp_object_type(ctx, p)); if (finalizer) finalizer(ctx, p); sum_freed += size; if (((((char*)q) + q->size) == (char*)p) && (q != h->free_list)) { @@ -159,9 +159,9 @@ sexp sexp_gc (sexp ctx, size_t *sum_freed) { #if SEXP_USE_GLOBAL_SYMBOLS int i; for (i=0; iimmutablep) #define sexp_freep(x) ((x)->freep) -#define sexp_object_type(x) (&(sexp_type_specs[(x)->tag])) -#define sexp_object_type_name(x) (sexp_type_name(sexp_object_type(x))) -#define sexp_type_name_by_index(x) (sexp_type_name(&(sexp_type_specs[(x)]))) - -#define sexp_type_size_of_object(t, x) \ - (((sexp_uint_t*)((char*)x + sexp_type_size_off(t)))[0] \ - * sexp_type_size_scale(t) \ - + sexp_type_size_base(t)) -#define sexp_type_num_slots_of_object(t, x) \ - (((sexp_uint_t*)((char*)x + sexp_type_field_len_off(t)))[0] \ - * sexp_type_field_len_scale(t) \ - + sexp_type_field_len_base(t)) -#define sexp_type_num_eq_slots_of_object(t, x) \ - (((sexp_uint_t*)((char*)x + sexp_type_field_len_off(t)))[0] \ - * sexp_type_field_len_scale(t) \ - + sexp_type_field_eq_len_base(t)) - #define sexp_check_tag(x,t) (sexp_pointerp(x) && (sexp_pointer_tag(x) == (t))) #define sexp_slot_ref(x,i) (((sexp*)&((x)->value))[i]) @@ -645,11 +628,37 @@ SEXP_API sexp sexp_make_integer(sexp ctx, sexp_sint_t x); #endif #if SEXP_USE_GLOBAL_TYPES -#define sexp_context_types(ctx) sexp_type_specs +SEXP_API struct sexp_struct *sexp_type_specs; +#define sexp_context_types(ctx) sexp_type_specs +#define sexp_type_by_index(ctx,i) (&(sexp_context_types(ctx)[i])) +#define sexp_context_num_types(ctx) sexp_num_types +#define sexp_context_type_array_size(ctx) sexp_type_array_size #else -#define sexp_context_types(ctx) sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)) +#define sexp_context_types(ctx) sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)) +#define sexp_type_by_index(ctx,i) (sexp_context_types(ctx)[i]) +#define sexp_context_num_types(ctx) \ + sexp_unbox_fixnum(sexp_global(ctx, SEXP_G_NUM_TYPES)) +#define sexp_context_type_array_size(ctx) \ + sexp_vector_length(sexp_global(ctx, SEXP_G_TYPES)) #endif +#define sexp_object_type(ctx,x) (sexp_type_by_index(ctx, ((x)->tag))) +#define sexp_object_type_name(ctx,x) (sexp_type_name(sexp_object_type(ctx, x))) +#define sexp_type_name_by_index(ctx,i) (sexp_type_name(sexp_type_by_index(ctx,i))) + +#define sexp_type_size_of_object(t, x) \ + (((sexp_uint_t*)((char*)x + sexp_type_size_off(t)))[0] \ + * sexp_type_size_scale(t) \ + + sexp_type_size_base(t)) +#define sexp_type_num_slots_of_object(t, x) \ + (((sexp_uint_t*)((char*)x + sexp_type_field_len_off(t)))[0] \ + * sexp_type_field_len_scale(t) \ + + sexp_type_field_len_base(t)) +#define sexp_type_num_eq_slots_of_object(t, x) \ + (((sexp_uint_t*)((char*)x + sexp_type_field_len_off(t)))[0] \ + * sexp_type_field_len_scale(t) \ + + sexp_type_field_eq_len_base(t)) + #define sexp_context_top(x) (sexp_stack_top(sexp_context_stack(x))) #define sexp_type_tag(x) ((x)->value.type.tag) @@ -692,6 +701,7 @@ enum sexp_context_globals { #endif #if ! SEXP_USE_GLOBAL_TYPES SEXP_G_TYPES, + SEXP_G_NUM_TYPES, #endif SEXP_G_OOM_ERROR, /* out of memory exception object */ SEXP_G_OOS_ERROR, /* out of stack exception object */ @@ -768,7 +778,6 @@ SEXP_API sexp sexp_buffered_flush (sexp ctx, sexp p); #define sexp_newline(ctx, p) sexp_write_char(ctx, '\n', (p)) -SEXP_API struct sexp_struct *sexp_type_specs; SEXP_API sexp sexp_make_context(sexp ctx); SEXP_API sexp sexp_alloc_tagged(sexp ctx, size_t size, sexp_uint_t tag); SEXP_API sexp sexp_cons(sexp ctx, sexp head, sexp tail); diff --git a/lib/chibi/filesystem.module b/lib/chibi/filesystem.module index fe0fbdcf..82a8ebda 100644 --- a/lib/chibi/filesystem.module +++ b/lib/chibi/filesystem.module @@ -15,6 +15,11 @@ file-regular? file-directory? file-character? file-block? file-fifo? file-link? file-socket? + get-file-descriptor-flags set-file-descriptor-flags! + get-file-descriptor-status set-file-descriptor-status! + open/read open/write open/read-write + open/create open/exclusive open/truncate + open/append open/non-block ) (import-immutable (scheme)) (include-shared "filesystem") diff --git a/lib/chibi/filesystem.stub b/lib/chibi/filesystem.stub index 69b50a31..8c42466f 100644 --- a/lib/chibi/filesystem.stub +++ b/lib/chibi/filesystem.stub @@ -2,6 +2,7 @@ (c-system-include "sys/types.h") (c-system-include "unistd.h") (c-system-include "dirent.h") +(c-system-include "fcntl.h") (define-c-type DIR finalizer: closedir) @@ -86,3 +87,29 @@ (define-c errno (open-pipe "pipe") ((result (array int 2)))) (define-c errno (make-fifo "mkfifo") (string (default #o644 int))) + +(define-c int (get-file-descriptor-flags "fcntl") + (int (value F_GETFD int))) +(define-c errno (set-file-descriptor-flags! "fcntl") + (int (value F_SETFD int) long)) + +(define-c int (get-file-descriptor-status "fcntl") + (int (value F_GETFL int))) +(define-c errno (set-file-descriptor-status! "fcntl") + (int (value F_SETFL int) long)) + +;; (define-c int (get-file-descriptor-lock "fcntl") +;; (int (value F_GETLK int) flock)) +;; (define-c errno (set-file-descriptor-lock! "fcntl") +;; (int (value F_SETLK int) flock)) +;; (define-c errno (try-set-file-descriptor-lock! "fcntl") +;; (int (value F_SETLKW int) flock)) + +(define-c-const int (open/read "O_RDONLY")) +(define-c-const int (open/write "O_WRONLY")) +(define-c-const int (open/read-write "O_RDWR")) +(define-c-const int (open/create "O_CREAT")) +(define-c-const int (open/exclusive "O_EXCL")) +(define-c-const int (open/truncate "O_TRUNC")) +(define-c-const int (open/append "O_APPEND")) +(define-c-const int (open/non-block "O_NONBLOCK")) diff --git a/lib/chibi/heap-stats.c b/lib/chibi/heap-stats.c index 8b928fe4..381d0b31 100644 --- a/lib/chibi/heap-stats.c +++ b/lib/chibi/heap-stats.c @@ -42,7 +42,7 @@ static void sexp_print_simple (sexp ctx, sexp x, sexp out, int depth) { } else { print_name: sexp_write_string(ctx, "#<", out); - sexp_write_string(ctx, sexp_object_type_name(x), out); + sexp_write_string(ctx, sexp_object_type_name(ctx, x), out); sexp_write_string(ctx, ">", out); } } @@ -97,7 +97,7 @@ static sexp sexp_heap_walk (sexp ctx, int depth, int printp) { res = SEXP_NULL; for (i=hi_type; i>0; i--) if (stats[i]) { - name = sexp_intern(ctx, sexp_type_name_by_index(i)); + name = sexp_intern(ctx, sexp_type_name_by_index(ctx, i)); tmp = sexp_cons(ctx, name, sexp_make_fixnum(stats[i])); res = sexp_cons(ctx, tmp, res); } diff --git a/lib/chibi/net.module b/lib/chibi/net.module index 14f3801f..41cdafe4 100644 --- a/lib/chibi/net.module +++ b/lib/chibi/net.module @@ -4,7 +4,7 @@ address-info-family address-info-socket-type address-info-protocol address-info-address address-info-address-length address-info-next) (import-immutable (scheme)) - (import (chibi posix)) + (import (chibi filesystem)) (include-shared "net") (include "net.scm")) diff --git a/lib/chibi/net.scm b/lib/chibi/net.scm index a6fd78e0..0ac1adca 100644 --- a/lib/chibi/net.scm +++ b/lib/chibi/net.scm @@ -13,8 +13,8 @@ (address-info-address addr) (address-info-address-length addr))) (lp (address-info-next addr)) - (let ((in (open-input-fd sock)) - (out (open-output-fd sock))) + (let ((in (open-input-file-descriptor sock)) + (out (open-output-file-descriptor sock))) (let ((res (proc in out))) (close-input-port in) res)))))))) diff --git a/lib/chibi/net.stub b/lib/chibi/net.stub index 8e595f8f..0d72bc90 100644 --- a/lib/chibi/net.stub +++ b/lib/chibi/net.stub @@ -23,4 +23,3 @@ (define-c int listen (int int)) (define-c int socket (int int int)) (define-c int connect (int sockaddr int)) - diff --git a/lib/chibi/process.module b/lib/chibi/process.module index 3e3f2cdb..fe03c2e5 100644 --- a/lib/chibi/process.module +++ b/lib/chibi/process.module @@ -1,6 +1,6 @@ (define-module (chibi process) - (export exit sleep fork kill execute waitpid + (export exit sleep alarm fork kill execute waitpid set-signal-action! make-signal-set signal-set-contains? signal-set-fill! signal-set-add! signal-set-delete! current-signal-mask diff --git a/lib/chibi/process.stub b/lib/chibi/process.stub index 5c0f1a34..7dbca7eb 100644 --- a/lib/chibi/process.stub +++ b/lib/chibi/process.stub @@ -59,12 +59,14 @@ (define-c errno (current-signal-mask "sigprocmask") ((value SIG_BLOCK int) (value NULL sigset_t) (result sigset_t))) +(define-c unsigned-int alarm (unsigned-int)) +(define-c unsigned-int sleep (unsigned-int)) + (define-c pid_t fork ()) ;;(define-c pid_t wait ((result int))) (define-c pid_t waitpid (int (result int) int)) (define-c errno kill (int int)) ;;(define-c errno raise (int)) -(define-c unsigned-int sleep (unsigned-int)) (define-c void exit (int)) (define-c int (execute execvp) (string (array string))) diff --git a/lib/srfi/1/search.scm b/lib/srfi/1/search.scm index 335faf4c..4ab9eb7d 100644 --- a/lib/srfi/1/search.scm +++ b/lib/srfi/1/search.scm @@ -30,10 +30,11 @@ (define (any pred ls . lists) (if (null? lists) - (let lp ((ls ls)) (and (pair? ls) (if (pred (car ls)) #t (lp (cdr ls))))) + (let lp ((ls ls)) (and (pair? ls) (if (pred (car ls)) (car ls) (lp (cdr ls))))) (let lp ((lists (cons ls lists))) (and (every pair? lists) - (if (apply pred (map car lists)) #t (lp (map cdr lists))))))) + (let ((args (map car lists))) + (if (apply pred args) args (lp (map cdr lists)))))))) (define (every pred ls . lists) (if (null? lists) diff --git a/lib/srfi/69/hash.c b/lib/srfi/69/hash.c index 9ab056e4..51da2b62 100644 --- a/lib/srfi/69/hash.c +++ b/lib/srfi/69/hash.c @@ -44,7 +44,7 @@ static sexp sexp_string_ci_hash (sexp ctx, sexp str, sexp bound) { sexp_unbox_fixnum(bound))); } -static sexp_uint_t hash_one (sexp obj, sexp_uint_t bound, sexp_sint_t depth) { +static sexp_uint_t hash_one (sexp ctx, sexp obj, sexp_uint_t bound, sexp_sint_t depth) { sexp_uint_t acc = FNV_OFFSET_BASIS, size; sexp_sint_t i, len; sexp t, *p; @@ -57,7 +57,7 @@ static sexp_uint_t hash_one (sexp obj, sexp_uint_t bound, sexp_sint_t depth) { #endif if (sexp_pointerp(obj)) { if (depth) { - t = &(sexp_type_specs[sexp_pointer_tag(obj)]); + t = sexp_object_type(ctx, obj); p = (sexp*) (((char*)obj) + sexp_type_field_base(t)); p0 = ((char*)obj) + offsetof(struct sexp_struct, value); if ((sexp)p == obj) p=(sexp*)p0; @@ -72,7 +72,7 @@ static sexp_uint_t hash_one (sexp obj, sexp_uint_t bound, sexp_sint_t depth) { depth--; for (i=0; i= SEXP_MAXIMUM_TYPES) { - fprintf(stderr, "chibi: exceeded maximum type limit\n"); - res = SEXP_FALSE; +#if SEXP_USE_GLOBAL_TYPES + struct sexp_struct *new, *tmp; +#else + sexp *v1, *v2; +#endif + sexp res, type; + sexp_uint_t i, len, num_types=sexp_context_num_types(ctx), + type_array_size=sexp_context_type_array_size(ctx); + if (num_types >= SEXP_MAXIMUM_TYPES) { + res = sexp_user_exception(ctx, SEXP_FALSE, "register-type: exceeded maximum type limit", name); } else if (! sexp_stringp(name)) { res = sexp_type_exception(ctx, "register-type: not a string", name); } else { - if (sexp_num_types >= sexp_type_array_size) { - len = sexp_type_array_size*2; + if (num_types >= type_array_size) { + len = type_array_size*2; if (len > SEXP_MAXIMUM_TYPES) len = SEXP_MAXIMUM_TYPES; +#if SEXP_USE_GLOBAL_TYPES new = malloc(len * sizeof(_sexp_type_specs[0])); - for (i=0; i sexp_num_types) free(tmp); + if (type_array_size > num_types) free(tmp); sexp_type_array_size = len; +#else + res = sexp_make_vector(ctx, sexp_make_fixnum(len), SEXP_VOID); + v1 = sexp_vector_data(res); + v2 = sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)); + for (i=0; i', out); break; diff --git a/tests/r5rs-tests.scm b/tests/r5rs-tests.scm index c35d71df..85b3a801 100644 --- a/tests/r5rs-tests.scm +++ b/tests/r5rs-tests.scm @@ -168,6 +168,10 @@ (test #t (equal? 2 2)) +(test #f (eqv? 2 2.0)) + +(test #f (equal? 2.0 2)) + (test #t (equal? (make-vector 5 'a) (make-vector 5 'a))) (test 4 (max 3 4)) @@ -212,21 +216,21 @@ (test 288 (lcm 32 -36)) -(test -5 (floor -4.3)) +(test #t (= -5 (floor -4.3))) -(test -4 (ceiling -4.3)) +(test #t (= -4 (ceiling -4.3))) -(test -4 (truncate -4.3)) +(test #t (= -4 (truncate -4.3))) -(test -4 (round -4.3)) +(test #t (= -4 (round -4.3))) -(test 3 (floor 3.5)) +(test #t (= 3 (floor 3.5))) -(test 4 (ceiling 3.5)) +(test #t (= 4 (ceiling 3.5))) -(test 3 (truncate 3.5)) +(test #t (= 3 (truncate 3.5))) -(test 4 (round 3.5)) +(test #t (= 4 (round 3.5))) (test 100 (string->number "100")) diff --git a/tools/genstubs.scm b/tools/genstubs.scm index a6a9fc98..bb55fcfd 100755 --- a/tools/genstubs.scm +++ b/tools/genstubs.scm @@ -238,6 +238,10 @@ ;; function objects (define (parse-func func) + (if (not (and (= 3 (length func)) + (or (identifier? (cadr func)) (list (cadr func))) + (list (caddr func)))) + (error "bad function definition" func)) (let* ((ret-type (parse-type (car func))) (scheme-name (if (pair? (cadr func)) (caadr func) (cadr func))) (c-name (if (pair? (cadr func)) @@ -678,7 +682,7 @@ (lambda (x) (let ((len (get-array-length func x))) (cat " " (type-c-name (type-base x)) " ") - (if (or (type-pointer? x) (and (type-array x) (not (number? len)))) + (if (and (type-array x) (not (number? len))) (cat "*")) (cat (if (type-auto-expand? x) "buf" "tmp") (type-index-string x)) (if (number? len) @@ -747,7 +751,8 @@ (if (not (number? (type-array a))) (cat " tmp" (type-index a) "[i] = NULL;\n"))) ((and (type-result? a) (not (basic-type? a)) - (not (type-free? a)) (not (type-auto-expand? a)) + (not (type-free? a)) (not (type-pointer? a)) + (not (type-auto-expand? a)) (or (not (type-array a)) (not (integer? (get-array-length func a))))) (cat " tmp" (type-index a) " = malloc(sizeof(tmp" (type-index a) @@ -768,6 +773,7 @@ (cond ((any (lambda (y) (and (type-array y) + (type-auto-expand? y) (eq? x (get-array-length func y)))) (func-c-args func)) => (lambda (y) (cat "len" (type-index y))))