From 7e696a40e51aa35b003aa9c3fc72139b34cddc71 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Tue, 14 Feb 2023 16:52:54 -0800 Subject: a lot of stuff. exec/eval works now --- .gitignore | 1 + hashtable.c | 27 +++++++++++++---------- hashtable.h | 5 +++-- parse.c | 8 +++---- precedent.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- precedent.h | 6 +++-- scope.c | 2 +- scope.h | 4 ++-- 8 files changed, 102 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index a1c9445..73aa70a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ a.exe *.swp precedent *.core +vgcore.* diff --git a/hashtable.c b/hashtable.c index ce4c65a..7cb253c 100644 --- a/hashtable.c +++ b/hashtable.c @@ -1,9 +1,22 @@ #include +#include #include "hashtable.h" const unsigned int fnvPrime = 16777619; const unsigned int fnvOffset = 2166136261U; +pair_t* init_pair(char* key, void* value) { + pair_t* p = malloc(sizeof(pair_t)); + p->key = key; + p->value = value; + return p; +} +hashtable_t* init_hashtable(unsigned int capacity) { + hashtable_t* ht = malloc(sizeof(hashtable_t)); + ht->pairs = calloc(capacity, sizeof(pair_t*)); + ht->capacity = capacity; + return ht; +} //FNV-1a hash unsigned int get_hash(char* str) { unsigned int hash = fnvOffset; @@ -13,19 +26,11 @@ unsigned int get_hash(char* str) { } return hash; } -hashtable_t* init_hashtable(unsigned int capacity) { - hashtable_t* ht = malloc(sizeof(hashtable_t)); - ht->pairs = calloc(capacity, sizeof(pair_t*)); - ht->capacity = capacity; - return ht; -} /* TODO: handle collision TODO: return 0 if something goes wrong */ -unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t pair) { - unsigned int hash = get_hash(pair.key); - pair_t* memPair = malloc(sizeof(pair_t)); - *memPair = pair; - hashtable->pairs[hash % hashtable->capacity] = memPair; +unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t* pair) { + unsigned int hash = get_hash(pair->key); + hashtable->pairs[hash % hashtable->capacity] = pair; return hash; } pair_t* hashtable_get_pair(hashtable_t* hashtable, char* key) { diff --git a/hashtable.h b/hashtable.h index be45964..43ab23a 100644 --- a/hashtable.h +++ b/hashtable.h @@ -5,14 +5,15 @@ typedef struct HashPair { char* key; void* value; } pair_t; +pair_t* init_pair(char* key, void* value); typedef struct HashTable { pair_t** pairs; int capacity; int itemCount; } hashtable_t; -unsigned int get_hash(char* str); hashtable_t* init_hashtable(unsigned int capacity); -unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t pair); +unsigned int get_hash(char* str); +unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t* pair); pair_t* hashtable_get_pair(hashtable_t* hashtable, char* key); #endif diff --git a/parse.c b/parse.c index e48adda..43dbf54 100644 --- a/parse.c +++ b/parse.c @@ -35,10 +35,7 @@ symset_t* parse_symbols(char** str) { } if (**str == ')') { (*str)++; - if (**str == ';') { - (*str)++; - return symbolSet; - } + return symbolSet; } else if (**str == '\0') { return symbolSet; @@ -62,11 +59,12 @@ symset_t* parse_symbols(char** str) { symbolName[i] = '\0'; sym_t* symbol = malloc(sizeof(sym_t)); symbol->province = KEY_REF; + symbol->argCount = 0; if(i > 1) { symbol->name = symbolName; } else { - symbol->name = "fork"; + symbol->name = "root"; } symset_t* symbols = parse_symbols(str); for (int s = 0; s < symbols->count; s++) { diff --git a/precedent.c b/precedent.c index df7ac33..95d62e5 100644 --- a/precedent.c +++ b/precedent.c @@ -4,8 +4,79 @@ #include "hashtable.h" #include "parse.h" +hashtable_t* ht; + int main() { - sym_t* finalSymbol = parse_symbol_final("store(5; test;); print(read(test;);); (hello; hello2;);"); + sym_t* finalSymbol = parse_symbol_final("store(print(hello;) myFunc;) myFunc()"); + printf("drawing program:\n"); write_symbol_visual(finalSymbol, 0); + printf("\nexecuting program:\n"); + ht = init_hashtable(1000); + 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]); + } +} +void* eval(sym_t* symbol) { + if (symbol->province == LITERAL) { + return symbol->name; + } + else if (symbol->province == KEY_REF) { + void* 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 */ +void* try_eval_internal(sym_t* symbol) { + unsigned int hash = get_hash((char*)symbol->name); + 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 (void*)1; + } + else if (hash == get_hash("store")) { + /* TODO: scope */ + /* first arg is value, remaining args are names */ + /* TODO: recursion for multiple pairs */ + char* key = (char*)eval(symbol->args[1]); + sym_t* value = symbol->args[0]; + pair_t* p = init_pair(key, (void*)value); + hashtable_add_pair(ht, p); + return (void*)1; + } + else if (hash == get_hash("print")) { + /* TODO: genericize printf type */ + printf("%s\n", (char*)eval(symbol->args[0])); + return (void*)1; + } + else { + return NULL; + } +} diff --git a/precedent.h b/precedent.h index 4449f83..5f3eeae 100644 --- a/precedent.h +++ b/precedent.h @@ -1,8 +1,10 @@ #include "parse.h" +#include "hashtable.h" #ifndef PRECEDENT #define PRECEDENT -void execute_imperative(sym_t symbol); -void* eval_symbol(sym_t symbol); +void exec_all(symset_t symset); +void* eval(sym_t* symbol); +void* try_eval_internal(sym_t* symbol); #endif diff --git a/scope.c b/scope.c index 4cc5249..afb9d5c 100644 --- a/scope.c +++ b/scope.c @@ -8,7 +8,7 @@ scope_t* init_scope(scope_t parent) { *(scope->parent) = parent; return scope; } -pair_t* get_pair_global(char* key, scope_t* scope) { +pair_t* get_pair_global(scope_t* scope, char* key) { while (scope->parent != NULL) { pair_t* pair = hashtable_get_pair(scope->hashtable, key); if (pair != NULL) { diff --git a/scope.h b/scope.h index 7847e06..d1cda0d 100644 --- a/scope.h +++ b/scope.h @@ -7,7 +7,7 @@ typedef struct Scope { struct Scope* parent; } scope_t; scope_t* init_scope(scope_t parent); -pair_t* get_pair_global(char* key, scope_t* scope); -pair_t* get_pair_local(char* key, scope_t* scope); +pair_t* get_pair_global(scope_t* scope, char* key); +pair_t* get_pair_local(scope_t* scope, char* key); #endif -- cgit v1.3.1