diff --git a/Makefile b/Makefile index 7302d81..24195cc 100644 --- a/Makefile +++ b/Makefile @@ -2,4 +2,4 @@ all: WL.c gcc WL.c main.c -o wl -Wall -Wextra -O0 -g3 WL.c: $(wildcard src/*.c src/*.h) - py amalg.py \ No newline at end of file + python amalg.py \ No newline at end of file diff --git a/WL.c b/WL.c index 0e65889..a75a240 100644 --- a/WL.c +++ b/WL.c @@ -4,7 +4,6 @@ // src/includes.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/includes.h" #ifndef WL_INCLUDES_INCLUDED #define WL_INCLUDES_INCLUDED @@ -35,7 +34,6 @@ // src/basic.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/basic.h" #ifndef WL_BASIC_INCLUDED #define WL_BASIC_INCLUDED @@ -83,7 +81,6 @@ bool grow_alloc(WL_Arena *a, char *p, int new_len); // src/basic.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/basic.c" #ifndef WL_AMALGAMATION #include "includes.h" @@ -178,7 +175,6 @@ bool grow_alloc(WL_Arena *a, char *p, int new_len) // src/file.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/file.h" #ifndef WL_FILE_INCLUDED #define WL_FILE_INCLUDED @@ -204,7 +200,6 @@ int file_read_all(String path, String *dst); // src/file.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/file.c" #ifndef WL_AMALGAMATION #include "includes.h" #include "file.h" @@ -324,7 +319,6 @@ int file_read_all(String path, String *dst) // src/parse.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/parse.h" #ifndef WL_PARSE_INCLUDED #define WL_PARSE_INCLUDED @@ -418,7 +412,6 @@ ParseResult parse(String src, WL_Arena *a, char *errbuf, int errmax); // src/parse.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/parse.c" #ifndef WL_AMALGAMATION #include "parse.h" @@ -2298,7 +2291,6 @@ ParseResult parse(String src, WL_Arena *a, char *errbuf, int errmax) // src/assemble.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/assemble.h" #ifndef WL_ASSEMBLE_INCLUDED #define WL_ASSEMBLE_INCLUDED @@ -2347,6 +2339,7 @@ enum { OPCODE_PRINT = 0x24, OPCODE_SYSVAR = 0x2C, OPCODE_SYSCALL = 0x2D, + OPCODE_FOR = 0x2E, }; typedef struct { @@ -2365,7 +2358,6 @@ AssembleResult assemble(Node *root, WL_Arena *arena, char *errbuf, int errmax); // src/assemble.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/assemble.c" #ifndef WL_AMALGAMATION #include "includes.h" @@ -2603,6 +2595,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)) @@ -2612,6 +2607,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)) @@ -3499,18 +3497,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; } @@ -3897,7 +3912,6 @@ char *print_instruction(char *p, char *data) // src/value.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/value.h" #ifndef WL_VALUE_INCLUDED #define WL_VALUE_INCLUDED @@ -3934,11 +3948,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 @@ -3947,7 +3963,6 @@ int value_to_string(Value v, char *dst, int max); // src/value.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/value.c" #ifndef WL_AMALGAMATION #include "value.h" @@ -4110,6 +4125,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; } @@ -4124,6 +4140,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; } @@ -4150,6 +4167,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); @@ -4160,6 +4198,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; } @@ -4202,6 +4242,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; } @@ -4288,6 +4331,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; @@ -4330,7 +4386,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: @@ -4361,12 +4417,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; @@ -4411,7 +4469,6 @@ int value_to_string(Value v, char *dst, int max) // src/eval.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/eval.h" #ifndef WL_EVAL_INCLUDED #define WL_EVAL_INCLUDED @@ -4428,7 +4485,6 @@ int eval(WL_Program p, WL_Arena *a, char *errbuf, int errmax); // src/eval.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/eval.c" #ifndef WL_AMALGAMATION #include "includes.h" @@ -4472,6 +4528,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, ...) @@ -5216,7 +5274,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; @@ -5224,7 +5283,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 { @@ -5249,6 +5309,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; @@ -5258,7 +5320,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; @@ -5317,7 +5444,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(""); } @@ -5326,6 +5452,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(""); } @@ -5378,11 +5516,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]; @@ -5392,14 +5605,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]; @@ -5409,14 +5622,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]; @@ -5424,11 +5637,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) @@ -5436,7 +5648,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--; @@ -5445,7 +5657,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) @@ -5476,11 +5726,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; @@ -5522,14 +5772,57 @@ 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 + } } //////////////////////////////////////////////////////////////////////////////////////// // src/public.c //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/public.c" #ifndef WL_AMALGAMATION #include "eval.h" diff --git a/WL.h b/WL.h index 5bee788..5e9d879 100644 --- a/WL.h +++ b/WL.h @@ -7,7 +7,6 @@ // src/public.h //////////////////////////////////////////////////////////////////////////////////////// -#line 1 "src/public.h" #ifndef WL_PUBLIC_INCLUDED #define WL_PUBLIC_INCLUDED @@ -51,17 +50,24 @@ 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 #endif // WL_AMALGAMATION diff --git a/amalg.py b/amalg.py index 14adebe..13fac58 100644 --- a/amalg.py +++ b/amalg.py @@ -13,7 +13,7 @@ class Amalgamator: self.out += "// " + file + "\n" self.out += "////////////////////////////////////////////////////////////////////////////////////////\n" self.out += "\n" - self.out += "#line 1 \"" + file + "\"\n" + # self.out += "#line 1 \"" + file + "\"\n" self.out += open(file).read() if len(self.out) > 0 and self.out[len(self.out)-1] != '\n': diff --git a/main.wl b/main.wl index ca88e76..cf913c4 100644 --- a/main.wl +++ b/main.wl @@ -1,2 +1,6 @@ +let set = {a: "G", b: "T", c: "K"} -$do_something(1, 2, 3) \ No newline at end of file +for item, i in set: { +
  • \item \i \set[item]
  • + "\n" +} diff --git a/src/assemble.c b/src/assemble.c index 746e1d2..441f73d 100644 --- a/src/assemble.c +++ b/src/assemble.c @@ -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; } diff --git a/src/assemble.h b/src/assemble.h index 982ecec..a8e76c8 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -46,6 +46,7 @@ enum { OPCODE_PRINT = 0x24, OPCODE_SYSVAR = 0x2C, OPCODE_SYSCALL = 0x2D, + OPCODE_FOR = 0x2E, }; typedef struct { diff --git a/src/eval.c b/src/eval.c index d857eff..dfdcbe8 100644 --- a/src/eval.c +++ b/src/eval.c @@ -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 -} \ No newline at end of file + 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 + } +} diff --git a/src/public.h b/src/public.h index 6cd983e..90c0d77 100644 --- a/src/public.h +++ b/src/public.h @@ -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 diff --git a/src/value.c b/src/value.c index 20baeaf..480df12 100644 --- a/src/value.c +++ b/src/value.c @@ -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; diff --git a/src/value.h b/src/value.h index 3038b27..c547f3a 100644 --- a/src/value.h +++ b/src/value.h @@ -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 \ No newline at end of file