about summary refs log tree commit diff
path: root/boot/ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/ir.c')
-rw-r--r--boot/ir.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/boot/ir.c b/boot/ir.c
index 16811ed..164d9a4 100644
--- a/boot/ir.c
+++ b/boot/ir.c
@@ -249,6 +249,7 @@ enum Expression_Kind
     EXPRESSION_CAST,
     EXPRESSION_CONSTRUCT,
     EXPRESSION_INCREMENT_DECREMENT,
+    EXPRESSION_FUNCTION_REF,
 };
 
 struct Expression_Integer_Literal
@@ -310,6 +311,10 @@ struct Expression_Call
     struct Expression* subject;
     // arguments of call in written order, the inner slot decides final ordering.
     Array(struct Call_Argument) arguments;
+    // direct calls can emit a simple call without additional syntax,
+    // however indirect calls which have closed-over state have to call
+    // them taking into account the function pointer and the state first.
+    bool is_indirect;
 };
 
 struct Expression_Member
@@ -351,6 +356,14 @@ struct Expression_Increment_Decrement
     struct Expression* subject;
 };
 
+// reference to a known catskill function in a value context.
+struct Expression_Function_Ref
+{
+    Function_Id function_id;
+    // matching synthetic closure type for the function's signature.
+    Type_Id closure_type_id;
+};
+
 union Expression_Value
 {
     struct Expression_Integer_Literal integer_literal;
@@ -367,6 +380,7 @@ union Expression_Value
     struct Expression_Cast cast;
     struct Expression_Construct construct;
     struct Expression_Increment_Decrement increment_decrement;
+    struct Expression_Function_Ref function_ref;
 };
 
 struct Expression
@@ -402,6 +416,14 @@ struct Function
     Array(struct Param) params;
     bool variadic; // is last parameter variadic?
 
+    // matching fat-closure struct type for this function's signature.
+    // synthesized lazily on first reference in value context, or 0.
+    Type_Id closure_type_id;
+
+    // tree-side header which produced this function node.
+    // required for synthesizing the closure type after function is lowered.
+    struct Tree_Function_Header* ast_header;
+
     // first lowering pass only fills out the ast body and not the lowered body,
     // to collect all top-declarations.
     struct Tree_Block* ast_body;
@@ -647,11 +669,14 @@ ir_make_sizeof(struct Type_Ref target, struct Span span)
 }
 
 struct Expression*
-ir_make_call(struct Expression* subject, Array(struct Call_Argument) arguments, struct Span span)
+ir_make_call(
+    struct Expression* subject, Array(struct Call_Argument) arguments, bool is_indirect,
+    struct Span span)
 {
     union Expression_Value v = { 0 };
     v.call.subject = subject;
     v.call.arguments = arguments;
+    v.call.is_indirect = is_indirect;
     return expression_new(EXPRESSION_CALL, v, span);
 }
 
@@ -703,6 +728,15 @@ ir_make_increment_decrement(
     return expression_new(EXPRESSION_INCREMENT_DECREMENT, v, span);
 }
 
+struct Expression*
+ir_make_function_ref(Function_Id function_id, Type_Id closure_type_id, struct Span span)
+{
+    union Expression_Value v = { 0 };
+    v.function_ref.function_id = function_id;
+    v.function_ref.closure_type_id = closure_type_id;
+    return expression_new(EXPRESSION_FUNCTION_REF, v, span);
+}
+
 struct Type_Ref
 type_ref_bare(Type_Id type_id)
 {