diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-08-12 19:00:42 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-08-12 19:06:03 +0300 |
| commit | 29c6d398d22d633425177400f34ab508260f02bf (patch) | |
| tree | 1f51a32536cab07243d1fe42aba38f86a856f3d4 /src | |
| parent | 2157fdbaca0b80e488c4f77ad5c0d04b051175cf (diff) | |
| download | ek-29c6d398d22d633425177400f34ab508260f02bf.tar.gz ek-29c6d398d22d633425177400f34ab508260f02bf.zip | |
implement defer for most control flow
+ continue/break
Diffstat (limited to 'src')
| -rw-r--r-- | src/actualize.c | 28 | ||||
| -rw-r--r-- | src/lower.c | 73 |
2 files changed, 55 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); } |
