diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-12-29 00:07:16 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-12-29 00:07:16 +0200 |
| commit | 90b0d817fedfa5715b195e16da67fa6bdd67638e (patch) | |
| tree | de5c01884a434ffcc940be2e96474f188c95362c /src/lower.c | |
| parent | 0e0c41af58a0f4ec5a39ce77822de71e5523fcba (diff) | |
| download | fwd-90b0d817fedfa5715b195e16da67fa6bdd67638e.tar.gz fwd-90b0d817fedfa5715b195e16da67fa6bdd67638e.zip | |
work towards a simple integer vector implementationgnc
+ Hopefully shows that useful programs can be implemented with
the rules present
+ Still missing at least external functions with non-void returns
Diffstat (limited to 'src/lower.c')
| -rw-r--r-- | src/lower.c | 221 |
1 files changed, 210 insertions, 11 deletions
diff --git a/src/lower.c b/src/lower.c index e29365d..9689928 100644 --- a/src/lower.c +++ b/src/lower.c @@ -27,7 +27,11 @@ static inline void mangle(FILE *f, struct ast *id) { - assert(id->k == AST_PROC_DEF || id->k == AST_VAR_DEF || id->k == AST_ID); + assert(id->k == AST_STRUCT_DEF + || id->k == AST_PROC_DEF + || id->k == AST_VAR_DEF + || id->k == AST_ID); + assert(id->s && id->scope); fprintf(f, "%s_s%zu", id->s, id->scope->number); } @@ -150,6 +154,12 @@ static void add_defn(struct state *state, char *defn) string_vec_append(state->defns, defn); } +static bool type_lowered(struct ast *type) +{ + assert(type->k == AST_STRUCT_DEF); + return ast_flags(type, AST_FLAG_LOWERED); +} + static void add_type(struct state *state, char *type) { string_vec_append(state->types, type); @@ -160,8 +170,10 @@ static int lower_block(struct state *state, struct ast *block, bool last); static int lower_params(struct state *state, struct ast *params); static int lower_expr(struct state *state, struct ast *expr); static int lower_proc(struct state *state, struct ast *proc); +static int lower_type_def(struct state *state, struct ast *type); +static char *lower_type_str(struct state *state, struct scope *scope, struct type *type); -static void _type_str(FILE *f, struct type *type) +static int _type_str(FILE *f, struct state *state, struct scope *scope, struct type *type) { assert(type); switch (type->k) { @@ -201,14 +213,40 @@ static void _type_str(FILE *f, struct type *type) fprintf(f, "fwd_closure_t"); break; + case TYPE_PURE_CLOSURE: + fprintf(f, "fwd_closure_t"); + break; + + case TYPE_ID: { + struct ast *def = file_scope_find_type(scope, type_str(type)); + + if (!ast_flags(def, AST_FLAG_LOWERED)) + if (lower_type_def(state, def)) + return -1; + + char *name = mangle2(def); + fprintf(f, "%s", name); + free(name); + break; + } + + case TYPE_PTR: { + char *rest = lower_type_str(state, scope, tptr_base(type)); + fprintf(f, "%s*", rest); + free(rest); + break; + } + default: internal_error("unhandled type lowering for %s", type_str(type)); abort(); break; } + + return 0; } -static char *lower_type_str(struct type *type) +static char *lower_type_str(struct state *state, struct scope *scope, struct type *type) { assert(type); @@ -216,9 +254,15 @@ static char *lower_type_str(struct type *type) FILE *f = open_memstream(&type_buf, &type_len); assert(f); - _type_str(f, type); + int r = _type_str(f, state, scope, type); fclose(f); assert(type_buf); + + if (r) { + free(type_buf); + return NULL; + } + return type_buf; } @@ -243,7 +287,7 @@ static int lower_closure_call(struct state *state, struct ast *call, struct ast foreach_node(a, call_args(call)) { returning |= a->k == AST_CLOSURE; - char *type = lower_type_str(a->t); + char *type = lower_type_str(state, a->scope, a->t); fprintf(ctx, " %s a%zu;\n", type, idx); free(type); @@ -269,7 +313,7 @@ out: q, q); } else { - fprintf(state->code, "stack = %s_call(stack, %s_ctx);\n", + fprintf(state->code, "stack = %s(stack, %s_ctx);\n", q, q); } @@ -340,10 +384,26 @@ static int lower_comparison(struct state *state, struct ast *expr) fprintf(state->code, " <= "); break; + case AST_GE: + fprintf(state->code, " >= "); + break; + case AST_LT: fprintf(state->code, " < "); break; + case AST_GT: + fprintf(state->code, " > "); + break; + + case AST_EQ: + fprintf(state->code, " == "); + break; + + case AST_NE: + fprintf(state->code, " != "); + break; + default: internal_error("unhandled lowering for comparison %s", ast_str(expr->k)); abort(); @@ -366,8 +426,12 @@ static int lower_binop(struct state *state, struct ast *expr) fprintf(state->code, " + "); break; + case AST_MUL: + fprintf(state->code, " * "); + break; + default: - internal_error("unhandled comparison %s", ast_str(expr->k)); + internal_error("unhandled binop %s", ast_str(expr->k)); abort(); } @@ -406,6 +470,41 @@ static int lower_expr(struct state *state, struct ast *expr) fprintf(state->code, "%lld", (long long)int_val(expr)); break; } + + case AST_NIL: { + fprintf(state->code, "NULL"); + break; + } + + case AST_CONSTRUCT: { + char *name = lower_type_str(state, expr->scope, expr->t); + fprintf(state->code, "(%s){", name); + free(name); + + foreach_node(n, construct_members(expr)) { + fprintf(state->code, ".%s = ", construction_id(n)); + + if (lower_expr(state, construction_expr(n))) + return -1; + + fprintf(state->code, ", "); + } + fprintf(state->code, "}"); + break; + } + + case AST_AS: { + char *name = lower_type_str(state, expr->scope, expr->t); + fprintf(state->code, "(%s)(", name); + free(name); + + if (lower_expr(state, as_expr(expr))) + return -1; + + fprintf(state->code, ")"); + break; + } + default: internal_error("unhandled expr lowering: %s", ast_str(expr->k)); abort(); @@ -445,7 +544,7 @@ static int lower_call(struct state *state, struct ast *call, bool last) foreach_node(a, call_args(call)) { returning |= a->k == AST_CLOSURE; - char *type = lower_type_str(a->t); + char *type = lower_type_str(state, a->scope, a->t); fprintf(ctx, " %s a%zu;\n", type, idx); free(type); @@ -508,11 +607,72 @@ static int lower_if(struct state *state, struct ast *stmt, bool last) return lower_block(state, if_else(stmt), last); } +static int lower_explode(struct state *state, struct ast *stmt, bool last) +{ + /* not significant to us */ + (void)last; + + int u = uniq(state); + struct ast *expr = explode_expr(stmt); + + char *type = lower_type_str(state, expr->scope, expr->t); + + indent(state); + fprintf(state->code, "%s explode_%d = ", type, u); + free(type); + + if (lower_expr(state, expr)) + return -1; + + fprintf(state->code, ";\n"); + + foreach_node(node, explode_deconstruct(stmt)) { + struct ast *var = deconstruction_var(node); + + char *type = lower_type_str(state, var->scope, var->t); + char *name = mangle2(var); + + indent(state); + fprintf(state->code, "%s %s = explode_%d.%s;\n", + type, name, u, deconstruction_id(node)); + + free(type); + free(name); + } + + return 0; +} + +static int lower_let(struct state *state, struct ast *stmt, bool last) +{ + /* not relevant */ + (void)last; + + struct ast *var = let_var(stmt); + char *type = lower_type_str(state, var->scope, var->t); + char *name = mangle2(var); + + indent(state); + fprintf(state->code, "%s %s = ", type, name); + + free(type); + free(name); + + if (lower_expr(state, let_expr(stmt))) + return -1; + + fprintf(state->code, ";\n"); + return 0; +} + static int lower_stmt(struct state *state, struct ast *stmt, bool last) { switch (stmt->k) { case AST_CALL: return lower_call(state, stmt, last); case AST_IF: return lower_if(state, stmt, last); + case AST_EXPLODE: return lower_explode(state, stmt, last); + case AST_LET: return lower_let(state, stmt, last); + case AST_EMPTY: break; default: internal_error("unhandled statement kind %s", ast_str(stmt->k)); abort(); @@ -548,7 +708,7 @@ static int lower_block(struct state *state, struct ast *block, bool last) static int lower_param(struct state *state, struct ast *param) { - char *type = lower_type_str(param->t); + char *type = lower_type_str(state, param->scope, param->t); char *name = mangle2(param); fprintf(state->ctx, " %s %s;\n", type, name); @@ -644,7 +804,7 @@ static int lower_extern_proc(struct state *state, struct ast *proc) idx + 1, fwd_typeid(p->t), fwd_typeparam(p->t), idx); - char *type_str = lower_type_str(p->t); + char *type_str = lower_type_str(state, p->scope, p->t); fprintf(new_state.ctx, " %s a%zu;\n", type_str, idx); free(type_str); idx++; @@ -679,7 +839,7 @@ static int lower_extern_proc(struct state *state, struct ast *proc) static int lower_param_copy(struct state *state, struct ast *param, FILE *f, size_t idx) { - char *type = lower_type_str(param->t); + char *type = lower_type_str(state, param->scope, param->t); fprintf(f, " %s a%zu;\n", type, idx); free(type); @@ -716,6 +876,45 @@ static int lower_param_copies(struct state *state, struct ast *params) return 0; } +static int lower_type_def(struct state *state, struct ast *type) +{ + assert(type->k == AST_STRUCT_DEF); + if (type_lowered(type)) + return 0; + + ast_flags(type, AST_FLAG_LOWERED); + + char *decl_buf = NULL; size_t decl_len = 0; + FILE *decl = open_memstream(&decl_buf, &decl_len); + assert(decl); + + char *name = mangle2(type); + fprintf(decl, "struct %s;\n", name); + fclose(decl); + + char *defn_buf = NULL; size_t defn_len = 0; + FILE *defn = open_memstream(&defn_buf, &defn_len); + assert(defn); + + fprintf(defn, "typedef struct %s {\n", name); + + foreach_node(n, struct_body(type)) { + assert(n->k == AST_VAR_DEF); + char *t = lower_type_str(state, n->scope, var_type(n)); + fprintf(defn, "\t%s %s;\n", t, var_id(n)); + free(t); + } + + fprintf(defn, "} %s;\n", name); + + fclose(defn); + free(name); + + add_type(state, decl_buf); + add_type(state, defn_buf); + return 0; +} + static int lower_proc(struct state *state, struct ast *proc) { if (proc_lowered(state, proc)) |
