diff --git a/debug.c b/debug.c index f08e818a..50fa6cb7 100644 --- a/debug.c +++ b/debug.c @@ -6,11 +6,12 @@ static const char* reverse_opcode_names[] = {"NOOP", "ERROR", "RESUMECC", "CALLCC", "APPLY1", "TAIL-CALL", "CALL", "FCALL0", "FCALL1", "FCALL2", "FCALL3", "FCALL4", "EVAL", "JUMP-UNLESS", "JUMP", "PUSH", "DROP", "STACK-REF", "LOCAL-REF", "LOCAL-SET", - "CLOSURE-REF", "VECTOR-REF", "VECTOR-SET", "VECTOR-LENGTH", - "STRING-REF", "STRING-SET", "STRING-LENGTH", - "MAKE-PROCEDURE", "MAKE-VECTOR", "NULLP", "INTEGERP", "SYMBOLP", "CHARP", - "EOFP", "TYPEP", "CAR", "CDR", "SET-CAR", "SET-CDR", "CONS", "ADD", "SUB", - "MUL", "DIV", "QUOT", "MOD", "NEG", "INV", "LT", "LE", "EQV", "EQ", + "CLOSURE-REF", "VECTOR-REF", "VECTOR-SET", "VECTOR-LENGTH", "STRING-REF", + "STRING-SET", "STRING-LENGTH", "MAKE-PROCEDURE", "MAKE-VECTOR", "NULL?", + "FIXNUM?", "SYMBOL?", "CHAR?", + "EOF?", "TYPEP", "CAR", "CDR", "SET-CAR", "SET-CDR", "CONS", "ADD", "SUB", + "MUL", "DIV", "QUOT", "MOD", "NEG", "INV", "LT", "LE", "EQN", "EQ", + "EXACT->INEXACT", "INEXACT->EXACT", "CHAR->INTEGER", "INTEGER->CHAR", "CHAR-UPCASE", "CHAR-DOWNCASE", "DISPLAY", "WRITE", "WRITE-CHAR", "NEWLINE", "FLUSH-OUTPUT", "READ", "READ-CHAR", "RET", "DONE", diff --git a/eval.c b/eval.c index ea8f8625..0bcb1d7e 100644 --- a/eval.c +++ b/eval.c @@ -1316,20 +1316,72 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) { else sexp_raise("/: not a number", sexp_list1(_ARG1)); break; case OP_LT: - _ARG2 = sexp_make_boolean(sexp_unbox_integer(_ARG1) - < sexp_unbox_integer(_ARG2)); + if (sexp_integerp(_ARG1) && sexp_integerp(_ARG2)) + i = _ARG1 < _ARG2; +#if USE_FLONUMS + else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2)) + i = sexp_flonum_value(_ARG1) < sexp_flonum_value(_ARG2); + else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2)) + i = sexp_flonum_value(_ARG1) < (double)sexp_unbox_integer(_ARG2); + else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2)) + i = (double)sexp_unbox_integer(_ARG1) < sexp_flonum_value(_ARG2); +#endif + else sexp_raise("<: not a number", sexp_list2(_ARG1, _ARG2)); + _ARG2 = sexp_make_boolean(i); top--; break; case OP_LE: - _ARG2 = sexp_make_boolean(sexp_unbox_integer(_ARG1) - <= sexp_unbox_integer(_ARG2)); + if (sexp_integerp(_ARG1) && sexp_integerp(_ARG2)) + i = _ARG1 <= _ARG2; +#if USE_FLONUMS + else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2)) + i = sexp_flonum_value(_ARG1) <= sexp_flonum_value(_ARG2); + else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2)) + i = sexp_flonum_value(_ARG1) <= (double)sexp_unbox_integer(_ARG2); + else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2)) + i = (double)sexp_unbox_integer(_ARG1) <= sexp_flonum_value(_ARG2); +#endif + else sexp_raise("<=: not a number", sexp_list2(_ARG1, _ARG2)); + _ARG2 = sexp_make_boolean(i); + top--; + break; + case OP_EQN: + if (sexp_integerp(_ARG1) && sexp_integerp(_ARG2)) + i = _ARG1 == _ARG2; +#if USE_FLONUMS + else if (sexp_flonump(_ARG1) && sexp_flonump(_ARG2)) + i = sexp_flonum_value(_ARG1) == sexp_flonum_value(_ARG2); + else if (sexp_flonump(_ARG1) && sexp_integerp(_ARG2)) + i = sexp_flonum_value(_ARG1) == (double)sexp_unbox_integer(_ARG2); + else if (sexp_integerp(_ARG1) && sexp_flonump(_ARG2)) + i = (double)sexp_unbox_integer(_ARG1) == sexp_flonum_value(_ARG2); +#endif + else sexp_raise("=: not a number", sexp_list2(_ARG1, _ARG2)); + _ARG2 = sexp_make_boolean(i); top--; break; case OP_EQ: - case OP_EQV: _ARG2 = sexp_make_boolean(_ARG1 == _ARG2); top--; break; + case OP_FIX2FLO: + if (sexp_integerp(_ARG1)) + _ARG1 = sexp_integer_to_flonum(_ARG1); + else +#if USE_FLONUMS + if (! sexp_flonump(_ARG1)) +#endif + sexp_raise("exact->inexact: not a number", sexp_list1(_ARG1)); + break; + case OP_FLO2FIX: +#if USE_FLONUMS + if (sexp_flonump(_ARG1)) + _ARG1 = sexp_make_integer((sexp_sint_t)sexp_flonum_value(_ARG1)); + else +#endif + if (! sexp_integerp(_ARG1)) + sexp_raise("inexact->exact: not a number", sexp_list1(_ARG1)); + break; case OP_CHAR2INT: _ARG1 = sexp_make_integer(sexp_unbox_character(_ARG1)); break; diff --git a/eval.h b/eval.h index 494c25fb..8a7a791b 100644 --- a/eval.h +++ b/eval.h @@ -7,10 +7,6 @@ #include "sexp.h" -#if USE_MATH -#include -#endif - /************************* additional types ***************************/ #define INIT_BCODE_SIZE 128 @@ -107,8 +103,10 @@ enum opcode_names { OP_INV, OP_LT, OP_LE, - OP_EQV, + OP_EQN, OP_EQ, + OP_FIX2FLO, + OP_FLO2FIX, OP_CHAR2INT, OP_INT2CHAR, OP_CHAR_UPCASE, diff --git a/init.scm b/init.scm index 3ab9d4f7..78332557 100644 --- a/init.scm +++ b/init.scm @@ -1,8 +1,7 @@ ;; let-syntax letrec-syntax syntax-rules -;; number? complex? real? rational? integer? exact? inexact? ;; remainder modulo -;; exact->inexact inexact->exact number->string string->number +;; number->string string->number ;; symbol->string string->symbol ;; char-alphabetic? char-numeric? char-whitespace? ;; char-upper-case? char-lower-case? @@ -15,16 +14,12 @@ ;; with-input-from-file with-output-to-file ;; peek-char char-ready? -(define (not x) (if x #f #t)) -(define (boolean? x) (if (eq? x #t) #t (eq? x #f))) - ;; provide c[ad]{2,4}r (define (caar x) (car (car x))) (define (cadr x) (car (cdr x))) (define (cdar x) (cdr (car x))) (define (cddr x) (cdr (cdr x))) - (define (caaar x) (car (car (car x)))) (define (caadr x) (car (car (cdr x)))) (define (cadar x) (car (cdr (car x)))) @@ -33,23 +28,22 @@ (define (cdadr x) (cdr (car (cdr x)))) (define (cddar x) (cdr (cdr (car x)))) (define (cdddr x) (cdr (cdr (cdr x)))) - -;; (define (caaaar x) (car (car (car (car x))))) -;; (define (caaadr x) (car (car (car (cdr x))))) -;; (define (caadar x) (car (car (cdr (car x))))) -;; (define (caaddr x) (car (car (cdr (cdr x))))) -;; (define (cadaar x) (car (cdr (car (car x))))) -;; (define (cadadr x) (car (cdr (car (cdr x))))) -;; (define (caddar x) (car (cdr (cdr (car x))))) -;; (define (cadddr x) (car (cdr (cdr (cdr x))))) -;; (define (cdaaar x) (cdr (car (car (car x))))) -;; (define (cdaadr x) (cdr (car (car (cdr x))))) -;; (define (cdadar x) (cdr (car (cdr (car x))))) -;; (define (cdaddr x) (cdr (car (cdr (cdr x))))) -;; (define (cddaar x) (cdr (cdr (car (car x))))) -;; (define (cddadr x) (cdr (cdr (car (cdr x))))) -;; (define (cdddar x) (cdr (cdr (cdr (car x))))) -;; (define (cddddr x) (cdr (cdr (cdr (cdr x))))) +(define (caaaar x) (car (car (car (car x))))) +(define (caaadr x) (car (car (car (cdr x))))) +(define (caadar x) (car (car (cdr (car x))))) +(define (caaddr x) (car (car (cdr (cdr x))))) +(define (cadaar x) (car (cdr (car (car x))))) +(define (cadadr x) (car (cdr (car (cdr x))))) +(define (caddar x) (car (cdr (cdr (car x))))) +(define (cadddr x) (car (cdr (cdr (cdr x))))) +(define (cdaaar x) (cdr (car (car (car x))))) +(define (cdaadr x) (cdr (car (car (cdr x))))) +(define (cdadar x) (cdr (car (cdr (car x))))) +(define (cdaddr x) (cdr (car (cdr (cdr x))))) +(define (cddaar x) (cdr (cdr (car (car x))))) +(define (cddadr x) (cdr (cdr (car (cdr x))))) +(define (cdddar x) (cdr (cdr (cdr (car x))))) +(define (cddddr x) (cdr (cdr (cdr (cdr x))))) (define (list . args) args) @@ -60,7 +54,7 @@ (define (list-ref ls k) (car (list-tail ls k))) -(define eqv? equal?) +(define (eqv? a b) (if (eq? a b) #t (and (flonum? a) (flonum? b) (= a b)))) (define (member obj ls) (if (null? ls) @@ -297,24 +291,29 @@ (define (force x) (if (procedure? x) (x) x)) +;; booleans + +(define (not x) (if x #f #t)) +(define (boolean? x) (if (eq? x #t) #t (eq? x #f))) + ;; char utils -;; (define (char=? a b) (= (char->integer a) (char->integer b))) -;; (define (charinteger a) (char->integer b))) -;; (define (char>? a b) (> (char->integer a) (char->integer b))) -;; (define (char<=? a b) (<= (char->integer a) (char->integer b))) -;; (define (char>=? a b) (>= (char->integer a) (char->integer b))) +(define (char=? a b) (= (char->integer a) (char->integer b))) +(define (charinteger a) (char->integer b))) +(define (char>? a b) (> (char->integer a) (char->integer b))) +(define (char<=? a b) (<= (char->integer a) (char->integer b))) +(define (char>=? a b) (>= (char->integer a) (char->integer b))) -;; (define (char-ci=? a b) -;; (= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) -;; (define (char-ciinteger (char-downcase a)) (char->integer (char-downcase b)))) -;; (define (char-ci>? a b) -;; (> (char->integer (char-downcase a)) (char->integer (char-downcase b)))) -;; (define (char-ci<=? a b) -;; (<= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) -;; (define (char-ci>=? a b) -;; (>= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) +(define (char-ci=? a b) + (= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) +(define (char-ciinteger (char-downcase a)) (char->integer (char-downcase b)))) +(define (char-ci>? a b) + (> (char->integer (char-downcase a)) (char->integer (char-downcase b)))) +(define (char-ci<=? a b) + (<= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) +(define (char-ci>=? a b) + (>= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) ;; string utils @@ -339,6 +338,14 @@ ;; math utils +(define (number? x) (if (fixnum? x) #t (flonum? x))) +(define complex? number?) +(define rational? number?) +(define real? number?) +(define exact? fixnum?) +(define inexact? flonum?) +(define (integer? x) (if (fixnum? x) #t (and (flonum? x) (= x (truncate x))))) + (define (zero? x) (= x 0)) (define (positive? x) (> x 0)) (define (negative? x) (< x 0)) diff --git a/opcodes.c b/opcodes.c index 1ada2e22..813c4d37 100644 --- a/opcodes.c +++ b/opcodes.c @@ -19,6 +19,8 @@ _OP(OPC_ACCESSOR, OP_VECTOR_LENGTH,1,0, SEXP_VECTOR, 0, 0,"vector-length", NULL, _OP(OPC_ACCESSOR, OP_STRING_REF,2,0, SEXP_STRING, SEXP_FIXNUM, 0,"string-ref", NULL, NULL), _OP(OPC_ACCESSOR, OP_STRING_SET,3,0, SEXP_STRING, SEXP_FIXNUM, 0,"string-set!", NULL, NULL), _OP(OPC_ACCESSOR, OP_STRING_LENGTH,1,0, SEXP_STRING, 0, 0,"string-length", NULL, NULL), +_OP(OPC_GENERIC, OP_FIX2FLO, 1, 0, 0, 0, 0, "exact->inexact", NULL, NULL), +_OP(OPC_GENERIC, OP_FLO2FIX, 1, 0, 0, 0, 0, "inexact->exact", NULL, NULL), _OP(OPC_GENERIC, OP_CHAR2INT, 1, 0, SEXP_CHAR, 0, 0, "char->integer", NULL, NULL), _OP(OPC_GENERIC, OP_INT2CHAR, 1, 0, SEXP_FIXNUM, 0, 0, "integer->char", NULL, NULL), _OP(OPC_GENERIC, OP_CHAR_UPCASE, 1, 0, SEXP_CHAR, 0, 0, "char-upcase", NULL, NULL), @@ -33,7 +35,7 @@ _OP(OPC_ARITHMETIC_CMP, OP_LT, 0, 1, SEXP_FIXNUM, 0, 0, "<", NULL, NULL), _OP(OPC_ARITHMETIC_CMP, OP_LE, 0, 1, SEXP_FIXNUM, 0, 0, "<=", NULL, NULL), _OP(OPC_ARITHMETIC_CMP, OP_LT, 0, 1, SEXP_FIXNUM, 0, 1, ">", NULL, NULL), _OP(OPC_ARITHMETIC_CMP, OP_LE, 0, 1, SEXP_FIXNUM, 0, 1, ">=", NULL, NULL), -_OP(OPC_ARITHMETIC_CMP, OP_EQ, 0, 1, SEXP_FIXNUM, 0, 0, "=", NULL, NULL), +_OP(OPC_ARITHMETIC_CMP, OP_EQN, 0, 1, SEXP_FIXNUM, 0, 0, "=", NULL, NULL), _OP(OPC_PREDICATE, OP_EQ, 2, 0, 0, 0, 0, "eq?", NULL, NULL), _OP(OPC_CONSTRUCTOR, OP_CONS, 2, 0, 0, 0, 0, "cons", NULL, NULL), _OP(OPC_CONSTRUCTOR, OP_MAKE_VECTOR, 2, 0, SEXP_FIXNUM, 0, 0, "make-vector", NULL, NULL), @@ -42,9 +44,11 @@ _OP(OPC_TYPE_PREDICATE, OP_NULLP, 1, 0, 0, 0, 0, "null?", NULL, NULL), _OP(OPC_TYPE_PREDICATE, OP_EOFP, 1, 0, 0, 0, 0, "eof-object?", NULL, NULL), _OP(OPC_TYPE_PREDICATE, OP_SYMBOLP, 1, 0, 0, 0, 0, "symbol?", NULL, NULL), _OP(OPC_TYPE_PREDICATE, OP_CHARP, 1, 0, 0, 0, 0, "char?", NULL, NULL), +_OP(OPC_TYPE_PREDICATE, OP_INTEGERP, 1, 0, 0, 0, 0, "fixnum?", NULL, NULL), _OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "pair?", (sexp)SEXP_PAIR, NULL), _OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "string?", (sexp)SEXP_STRING, NULL), _OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "vector?", (sexp)SEXP_VECTOR, NULL), +_OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "flonum?", (sexp)SEXP_FLONUM, NULL), _OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "procedure?", (sexp)SEXP_PROCEDURE, NULL), _OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "input-port?", (sexp)SEXP_IPORT, NULL), _OP(OPC_TYPE_PREDICATE, OP_TYPEP, 1, 0, 0, 0, 0, "output-port?", (sexp)SEXP_OPORT, NULL), diff --git a/sexp.c b/sexp.c index 48d68cee..fd55200a 100644 --- a/sexp.c +++ b/sexp.c @@ -449,6 +449,7 @@ sexp sexp_make_output_port(FILE* out) { void sexp_write (sexp obj, sexp out) { unsigned long len, c, res; long i=0; + double f; sexp x, *elts; char *str=NULL; @@ -485,7 +486,9 @@ void sexp_write (sexp obj, sexp out) { } break; case SEXP_FLONUM: - sexp_printf(out, "%g", sexp_flonum_value(obj)); break; + f = sexp_flonum_value(obj); + sexp_printf(out, "%.15g%s", f, (f == trunc(f)) ? ".0" : ""); + break; case SEXP_PROCEDURE: sexp_printf(out, "#", obj); break; case SEXP_IPORT: diff --git a/sexp.h b/sexp.h index 04c67fd1..4d46b3c6 100644 --- a/sexp.h +++ b/sexp.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "config.h" #include "defaults.h" @@ -230,7 +231,11 @@ struct sexp_struct { #define sexp_flonum_value(f) ((f)->value.flonum) +#if USE_FLONUMS #define sexp_integer_to_flonum(x) (sexp_make_flonum(sexp_unbox_integer(x))) +#else +#define sexp_integer_to_flonum(x) (x) +#endif /*************************** field accessors **************************/