aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/lower.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/boot/lower.c b/boot/lower.c
index aea49ce..f3c04d3 100644
--- a/boot/lower.c
+++ b/boot/lower.c
@@ -80,6 +80,9 @@ struct Lower_Context
// monotonic counter of synthesized types
uint synthetic_type_counter;
+ // monotonic counter for other synthetic objects (lambdas, temporaries).
+ uint synthetic_counter;
+
// stack of lexical scopes.
// all top-level declarations are stored are stored in the first unit scope.
Array(struct Scope) scope_stack;
@@ -241,6 +244,16 @@ lower_synthesize_type_name(struct Lower_Context* ctx)
return string_from_c_string(name_buf);
}
+// create a synthetic name for some non-type object, e.g. a lifted lambda.
+// `kind` is a short tag baked into the name for easier observability.
+struct String
+lower_synthesize_name(struct Lower_Context* ctx, const ascii* kind)
+{
+ ascii name_buf[64];
+ snprintf(name_buf, sizeof name_buf, "__cat_%s_%lu", kind, ctx->synthetic_counter++);
+ return string_from_c_string(name_buf);
+}
+
// look up an existing structural synthetic by hash, or build a fresh one.
// inner type references are interned, contributing to dependencies.
Type_Id
@@ -880,12 +893,31 @@ lower_expression(struct Lower_Context* ctx, struct Tree_Expression* tree_expr)
lower_emit_error_c(
ctx->unit, tree_expr->span, "type expression not allowed inside a function body");
return nil;
+ case TREE_EXPRESSION_FUNCTION: {
+ // anonymous function: lift it up as a synthetic function table entry,
+ // replace the expression with a name reference.
+ // TODO: should we have a better kind of reference here than a name?
+ // maybe a function reference somehow?
+ struct String name = lower_synthesize_name(ctx, "lambda");
+
+ // NOTE: we are allowed to register functions whenever we want,
+ // even while iterating over them, the pass will eventually get to them.
+ if (!lower_register_function_shell(ctx->unit, name, tree_expr->span)) return nil;
+
+ Function_Id id;
+ lower_function_lookup_by_name(ctx->unit, name, &id);
+
+ struct Function* fn = *array_at(struct Function*, &ctx->unit->functions.entries, id);
+ fn->synthetic = true;
+ lower_fill_function_signature(ctx, fn, tree_expr);
+
+ return lower_make_name_expression(name, tree_expr->span);
+ }
case TREE_EXPRESSION_SUBSCRIPT:
case TREE_EXPRESSION_MEMBER:
case TREE_EXPRESSION_INCREMENT_DECREMENT:
case TREE_EXPRESSION_TRY:
case TREE_EXPRESSION_MUST:
- case TREE_EXPRESSION_FUNCTION:
// TODO: implement these
default:
lower_emit_error_c(ctx->unit, tree_expr->span, "unimplemented: this expression kind");
@@ -1501,6 +1533,7 @@ lower_tree(struct Tree* tree, struct Source_File source, struct Unit* unit)
.unit = unit,
.source = source,
.synthetic_type_counter = 0,
+ .synthetic_counter = 0,
.scope_stack = array_new(struct Scope, 32),
};