diff options
| -rw-r--r-- | include/ek/ast.h | 7 | ||||
| -rw-r--r-- | src/actualize.c | 19 | ||||
| -rw-r--r-- | src/lower.c | 70 | ||||
| -rw-r--r-- | src/parser.y | 5 | ||||
| -rw-r--r-- | tests/nested_structs.ek | 17 | ||||
| -rw-r--r-- | tests/structs.ek | 6 |
6 files changed, 75 insertions, 49 deletions
diff --git a/include/ek/ast.h b/include/ek/ast.h index 5156b1d..62a0901 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -166,10 +166,8 @@ enum ast_flags { AST_FLAG_CONST = (1 << 1), /** External definition. Disables generic support. */ AST_FLAG_EXTERN = (1 << 2), - /** Variadic procedures and macros. */ + /** Variadic macros. */ AST_FLAG_VARIADIC = (1 << 3), - /** Delayed execution. Mainly \c do loops. */ - AST_FLAG_DELAYED = (1 << 4), /** Public node, should be propagated to parent scopes. */ AST_FLAG_PUBLIC = (1 << 5), /** @@ -188,12 +186,11 @@ enum ast_flags { AST_FLAG_INIT = (1 << 10), /** Whether a struct/union initialization is index or name based. */ AST_FLAG_MEMBER = (1 << 11), - /** AST node has several owners, requires special destruction handling. */ - AST_FLAG_SHARED = (1 << 12), /** Struct/union is generic. */ AST_FLAG_GENERIC = (1 << 13), AST_FLAG_NOMANGLE = (1 << 14), AST_FLAG_DOEXPR = (1 << 15), + AST_FLAG_LOWERED = (1 << 16), }; struct ast; diff --git a/src/actualize.c b/src/actualize.c index 7bb4e55..0c9d09e 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -2167,6 +2167,7 @@ static int actualize_dot(struct act_state *state, id); if (exists) { assert(exists->t); + exists->uses++; set_type(node, exists->t); return 0; } @@ -2234,18 +2235,15 @@ static int actualize_init(struct act_state *state, struct init_helper arg = vect_at(struct init_helper, init_args, ai); - struct init_helper mem = {0}; - foreach_vec(mi, struct_members) { - mem = vect_at(struct init_helper, struct_members, mi); - if (same_id(mem.id, arg.id)) - goto ok; - } + struct init_helper mem = vect_at(struct init_helper, struct_members, + ai); - semantic_error(scope->fctx, arg.n, "unknown argument %s", - arg.id); - goto err; + /* not the best error message but works for now */ + if (!same_id(arg.id, mem.id)) { + semantic_error(scope->fctx, node, "malformed init"); + goto err; + } -ok: if (!types_match(arg.n->t, mem.n->t)) { type_mismatch(scope, "init type mismatch", arg.n, arg.n->t, mem.n->t); @@ -2344,6 +2342,7 @@ static int actualize_fetch(struct act_state *state, struct scope *scope, return -1; } + member->uses++; set_type(fetch, member->t); return 0; } diff --git a/src/lower.c b/src/lower.c index 1ce91a4..58ffe7a 100644 --- a/src/lower.c +++ b/src/lower.c @@ -173,40 +173,19 @@ char *build_str(const char *fmt, ...) { return buf; } -static size_t get_scope_number(struct ast *id) +static char *mangle_scope(struct ast *id, struct scope *s) { - /** @todo this mirrors what's in actualize.c:actualize_id, same comments - * apply */ - struct ast *def = file_scope_find_var(id->scope, id->s); - if (def) - return def->scope->number; - - def = file_scope_find_proc(id->scope, id->s); - if (def) - return def->scope->number; - - return 0; + return build_str("%s_s%zi", id->s, s->number); } -static char *mangle_idx(struct ast *id, size_t idx) +static char *mangle(struct ast *id) { - assert(id->scope); - assert(id->s); - char *name = id->s; - /* oh wait, I need to do a variable lookup on the ID, not use the ID's - * scope number, duh */ struct ast *def = file_scope_find_symbol(id->scope, name); if (ast_flags(def, AST_FLAG_NOMANGLE)) return strdup(name); - size_t number = get_scope_number(def); - return build_str("%s_s%zif%zi", name, number, idx); -} - -static char *mangle(struct ast *id) -{ - return mangle_idx(id, 0); + return mangle_scope(id, def->scope); } typedef int (*visit_struct_t)(struct lower_state *s, struct ast *n, size_t o, @@ -869,7 +848,8 @@ static void lower_struct_retval(struct lower_state *s, struct type *rtype, static void lower_simple_retval(struct lower_state *s, struct type *rtype, struct retval *retval) { - char *name = build_str("(rv_%zd);\n", s->uniq++); + char *name = build_str("rv_%zd", s->uniq++); + printf("(%s);\n", name); *retval = build_retval(is_small_type(rtype) ? REG_I9 : REG_I27, name); } @@ -980,8 +960,17 @@ static int lower_fetch(struct lower_state *s, struct ast *f, * specific function from a struct */ assert(f->k == AST_FETCH); assert(f->t->k == TYPE_CALLABLE); - char *name = mangle(f); - *retval = build_retval(REG_I27, name); + + struct ast *def = (fetch_type(f))->d; + assert(def); + + struct ast *proc = scope_find_proc(def->scope, fetch_id(f)); + assert(proc); + + char *name = mangle(proc); + char *fetch = build_str("&%s", name); + *retval = build_retval(REG_I27, fetch); + free(name); return 0; } @@ -1178,6 +1167,9 @@ static int lower_proc(struct ast *n) if (!proc_body(n)) return 0; + if (ast_flags(n, AST_FLAG_LOWERED)) + return 0; + struct lower_state state = create_state(); /* name */ @@ -1213,6 +1205,21 @@ static int lower_proc(struct ast *n) printf("}\n"); destroy_state(&state); + ast_set_flags(n, AST_FLAG_LOWERED); + return 0; +} + +static int lower_struct(struct ast *s) +{ + if (ast_flags(s, AST_FLAG_LOWERED)) + return 0; + + foreach_node(n, struct_body(s)) { + if (n->k == AST_PROC_DEF && lower_proc(n)) + return -1; + } + + ast_set_flags(s, AST_FLAG_LOWERED); return 0; } @@ -1234,8 +1241,13 @@ int lower(struct scope *root) struct ast *node = p->node; if (node->k == AST_PROC_DEF && lower_proc(p->node)) return -1; + } - /** @todo variables, structs, etc. */ + foreach_visible(p, root->types) { + assert(p->node); + struct ast *node = p->node; + if (node->k == AST_STRUCT_DEF && lower_struct(p->node)) + return -1; } return 0; diff --git a/src/parser.y b/src/parser.y index b120e1b..8cb51cb 100644 --- a/src/parser.y +++ b/src/parser.y @@ -421,10 +421,7 @@ while : "while" expr body { $$ = gen_while($2, $3, src_loc(@$)); } do_while - : "do" body "while" expr ";" { - $$ = gen_while($2, $4, src_loc(@$)); - ast_set_flags($$, AST_FLAG_DELAYED); - } + : "do" body "while" expr ";" { $$ = gen_do_while($2, $4, src_loc(@$)); } goto : "goto" ID { $$ = gen_goto($[ID], NULL, src_loc(@$)); } diff --git a/tests/nested_structs.ek b/tests/nested_structs.ek new file mode 100644 index 0000000..1429a77 --- /dev/null +++ b/tests/nested_structs.ek @@ -0,0 +1,17 @@ +typedef i27 {} +typedef i9 {} + +typedef a { + i27 a; + i27 b; +} + +typedef b { + a a; + i27 b; +} + +main() +{ + mut p = b!{.a = a!{.a = 1, .b = 2}, .b = 3}; +} diff --git a/tests/structs.ek b/tests/structs.ek index 22cce71..3e64b94 100644 --- a/tests/structs.ek +++ b/tests/structs.ek @@ -11,8 +11,12 @@ typedef int_pair { } } +extern _putchar(i9 c); + main() { - mut p = int_pair!{.a = 9, .b = 10}; + mut p = int_pair!{.a = 1, .b = 2}; i27 s = p.sum(); + _putchar('0' + s as i9); + _putchar('\n'); } |
