wow, looks like all tests pass...

This commit is contained in:
Alex Shinn 2009-03-29 16:24:56 +09:00
parent 373e2788cc
commit 45fe39b2db
13 changed files with 102 additions and 48 deletions

View file

@ -12,7 +12,6 @@ junk*
*.tar.bz2 *.tar.bz2
*.log *.log
*.err *.err
*.res
*.out *.out
gc gc
gc6.8 gc6.8

45
eval.c
View file

@ -103,17 +103,19 @@ static sexp sexp_flatten_dot (sexp ls) {
return sexp_nreverse(sexp_reverse_flatten_dot(ls)); return sexp_nreverse(sexp_reverse_flatten_dot(ls));
} }
static int sexp_param_index (sexp params, sexp name) { static int sexp_param_index (sexp lambda, sexp name) {
sexp ls = sexp_lambda_params(lambda);
int i = 0; int i = 0;
while (sexp_pairp(params)) { for (i=0; sexp_pairp(ls); ls=sexp_cdr(ls), i++)
if (sexp_car(params) == name) if (sexp_car(ls) == name)
return i; return i;
params = sexp_cdr(params); if (ls == name)
i++;
}
if (params == name)
return i; return i;
return -1; ls = sexp_lambda_locals(lambda);
for (i=-1; sexp_pairp(ls); ls=sexp_cdr(ls), i--)
if (sexp_car(ls) == name)
return i;
return -10000;
} }
/************************* bytecode utilities ***************************/ /************************* bytecode utilities ***************************/
@ -150,8 +152,10 @@ static void emit(char c, sexp context) {
} }
static void emit_word(sexp_uint_t val, sexp context) { static void emit_word(sexp_uint_t val, sexp context) {
unsigned char *data;
expand_bcode(context, sizeof(sexp)); expand_bcode(context, sizeof(sexp));
*((sexp_uint_t*)(&(sexp_bytecode_data(sexp_context_bc(context))[sexp_context_pos(context)]))) = val; data = sexp_bytecode_data(sexp_context_bc(context));
*((sexp_uint_t*)(&(data[sexp_context_pos(context)]))) = val;
sexp_context_pos(context) += sizeof(sexp); sexp_context_pos(context) += sizeof(sexp);
} }
@ -324,6 +328,7 @@ static sexp analyze_lambda (sexp x, sexp context) {
sexp_lambda_params(res) = sexp_cadr(x); sexp_lambda_params(res) = sexp_cadr(x);
sexp_lambda_fv(res) = SEXP_NULL; sexp_lambda_fv(res) = SEXP_NULL;
sexp_lambda_sv(res) = SEXP_NULL; sexp_lambda_sv(res) = SEXP_NULL;
sexp_lambda_locals(res) = SEXP_NULL;
context = sexp_child_context(context, res); context = sexp_child_context(context, res);
sexp_context_env(context) sexp_context_env(context)
= extend_env(sexp_context_env(context), = extend_env(sexp_context_env(context),
@ -514,12 +519,10 @@ static void generate_non_global_ref (sexp name, sexp cell, sexp lambda,
sexp fv, sexp context, int unboxp) { sexp fv, sexp context, int unboxp) {
sexp_uint_t i; sexp_uint_t i;
sexp loc = sexp_cdr(cell); sexp loc = sexp_cdr(cell);
sexp_debug("cell: ", cell);
if (loc == lambda && sexp_lambdap(lambda)) { if (loc == lambda && sexp_lambdap(lambda)) {
/* local ref */ /* local ref */
sexp_debug("params: ", sexp_lambda_params(lambda));
emit(OP_LOCAL_REF, context); emit(OP_LOCAL_REF, context);
emit_word(sexp_param_index(sexp_lambda_params(lambda), name), context); emit_word(sexp_param_index(lambda, name), context);
} 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++)
@ -642,9 +645,12 @@ static void generate_lambda (sexp lambda, sexp context) {
fv = sexp_lambda_fv(lambda); fv = sexp_lambda_fv(lambda);
ctx = sexp_new_context(sexp_context_stack(context)); ctx = sexp_new_context(sexp_context_stack(context));
sexp_context_lambda(ctx) = lambda; 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);
/* box mutable vars */ /* box mutable vars */
for (ls=sexp_lambda_sv(lambda); sexp_pairp(ls); ls=sexp_cdr(ls)) { for (ls=sexp_lambda_sv(lambda); sexp_pairp(ls); ls=sexp_cdr(ls)) {
k = sexp_param_index(sexp_lambda_params(lambda), sexp_car(ls)); k = sexp_param_index(lambda, sexp_car(ls));
if (k >= 0) { if (k >= 0) {
emit(OP_LOCAL_REF, ctx); emit(OP_LOCAL_REF, ctx);
emit_word(k, ctx); emit_word(k, ctx);
@ -710,7 +716,7 @@ static sexp diff_free_vars (sexp fv, sexp params) {
/* sexp_debug("diff-free-vars: ", fv); */ /* sexp_debug("diff-free-vars: ", fv); */
/* sexp_debug("params: ", params); */ /* sexp_debug("params: ", params); */
for ( ; sexp_pairp(fv); fv=sexp_cdr(fv)) for ( ; sexp_pairp(fv); fv=sexp_cdr(fv))
if (sexp_param_index(params, sexp_ref_name(sexp_car(fv))) < 0) if (sexp_memq(sexp_ref_name(sexp_car(fv)), params) == SEXP_FALSE)
sexp_push(res, sexp_car(fv)); sexp_push(res, sexp_car(fv));
/* sexp_debug(" => ", res); */ /* sexp_debug(" => ", res); */
return res; return res;
@ -720,7 +726,7 @@ static sexp free_vars (sexp x, sexp fv) {
sexp fv1, fv2; sexp fv1, fv2;
if (sexp_lambdap(x)) { if (sexp_lambdap(x)) {
fv1 = free_vars(sexp_lambda_body(x), SEXP_NULL); fv1 = free_vars(sexp_lambda_body(x), SEXP_NULL);
fv2 = diff_free_vars(fv1, sexp_lambda_params(x)); fv2 = diff_free_vars(fv1, sexp_flatten_dot(sexp_lambda_params(x)));
sexp_lambda_fv(x) = fv2; sexp_lambda_fv(x) = fv2;
fv = union_free_vars(fv2, fv); fv = union_free_vars(fv2, fv);
} else if (sexp_pairp(x)) { } else if (sexp_pairp(x)) {
@ -763,6 +769,7 @@ static sexp make_opcode_procedure (sexp op, sexp_uint_t i, sexp env,
sexp_lambda_params(lambda) = params; sexp_lambda_params(lambda) = params;
sexp_lambda_fv(lambda) = SEXP_NULL; sexp_lambda_fv(lambda) = SEXP_NULL;
sexp_lambda_sv(lambda) = SEXP_NULL; sexp_lambda_sv(lambda) = SEXP_NULL;
sexp_lambda_locals(lambda) = SEXP_NULL;
sexp_context_lambda(context) = lambda; sexp_context_lambda(context) = lambda;
sexp_context_top(context) = top; sexp_context_top(context) = top;
env = extend_env(env, params, lambda); env = extend_env(env, params, lambda);
@ -1396,6 +1403,10 @@ sexp compile (sexp x, sexp context) {
sexp eval_in_context (sexp obj, sexp context) { sexp eval_in_context (sexp obj, sexp context) {
sexp thunk = compile(obj, context); sexp thunk = compile(obj, context);
if (sexp_exceptionp(thunk)) {
sexp_print_exception(obj, cur_error_port);
return SEXP_UNDEF;
}
return apply(thunk, SEXP_NULL, context); return apply(thunk, SEXP_NULL, context);
} }
@ -1431,6 +1442,9 @@ void repl (sexp context) {
obj = sexp_read(cur_input_port); obj = sexp_read(cur_input_port);
if (obj == SEXP_EOF) if (obj == SEXP_EOF)
break; break;
if (sexp_exceptionp(obj)) {
sexp_print_exception(obj, cur_error_port);
} else {
res = eval_in_context(obj, context); res = eval_in_context(obj, context);
if (res != SEXP_UNDEF) { if (res != SEXP_UNDEF) {
sexp_write(res, cur_output_port); sexp_write(res, cur_output_port);
@ -1438,6 +1452,7 @@ void repl (sexp context) {
} }
} }
} }
}
int main (int argc, char **argv) { int main (int argc, char **argv) {
sexp env, obj, res, context, err_handler, err_handler_sym; sexp env, obj, res, context, err_handler, err_handler_sym;

62
sexp.c
View file

@ -36,7 +36,9 @@ static char sexp_separators[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, /* x5_ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, /* x5_ */
}; };
#define digit_value(c) (((c)<='9') ? ((c) - '0') : ((toupper(c) - 'A') + 10)) static int digit_value (c) {
return (((c)<='9') ? ((c) - '0') : ((toupper(c) - 'A') + 10));
}
static int is_separator(int c) { static int is_separator(int c) {
/* return (!((c-9)&(~3))) | (~(c^4)); */ /* return (!((c-9)&(~3))) | (~(c^4)); */
@ -133,9 +135,12 @@ sexp sexp_print_exception(sexp exn, sexp out) {
} }
static sexp sexp_read_error(char *message, sexp irritants, sexp port) { static sexp sexp_read_error(char *message, sexp irritants, sexp port) {
return sexp_make_exception(the_read_error_symbol, sexp_make_string(message), sexp name = (sexp_port_name(port)
? sexp_make_string(sexp_port_name(port)) : SEXP_FALSE);
return sexp_make_exception(the_read_error_symbol,
sexp_make_string(message),
irritants, irritants,
sexp_make_string(sexp_port_name(port)), name,
sexp_make_integer(sexp_port_line(port))); sexp_make_integer(sexp_port_line(port)));
} }
@ -382,6 +387,7 @@ sexp sexp_get_output_string(sexp port) {
sexp sexp_make_input_port(FILE* in) { sexp sexp_make_input_port(FILE* in) {
sexp p = sexp_alloc_type(port, SEXP_IPORT); sexp p = sexp_alloc_type(port, SEXP_IPORT);
sexp_port_stream(p) = in; sexp_port_stream(p) = in;
sexp_port_name(p) = NULL;
sexp_port_line(p) = 0; sexp_port_line(p) = 0;
return p; return p;
} }
@ -389,6 +395,7 @@ sexp sexp_make_input_port(FILE* in) {
sexp sexp_make_output_port(FILE* out) { sexp sexp_make_output_port(FILE* out) {
sexp p = sexp_alloc_type(port, SEXP_OPORT); sexp p = sexp_alloc_type(port, SEXP_OPORT);
sexp_port_stream(p) = out; sexp_port_stream(p) = out;
sexp_port_name(p) = NULL;
sexp_port_line(p) = 0; sexp_port_line(p) = 0;
return p; return p;
} }
@ -480,7 +487,12 @@ void sexp_write (sexp obj, sexp out) {
} else if (sexp_integerp(obj)) { } else if (sexp_integerp(obj)) {
sexp_printf(out, "%ld", sexp_unbox_integer(obj)); sexp_printf(out, "%ld", sexp_unbox_integer(obj));
} else if (sexp_charp(obj)) { } else if (sexp_charp(obj)) {
if ((33 <= sexp_unbox_character(obj)) && (sexp_unbox_character(obj) < 127)) if (obj == sexp_make_character(' '))
sexp_write_string("#\\space", out);
else if (obj == sexp_make_character('\n'))
sexp_write_string("#\\newline", out);
else if ((33 <= sexp_unbox_character(obj))
&& (sexp_unbox_character(obj) < 127))
sexp_printf(out, "#\\%c", sexp_unbox_character(obj)); sexp_printf(out, "#\\%c", sexp_unbox_character(obj));
else else
sexp_printf(out, "#\\x%02d", sexp_unbox_character(obj)); sexp_printf(out, "#\\x%02d", sexp_unbox_character(obj));
@ -700,49 +712,59 @@ sexp sexp_read_raw (sexp in) {
res = sexp_read_number(in, 10); break; res = sexp_read_number(in, 10); break;
case 'x': case 'x':
res = sexp_read_number(in, 16); break; res = sexp_read_number(in, 16); break;
/* case 'e': */ case 'e':
/* case 'i': */ res = sexp_read(in);
if (sexp_flonump(res))
res = sexp_make_integer((sexp_sint_t)sexp_flonum_value(res));
break;
case 'i':
res = sexp_read(in);
if (sexp_integerp(res))
res = sexp_make_flonum(sexp_unbox_integer(res));
break;
case 'f': case 'f':
case 't': case 't':
c2 = sexp_read_char(in); c2 = sexp_read_char(in);
if (c2 == EOF || is_separator(c2)) { if (c2 == EOF || is_separator(c2)) {
res = (c1 == 't' ? SEXP_TRUE : SEXP_FALSE); res = (c1 == 't' ? SEXP_TRUE : SEXP_FALSE);
sexp_push_char(c2, in);
} else { } else {
return sexp_read_error("invalid syntax #%c%c", res = sexp_read_error("invalid syntax #%c%c",
sexp_list2(sexp_make_character(c1), sexp_list2(sexp_make_character(c1),
sexp_make_character(c2)), sexp_make_character(c2)),
in); in);
} }
sexp_push_char(c2, in);
break; break;
case ';': case ';':
sexp_read_raw(in); sexp_read_raw(in);
goto scan_loop; goto scan_loop;
case '\\': case '\\':
c1 = sexp_read_char(in); c1 = sexp_read_char(in);
c2 = sexp_read_char(in);
if (c2 == EOF || is_separator(c2)) {
sexp_push_char(c2, in);
res = sexp_make_character(c1);
} else if ((c1 == 'x' || c1 == 'X') && isxdigit(c2)) {
c1 = sexp_read_char(in);
res = sexp_make_character(16 * digit_value(c2) + digit_value(c1));
} else {
str = sexp_read_symbol(in, c1); str = sexp_read_symbol(in, c1);
if (str[0] == '\0')
res =
sexp_read_error("unexpected end of character literal", SEXP_NULL, in);
if (str[1] == '\0') {
res = sexp_make_character(c1);
} else if ((c1 == 'x' || c1 == 'X') &&
isxdigit(str[0]) && isxdigit(str[1]) && str[2] == '\0') {
res = sexp_make_character(16 * digit_value(c1) + digit_value(str[1]));
} else {
if (strcasecmp(str, "space") == 0) if (strcasecmp(str, "space") == 0)
res = sexp_make_character(' '); res = sexp_make_character(' ');
else if (strcasecmp(str, "newline") == 0) else if (strcasecmp(str, "newline") == 0)
res = sexp_make_character('\r'); res = sexp_make_character('\n');
else if (strcasecmp(str, "return") == 0) else if (strcasecmp(str, "return") == 0)
res = sexp_make_character('\r'); res = sexp_make_character('\r');
else if (strcasecmp(str, "tab") == 0) else if (strcasecmp(str, "tab") == 0)
res = sexp_make_character('\t'); res = sexp_make_character('\t');
else { else {
return sexp_read_error("unknown character name", res = sexp_read_error("unknown character name",
sexp_list1(sexp_make_string(str)), sexp_list1(sexp_make_string(str)),
in); in);
} }
} }
sexp_free(str);
break; break;
case '(': case '(':
sexp_push_char(c1, in); sexp_push_char(c1, in);
@ -750,7 +772,7 @@ sexp sexp_read_raw (sexp in) {
if (! sexp_listp(res)) { if (! sexp_listp(res)) {
if (! sexp_exceptionp(res)) { if (! sexp_exceptionp(res)) {
sexp_deep_free(res); sexp_deep_free(res);
return sexp_read_error("dotted list not allowed in vector syntax", res = sexp_read_error("dotted list not allowed in vector syntax",
SEXP_NULL, SEXP_NULL,
in); in);
} }
@ -759,7 +781,7 @@ sexp sexp_read_raw (sexp in) {
} }
break; break;
default: default:
return sexp_read_error("invalid # syntax", res = sexp_read_error("invalid # syntax",
sexp_list1(sexp_make_character(c1)), in); sexp_list1(sexp_make_character(c1)), in);
} }
break; break;

View file

@ -0,0 +1,8 @@
((lambda (a b)
((lambda (c d e)
(write (+ e (* c 1000) (* a 100) (* b 10) d))
(newline))
(- a 2) (+ b 2) 10000))
3 5)

View file

@ -0,0 +1 @@
1000 1003

View file

@ -0,0 +1,8 @@
(let ((a 1000))
(define b (+ a 3))
(write a)
(display " ")
(write b)
(newline))

View file

@ -0,0 +1 @@
11357