diff --git a/eval.c b/eval.c index e5cf0c79..d9a5a0f9 100644 --- a/eval.c +++ b/eval.c @@ -204,7 +204,7 @@ static void expand_bcode (sexp ctx, sexp_uint_t size) { if (sexp_bytecode_length(sexp_context_bc(ctx)) < (sexp_context_pos(ctx))+size) { tmp=sexp_alloc_bytecode(ctx, sexp_bytecode_length(sexp_context_bc(ctx))*2); - sexp_bytecode_name(tmp) = SEXP_FALSE; + sexp_bytecode_name(tmp) = sexp_bytecode_name(sexp_context_bc(ctx)); sexp_bytecode_length(tmp) = sexp_bytecode_length(sexp_context_bc(ctx))*2; sexp_bytecode_literals(tmp) @@ -551,6 +551,7 @@ static sexp analyze_lambda (sexp ctx, sexp x) { sexp_return(res, sexp_compile_error(ctx, "duplicate parameter", x)); /* build lambda and analyze body */ res = sexp_make_lambda(ctx, tmp=sexp_copy_list(ctx, sexp_cadr(x))); + sexp_lambda_source(res) = sexp_pair_source(x); ctx2 = sexp_make_child_context(ctx, res); tmp = sexp_flatten_dot(ctx2, sexp_lambda_params(res)); sexp_context_env(ctx2) = sexp_extend_env(ctx2, sexp_context_env(ctx2), tmp, res); @@ -624,6 +625,7 @@ static sexp analyze_define (sexp ctx, sexp x) { sexp_push(ctx, sexp_lambda_sv(sexp_env_lambda(env)), name); sexp_push(ctx, sexp_lambda_locals(sexp_env_lambda(env)), name); tmp = sexp_cons(ctx, sexp_cdr(x), ctx); + sexp_pair_source(tmp) = sexp_pair_source(x); sexp_push(ctx, sexp_lambda_defs(sexp_env_lambda(env)), tmp); res = SEXP_VOID; } else { diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index ad773145..e2dc3e8c 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -183,6 +183,7 @@ struct sexp_struct { char gc_mark; unsigned int immutablep:1; unsigned int freep:1; + unsigned int syntacticp:1; #if SEXP_USE_HEADER_MAGIC unsigned int magic; #endif @@ -239,12 +240,11 @@ struct sexp_struct { } cpointer; /* runtime types */ struct { - unsigned int syntacticp:1; sexp parent, lambda, bindings; } env; struct { sexp_uint_t length; - sexp name, literals; + sexp name, literals, source; unsigned char data[]; } bytecode; struct { @@ -271,22 +271,22 @@ struct sexp_struct { } core; /* ast types */ struct { - sexp name, params, body, defs, locals, flags, fv, sv; + sexp name, params, body, defs, locals, flags, fv, sv, source; } lambda; struct { - sexp test, pass, fail; + sexp test, pass, fail, source; } cnd; struct { - sexp var, value; + sexp var, value, source; } set; struct { - sexp name, cell; + sexp name, cell, source; } ref; struct { - sexp ls; + sexp ls, source; } seq; struct { - sexp value; + sexp value, source; } lit; /* compiler state */ struct { @@ -604,9 +604,10 @@ SEXP_API sexp sexp_make_unsigned_integer(sexp ctx, sexp_luint_t x); #define sexp_bytecode_length(x) ((x)->value.bytecode.length) #define sexp_bytecode_name(x) ((x)->value.bytecode.name) #define sexp_bytecode_literals(x) ((x)->value.bytecode.literals) +#define sexp_bytecode_source(x) ((x)->value.bytecode.source) #define sexp_bytecode_data(x) ((x)->value.bytecode.data) -#define sexp_env_syntactic_p(x) ((x)->value.env.syntacticp) +#define sexp_env_syntactic_p(x) ((x)->syntacticp) #define sexp_env_parent(x) ((x)->value.env.parent) #define sexp_env_bindings(x) ((x)->value.env.bindings) #define sexp_env_local_p(x) (sexp_env_parent(x)) @@ -648,21 +649,27 @@ SEXP_API sexp sexp_make_unsigned_integer(sexp ctx, sexp_luint_t x); #define sexp_lambda_body(x) ((x)->value.lambda.body) #define sexp_lambda_fv(x) ((x)->value.lambda.fv) #define sexp_lambda_sv(x) ((x)->value.lambda.sv) +#define sexp_lambda_source(x) ((x)->value.lambda.source) #define sexp_cnd_test(x) ((x)->value.cnd.test) #define sexp_cnd_pass(x) ((x)->value.cnd.pass) #define sexp_cnd_fail(x) ((x)->value.cnd.fail) +#define sexp_cnd_source(x) ((x)->value.cnd.source) #define sexp_set_var(x) ((x)->value.set.var) #define sexp_set_value(x) ((x)->value.set.value) +#define sexp_set_source(x) ((x)->value.set.source) #define sexp_ref_name(x) ((x)->value.ref.name) #define sexp_ref_cell(x) ((x)->value.ref.cell) #define sexp_ref_loc(x) (sexp_cdr(sexp_ref_cell(x))) +#define sexp_ref_source(x) ((x)->value.ref.source) #define sexp_seq_ls(x) ((x)->value.seq.ls) +#define sexp_seq_source(x) ((x)->value.seq.source) #define sexp_lit_value(x) ((x)->value.lit.value) +#define sexp_lit_source(x) ((x)->value.lit.source) #define sexp_stack_length(x) ((x)->value.stack.length) #define sexp_stack_top(x) ((x)->value.stack.top) diff --git a/sexp.c b/sexp.c index 069edea7..a1ff7949 100644 --- a/sexp.c +++ b/sexp.c @@ -100,15 +100,15 @@ static struct sexp_struct _sexp_type_specs[] = { _DEF_TYPE(SEXP_MACRO, sexp_offsetof(macro, proc), 2, 2, 0, 0, sexp_sizeof(macro), 0, 0, "macro", NULL), _DEF_TYPE(SEXP_SYNCLO, sexp_offsetof(synclo, env), 3, 3, 0, 0, sexp_sizeof(synclo), 0, 0, "syntactic-closure", NULL), _DEF_TYPE(SEXP_ENV, sexp_offsetof(env, parent), 3, 3, 0, 0, sexp_sizeof(env), 0, 0, "environment", NULL), - _DEF_TYPE(SEXP_BYTECODE, sexp_offsetof(bytecode, name), 2, 2, 0, 0, sexp_sizeof(bytecode), offsetof(struct sexp_struct, value.bytecode.length), 1, "bytecode", NULL), + _DEF_TYPE(SEXP_BYTECODE, sexp_offsetof(bytecode, name), 3, 3, 0, 0, sexp_sizeof(bytecode), offsetof(struct sexp_struct, value.bytecode.length), 1, "bytecode", NULL), _DEF_TYPE(SEXP_CORE, 0, 0, 0, 0, 0, sexp_sizeof(core), 0, 0, "core-form", NULL), _DEF_TYPE(SEXP_OPCODE, sexp_offsetof(opcode, data), 3, 3, 0, 0, sexp_sizeof(opcode), 0, 0, "opcode", NULL), - _DEF_TYPE(SEXP_LAMBDA, sexp_offsetof(lambda, name), 8, 8, 0, 0, sexp_sizeof(lambda), 0, 0, "lambda", NULL), - _DEF_TYPE(SEXP_CND, sexp_offsetof(cnd, test), 3, 3, 0, 0, sexp_sizeof(cnd), 0, 0, "conditional", NULL), - _DEF_TYPE(SEXP_REF, sexp_offsetof(ref, name), 2, 2, 0, 0, sexp_sizeof(ref), 0, 0, "reference", NULL), - _DEF_TYPE(SEXP_SET, sexp_offsetof(set, var), 2, 2, 0, 0, sexp_sizeof(set), 0, 0, "set!", NULL), - _DEF_TYPE(SEXP_SEQ, sexp_offsetof(seq, ls), 1, 1, 0, 0, sexp_sizeof(seq), 0, 0, "sequence", NULL), - _DEF_TYPE(SEXP_LIT, sexp_offsetof(lit, value), 1, 1, 0, 0, sexp_sizeof(lit), 0, 0, "literal", NULL), + _DEF_TYPE(SEXP_LAMBDA, sexp_offsetof(lambda, name), 9, 9, 0, 0, sexp_sizeof(lambda), 0, 0, "lambda", NULL), + _DEF_TYPE(SEXP_CND, sexp_offsetof(cnd, test), 4, 4, 0, 0, sexp_sizeof(cnd), 0, 0, "conditional", NULL), + _DEF_TYPE(SEXP_REF, sexp_offsetof(ref, name), 3, 3, 0, 0, sexp_sizeof(ref), 0, 0, "reference", NULL), + _DEF_TYPE(SEXP_SET, sexp_offsetof(set, var), 3, 3, 0, 0, sexp_sizeof(set), 0, 0, "set!", NULL), + _DEF_TYPE(SEXP_SEQ, sexp_offsetof(seq, ls), 2, 2, 0, 0, sexp_sizeof(seq), 0, 0, "sequence", NULL), + _DEF_TYPE(SEXP_LIT, sexp_offsetof(lit, value), 2, 2, 0, 0, sexp_sizeof(lit), 0, 0, "literal", NULL), _DEF_TYPE(SEXP_STACK, sexp_offsetof(stack, data), 1, 1, sexp_offsetof(stack, top), 1, sexp_sizeof(stack), offsetof(struct sexp_struct, value.stack.length), sizeof(sexp), "stack", NULL), _DEF_TYPE(SEXP_CONTEXT, sexp_offsetof(context, bc), 7, 7, 0, 0, sexp_sizeof(context), 0, 0, "context", NULL), }; @@ -417,8 +417,10 @@ sexp sexp_print_exception_op (sexp ctx sexp_api_params(self, n), sexp exn, sexp sexp_write_string(ctx, sexp_opcode_name(sexp_exception_procedure(exn)), out); } } - if (sexp_pairp(sexp_exception_source(exn))) { - ls = sexp_exception_source(exn); + ls = sexp_exception_source(exn); + if ((! (ls && sexp_pairp(ls))) && sexp_exception_procedure(exn)) + ls = sexp_bytecode_source(sexp_procedure_code(sexp_exception_procedure(exn))); + if (ls && sexp_pairp(ls)) { if (sexp_fixnump(sexp_cdr(ls)) && (sexp_cdr(ls) >= SEXP_ZERO)) { sexp_write_string(ctx, " on line ", out); sexp_write(ctx, sexp_cdr(ls), out); diff --git a/vm.c b/vm.c index 3ae152da..8e96d597 100644 --- a/vm.c +++ b/vm.c @@ -301,6 +301,7 @@ static void generate_lambda (sexp ctx, sexp lambda) { len = sexp_length(ctx2, sexp_lambda_params(lambda)); bc = finalize_bytecode(ctx2); sexp_bytecode_name(bc) = sexp_lambda_name(lambda); + sexp_bytecode_source(bc) = sexp_lambda_source(lambda); if (sexp_nullp(fv)) { /* shortcut, no free vars */ tmp = sexp_make_vector(ctx2, SEXP_ZERO, SEXP_VOID); @@ -441,9 +442,12 @@ static sexp_uint_t sexp_restore_stack (sexp saved, sexp *current) { goto call_error_handler;} \ while (0) -#define sexp_check_exception() do {if (sexp_exceptionp(_ARG1)) \ - goto call_error_handler;} \ - while (0) +#define sexp_check_exception() \ + do {if (sexp_exceptionp(_ARG1)) { \ + if (! sexp_exception_procedure(_ARG1)) \ + sexp_exception_procedure(_ARG1) = self; \ + goto call_error_handler;}} \ + while (0) sexp sexp_vm (sexp ctx, sexp proc) { sexp bc = sexp_procedure_code(proc), cp = sexp_procedure_vars(proc);