Add and multiply now work, but robustly.

This commit is contained in:
Simon Brooke 2017-09-13 17:00:13 +01:00
parent 0826dcfdda
commit 648a4cd522
3 changed files with 58 additions and 3 deletions

View file

@ -88,7 +88,8 @@ int main( int argc, char *argv[] ) {
bind_function( "read", &lisp_read );
bind_function( "print", &lisp_print );
bind_function( "plus", &lisp_plus);
bind_function( "add", &lisp_add);
bind_function( "multiply", &lisp_multiply);
/*
* primitive special forms

View file

@ -32,7 +32,7 @@
* @return a pointer to an integer or real.
*/
struct cons_pointer
lisp_plus(struct stack_frame *frame, struct cons_pointer env) {
lisp_add(struct stack_frame *frame, struct cons_pointer env) {
struct cons_pointer result = NIL;
long int i_accumulator = 0;
long double d_accumulator = 0;
@ -71,3 +71,49 @@ lisp_plus(struct stack_frame *frame, struct cons_pointer env) {
return result;
}
/**
* Multiply an indefinite number of numbers together
* @param env the evaluation environment - ignored;
* @param frame the stack frame.
* @return a pointer to an integer or real.
*/
struct cons_pointer
lisp_multiply(struct stack_frame *frame, struct cons_pointer env) {
struct cons_pointer result = NIL;
long int i_accumulator = 1;
long double d_accumulator = 1;
bool is_int = true;
for (int i = 0; i < args_in_frame && !nilp(frame->arg[i]); i++) {
struct cons_space_object arg = pointer2cell(frame->arg[i]);
switch (arg.tag.value) {
case INTEGERTV:
i_accumulator *= arg.payload.integer.value;
d_accumulator *= numeric_value( frame->arg[i]);
break;
case REALTV:
d_accumulator *= arg.payload.real.value;
is_int = false;
default:
lisp_throw(
c_string_to_lisp_string("Cannot multiply: not a number"),
frame);
}
if (! nilp(frame->more)) {
lisp_throw(
c_string_to_lisp_string("Cannot yet multiply more than 8 numbers"),
frame);
}
if ( is_int) {
result = make_integer( i_accumulator);
} else {
result = make_real( d_accumulator);
}
}
return result;
}

View file

@ -23,8 +23,16 @@ extern "C" {
* @return a pointer to an integer or real.
*/
struct cons_pointer
lisp_plus(struct stack_frame *frame, struct cons_pointer env);
lisp_add(struct stack_frame *frame, struct cons_pointer env);
/**
* Multiply an indefinite number of numbers together
* @param env the evaluation environment - ignored;
* @param frame the stack frame.
* @return a pointer to an integer or real.
*/
struct cons_pointer
lisp_multiply(struct stack_frame *frame, struct cons_pointer env);
#ifdef __cplusplus