| 18 |
enum { |
enum { |
| 19 |
integer, |
integer, |
| 20 |
string, |
string, |
|
ref, /* Reference (to an element in the |
|
|
hash table) */ |
|
| 21 |
func, /* Function pointer */ |
func, /* Function pointer */ |
| 22 |
symb, |
symb, |
| 23 |
list |
list |
| 68 |
{ |
{ |
| 69 |
long i; |
long i; |
| 70 |
|
|
| 71 |
|
env->err=0; |
| 72 |
for(i= 0; i<HASHTBLSIZE; i++) |
for(i= 0; i<HASHTBLSIZE; i++) |
| 73 |
env->symbols[i]= NULL; |
env->symbols[i]= NULL; |
| 74 |
} |
} |
| 103 |
} |
} |
| 104 |
|
|
| 105 |
/* Generic push function. */ |
/* Generic push function. */ |
| 106 |
int push(stackitem** stack_head, stackitem* in_item) |
void push(stackitem** stack_head, stackitem* in_item) |
| 107 |
{ |
{ |
| 108 |
in_item->next= *stack_head; |
in_item->next= *stack_head; |
| 109 |
*stack_head= in_item; |
*stack_head= in_item; |
|
return 1; |
|
| 110 |
} |
} |
| 111 |
|
|
| 112 |
/* Push a value onto the stack */ |
/* Push a value onto the stack */ |
| 119 |
} |
} |
| 120 |
|
|
| 121 |
/* Push an integer onto the stack. */ |
/* Push an integer onto the stack. */ |
| 122 |
int push_int(stackitem **stack_head, int in_val) |
void push_int(stackitem **stack_head, int in_val) |
| 123 |
{ |
{ |
| 124 |
value *new_value= malloc(sizeof(value)); |
value *new_value= malloc(sizeof(value)); |
| 125 |
stackitem *new_item= malloc(sizeof(stackitem)); |
stackitem *new_item= malloc(sizeof(stackitem)); |
| 130 |
new_value->refcount=1; |
new_value->refcount=1; |
| 131 |
|
|
| 132 |
push(stack_head, new_item); |
push(stack_head, new_item); |
|
return 1; |
|
| 133 |
} |
} |
| 134 |
|
|
| 135 |
/* Copy a string onto the stack. */ |
/* Copy a string onto the stack. */ |
| 136 |
int push_cstring(stackitem **stack_head, const char *in_string) |
void push_cstring(stackitem **stack_head, const char *in_string) |
| 137 |
{ |
{ |
| 138 |
value *new_value= malloc(sizeof(value)); |
value *new_value= malloc(sizeof(value)); |
| 139 |
stackitem *new_item= malloc(sizeof(stackitem)); |
stackitem *new_item= malloc(sizeof(stackitem)); |
| 145 |
new_value->refcount=1; |
new_value->refcount=1; |
| 146 |
|
|
| 147 |
push(stack_head, new_item); |
push(stack_head, new_item); |
|
return 1; |
|
| 148 |
} |
} |
| 149 |
|
|
| 150 |
/* Push a symbol onto the stack. */ |
/* Push a symbol onto the stack. */ |
| 151 |
int push_sym(environment *env, const char *in_string) |
void push_sym(environment *env, const char *in_string) |
| 152 |
{ |
{ |
| 153 |
stackitem *new_item; /* The new stack item */ |
stackitem *new_item; /* The new stack item */ |
| 154 |
/* ...which will contain... */ |
/* ...which will contain... */ |
| 203 |
} |
} |
| 204 |
} |
} |
| 205 |
push(&(env->head), new_item); |
push(&(env->head), new_item); |
|
return 1; |
|
| 206 |
} |
} |
| 207 |
|
|
| 208 |
void printerr(const char* in_string) { |
void printerr(const char* in_string) { |
| 241 |
|
|
| 242 |
if((env->head)==NULL) { |
if((env->head)==NULL) { |
| 243 |
printerr("Stack empty"); |
printerr("Stack empty"); |
| 244 |
|
env->err=1; |
| 245 |
return; |
return; |
| 246 |
} |
} |
| 247 |
|
|
| 259 |
/* Prints the top element of the stack. */ |
/* Prints the top element of the stack. */ |
| 260 |
void print_h(stackitem *stack_head) |
void print_h(stackitem *stack_head) |
| 261 |
{ |
{ |
|
|
|
|
if(stack_head==NULL) { |
|
|
printerr("Stack empty"); |
|
|
return; |
|
|
} |
|
|
|
|
| 262 |
switch(stack_head->item->type) { |
switch(stack_head->item->type) { |
| 263 |
case integer: |
case integer: |
| 264 |
printf("%d", stack_head->item->content.val); |
printf("%d", stack_head->item->content.val); |
| 269 |
case symb: |
case symb: |
| 270 |
printf("'%s'", ((symbol *)(stack_head->item->content.ptr))->id); |
printf("'%s'", ((symbol *)(stack_head->item->content.ptr))->id); |
| 271 |
break; |
break; |
| 272 |
|
case func: |
| 273 |
|
printf("#<function %p>", (funcp)(stack_head->item->content.ptr)); |
| 274 |
|
break; |
| 275 |
|
case list: |
| 276 |
|
printf("#<list %p>", (funcp)(stack_head->item->content.ptr)); |
| 277 |
|
break; |
| 278 |
default: |
default: |
| 279 |
printf("%p", (funcp)(stack_head->item->content.ptr)); |
printf("#<unknown %p>", (funcp)(stack_head->item->content.ptr)); |
| 280 |
break; |
break; |
| 281 |
} |
} |
| 282 |
} |
} |
| 283 |
|
|
| 284 |
extern void print_(environment *env) { |
extern void print_(environment *env) { |
| 285 |
|
if(env->head==NULL) { |
| 286 |
|
printerr("Stack empty"); |
| 287 |
|
env->err=1; |
| 288 |
|
return; |
| 289 |
|
} |
| 290 |
print_h(env->head); |
print_h(env->head); |
| 291 |
} |
} |
| 292 |
|
|
| 294 |
extern void print(environment *env) |
extern void print(environment *env) |
| 295 |
{ |
{ |
| 296 |
print_(env); |
print_(env); |
| 297 |
|
if(env->err) return; |
| 298 |
toss(env); |
toss(env); |
| 299 |
} |
} |
| 300 |
|
|
| 313 |
/* Prints the stack. */ |
/* Prints the stack. */ |
| 314 |
extern void printstack(environment *env) |
extern void printstack(environment *env) |
| 315 |
{ |
{ |
| 316 |
if(env->head != NULL) { |
if(env->head == NULL) { |
|
print_st(env->head, 1); |
|
|
nl(); |
|
|
} else { |
|
| 317 |
printerr("Stack empty"); |
printerr("Stack empty"); |
| 318 |
|
env->err=1; |
| 319 |
|
return; |
| 320 |
} |
} |
| 321 |
|
print_st(env->head, 1); |
| 322 |
|
nl(); |
| 323 |
} |
} |
| 324 |
|
|
| 325 |
/* Swap the two top elements on the stack. */ |
/* Swap the two top elements on the stack. */ |
| 329 |
|
|
| 330 |
if((env->head)==NULL) { |
if((env->head)==NULL) { |
| 331 |
printerr("Stack empty"); |
printerr("Stack empty"); |
| 332 |
|
env->err=1; |
| 333 |
return; |
return; |
| 334 |
} |
} |
| 335 |
|
|
| 336 |
if(env->head->next==NULL) { |
if(env->head->next==NULL) { |
| 337 |
printerr("Not enough arguments"); |
printerr("Not enough arguments"); |
| 338 |
|
env->err=1; |
| 339 |
return; |
return; |
| 340 |
} |
} |
| 341 |
|
|
| 361 |
|
|
| 362 |
if(env->head == NULL) { |
if(env->head == NULL) { |
| 363 |
printerr("Stack empty"); |
printerr("Stack empty"); |
| 364 |
|
env->err=1; |
| 365 |
return; |
return; |
| 366 |
} |
} |
| 367 |
|
|
| 368 |
if(env->head->item->type!=symb) { |
if(env->head->item->type!=symb) { |
| 369 |
printerr("Not a symbol"); |
printerr("Not a symbol"); |
| 370 |
|
env->err=1; |
| 371 |
return; |
return; |
| 372 |
} |
} |
| 373 |
|
|
| 374 |
val=((symbol *)(env->head->item->content.ptr))->val; |
val=((symbol *)(env->head->item->content.ptr))->val; |
| 375 |
if(val == NULL){ |
if(val == NULL){ |
| 376 |
printerr("Unbound variable"); |
printerr("Unbound variable"); |
| 377 |
|
env->err=1; |
| 378 |
return; |
return; |
| 379 |
} |
} |
| 380 |
toss(env); /* toss the symbol */ |
toss(env); /* toss the symbol */ |
| 381 |
|
if(env->err) return; |
| 382 |
push_val(&(env->head), val); /* Return its bound value */ |
push_val(&(env->head), val); /* Return its bound value */ |
| 383 |
} |
} |
| 384 |
|
|
| 388 |
extern void eval(environment *env) |
extern void eval(environment *env) |
| 389 |
{ |
{ |
| 390 |
funcp in_func; |
funcp in_func; |
|
value* val; |
|
| 391 |
if(env->head==NULL) { |
if(env->head==NULL) { |
| 392 |
printerr("Stack empty"); |
printerr("Stack empty"); |
| 393 |
|
env->err=1; |
| 394 |
return; |
return; |
| 395 |
} |
} |
| 396 |
|
|
| 397 |
/* if it's a symbol */ |
/* if it's a symbol */ |
| 398 |
if(env->head->item->type==symb) { |
if(env->head->item->type==symb) { |
| 399 |
|
|
| 400 |
/* If it's not bound to anything */ |
rcl(env); /* get its contents */ |
| 401 |
if (((symbol *)(env->head->item->content.ptr))->val == NULL) { |
if(env->err) return; |
| 402 |
printerr("Unbound variable"); |
if(env->head->item->type!=symb){ /* don't recurse symbols */ |
| 403 |
|
eval(env); /* evaluate the value */ |
| 404 |
return; |
return; |
| 405 |
} |
} |
|
|
|
|
/* If it contains a function */ |
|
|
if (((symbol *)(env->head->item->content.ptr))->val->type == func) { |
|
|
in_func= |
|
|
(funcp)(((symbol *)(env->head->item->content.ptr))->val->content.ptr); |
|
|
toss(env); |
|
|
(*in_func)(env); /* Run the function */ |
|
|
return; |
|
|
} else { /* If it's not a function */ |
|
|
val=((symbol *)(env->head->item->content.ptr))->val; |
|
|
toss(env); /* toss the symbol */ |
|
|
push_val(&(env->head), val); /* Return its bound value */ |
|
|
} |
|
| 406 |
} |
} |
| 407 |
|
|
| 408 |
/* If it's a lone function value, run it */ |
/* If it's a lone function value, run it */ |
| 409 |
if(env->head->item->type==func) { |
if(env->head->item->type==func) { |
| 410 |
in_func= (funcp)(env->head->item->content.ptr); |
in_func= (funcp)(env->head->item->content.ptr); |
| 411 |
toss(env); |
toss(env); |
| 412 |
|
if(env->err) return; |
| 413 |
(*in_func)(env); |
(*in_func)(env); |
|
return; |
|
| 414 |
} |
} |
|
|
|
| 415 |
} |
} |
| 416 |
|
|
| 417 |
/* Make a list. */ |
/* Make a list. */ |
| 540 |
/* Is top element a list? */ |
/* Is top element a list? */ |
| 541 |
if(env->head==NULL || env->head->item->type!=list) { |
if(env->head==NULL || env->head->item->type!=list) { |
| 542 |
printerr("Stack empty or not a list"); |
printerr("Stack empty or not a list"); |
| 543 |
|
env->err=1; |
| 544 |
return; |
return; |
| 545 |
} |
} |
| 546 |
|
|
| 568 |
|
|
| 569 |
if((env->head)==NULL || env->head->next==NULL) { |
if((env->head)==NULL || env->head->next==NULL) { |
| 570 |
printerr("Not enough elements to compare"); |
printerr("Not enough elements to compare"); |
| 571 |
|
env->err=1; |
| 572 |
return; |
return; |
| 573 |
} |
} |
| 574 |
|
|
| 588 |
|
|
| 589 |
if((env->head)==NULL || env->head->item->type!=integer) { |
if((env->head)==NULL || env->head->item->type!=integer) { |
| 590 |
printerr("Stack empty or element is not a integer"); |
printerr("Stack empty or element is not a integer"); |
| 591 |
|
env->err=1; |
| 592 |
return; |
return; |
| 593 |
} |
} |
| 594 |
|
|
| 614 |
if(env->head==NULL || env->head->next==NULL |
if(env->head==NULL || env->head->next==NULL |
| 615 |
|| env->head->item->type!=symb) { |
|| env->head->item->type!=symb) { |
| 616 |
printerr("Define what?"); |
printerr("Define what?"); |
| 617 |
|
env->err=1; |
| 618 |
return; |
return; |
| 619 |
} |
} |
| 620 |
|
|
| 697 |
|
|
| 698 |
while(fgets(in_string, 100, stdin) != NULL) { |
while(fgets(in_string, 100, stdin) != NULL) { |
| 699 |
stack_read(&myenv, in_string); |
stack_read(&myenv, in_string); |
| 700 |
|
if(myenv.err) { |
| 701 |
|
printf("(error %d) ", myenv.err); |
| 702 |
|
myenv.err=0; |
| 703 |
|
} |
| 704 |
printf("okidok\n "); |
printf("okidok\n "); |
| 705 |
} |
} |
| 706 |
|
|