Made try/catch actually work

This commit is contained in:
Simon Brooke 2021-09-12 16:20:13 +01:00
parent 462c0c69b4
commit a8315d649f
No known key found for this signature in database
GPG key ID: A7A4F18D1D4DF987
4 changed files with 60 additions and 13 deletions

View file

@ -278,6 +278,7 @@ int main( int argc, char *argv[] ) {
bind_special( L"progn", &lisp_progn ); bind_special( L"progn", &lisp_progn );
bind_special( L"quote", &lisp_quote ); bind_special( L"quote", &lisp_quote );
bind_special( L"set!", &lisp_set_shriek ); bind_special( L"set!", &lisp_set_shriek );
bind_special( L"try", &lisp_try );
debug_print( L"Initialised oblist\n", DEBUG_BOOTSTRAP ); debug_print( L"Initialised oblist\n", DEBUG_BOOTSTRAP );
debug_dump_object( oblist, DEBUG_BOOTSTRAP ); debug_dump_object( oblist, DEBUG_BOOTSTRAP );

View file

@ -138,7 +138,7 @@ struct cons_pointer eval_forms( struct stack_frame *frame,
/** /**
* OK, the idea here (and I know this is less than perfect) is that the basic `try` * OK, the idea here (and I know this is less than perfect) is that the basic `try`
* function in PSSE takes two arguments, the first, `body`, being a list of forms, * special form in PSSE takes two arguments, the first, `body`, being a list of forms,
* and the second, `catch`, being a catch handler (which is also a list of forms). * and the second, `catch`, being a catch handler (which is also a list of forms).
* Forms from `body` are evaluated in turn until one returns an exception object, * Forms from `body` are evaluated in turn until one returns an exception object,
* or until the list is exhausted. If the list was exhausted, then the value of * or until the list is exhausted. If the list was exhausted, then the value of
@ -158,7 +158,7 @@ struct cons_pointer lisp_try( struct stack_frame *frame,
// TODO: need to put the exception into the environment! // TODO: need to put the exception into the environment!
result = c_progn( frame, frame_pointer, frame->arg[1], result = c_progn( frame, frame_pointer, frame->arg[1],
make_cons( make_cons make_cons( make_cons
( c_string_to_lisp_keyword ( c_string_to_lisp_symbol
( L"*exception*" ), result ), env ) ); ( L"*exception*" ), result ), env ) );
} }
@ -440,10 +440,9 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
result = next_pointer; result = next_pointer;
} else { } else {
result = result =
( *fn_cell.payload. ( *fn_cell.payload.special.
special.executable ) ( get_stack_frame executable ) ( get_stack_frame( next_pointer ),
( next_pointer ), next_pointer, env );
next_pointer, env );
debug_print( L"Special form returning: ", DEBUG_EVAL ); debug_print( L"Special form returning: ", DEBUG_EVAL );
debug_print_object( result, DEBUG_EVAL ); debug_print_object( result, DEBUG_EVAL );
debug_println( DEBUG_EVAL ); debug_println( DEBUG_EVAL );
@ -1238,8 +1237,7 @@ lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer,
struct cons_pointer env ) { struct cons_pointer env ) {
struct cons_pointer message = frame->arg[0]; struct cons_pointer message = frame->arg[0];
return exceptionp( message ) ? message : throw_exception( message, return exceptionp( message ) ? message : throw_exception( message,
frame-> frame->previous );
previous );
} }
/** /**
@ -1406,14 +1404,13 @@ struct cons_pointer c_append( struct cons_pointer l1, struct cons_pointer l2 ) {
if ( pointer2cell( l1 ).tag.value == pointer2cell( l2 ).tag.value ) { if ( pointer2cell( l1 ).tag.value == pointer2cell( l2 ).tag.value ) {
if ( nilp( c_cdr( l1 ) ) ) { if ( nilp( c_cdr( l1 ) ) ) {
return return
make_string_like_thing( ( pointer2cell( l1 ). make_string_like_thing( ( pointer2cell( l1 ).payload.
payload.string.character ), string.character ), l2,
l2,
pointer2cell( l1 ).tag.value ); pointer2cell( l1 ).tag.value );
} else { } else {
return return
make_string_like_thing( ( pointer2cell( l1 ). make_string_like_thing( ( pointer2cell( l1 ).payload.
payload.string.character ), string.character ),
c_append( c_cdr( l1 ), l2 ), c_append( c_cdr( l1 ), l2 ),
pointer2cell( l1 ).tag.value ); pointer2cell( l1 ).tag.value );
} }

View file

@ -219,4 +219,8 @@ struct cons_pointer lisp_list( struct stack_frame *frame,
struct cons_pointer lisp_let( struct stack_frame *frame, struct cons_pointer lisp_let( struct stack_frame *frame,
struct cons_pointer frame_pointer, struct cons_pointer frame_pointer,
struct cons_pointer env ); struct cons_pointer env );
struct cons_pointer lisp_try( struct stack_frame *frame,
struct cons_pointer frame_pointer,
struct cons_pointer env );
#endif #endif

45
unit-tests/try.sh Executable file
View file

@ -0,0 +1,45 @@
#!/bin/bash
expected=':foo'
actual=`echo "(try ((+ 2 (/ 1 'a))) (:foo))" | target/psse | tail -1`
if [ "${expected}" = "${actual}" ]
then
echo "OK"
else
echo "Fail: expected '${expected}', got '${actual}'"
exit 1
fi
expected='4'
actual=`echo "(try ((+ 2 (/ 1 'a))) ((+ 2 2)))" | target/psse | tail -1`
if [ "${expected}" = "${actual}" ]
then
echo "OK"
else
echo "Fail: expected '${expected}', got '${actual}'"
exit 1
fi
expected='8'
actual=`echo "(try (:body (+ 2 (/ 1 'a))) (:catch (* 2 2 2)))" | target/psse | tail -1`
if [ "${expected}" = "${actual}" ]
then
echo "OK"
else
echo "Fail: expected '${expected}', got '${actual}'"
exit 1
fi
expected=''
actual=`echo "(try (:body (+ 2 (/ 1 'a))) (:catch *exception*))" | target/psse | tail -1`
if [ "${expected}" = "${actual}" ]
then
echo "OK"
else
echo "Fail: expected '${expected}', got '${actual}'"
exit 1
fi