added .if, .cpy, .deref, arithmetic

This commit is contained in:
TriMill 2023-02-23 11:43:57 -05:00
parent 3d6b2cbda5
commit f2e88733f6
6 changed files with 153 additions and 21 deletions

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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);