fixing closures with more than one variable

This commit is contained in:
Alex Shinn 2009-03-29 02:21:59 +09:00
parent ac4b35962a
commit 373e2788cc
6 changed files with 25 additions and 22 deletions

View file

@ -45,8 +45,7 @@ void disasm (sexp bc) {
break; break;
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
if ((! (opcode == OP_RET) || (opcode == OP_DONE)) if (ip - sexp_bytecode_data(bc) < sexp_bytecode_length(bc))
&& (ip - sexp_bytecode_data(bc) < sexp_bytecode_length(bc)))
goto loop; goto loop;
} }

44
eval.c
View file

@ -217,7 +217,7 @@ static sexp sexp_new_context(sexp *stack) {
sexp_context_depth(res) = 0; sexp_context_depth(res) = 0;
sexp_context_pos(res) = 0; sexp_context_pos(res) = 0;
sexp_context_top(res) = 0; sexp_context_top(res) = 0;
sexp_context_tailp(res) = 1; sexp_context_tailp(res) = 0;
return res; return res;
} }
@ -480,8 +480,10 @@ static void generate_seq (sexp app, sexp context) {
} }
static void generate_cnd (sexp cnd, sexp context) { static void generate_cnd (sexp cnd, sexp context) {
sexp_sint_t label1, label2; sexp_sint_t label1, label2, tailp=sexp_context_tailp(context);
sexp_context_tailp(context) = 0;
generate(sexp_cnd_test(cnd), context); generate(sexp_cnd_test(cnd), context);
sexp_context_tailp(context) = tailp;
emit(OP_JUMP_UNLESS, context); emit(OP_JUMP_UNLESS, context);
sexp_context_depth(context)--; sexp_context_depth(context)--;
label1 = sexp_context_make_label(context); label1 = sexp_context_make_label(context);
@ -504,7 +506,7 @@ static void generate_ref (sexp ref, sexp context, int unboxp) {
} else { } else {
lam = sexp_context_lambda(context); lam = sexp_context_lambda(context);
generate_non_global_ref(sexp_ref_name(ref), sexp_ref_cell(ref), lam, generate_non_global_ref(sexp_ref_name(ref), sexp_ref_cell(ref), lam,
sexp_lambda_fv(lam), context, unboxp); sexp_lambda_fv(lam), context, unboxp);
} }
} }
@ -521,7 +523,8 @@ static void generate_non_global_ref (sexp name, sexp cell, sexp lambda,
} else { } else {
/* closure ref */ /* closure ref */
for (i=0; sexp_pairp(fv); fv=sexp_cdr(fv), i++) for (i=0; sexp_pairp(fv); fv=sexp_cdr(fv), i++)
if (name == sexp_car(fv) && loc == sexp_cdr(fv)) if ((name == sexp_ref_name(sexp_car(fv)))
&& (loc == sexp_ref_loc(sexp_car(fv))))
break; break;
emit(OP_CLOSURE_REF, context); emit(OP_CLOSURE_REF, context);
emit_word(i, context); emit_word(i, context);
@ -669,7 +672,7 @@ static void generate_lambda (sexp lambda, sexp context) {
for (k=0; sexp_pairp(fv); fv=sexp_cdr(fv), k++) { for (k=0; sexp_pairp(fv); fv=sexp_cdr(fv), k++) {
ref = sexp_car(fv); ref = sexp_car(fv);
generate_non_global_ref(sexp_ref_name(ref), sexp_ref_cell(ref), generate_non_global_ref(sexp_ref_name(ref), sexp_ref_cell(ref),
prev_lambda, prev_fv, context, 0); prev_lambda, prev_fv, context, 0);
emit_push(sexp_make_integer(k), context); emit_push(sexp_make_integer(k), context);
emit(OP_STACK_REF, context); emit(OP_STACK_REF, context);
emit_word(3, context); emit_word(3, context);
@ -821,7 +824,7 @@ sexp vm(sexp bc, sexp cp, sexp e, sexp* stack, sexp_sint_t top) {
case OP_NOOP: case OP_NOOP:
fprintf(stderr, "<<<NOOP>>>\n"); fprintf(stderr, "<<<NOOP>>>\n");
break; break;
case OP_STACK_REF: case OP_STACK_REF: /* pick in forth */
fprintf(stderr, "%ld - %ld => %ld", top, (sexp_sint_t) ((sexp*)ip)[0], top - (sexp_sint_t) ((sexp*)ip)[0]); fprintf(stderr, "%ld - %ld => %ld", top, (sexp_sint_t) ((sexp*)ip)[0], top - (sexp_sint_t) ((sexp*)ip)[0]);
stack[top] = stack[top - (sexp_sint_t) ((sexp*)ip)[0]]; stack[top] = stack[top - (sexp_sint_t) ((sexp*)ip)[0]];
ip += sizeof(sexp); ip += sizeof(sexp);
@ -840,8 +843,8 @@ sexp vm(sexp bc, sexp cp, sexp e, sexp* stack, sexp_sint_t top) {
ip += sizeof(sexp); ip += sizeof(sexp);
break; break;
case OP_CLOSURE_REF: case OP_CLOSURE_REF:
fprintf(stderr, "%ld", sexp_unbox_integer(((sexp*)ip)[0])); fprintf(stderr, "%ld", (sexp_sint_t) ((sexp*)ip)[0]);
_PUSH(sexp_vector_ref(cp, ((sexp*)ip)[0])); _PUSH(sexp_vector_ref(cp, sexp_make_integer(((sexp*)ip)[0])));
ip += sizeof(sexp); ip += sizeof(sexp);
break; break;
case OP_VECTOR_REF: case OP_VECTOR_REF:
@ -1041,7 +1044,7 @@ sexp vm(sexp bc, sexp cp, sexp e, sexp* stack, sexp_sint_t top) {
/* save frame info */ /* save frame info */
ip = ((unsigned char*) sexp_unbox_integer(stack[top-i-3])) - sizeof(sexp); ip = ((unsigned char*) sexp_unbox_integer(stack[top-i-3])) - sizeof(sexp);
cp = stack[top-i-2]; cp = stack[top-i-2];
fp = stack[top-i-2]; fp = (sexp_sint_t) stack[top-i-2];
/* copy new args into place */ /* copy new args into place */
for (k=0; k<i; k++) for (k=0; k<i; k++)
stack[top-j+k] = stack[top-i-1+k]; stack[top-j+k] = stack[top-i-1+k];
@ -1116,16 +1119,17 @@ sexp vm(sexp bc, sexp cp, sexp e, sexp* stack, sexp_sint_t top) {
stack[top+1] = sexp_make_integer(ip); stack[top+1] = sexp_make_integer(ip);
stack[top+2] = cp; stack[top+2] = cp;
stack[top+3] = sexp_make_integer(fp); stack[top+3] = sexp_make_integer(fp);
_ARG1 tmp2 = sexp_vector(1, sexp_save_stack(stack, top+4));
= sexp_make_procedure(sexp_make_integer(0), sexp_make_integer(1), _ARG1 = sexp_make_procedure(sexp_make_integer(0),
continuation_resumer, sexp_make_integer(1),
sexp_vector(1, sexp_save_stack(stack, top+4))); continuation_resumer,
tmp2);
top++; top++;
ip -= sizeof(sexp); ip -= sizeof(sexp);
goto make_call; goto make_call;
break; break;
case OP_RESUMECC: case OP_RESUMECC:
tmp1 = _ARG5; tmp1 = stack[fp-1];
top = sexp_restore_stack(sexp_vector_ref(cp, 0), stack); top = sexp_restore_stack(sexp_vector_ref(cp, 0), stack);
fp = sexp_unbox_integer(_ARG1); fp = sexp_unbox_integer(_ARG1);
cp = _ARG2; cp = _ARG2;
@ -1210,12 +1214,12 @@ sexp vm(sexp bc, sexp cp, sexp e, sexp* stack, sexp_sint_t top) {
_ARG1 = (i == EOF) ? SEXP_EOF : sexp_make_character(i); _ARG1 = (i == EOF) ? SEXP_EOF : sexp_make_character(i);
break; break;
case OP_RET: case OP_RET:
fp = sexp_unbox_integer(_ARG2); i = sexp_unbox_integer(stack[fp]);
cp = _ARG3; stack[fp-i] = _ARG1;
ip = (unsigned char*) sexp_unbox_integer(_ARG4); top = fp-i+1;
i = sexp_unbox_integer(_ARG5); ip = (unsigned char*) sexp_unbox_integer(stack[fp+1]);
stack[top-i-5] = _ARG1; cp = stack[fp+2];
top = top-i-4; fp = sexp_unbox_integer(stack[fp+3]);
break; break;
case OP_DONE: case OP_DONE:
fprintf(stderr, "\n"); fprintf(stderr, "\n");