A bunch of fixes
This commit is contained in:
+29
-6
@@ -235,6 +235,9 @@ bool global_scope(Assembler *a)
|
||||
|
||||
Symbol *find_symbol_in_local_scope(Assembler *a, String name)
|
||||
{
|
||||
if (name.len == 0)
|
||||
return NULL;
|
||||
|
||||
Scope *scope = &a->scopes[a->num_scopes-1];
|
||||
for (int i = a->num_syms-1; i >= scope->sym_base; i--)
|
||||
if (streq(a->syms[i].name, name))
|
||||
@@ -244,6 +247,9 @@ Symbol *find_symbol_in_local_scope(Assembler *a, String name)
|
||||
|
||||
Symbol *find_symbol_in_function(Assembler *a, String name)
|
||||
{
|
||||
if (name.len == 0)
|
||||
return NULL;
|
||||
|
||||
Scope *scope = parent_scope(a);
|
||||
for (int i = a->num_syms-1; i >= scope->sym_base; i--)
|
||||
if (streq(a->syms[i].name, name))
|
||||
@@ -1131,18 +1137,35 @@ void assemble_statement(Assembler *a, Node *node, bool pop_expr)
|
||||
|
||||
case NODE_FOR:
|
||||
{
|
||||
assemble_expr(a, node->for_set, 1);
|
||||
|
||||
// TODO
|
||||
|
||||
int ret = push_scope(a, SCOPE_FOR);
|
||||
if (ret < 0) return;
|
||||
|
||||
declare_variable(a, node->for_var1);
|
||||
declare_variable(a, node->for_var2);
|
||||
int var_1 = declare_variable(a, node->for_var1);
|
||||
int var_2 = declare_variable(a, node->for_var2);
|
||||
int var_3 = declare_variable(a, (String) { NULL, 0 });
|
||||
|
||||
assemble_expr(a, node->for_set, 1);
|
||||
append_u8(&a->out, OPCODE_SETV);
|
||||
append_u8(&a->out, var_3);
|
||||
|
||||
append_u8(&a->out, OPCODE_PUSHI);
|
||||
append_s64(&a->out, 0);
|
||||
append_u8(&a->out, OPCODE_SETV);
|
||||
append_u8(&a->out, var_2);
|
||||
|
||||
int start = append_u8(&a->out, OPCODE_FOR);
|
||||
append_u8(&a->out, var_3);
|
||||
append_u8(&a->out, var_1);
|
||||
append_u8(&a->out, var_2);
|
||||
int p = append_u32(&a->out, 0);
|
||||
|
||||
assemble_statement(a, node->left, pop_expr);
|
||||
|
||||
append_u8(&a->out, OPCODE_JUMP);
|
||||
append_u32(&a->out, start);
|
||||
|
||||
patch_with_current_offset(&a->out, p);
|
||||
|
||||
ret = pop_scope(a);
|
||||
if (ret < 0) return;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ enum {
|
||||
OPCODE_PRINT = 0x24,
|
||||
OPCODE_SYSVAR = 0x2C,
|
||||
OPCODE_SYSCALL = 0x2D,
|
||||
OPCODE_FOR = 0x2E,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
+256
-18
@@ -41,6 +41,8 @@ struct WL_State {
|
||||
String sysvar;
|
||||
String syscall;
|
||||
bool syscall_error;
|
||||
int stack_before_user;
|
||||
int stack_base_for_user;
|
||||
};
|
||||
|
||||
void eval_report(WL_State *state, char *fmt, ...)
|
||||
@@ -785,7 +787,8 @@ int step(WL_State *state)
|
||||
|
||||
Value *src = array_select(set, key);
|
||||
if (src == NULL) {
|
||||
assert(0); // TODO
|
||||
eval_report(state, "Index out of range");
|
||||
return -1;
|
||||
}
|
||||
r = *src;
|
||||
|
||||
@@ -793,7 +796,8 @@ int step(WL_State *state)
|
||||
|
||||
int ret = map_select(set, key, &r);
|
||||
if (ret < 0) {
|
||||
assert(0); // TODO
|
||||
eval_report(state, "Key not contained in map");
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -818,6 +822,8 @@ int step(WL_State *state)
|
||||
String name = { state->data.ptr + off, len };
|
||||
|
||||
state->sysvar = name;
|
||||
state->stack_before_user = state->eval_depth;
|
||||
state->stack_base_for_user = state->groups[state->num_groups-1];
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -827,7 +833,72 @@ int step(WL_State *state)
|
||||
uint32_t len = read_u32(state);
|
||||
String name = { state->data.ptr + off, len };
|
||||
|
||||
int num_args = state->eval_depth - state->groups[state->num_groups-1];
|
||||
|
||||
Value v = make_int(state->a, num_args);
|
||||
if (v == VALUE_ERROR) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
state->eval_stack[state->eval_depth++] = v;
|
||||
|
||||
state->syscall = name;
|
||||
state->stack_before_user = state->eval_depth;
|
||||
state->stack_base_for_user = state->groups[state->num_groups-1];
|
||||
}
|
||||
break;
|
||||
|
||||
case OPCODE_FOR:
|
||||
{
|
||||
uint8_t var_3 = read_u8(state);
|
||||
uint8_t var_1 = read_u8(state);
|
||||
uint8_t var_2 = read_u8(state);
|
||||
uint32_t end = read_u32(state);
|
||||
|
||||
int base;
|
||||
{
|
||||
int group = state->frames[state->num_frames-1].group;
|
||||
base = state->groups[group];
|
||||
}
|
||||
|
||||
int64_t idx;
|
||||
{
|
||||
Value idx_val = state->eval_stack[base + var_2];
|
||||
if (type_of(idx_val) != TYPE_INT) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
idx = get_int(idx_val);
|
||||
}
|
||||
|
||||
Value set = state->eval_stack[base + var_3];
|
||||
|
||||
Type set_type = type_of(set);
|
||||
if (set_type == TYPE_ARRAY) {
|
||||
|
||||
if (value_length(set) == idx) {
|
||||
state->off = end;
|
||||
break;
|
||||
}
|
||||
|
||||
state->eval_stack[base + var_1] = *array_select(set, idx);
|
||||
|
||||
} else if (set_type == TYPE_MAP) {
|
||||
|
||||
if (value_length(set) == idx) {
|
||||
state->off = end;
|
||||
break;
|
||||
}
|
||||
|
||||
state->eval_stack[base + var_1] = *map_select_by_index(set, idx);
|
||||
|
||||
} else {
|
||||
assert(0); // TODO
|
||||
}
|
||||
|
||||
Value v = make_int(state->a, idx + 1);
|
||||
if (v == VALUE_ERROR) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
state->eval_stack[base + var_2] = v;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -886,7 +957,6 @@ WL_Result WL_eval(WL_State *state)
|
||||
if (state->syscall_error)
|
||||
return (WL_Result) { WL_ERROR, (WL_String) { NULL, 0 } };
|
||||
|
||||
// TODO
|
||||
state->sysvar = S("");
|
||||
}
|
||||
|
||||
@@ -895,6 +965,18 @@ WL_Result WL_eval(WL_State *state)
|
||||
if (state->syscall_error)
|
||||
return (WL_Result) { WL_ERROR, (WL_String) { NULL, 0 } };
|
||||
|
||||
int group = state->groups[state->num_groups-1];
|
||||
|
||||
Value v = state->eval_stack[--state->eval_depth];
|
||||
if (type_of(v) != TYPE_INT) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
int64_t num_rets = get_int(v);
|
||||
for (int i = 0; i < num_rets; i++)
|
||||
state->eval_stack[group + i] = state->eval_stack[state->eval_depth - num_rets + i];
|
||||
|
||||
state->eval_depth = group + num_rets;
|
||||
|
||||
state->syscall = S("");
|
||||
}
|
||||
|
||||
@@ -947,11 +1029,86 @@ static bool in_syscall(WL_State *state)
|
||||
return (state->syscall.len > 0 || state->sysvar.len > 0) && !state->syscall_error;
|
||||
}
|
||||
|
||||
int WL_peeknone(WL_State *state, int off)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth + off < state->stack_base_for_user || off >= 0)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth + off];
|
||||
if (type_of(v) != TYPE_NONE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_peekint(WL_State *state, int off, long long *x)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth + off < state->stack_base_for_user || off >= 0)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth + off];
|
||||
if (type_of(v) != TYPE_INT)
|
||||
return 0;
|
||||
|
||||
*x = get_int(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_peekfloat(WL_State *state, int off, float *x)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth + off < state->stack_base_for_user || off >= 0)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth + off];
|
||||
if (type_of(v) != TYPE_FLOAT)
|
||||
return 0;
|
||||
|
||||
*x = get_float(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_peekstr(WL_State *state, int off, WL_String *str)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth + off < state->stack_base_for_user || off >= 0)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth + off];
|
||||
if (type_of(v) != TYPE_STRING)
|
||||
return 0;
|
||||
|
||||
String s = get_str(v);
|
||||
*str = (WL_String) { s.ptr, s.len };
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_popnone(WL_State *state)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth == state->stack_base_for_user)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth-1];
|
||||
if (type_of(v) != TYPE_NONE)
|
||||
return 0;
|
||||
|
||||
state->eval_depth--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_popint(WL_State *state, long long *x)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth == 0)
|
||||
if (state->eval_depth == state->stack_base_for_user)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth-1];
|
||||
@@ -961,14 +1118,14 @@ int WL_popint(WL_State *state, long long *x)
|
||||
*x = get_int(v);
|
||||
|
||||
state->eval_depth--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_popfloat(WL_State *state, float *x)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth == 0)
|
||||
if (state->eval_depth == state->stack_base_for_user)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth-1];
|
||||
@@ -978,14 +1135,14 @@ int WL_popfloat(WL_State *state, float *x)
|
||||
*x = get_float(v);
|
||||
|
||||
state->eval_depth--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_popstr(WL_State *state, char **str, int *len)
|
||||
int WL_popstr(WL_State *state, WL_String *str)
|
||||
{
|
||||
if (!in_syscall(state)) return 0;
|
||||
|
||||
if (state->eval_depth == 0)
|
||||
if (state->eval_depth == state->stack_base_for_user)
|
||||
return 0;
|
||||
|
||||
Value v = state->eval_stack[state->eval_depth-1];
|
||||
@@ -993,11 +1150,10 @@ int WL_popstr(WL_State *state, char **str, int *len)
|
||||
return 0;
|
||||
|
||||
String s = get_str(v);
|
||||
*str = s.ptr;
|
||||
*len = s.len;
|
||||
*str = (WL_String) { s.ptr, s.len };
|
||||
|
||||
state->eval_depth--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WL_popany(WL_State *state)
|
||||
@@ -1005,7 +1161,7 @@ int WL_popany(WL_State *state)
|
||||
if (!in_syscall(state))
|
||||
return 0;
|
||||
|
||||
if (state->eval_depth == 0)
|
||||
if (state->eval_depth == state->stack_base_for_user)
|
||||
return 0;
|
||||
|
||||
state->eval_depth--;
|
||||
@@ -1014,7 +1170,45 @@ int WL_popany(WL_State *state)
|
||||
|
||||
void WL_select(WL_State *state)
|
||||
{
|
||||
// TODO
|
||||
Value key = state->eval_stack[--state->eval_depth];
|
||||
Value set = state->eval_stack[state->eval_depth-1];
|
||||
Value val;
|
||||
|
||||
Type set_type = type_of(set);
|
||||
if (set_type == TYPE_ARRAY) {
|
||||
|
||||
Type key_type = type_of(key);
|
||||
if (key_type != TYPE_INT) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
|
||||
int64_t idx = get_int(key);
|
||||
Value *src = array_select(set, idx);
|
||||
if (src == NULL) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
val = *src;
|
||||
|
||||
} else if (set_type == TYPE_MAP) {
|
||||
|
||||
int ret = map_select(set, key, &val);
|
||||
if (ret < 0) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
assert(0); // TODO
|
||||
}
|
||||
|
||||
state->eval_stack[state->eval_depth++] = val;
|
||||
}
|
||||
|
||||
void WL_pushnone(WL_State *state)
|
||||
{
|
||||
if (!in_syscall(state)) return;
|
||||
|
||||
state->eval_stack[state->eval_depth++] = VALUE_NONE;
|
||||
}
|
||||
|
||||
void WL_pushint(WL_State *state, long long x)
|
||||
@@ -1045,11 +1239,11 @@ void WL_pushfloat(WL_State *state, float x)
|
||||
state->eval_stack[state->eval_depth++] = v;
|
||||
}
|
||||
|
||||
void WL_pushstr(WL_State *state, char *str, int len)
|
||||
void WL_pushstr(WL_State *state, WL_String str)
|
||||
{
|
||||
if (!in_syscall(state)) return;
|
||||
|
||||
Value v = make_str(state->a, (String) { str, len });
|
||||
Value v = make_str(state->a, (String) { str.ptr, str.len });
|
||||
if (v == VALUE_ERROR) {
|
||||
eval_report(state, "Out of memory");
|
||||
state->syscall_error = true;
|
||||
@@ -1091,5 +1285,49 @@ void WL_pushmap(WL_State *state, int cap)
|
||||
|
||||
void WL_insert(WL_State *state)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
Value key = state->eval_stack[--state->eval_depth];
|
||||
Value val = state->eval_stack[--state->eval_depth];
|
||||
Value set = state->eval_stack[state->eval_depth-1];
|
||||
|
||||
Type set_type = type_of(set);
|
||||
if (set_type == TYPE_ARRAY) {
|
||||
|
||||
Type key_type = type_of(key);
|
||||
if (key_type != TYPE_INT) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
|
||||
int64_t idx = get_int(key);
|
||||
Value *dst = array_select(set, idx);
|
||||
if (dst == NULL) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
*dst = val;
|
||||
|
||||
} else if (set_type == TYPE_MAP) {
|
||||
|
||||
int ret = map_insert(state->a, set, key, val);
|
||||
if (ret < 0) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
assert(0); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
void WL_append(WL_State *state)
|
||||
{
|
||||
Value val = state->eval_stack[--state->eval_depth];
|
||||
Value set = state->eval_stack[state->eval_depth-1];
|
||||
|
||||
if (type_of(set) != TYPE_ARRAY) {
|
||||
assert(0); // TODO
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_append(state->a, set, val) < 0) {
|
||||
assert(0); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -41,16 +41,23 @@ WL_State *WL_State_init (WL_Arena *a, WL_Program p, char *err, int errmax);
|
||||
void WL_State_free (WL_State *state);
|
||||
WL_Result WL_eval (WL_State *state);
|
||||
int WL_streq (WL_String a, char *b, int blen);
|
||||
int WL_peeknone (WL_State *state, int off);
|
||||
int WL_peekint (WL_State *state, int off, long long *x);
|
||||
int WL_peekfloat (WL_State *state, int off, float *x);
|
||||
int WL_peekstr (WL_State *state, int off, WL_String *str);
|
||||
int WL_popnone (WL_State *state);
|
||||
int WL_popint (WL_State *state, long long *x);
|
||||
int WL_popfloat (WL_State *state, float *x);
|
||||
int WL_popstr (WL_State *state, char **str, int *len);
|
||||
int WL_popstr (WL_State *state, WL_String *str);
|
||||
int WL_popany (WL_State *state);
|
||||
void WL_select (WL_State *state);
|
||||
void WL_pushnone (WL_State *state);
|
||||
void WL_pushint (WL_State *state, long long x);
|
||||
void WL_pushfloat (WL_State *state, float x);
|
||||
void WL_pushstr (WL_State *state, char *str, int len);
|
||||
void WL_pushstr (WL_State *state, WL_String str);
|
||||
void WL_pusharray (WL_State *state, int cap);
|
||||
void WL_pushmap (WL_State *state, int cap);
|
||||
void WL_insert (WL_State *state);
|
||||
void WL_append (WL_State *state);
|
||||
|
||||
#endif // WL_PUBLIC_INCLUDED
|
||||
|
||||
+46
-3
@@ -160,6 +160,7 @@ Value make_map(WL_Arena *a)
|
||||
m->count = 0;
|
||||
m->tail_count = 0;
|
||||
m->tail = &m->head;
|
||||
m->head.next = NULL;
|
||||
|
||||
return (Value) m | 7;
|
||||
}
|
||||
@@ -174,6 +175,7 @@ Value make_array(WL_Arena *a)
|
||||
v->count = 0;
|
||||
v->tail_count = 0;
|
||||
v->tail = &v->head;
|
||||
v->head.next = NULL;
|
||||
|
||||
return (Value) v | 7;
|
||||
}
|
||||
@@ -200,6 +202,27 @@ int map_select(Value map, Value key, Value *val)
|
||||
return -1;
|
||||
}
|
||||
|
||||
Value *map_select_by_index(Value map, int key)
|
||||
{
|
||||
MapValue *p = get_map(map);
|
||||
MapItems *batch = &p->head;
|
||||
int cursor = 0;
|
||||
while (batch) {
|
||||
|
||||
int num = ITEMS_PER_MAP_BATCH;
|
||||
if (batch->next == NULL)
|
||||
num = p->tail_count;
|
||||
|
||||
if (cursor <= key && key < cursor + num)
|
||||
return &batch->keys[key - cursor];
|
||||
|
||||
batch = batch->next;
|
||||
cursor += num;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int map_insert(WL_Arena *a, Value map, Value key, Value val)
|
||||
{
|
||||
MapValue *p = get_map(map);
|
||||
@@ -210,6 +233,8 @@ int map_insert(WL_Arena *a, Value map, Value key, Value val)
|
||||
return -1;
|
||||
|
||||
batch->next = NULL;
|
||||
if (p->tail)
|
||||
p->tail->next = batch;
|
||||
p->tail = batch;
|
||||
p->tail_count = 0;
|
||||
}
|
||||
@@ -252,6 +277,9 @@ int array_append(WL_Arena *a, Value array, Value val)
|
||||
return -1;
|
||||
|
||||
batch->next = NULL;
|
||||
|
||||
if (p->tail)
|
||||
p->tail->next = batch;
|
||||
p->tail = batch;
|
||||
p->tail_count = 0;
|
||||
}
|
||||
@@ -338,6 +366,19 @@ bool valgrt(Value a, Value b)
|
||||
return false;
|
||||
}
|
||||
|
||||
int value_length(Value v)
|
||||
{
|
||||
Type type = type_of(v);
|
||||
|
||||
if (type == TYPE_ARRAY)
|
||||
return get_array(v)->count;
|
||||
|
||||
if (type == TYPE_MAP)
|
||||
return get_map(v)->count;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *dst;
|
||||
int max;
|
||||
@@ -380,7 +421,7 @@ static void value_to_string_inner(Value v, ToStringContext *tostr)
|
||||
switch (type_of(v)) {
|
||||
|
||||
case TYPE_NONE:
|
||||
tostr_appends(tostr, S("none"));
|
||||
//tostr_appends(tostr, S("none"));
|
||||
break;
|
||||
|
||||
case TYPE_BOOL:
|
||||
@@ -411,12 +452,14 @@ static void value_to_string_inner(Value v, ToStringContext *tostr)
|
||||
value_to_string_inner(batch->keys[i], tostr);
|
||||
tostr_appends(tostr, S(": "));
|
||||
value_to_string_inner(batch->items[i], tostr);
|
||||
tostr_appends(tostr, S(", "));
|
||||
|
||||
if (batch->next != NULL || i+1 < num)
|
||||
tostr_appends(tostr, S(", "));
|
||||
}
|
||||
|
||||
batch = batch->next;
|
||||
}
|
||||
tostr_appends(tostr, S("}"));
|
||||
tostr_appends(tostr, S(" }"));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -34,11 +34,13 @@ Value make_str (WL_Arena *a, String x);
|
||||
Value make_map (WL_Arena *a);
|
||||
Value make_array (WL_Arena *a);
|
||||
int map_select (Value map, Value key, Value *val);
|
||||
Value* map_select_by_index(Value map, int key);
|
||||
int map_insert (WL_Arena *a, Value map, Value key, Value val);
|
||||
Value* array_select (Value array, int key);
|
||||
int array_append (WL_Arena *a, Value array, Value val);
|
||||
bool valeq (Value a, Value b);
|
||||
bool valgrt (Value a, Value b);
|
||||
int value_length (Value v);
|
||||
int value_to_string(Value v, char *dst, int max);
|
||||
|
||||
#endif // WL_VALUE_INCLUDED
|
||||
Reference in New Issue
Block a user