Started work on nlambda. It isn't working yet.

This commit is contained in:
Simon Brooke 2018-12-13 17:08:47 +00:00
parent 0550b0168f
commit facd5ccc94
8 changed files with 118 additions and 22 deletions

27
lisp/defun.lisp Normal file
View file

@ -0,0 +1,27 @@
;; Because I don't (yet) have syntax for varargs, the body must be passed
;; to defun as a list of sexprs.
(set! defun!
(nlambda
(name args body)
(cond (symbolp name)
(set! name (apply lambda (cons args body))))))
(defun! square (x) ((* x x)))
(set! defsp!
(nlambda
(name args body)
(cond (symbolp name)
(set! name (nlambda args body)))))
(defsp! cube (x) ((* x x x)))
(set! p 5)
(square 5) ;; should work
(square p) ;; should work
(cube 5) ;; should work
(cube p) ;; should fail: unbound symbol

View file

@ -215,6 +215,22 @@ struct cons_pointer make_lambda( struct cons_pointer args,
return pointer; return pointer;
} }
/**
* Construct an nlambda (interpretable source) cell; to a
* lambda as a special form is to a function.
*/
struct cons_pointer make_nlambda( struct cons_pointer args,
struct cons_pointer body ) {
struct cons_pointer pointer = allocate_cell( NLAMBDATAG );
struct cons_space_object *cell = &pointer2cell( pointer );
inc_ref( args );
inc_ref( body );
cell->payload.lambda.args = args;
cell->payload.lambda.body = body;
return pointer;
}
/** /**
* Construct a string from this character (which later will be UTF) and * Construct a string from this character (which later will be UTF) and
* this tail. A string is implemented as a flat list of cells each of which * this tail. A string is implemented as a flat list of cells each of which

View file

@ -73,6 +73,12 @@
#define NILTAG "NIL " #define NILTAG "NIL "
#define NILTV 541870414 #define NILTV 541870414
/**
* An nlambda cell.
*/
#define NLAMBDATAG "NLMD"
#define NLAMBDATV 1145916494
/** /**
* An open read stream. * An open read stream.
*/ */
@ -303,6 +309,9 @@ struct integer_payload {
long int value; long int value;
}; };
/**
* payload for lambda and nlambda cells
*/
struct lambda_payload { struct lambda_payload {
struct cons_pointer args; struct cons_pointer args;
struct cons_pointer body; struct cons_pointer body;
@ -402,7 +411,7 @@ struct cons_space_object {
*/ */
struct integer_payload integer; struct integer_payload integer;
/* /*
* if tag == LAMBDATAG * if tag == LAMBDATAG or NLAMBDATAG
*/ */
struct lambda_payload lambda; struct lambda_payload lambda;
/* /*
@ -481,6 +490,13 @@ struct cons_pointer make_lambda( struct cons_pointer args,
struct cons_pointer body ); struct cons_pointer body );
/** /**
* Construct an nlambda (interpretable source) cell; to a
* lambda as a special form is to a function.
*/
struct cons_pointer make_nlambda( struct cons_pointer args,
struct cons_pointer body );
/**
* Construct a cell which points to an executable Lisp special form. * Construct a cell which points to an executable Lisp special form.
*/ */
struct cons_pointer make_special( struct cons_pointer src, struct cons_pointer make_special( struct cons_pointer src,

View file

@ -107,6 +107,7 @@ int main( int argc, char *argv[] ) {
*/ */
bind_special( "cond", &lisp_cond ); bind_special( "cond", &lisp_cond );
bind_special( "lambda", &lisp_lambda ); bind_special( "lambda", &lisp_lambda );
bind_special( "nlambda", &lisp_nlambda );
bind_special( "quote", &lisp_quote ); bind_special( "quote", &lisp_quote );
bind_special( "set!", &lisp_set_shriek ); bind_special( "set!", &lisp_set_shriek );

View file

@ -96,15 +96,7 @@ struct cons_pointer eval_form( struct stack_frame *parent,
return result; return result;
} }
/** struct cons_pointer compose_body( struct stack_frame *frame ) {
* The Lisp interpreter.
*
* @param frame the stack frame in which the expression is to be interpreted;
* @param env the environment in which it is to be intepreted.
*/
struct cons_pointer
lisp_lambda( struct stack_frame *frame, struct cons_pointer env ) {
dump_frame( stderr, 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;
@ -112,10 +104,31 @@ lisp_lambda( struct stack_frame *frame, struct cons_pointer env ) {
if ( !nilp( frame->arg[i] ) ) { if ( !nilp( frame->arg[i] ) ) {
body = make_cons( frame->arg[i], body ); body = make_cons( frame->arg[i], body );
} }
} }
return make_lambda( frame->arg[0], body ); return body;
}
/**
* Construct an interpretable function.
*
* @param frame the stack frame in which the expression is to be interpreted;
* @param env the environment in which it is to be intepreted.
*/
struct cons_pointer
lisp_lambda( struct stack_frame *frame, struct cons_pointer env ) {
return make_lambda( frame->arg[0], compose_body( frame ) );
}
/**
* Construct an interpretable special form.
*
* @param frame the stack frame in which the expression is to be interpreted;
* @param env the environment in which it is to be intepreted.
*/
struct cons_pointer
lisp_nlambda( struct stack_frame *frame, struct cons_pointer env ) {
return make_nlambda( frame->arg[0], compose_body( frame ) );
} }
@ -153,7 +166,6 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
} }
/** /**
* Internal guts of apply. * Internal guts of apply.
* @param frame the stack frame, expected to have only one argument, a list * @param frame the stack frame, expected to have only one argument, a list
@ -197,6 +209,14 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
free_stack_frame( next ); free_stack_frame( next );
} }
break; break;
case NLAMBDATV:
{
struct stack_frame *next =
make_special_frame( frame, args, env );
result = ( *fn_cell.payload.special.executable ) ( next, env );
free_stack_frame( next );
}
break;
case SPECIALTV: case SPECIALTV:
{ {
struct stack_frame *next = struct stack_frame *next =

View file

@ -42,7 +42,7 @@ 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 );
/** /**
* The Lisp interpreter. * Construct an interpretable function.
* *
* @param frame the stack frame in which the expression is to be interpreted; * @param frame the stack frame in which the expression is to be interpreted;
* @param lexpr the lambda expression to be interpreted; * @param lexpr the lambda expression to be interpreted;
@ -51,6 +51,15 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env );
struct cons_pointer lisp_lambda( struct stack_frame *frame, struct cons_pointer lisp_lambda( struct stack_frame *frame,
struct cons_pointer env ); struct cons_pointer env );
/**
* Construct an interpretable special form.
*
* @param frame the stack frame in which the expression is to be interpreted;
* @param env the environment in which it is to be intepreted.
*/
struct cons_pointer
lisp_nlambda( struct stack_frame *frame, struct cons_pointer env );
struct cons_pointer lisp_quote( struct stack_frame *frame, struct cons_pointer lisp_quote( struct stack_frame *frame,
struct cons_pointer env ); struct cons_pointer env );

View file

@ -131,15 +131,18 @@ void print( FILE * output, struct cons_pointer pointer ) {
} }
break; break;
case LAMBDATV: case LAMBDATV:
fputws( L"(lambda ", output ); print( output, make_cons( c_string_to_lisp_symbol("lambda"),
print( output, cell.payload.lambda.args ); make_cons( cell.payload.lambda.args,
fputws( L" ", output ); cell.payload.lambda.body ) ) );
print( output, cell.payload.lambda.body );
fputws( L")", output );
break; break;
case NILTV: case NILTV:
fwprintf( output, L"nil" ); fwprintf( output, L"nil" );
break; break;
case NLAMBDATV:
print( output, make_cons( c_string_to_lisp_symbol("nlambda"),
make_cons( cell.payload.lambda.args,
cell.payload.lambda.body ) ) );
break;
case REALTV: case REALTV:
/* TODO: using the C heap is a bad plan because it will fragment. /* TODO: using the C heap is a bad plan because it will fragment.
* As soon as I have working vector space I'll use a special purpose * As soon as I have working vector space I'll use a special purpose

View file

@ -60,6 +60,10 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
c == '\0' || iswblank( c ) || iswcntrl( c ); c = fgetwc( input ) ); c == '\0' || iswblank( c ) || iswcntrl( c ); c = fgetwc( input ) );
switch ( c ) { switch ( c ) {
case ';':
for ( c= fgetwc( input ); c != '\n'; c= fgetwc( input ));
/* skip all characters from semi-colon to the end of the line */
break;
case EOF: case EOF:
result = lisp_throw( c_string_to_lisp_string result = lisp_throw( c_string_to_lisp_string
( "End of input while reading" ), frame ); ( "End of input while reading" ), frame );