All unit tests pass. The eval-quote problem is solved.

This commit is contained in:
Simon Brooke 2018-12-07 06:43:23 +00:00
parent fd9c851185
commit 645ab3674e
2 changed files with 18 additions and 31 deletions

View file

@ -86,6 +86,7 @@ int main( int argc, char *argv[] ) {
bind_function( "cons", &lisp_cons );
bind_function( "eq", &lisp_eq );
bind_function( "equal", &lisp_equal );
bind_function( "eval", &lisp_eval );
bind_function( "multiply", &lisp_multiply );
bind_function( "read", &lisp_read );
bind_function( "print", &lisp_print );
@ -101,7 +102,6 @@ int main( int argc, char *argv[] ) {
* primitive special forms
*/
bind_special( "cond", &lisp_cond );
bind_function( "eval", &lisp_eval );
bind_special( "quote", &lisp_quote );

View file

@ -36,8 +36,6 @@
/*
* also to create in this section:
* struct cons_pointer lisp_cond( struct cons_pointer args, struct cons_pointer env,
struct stack_frame* frame);
* struct cons_pointer lisp_let( struct cons_pointer args, struct cons_pointer env,
struct stack_frame* frame);
* struct cons_pointer lisp_mapcar( struct cons_pointer args, struct cons_pointer env,
@ -74,9 +72,9 @@ struct cons_pointer c_cdr( struct cons_pointer arg ) {
/**
* Useful building block; evaluate this single form in the context of this
* Useful building block; evaluate this single form in the context of this
* parent stack frame and this environment.
* @param parent the parent stack frame.
* @param parent the parent stack frame.
* @param form the form to be evaluated.
* @param env the evaluation environment.
* @return the result of evaluating the form.
@ -130,7 +128,7 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
case FUNCTIONTV:
/*
* actually, this is apply
* actually, this is apply
*/
{
struct stack_frame *next = make_stack_frame( frame, args, env );
@ -179,11 +177,11 @@ struct cons_pointer c_type( struct cons_pointer pointer ) {
/**
* (eval s_expr)
*
* Special form.
* function.
* If s_expr is a number, NIL, or T, returns s_expr.
* If s_expr is an unprotected string, returns the value that s_expr is bound
* to in the evaluation environment (env).
* If s_expr is a list, expects the car to be something that evaluates to a
* If s_expr is a list, expects the car to be something that evaluates to a
* function or special form.
* If a function, evaluates all the other top level elements in s_expr and
* passes them in a stack frame as arguments to the function.
@ -200,17 +198,6 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
switch ( cell.tag.value ) {
case CONSTV:
result = c_apply( frame, env );
/* I have a profound misunderstanding of how quote and eval should interact!
* if ( equal( c_car(frame->arg[0]), c_string_to_lisp_symbol("quote")))
* /\* car is QUOTE. TODO: It is ABSURDLY expensive to 'equal' each time! *\/
* {
* /\* we need to eval it again *\/
* frame->arg[0] = result;
* fputws( L"quote - re-evaling", stderr);
* dump_frame( stderr, frame );
* result = c_apply(frame, env);
* } */
break;
case SYMBOLTV:
@ -227,11 +214,11 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
}
break;
/*
* the Clojure practice of having a map serve in the function place of
* the Clojure practice of having a map serve in the function place of
* an s-expression is a good one and I should adopt it; also if the
* object is a consp it could be interpretable source code but in the
* long run I don't want an interpreter, and if I can get away without
* so much the better.
* long run I don't want an interpreter, and if I can get away without
* so much the better.
*/
}
@ -245,7 +232,7 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
/**
* (apply fn args)
*
*
* function. Apply the function which is the result of evaluating the
* first argoment to the list of arguments which is the result of evaluating
* the second argument
@ -386,7 +373,7 @@ lisp_equal( struct stack_frame *frame, struct cons_pointer env ) {
/**
* (read)
* (read read-stream)
* Read one complete lisp form and return it. If read-stream is specified and
* Read one complete lisp form and return it. If read-stream is specified and
* is a read stream, then read from that stream, else stdin.
*/
struct cons_pointer
@ -404,7 +391,7 @@ lisp_read( struct stack_frame *frame, struct cons_pointer env ) {
/**
* (print expr)
* (print expr write-stream)
* Print one complete lisp form and return NIL. If write-stream is specified and
* Print one complete lisp form and return NIL. If write-stream is specified and
* is a write stream, then print to that stream, else stdout.
*/
struct cons_pointer
@ -434,13 +421,13 @@ lisp_type( struct stack_frame *frame, struct cons_pointer env ) {
/**
* Function; evaluate the forms which are listed in my single argument
* Function; evaluate the forms which are listed in my single argument
* sequentially and return the value of the last. This function is called 'do'
* in some dialects of Lisp.
*
*
* @param frame My stack frame.
* @param env My environment (ignored).
* @return the value of the last form on the sequence which is my single
* @return the value of the last form on the sequence which is my single
* argument.
*/
struct cons_pointer
@ -459,9 +446,9 @@ lisp_progn( struct stack_frame *frame, struct cons_pointer env ) {
}
/**
* Special form: conditional. Each arg is expected to be a list; if the first
* item in such a list evaluates to non-NIL, the remaining items in that list
* are evaluated in turn and the value of the last returned. If no arg (clause)
* Special form: conditional. Each arg is expected to be a list; if the first
* item in such a list evaluates to non-NIL, the remaining items in that list
* are evaluated in turn and the value of the last returned. If no arg (clause)
* has a first element which evaluates to non NIL, then NIL is returned.
* @param frame My stack frame.
* @param env My environment (ignored).