summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--doc/example.pcdt2
-rw-r--r--eval.c123
-rw-r--r--eval.h9
-rw-r--r--example.pcdt3
-rw-r--r--parse.c5
-rw-r--r--precedent.c140
-rw-r--r--precedent.h7
9 files changed, 167 insertions, 125 deletions
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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#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] <file>\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