aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-08-12 19:00:42 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-08-12 19:06:03 +0300
commit29c6d398d22d633425177400f34ab508260f02bf (patch)
tree1f51a32536cab07243d1fe42aba38f86a856f3d4
parent2157fdbaca0b80e488c4f77ad5c0d04b051175cf (diff)
downloadek-29c6d398d22d633425177400f34ab508260f02bf.tar.gz
ek-29c6d398d22d633425177400f34ab508260f02bf.zip
implement defer for most control flow
+ continue/break
-rw-r--r--src/actualize.c28
-rw-r--r--src/lower.c73
-rw-r--r--tests/generic_defer.ek3
3 files changed, 58 insertions, 46 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 3837d00..602325a 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -501,7 +501,7 @@ static int analyze(struct scope *scope, struct ast *tree)
if (actualize(&state, scope, node))
return -1;
- printf("//actualized:\n");
+ printf("\n//actualized:\n");
ast_dump(0, node);
}
@@ -693,6 +693,7 @@ static int _reset(struct ast *node, void *data)
ast_clear_flags(node, AST_FLAG_INIT | AST_FLAG_ACTUAL);
/* clear type info */
node->t = NULL;
+ node->scope = NULL;
return 0;
}
@@ -733,6 +734,9 @@ static int expand_type(struct ast *expd, struct ast *params, struct type *types)
struct act_state state = {0};
int ret = actualize(&state, p, expd);
assert(ret == 0);
+
+ printf("\n//expanded:\n");
+ ast_dump(0, expd);
return ret;
}
@@ -897,10 +901,6 @@ static int maybe_ufcs(struct act_state *state, struct scope *scope,
return 0;
struct type *ptypes = callable_ptypes(dot->t);
- if (!ptypes)
- /* no ufcs */
- return 0;
-
struct ast *expr = dot_expr(dot);
char *id = strdup(dot_id(dot));
call_expr(call) = gen_fetch(id, clone_type(expr->t), dot->loc);
@@ -909,20 +909,26 @@ static int maybe_ufcs(struct act_state *state, struct scope *scope,
struct ast *ref = NULL;
- if (ptypes->k == TYPE_PTR) {
+ if (!ptypes) {
+ ref = NULL;
+ }
+ else if (ptypes->k == TYPE_PTR) {
/* is ufcs expects reference to member, try to take address */
ref = gen_unop(AST_REF, expr, dot->loc);
ref->t = tgen_ptr(clone_type(expr->t), dot->loc);
ref->scope = scope;
- } else {
+ }
+ else {
/* otherwise, try to pass expr as is */
ref = expr;
}
- if (simplify_refderef(state, scope, ref))
+ if (ref && simplify_refderef(state, scope, ref))
return -1;
- call_args(call) = ast_prepend(call_args(call), ref);
+ if (ref)
+ call_args(call) = ast_prepend(call_args(call), ref);
+
return 0;
}
@@ -1626,6 +1632,10 @@ static int actualize_alias(struct act_state *state, struct scope *scope,
static int actualize_defer(struct act_state *state,
struct scope *scope, struct ast *node)
{
+ /** @todo this doesn't work for shadowed variables, as the scope might
+ * be set to the scope containing a shadowing variable, which means that
+ * when lower.c does a file_scope_find_*() it finds the shadowed
+ * variable first. */
struct ast *expr = defer_expr(node);
if (actualize(state, scope, expr))
return -1;
diff --git a/src/lower.c b/src/lower.c
index 18d0576..c239836 100644
--- a/src/lower.c
+++ b/src/lower.c
@@ -32,6 +32,8 @@ struct lower_state {
struct vec dealloc;
size_t deallocs;
+
+ struct vec procs;
};
static struct lower_state create_state()
@@ -41,6 +43,8 @@ static struct lower_state create_state()
state.bottom = vec_create(sizeof(char *));
state.out = vec_create(sizeof(char *));
state.dealloc = vec_create(sizeof(char *));
+ state.procs = vec_create(sizeof(struct ast *));
+
state.deallocs = 0;
state.uniq = 0;
return state;
@@ -57,6 +61,13 @@ static void destroy_state(struct lower_state *state)
vec_destroy(&state->bottom);
vec_destroy(&state->out);
vec_destroy(&state->dealloc);
+ vec_destroy(&state->procs);
+}
+
+static void add_proc(struct lower_state *s, struct ast *proc)
+{
+ assert(proc->k == AST_PROC_DEF);
+ vec_append(&s->procs, &proc);
}
static void add_dealloc(struct lower_state *s, char *dealloc)
@@ -190,6 +201,8 @@ static char *mangle(struct ast *id)
return mangle_scope(id, def->scope);
}
+static int lower_proc(struct ast *n);
+
typedef int (*visit_struct_t)(struct lower_state *s, struct ast *n, size_t o,
void *d);
static ssize_t visit_struct(struct lower_state *s, struct ast *def, size_t base,
@@ -520,6 +533,10 @@ static int lower_id(struct lower_state *s, struct ast *id,
/* this likely isn't enough and we need to add the & to most things we
* want to take the address of */
if (type->k == TYPE_CALLABLE) {
+ struct ast *def = file_scope_find_proc(id->scope, id->s);
+ assert(def);
+
+ add_proc(s, def);
char *o = m;
m = build_str("&%s", m);
free(o);
@@ -994,6 +1011,8 @@ static int lower_fetch(struct lower_state *s, struct ast *f,
struct ast *proc = scope_find_proc(def->scope, fetch_id(f));
assert(proc);
+ add_proc(s, proc);
+
char *name = mangle(proc);
char *fetch = build_str("&%s", name);
*retval = build_retval(REG_I27, fetch);
@@ -1219,6 +1238,10 @@ static int lower_label(struct lower_state *s, struct ast *n)
static int lower_statement(struct lower_state *s, struct ast *n)
{
struct retval retval = retval_create();
+ if (ast_flags(n, AST_FLAG_LOWERED))
+ return 0;
+
+ ast_set_flags(n, AST_FLAG_LOWERED);
int ret = 0;
switch (n->k) {
@@ -1253,6 +1276,8 @@ static int lower_proc(struct ast *n)
if (ast_flags(n, AST_FLAG_LOWERED))
return 0;
+ ast_set_flags(n, AST_FLAG_LOWERED);
+
struct lower_state state = create_state();
/* name */
@@ -1287,51 +1312,25 @@ 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))
+ foreach_vec(pi, state.procs) {
+ struct ast *proc = vect_at(struct ast*, state.procs, pi);
+ if (lower_proc(proc)) {
+ destroy_state(&state);
return -1;
+ }
}
-
- ast_set_flags(s, AST_FLAG_LOWERED);
+ destroy_state(&state);
return 0;
}
int lower(struct scope *root)
{
- /* go through all child scopes but only do actual work on file-scope
- * includes are allowed inside procs etc to make something only locally
- * visible */
- for (struct scope *c = root->children; c; c = c->next) {
- if (lower(c))
- return -1;
- }
-
- if (!scope_flags(root, SCOPE_FILE))
- return 0;
-
- foreach_visible(p, root->symbols) {
- assert(p->node);
- struct ast *node = p->node;
- if (node->k == AST_PROC_DEF && lower_proc(p->node))
- return -1;
- }
-
- 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;
+ struct ast *main = file_scope_find_proc(root, "main");
+ if (!main) {
+ error("no main");
+ return -1;
}
- return 0;
+ return lower_proc(main);
}
diff --git a/tests/generic_defer.ek b/tests/generic_defer.ek
index 11c099c..cb11154 100644
--- a/tests/generic_defer.ek
+++ b/tests/generic_defer.ek
@@ -13,5 +13,8 @@ typedef a[any T] {
main()
{
a![i27] a = a![i27]{.b = 10};
+ a.do_stuff();
+
a![i9] b = a![i9]{.b = 20 as i9};
+ b.do_stuff();
}