From dfe729c98b63d0f6c0041799a0fb46b2f476502e Mon Sep 17 00:00:00 2001 From: Preston Pan Date: Mon, 8 Jan 2024 18:31:56 -0800 Subject: allow for future FLI system --- builtins.c | 1086 ++++++++++++++++++++++++++++++++++++++++++++++++++ builtins.h | 53 +++ examples/aoc1.stem | 9 + examples/repl.stem | 2 + examples/simple.stem | 1 + main.c | 14 +- parser.c | 1037 ++++------------------------------------------- parser.h | 27 +- 8 files changed, 1248 insertions(+), 981 deletions(-) create mode 100644 builtins.c create mode 100644 builtins.h create mode 100644 examples/simple.stem diff --git a/builtins.c b/builtins.c new file mode 100644 index 0000000..011b263 --- /dev/null +++ b/builtins.c @@ -0,0 +1,1086 @@ +#include "builtins.h" +#include "parser.h" +#include +#include +#include +#include +#include + +#define MAX 50 +#define JUSTDO(a) \ + if (!(a)) { \ + perror(#a); \ + exit(1); \ + } + +extern array_t *STACK; +extern array_t *EVAL_STACK; +extern ht_t *WORD_TABLE; +extern char *INBUF; +extern parser_t *PARSER; + +extern ht_t *FLIT; +extern ht_t *OBJ_FREE_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) */ + +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) { + 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: + printf("CUSTOM VALUE\n"); + 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(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(VFLOAT); + if (v1->type == VINT && v2->type == VINT) { + retval->type = VINT; + } + retval->int_float = powl(v1->int_float, v2->int_float); + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} + +void stemsin(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + value_t *retval = init_value(VFLOAT); + retval->int_float = sinhl(v1->int_float); + array_append(STACK, retval); + value_free(v1); +} + +void stemcos(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + value_t *retval = init_value(VFLOAT); + retval->int_float = coshl(v1->int_float); + array_append(STACK, retval); + value_free(v1); +} + +void stemexp(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + value_t *retval = init_value(VFLOAT); + retval->int_float = expl(v1->int_float); + array_append(STACK, retval); + value_free(v1); +} + +void stemeval(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + array_append(STACK, v1); + eval_error(); + return; + } + if (v1->type == VQUOTE) { + array_append(EVAL_STACK, v1); + for (int i = 0; i < v1->quote->size; i++) { + eval(value_copy(v1->quote->items[i])); + } + value_t *vf = array_pop(EVAL_STACK); + if (vf) { + value_free(vf); + } + } else { + eval(v1); + } +} + +void stemln(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + value_t *retval = init_value(VFLOAT); + retval->int_float = logl(v1->int_float); + array_append(STACK, retval); + value_free(v1); +} +void stemceil(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + value_t *retval = init_value(VFLOAT); + retval->int_float = ceil(v1->int_float); + array_append(STACK, retval); + value_free(v1); +} +void stemfloor(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + value_t *retval = init_value(VFLOAT); + retval->int_float = floor(v1->int_float); + array_append(STACK, retval); + value_free(v1); +} + +void strquote(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + if (v1->type != VSTR) { + array_append(STACK, v1); + eval_error(); + return; + } + value_t *retval = init_value(VQUOTE); + retval->quote = init_array(10); + char *s = malloc(strlen(v1->str_word->value) + 1); + strcpy(s, v1->str_word->value); + parser_t *p = init_parser(s); + value_t *cur; + while (1) { + cur = parser_get_next(p); + if (cur == NULL) + break; + array_append(retval->quote, cur); + } + array_append(STACK, retval); + value_free(v1); + free(p->source); + free(p); +} + +void curry(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 (v2->type != VQUOTE) { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + + array_append(v2->quote, v1); + array_append(STACK, v2); +} +void stemfread(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + if (v1->type != VSTR) { + array_append(STACK, v1); + eval_error(); + return; + } + char *val = NULL; + size_t len; + FILE *fp = fopen(v1->str_word->value, "rb"); + if (!fp) { + array_append(STACK, v1); + eval_error(); + return; + } + ssize_t bytes_read = getdelim(&val, &len, '\0', fp); + fclose(fp); + value_t *retval = init_value(VSTR); + retval->str_word = init_string(val); + array_append(STACK, retval); + value_free(v1); + free(val); +} +void stemread(value_t *v) { + value_t *retval = init_value(VSTR); + char *a = get_line(stdin); + retval->str_word = init_string(a); + array_append(STACK, retval); + free(a); +} + +void stemexit(value_t *v) { + ht_free(WORD_TABLE, value_free); + ht_free(FLIT, func_free); + array_free(STACK); + free(INBUF); + free(PARSER); + array_free(EVAL_STACK); + ht_free(OBJ_FREE_TABLE, func_free); + exit(0); +} + +void quote(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = init_value(VQUOTE); + retval->quote = init_array(10); + array_append(retval->quote, v1); + array_append(STACK, retval); +} +void stemtype(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = init_value(VINT); + retval->int_float = v1->type; + array_append(STACK, v1); + array_append(STACK, retval); +} + +void dsc(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_free(v1); +} +void swap(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; + } + array_append(STACK, v2); + array_append(STACK, v1); +} + +void isdef(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = init_value(VINT); + if (v1->type != VWORD) { + retval->int_float = 0; + } else { + retval->int_float = ht_exists(WORD_TABLE, v1->str_word); + } + array_append(STACK, v1); + array_append(STACK, retval); +} + +void stemdup(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = value_copy(v1); + array_append(STACK, v1); + array_append(STACK, retval); +} + +void questionmark(value_t *v) { + for (int i = 0; i < STACK->size; i++) { + print_value(STACK->items[i]); + } +} + +void period(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + print_value(v1); + value_free(v1); +} +void stemlen(value_t *v) { + + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = init_value(VINT); + if (v1->type == VINT || v1->type == VFLOAT) { + retval->int_float = 1; + } else if (v1->type == VSTR || v1->type == VWORD) { + retval->int_float = strlen(v1->str_word->value); + } else if (v1->type == VQUOTE) { + retval->int_float = v1->quote->size; + } + array_append(STACK, v1); + array_append(STACK, retval); +} + +void dip(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 (v2->type == VQUOTE) { + array_append(EVAL_STACK, v1); + array_append(EVAL_STACK, v2); + for (int i = 0; i < v2->quote->size; i++) { + eval(value_copy(v2->quote->items[i])); + } + value_free(array_pop(EVAL_STACK)); + value_free(array_pop(EVAL_STACK)); + } else { + eval(v1); + } + array_append(STACK, v1); +} + +void keep(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; + } + + array_append(STACK, value_copy(v1)); + if (v2->type == VQUOTE) { + array_append(EVAL_STACK, v2); + for (int i = 0; i < v2->quote->size; i++) { + eval(value_copy(v2->quote->items[i])); + } + value_free(array_pop(EVAL_STACK)); + } else { + eval(v1); + } + array_append(STACK, v1); +} + +void del(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 (v2->type != VINT) { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + switch (v1->type) { + case VQUOTE: + break; + case VSTR: + break; + case VWORD: + break; + default: + value_free(v1); + break; + } +} + +void clear(value_t *v) { + for (int i = 0; i < STACK->size; i++) { + value_free(array_pop(STACK)); + } +} + +void stemif(value_t *v) { + value_t *v3 = array_pop(STACK); + if (v3 == NULL) { + eval_error(); + return; + } + value_t *v2 = array_pop(STACK); + if (v2 == NULL) { + array_append(STACK, v3); + eval_error(); + return; + } + + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + array_append(STACK, v2); + array_append(STACK, v3); + eval_error(); + return; + } + + if (v1->type != VINT) { + array_append(STACK, v1); + array_append(STACK, v2); + array_append(STACK, v3); + eval_error(); + return; + } + + if (v1->int_float) { + value_free(v3); + value_free(v1); + if (v2->type == VQUOTE) { + + array_append(EVAL_STACK, v2); + for (int i = 0; i < v2->quote->size; i++) { + eval(value_copy(v2->quote->items[i])); + } + value_t *vf = array_pop(EVAL_STACK); + if (vf) { + value_free(vf); + } + } else { + eval(v2); + } + } else { + value_free(v2); + value_free(v1); + if (v3->type == VQUOTE) { + array_append(EVAL_STACK, v3); + for (int i = 0; i < v3->quote->size; i++) { + eval(value_copy(v3->quote->items[i])); + } + value_t *vf = array_pop(EVAL_STACK); + if (vf) { + value_free(vf); + } + } else { + eval(v3); + } + } +} +void gtequals(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(VINT); + if (v1->type == VSTR && v2->type == VSTR || + v1->type == VWORD && v2->type == VWORD) { + retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) <= 0; + } else if ((v1->type == VINT || v1->type == VFLOAT) && + (v2->type == VINT || v2->type == VFLOAT)) { + retval->int_float = v1->int_float >= v2->int_float; + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} +void ltequals(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(VINT); + if (v1->type == VSTR && v2->type == VSTR || + v1->type == VWORD && v2->type == VWORD) { + retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) <= 0; + } else if ((v1->type == VINT || v1->type == VFLOAT) && + (v2->type == VINT || v2->type == VFLOAT)) { + retval->int_float = v1->int_float <= v2->int_float; + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} + +void gthan(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(VINT); + if (v1->type == VSTR && v2->type == VSTR || + v1->type == VWORD && v2->type == VWORD) { + retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) > 0; + } else if ((v1->type == VINT || v1->type == VFLOAT) && + (v2->type == VINT || v2->type == VFLOAT)) { + retval->int_float = v1->int_float > v2->int_float; + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} + +void lthan(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(VINT); + if (v1->type == VSTR && v2->type == VSTR || + v1->type == VWORD && v2->type == VWORD) { + retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) < 0; + } else if ((v1->type == VINT || v1->type == VFLOAT) && + (v2->type == VINT || v2->type == VFLOAT)) { + retval->int_float = v1->int_float < v2->int_float; + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} + +void equals(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(VINT); + if (v1->type == VSTR && v2->type == VSTR || + v1->type == VWORD && v2->type == VWORD) { + retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) == 0; + } else if ((v1->type == VINT || v1->type == VFLOAT) && + (v2->type == VINT || v2->type == VFLOAT)) { + retval->int_float = v1->int_float == v2->int_float; + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} +void nequals(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(VINT); + if (v1->type == VSTR && v2->type == VSTR || + v1->type == VWORD && v2->type == VWORD) { + retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) != 0; + } else if ((v1->type == VINT || v1->type == VFLOAT) && + (v2->type == VINT || v2->type == VFLOAT)) { + retval->int_float = v1->int_float != v2->int_float; + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); + value_free(v1); + value_free(v2); +} + +void wtostr(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + if (v1->type != VWORD) { + array_append(STACK, v1); + eval_error(); + return; + } + v1->type = VSTR; + array_append(STACK, v1); +} + +void compose(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; + if (v2->type == VSTR && v1->type == VSTR) { + retval = init_value(VSTR); + string_concat(v1->str_word, v2->str_word); + retval->str_word = string_copy(v1->str_word); + value_free(v1); + value_free(v2); + } else if (v2->type == VWORD && v1->type == VWORD) { + retval = init_value(VWORD); + string_concat(v1->str_word, v2->str_word); + retval->str_word = string_copy(v1->str_word); + value_free(v1); + value_free(v2); + } else if (v2->type == VQUOTE && v1->type == VQUOTE) { + retval = v1; + array_extend(v1->quote, v2->quote); + free(v2->quote); + free(v2); + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, retval); +} + +void isnum(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = init_value(VINT); + + bool isnum = true; + for (int i = 0; i < v1->str_word->length; i++) { + if (isspace(v1->str_word->value[i])) { + continue; + } else if (!isdigit(v1->str_word->value[i])) { + isnum = false; + break; + } + } + retval->int_float = isnum; + + array_append(STACK, v1); + array_append(STACK, retval); +} + +void stoi(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + + value_t *retval = init_value(VINT); + retval->int_float = atoi(v1->str_word->value); + array_append(STACK, retval); + value_free(v1); +} + +void ssize(value_t *v) { + value_t *retval = init_value(VINT); + retval->int_float = STACK->size; + array_append(STACK, retval); +} +void qstack(value_t *v) { + value_t *retval = init_value(VQUOTE); + retval->quote = array_copy(STACK); + array_append(STACK, retval); +} + +void vat(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 != VINT) { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + if (v2->type == VQUOTE) { + if (v2->quote->size <= v1->int_float) { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + array_append(STACK, v2); + array_append(STACK, value_copy(v2->quote->items[(int)v1->int_float])); + value_free(v1); + } else if (v2->type == VSTR) { + if (v2->str_word->length <= v1->int_float) { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } + char *a = (char[]){v2->str_word->value[(int)v1->int_float], '\0'}; + string_t *s = init_string(a); + value_t *retval = init_value(VINT); + retval->str_word = s; + array_append(STACK, v2); + array_append(STACK, retval); + value_free(v1); + } else { + array_append(STACK, v1); + array_append(STACK, v2); + eval_error(); + return; + } +} + +void stemfwrite(value_t *v) { + value_t *v1 = array_pop(STACK); + if (v1 == NULL) { + eval_error(); + return; + } + if (v1->type != VSTR) { + array_append(STACK, v1); + eval_error(); + return; + } + char *val; + size_t len; + FILE *fp = fopen(v1->str_word->value, "w+"); + if (!fp) { + array_append(STACK, v1); + eval_error(); + return; + } + fprintf(fp, "%s", v1->str_word->value); + value_free(v1); + fclose(fp); +} + +void add_func(ht_t *h, void (*func)(value_t *), char *key) { + string_t *s = init_string(key); + ht_add(h, s, func); +} + +void add_funcs() { + add_func(FLIT, period, "."); + add_func(FLIT, questionmark, "?"); + add_func(FLIT, stemadd, "+"); + add_func(FLIT, stemsub, "-"); + add_func(FLIT, stemdiv, "/"); + add_func(FLIT, stemmul, "*"); + add_func(FLIT, stempow, "pow"); + add_func(FLIT, stemsin, "sin"); + add_func(FLIT, stemcos, "cos"); + add_func(FLIT, stemexp, "exp"); + add_func(FLIT, strquote, "strquote"); + add_func(FLIT, stemeval, "eval"); + add_func(FLIT, stemfunc, "func"); + add_func(FLIT, nop, "nop"); + add_func(FLIT, stemln, "ln"); + add_func(FLIT, stemfloor, "floor"); + add_func(FLIT, stemceil, "ceil"); + add_func(FLIT, stemfread, "fread"); + add_func(FLIT, stemread, "read"); + add_func(FLIT, vat, "vat"); + add_func(FLIT, qstack, "qstack"); + add_func(FLIT, ssize, "ssize"); + add_func(FLIT, stoi, "stoi"); + add_func(FLIT, isnum, "isnum"); + add_func(FLIT, compose, "compose"); + add_func(FLIT, stemfwrite, "wtostr"); + add_func(FLIT, lthan, "<"); + add_func(FLIT, ltequals, "<="); + add_func(FLIT, gthan, ">"); + add_func(FLIT, gtequals, ">="); + add_func(FLIT, nequals, "!="); + add_func(FLIT, equals, "="); + add_func(FLIT, stemif, "if"); + add_func(FLIT, clear, "clear"); + add_func(FLIT, keep, "keep"); + add_func(FLIT, dip, "dip"); + add_func(FLIT, stemlen, "len"); + add_func(FLIT, quote, "quote"); + add_func(FLIT, stemexit, "exit"); + add_func(FLIT, stemtype, "type"); + add_func(FLIT, stemdup, "dup"); + add_func(FLIT, curry, "curry"); + add_func(FLIT, swap, "swap"); + add_func(FLIT, isdef, "isdef"); + add_func(FLIT, dsc, "dsc"); +} diff --git a/builtins.h b/builtins.h new file mode 100644 index 0000000..a32125d --- /dev/null +++ b/builtins.h @@ -0,0 +1,53 @@ +#ifndef BUILTINS_H_ +#define BUILTINS_H_ +#include "./parser.h" +void stemadd(value_t *v); +void stemsub(value_t *v); +void stemmul(value_t *v); +void stemdiv(value_t *v); +void stemfunc(value_t *v); +void stempow(value_t *v); +void stemsin(value_t *v); +void stemcos(value_t *v); +void stemexp(value_t *v); +void stemeval(value_t *v); +void stemln(value_t *v); +void stemceil(value_t *v); +void stemfloor(value_t *v); +void strquote(value_t *v); +void curry(value_t *v); +void nop(value_t *v); +void stemfread(value_t *v); +void stemread(value_t *v); +void stemexit(value_t *v); +void quote(value_t *v); +void stemtype(value_t *v); +void dsc(value_t *v); +void swap(value_t *v); +void isdef(value_t *v); +void stemdup(value_t *v); +void questionmark(value_t *v); +void period(value_t *v); +void stemlen(value_t *v); +void dip(value_t *v); +void keep(value_t *v); +void del(value_t *v); +void clear(value_t *v); +void stemif(value_t *v); +void gtequals(value_t *v); +void ltequals(value_t *v); +void gthan(value_t *v); +void lthan(value_t *v); +void equals(value_t *v); +void nequals(value_t *v); +void wtostr(value_t *v); +void compose(value_t *v); +void isnum(value_t *v); +void stoi(value_t *v); +void ssize(value_t *v); +void qstack(value_t *v); +void vat(value_t *v); +void stemfwrite(value_t *v); + +void add_funcs(); +#endif // BUILTINS_H_ diff --git a/examples/aoc1.stem b/examples/aoc1.stem index e69de29..16f739d 100644 --- a/examples/aoc1.stem +++ b/examples/aoc1.stem @@ -0,0 +1,9 @@ + +dsc +swap +isnum +char +0 +str + +read_str [ ] diff --git a/examples/repl.stem b/examples/repl.stem index 1468835..6ed6795 100644 --- a/examples/repl.stem +++ b/examples/repl.stem @@ -1,4 +1,6 @@ "./stdlib.stem" fread strquote eval "./math.stem" include +"You can make your own REPL by changing the code!" dsc + repl [ "> " . read strquote eval repl ] func repl diff --git a/examples/simple.stem b/examples/simple.stem new file mode 100644 index 0000000..5853c3f --- /dev/null +++ b/examples/simple.stem @@ -0,0 +1 @@ +3 4 + . diff --git a/main.c b/main.c index afa2e65..68e093e 100644 --- a/main.c +++ b/main.c @@ -1,14 +1,17 @@ +#include "builtins.h" #include "parser.h" #include #include #include #include - extern ht_t *WORD_TABLE; + extern array_t *STACK; extern char *INBUF; extern parser_t *PARSER; extern array_t *EVAL_STACK; +extern ht_t *OBJ_FREE_TABLE; +extern ht_t *FLIT; void usage() { printf("Usage: stem [-hv] [file]\n"); @@ -51,6 +54,11 @@ int main(int argc, char **argv) { STACK = init_array(10); WORD_TABLE = init_ht(500); EVAL_STACK = init_array(10); + FLIT = init_ht(500); + OBJ_FREE_TABLE = init_ht(500); + + add_funcs(); + while (1) { v = parser_get_next(PARSER); if (v == NULL) @@ -59,7 +67,9 @@ int main(int argc, char **argv) { } free(INBUF); - ht_free(WORD_TABLE); + ht_free(WORD_TABLE, value_free); + ht_free(FLIT, func_free); + ht_free(OBJ_FREE_TABLE, func_free); array_free(STACK); free(PARSER); array_free(EVAL_STACK); diff --git a/parser.c b/parser.c index 1bbf793..4ee06e2 100644 --- a/parser.c +++ b/parser.c @@ -7,19 +7,17 @@ #include #include -#define MAX 50 -#define JUSTDO(a) \ - if (!(a)) { \ - perror(#a); \ - exit(1); \ - } - array_t *STACK; array_t *EVAL_STACK; ht_t *WORD_TABLE; char *INBUF; parser_t *PARSER; +ht_t *FLIT; +ht_t *OBJ_FREE_TABLE; + +void func_free(void *f) {} + array_t *init_array(size_t size) { array_t *a = calloc(1, sizeof(array_t)); a->size = 0; @@ -92,13 +90,18 @@ value_t *value_copy(value_t *v) { return a; } -void value_free(value_t *v) { +void value_free(void *vtmp) { + value_t *v = (value_t *)vtmp; if (v->type == VSTR || v->type == VWORD) { string_free(v->str_word); } if (v->type == VQUOTE) { array_free(v->quote); } + if (v->type == VCUSTOM) { + void (*freefunc)(void *) = ht_get(FLIT, v->str_word); + freefunc(v->custom); + } free(v); } @@ -243,7 +246,7 @@ value_t *parser_get_next(parser_t *p) { } } -node_t *init_node(string_t *key, value_t *value) { +node_t *init_node(string_t *key, void *value) { node_t *n = calloc(1, sizeof(node_t)); n->key = key; n->value = value; @@ -251,9 +254,9 @@ node_t *init_node(string_t *key, value_t *value) { return n; } -void node_free(node_t *n) { +void node_free(node_t *n, void (*freefunc)(void *)) { string_free(n->key); - value_free(n->value); + freefunc(n->value); free(n); } @@ -264,7 +267,7 @@ sll_t *init_sll() { return l; } -void sll_add(sll_t *l, string_t *s, value_t *v) { +void sll_add(sll_t *l, string_t *s, void *v) { if (l->head == NULL) { node_t *n = init_node(s, v); l->head = n; @@ -273,7 +276,7 @@ void sll_add(sll_t *l, string_t *s, value_t *v) { } node_t *cur = l->head; while (cur->next != NULL) { - if (strcmp(s->value, cur->value->str_word->value) == 0) { + if (strcmp(s->value, cur->key->value) == 0) { value_free(cur->value); string_free(s); cur->value = v; @@ -281,7 +284,7 @@ void sll_add(sll_t *l, string_t *s, value_t *v) { } cur = cur->next; } - if (strcmp(s->value, cur->value->str_word->value) == 0) { + if (strcmp(s->value, cur->key->value) == 0) { value_free(cur->value); string_free(s); cur->value = v; @@ -291,7 +294,32 @@ void sll_add(sll_t *l, string_t *s, value_t *v) { cur->next = n; } -value_t *sll_get(sll_t *l, string_t *k) { +void sll_add_func(sll_t *l, string_t *s, void *v) { + if (l->head == NULL) { + node_t *n = init_node(s, v); + l->head = n; + l->size++; + return; + } + node_t *cur = l->head; + while (cur->next != NULL) { + if (strcmp(s->value, cur->key->value) == 0) { + string_free(s); + cur->value = v; + return; + } + cur = cur->next; + } + if (strcmp(s->value, cur->key->value) == 0) { + string_free(s); + cur->value = v; + return; + } + node_t *n = init_node(s, v); + cur->next = n; +} + +void *sll_get(sll_t *l, string_t *k) { if (l->head == NULL) return NULL; node_t *cur = l->head; @@ -303,13 +331,13 @@ value_t *sll_get(sll_t *l, string_t *k) { return NULL; } -void sll_free(sll_t *l) { +void sll_free(sll_t *l, void (*func)(void *)) { node_t *cur = l->head; node_t *tmp; while (cur != NULL) { tmp = cur; cur = cur->next; - node_free(tmp); + node_free(tmp, func); } free(l); } @@ -324,19 +352,23 @@ ht_t *init_ht(size_t size) { return h; } -void ht_add(ht_t *h, string_t *key, value_t *v) { +void ht_add(ht_t *h, string_t *key, void *v) { sll_add(h->buckets[hash(h, key->value)], key, v); } -value_t *ht_get(ht_t *h, string_t *key) { +void ht_add_func(ht_t *h, string_t *key, void *v) { + sll_add_func(h->buckets[hash(h, key->value)], key, v); +} + +void *ht_get(ht_t *h, string_t *key) { return sll_get(h->buckets[hash(h, key->value)], key); } bool ht_exists(ht_t *h, string_t *key) { return ht_get(h, key) != NULL; } -void ht_free(ht_t *h) { +void ht_free(ht_t *h, void (*func)(void *)) { for (int i = 0; i < h->size; i++) { - sll_free(h->buckets[i]); + sll_free(h->buckets[i], func); } free(h->buckets); free(h); @@ -353,953 +385,6 @@ unsigned long hash(ht_t *h, char *key) { return hash % h->size; } -void print_value(value_t *v) { - 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; - } -} - -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; -} - -bool eval_error() { - value_t *v = init_value(VERR); - array_append(STACK, v); - return true; -} - -/* 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) */ -bool eval_builtins(value_t *v) { - char *str = v->str_word->value; - value_t *v1; - value_t *v2; - value_t *v3; - value_t *retval; - if (strcmp(str, "func") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - if (v1->type != VWORD) { - value_free(v); - return eval_error(); - } - ht_add(WORD_TABLE, string_copy(v1->str_word), v2); - value_free(v1); - } else if (strcmp(str, "+") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - 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); - value_free(v); - return eval_error(); - } - retval->int_float = v1->int_float + v2->int_float; - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "-") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - 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); - } else if (strcmp(str, "/") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - 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); - } else if (strcmp(str, "*") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - 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); - } else if (strcmp(str, "pow") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - retval = init_value(VFLOAT); - if (v1->type == VINT && v2->type == VINT) { - retval->type = VINT; - } - retval->int_float = powl(v1->int_float, v2->int_float); - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "eval") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v1); - return eval_error(); - } - if (v1->type == VQUOTE) { - array_append(EVAL_STACK, v); - array_append(EVAL_STACK, v1); - for (int i = 0; i < v1->quote->size; i++) { - eval(value_copy(v1->quote->items[i])); - } - value_t *vf = array_pop(EVAL_STACK); - if (vf) { - value_free(vf); - } - array_pop(EVAL_STACK); - } else { - eval(v1); - } - } else if (strcmp(str, "strquote") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - if (v1->type != VSTR) { - array_append(STACK, v1); - value_free(v); - return eval_error(); - } - retval = init_value(VQUOTE); - retval->quote = init_array(10); - char *s = malloc(strlen(v1->str_word->value) + 1); - strcpy(s, v1->str_word->value); - parser_t *p = init_parser(s); - value_t *cur; - while (1) { - cur = parser_get_next(p); - if (cur == NULL) - break; - array_append(retval->quote, cur); - } - array_append(STACK, retval); - value_free(v1); - free(p->source); - free(p); - } else if (strcmp(str, ".") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - print_value(v1); - value_free(v1); - } else if (strcmp(str, "qstack") == 0) { - retval = init_value(VQUOTE); - retval->quote = array_copy(STACK); - array_append(STACK, retval); - } else if (strcmp(str, "?") == 0) { - for (int i = 0; i < STACK->size; i++) { - print_value(STACK->items[i]); - } - } else if (strcmp(str, "sin") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - retval = init_value(VFLOAT); - retval->int_float = sinhl(v1->int_float); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "cos") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - retval = init_value(VFLOAT); - retval->int_float = coshl(v1->int_float); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "exp") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - retval = init_value(VFLOAT); - retval->int_float = expl(v1->int_float); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "floor") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - retval = init_value(VFLOAT); - retval->int_float = floor(v1->int_float); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "ceil") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - retval = init_value(VFLOAT); - retval->int_float = ceil(v1->int_float); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "ln") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - retval = init_value(VFLOAT); - retval->int_float = logl(v1->int_float); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "ssize") == 0) { - retval = init_value(VINT); - retval->int_float = STACK->size; - array_append(STACK, retval); - } else if (strcmp(str, "compose") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - if (v2->type == VSTR && v1->type == VSTR) { - retval = init_value(VSTR); - string_concat(v1->str_word, v2->str_word); - retval->str_word = string_copy(v1->str_word); - value_free(v1); - value_free(v2); - } else if (v2->type == VWORD && v1->type == VWORD) { - retval = init_value(VWORD); - string_concat(v1->str_word, v2->str_word); - retval->str_word = string_copy(v1->str_word); - value_free(v1); - value_free(v2); - } else if (v2->type == VQUOTE && v1->type == VQUOTE) { - retval = v1; - array_extend(v1->quote, v2->quote); - free(v2->quote); - free(v2); - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - } else if (strcmp(str, "wtostr") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - if (v1->type != VWORD) { - value_free(v); - array_append(STACK, v1); - return eval_error(); - } - v1->type = VSTR; - array_append(STACK, v1); - } else if (strcmp(str, "=") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VSTR && v2->type == VSTR || - v1->type == VWORD && v2->type == VWORD) { - retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) == 0; - } else if ((v1->type == VINT || v1->type == VFLOAT) && - (v2->type == VINT || v2->type == VFLOAT)) { - retval->int_float = v1->int_float == v2->int_float; - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "!=") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VSTR && v2->type == VSTR || - v1->type == VWORD && v2->type == VWORD) { - retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) != 0; - } else if ((v1->type == VINT || v1->type == VFLOAT) && - (v2->type == VINT || v2->type == VFLOAT)) { - retval->int_float = v1->int_float != v2->int_float; - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "<=") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VSTR && v2->type == VSTR || - v1->type == VWORD && v2->type == VWORD) { - retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) <= 0; - } else if ((v1->type == VINT || v1->type == VFLOAT) && - (v2->type == VINT || v2->type == VFLOAT)) { - retval->int_float = v1->int_float <= v2->int_float; - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "<=") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VSTR && v2->type == VSTR || - v1->type == VWORD && v2->type == VWORD) { - retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) <= 0; - } else if ((v1->type == VINT || v1->type == VFLOAT) && - (v2->type == VINT || v2->type == VFLOAT)) { - retval->int_float = v1->int_float <= v2->int_float; - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "stoi") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = init_value(VINT); - retval->int_float = atoi(v1->str_word->value); - array_append(STACK, retval); - value_free(v1); - } else if (strcmp(str, "isnum") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = init_value(VINT); - - bool isnum = true; - for (int i = 0; i < v1->str_word->length; i++) { - if (isspace(v1->str_word->value[i])) { - continue; - } else if (!isdigit(v1->str_word->value[i])) { - isnum = false; - break; - } - } - retval->int_float = isnum; - - array_append(STACK, v1); - array_append(STACK, retval); - } else if (strcmp(str, ">") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VSTR && v2->type == VSTR || - v1->type == VWORD && v2->type == VWORD) { - retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) > 0; - } else if ((v1->type == VINT || v1->type == VFLOAT) && - (v2->type == VINT || v2->type == VFLOAT)) { - retval->int_float = v1->int_float > v2->int_float; - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, ">=") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VSTR && v2->type == VSTR || - v1->type == VWORD && v2->type == VWORD) { - retval->int_float = strcmp(v1->str_word->value, v2->str_word->value) >= 0; - } else if ((v1->type == VINT || v1->type == VFLOAT) && - (v2->type == VINT || v2->type == VFLOAT)) { - retval->int_float = v1->int_float >= v2->int_float; - } else { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, retval); - value_free(v1); - value_free(v2); - } else if (strcmp(str, "if") == 0) { - v3 = array_pop(STACK); - if (v3 == NULL) { - value_free(v); - return eval_error(); - } - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - array_append(STACK, v3); - return eval_error(); - } - - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - array_append(STACK, v3); - return eval_error(); - } - - if (v1->type != VINT) { - array_append(STACK, v1); - array_append(STACK, v2); - array_append(STACK, v3); - value_free(v); - return eval_error(); - } - - if (v1->int_float) { - value_free(v3); - value_free(v1); - if (v2->type == VQUOTE) { - - array_append(EVAL_STACK, v2); - array_append(EVAL_STACK, v); - for (int i = 0; i < v2->quote->size; i++) { - eval(value_copy(v2->quote->items[i])); - } - array_pop(EVAL_STACK); - value_t *vf = array_pop(EVAL_STACK); - if (vf) { - value_free(vf); - } - } else { - eval(v2); - } - } else { - value_free(v2); - value_free(v1); - if (v3->type == VQUOTE) { - array_append(EVAL_STACK, v3); - array_append(EVAL_STACK, v); - for (int i = 0; i < v3->quote->size; i++) { - eval(value_copy(v3->quote->items[i])); - } - array_pop(EVAL_STACK); - value_t *vf = array_pop(EVAL_STACK); - if (vf) { - value_free(vf); - } - } else { - eval(v3); - } - } - } else if (strcmp(str, "clear") == 0) { - for (int i = 0; i < STACK->size; i++) { - value_free(array_pop(STACK)); - } - } else if (strcmp(str, "curry") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - if (v2->type != VQUOTE) { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - - array_append(v2->quote, v1); - array_append(STACK, v2); - } else if (strcmp(str, "del") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - array_append(STACK, v2); - value_free(v); - return eval_error(); - } - - if (v2->type != VINT) { - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - switch (v1->type) { - case VQUOTE: - break; - case VSTR: - break; - case VWORD: - break; - default: - value_free(v1); - break; - } - } else if (strcmp(str, "keep") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - array_append(STACK, value_copy(v1)); - if (v2->type == VQUOTE) { - array_append(EVAL_STACK, v); - array_append(EVAL_STACK, v2); - for (int i = 0; i < v2->quote->size; i++) { - eval(value_copy(v2->quote->items[i])); - } - value_free(array_pop(EVAL_STACK)); - array_pop(EVAL_STACK); - } else { - eval(v1); - } - array_append(STACK, v1); - } else if (strcmp(str, "dip") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - if (v2->type == VQUOTE) { - array_append(EVAL_STACK, v); - array_append(EVAL_STACK, v1); - array_append(EVAL_STACK, v2); - for (int i = 0; i < v2->quote->size; i++) { - eval(value_copy(v2->quote->items[i])); - } - value_free(array_pop(EVAL_STACK)); - value_free(array_pop(EVAL_STACK)); - array_pop(EVAL_STACK); - } else { - eval(v1); - } - array_append(STACK, v1); - } else if (strcmp(str, "len") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type == VINT || v1->type == VFLOAT) { - retval->int_float = 1; - } else if (v1->type == VSTR || v1->type == VWORD) { - retval->int_float = strlen(v1->str_word->value); - } else if (v1->type == VQUOTE) { - retval->int_float = v1->quote->size; - } - array_append(STACK, v1); - array_append(STACK, retval); - } else if (strcmp(str, "dup") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = value_copy(v1); - array_append(STACK, v1); - array_append(STACK, retval); - } else if (strcmp(str, "isdef") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = init_value(VINT); - if (v1->type != VWORD) { - retval->int_float = 0; - } else { - retval->int_float = ht_exists(WORD_TABLE, v1->str_word); - } - array_append(STACK, v1); - array_append(STACK, retval); - } else if (strcmp(str, "swap") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - array_append(STACK, v2); - value_free(v); - return eval_error(); - } - array_append(STACK, v2); - array_append(STACK, v1); - } else if (strcmp(str, "dsc") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - value_free(v1); - } else if (strcmp(str, "type") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = init_value(VINT); - retval->int_float = v1->type; - array_append(STACK, v1); - array_append(STACK, retval); - } else if (strcmp(str, "quote") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - - retval = init_value(VQUOTE); - retval->quote = init_array(10); - array_append(retval->quote, v1); - array_append(STACK, retval); - } else if (strcmp(str, "exit") == 0) { - ht_free(WORD_TABLE); - array_free(STACK); - free(INBUF); - free(PARSER); - array_free(EVAL_STACK); - value_free(v); - exit(0); - } else if (strcmp(str, "read") == 0) { - retval = init_value(VSTR); - char *a = get_line(stdin); - retval->str_word = init_string(a); - array_append(STACK, retval); - free(a); - } else if (strcmp(str, "fread") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - if (v1->type != VSTR) { - value_free(v); - array_append(STACK, v1); - return eval_error(); - } - char *val = NULL; - size_t len; - FILE *fp = fopen(v1->str_word->value, "rb"); - if (!fp) { - value_free(v); - array_append(STACK, v1); - return eval_error(); - } - ssize_t bytes_read = getdelim(&val, &len, '\0', fp); - fclose(fp); - retval = init_value(VSTR); - retval->str_word = init_string(val); - array_append(STACK, retval); - value_free(v1); - free(val); - } else if (strcmp(str, "fwrite") == 0) { - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - return eval_error(); - } - if (v1->type != VSTR) { - value_free(v); - array_append(STACK, v1); - return eval_error(); - } - char *val; - size_t len; - FILE *fp = fopen(v1->str_word->value, "w+"); - if (!fp) { - value_free(v); - array_append(STACK, v1); - return eval_error(); - } - fprintf(fp, "%s", v1->str_word->value); - value_free(v1); - fclose(fp); - } else if (strcmp(str, "vat") == 0) { - v2 = array_pop(STACK); - if (v2 == NULL) { - value_free(v); - return eval_error(); - } - v1 = array_pop(STACK); - if (v1 == NULL) { - value_free(v); - array_append(STACK, v2); - return eval_error(); - } - - if (v1->type != VINT) { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - if (v2->type == VQUOTE) { - if (v2->quote->size <= v1->int_float) { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - array_append(STACK, v2); - array_append(STACK, value_copy(v2->quote->items[(int)v1->int_float])); - value_free(v1); - } else if (v2->type == VSTR) { - if (v2->str_word->length <= v1->int_float) { - value_free(v); - array_append(STACK, v1); - array_append(STACK, v2); - return eval_error(); - } - char *a = (char[]){v2->str_word->value[(int)v1->int_float], '\0'}; - string_t *s = init_string(a); - retval = init_value(VINT); - retval->str_word = s; - array_append(STACK, v2); - array_append(STACK, retval); - value_free(v1); - } else { - array_append(STACK, v1); - array_append(STACK, v2); - value_free(v); - return eval_error(); - } - } else if (strcmp(str, "nop") == 0) { - - } else { - return false; - } - value_free(v); - return true; -} - bool eval_ht(value_t *v) { value_t *func = ht_get(WORD_TABLE, v->str_word); if (func == NULL) @@ -1315,6 +400,20 @@ bool eval_ht(value_t *v) { return true; } +bool eval_builtins(value_t *v) { + if (v->type != VSTR && v->type != VWORD) { + printf("what the fuck\n"); + } + void (*func)(value_t *) = ht_get(FLIT, v->str_word); + if (func == NULL) + return false; + array_append(EVAL_STACK, v); + func(v); + array_pop(EVAL_STACK); + value_free(v); + return true; +} + void eval(value_t *v) { switch (v->type) { case VINT: @@ -1322,6 +421,7 @@ void eval(value_t *v) { case VSTR: case VQUOTE: case VERR: + case VCUSTOM: array_append(STACK, v); break; case VWORD: @@ -1335,6 +435,5 @@ void eval(value_t *v) { } } } - break; } } diff --git a/parser.h b/parser.h index 334834a..3fc1772 100644 --- a/parser.h +++ b/parser.h @@ -14,12 +14,13 @@ struct ARRAY_STRUCT { }; struct VALUE_STRUCT { - enum { VWORD, VINT, VFLOAT, VSTR, VQUOTE, VERR } type; + enum { VWORD, VINT, VFLOAT, VSTR, VQUOTE, VERR, VCUSTOM } type; union { long double int_float; array_t *quote; string_t *str_word; }; + void *custom; bool escaped; }; @@ -31,7 +32,7 @@ typedef struct PARSER_STRUCT { typedef struct NODE_STRUCT { string_t *key; - value_t *value; + void *value; struct NODE_STRUCT *next; } node_t; @@ -45,6 +46,8 @@ typedef struct { size_t size; } ht_t; +void func_free(void *f); + array_t *init_array(size_t size); void array_append(array_t *a, value_t *v); @@ -53,13 +56,15 @@ value_t *array_pop(array_t *a); array_t *array_copy(array_t *a); +void array_extend(array_t *a1, array_t *a2); + void array_free(array_t *a); value_t *init_value(int type); value_t *value_copy(value_t *v); -void value_free(value_t *v); +void value_free(void *v); parser_t *init_parser(char *source); @@ -71,23 +76,25 @@ void parser_skip_whitespace(parser_t *p); value_t *parser_get_next(parser_t *p); -node_t *init_node(string_t *key, value_t *v); +node_t *init_node(string_t *key, void *v); sll_t *init_sll(); -void sll_add(sll_t *l, string_t *key, value_t *v); +void sll_add(sll_t *l, string_t *key, void *v); -value_t *sll_get(sll_t *l, string_t *key); +void *sll_get(sll_t *l, string_t *key); -void sll_free(sll_t *l); +void sll_free(sll_t *l, void (*freefunc)(void *)); ht_t *init_ht(size_t size); -void ht_add(ht_t *h, string_t *key, value_t *v); +void ht_add(ht_t *h, string_t *key, void *v); + +void *ht_get(ht_t *h, string_t *key); -value_t *ht_get(ht_t *h, string_t *key); +bool ht_exists(ht_t *h, string_t *key); -void ht_free(ht_t *h); +void ht_free(ht_t *h, void (*freefunc)(void *)); unsigned long hash(ht_t *h, char *key); -- cgit