All unit tests pass. The eval-quote problem is solved.
This commit is contained in:
parent
fd9c851185
commit
645ab3674e
|
@ -86,6 +86,7 @@ int main( int argc, char *argv[] ) {
|
||||||
bind_function( "cons", &lisp_cons );
|
bind_function( "cons", &lisp_cons );
|
||||||
bind_function( "eq", &lisp_eq );
|
bind_function( "eq", &lisp_eq );
|
||||||
bind_function( "equal", &lisp_equal );
|
bind_function( "equal", &lisp_equal );
|
||||||
|
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( "print", &lisp_print );
|
bind_function( "print", &lisp_print );
|
||||||
|
@ -101,7 +102,6 @@ int main( int argc, char *argv[] ) {
|
||||||
* primitive special forms
|
* primitive special forms
|
||||||
*/
|
*/
|
||||||
bind_special( "cond", &lisp_cond );
|
bind_special( "cond", &lisp_cond );
|
||||||
bind_function( "eval", &lisp_eval );
|
|
||||||
bind_special( "quote", &lisp_quote );
|
bind_special( "quote", &lisp_quote );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* also to create in this section:
|
* 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 cons_pointer lisp_let( struct cons_pointer args, struct cons_pointer env,
|
||||||
struct stack_frame* frame);
|
struct stack_frame* frame);
|
||||||
* struct cons_pointer lisp_mapcar( struct cons_pointer args, struct cons_pointer env,
|
* 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.
|
* 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 form the form to be evaluated.
|
||||||
* @param env the evaluation environment.
|
* @param env the evaluation environment.
|
||||||
* @return the result of evaluating the form.
|
* @return the result of evaluating the form.
|
||||||
|
@ -130,7 +128,7 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
|
||||||
case FUNCTIONTV:
|
case FUNCTIONTV:
|
||||||
/*
|
/*
|
||||||
* actually, this is apply
|
* actually, this is apply
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
struct stack_frame *next = make_stack_frame( frame, args, env );
|
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)
|
* (eval s_expr)
|
||||||
*
|
*
|
||||||
* Special form.
|
* function.
|
||||||
* If s_expr is a number, NIL, or T, returns s_expr.
|
* 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
|
* If s_expr is an unprotected string, returns the value that s_expr is bound
|
||||||
* to in the evaluation environment (env).
|
* 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.
|
* function or special form.
|
||||||
* If a function, evaluates all the other top level elements in s_expr and
|
* 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.
|
* 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 ) {
|
switch ( cell.tag.value ) {
|
||||||
case CONSTV:
|
case CONSTV:
|
||||||
result = c_apply( frame, env );
|
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;
|
break;
|
||||||
|
|
||||||
case SYMBOLTV:
|
case SYMBOLTV:
|
||||||
|
@ -227,11 +214,11 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
}
|
}
|
||||||
break;
|
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
|
* 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
|
* 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
|
* long run I don't want an interpreter, and if I can get away without
|
||||||
* so much the better.
|
* so much the better.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +232,7 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (apply fn args)
|
* (apply fn args)
|
||||||
*
|
*
|
||||||
* function. Apply the function which is the result of evaluating the
|
* function. Apply the function which is the result of evaluating the
|
||||||
* first argoment to the list of arguments which is the result of evaluating
|
* first argoment to the list of arguments which is the result of evaluating
|
||||||
* the second argument
|
* the second argument
|
||||||
|
@ -386,7 +373,7 @@ lisp_equal( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
/**
|
/**
|
||||||
* (read)
|
* (read)
|
||||||
* (read read-stream)
|
* (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.
|
* is a read stream, then read from that stream, else stdin.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer
|
struct cons_pointer
|
||||||
|
@ -404,7 +391,7 @@ lisp_read( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
/**
|
/**
|
||||||
* (print expr)
|
* (print expr)
|
||||||
* (print expr write-stream)
|
* (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.
|
* is a write stream, then print to that stream, else stdout.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer
|
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'
|
* sequentially and return the value of the last. This function is called 'do'
|
||||||
* in some dialects of Lisp.
|
* in some dialects of Lisp.
|
||||||
*
|
*
|
||||||
* @param frame My stack frame.
|
* @param frame My stack frame.
|
||||||
* @param env My environment (ignored).
|
* @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.
|
* argument.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer
|
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
|
* 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
|
* 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)
|
* 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.
|
* has a first element which evaluates to non NIL, then NIL is returned.
|
||||||
* @param frame My stack frame.
|
* @param frame My stack frame.
|
||||||
* @param env My environment (ignored).
|
* @param env My environment (ignored).
|
||||||
|
|
Loading…
Reference in a new issue