#include <builtins.h>
#include <ctype.h>
#include <dlfcn.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stem.h>
#include <string.h>
#include <unistd.h>
/* macros taken from stackoverflow */
#define MAX 1000
#define JUSTDO(a) \
if (!(a)) { \
perror(#a); \
exit(1); \
}
extern array_t *STACK;
extern array_t *EVAL_STACK;
extern ht_t *WORD_TABLE;
extern parser_t *PARSER;
extern ht_t *FLIT;
extern ht_t *OBJ_TABLE;
/* TODO: rotr, rotl, dip, map, filter, errstr, join (for strings), switch
* (for quotes), split (split array, string, word into two), del (deleting
* entries from quotes, strings, words) */
/* taken from stackoverflow */
char *get_line(FILE *f) {
int len = MAX;
char buf[MAX], *e = NULL, *ret;
JUSTDO(ret = calloc(MAX, 1));
while (fgets(buf, MAX, f)) {
if (len - strlen(ret) < MAX)
JUSTDO(ret = realloc(ret, len *= 2));
strcat(ret, buf);
if ((e = strrchr(ret, '\n')))
break;
}
if (e)
*e = '\0';
return ret;
}
void print_value(value_t *v) {
custom_t *c;
switch (v->type) {
case VINT:
printf("%.0Lf\n", v->int_float);
break;
case VFLOAT:
printf("%Lf\n", v->int_float);
break;
case VSTR:
printf("%s", v->str_word->value);
break;
case VWORD:
printf("W: %s\n", v->str_word->value);
break;
case VQUOTE:
printf("Q:\n");
for (int i = 0; i < v->quote->size; i++) {
print_value(v->quote->items[i]);
}
break;
case VERR:
printf("STACK ERR\n");
break;
case VCUSTOM:
c = ht_get(OBJ_TABLE, v->str_word);
c->printfunc(v->custom);
break;
}
}
void eval_error() {
value_t *v = init_value(VERR);
array_append(STACK, v);
}
void stemadd(value_t *v) {
value_t *v2 = array_pop(STACK);
if (v2 == NULL) {
eval_error();
return;
}
value_t *v1 = array_pop(STACK);
if (v1 == NULL) {
array_append(STACK, v2);
eval_error();
return;
}
value_t *retval = init_value(VFLOAT);
if (v1->type == VINT && v2->type == VINT) {
retval->type = VINT;
}
if (v1->type != VINT && v1->type != VFLOAT ||
v2->type != VINT && v2->type != VFLOAT) {
array_append(STACK, v1);
array_append(STACK, v2);
eval_error();
return;
}
retval->int_float = v1->int_float + v2->int_float;
array_append(STACK, retval);
value_free(v1);
value_free(v2);
}
void stemsub(value_t *v) {
value_t *v2 = array_pop(STACK);
if (v2 == NULL) {
eval_error();
return;
}
value_t *v1 = array_pop(STACK);
if (v1 == NULL) {
array_append(STACK, v2);
eval_error();
return;
}
value_t *retval = init_value(VFLOAT);
if (v1->type == VINT && v2->type == VINT) {
retval->type = VINT;
}
retval->int_float = v1->int_float - v2->int_float;
array_append(STACK, retval);
value_free(v1);
value_free(v2);
}
void stemmul(value_t *v) {
value_t *v2 = array_pop(STACK);
if (v2 == NULL) {
eval_error();
return;
}
value_t *v1 = array_pop(STACK);
if (v1 == NULL) {
array_append(STACK, v2);
eval_error();
return;
}
value_t *retval = init_value(VFLOAT);
if (v1->type == VINT && v2->type == VINT) {
retval->type = VINT;
}
retval->int_float = v1->int_float * v2->int_float;
array_append(STACK, retval);
value_free(v1);
value_free(v2);
}
void stemdiv(value_t *v) {
value_t *v2 = array_pop(STACK);
if (v2 == NULL) {
eval_error();
return;
}
value_t *v1 = array_pop(STACK);
if (v1 == NULL) {
array_append(STACK, v2);
eval_error();
return;
}
value_t *retval = init_value(VFLOAT);
if (v1->type == VINT && v2->type == VINT) {
retval->type = VINT;
}
retval->int_float = v1->int_float / v2->int_float;
array_append(STACK, retval);
value_free(v1);
value_free(v2);
}
void stemfunc(value_t *v) {
value_t *v2 = array_pop(STACK);
if (v2 == NULL) {
eval_error();
return;
}
value_t *v1 = array_pop(STACK);
if (v1 == NULL) {
array_append(STACK, v2);
eval_error();
return;
}
if (v1->type != VWORD) {
eval_error();
return;
}
ht_add(WORD_TABLE, string_copy(v1->str_word), v2, value_free);
value_free(v1);
}
void nop(value_t *v) {}
void stempow(value_t *v) {
value_t *v2 = array_pop(STACK);
if (v2 == NULL) {
eval_error();
return;
}
value_t *v1 = array_pop(STACK);
if (v1 == NULL) {
array_append(STACK, v2);
eval_error();
return;
}
value_t *retval = init_value
|