added .if, .cpy, .deref, arithmetic
This commit is contained in:
parent
3d6b2cbda5
commit
f2e88733f6
6 changed files with 153 additions and 21 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
140
src/eval.c
140
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
11
src/trie.h
11
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);
|
||||
|
|
Loading…
Reference in a new issue