--- stack/stack.c 2002/02/08 00:59:34 1.55 +++ stack/stack.c 2002/02/08 16:33:14 1.64 @@ -48,6 +48,7 @@ typedef struct stackitem_struct { value *item; /* The value on the stack */ + /* (This is never NULL) */ struct stackitem_struct *next; /* Next item */ } stackitem; @@ -346,9 +347,6 @@ case list: push_sym(env, "list"); break; - default: - push_sym(env, "unknown"); - break; } } @@ -360,7 +358,7 @@ printf("%d", stack_head->item->content.val); break; case string: - printf("\"%s\"", (char*)stack_head->item->content.ptr); + printf("%s", (char*)stack_head->item->content.ptr); break; case symb: printf("%s", ((symbol *)(stack_head->item->content.ptr))->id); @@ -379,9 +377,6 @@ } printf("]"); break; - default: - printf("#", (stack_head->item->content.ptr)); - break; } } @@ -438,6 +433,23 @@ env->head->next= temp; } +/* Rotate the first three elements on the stack. */ +extern void rot(environment *env) +{ + stackitem *temp= env->head; + + if(env->head==NULL || env->head->next==NULL + || env->head->next->next==NULL) { + printerr("Too Few Arguments"); + env->err=1; + return; + } + + env->head= env->head->next->next; + temp->next->next= env->head->next; + env->head->next= temp; +} + /* Recall a value from a symbol, if bound */ extern void rcl(environment *env) { @@ -484,24 +496,24 @@ return; } + eval_start: + switch(env->head->item->type) { /* if it's a symbol */ case symb: rcl(env); /* get its contents */ if(env->err) return; if(env->head->item->type!=symb){ /* don't recurse symbols */ - eval(env); /* evaluate the value */ - return; + goto eval_start; } - break; + return; /* If it's a lone function value, run it */ case func: in_func= (funcp)(env->head->item->content.ptr); toss(env); if(env->err) return; - (*in_func)(env); - break; + return (*in_func)(env); /* If it's a list */ case list: @@ -510,19 +522,23 @@ toss(env); if(env->err) return; iterator= (stackitem*)temp_val->content.ptr; - while(iterator!=NULL && iterator->item!=NULL) { + while(iterator!=NULL) { push_val(&(env->head), iterator->item); if(env->head->item->type==symb && strcmp(";", ((symbol*)(env->head->item->content.ptr))->id)==0) { toss(env); if(env->err) return; + if(iterator->next == NULL){ + free_val(temp_val); + goto eval_start; + } eval(env); if(env->err) return; } iterator= iterator->next; } free_val(temp_val); - break; + return; /* If it's a string */ case string: @@ -532,17 +548,15 @@ if(env->err) return; temp_string= malloc(strlen((char*)temp_val->content.ptr)+5); strcpy(temp_string, "[ "); - strcat(temp_string, (char*)temp_val->content.ptr); + strcpy(temp_string+2, (char*)temp_val->content.ptr); + free_val(temp_val); strcat(temp_string, " ]"); stack_read(env, temp_string); - eval(env); - if(env->err) return; - free_val(temp_val); free(temp_string); - break; + goto eval_start; case integer: - break; + return; } } @@ -943,10 +957,72 @@ a=env->head->item->content.val; toss(env); if(env->err) return; - b=env->head->item->content.val; + if(env->head->item->refcount == 1) + env->head->item->content.val += a; + else { + b=env->head->item->content.val; + toss(env); + if(env->err) return; + push_int(&(env->head), a+b); + } +} + +/* - */ +extern void sx_2d(environment *env) { + int a, b; + + if((env->head)==NULL || env->head->next==NULL) { + printerr("Too Few Arguments"); + env->err=1; + return; + } + + if(env->head->item->type!=integer + || env->head->next->item->type!=integer) { + printerr("Bad Argument Type"); + env->err=2; + return; + } + a=env->head->item->content.val; + toss(env); + if(env->err) return; + if(env->head->item->refcount == 1) + env->head->item->content.val -= a; + else { + b=env->head->item->content.val; + toss(env); + if(env->err) return; + push_int(&(env->head), b-a); + } +} + +/* > */ +extern void sx_3e(environment *env) { + int a, b; + + if((env->head)==NULL || env->head->next==NULL) { + printerr("Too Few Arguments"); + env->err=1; + return; + } + + if(env->head->item->type!=integer + || env->head->next->item->type!=integer) { + printerr("Bad Argument Type"); + env->err=2; + return; + } + a=env->head->item->content.val; toss(env); if(env->err) return; - push_int(&(env->head), a+b); + if(env->head->item->refcount == 1) + env->head->item->content.val = (env->head->item->content.val > a); + else { + b=env->head->item->content.val; + toss(env); + if(env->err) return; + push_int(&(env->head), b>a); + } } /* Return copy of a value */ @@ -1003,3 +1079,116 @@ } push_val(&(env->head), copy_val(env->head->item)); } + +/* "if", If-Then */ +extern void sx_6966(environment *env) { + + int truth; + + if((env->head)==NULL || env->head->next==NULL) { + printerr("Too Few Arguments"); + env->err=1; + return; + } + + if(env->head->next->item->type != integer) { + printerr("Bad Argument Type"); + env->err=2; + return; + } + + swap(env); + if(env->err) return; + + truth=env->head->item->content.val; + + toss(env); + if(env->err) return; + + if(truth) + eval(env); + else + toss(env); +} + +/* If-Then-Else */ +extern void ifelse(environment *env) { + + int truth; + + if((env->head)==NULL || env->head->next==NULL + || env->head->next->next==NULL) { + printerr("Too Few Arguments"); + env->err=1; + return; + } + + if(env->head->next->next->item->type != integer) { + printerr("Bad Argument Type"); + env->err=2; + return; + } + + rot(env); + if(env->err) return; + + truth=env->head->item->content.val; + + toss(env); + if(env->err) return; + + if(!truth) + swap(env); + if(env->err) return; + + toss(env); + if(env->err) return; + + eval(env); +} + +/* while */ +extern void sx_7768696c65(environment *env) { + + int truth; + value *loop, *test; + + if((env->head)==NULL || env->head->next==NULL) { + printerr("Too Few Arguments"); + env->err=1; + return; + } + + loop= env->head->item; + loop->refcount++; + toss(env); if(env->err) return; + + test= env->head->item; + test->refcount++; + toss(env); if(env->err) return; + + do { + push_val(&(env->head), test); + eval(env); + + if(env->head->item->type != integer) { + printerr("Bad Argument Type"); + env->err=2; + return; + } + + truth= env->head->item->content.val; + toss(env); if(env->err) return; + + if(truth) { + push_val(&(env->head), loop); + eval(env); + } else { + toss(env); + } + + } while(truth); + + free_val(test); + free_val(loop); +}