Much work, all I think positive, but defun still doesn't work.
This commit is contained in:
parent
efea0192f3
commit
637d78fb1b
|
@ -4,8 +4,8 @@
|
||||||
(nlambda
|
(nlambda
|
||||||
form
|
form
|
||||||
(cond ((symbolp (car form))
|
(cond ((symbolp (car form))
|
||||||
(set! (car form) (apply lambda (cdr form)))))
|
(set (car form) (apply lambda (cdr form))))
|
||||||
(t nil)))
|
(t nil))))
|
||||||
|
|
||||||
(defun! square (x) (* x x))
|
(defun! square (x) (* x x))
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,33 @@ void dump_pages( FILE * output ) {
|
||||||
void free_cell( struct cons_pointer pointer ) {
|
void free_cell( struct cons_pointer pointer ) {
|
||||||
struct cons_space_object *cell = &pointer2cell( pointer );
|
struct cons_space_object *cell = &pointer2cell( pointer );
|
||||||
|
|
||||||
|
switch ( cell->tag.value ) {
|
||||||
|
/* for all the types of cons-space object which point to other
|
||||||
|
* cons-space objects, cascade the decrement. */
|
||||||
|
case CONSTV:
|
||||||
|
dec_ref( cell->payload.cons.car );
|
||||||
|
dec_ref( cell->payload.cons.cdr );
|
||||||
|
break;
|
||||||
|
case EXCEPTIONTV:
|
||||||
|
dec_ref( cell->payload.exception.message );
|
||||||
|
break;
|
||||||
|
case FUNCTIONTV:
|
||||||
|
dec_ref( cell->payload.function.source );
|
||||||
|
break;
|
||||||
|
case LAMBDATV:
|
||||||
|
case NLAMBDATV:
|
||||||
|
dec_ref( cell->payload.lambda.args );
|
||||||
|
dec_ref( cell->payload.lambda.body );
|
||||||
|
break;
|
||||||
|
case SPECIALTV:
|
||||||
|
dec_ref( cell->payload.special.source );
|
||||||
|
break;
|
||||||
|
case STRINGTV:
|
||||||
|
case SYMBOLTV:
|
||||||
|
dec_ref( cell->payload.string.cdr );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !check_tag( pointer, FREETAG ) ) {
|
if ( !check_tag( pointer, FREETAG ) ) {
|
||||||
if ( cell->count == 0 ) {
|
if ( cell->count == 0 ) {
|
||||||
fwprintf( stderr, L"Freeing cell " );
|
fwprintf( stderr, L"Freeing cell " );
|
||||||
|
|
|
@ -177,6 +177,9 @@ struct cons_pointer make_exception( struct cons_pointer message,
|
||||||
struct cons_pointer pointer = allocate_cell( EXCEPTIONTAG );
|
struct cons_pointer pointer = allocate_cell( EXCEPTIONTAG );
|
||||||
struct cons_space_object *cell = &pointer2cell( pointer );
|
struct cons_space_object *cell = &pointer2cell( pointer );
|
||||||
|
|
||||||
|
inc_ref( pointer ); /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
|
||||||
|
|
||||||
|
inc_ref( message );
|
||||||
cell->payload.exception.message = message;
|
cell->payload.exception.message = message;
|
||||||
cell->payload.exception.frame = frame;
|
cell->payload.exception.frame = frame;
|
||||||
|
|
||||||
|
@ -206,6 +209,9 @@ struct cons_pointer make_lambda( struct cons_pointer args,
|
||||||
struct cons_pointer body ) {
|
struct cons_pointer body ) {
|
||||||
struct cons_pointer pointer = allocate_cell( LAMBDATAG );
|
struct cons_pointer pointer = allocate_cell( LAMBDATAG );
|
||||||
struct cons_space_object *cell = &pointer2cell( pointer );
|
struct cons_space_object *cell = &pointer2cell( pointer );
|
||||||
|
|
||||||
|
inc_ref( pointer ); /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
|
||||||
|
|
||||||
inc_ref( args );
|
inc_ref( args );
|
||||||
inc_ref( body );
|
inc_ref( body );
|
||||||
cell->payload.lambda.args = args;
|
cell->payload.lambda.args = args;
|
||||||
|
@ -221,6 +227,9 @@ struct cons_pointer make_lambda( struct cons_pointer args,
|
||||||
struct cons_pointer make_nlambda( struct cons_pointer args,
|
struct cons_pointer make_nlambda( struct cons_pointer args,
|
||||||
struct cons_pointer body ) {
|
struct cons_pointer body ) {
|
||||||
struct cons_pointer pointer = allocate_cell( NLAMBDATAG );
|
struct cons_pointer pointer = allocate_cell( NLAMBDATAG );
|
||||||
|
|
||||||
|
inc_ref( pointer ); /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
|
||||||
|
|
||||||
struct cons_space_object *cell = &pointer2cell( pointer );
|
struct cons_space_object *cell = &pointer2cell( pointer );
|
||||||
inc_ref( args );
|
inc_ref( args );
|
||||||
inc_ref( body );
|
inc_ref( body );
|
||||||
|
|
|
@ -80,8 +80,8 @@ bool equal( struct cons_pointer a, struct cons_pointer b ) {
|
||||||
&& ( equal( cell_a->payload.string.cdr,
|
&& ( equal( cell_a->payload.string.cdr,
|
||||||
cell_b->payload.string.cdr )
|
cell_b->payload.string.cdr )
|
||||||
|| ( end_of_string( cell_a->payload.string.cdr )
|
|| ( end_of_string( cell_a->payload.string.cdr )
|
||||||
&& end_of_string( cell_b->payload.
|
&& end_of_string( cell_b->payload.string.
|
||||||
string.cdr ) ) );
|
cdr ) ) );
|
||||||
break;
|
break;
|
||||||
case INTEGERTV:
|
case INTEGERTV:
|
||||||
result =
|
result =
|
||||||
|
|
|
@ -92,8 +92,10 @@ int main( int argc, char *argv[] ) {
|
||||||
bind_function( "eval", &lisp_eval );
|
bind_function( "eval", &lisp_eval );
|
||||||
bind_function( "multiply", &lisp_multiply );
|
bind_function( "multiply", &lisp_multiply );
|
||||||
bind_function( "read", &lisp_read );
|
bind_function( "read", &lisp_read );
|
||||||
|
bind_function( "oblist", &lisp_oblist );
|
||||||
bind_function( "print", &lisp_print );
|
bind_function( "print", &lisp_print );
|
||||||
bind_function( "progn", &lisp_progn );
|
bind_function( "progn", &lisp_progn );
|
||||||
|
bind_function( "set", &lisp_set );
|
||||||
bind_function( "subtract", &lisp_subtract );
|
bind_function( "subtract", &lisp_subtract );
|
||||||
bind_function( "type", &lisp_type );
|
bind_function( "type", &lisp_type );
|
||||||
|
|
||||||
|
@ -112,11 +114,6 @@ int main( int argc, char *argv[] ) {
|
||||||
bind_special( "quote", &lisp_quote );
|
bind_special( "quote", &lisp_quote );
|
||||||
bind_special( "set!", &lisp_set_shriek );
|
bind_special( "set!", &lisp_set_shriek );
|
||||||
|
|
||||||
|
|
||||||
/* bind the oblist last, at this stage. Something clever needs to be done
|
|
||||||
* here and I'm not sure what it is. */
|
|
||||||
deep_bind( c_string_to_lisp_symbol( "oblist" ), oblist );
|
|
||||||
|
|
||||||
repl( stdin, stdout, stderr, show_prompt );
|
repl( stdin, stdout, stderr, show_prompt );
|
||||||
|
|
||||||
if ( dump_at_end ) {
|
if ( dump_at_end ) {
|
||||||
|
|
|
@ -133,7 +133,6 @@ struct cons_pointer
|
||||||
intern( struct cons_pointer key, struct cons_pointer environment ) {
|
intern( struct cons_pointer key, struct cons_pointer environment ) {
|
||||||
struct cons_pointer result = environment;
|
struct cons_pointer result = environment;
|
||||||
struct cons_pointer canonical = internedp( key, environment );
|
struct cons_pointer canonical = internedp( key, environment );
|
||||||
|
|
||||||
if ( nilp( canonical ) ) {
|
if ( nilp( canonical ) ) {
|
||||||
/*
|
/*
|
||||||
* not currently bound
|
* not currently bound
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct cons_pointer c_car( struct cons_pointer arg ) {
|
||||||
struct cons_pointer c_cdr( struct cons_pointer arg ) {
|
struct cons_pointer c_cdr( struct cons_pointer arg ) {
|
||||||
struct cons_pointer result = NIL;
|
struct cons_pointer result = NIL;
|
||||||
|
|
||||||
if ( consp( arg ) ) {
|
if ( consp( arg ) || stringp( arg ) || symbolp( arg ) ) {
|
||||||
result = pointer2cell( arg ).payload.cons.cdr;
|
result = pointer2cell( arg ).payload.cons.cdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +115,16 @@ struct cons_pointer eval_forms( struct stack_frame *frame,
|
||||||
eval_forms( frame, c_cdr( list ), env ) ) : NIL;
|
eval_forms( frame, c_cdr( list ), env ) ) : NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the object list (root namespace).
|
||||||
|
*
|
||||||
|
* (oblist)
|
||||||
|
*/
|
||||||
|
struct cons_pointer
|
||||||
|
lisp_oblist( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
return oblist;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used to construct the body for `lambda` and `nlambda` expressions.
|
* used to construct the body for `lambda` and `nlambda` expressions.
|
||||||
|
@ -123,12 +133,18 @@ struct cons_pointer compose_body( struct stack_frame *frame ) {
|
||||||
struct cons_pointer body =
|
struct cons_pointer body =
|
||||||
!nilp( frame->arg[args_in_frame - 1] ) ? frame->more : NIL;
|
!nilp( frame->arg[args_in_frame - 1] ) ? frame->more : NIL;
|
||||||
|
|
||||||
for ( int i = args_in_frame - 1; i >= 0; i-- ) {
|
for ( int i = args_in_frame - 1; i > 0; i-- ) {
|
||||||
if ( !nilp( frame->arg[i] ) ) {
|
if ( !nilp( body ) ) {
|
||||||
|
body = make_cons( frame->arg[i], body );
|
||||||
|
} else if ( !nilp( frame->arg[i] ) ) {
|
||||||
body = make_cons( frame->arg[i], body );
|
body = make_cons( frame->arg[i], body );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fputws( L"compose_body returning ", stderr );
|
||||||
|
print( stderr, body );
|
||||||
|
fputws( L"\n", stderr );
|
||||||
|
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +185,7 @@ struct cons_pointer
|
||||||
eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
|
eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
|
||||||
struct cons_pointer env ) {
|
struct cons_pointer env ) {
|
||||||
struct cons_pointer result = NIL;
|
struct cons_pointer result = NIL;
|
||||||
fwprintf( stderr, L"eval_lambda called" );
|
fwprintf( stderr, L"eval_lambda called\n" );
|
||||||
|
|
||||||
struct cons_pointer new_env = env;
|
struct cons_pointer new_env = env;
|
||||||
struct cons_pointer names = cell.payload.lambda.args;
|
struct cons_pointer names = cell.payload.lambda.args;
|
||||||
|
@ -278,7 +294,9 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
{
|
{
|
||||||
struct stack_frame *next =
|
struct stack_frame *next =
|
||||||
make_special_frame( frame, args, env );
|
make_special_frame( frame, args, env );
|
||||||
result = ( *fn_cell.payload.special.executable ) ( next, env );
|
fputws( L"Stack frame for nlambda\n", stderr );
|
||||||
|
dump_frame( stderr, next );
|
||||||
|
result = eval_lambda( fn_cell, next, env );
|
||||||
if ( !exceptionp( result ) ) {
|
if ( !exceptionp( result ) ) {
|
||||||
/* if we're returning an exception, we should NOT free the
|
/* if we're returning an exception, we should NOT free the
|
||||||
* stack frame. Corollary is, when we free an exception, we
|
* stack frame. Corollary is, when we free an exception, we
|
||||||
|
@ -440,13 +458,45 @@ lisp_quote( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
return frame->arg[0];
|
return frame->arg[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (set name value)
|
||||||
|
* (set name value namespace)
|
||||||
|
*
|
||||||
|
* Function.
|
||||||
|
* `namespace` defaults to the oblist.
|
||||||
|
* Binds the value of `name` in the `namespace` to value of `value`, altering
|
||||||
|
* the namespace in so doing. `namespace` defaults to the value of `oblist`.
|
||||||
|
*/
|
||||||
|
struct cons_pointer
|
||||||
|
lisp_set( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
struct cons_pointer result = NIL;
|
||||||
|
struct cons_pointer namespace =
|
||||||
|
nilp( frame->arg[2] ) ? oblist : frame->arg[2];
|
||||||
|
|
||||||
|
if ( symbolp( frame->arg[0] ) ) {
|
||||||
|
deep_bind( frame->arg[0], frame->arg[1] );
|
||||||
|
result = frame->arg[1];
|
||||||
|
} else {
|
||||||
|
result =
|
||||||
|
make_exception( make_cons
|
||||||
|
( c_string_to_lisp_string
|
||||||
|
( "The first argument to `set!` is not a symbol: " ),
|
||||||
|
make_cons( frame->arg[0], NIL ) ), frame );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (set! symbol value)
|
* (set! symbol value)
|
||||||
* (set! symbol value namespace)
|
* (set! symbol value namespace)
|
||||||
*
|
*
|
||||||
* Special form.
|
* Special form.
|
||||||
* `namespace` defaults to the oblist.
|
* `namespace` defaults to the oblist.
|
||||||
* Binds `symbol` to `value` in the namespace, altering the namespace in so doing.
|
* Binds `symbol` in the `namespace` to value of `value`, altering
|
||||||
|
* the namespace in so doing. `namespace` defaults to the value of `oblist`.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer
|
struct cons_pointer
|
||||||
lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env ) {
|
lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
@ -455,13 +505,15 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
nilp( frame->arg[2] ) ? oblist : frame->arg[2];
|
nilp( frame->arg[2] ) ? oblist : frame->arg[2];
|
||||||
|
|
||||||
if ( symbolp( frame->arg[0] ) ) {
|
if ( symbolp( frame->arg[0] ) ) {
|
||||||
deep_bind( frame->arg[0], eval_form( frame, frame->arg[1], env ) );
|
struct cons_pointer val = eval_form( frame, frame->arg[1], env );
|
||||||
result = frame->arg[1];
|
deep_bind( frame->arg[0], val );
|
||||||
|
result = val;
|
||||||
} else {
|
} else {
|
||||||
result =
|
result =
|
||||||
make_exception( c_string_to_lisp_string
|
make_exception( make_cons
|
||||||
( "The first argument to `set!` is not a symbol" ),
|
( c_string_to_lisp_string
|
||||||
frame );
|
( "The first argument to `set!` is not a symbol: " ),
|
||||||
|
make_cons( frame->arg[0], NIL ) ), frame );
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -670,15 +722,16 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
|
||||||
if ( consp( clause_pointer ) ) {
|
if ( consp( clause_pointer ) ) {
|
||||||
struct cons_space_object cell = pointer2cell( clause_pointer );
|
struct cons_space_object cell = pointer2cell( clause_pointer );
|
||||||
result = eval_form( frame, c_car( clause_pointer ), env);
|
result = eval_form( frame, c_car( clause_pointer ), env );
|
||||||
|
|
||||||
if ( !nilp( result ) ) {
|
if ( !nilp( result ) ) {
|
||||||
struct cons_pointer vals = eval_forms( frame, c_cdr( clause_pointer ), env );
|
struct cons_pointer vals =
|
||||||
|
eval_forms( frame, c_cdr( clause_pointer ), env );
|
||||||
|
|
||||||
while (consp( vals)) {
|
while ( consp( vals ) ) {
|
||||||
result = c_car(vals);
|
result = c_car( vals );
|
||||||
vals = c_cdr(vals);
|
vals = c_cdr( vals );
|
||||||
}
|
}
|
||||||
|
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
@ -698,6 +751,11 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: make this do something sensible somehow.
|
* TODO: make this do something sensible somehow.
|
||||||
|
* This requires that a frame be a heap-space object with a cons-space
|
||||||
|
* object pointing to it. Then this should become a normal lisp function
|
||||||
|
* which expects a normally bound frame and environment, such that
|
||||||
|
* frame->arg[0] is the message, and frame->arg[1] is the cons-space
|
||||||
|
* pointer to the frame in which the exception occurred.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer
|
struct cons_pointer
|
||||||
lisp_throw( struct cons_pointer message, struct stack_frame *frame ) {
|
lisp_throw( struct cons_pointer message, struct stack_frame *frame ) {
|
||||||
|
|
|
@ -71,6 +71,12 @@ struct cons_pointer lisp_eval( struct stack_frame *frame,
|
||||||
struct cons_pointer lisp_apply( struct stack_frame *frame,
|
struct cons_pointer lisp_apply( struct stack_frame *frame,
|
||||||
struct cons_pointer env );
|
struct cons_pointer env );
|
||||||
|
|
||||||
|
struct cons_pointer
|
||||||
|
lisp_oblist( struct stack_frame *frame, struct cons_pointer env );
|
||||||
|
|
||||||
|
struct cons_pointer
|
||||||
|
lisp_set( struct stack_frame *frame, struct cons_pointer env );
|
||||||
|
|
||||||
struct cons_pointer
|
struct cons_pointer
|
||||||
lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env );
|
lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env );
|
||||||
|
|
||||||
|
|
17
src/print.c
17
src/print.c
|
@ -132,8 +132,8 @@ void print( FILE * output, struct cons_pointer pointer ) {
|
||||||
case LAMBDATV:
|
case LAMBDATV:
|
||||||
print( output, make_cons( c_string_to_lisp_symbol( "lambda" ),
|
print( output, make_cons( c_string_to_lisp_symbol( "lambda" ),
|
||||||
make_cons( cell.payload.lambda.args,
|
make_cons( cell.payload.lambda.args,
|
||||||
cell.payload.lambda.
|
cell.payload.
|
||||||
body ) ) );
|
lambda.body ) ) );
|
||||||
break;
|
break;
|
||||||
case NILTV:
|
case NILTV:
|
||||||
fwprintf( output, L"nil" );
|
fwprintf( output, L"nil" );
|
||||||
|
@ -141,8 +141,8 @@ void print( FILE * output, struct cons_pointer pointer ) {
|
||||||
case NLAMBDATV:
|
case NLAMBDATV:
|
||||||
print( output, make_cons( c_string_to_lisp_symbol( "nlambda" ),
|
print( output, make_cons( c_string_to_lisp_symbol( "nlambda" ),
|
||||||
make_cons( cell.payload.lambda.args,
|
make_cons( cell.payload.lambda.args,
|
||||||
cell.payload.lambda.
|
cell.payload.
|
||||||
body ) ) );
|
lambda.body ) ) );
|
||||||
break;
|
break;
|
||||||
case READTV:
|
case READTV:
|
||||||
fwprintf( output, L"(Input stream)" );
|
fwprintf( output, L"(Input stream)" );
|
||||||
|
@ -173,8 +173,9 @@ void print( FILE * output, struct cons_pointer pointer ) {
|
||||||
print_string( output, pointer );
|
print_string( output, pointer );
|
||||||
break;
|
break;
|
||||||
case SYMBOLTV:
|
case SYMBOLTV:
|
||||||
if ( print_use_colours )
|
if ( print_use_colours ) {
|
||||||
fputws( L"\x1B[1;33m", output );
|
fputws( L"\x1B[1;33m", output );
|
||||||
|
}
|
||||||
print_string_contents( output, pointer );
|
print_string_contents( output, pointer );
|
||||||
break;
|
break;
|
||||||
case SPECIALTV:
|
case SPECIALTV:
|
||||||
|
@ -185,10 +186,10 @@ void print( FILE * output, struct cons_pointer pointer ) {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fwprintf( stderr,
|
fwprintf( stderr,
|
||||||
L"%sError: Unrecognised tag value %d (%c%c%c%c)%s\n",
|
L"%sError: Unrecognised tag value %d (%c%c%c%c)\n",
|
||||||
"\x1B[31m",
|
print_use_colours ? "\x1B[31m" : "",
|
||||||
cell.tag.value, cell.tag.bytes[0], cell.tag.bytes[1],
|
cell.tag.value, cell.tag.bytes[0], cell.tag.bytes[1],
|
||||||
cell.tag.bytes[2], cell.tag.bytes[3], "\x1B[39m" );
|
cell.tag.bytes[2], cell.tag.bytes[3] );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/repl.c
10
src/repl.c
|
@ -97,10 +97,12 @@ repl( FILE * in_stream, FILE * out_stream, FILE * error_stream,
|
||||||
|
|
||||||
struct cons_pointer val = repl_eval( input );
|
struct cons_pointer val = repl_eval( input );
|
||||||
|
|
||||||
/* suppress the 'end of stream' exception */
|
if ( feof( pointer2cell( input_stream ).payload.stream.stream ) ) {
|
||||||
if ( !exceptionp( val ) &&
|
/* suppress the 'end of stream' exception */
|
||||||
!feof( pointer2cell( input_stream ).payload.stream.
|
if ( !exceptionp( val ) ) {
|
||||||
stream ) ) {
|
repl_print( output_stream, val );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
repl_print( output_stream, val );
|
repl_print( output_stream, val );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,9 +169,10 @@ void dump_frame( FILE * output, struct stack_frame *frame ) {
|
||||||
for ( int arg = 0; arg < args_in_frame; arg++ ) {
|
for ( int arg = 0; arg < args_in_frame; arg++ ) {
|
||||||
struct cons_space_object cell = pointer2cell( frame->arg[arg] );
|
struct cons_space_object cell = pointer2cell( frame->arg[arg] );
|
||||||
|
|
||||||
fwprintf( output, L"Arg %d:\t%c%c%c%c\t", arg,
|
fwprintf( output, L"Arg %d:\t%c%c%c%c\tcount: %10u\tvalue: ", arg,
|
||||||
cell.tag.bytes[0],
|
cell.tag.bytes[0],
|
||||||
cell.tag.bytes[1], cell.tag.bytes[2], cell.tag.bytes[3] );
|
cell.tag.bytes[1], cell.tag.bytes[2], cell.tag.bytes[3],
|
||||||
|
cell.count );
|
||||||
|
|
||||||
print( output, frame->arg[arg] );
|
print( output, frame->arg[arg] );
|
||||||
fputws( L"\n", output );
|
fputws( L"\n", output );
|
||||||
|
|
16
unit-tests/lambda.sh
Normal file
16
unit-tests/lambda.sh
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
expected='(lambda (l) l)(1 2 3 4 5 6 7 8 9 10)'
|
||||||
|
actual=`target/psse 2>/dev/null <<EOF
|
||||||
|
(set! list (lambda (l) l))
|
||||||
|
(list '(1 2 3 4 5 6 7 8 9 10))
|
||||||
|
EOF`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
Loading…
Reference in a new issue