mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-12 23:47:34 +02:00
initial tail-call optimization support
This commit is contained in:
parent
f63382cff8
commit
ec57daaf5f
4 changed files with 53 additions and 14 deletions
9
debug.c
9
debug.c
|
@ -3,7 +3,8 @@
|
|||
/* BSD-style license: http://synthcode.com/license.txt */
|
||||
|
||||
static const char* reverse_opcode_names[] =
|
||||
{"NOOP", "CALL", "APPLY1", "CALLCC", "RESUMECC", "ERROR", "FCALL0", "FCALL1",
|
||||
{"NOOP", "TAIL-CALL", "CALL", "APPLY1", "CALLCC", "RESUMECC", "ERROR",
|
||||
"FCALL0", "FCALL1",
|
||||
"FCALL2", "FCALL3", "FCALL4", "FCALL5", "FCALL6", "FCALL7", "FCALLN",
|
||||
"JUMP-UNLESS", "JUMP", "RET", "DONE", "PARAMETER",
|
||||
"STACK-REF", "STACK-SET", "GLOBAL-REF", "GLOBAL-SET", "CLOSURE-REF",
|
||||
|
@ -35,10 +36,16 @@ void disasm (bytecode bc) {
|
|||
break;
|
||||
case OP_GLOBAL_REF:
|
||||
case OP_GLOBAL_SET:
|
||||
case OP_TAIL_CALL:
|
||||
case OP_CALL:
|
||||
case OP_PUSH:
|
||||
sexp_write(((sexp*)ip)[0], cur_error_port);
|
||||
ip += sizeof(sexp);
|
||||
if (opcode==OP_TAIL_CALL) {
|
||||
fprintf(stderr, " ");
|
||||
sexp_write(((sexp*)ip)[0], cur_error_port);
|
||||
ip += sizeof(sexp);
|
||||
}
|
||||
break;
|
||||
case OP_JUMP:
|
||||
case OP_JUMP_UNLESS:
|
||||
|
|
53
eval.c
53
eval.c
|
@ -344,12 +344,19 @@ void analyze_app (sexp obj, bytecode *bc, unsigned int *i, env e,
|
|||
analyze(SEXP_CAR(obj), bc, i, e, params, fv, sv, d, 0);
|
||||
|
||||
/* maybe overwrite the current frame */
|
||||
/* if (tailp) { */
|
||||
/* } */
|
||||
|
||||
/* make the call */
|
||||
emit(bc, i, OP_CALL);
|
||||
emit_word(bc, i, (sexp_uint_t) sexp_make_integer(len));
|
||||
if (tailp) {
|
||||
/* args ... */
|
||||
/* i */
|
||||
/* ip */
|
||||
/* cp */
|
||||
emit(bc, i, OP_TAIL_CALL);
|
||||
emit_word(bc, i, (sexp_uint_t) sexp_make_integer(sexp_length(params)+(*d)));
|
||||
emit_word(bc, i, (sexp_uint_t) sexp_make_integer(len));
|
||||
} else {
|
||||
/* normal call */
|
||||
emit(bc, i, OP_CALL);
|
||||
emit_word(bc, i, (sexp_uint_t) sexp_make_integer(len));
|
||||
}
|
||||
}
|
||||
|
||||
sexp free_vars (env e, sexp formals, sexp obj, sexp fv) {
|
||||
|
@ -465,10 +472,10 @@ bytecode compile(sexp params, sexp obj, env e, sexp fv, sexp sv, int done_p) {
|
|||
if (SEXP_PAIRP(SEXP_CDR(obj))) {
|
||||
analyze(SEXP_CAR(obj), &bc, &i, e, params, fv, sv, &d, 0);
|
||||
emit(&bc, &i, OP_DROP);
|
||||
} else
|
||||
analyze(SEXP_CAR(obj), &bc, &i, e, params, fv, sv, &d, 1);
|
||||
} else {
|
||||
analyze(SEXP_CAR(obj), &bc, &i, e, params, fv, sv, &d, ! done_p);
|
||||
}
|
||||
}
|
||||
/* return */
|
||||
emit(&bc, &i, done_p ? OP_DONE : OP_RET);
|
||||
shrink_bcode(&bc, i);
|
||||
print_bytecode(bc);
|
||||
|
@ -670,11 +677,35 @@ sexp vm(bytecode bc, env e, sexp* stack, unsigned int top) {
|
|||
stack[top-2]=((stack[top-1] == stack[top-2]) ? SEXP_TRUE : SEXP_FALSE);
|
||||
top--;
|
||||
break;
|
||||
case OP_TAIL_CALL:
|
||||
j = sexp_unbox_integer(((sexp*)ip)[0]); /* current depth */
|
||||
ip += sizeof(sexp);
|
||||
i = sexp_unbox_integer(((sexp*)ip)[0]); /* number of params */
|
||||
tmp1 = stack[top-1]; /* procedure to call */
|
||||
/* fprintf(stderr, "tail call: depth=%d, i=%d, top=%d\n", j, i, top); */
|
||||
/* print_stack(stack, top); */
|
||||
/* save frame info */
|
||||
stack[top] = stack[top-i-j];
|
||||
stack[top+1] = stack[top-i-j+1];
|
||||
/* copy new args into place */
|
||||
for (k=top-i-1; k<top-1; k++)
|
||||
stack[k-j-i] = stack[k];
|
||||
/* restore frame info */
|
||||
stack[top-j-i] = stack[top];
|
||||
stack[top-j-i+1] = stack[top+1];
|
||||
top -= (j-i);
|
||||
/* print_stack(stack, top); */
|
||||
/* exit(0); */
|
||||
bc = sexp_procedure_code(tmp1);
|
||||
ip = bc->data;
|
||||
cp = sexp_procedure_vars(tmp1);
|
||||
break;
|
||||
case OP_CALL:
|
||||
if (top >= INIT_STACK_SIZE)
|
||||
errx(1, "out of stack space: %d", top);
|
||||
/* fprintf(stderr, "CALL\n"); */
|
||||
/* print_stack(stack, top); */
|
||||
i = (sexp_uint_t) ((sexp*)ip)[0];
|
||||
i = sexp_unbox_integer(i);
|
||||
i = sexp_unbox_integer(((sexp*)ip)[0]);
|
||||
tmp1 = stack[top-1];
|
||||
if (! SEXP_PROCEDUREP(tmp1)) {
|
||||
fprintf(stderr, "error: non-procedure app\n");
|
||||
|
|
1
eval.h
1
eval.h
|
@ -91,6 +91,7 @@ enum opcode_classes {
|
|||
|
||||
enum opcode_names {
|
||||
OP_NOOP,
|
||||
OP_TAIL_CALL,
|
||||
OP_CALL,
|
||||
OP_APPLY1,
|
||||
OP_CALLCC,
|
||||
|
|
4
sexp.c
4
sexp.c
|
@ -419,7 +419,7 @@ void sexp_write (sexp obj, sexp out) {
|
|||
sexp_write_char('"', out);
|
||||
i = sexp_string_length(obj);
|
||||
str = sexp_string_data(obj);
|
||||
/* FALLTHROUGH */
|
||||
/* ... FALLTHROUGH ... */
|
||||
case SEXP_SYMBOL:
|
||||
if (obj->tag != SEXP_STRING) {
|
||||
i = sexp_symbol_length(obj);
|
||||
|
@ -584,7 +584,7 @@ sexp sexp_read_raw (sexp in) {
|
|||
while ((c1 = sexp_read_char(in)) != EOF)
|
||||
if (c1 == '\n')
|
||||
break;
|
||||
/* fallthrough */
|
||||
/* ... FALLTHROUGH ... */
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
|
|
Loading…
Add table
Reference in a new issue