From f2e88733f6dabcb102f689b91faaef3018bd9843 Mon Sep 17 00:00:00 2001 From: TriMill Date: Thu, 23 Feb 2023 11:43:57 -0500 Subject: [PATCH] added .if, .cpy, .deref, arithmetic --- examples/cat.sysh | 11 ++-- gen/commands | 6 +- src/eval.c | 140 +++++++++++++++++++++++++++++++++++++++++++--- src/hashmap.c | 4 +- src/hashmap.h | 2 +- src/trie.h | 11 ++-- 6 files changed, 153 insertions(+), 21 deletions(-) diff --git a/examples/cat.sysh b/examples/cat.sysh index fb8db4c..e9a49f9 100644 --- a/examples/cat.sysh +++ b/examples/cat.sysh @@ -1,5 +1,8 @@ -.set $buf { .alloc 1024 } -.set $read { read 0 $buf 1024 } -write 1 $buf $read +.set $BUF_MAX 1024 +.set $buf { .alloc $BUF_MAX } +.set $read 1 +.while $read { + .set $read { read 0 $buf $BUF_MAX } + write 1 $buf $read +} .free $buf - diff --git a/gen/commands b/gen/commands index 927ae4a..86e6a51 100644 --- a/gen/commands +++ b/gen/commands @@ -4,7 +4,9 @@ .set C_SET .cpy C_CPY .deref C_DEREF -.strerror C_STRERROR .if C_IF .while C_WHILE -.for C_FOR +.add C_ADD +.sub C_SUB +.mul C_MUL +.div C_DIV diff --git a/src/eval.c b/src/eval.c index 4499f5d..b92f7f2 100644 --- a/src/eval.c +++ b/src/eval.c @@ -11,8 +11,6 @@ #include "scanner.h" #include "trie.h" -#define LOGERROR(msg) fprintf(stderr, "sysh: " msg ## "\n") - static void log_error(const char* format, ...) { va_list args; va_start(args, format); @@ -67,6 +65,7 @@ static long eval_syscall(Line* line, Hashmap* vars) { } } long result = syscall(line->id, args[0], args[1], args[2], args[3], args[4], args[5]); + hashmap_add(vars, "ERRNO", errno); for(int i = 0; i < line->len; i++) { if(cloned[i]) free((void*)args[i]); } @@ -134,21 +133,145 @@ static long eval_set(Line* line, Hashmap* vars) { log_error("bad argument to .set"); return -1; } - hashmap_add(vars, strdup(line->args[0].as.str), val); + hashmap_add(vars, line->args[0].as.str, val); } else { hashmap_remove(vars, line->args[0].as.str); } return 0; } +static long eval_while(Line* line, Hashmap* vars) { + if(line->len != 2) { + log_error(".while expected 2 args, got %d", line->len); + return -1; + } + long result = 0; + while(true) { + long val; + if(!eval_arg(line->args[0], &val, NULL, vars)) { + log_error("bad argument to .while"); + return -1; + } + if(!val) break; + if(!eval_arg(line->args[1], &result, NULL, vars)) { + log_error("bad argument to .while"); + return -1; + } + } + return result; +} + +static long eval_if(Line* line, Hashmap* vars) { + if(line->len < 2 || line->len > 3) { + log_error(".if expected 2 or 3 args, got %d", line->len); + return -1; + } + long val; + if(!eval_arg(line->args[0], &val, NULL, vars)) { + log_error("bad argument to .if"); + return -1; + } + if(val) { + long result; + if(!eval_arg(line->args[1], &result, NULL, vars)) { + log_error("bad argument to .if"); + return -1; + } + return result; + } else if(line->len == 3) { + long result; + if(!eval_arg(line->args[2], &result, NULL, vars)) { + log_error("bad argument to .if"); + return -1; + } + return result; + + } else { + return 0; + } +} + +static long eval_cpy(Line* line, Hashmap* vars) { + if(line->len != 3) { + log_error(".cpy expected 3 arguments, got %d", line->len); + return -1; + } + long dst; + if(!eval_arg(line->args[0], &dst, NULL, vars)) { + log_error("bad argument to .cpy"); + return -1; + } + long n; + if(!eval_arg(line->args[2], &n, NULL, vars)) { + log_error("bad argument to .cpy"); + return -1; + } + long src; + bool cloned; + if(!eval_arg(line->args[1], &src, &cloned, vars)) { + log_error("bad argument to .cpy"); + return -1; + } + memcpy((void*)dst, (void*)src, n); + if(cloned) free((void*)src); + return 0; +} + +static long eval_deref(Line* line, Hashmap* vars) { + if(line->len != 1) { + log_error(".deref expected 1 argument, got %d", line->len); + return -1; + } + long val; + bool cloned; + if(!eval_arg(line->args[0], &val, &cloned, vars)) { + log_error("bad argument to .deref"); + return -1; + } + long result = *((unsigned char*)val); + if(cloned) free((void*)val); + return result; +} + +static long fn_add(long a, long b) { return a + b; } +static long fn_sub(long a, long b) { return a - b; } +static long fn_mul(long a, long b) { return a * b; } +static long fn_div(long a, long b) { return a / b; } + +static long eval_op(Line* line, Hashmap* vars, const char* name, long (*op)(long, long)) { + if(line->len != 2) { + log_error("%s expected 1 argument, got %d", name, line->len); + return -1; + } + long val1; + if(!eval_arg(line->args[0], &val1, NULL, vars)) { + log_error("bad argument to %s", name); + return -1; + } + long val2; + if(!eval_arg(line->args[1], &val2, NULL, vars)) { + log_error("bad argument to %s", name); + return -1; + } + return op(val1, val2); +} + static long eval_line(Line* line, Hashmap* vars) { if(line->id >= 0) { return eval_syscall(line, vars); } else switch(line->id) { - case C_ALLOC: return eval_alloc(line, vars); - case C_REALLOC: return eval_realloc(line, vars); - case C_FREE: return eval_free(line, vars); - case C_SET: return eval_set(line, vars); + case C_ALLOC: return eval_alloc(line, vars); + case C_REALLOC: return eval_realloc(line, vars); + case C_FREE: return eval_free(line, vars); + case C_SET: return eval_set(line, vars); + case C_CPY: return eval_cpy(line, vars); + case C_DEREF: return eval_deref(line, vars); + case C_WHILE: return eval_while(line, vars); + case C_IF: return eval_if(line, vars); + case C_ADD: return eval_op(line, vars, ".add", fn_add); + case C_SUB: return eval_op(line, vars, ".sub", fn_sub); + case C_MUL: return eval_op(line, vars, ".mul", fn_mul); + case C_DIV: return eval_op(line, vars, ".div", fn_div); default: return 0; // unreachable } } @@ -157,8 +280,9 @@ long eval_block(Block* block, Hashmap* vars) { long result = 0; for(int i = 0; i < block->len; i++) { result = eval_line(&block->lines[i], vars); + hashmap_add(vars, "LAST", result); if(errno > 0) { - fprintf(stderr, "E%d: %s\n", errno, strerror(errno)); + log_error("E%d: %s", errno, strerror(errno)); } } return result; diff --git a/src/hashmap.c b/src/hashmap.c index 4f6799a..21100b7 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -80,7 +80,7 @@ bool hashmap_get(Hashmap* hashmap, const char* key, long* value) { return true; } -bool hashmap_add(Hashmap* hashmap, char* key, long value) { +bool hashmap_add(Hashmap* hashmap, const char* key, long value) { if(hashmap->len + 1 > hashmap->capacity * TABLE_MAX_LOAD) { int capacity = (hashmap->capacity == 0 ? 8 : (2 * hashmap->capacity)); hashmap_grow(hashmap, capacity); @@ -89,8 +89,8 @@ bool hashmap_add(Hashmap* hashmap, char* key, long value) { bool new_key = e->key == NULL; if(new_key) { hashmap->len++; + e->key = strdup(key); } - e->key = key; e->value = value; return new_key; } diff --git a/src/hashmap.h b/src/hashmap.h index d0f94a4..765e509 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -17,7 +17,7 @@ typedef struct { void hashmap_init(Hashmap* hashmap); void hashmap_free(Hashmap* hashmap); -bool hashmap_add(Hashmap* hashmap, char* key, long value); +bool hashmap_add(Hashmap* hashmap, const char* key, long value); bool hashmap_get(Hashmap* hashmap, const char* key, long* value); bool hashmap_remove(Hashmap* hashmap, const char* key); diff --git a/src/trie.h b/src/trie.h index a1f7c9f..81f88c5 100644 --- a/src/trie.h +++ b/src/trie.h @@ -6,9 +6,12 @@ #define C_SET -5 #define C_CPY -6 #define C_DEREF -7 -#define C_STRERROR -8 -#define C_IF -9 -#define C_WHILE -10 -#define C_FOR -11 +#define C_IF -8 +#define C_WHILE -9 +#define C_ADD -10 +#define C_SUB -11 +#define C_MUL -12 +#define C_DIV -13 + long trie_get(const char* key);