aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ek/ast.h7
-rw-r--r--src/actualize.c19
-rw-r--r--src/lower.c70
-rw-r--r--src/parser.y5
-rw-r--r--tests/nested_structs.ek17
-rw-r--r--tests/structs.ek6
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');
}