flushing out library

This commit is contained in:
Alex Shinn 2009-04-01 17:25:47 +09:00
parent 51352245b2
commit ee5f33c9fb
7 changed files with 274 additions and 136 deletions

View file

@ -6,12 +6,13 @@ static const char* reverse_opcode_names[] =
{"NOOP", "ERROR", "RESUMECC", "CALLCC", "APPLY1", "TAIL_CALL", "CALL", {"NOOP", "ERROR", "RESUMECC", "CALLCC", "APPLY1", "TAIL_CALL", "CALL",
"FCALL0", "FCALL1", "FCALL2", "FCALL3", "FCALL4", "EVAL", "JUMP_UNLESS", "FCALL0", "FCALL1", "FCALL2", "FCALL3", "FCALL4", "EVAL", "JUMP_UNLESS",
"JUMP", "PUSH", "DROP", "STACK_REF", "LOCAL_REF", "LOCAL_SET", "JUMP", "PUSH", "DROP", "STACK_REF", "LOCAL_REF", "LOCAL_SET",
"CLOSURE_REF", "VECTOR_REF", "VECTOR_SET", "STRING_REF", "STRING_SET", "CLOSURE_REF", "VECTOR_REF", "VECTOR_SET", "VECTOR_LENGTH",
"STRING_REF", "STRING_SET", "STRING_LENGTH",
"MAKE_PROCEDURE", "MAKE_VECTOR", "NULLP", "INTEGERP", "SYMBOLP", "CHARP", "MAKE_PROCEDURE", "MAKE_VECTOR", "NULLP", "INTEGERP", "SYMBOLP", "CHARP",
"EOFP", "TYPEP", "CAR", "CDR", "SET_CAR", "SET_CDR", "CONS", "ADD", "SUB", "EOFP", "TYPEP", "CAR", "CDR", "SET_CAR", "SET_CDR", "CONS", "ADD", "SUB",
"MUL", "DIV", "QUOT", "MOD", "NEG", "INV", "LT", "LE", "EQV", "EQ", "MUL", "DIV", "QUOT", "MOD", "NEG", "INV", "LT", "LE", "EQV", "EQ",
"DISPLAY", "WRITE", "WRITE_CHAR", "NEWLINE", "FLUSH_OUTPUT", "READ", "CHAR->INTEGER", "INTEGER->CHAR", "DISPLAY", "WRITE", "WRITE_CHAR",
"READ_CHAR", "RET", "DONE", "NEWLINE", "FLUSH_OUTPUT", "READ", "READ_CHAR", "RET", "DONE",
}; };
void disasm (sexp bc, sexp out) { void disasm (sexp bc, sexp out) {

74
eval.c
View file

@ -135,6 +135,8 @@ static void shrink_bcode(sexp context, sexp_uint_t i) {
if (sexp_bytecode_length(sexp_context_bc(context)) != i) { if (sexp_bytecode_length(sexp_context_bc(context)) != i) {
tmp = sexp_alloc_tagged(sexp_sizeof(bytecode) + i, SEXP_BYTECODE); tmp = sexp_alloc_tagged(sexp_sizeof(bytecode) + i, SEXP_BYTECODE);
sexp_bytecode_length(tmp) = i; sexp_bytecode_length(tmp) = i;
sexp_bytecode_literals(tmp)
= sexp_bytecode_literals(sexp_context_bc(context));
memcpy(sexp_bytecode_data(tmp), memcpy(sexp_bytecode_data(tmp),
sexp_bytecode_data(sexp_context_bc(context)), sexp_bytecode_data(sexp_context_bc(context)),
i); i);
@ -151,6 +153,8 @@ static void expand_bcode(sexp context, sexp_uint_t size) {
SEXP_BYTECODE); SEXP_BYTECODE);
sexp_bytecode_length(tmp) sexp_bytecode_length(tmp)
= sexp_bytecode_length(sexp_context_bc(context))*2; = sexp_bytecode_length(sexp_context_bc(context))*2;
sexp_bytecode_literals(tmp)
= sexp_bytecode_literals(sexp_context_bc(context));
memcpy(sexp_bytecode_data(tmp), memcpy(sexp_bytecode_data(tmp),
sexp_bytecode_data(sexp_context_bc(context)), sexp_bytecode_data(sexp_context_bc(context)),
sexp_bytecode_length(sexp_context_bc(context))); sexp_bytecode_length(sexp_context_bc(context)));
@ -174,6 +178,8 @@ static void emit_word(sexp_uint_t val, sexp context) {
static void emit_push(sexp obj, sexp context) { static void emit_push(sexp obj, sexp context) {
emit(OP_PUSH, context); emit(OP_PUSH, context);
emit_word((sexp_uint_t)obj, context); emit_word((sexp_uint_t)obj, context);
if (sexp_pointerp(obj))
sexp_push(sexp_bytecode_literals(sexp_context_bc(context)), obj);
} }
static sexp sexp_make_procedure(sexp flags, sexp num_args, static sexp sexp_make_procedure(sexp flags, sexp num_args,
@ -253,6 +259,7 @@ static sexp sexp_make_context(sexp *stack, sexp env) {
sexp_context_bc(res) sexp_context_bc(res)
= sexp_alloc_tagged(sexp_sizeof(bytecode)+INIT_BCODE_SIZE, SEXP_BYTECODE); = sexp_alloc_tagged(sexp_sizeof(bytecode)+INIT_BCODE_SIZE, SEXP_BYTECODE);
sexp_bytecode_length(sexp_context_bc(res)) = INIT_BCODE_SIZE; sexp_bytecode_length(sexp_context_bc(res)) = INIT_BCODE_SIZE;
sexp_bytecode_literals(sexp_context_bc(res)) = SEXP_NULL;
sexp_context_lambda(res) = SEXP_FALSE; sexp_context_lambda(res) = SEXP_FALSE;
sexp_context_stack(res) = stack; sexp_context_stack(res) = stack;
sexp_context_env(res) = env; sexp_context_env(res) = env;
@ -289,10 +296,10 @@ static sexp sexp_identifier_eq (sexp e1, sexp id1, sexp e2, sexp id2) {
id2 = sexp_synclo_expr(id2); id2 = sexp_synclo_expr(id2);
} }
cell = env_cell(e1, id1); cell = env_cell(e1, id1);
if (sexp_lambdap(sexp_cdr(cell))) if (cell && sexp_lambdap(sexp_cdr(cell)))
lam1 = sexp_cdr(cell); lam1 = sexp_cdr(cell);
cell = env_cell(e2, id2); cell = env_cell(e2, id2);
if (sexp_lambdap(sexp_cdr(cell))) if (cell && sexp_lambdap(sexp_cdr(cell)))
lam2 = sexp_cdr(cell); lam2 = sexp_cdr(cell);
return sexp_make_boolean((id1 == id2) && (lam1 == lam2)); return sexp_make_boolean((id1 == id2) && (lam1 == lam2));
} }
@ -357,13 +364,21 @@ static sexp analyze (sexp x, sexp context) {
} else if (sexp_macrop(op)) { } else if (sexp_macrop(op)) {
x = apply(sexp_macro_proc(op), x = apply(sexp_macro_proc(op),
sexp_list3(x, sexp_context_env(context), sexp_macro_env(op)), sexp_list3(x, sexp_context_env(context), sexp_macro_env(op)),
context); sexp_child_context(context, sexp_context_lambda(context)));
/* sexp_debug("expand => ", x, context); */ /* sexp_debug("expand => ", x, context); */
goto loop; goto loop;
} else if (sexp_opcodep(op)) { } else if (sexp_opcodep(op)) {
res = analyze_app(sexp_cdr(x), context); res = sexp_length(sexp_cdr(x));
analyze_check_exception(res); if (sexp_unbox_integer(res) < sexp_opcode_num_args(op)) {
sexp_push(res, op); res = sexp_compile_error("not enough args for opcode", sexp_list1(x));
} else if ((sexp_unbox_integer(res) > sexp_opcode_num_args(op))
&& (! sexp_opcode_variadic_p(op))) {
res = sexp_compile_error("too many args for opcode", sexp_list1(x));
} else {
res = analyze_app(sexp_cdr(x), context);
analyze_check_exception(res);
sexp_push(res, op);
}
} else { } else {
res = analyze_app(x, context); res = analyze_app(x, context);
} }
@ -537,10 +552,10 @@ static void sexp_context_patch_label (sexp context, sexp_sint_t label) {
static sexp finalize_bytecode (sexp context) { static sexp finalize_bytecode (sexp context) {
emit(OP_RET, context); emit(OP_RET, context);
shrink_bcode(context, sexp_context_pos(context)); shrink_bcode(context, sexp_context_pos(context));
disasm(sexp_context_bc(context), /* disasm(sexp_context_bc(context), */
env_global_ref(sexp_context_env(context), /* env_global_ref(sexp_context_env(context), */
the_cur_err_symbol, /* the_cur_err_symbol, */
SEXP_FALSE)); /* SEXP_FALSE)); */
return sexp_context_bc(context); return sexp_context_bc(context);
} }
@ -950,8 +965,8 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
sexp_sint_t i, j, k, fp=top-4; sexp_sint_t i, j, k, fp=top-4;
loop: loop:
/* print_stack(stack, top, fp); */ /* print_stack(stack, top, fp, env_global_ref(env, the_cur_err_symbol, SEXP_FALSE)); */
/* fprintf(stderr, "%s\n", (*ip<=71)?reverse_opcode_names[*ip]:"UNKNOWN"); */ /* fprintf(stderr, "%s\n", (*ip<=71)?reverse_opcode_names[*ip]:"UNKNOWN"); */
switch (*ip++) { switch (*ip++) {
case OP_NOOP: case OP_NOOP:
fprintf(stderr, "<<<NOOP>>>\n"); fprintf(stderr, "<<<NOOP>>>\n");
@ -1089,6 +1104,12 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
ip += sizeof(sexp); ip += sizeof(sexp);
sexp_check_exception(); sexp_check_exception();
break; break;
case OP_FCALL4:
_ARG4 =((sexp_proc4)_UWORD0)(_ARG1, _ARG2, _ARG3, _ARG4);
top -= 3;
ip += sizeof(sexp);
sexp_check_exception();
break;
case OP_EVAL: case OP_EVAL:
sexp_context_top(context) = top; sexp_context_top(context) = top;
_ARG1 = eval_in_context(_ARG1, context); _ARG1 = eval_in_context(_ARG1, context);
@ -1142,6 +1163,9 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
_ARG3 = SEXP_UNDEF; _ARG3 = SEXP_UNDEF;
top-=2; top-=2;
break; break;
case OP_VECTOR_LENGTH:
_ARG1 = sexp_make_integer(sexp_vector_length(_ARG1));
break;
case OP_STRING_REF: case OP_STRING_REF:
_ARG2 = sexp_string_ref(_ARG1, _ARG2); _ARG2 = sexp_string_ref(_ARG1, _ARG2);
top--; top--;
@ -1151,6 +1175,9 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
_ARG3 = SEXP_UNDEF; _ARG3 = SEXP_UNDEF;
top-=2; top-=2;
break; break;
case OP_STRING_LENGTH:
_ARG1 = sexp_make_integer(sexp_string_length(_ARG1));
break;
case OP_MAKE_PROCEDURE: case OP_MAKE_PROCEDURE:
_ARG4 = sexp_make_procedure(_ARG1, _ARG2, _ARG3, _ARG4); _ARG4 = sexp_make_procedure(_ARG1, _ARG2, _ARG3, _ARG4);
top-=3; top-=3;
@ -1289,11 +1316,13 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
else sexp_raise("/: not a number", sexp_list1(_ARG1)); else sexp_raise("/: not a number", sexp_list1(_ARG1));
break; break;
case OP_LT: case OP_LT:
_ARG2 = sexp_make_boolean(_ARG1 < _ARG2); _ARG2 = sexp_make_boolean(sexp_unbox_integer(_ARG1)
< sexp_unbox_integer(_ARG2));
top--; top--;
break; break;
case OP_LE: case OP_LE:
_ARG2 = sexp_make_boolean(_ARG1 <= _ARG2); _ARG2 = sexp_make_boolean(sexp_unbox_integer(_ARG1)
<= sexp_unbox_integer(_ARG2));
top--; top--;
break; break;
case OP_EQ: case OP_EQ:
@ -1301,6 +1330,12 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
_ARG2 = sexp_make_boolean(_ARG1 == _ARG2); _ARG2 = sexp_make_boolean(_ARG1 == _ARG2);
top--; top--;
break; break;
case OP_CHAR2INT:
_ARG1 = sexp_make_integer(sexp_unbox_character(_ARG1));
break;
case OP_INT2CHAR:
_ARG1 = sexp_make_character(sexp_unbox_integer(_ARG1));
break;
case OP_DISPLAY: case OP_DISPLAY:
if (sexp_stringp(_ARG1)) { if (sexp_stringp(_ARG1)) {
sexp_write_string(sexp_string_data(_ARG1), _ARG2); sexp_write_string(sexp_string_data(_ARG1), _ARG2);
@ -1412,6 +1447,10 @@ define_math_op(sexp_asin, asin)
define_math_op(sexp_acos, acos) define_math_op(sexp_acos, acos)
define_math_op(sexp_atan, atan) define_math_op(sexp_atan, atan)
define_math_op(sexp_sqrt, sqrt) 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)
#endif #endif
@ -1526,6 +1565,13 @@ void scheme_init () {
the_cur_out_symbol = sexp_intern("*current-output-port*"); the_cur_out_symbol = sexp_intern("*current-output-port*");
the_cur_err_symbol = sexp_intern("*current-error-port*"); the_cur_err_symbol = sexp_intern("*current-error-port*");
the_interaction_env_symbol = sexp_intern("*interaction-environment*"); the_interaction_env_symbol = sexp_intern("*interaction-environment*");
#if USE_BOEHM
GC_add_roots((char*)&continuation_resumer,
((char*)&continuation_resumer)+sizeof(continuation_resumer)+1);
GC_add_roots((char*)&final_resumer,
((char*)&final_resumer)+sizeof(continuation_resumer)+1);
GC_add_roots((char*)&opcodes, ((char*)&opcodes)+sizeof(opcodes)+1);
#endif
context = sexp_make_context(NULL, NULL); context = sexp_make_context(NULL, NULL);
emit(OP_RESUMECC, context); emit(OP_RESUMECC, context);
continuation_resumer = finalize_bytecode(context); continuation_resumer = finalize_bytecode(context);

4
eval.h
View file

@ -80,8 +80,10 @@ enum opcode_names {
OP_CLOSURE_REF, OP_CLOSURE_REF,
OP_VECTOR_REF, OP_VECTOR_REF,
OP_VECTOR_SET, OP_VECTOR_SET,
OP_VECTOR_LENGTH,
OP_STRING_REF, OP_STRING_REF,
OP_STRING_SET, OP_STRING_SET,
OP_STRING_LENGTH,
OP_MAKE_PROCEDURE, OP_MAKE_PROCEDURE,
OP_MAKE_VECTOR, OP_MAKE_VECTOR,
OP_NULLP, OP_NULLP,
@ -107,6 +109,8 @@ enum opcode_names {
OP_LE, OP_LE,
OP_EQV, OP_EQV,
OP_EQ, OP_EQ,
OP_CHAR2INT,
OP_INT2CHAR,
OP_DISPLAY, OP_DISPLAY,
OP_WRITE, OP_WRITE,
OP_WRITE_CHAR, OP_WRITE_CHAR,

311
init.scm
View file

@ -1,30 +1,26 @@
;; cond case delay do ;; let-syntax letrec-syntax syntax-rules
;; quasiquote let-syntax ;; number? complex? real? rational? integer? exact? inexact?
;; letrec-syntax syntax-rules not boolean? number? ;; positive? negative? max min remainder
;; complex? real? rational? integer? exact? inexact? ;; modulo numerator denominator
;; positive? negative? odd? even? max min quotient remainder
;; modulo numerator denominator floor ceiling truncate round
;; rationalize expt ;; rationalize expt
;; make-rectangular make-polar real-part imag-part magnitude angle ;; make-rectangular make-polar real-part imag-part magnitude angle
;; exact->inexact inexact->exact number->string string->number ;; exact->inexact inexact->exact number->string string->number
;; symbol->string string->symbol ;; symbol->string string->symbol
;; char-alphabetic? char-numeric? char-whitespace? ;; char-alphabetic? char-numeric? char-whitespace?
;; char-upper-case? char-lower-case? char->integer integer->char ;; char-upper-case? char-lower-case?
;; char-upcase char-downcase make-string string string-length ;; char-upcase char-downcase make-string
;; string=? string-ci=? string<? string>? ;; string=? string-ci=? string<? string>?
;; string<=? string>=? string-ci<? string-ci>? string-ci<=? string-ci>=? ;; string<=? string>=? string-ci<? string-ci>? string-ci<=? string-ci>=?
;; substring string-append string->list list->string string-copy ;; substring string-append string-copy
;; string-fill! vector vector-length ;; values call-with-values dynamic-wind
;; vector->list list->vector vector-fill! procedure? apply ;; call-with-input-file call-with-output-file
;; map for-each force call-with-current-continuation values ;; with-input-from-file with-output-to-file
;; call-with-values dynamic-wind scheme-report-environment
;; null-environment call-with-input-file call-with-output-file
;; current-input-port current-output-port
;; with-input-from-file with-output-to-file open-input-file
;; open-output-file close-input-port close-output-port
;; peek-char char-ready? ;; 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 ;; provide c[ad]{2,4}r
(define (caar x) (car (car x))) (define (caar x) (car (car x)))
@ -61,7 +57,7 @@
(define (list . args) args) (define (list . args) args)
(define (list-tail ls k) (define (list-tail ls k)
(if (zero? k) (if (eq? k 0)
ls ls
(list-tail (cdr ls) (- k 1)))) (list-tail (cdr ls) (- k 1))))
@ -82,8 +78,8 @@
(if (null? ls) (if (null? ls)
#f #f
(if (equal? obj (caar ls)) (if (equal? obj (caar ls))
ls (car ls)
(member obj (cdr ls))))) (assoc obj (cdr ls)))))
(define assv assoc) (define assv assoc)
@ -105,27 +101,21 @@
;; map with a fast-path for single lists ;; map with a fast-path for single lists
(define (map proc ls . lol) (define (map proc ls . lol)
(define (map1 proc ls res)
(if (pair? ls)
(map1 proc (cdr ls) (cons (proc (car ls)) res))
(reverse res)))
(define (mapn proc lol res)
(if (null? (car lol))
(reverse res)
(mapn proc
(map1 cdr lol '())
(cons (apply1 proc (map1 car lol '())) res))))
(if (null? lol) (if (null? lol)
(map1 proc ls '()) (map1 proc ls '())
(mapn proc (cons ls lol) '()))) (mapn proc (cons ls lol) '())))
(define (map1 proc ls res) (define for-each map)
(if (pair? ls)
(map1 proc (cdr ls) (cons (proc (car ls)) res))
(reverse res)))
(define (mapn proc lol res)
(if (null? (car lol))
(reverse res)
(mapn proc
(map1 cdr lol '())
(cons (apply1 proc (map1 car lol '())) res))))
;; math utilities
(define (zero? x) (= x 0))
(define (positive? x) (> x 0))
(define (negative? x) (< x 0))
;; syntax ;; syntax
@ -156,37 +146,6 @@
'()) '())
(lambda (x y) (identifier=? use-env x use-env y)))))) (lambda (x y) (identifier=? use-env x use-env y))))))
(define-syntax letrec
(er-macro-transformer
(lambda (expr rename compare)
(list
(cons (rename 'lambda)
(cons '()
(append (map (lambda (x) (cons (rename 'define) x)) (cadr expr))
(cddr expr))))))))
(define-syntax let
(er-macro-transformer
(lambda (expr rename compare)
(if (identifier? (cadr expr))
(list (rename 'letrec)
(list (list (cadr expr)
(cons (rename 'lambda)
(cons (map car (caddr expr))
(cdddr expr)))))
(cons (cadr expr) (map cadr (caddr expr))))
(cons (cons (rename 'lambda) (cons (map car (cadr expr)) (cddr expr)))
(map cadr (cadr expr)))))))
(define-syntax let*
(er-macro-transformer
(lambda (expr rename compare)
(if (null? (cadr expr))
(cons (rename 'begin) (cddr expr))
(list (rename 'let)
(list (caadr expr))
(cons (rename 'let*) (cons (cdadr expr) (cddr expr))))))))
(define-syntax or (define-syntax or
(er-macro-transformer (er-macro-transformer
(lambda (expr rename compare) (lambda (expr rename compare)
@ -213,52 +172,134 @@
(lambda (expr rename compare) (lambda (expr rename compare)
(if (null? (cdr expr)) (if (null? (cdr expr))
#f #f
(let ((cl (cadr expr))) ((lambda (cl)
(if (eq? 'else (car cl)) (if (compare 'else (car cl))
(cons (rename 'begin) (cdr cl)) (cons (rename 'begin) (cdr cl))
(if (if (null? (cdr cl)) #t (eq? '=> (cadr cl))) (if (if (null? (cdr cl)) #t (compare '=> (cadr cl)))
(list (rename 'let) (list (rename 'let)
(list (list (rename 'tmp) (car cl))) (list (list (rename 'tmp) (car cl)))
(list (rename 'if) (rename 'tmp) (list (rename 'if) (rename 'tmp)
(if (null? (cdr cl)) (if (null? (cdr cl))
(rename 'tmp) (rename 'tmp)
(list (caddr cl) (rename 'tmp))))) (list (caddr cl) (rename 'tmp)))))
(list (rename 'if) (list (rename 'if)
(car cl) (car cl)
(cons (rename 'begin) (cdr cl)) (cons (rename 'begin) (cdr cl))
(cons (rename 'cond) (cddr expr)))))))))) (cons (rename 'cond) (cddr expr))))))
(cadr expr))))))
(define-syntax quasiquote (define-syntax quasiquote
(er-macro-transformer (er-macro-transformer
(lambda (expr rename compare) (lambda (expr rename compare)
(define (qq x d) (define (qq x d)
(if (pair? x) (cond
(if (eq? 'unquote (car x)) ((pair? x)
(if (<= d 0) (cond
(cadr x) ((eq? 'unquote (car x))
(list (rename 'unquote) (qq (cadr x) (- d 1)))) (if (<= d 0)
(if (eq? 'unquote-splicing (car x)) (cadr x)
(if (<= d 0) (list (rename 'unquote) (qq (cadr x) (- d 1)))))
(list (rename 'cons) (qq (car x) d) (qq (cdr x) d)) ((eq? 'unquote-splicing (car x))
(list (rename 'unquote-splicing) (qq (cadr x) (- d 1)))) (if (<= d 0)
(if (eq? 'quasiquote (car x)) (list (rename 'cons) (qq (car x) d) (qq (cdr x) d))
(list (rename 'quasiquote) (qq (cadr x) (+ d 1))) (list (rename 'unquote-splicing) (qq (cadr x) (- d 1)))))
(if (and (<= d 0) ((eq? 'quasiquote (car x))
(pair? (car x)) (list (rename 'quasiquote) (qq (cadr x) (+ d 1))))
(eq? 'unquote-splicing (caar x))) ((and (<= d 0) (pair? (car x)) (eq? 'unquote-splicing (caar x)))
(list (rename 'append) (if (null? (cdr x))
(cadar x) (cadar x)
(qq (cdr x) d)) (list (rename 'append) (cadar x) (qq (cdr x) d))))
(list (rename 'cons) (else
(qq (car x) d) (list (rename 'cons) (qq (car x) d) (qq (cdr x) d)))))
(qq (cdr x) d)))))) ((vector? x) (list (rename 'list->vector) (qq (vector->list x) d)))
(if (vector? x) ((symbol? x) (list (rename 'quote) x))
(list (rename 'list->vector) (qq (vector->list x) d)) (else x)))
(if (symbol? x)
(list (rename 'quote) x)
x))))
(qq (cadr expr) 0)))) (qq (cadr expr) 0))))
(define-syntax letrec
(er-macro-transformer
(lambda (expr rename compare)
((lambda (defs)
`((,(rename 'lambda) () ,@defs ,@(cddr expr))))
(map (lambda (x) (cons (rename 'define) x)) (cadr expr))))))
(define-syntax let
(er-macro-transformer
(lambda (expr rename compare)
(if (identifier? (cadr expr))
`(,(rename 'letrec) ((,(cadr expr)
(,(rename 'lambda) ,(map car (caddr expr))
,@(cdddr expr))))
,(cons (cadr expr) (map cadr (caddr expr))))
`((,(rename 'lambda) ,(map car (cadr expr)) ,@(cddr expr))
,@(map cadr (cadr expr)))))))
(define-syntax let*
(er-macro-transformer
(lambda (expr rename compare)
(if (null? (cadr expr))
`(,(rename 'begin) ,@(cddr expr))
`(,(rename 'let) (,(caadr expr))
(,(rename 'let*) ,(cdadr expr) ,@(cddr expr)))))))
(define-syntax case
(er-macro-transformer
(lambda (expr rename compare)
(define (clause ls)
(cond
((null? ls) #f)
((compare 'else (caar ls))
`(,(rename 'begin) ,@(cdar ls)))
(else
(if (and (pair? (caar ls)) (null? (cdaar ls)))
`(,(rename 'if) (,(rename 'eqv?) ,(rename 'tmp) ',(caaar ls))
(,(rename 'begin) ,@(cdar ls))
,(clause (cdr ls)))
`(,(rename 'if) (,(rename 'memv) ,(rename 'tmp) ',(caar ls))
(,(rename 'begin) ,@(cdar ls))
,(clause (cdr ls)))))))
`(let ((,(rename 'tmp) ,(cadr expr)))
,(clause (cddr expr))))))
(define-syntax do
(er-macro-transformer
(lambda (expr rename compare)
(let* ((body
`(,(rename 'begin)
,@(cdddr expr)
(,(rename 'lp)
,@(map (lambda (x) (if (pair? (cddr x)) (caddr x) (car x)))
(cadr expr)))))
(check (caddr expr))
(wrap
(if (null? (cdr check))
`(,(rename 'let) ((,(rename 'tmp) ,(car check)))
(,(rename 'if) ,(rename 'tmp)
,(rename 'tmp)
,body))
`(,(rename 'if) ,(car check)
(,(rename 'begin) ,@(cdr check))
,body))))
`(,(rename 'let) ,(rename 'lp)
,(map (lambda (x) (list (car x) (cadr x))) (cadr expr))
,wrap)))))
(define-syntax delay
(er-macro-transformer
(lambda (expr rename compare)
`(,(rename 'make-promise) (,(rename 'lambda) () ,(cadr epr))))))
(define (make-promise thunk)
(lambda ()
(let ((computed? #f) (result #f))
(if (not computed?)
(begin
(set! result (thunk))
(set! computed? #t)))
result)))
(define (force x) (if (procedure? x) (x) x))
;; char utils ;; char utils
;; (define (char=? a b) (= (char->integer a) (char->integer b))) ;; (define (char=? a b) (= (char->integer a) (char->integer b)))
@ -278,24 +319,35 @@
;; (define (char-ci>=? a b) ;; (define (char-ci>=? a b)
;; (>= (char->integer (char-downcase a)) (char->integer (char-downcase b)))) ;; (>= (char->integer (char-downcase a)) (char->integer (char-downcase b))))
;; vector utils ;; string utils
(define (list->vector ls) (define (list->string ls)
(let ((vec (make-vector (length ls)))) (let ((str (make-string (length ls) #\space)))
(let lp ((ls ls) (i 0)) (let lp ((ls ls) (i 0))
(if (pair? ls) (if (pair? ls)
(begin (begin
(vector-set! vec i (car ls)) (string-set! str i (car ls))
(lp (cdr ls) (+ i 1))))) (lp (cdr ls) (+ i 1)))))
vec)) str))
(define (vector->list vec) (define (string->list str)
(let lp ((i (- (vector-length vec) 1)) (res '())) (let lp ((i (- (string-length str) 1)) (res '()))
(if (< i 0) (if (< i 0) res (lp (- i 1) (cons (string-ref str i) res)))))
res
(lp (- i 1) (cons (vector-ref vec i) res)))))
;; math (define (string-fill! str ch)
(let lp ((i (- (string-length str) 1)))
(if (>= i 0) (begin (string-set! str i ch) (lp (- i 1))))))
(define (string . args) (list->string args))
;; math utils
(define (zero? x) (= x 0))
(define (positive? x) (> x 0))
(define (negative? x) (< x 0))
(define (even? n) (= (remainder n 2) 0))
(define (odd? n) (= (remainder n 2) 1))
;; (define (abs x) (if (< x 0) (- x) x)) ;; (define (abs x) (if (< x 0) (- x) x))
@ -307,5 +359,28 @@
;; (define (lcm a b) ;; (define (lcm a b)
;; (quotient (* a b) (gcd a b))) ;; (quotient (* a b) (gcd a b)))
;; vector utils
(define (list->vector ls)
(let ((vec (make-vector (length ls) #f)))
(let lp ((ls ls) (i 0))
(if (pair? ls)
(begin
(vector-set! vec i (car ls))
(lp (cdr ls) (+ i 1)))))
vec))
(define (vector->list vec)
(let lp ((i (- (vector-length vec) 1)) (res '()))
(if (< i 0) res (lp (- i 1) (cons (vector-ref vec i) res)))))
(define (vector-fill! str ch)
(let lp ((i (- (vector-length str) 1)))
(if (>= i 0) (begin (vector-set! str i ch) (lp (- i 1))))))
(define (vector . args) (list->vector args))
;; miscellaneous
(define (load file) (%load file (interaction-environment))) (define (load file) (%load file (interaction-environment)))

View file

@ -15,8 +15,12 @@ _OP(OPC_ACCESSOR, OP_CDR, 1, 0, SEXP_PAIR, 0, 0, "cdr", NULL, NULL),
_OP(OPC_ACCESSOR, OP_SET_CDR, 2, 0, SEXP_PAIR, 0, 0, "set-cdr!", NULL, NULL), _OP(OPC_ACCESSOR, OP_SET_CDR, 2, 0, SEXP_PAIR, 0, 0, "set-cdr!", NULL, NULL),
_OP(OPC_ACCESSOR, OP_VECTOR_REF,2,0, SEXP_VECTOR, SEXP_FIXNUM, 0,"vector-ref", NULL, NULL), _OP(OPC_ACCESSOR, OP_VECTOR_REF,2,0, SEXP_VECTOR, SEXP_FIXNUM, 0,"vector-ref", NULL, NULL),
_OP(OPC_ACCESSOR, OP_VECTOR_SET,3,0, SEXP_VECTOR, SEXP_FIXNUM, 0,"vector-set!", NULL, NULL), _OP(OPC_ACCESSOR, OP_VECTOR_SET,3,0, SEXP_VECTOR, SEXP_FIXNUM, 0,"vector-set!", NULL, NULL),
_OP(OPC_ACCESSOR, OP_VECTOR_LENGTH,1,0, SEXP_VECTOR, 0, 0,"vector-length", NULL, NULL),
_OP(OPC_ACCESSOR, OP_STRING_REF,2,0, SEXP_STRING, SEXP_FIXNUM, 0,"string-ref", NULL, 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_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_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_ARITHMETIC, OP_ADD, 0, 1, SEXP_FIXNUM, 0, 0, "+", NULL, NULL), _OP(OPC_ARITHMETIC, OP_ADD, 0, 1, SEXP_FIXNUM, 0, 0, "+", NULL, NULL),
_OP(OPC_ARITHMETIC, OP_MUL, 0, 1, SEXP_FIXNUM, 0, 0, "*", NULL, NULL), _OP(OPC_ARITHMETIC, OP_MUL, 0, 1, SEXP_FIXNUM, 0, 0, "*", NULL, NULL),
_OP(OPC_ARITHMETIC_INV, OP_SUB, 0, 1, SEXP_FIXNUM, 0, OP_NEG, "-", NULL, NULL), _OP(OPC_ARITHMETIC_INV, OP_SUB, 0, 1, SEXP_FIXNUM, 0, OP_NEG, "-", NULL, NULL),
@ -77,6 +81,10 @@ _FN1(0, "asin", sexp_asin),
_FN1(0, "acos", sexp_acos), _FN1(0, "acos", sexp_acos),
_FN1(0, "atan", sexp_atan), _FN1(0, "atan", sexp_atan),
_FN1(0, "sqrt", sexp_sqrt), _FN1(0, "sqrt", sexp_sqrt),
_FN1(0, "round", sexp_round),
_FN1(0, "truncate", sexp_trunc),
_FN1(0, "floor", sexp_floor),
_FN1(0, "ceiling", sexp_ceiling),
#endif #endif
_FN2(0, SEXP_PAIR, "memq", sexp_memq), _FN2(0, SEXP_PAIR, "memq", sexp_memq),
_FN2(0, SEXP_PAIR, "assq", sexp_assq), _FN2(0, SEXP_PAIR, "assq", sexp_assq),

4
sexp.c
View file

@ -47,7 +47,7 @@ static int is_separator(int c) {
static sexp* symbol_table = NULL; static sexp* symbol_table = NULL;
static unsigned long symbol_table_primes[] = { static unsigned long symbol_table_primes[] = {
97, 389, 1543, 6151, 12289, 24593, 49157, 98317, 196613, 393241, /* 97, 389, */ 1543, 6151, 12289, 24593, 49157, 98317, 196613, 393241,
786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653,
100663319, 201326611, 402653189, 805306457, 1610612741}; 100663319, 201326611, 402653189, 805306457, 1610612741};
static int symbol_table_prime_index = 0; static int symbol_table_prime_index = 0;
@ -934,6 +934,8 @@ void sexp_init() {
sexp_initialized_p = 1; sexp_initialized_p = 1;
#if USE_BOEHM #if USE_BOEHM
GC_init(); GC_init();
GC_add_roots((char*)&symbol_table,
((char*)&symbol_table)+sizeof(symbol_table)+1);
#endif #endif
symbol_table = sexp_alloc(symbol_table_primes[0]*sizeof(sexp)); symbol_table = sexp_alloc(symbol_table_primes[0]*sizeof(sexp));
the_dot_symbol = sexp_intern("."); the_dot_symbol = sexp_intern(".");

2
sexp.h
View file

@ -109,6 +109,7 @@ struct sexp_struct {
} env; } env;
struct { struct {
sexp_uint_t length; sexp_uint_t length;
sexp literals;
unsigned char data[]; unsigned char data[];
} bytecode; } bytecode;
struct { struct {
@ -263,6 +264,7 @@ struct sexp_struct {
#define sexp_bytecode_length(x) ((x)->value.bytecode.length) #define sexp_bytecode_length(x) ((x)->value.bytecode.length)
#define sexp_bytecode_data(x) ((x)->value.bytecode.data) #define sexp_bytecode_data(x) ((x)->value.bytecode.data)
#define sexp_bytecode_literals(x) ((x)->value.bytecode.literals)
#define sexp_env_flags(x) ((x)->value.env.flags) #define sexp_env_flags(x) ((x)->value.env.flags)
#define sexp_env_parent(x) ((x)->value.env.parent) #define sexp_env_parent(x) ((x)->value.env.parent)