Reverse
This commit is contained in:
parent
9e5af35aa0
commit
9ff2f14c7d
|
@ -95,6 +95,7 @@ int main( int argc, char *argv[] ) {
|
||||||
bind_function( "oblist", &lisp_oblist );
|
bind_function( "oblist", &lisp_oblist );
|
||||||
bind_function( "print", &lisp_print );
|
bind_function( "print", &lisp_print );
|
||||||
bind_function( "progn", &lisp_progn );
|
bind_function( "progn", &lisp_progn );
|
||||||
|
bind_function( "reverse", &lisp_reverse );
|
||||||
bind_function( "set", &lisp_set );
|
bind_function( "set", &lisp_set );
|
||||||
bind_function( "subtract", &lisp_subtract );
|
bind_function( "subtract", &lisp_subtract );
|
||||||
bind_function( "type", &lisp_type );
|
bind_function( "type", &lisp_type );
|
||||||
|
|
|
@ -234,6 +234,8 @@
|
||||||
*/
|
*/
|
||||||
#define numberp(conspoint) (check_tag(conspoint,INTEGERTAG)||check_tag(conspoint,RATIOTAG)||check_tag(conspoint,REALTAG)||check_tag(conspoint,BIGNUMTAG))
|
#define numberp(conspoint) (check_tag(conspoint,INTEGERTAG)||check_tag(conspoint,RATIOTAG)||check_tag(conspoint,REALTAG)||check_tag(conspoint,BIGNUMTAG))
|
||||||
|
|
||||||
|
#define sequencep(conspoint) (check_tag(conspoint,CONSTAG)||check_tag(conspoint,STRINGTAG)||check_tag(conspoint,SYMBOLTAG))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* true if thr conspointer points to a vector pointer.
|
* true if thr conspointer points to a vector pointer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -169,11 +169,13 @@ lisp_nlambda( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_binding( struct cons_pointer name, struct cons_pointer val ) {
|
void log_binding( struct cons_pointer name, struct cons_pointer val ) {
|
||||||
print( stderr, c_string_to_lisp_string( "\n\tBinding " ) );
|
#ifdef DEBUG
|
||||||
|
fputws( L"\n\tBinding ", stderr );
|
||||||
print( stderr, name );
|
print( stderr, name );
|
||||||
print( stderr, c_string_to_lisp_string( " to " ) );
|
fputws( L" to ", stderr);
|
||||||
print( stderr, val );
|
print( stderr, val );
|
||||||
fputws( L"\"\n", stderr );
|
fputws( L"\"\n", stderr );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,8 +281,10 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
struct cons_pointer exep = NIL;
|
struct cons_pointer exep = NIL;
|
||||||
struct stack_frame *next =
|
struct stack_frame *next =
|
||||||
make_stack_frame( frame, args, env, &exep );
|
make_stack_frame( frame, args, env, &exep );
|
||||||
|
#ifdef DEBUG
|
||||||
fputws( L"Stack frame for lambda\n", stderr );
|
fputws( L"Stack frame for lambda\n", stderr );
|
||||||
dump_frame( stderr, next );
|
dump_frame( stderr, next );
|
||||||
|
#endif
|
||||||
result = eval_lambda( fn_cell, next, env );
|
result = eval_lambda( fn_cell, next, env );
|
||||||
if ( exceptionp( result ) ) {
|
if ( exceptionp( result ) ) {
|
||||||
/* if we're returning an exception, we should NOT free the
|
/* if we're returning an exception, we should NOT free the
|
||||||
|
@ -296,8 +300,10 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
{
|
{
|
||||||
struct stack_frame *next =
|
struct stack_frame *next =
|
||||||
make_special_frame( frame, args, env );
|
make_special_frame( frame, args, env );
|
||||||
|
#ifdef DEBUG
|
||||||
fputws( L"Stack frame for nlambda\n", stderr );
|
fputws( L"Stack frame for nlambda\n", stderr );
|
||||||
dump_frame( stderr, next );
|
dump_frame( stderr, next );
|
||||||
|
#endif
|
||||||
result = eval_lambda( fn_cell, next, env );
|
result = eval_lambda( fn_cell, next, env );
|
||||||
if ( !exceptionp( result ) ) {
|
if ( !exceptionp( result ) ) {
|
||||||
/* if we're returning an exception, we should NOT free the
|
/* if we're returning an exception, we should NOT free the
|
||||||
|
@ -376,8 +382,10 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
struct cons_pointer result = frame->arg[0];
|
struct cons_pointer result = frame->arg[0];
|
||||||
struct cons_space_object cell = pointer2cell( frame->arg[0] );
|
struct cons_space_object cell = pointer2cell( frame->arg[0] );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
fputws( L"Eval: ", stderr );
|
fputws( L"Eval: ", stderr );
|
||||||
dump_frame( stderr, frame );
|
dump_frame( stderr, frame );
|
||||||
|
#endif
|
||||||
|
|
||||||
switch ( cell.tag.value ) {
|
switch ( cell.tag.value ) {
|
||||||
case CONSTV:
|
case CONSTV:
|
||||||
|
@ -415,9 +423,11 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
fputws( L"Eval returning ", stderr );
|
fputws( L"Eval returning ", stderr );
|
||||||
print( stderr, result );
|
print( stderr, result );
|
||||||
fputws( L"\n", stderr );
|
fputws( L"\n", stderr );
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -432,17 +442,20 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
*/
|
*/
|
||||||
struct cons_pointer
|
struct cons_pointer
|
||||||
lisp_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
lisp_apply( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
#ifdef DEBUG
|
||||||
fputws( L"Apply: ", stderr );
|
fputws( L"Apply: ", stderr );
|
||||||
dump_frame( stderr, frame );
|
dump_frame( stderr, frame );
|
||||||
|
#endif
|
||||||
set_reg( frame, 0, make_cons( frame->arg[0], frame->arg[1] ) );
|
set_reg( frame, 0, make_cons( frame->arg[0], frame->arg[1] ) );
|
||||||
set_reg( frame, 1, NIL );
|
set_reg( frame, 1, NIL );
|
||||||
|
|
||||||
struct cons_pointer result = c_apply( frame, env );
|
struct cons_pointer result = c_apply( frame, env );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
fputws( L"Apply returning ", stderr );
|
fputws( L"Apply returning ", stderr );
|
||||||
print( stderr, result );
|
print( stderr, result );
|
||||||
fputws( L"\n", stderr );
|
fputws( L"\n", stderr );
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -641,6 +654,40 @@ lisp_read( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reverse a sequence.
|
||||||
|
*/
|
||||||
|
struct cons_pointer c_reverse( struct cons_pointer arg) {
|
||||||
|
struct cons_pointer result = NIL;
|
||||||
|
|
||||||
|
for (struct cons_pointer p = arg; sequencep(p); p = c_cdr(p)) {
|
||||||
|
struct cons_space_object o = pointer2cell(p);
|
||||||
|
switch (o.tag.value) {
|
||||||
|
case CONSTV:
|
||||||
|
result = make_cons(o.payload.cons.car, result);
|
||||||
|
break;
|
||||||
|
case STRINGTV:
|
||||||
|
result = make_string(o.payload.string.character, result);
|
||||||
|
break;
|
||||||
|
case SYMBOLTV:
|
||||||
|
result = make_symbol(o.payload.string.character, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (reverse sequence)
|
||||||
|
* Return a sequence like this sequence but with the members in the reverse order.
|
||||||
|
*/
|
||||||
|
struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer env ) {
|
||||||
|
return c_reverse( frame->arg[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (print expr)
|
* (print expr)
|
||||||
* (print expr write-stream)
|
* (print expr write-stream)
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct cons_pointer c_car( struct cons_pointer arg );
|
||||||
*/
|
*/
|
||||||
struct cons_pointer c_cdr( struct cons_pointer arg );
|
struct cons_pointer c_cdr( struct cons_pointer arg );
|
||||||
|
|
||||||
|
struct cons_pointer c_reverse( 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
|
||||||
|
@ -117,10 +118,12 @@ struct cons_pointer lisp_eq( struct stack_frame *frame,
|
||||||
struct cons_pointer env );
|
struct cons_pointer env );
|
||||||
struct cons_pointer lisp_equal( struct stack_frame *frame,
|
struct cons_pointer lisp_equal( struct stack_frame *frame,
|
||||||
struct cons_pointer env );
|
struct cons_pointer env );
|
||||||
struct cons_pointer lisp_read( struct stack_frame *frame,
|
|
||||||
struct cons_pointer env );
|
|
||||||
struct cons_pointer lisp_print( struct stack_frame *frame,
|
struct cons_pointer lisp_print( struct stack_frame *frame,
|
||||||
struct cons_pointer env );
|
struct cons_pointer env );
|
||||||
|
struct cons_pointer lisp_read( struct stack_frame *frame,
|
||||||
|
struct cons_pointer env );
|
||||||
|
struct cons_pointer lisp_reverse( struct stack_frame *frame,
|
||||||
|
struct cons_pointer env );
|
||||||
/**
|
/**
|
||||||
* Function: Get the Lisp type of the single argument.
|
* Function: Get the Lisp type of the single argument.
|
||||||
* @param frame My stack frame.
|
* @param frame My stack frame.
|
||||||
|
|
|
@ -148,6 +148,8 @@ struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
|
||||||
initial = fgetwc( input );
|
initial = fgetwc( input );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fwprintf( stderr, L"read_number starting '%c' (%d)\n", initial, initial );
|
fwprintf( stderr, L"read_number starting '%c' (%d)\n", initial, initial );
|
||||||
#endif
|
#endif
|
||||||
|
@ -164,7 +166,7 @@ struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
|
||||||
} else if ( c == btowc( '/' ) ) {
|
} else if ( c == btowc( '/' ) ) {
|
||||||
if ( seen_period || dividend > 0 ) {
|
if ( seen_period || dividend > 0 ) {
|
||||||
return make_exception( c_string_to_lisp_string
|
return make_exception( c_string_to_lisp_string
|
||||||
( "Malformed number: dividend must be integer" ),
|
( "Malformed number: dividend of rational must be integer" ),
|
||||||
frame );
|
frame );
|
||||||
} else {
|
} else {
|
||||||
dividend = negative ? 0 - accumulator : accumulator;
|
dividend = negative ? 0 - accumulator : accumulator;
|
||||||
|
|
|
@ -23,3 +23,57 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
expected='1/4'
|
||||||
|
actual=`echo "(+ 3/14 1/28)" | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (+ integer ratio) should be ratio
|
||||||
|
expected='25/4'
|
||||||
|
actual=`echo "(+ 6 1/4)" | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (+ ratio integer) should be ratio
|
||||||
|
expected='25/4'
|
||||||
|
actual=`echo "(+ 1/4 6)" | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# (+ real ratio) should be real
|
||||||
|
# for this test, trailing zeros can be ignored
|
||||||
|
expected='6.25'
|
||||||
|
actual=`echo "(+ 6.000000001 1/4)" |\
|
||||||
|
target/psse 2> /dev/null |\
|
||||||
|
sed 's/0*$//' |\
|
||||||
|
head -2 |\
|
||||||
|
tail -1`
|
||||||
|
|
||||||
|
outcome=`echo "sqrt((${expected} - ${actual})^2) < 0.0000001" | bc`
|
||||||
|
|
||||||
|
if [ "${outcome}" = "1" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
36
unit-tests/reverse.sh
Normal file
36
unit-tests/reverse.sh
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
expected='"god yzal eht revo depmuj xof nworb kciuq ehT"'
|
||||||
|
actual=`echo '(reverse "The quick brown fox jumped over the lazy dog")' | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
expected='(1024 512 256 128 64 32 16 8 4 2)'
|
||||||
|
actual=`echo "(reverse '(2 4 8 16 32 64 128 256 512 1024))" | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
expected='esrever'
|
||||||
|
actual=`echo "(reverse 'reverse)" | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
Loading…
Reference in a new issue