detecting undefined variables

This commit is contained in:
Alex Shinn 2009-04-03 17:58:03 +09:00
parent 636502de73
commit 55841679e8
7 changed files with 69 additions and 52 deletions

View file

@ -5,7 +5,8 @@
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",
"JUMP", "PUSH", "DROP", "GLOBAL-REF", "GLOBAL-KNOWN-REF", "STACK-REF",
"LOCAL-REF", "LOCAL-SET",
"CLOSURE-REF", "VECTOR-REF", "VECTOR-SET", "VECTOR-LENGTH", "STRING-REF",
"STRING-SET", "STRING-LENGTH", "MAKE-PROCEDURE", "MAKE-VECTOR", "AND",
"NULL?", "FIXNUM?", "SYMBOL?", "CHAR?",
@ -45,6 +46,8 @@ static sexp sexp_disasm (sexp bc, sexp out) {
sexp_printf(out, "%ld", (sexp_sint_t) ((sexp*)ip)[0]);
ip += sizeof(sexp);
break;
case OP_GLOBAL_REF:
case OP_GLOBAL_KNOWN_REF:
case OP_TAIL_CALL:
case OP_CALL:
case OP_PUSH:
@ -55,7 +58,7 @@ static sexp sexp_disasm (sexp bc, sexp out) {
sexp_write_char('\n', out);
if (ip - sexp_bytecode_data(bc) < sexp_bytecode_length(bc))
goto loop;
return SEXP_UNDEF;
return SEXP_VOID;
}
static void print_bytecode (sexp bc) {

80
eval.c
View file

@ -307,7 +307,7 @@ static sexp analyze_app (sexp x, sexp context) {
static sexp analyze_seq (sexp ls, sexp context) {
sexp res, tmp;
if (sexp_nullp(ls))
res = SEXP_UNDEF;
res = SEXP_VOID;
else if (sexp_nullp(sexp_cdr(ls)))
res = analyze(sexp_car(ls), context);
else {
@ -369,7 +369,7 @@ static sexp analyze_lambda (sexp x, sexp context) {
tmp = sexp_car(ls);
if (sexp_pairp(sexp_cadr(tmp))) {
name = sexp_caadr(tmp);
value = analyze_lambda(sexp_cons(SEXP_UNDEF, sexp_cons(sexp_cdadr(tmp),
value = analyze_lambda(sexp_cons(SEXP_VOID, sexp_cons(sexp_cdadr(tmp),
sexp_cddr(tmp))),
context);
} else {
@ -395,7 +395,7 @@ static sexp analyze_if (sexp x, sexp context) {
sexp test, pass, fail, fail_expr;
analyze_bind(test, sexp_cadr(x), context);
analyze_bind(pass, sexp_caddr(x), context);
fail_expr = sexp_pairp(sexp_cdddr(x)) ? sexp_cadddr(x) : SEXP_UNDEF;
fail_expr = sexp_pairp(sexp_cdddr(x)) ? sexp_cadddr(x) : SEXP_VOID;
analyze_bind(fail, fail_expr, context);
return sexp_make_cnd(test, pass, fail);
}
@ -409,12 +409,12 @@ static sexp analyze_define (sexp x, sexp context) {
sexp_push(sexp_lambda_sv(sexp_env_lambda(env)), name);
sexp_push(sexp_lambda_locals(sexp_env_lambda(env)), name);
sexp_push(sexp_lambda_defs(sexp_env_lambda(env)), x);
return SEXP_UNDEF;
return SEXP_VOID;
} else {
env_cell_create(env, name, SEXP_DEF);
env_cell_create(env, name, SEXP_VOID);
}
if (sexp_pairp(sexp_cadr(x)))
value = analyze_lambda(sexp_cons(SEXP_UNDEF,
value = analyze_lambda(sexp_cons(SEXP_VOID,
sexp_cons(sexp_cdadr(x), sexp_cddr(x))),
context);
else
@ -431,9 +431,9 @@ static sexp analyze_define_syntax (sexp x, sexp context) {
return sexp_compile_error("non-top-level define-syntax", sexp_list1(x));
proc = eval_in_context(sexp_caddr(x), context);
analyze_check_exception(proc);
cell = env_cell_create(sexp_context_env(context), name, SEXP_UNDEF);
cell = env_cell_create(sexp_context_env(context), name, SEXP_VOID);
sexp_cdr(cell) = sexp_make_macro(proc, sexp_context_env(context));
return SEXP_UNDEF;
return SEXP_VOID;
}
static sexp analyze_bind_syntax (sexp ls, sexp eval_ctx, sexp bind_ctx) {
@ -445,7 +445,7 @@ static sexp analyze_bind_syntax (sexp ls, sexp eval_ctx, sexp bind_ctx) {
sexp_cons(sexp_caar(ls),
sexp_make_macro(proc, sexp_context_env(eval_ctx))));
}
return SEXP_UNDEF;
return SEXP_VOID;
}
static sexp analyze_let_syntax (sexp x, sexp context) {
@ -623,9 +623,13 @@ static void generate_ref (sexp ref, sexp context, int unboxp) {
sexp lam;
if (! sexp_lambdap(sexp_ref_loc(ref))) {
/* global ref */
if (unboxp) {
emit((sexp_cdr(sexp_ref_cell(ref)) == SEXP_UNDEF)
? OP_GLOBAL_REF : OP_GLOBAL_KNOWN_REF,
context);
emit_word((sexp_uint_t)sexp_ref_cell(ref), context);
} else
emit_push(sexp_ref_cell(ref), context);
if (unboxp)
emit(OP_CDR, context);
} else {
lam = sexp_context_lambda(context);
generate_non_global_ref(sexp_ref_name(ref), sexp_ref_cell(ref), lam,
@ -769,7 +773,7 @@ static void generate_lambda (sexp lambda, sexp context) {
sexp_context_lambda(ctx) = lambda;
/* allocate space for local vars */
for (ls=sexp_lambda_locals(lambda); sexp_pairp(ls); ls=sexp_cdr(ls))
emit_push(SEXP_UNDEF, ctx);
emit_push(SEXP_VOID, ctx);
/* box mutable vars */
for (ls=sexp_lambda_sv(lambda); sexp_pairp(ls); ls=sexp_cdr(ls)) {
k = sexp_param_index(lambda, sexp_car(ls));
@ -790,11 +794,11 @@ static void generate_lambda (sexp lambda, sexp context) {
bc = finalize_bytecode(ctx);
if (sexp_nullp(fv)) {
/* shortcut, no free vars */
vec = sexp_make_vector(sexp_make_integer(0), SEXP_UNDEF);
vec = sexp_make_vector(sexp_make_integer(0), SEXP_VOID);
generate_lit(sexp_make_procedure(flags, len, bc, vec), context);
} else {
/* push the closed vars */
emit_push(SEXP_UNDEF, context);
emit_push(SEXP_VOID, context);
emit_push(sexp_length(fv), context);
emit(OP_MAKE_VECTOR, context);
sexp_context_depth(context)--;
@ -934,7 +938,7 @@ static sexp make_opcode_procedure (sexp op, sexp_uint_t i, sexp env,
res = sexp_make_procedure(sexp_make_integer(0),
sexp_make_integer(i),
bc,
SEXP_UNDEF);
SEXP_VOID);
if (i == sexp_opcode_num_args(op))
sexp_opcode_proc(op) = res;
return res;
@ -945,7 +949,7 @@ static sexp make_opcode_procedure (sexp op, sexp_uint_t i, sexp env,
static sexp sexp_save_stack(sexp *stack, sexp_uint_t to) {
sexp res, *data;
sexp_uint_t i;
res = sexp_make_vector(sexp_make_integer(to), SEXP_UNDEF);
res = sexp_make_vector(sexp_make_integer(to), SEXP_VOID);
data = sexp_vector_data(res);
for (i=0; i<to; i++)
data[i] = stack[i];
@ -1151,6 +1155,14 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
case OP_DROP:
top--;
break;
case OP_GLOBAL_REF:
if (sexp_cdr(_WORD0) == SEXP_UNDEF)
sexp_raise("undefined variable", sexp_list1(sexp_car(_WORD0)));
/* ... FALLTHROUGH ... */
case OP_GLOBAL_KNOWN_REF:
_PUSH(sexp_cdr(_WORD0));
ip += sizeof(sexp);
break;
case OP_STACK_REF: /* `pick' in forth */
stack[top] = stack[top - _SWORD0];
ip += sizeof(sexp);
@ -1163,7 +1175,7 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
break;
case OP_LOCAL_SET:
stack[fp - 1 - _SWORD0] = _ARG1;
_ARG1 = SEXP_UNDEF;
_ARG1 = SEXP_VOID;
ip += sizeof(sexp);
break;
case OP_CLOSURE_REF:
@ -1180,7 +1192,7 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
if (! sexp_vectorp(_ARG1))
sexp_raise("vector-set!: not a vector", sexp_list1(_ARG1));
sexp_vector_set(_ARG1, _ARG2, _ARG3);
_ARG3 = SEXP_UNDEF;
_ARG3 = SEXP_VOID;
top-=2;
break;
case OP_VECTOR_LENGTH:
@ -1192,7 +1204,7 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
break;
case OP_STRING_SET:
sexp_string_set(_ARG1, _ARG2, _ARG3);
_ARG3 = SEXP_UNDEF;
_ARG3 = SEXP_VOID;
top-=2;
break;
case OP_STRING_LENGTH:
@ -1236,14 +1248,14 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
if (! sexp_pairp(_ARG1))
sexp_raise("set-car!: not a pair", sexp_list1(_ARG1));
sexp_car(_ARG1) = _ARG2;
_ARG2 = SEXP_UNDEF;
_ARG2 = SEXP_VOID;
top--;
break;
case OP_SET_CDR:
if (! sexp_pairp(_ARG1))
sexp_raise("set-cdr!: not a pair", sexp_list1(_ARG1));
sexp_cdr(_ARG1) = _ARG2;
_ARG2 = SEXP_UNDEF;
_ARG2 = SEXP_VOID;
top--;
break;
case OP_CONS:
@ -1426,33 +1438,33 @@ sexp vm(sexp bc, sexp cp, sexp context, sexp* stack, sexp_sint_t top) {
case OP_DISPLAY:
if (sexp_stringp(_ARG1)) {
sexp_write_string(sexp_string_data(_ARG1), _ARG2);
_ARG2 = SEXP_UNDEF;
_ARG2 = SEXP_VOID;
top--;
break;
} else if (sexp_charp(_ARG1)) {
sexp_write_char(sexp_unbox_character(_ARG1), _ARG2);
_ARG2 = SEXP_UNDEF;
_ARG2 = SEXP_VOID;
top--;
break;
}
/* ... FALLTHROUGH ... */
case OP_WRITE:
sexp_write(_ARG1, _ARG2);
_ARG2 = SEXP_UNDEF;
_ARG2 = SEXP_VOID;
top--;
break;
case OP_WRITE_CHAR:
sexp_write_char(sexp_unbox_character(_ARG1), _ARG2);
_ARG2 = SEXP_UNDEF;
_ARG2 = SEXP_VOID;
top--;
break;
case OP_NEWLINE:
sexp_write_char('\n', _ARG1);
_ARG1 = SEXP_UNDEF;
_ARG1 = SEXP_VOID;
break;
case OP_FLUSH_OUTPUT:
sexp_flush(_ARG1);
_ARG1 = SEXP_UNDEF;
_ARG1 = SEXP_VOID;
break;
case OP_READ:
_ARG1 = sexp_read(_ARG1);
@ -1498,7 +1510,7 @@ sexp sexp_open_output_file (sexp path) {
sexp sexp_close_port (sexp port) {
fclose(sexp_port_stream(port));
return SEXP_UNDEF;
return SEXP_VOID;
}
sexp sexp_load (sexp source, sexp env) {
@ -1510,7 +1522,7 @@ sexp sexp_load (sexp source, sexp env) {
break;
}
if (obj == SEXP_EOF)
res = SEXP_UNDEF;
res = SEXP_VOID;
sexp_close_port(in);
return res;
}
@ -1580,7 +1592,7 @@ static sexp sexp_string_concatenate (sexp str_ls) {
return sexp_type_exception("not a string", sexp_car(ls));
else
len += sexp_string_length(sexp_car(ls));
res = sexp_make_string(sexp_make_integer(len), SEXP_UNDEF);
res = sexp_make_string(sexp_make_integer(len), SEXP_VOID);
p = sexp_string_data(res);
for (ls=str_ls; sexp_pairp(ls); ls=sexp_cdr(ls)) {
len = sexp_string_length(sexp_car(ls));
@ -1657,7 +1669,7 @@ static sexp sexp_make_standard_env (sexp version) {
&& sexp_opcode_opt_param_p(op)
&& sexp_opcode_default(op)) {
sym = sexp_intern((char*)sexp_opcode_default(op));
cell = env_cell_create(e, sym, SEXP_UNDEF);
cell = env_cell_create(e, sym, SEXP_VOID);
sexp_opcode_default(op) = cell;
}
env_define(e, sexp_intern(sexp_opcode_name(op)), op);
@ -1681,7 +1693,7 @@ sexp apply(sexp proc, sexp args, sexp context) {
stack[top] = sexp_make_integer(top);
top++;
stack[top++] = sexp_make_integer(sexp_bytecode_data(final_resumer));
stack[top++] = sexp_make_vector(0, SEXP_UNDEF);
stack[top++] = sexp_make_vector(0, SEXP_VOID);
stack[top++] = sexp_make_integer(0);
return vm(sexp_procedure_code(proc),
sexp_procedure_vars(proc),
@ -1700,7 +1712,7 @@ sexp compile (sexp x, sexp context) {
return sexp_make_procedure(sexp_make_integer(0),
sexp_make_integer(0),
finalize_bytecode(ctx),
sexp_make_vector(0, SEXP_UNDEF));
sexp_make_vector(0, SEXP_VOID));
}
sexp eval_in_context (sexp obj, sexp context) {
@ -1709,7 +1721,7 @@ sexp eval_in_context (sexp obj, sexp context) {
sexp_print_exception(thunk, env_global_ref(sexp_context_env(context),
the_cur_err_symbol,
SEXP_FALSE));
return SEXP_UNDEF;
return SEXP_VOID;
}
return apply(thunk, SEXP_NULL, context);
}

2
eval.h
View file

@ -70,6 +70,8 @@ enum opcode_names {
OP_JUMP,
OP_PUSH,
OP_DROP,
OP_GLOBAL_REF,
OP_GLOBAL_KNOWN_REF,
OP_STACK_REF,
OP_LOCAL_REF,
OP_LOCAL_SET,

6
main.c
View file

@ -17,7 +17,7 @@ void repl (sexp context) {
sexp_print_exception(obj, err);
} else {
res = eval_in_context(obj, context);
if (res != SEXP_UNDEF) {
if (res != SEXP_VOID) {
sexp_write(res, out);
sexp_write_char('\n', out);
}
@ -32,12 +32,12 @@ void run_main (int argc, char **argv) {
env = sexp_make_standard_env(sexp_make_integer(5));
context = sexp_make_context(NULL, env);
sexp_context_tailp(context) = 0;
emit_push(SEXP_UNDEF, context);
emit_push(SEXP_VOID, context);
emit(OP_DONE, context);
err_handler = sexp_make_procedure(sexp_make_integer(0),
sexp_make_integer(0),
finalize_bytecode(context),
sexp_make_vector(0, SEXP_UNDEF));
sexp_make_vector(0, SEXP_VOID));
env_define(env, the_err_handler_symbol, err_handler);
/* parse options */

View file

@ -41,7 +41,7 @@ _OP(OPC_ARITHMETIC_CMP, OP_LE, 0, 1, SEXP_FIXNUM, 0, 1, ">=", 0, NULL),
_OP(OPC_ARITHMETIC_CMP, OP_EQN, 0, 1, SEXP_FIXNUM, 0, 0, "=", 0, NULL),
_OP(OPC_PREDICATE, OP_EQ, 2, 0, 0, 0, 0, "eq?", 0, NULL),
_OP(OPC_CONSTRUCTOR, OP_CONS, 2, 0, 0, 0, 0, "cons", 0, NULL),
_OP(OPC_CONSTRUCTOR, OP_MAKE_VECTOR, 1, 1, SEXP_FIXNUM, 0, 0, "make-vector", SEXP_UNDEF, NULL),
_OP(OPC_CONSTRUCTOR, OP_MAKE_VECTOR, 1, 1, SEXP_FIXNUM, 0, 0, "make-vector", SEXP_VOID, NULL),
_OP(OPC_CONSTRUCTOR, OP_MAKE_PROCEDURE, 4, 0, 0, 0, 0, "make-procedure", 0, NULL),
_OP(OPC_TYPE_PREDICATE, OP_NULLP, 1, 0, 0, 0, 0, "null?", 0, NULL),
_OP(OPC_TYPE_PREDICATE, OP_EOFP, 1, 0, 0, 0, 0, "eof-object?", 0, NULL),

16
sexp.c
View file

@ -147,7 +147,7 @@ sexp sexp_print_exception (sexp exn, sexp out) {
} else {
sexp_write_string("\n", out);
}
return SEXP_UNDEF;
return SEXP_VOID;
}
static sexp sexp_read_error (char *message, sexp irritants, sexp port) {
@ -296,7 +296,7 @@ sexp sexp_make_string(sexp len, sexp ch) {
sexp sexp_c_string(char *str) {
sexp_uint_t len = strlen(str);
sexp s = sexp_make_string(sexp_make_integer(len), SEXP_UNDEF);
sexp s = sexp_make_string(sexp_make_integer(len), SEXP_VOID);
memcpy(sexp_string_data(s), str, len);
return s;
}
@ -318,7 +318,7 @@ sexp sexp_substring (sexp str, sexp start, sexp end) {
|| (end < start))
return sexp_range_exception(str, start, end);
res = sexp_make_string(sexp_fx_sub(end, start),
SEXP_UNDEF);
SEXP_VOID);
memcpy(sexp_string_data(res),
sexp_string_data(str)+sexp_unbox_integer(start),
sexp_string_length(res));
@ -393,7 +393,7 @@ sexp sexp_make_vector(sexp len, sexp dflt) {
}
sexp sexp_list_to_vector(sexp ls) {
sexp x, vec = sexp_make_vector(sexp_length(ls), SEXP_UNDEF);
sexp x, vec = sexp_make_vector(sexp_length(ls), SEXP_VOID);
sexp *elts = sexp_vector_data(vec);
int i;
for (i=0, x=ls; sexp_pairp(x); i++, x=sexp_cdr(x))
@ -402,7 +402,7 @@ sexp sexp_list_to_vector(sexp ls) {
}
sexp sexp_vector(int count, ...) {
sexp vec = sexp_make_vector(sexp_make_integer(count), SEXP_UNDEF);
sexp vec = sexp_make_vector(sexp_make_integer(count), SEXP_VOID);
sexp *elts = sexp_vector_data(vec);
va_list ap;
int i;
@ -443,7 +443,7 @@ int sstream_write (void *vec, const char *src, int n) {
pos = sexp_unbox_integer(sexp_stream_pos(vec));
newpos = pos+n;
if (newpos > len) {
newbuf = sexp_make_string(sexp_make_integer(len*2), SEXP_UNDEF);
newbuf = sexp_make_string(sexp_make_integer(len*2), SEXP_VOID);
memcpy(sexp_string_data(newbuf),
sexp_string_data(sexp_stream_buf(vec)),
pos);
@ -483,7 +483,7 @@ sexp sexp_make_output_string_port () {
FILE *out;
sexp res, size, cookie;
size = sexp_make_integer(SEXP_INIT_STRING_PORT_SIZE);
cookie = sexp_vector(3, sexp_make_string(size, SEXP_UNDEF),
cookie = sexp_vector(3, sexp_make_string(size, SEXP_VOID),
size, sexp_make_integer(0));
out = funopen(cookie, NULL, &sstream_write, &sstream_seek, NULL);
res = sexp_make_output_port(out);
@ -708,8 +708,8 @@ void sexp_write (sexp obj, sexp out) {
sexp_write_string("#f", out); break;
case (sexp_uint_t) SEXP_EOF:
sexp_write_string("#<eof>", out); break;
case (sexp_uint_t) SEXP_DEF:
case (sexp_uint_t) SEXP_UNDEF:
case (sexp_uint_t) SEXP_VOID:
sexp_write_string("#<undef>", out); break;
case (sexp_uint_t) SEXP_ERROR:
sexp_write_string("#<error>", out); break;

6
sexp.h
View file

@ -177,9 +177,9 @@ struct sexp_struct {
#define SEXP_FALSE SEXP_MAKE_IMMEDIATE(1)
#define SEXP_TRUE SEXP_MAKE_IMMEDIATE(2)
#define SEXP_EOF SEXP_MAKE_IMMEDIATE(3)
#define SEXP_UNDEF SEXP_MAKE_IMMEDIATE(4)
#define SEXP_ERROR SEXP_MAKE_IMMEDIATE(5) /* exceptions are preferred */
#define SEXP_DEF SEXP_MAKE_IMMEDIATE(6) /* internal use */
#define SEXP_VOID SEXP_MAKE_IMMEDIATE(4)
#define SEXP_ERROR SEXP_MAKE_IMMEDIATE(5) /* internal use */
#define SEXP_UNDEF SEXP_MAKE_IMMEDIATE(6) /* internal use */
#define SEXP_CLOSE SEXP_MAKE_IMMEDIATE(7) /* internal use */
#define SEXP_RAWDOT SEXP_MAKE_IMMEDIATE(8) /* internal use */