From 012a218e3f25f4712e6eb9a197e4473f0617eaed Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Wed, 15 Feb 2023 19:36:22 -0800 Subject: added reading from files, fixed some bugs --- .gitignore | 1 + Makefile | 2 +- doc/example.pcdt | 2 + eval.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ eval.h | 9 ++++ example.pcdt | 3 -- parse.c | 5 +- precedent.c | 140 +++++++++++-------------------------------------------- precedent.h | 7 +-- 9 files changed, 167 insertions(+), 125 deletions(-) create mode 100644 doc/example.pcdt create mode 100644 eval.c create mode 100644 eval.h delete mode 100644 example.pcdt diff --git a/.gitignore b/.gitignore index 27fc188..03b17b3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ precedent *.core vgcore.* *.dSYM/ +/*.pcdt diff --git a/Makefile b/Makefile index e3dcd83..3d5b3ed 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ PREFIX ?= /usr BINDIR ?= ${PREFIX}/bin generate: - $(CC) -o precedent precedent.c hashtable.c scope.c parse.c $(CFLAGS) + $(CC) -o precedent precedent.c hashtable.c scope.c parse.c eval.c $(CFLAGS) clean: rm precedent diff --git a/doc/example.pcdt b/doc/example.pcdt new file mode 100644 index 0000000..68d0a84 --- /dev/null +++ b/doc/example.pcdt @@ -0,0 +1,2 @@ +store(hello;myVar;) +print(myVar()) diff --git a/eval.c b/eval.c new file mode 100644 index 0000000..3cbe987 --- /dev/null +++ b/eval.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include "eval.h" +#include "hashtable.h" +#include "parse.h" + +hashtable_t* ht; +const int hashtableSize = 1000; +const int trueVal = 1; +sym_t trueSym = {LITERAL, INT, (void*)&trueVal, NULL, 0}; +const int falseVal = 0; +sym_t falseSym = {LITERAL, INT, (void*)&falseVal, NULL, 0}; + +void init_eval() { + ht = init_hashtable(hashtableSize); +} +/* TODO: read base hashtable from file to allow modularity +pair value value? */ +void exec_all(symset_t symset) { + for (int i = 0; i < symset.count; i++) { + /* dispose of result */ + eval(symset.symbols[i]); + } +} +sym_t* eval(sym_t* symbol) { + if (symbol->province == LITERAL) { + return(symbol); + } + else if (symbol->province == KEY_REF) { + sym_t* ir = try_eval_internal(symbol); + if (ir != NULL) { + return ir; + } + else { + /* not an internal function, search hashtable for + next symbol */ + /* TODO: scope */ + pair_t* p = hashtable_get_pair(ht, (char*)symbol->name); + if (p != NULL) { + return eval((sym_t*)p->value); + } + else { + printf("no matching pair in hashtable\n"); + return NULL; + } + } + } + else { + printf("no symbol province\n"); + return NULL; + } +} +/* internal functions? +this function has side-effects */ +sym_t* try_eval_internal(sym_t* symbol) { + unsigned int hash = get_hash((char*)symbol->name); + /* TODO: return last arg. that's the function return line */ + if (hash == get_hash("root")) { + /* execute all args as roots */ + symset_t symset; + symset.symbols = symbol->args; + symset.count = symbol->argCount; + exec_all(symset); + return &trueSym; + } + else if (hash == get_hash("store")) { + /* TODO: scope */ + /* first arg is value, remaining args are names */ + /* TODO: recursion for multiple pairs */ + char* k = symtos(eval(symbol->args[1])); + sym_t* v = eval(symbol->args[0]); + pair_t* p = init_pair(k, (void*)v); + hashtable_add_pair(ht, p); + return &trueSym; + } + else if (hash == get_hash("eq")) { + litType_t type = NO_TYPE; + void* lastVal = NULL; + for (int i = 0; i < symbol->argCount; i++) { + sym_t* v = eval(symbol->args[i]); + /* initialize */ + if (type == NO_TYPE) { + type = v->litType; + lastVal = v->name; + } + else { + /* interpret type */ + if (type == INT) { + if (symtoi(v) != *((int*)lastVal)) { + return &falseSym; + } + } + if (type == STRING) { + if (strcmp(symtos(v), (char*)lastVal) != 0) { + return &falseSym; + } + } + /* TODO: float */ + } + } + return &trueSym; + } + else if (hash == get_hash("print")) { + sym_t* v = eval(symbol->args[0]); + switch (v->litType) { + case NO_TYPE: + break; + case INT: + printf("%d\n", symtoi(v)); + break; + case FLOAT: + break; + case STRING: + printf("%s\n", symtos(v)); + break; + } + return &trueSym; + } + else { + return NULL; + } +} diff --git a/eval.h b/eval.h new file mode 100644 index 0000000..662774a --- /dev/null +++ b/eval.h @@ -0,0 +1,9 @@ +#include "parse.h" +#ifndef EVAL +#define EVAL +void init_eval(void); +void throw(char* error, int symbolLocale); +void exec_all(symset_t symset); +sym_t* eval(sym_t* symbol); +sym_t* try_eval_internal(sym_t* symbol); +#endif diff --git a/example.pcdt b/example.pcdt deleted file mode 100644 index 6c4dd92..0000000 --- a/example.pcdt +++ /dev/null @@ -1,3 +0,0 @@ -store(5; myVar;); -print(read(myVar;);); -(hello; hello2;) diff --git a/parse.c b/parse.c index d8a06d0..c174c23 100644 --- a/parse.c +++ b/parse.c @@ -63,7 +63,7 @@ symset_t* parse_symbols(char** str) { /* TODO: float */ /* string */ if (isalpha(symbolName[0])) { - symbolName = realloc(symbolName, i * sizeof(char)); + //symbolName = realloc(symbolName, i * sizeof(char)); symbol->name = symbolName; symbol->litType = STRING; } @@ -110,6 +110,7 @@ sym_t* parse_symbol_final(char* str) { sym_t* root = malloc(sizeof(sym_t)); root->name = "root"; root->province = KEY_REF; + root->argCount = 0; for (int s = 0; s < finalSymset->count; s++) { symbol_add_arg(root, finalSymset->symbols[s]); } @@ -119,7 +120,7 @@ void write_symbol_visual(sym_t* symbol, int offset) { for (int o = 0; o < offset; o++) { printf(" "); } - printf("%s (%s)\n", (char*)(symbol->name), symbol->province == 1 ? "KEY" : "LITERAL"); + printf("%s (%s)\n", (char*)(symbol->name), symbol->province == KEY_REF ? "KEY" : "LITERAL"); for (int i = 0; i < symbol->argCount; i++) { write_symbol_visual(symbol->args[i], offset + 4); } diff --git a/precedent.c b/precedent.c index 9d60bfd..38fc617 100644 --- a/precedent.c +++ b/precedent.c @@ -4,124 +4,38 @@ #include "precedent.h" #include "hashtable.h" #include "parse.h" +#include "eval.h" -hashtable_t* ht; -const int trueVal = 1; -sym_t trueSym = {LITERAL, INT, (void*)&trueVal, NULL, 0}; -const int falseVal = 0; -sym_t falseSym = {LITERAL, INT, (void*)&falseVal, NULL, 0}; - -int main() { - sym_t* finalSymbol = parse_symbol_final("print(eq(0; 1;))"); +int main(int argc, char** argv) { + if (argc > 1) { + if (strcmp("--version", argv[1]) == 0) { + printf("precedent, version 0.1\n"); + printf("Copyright 2023 Kai Stevenson\n"); + printf("This software was licensed under the MIT license;\n"); + printf("for more information, see the license file.\n"); + return 0; + } + else if (strcmp("--help", argv[1]) == 0) { + printf("usage: precedent [--version] [--help] \n"); + return 0; + } + } + sym_t* finalSymbol = parse_symbol_final(read_file(argv[1])); printf("drawing program:\n"); write_symbol_visual(finalSymbol, 0); printf("\nexecuting program:\n"); - ht = init_hashtable(1000); + init_eval(); eval(finalSymbol); return 0; } -/* TODO: read base hashtable from file to allow modularity -pair value value? */ -void exec_all(symset_t symset) { - for (int i = 0; i < symset.count; i++) { - /* dispose of result */ - eval(symset.symbols[i]); - } -} -sym_t* eval(sym_t* symbol) { - if (symbol->province == LITERAL) { - return(symbol); - } - else if (symbol->province == KEY_REF) { - sym_t* ir = try_eval_internal(symbol); - if (ir != NULL) { - return ir; - } - else { - /* not an internal function, search hashtable for - next symbol */ - /* TODO: scope */ - pair_t* p = hashtable_get_pair(ht, (char*)symbol->name); - if (p != NULL) { - return eval((sym_t*)p->value); - } - else { - return NULL; - } - } - } - else { - return NULL; - } -} -/* internal functions? -this function has side-effects */ -sym_t* try_eval_internal(sym_t* symbol) { - unsigned int hash = get_hash((char*)symbol->name); - /* TODO: return last arg. that's the function return line */ - if (hash == get_hash("root")) { - /* execute all args as roots */ - symset_t symset; - symset.symbols = symbol->args; - symset.count = symbol->argCount; - exec_all(symset); - return &trueSym; - } - else if (hash == get_hash("store")) { - /* TODO: scope */ - /* first arg is value, remaining args are names */ - /* TODO: recursion for multiple pairs */ - sym_t* v = eval(symbol->args[0]); - char* key = symtos(v); - sym_t* value = symbol->args[0]; - pair_t* p = init_pair(key, (void*)value); - hashtable_add_pair(ht, p); - return &trueSym; - } - else if (hash == get_hash("eq")) { - litType_t type = NO_TYPE; - void* lastVal = NULL; - for (int i = 0; i < symbol->argCount; i++) { - sym_t* v = eval(symbol->args[i]); - /* initialize */ - if (type == NO_TYPE) { - type = v->litType; - lastVal = v->name; - } - else { - /* interpret type */ - if (type == INT) { - if (symtoi(v) != *((int*)lastVal)) { - return &falseSym; - } - } - if (type == STRING) { - if (strcmp(symtos(v), (char*)lastVal) != 0) { - return &falseSym; - } - } - /* TODO: float */ - } - } - return &trueSym; - } - else if (hash == get_hash("print")) { - sym_t* v = eval(symbol->args[0]); - switch (v->litType) { - case NO_TYPE: - break; - case INT: - printf("%d\n", symtoi(v)); - break; - case FLOAT: - break; - case STRING: - printf("%s\n", symtos(v)); - break; - } - return &trueSym; - } - else { - return NULL; - } +char* read_file(char* path) { + FILE* file = fopen(path, "r"); + fseek(file, 0, SEEK_END); + unsigned long int length = ftell(file); + fseek(file, 0, SEEK_SET); + char* out = malloc((length + 1) * sizeof(char)); + fread(out, length, 1, file); + fclose(file); + out[length] = '\0'; + return out; } diff --git a/precedent.h b/precedent.h index aecf015..a1302d4 100644 --- a/precedent.h +++ b/precedent.h @@ -1,11 +1,6 @@ #include "parse.h" #include "hashtable.h" #ifndef PRECEDENT +char* read_file(char* path); #define PRECEDENT - -void throw(char* error, int symbolLocale); -void exec_all(symset_t symset); -sym_t* eval(sym_t* symbol); -sym_t* try_eval_internal(sym_t* symbol); - #endif -- cgit v1.3.1