Much work on the interpreter, but it is getting messy
Going to try something radically different
This commit is contained in:
parent
7d0b6bec97
commit
7189c0172c
|
@ -34,6 +34,13 @@
|
|||
#define CONSTAG "CONS"
|
||||
#define CONSTV 1397641027
|
||||
|
||||
/**
|
||||
* An exception.
|
||||
*/
|
||||
#define EXCEPTIONTAG "EXEP"
|
||||
/* TODO: this is wrong */
|
||||
#define EXCEPTIONTV 1346721861
|
||||
|
||||
/**
|
||||
* An unallocated cell on the free list - should never be encountered by a Lisp
|
||||
* function. 1162170950
|
||||
|
@ -117,13 +124,6 @@
|
|||
/* TODO: this is wrong */
|
||||
#define WRITETV 1414091351
|
||||
|
||||
/**
|
||||
* An exception.
|
||||
*/
|
||||
#define EXCEPTIONTAG "EXEP"
|
||||
/* TODO: this is wrong */
|
||||
#define EXCEPTIONTV 1346721861
|
||||
|
||||
/**
|
||||
* a cons pointer which points to the special NIL cell
|
||||
*/
|
||||
|
|
|
@ -78,8 +78,8 @@ bool equal( struct cons_pointer a, struct cons_pointer b ) {
|
|||
&& ( equal( cell_a->payload.string.cdr,
|
||||
cell_b->payload.string.cdr )
|
||||
|| ( end_of_string( cell_a->payload.string.cdr )
|
||||
&& end_of_string( cell_b->payload.string.
|
||||
cdr ) ) );
|
||||
&& end_of_string( cell_b->payload.
|
||||
string.cdr ) ) );
|
||||
break;
|
||||
case INTEGERTV:
|
||||
case REALTV:
|
||||
|
|
|
@ -74,6 +74,7 @@ int main( int argc, char *argv[] ) {
|
|||
*/
|
||||
deep_bind( c_string_to_lisp_symbol( "nil" ), NIL );
|
||||
deep_bind( c_string_to_lisp_symbol( "t" ), TRUE );
|
||||
/* lambda is even more privileged than a special form */
|
||||
deep_bind( c_string_to_lisp_symbol( "lambda" ), LAMBDA );
|
||||
|
||||
/*
|
||||
|
|
|
@ -104,17 +104,43 @@ struct cons_pointer eval_form( struct stack_frame *parent,
|
|||
* @param env the environment in which it is to be intepreted.
|
||||
*/
|
||||
struct cons_pointer
|
||||
lisp_lambda( struct stack_frame *frame, struct cons_pointer lexpr,
|
||||
struct cons_pointer env ) {
|
||||
lisp_lambda( struct stack_frame *frame, struct cons_pointer env ) {
|
||||
struct cons_pointer result = NIL;
|
||||
struct cons_pointer lexpr = frame->arg[0];
|
||||
struct cons_pointer should_be_lambda =
|
||||
eval_form( frame, c_car( lexpr ), env );
|
||||
|
||||
dump_frame( stderr, frame );
|
||||
|
||||
if ( lambdap( should_be_lambda ) ) {
|
||||
struct cons_pointer new_env = env;
|
||||
struct cons_pointer args = c_car( c_cdr( lexpr ) );
|
||||
struct cons_pointer body = c_cdr( c_cdr( lexpr ) );
|
||||
|
||||
for ( int i = 1; i < args_in_frame && consp( args ); i++ ) {
|
||||
args = c_cdr( args );
|
||||
struct cons_pointer arg = c_car( args );
|
||||
print( stderr, c_string_to_lisp_string( "\n\tBinding " ) );
|
||||
print( stderr, arg );
|
||||
print( stderr, c_string_to_lisp_string( " to " ) );
|
||||
print( stderr, frame->arg[i] );
|
||||
|
||||
new_env = make_cons( make_cons( arg, frame->arg[i] ), new_env );
|
||||
}
|
||||
|
||||
while ( !nilp( body ) ) {
|
||||
struct cons_pointer sexpr = c_car( body );
|
||||
body = c_cdr( body );
|
||||
|
||||
result = eval_form( frame, sexpr, new_env );
|
||||
}
|
||||
} else {
|
||||
if ( exceptionp( should_be_lambda ) ) {
|
||||
result = should_be_lambda;
|
||||
} else {
|
||||
char *buffer = malloc( 1024 );
|
||||
struct cons_space_object not_lambda = pointer2cell( should_be_lambda );
|
||||
struct cons_space_object not_lambda =
|
||||
pointer2cell( should_be_lambda );
|
||||
memset( buffer, '\0', 1024 );
|
||||
sprintf( buffer,
|
||||
"Expected lambda, but found cell with tag %d (%c%c%c%c)",
|
||||
|
@ -125,6 +151,7 @@ lisp_lambda( struct stack_frame *frame, struct cons_pointer lexpr,
|
|||
free( buffer );
|
||||
result = lisp_throw( message, frame );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -159,7 +186,6 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
|||
free_stack_frame( next );
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNCTIONTV:
|
||||
{
|
||||
struct stack_frame *next =
|
||||
|
@ -168,12 +194,17 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
|||
free_stack_frame( next );
|
||||
}
|
||||
break;
|
||||
|
||||
case CONSTV:
|
||||
{
|
||||
result = lisp_lambda( frame, fn_pointer, env );
|
||||
fwprintf( stdout,
|
||||
L"Treating cons as lambda expression (apply)\n" );
|
||||
result = lisp_lambda( frame, env );
|
||||
}
|
||||
break;
|
||||
case EXCEPTIONTV:
|
||||
/* just pass exceptions straight back */
|
||||
result = fn_pointer;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char *buffer = malloc( 1024 );
|
||||
|
@ -235,7 +266,14 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
|
|||
|
||||
switch ( cell.tag.value ) {
|
||||
case CONSTV:
|
||||
print( stderr, frame->arg[0] );
|
||||
if ( lambdap( c_car( frame->arg[0] ) ) ) {
|
||||
fwprintf( stdout,
|
||||
L"Treating cons as lambda expression (eval)\n" );
|
||||
result = lisp_lambda( frame, env );
|
||||
} else {
|
||||
result = c_apply( frame, env );
|
||||
}
|
||||
break;
|
||||
|
||||
case SYMBOLTV:
|
||||
|
|
|
@ -37,6 +37,16 @@ struct cons_pointer lisp_eval( struct stack_frame *frame,
|
|||
struct cons_pointer env );
|
||||
struct cons_pointer lisp_apply( struct stack_frame *frame,
|
||||
struct cons_pointer env );
|
||||
/**
|
||||
* The Lisp interpreter.
|
||||
*
|
||||
* @param frame the stack frame in which the expression is to be interpreted;
|
||||
* @param lexpr the lambda expression 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 );
|
||||
|
||||
struct cons_pointer lisp_quote( struct stack_frame *frame,
|
||||
struct cons_pointer env );
|
||||
|
||||
|
|
26
src/print.c
26
src/print.c
|
@ -22,20 +22,34 @@
|
|||
#include "integer.h"
|
||||
#include "print.h"
|
||||
|
||||
/**
|
||||
* Whether or not we colorise output.
|
||||
* TODO: this should be a Lisp symbol binding, not a C variable.
|
||||
*/
|
||||
int print_use_colours = 0;
|
||||
|
||||
/**
|
||||
* print all the characters in the symbol or string indicated by `pointer`
|
||||
* onto this `output`; if `pointer` does not indicate a string or symbol,
|
||||
* don't print anything but just return.
|
||||
*/
|
||||
void print_string_contents( FILE * output, struct cons_pointer pointer ) {
|
||||
if ( stringp( pointer ) || symbolp( pointer ) ) {
|
||||
while ( stringp( pointer ) || symbolp( pointer ) ) {
|
||||
struct cons_space_object *cell = &pointer2cell( pointer );
|
||||
wint_t c = cell->payload.string.character;
|
||||
|
||||
if ( c != '\0' ) {
|
||||
fputwc( c, output );
|
||||
}
|
||||
print_string_contents( output, cell->payload.string.cdr );
|
||||
pointer = cell->payload.string.cdr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* print all the characters in the string indicated by `pointer` onto
|
||||
* the stream at this `output`, prepending and appending double quote
|
||||
* characters.
|
||||
*/
|
||||
void print_string( FILE * output, struct cons_pointer pointer ) {
|
||||
fputwc( btowc( '"' ), output );
|
||||
print_string_contents( output, pointer );
|
||||
|
@ -43,7 +57,9 @@ void print_string( FILE * output, struct cons_pointer pointer ) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Print a single list cell (cons cell).
|
||||
* Print a single list cell (cons cell) indicated by `pointer` to the
|
||||
* stream indicated by `output`. if `initial_space` is `true`, prepend
|
||||
* a space character.
|
||||
*/
|
||||
void
|
||||
print_list_contents( FILE * output, struct cons_pointer pointer,
|
||||
|
@ -83,6 +99,10 @@ void print_list( FILE * output, struct cons_pointer pointer ) {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the cons-space object indicated by `pointer` to the stream indicated
|
||||
* by `output`.
|
||||
*/
|
||||
void print( FILE * output, struct cons_pointer pointer ) {
|
||||
struct cons_space_object cell = pointer2cell( pointer );
|
||||
char *buffer;
|
||||
|
|
Loading…
Reference in a new issue