Started work on nlambda. It isn't working yet.
This commit is contained in:
parent
0550b0168f
commit
facd5ccc94
27
lisp/defun.lisp
Normal file
27
lisp/defun.lisp
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
13
src/print.c
13
src/print.c
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in a new issue