@@ -20,6 +20,10 @@ pub const ExprId = enum(u32) { _ };
2020pub const PatId = enum (u32 ) { _ };
2121/// Identifier for a definition in Monotype IR.
2222pub const DefId = enum (u32 ) { _ };
23+ /// Identifier for a nested definition in Monotype IR.
24+ pub const NestedDefId = enum (u32 ) { _ };
25+ /// Identifier for a function specialization in Monotype IR.
26+ pub const FnId = enum (u32 ) { _ };
2327/// Identifier for a local binding in Monotype IR.
2428pub const LocalId = enum (u32 ) { _ };
2529/// Identifier assigned by Monotype lifting when this storage is consumed.
@@ -82,6 +86,11 @@ pub const FnTemplate = struct {
8286 mono_fn_ty : Type.TypeId ,
8387};
8488
89+ /// Monotype function-specialization metadata.
90+ pub const Fn = struct {
91+ source : FnTemplate ,
92+ };
93+
8594/// Compare the fields that make two function templates identical for Monotype.
8695pub fn fnTemplateIdentityEql (lhs : FnTemplate , rhs : FnTemplate ) bool {
8796 return std .meta .eql (lhs .fn_def , rhs .fn_def ) and
@@ -181,9 +190,9 @@ pub const TagExpr = struct {
181190
182191/// Lambda expression before lifting.
183192pub const LambdaExpr = struct {
193+ fn_id : FnId ,
184194 args : Span (TypedLocal ),
185195 body : ExprId ,
186- source : FnTemplate ,
187196};
188197
189198/// Call through a function value before lambda solving.
@@ -194,7 +203,7 @@ pub const CallValue = struct {
194203
195204/// Direct call target before or after Monotype lifting.
196205pub const ProcCallee = union (enum ) {
197- template : FnTemplate ,
206+ func : FnId ,
198207 lifted : LiftedFnId ,
199208};
200209
@@ -267,7 +276,7 @@ pub const ExprData = union(enum) {
267276 },
268277 lambda : LambdaExpr ,
269278 def_ref : DefId ,
270- fn_def : FnTemplate ,
279+ fn_def : FnId ,
271280 fn_ref : LiftedFnId ,
272281 call_value : CallValue ,
273282 call_proc : CallProc ,
@@ -377,6 +386,7 @@ pub const Stmt = union(enum) {
377386pub const Def = struct {
378387 symbol : Common.Symbol ,
379388 fn_def : ? FnTemplate = null ,
389+ fn_id : ? FnId = null ,
380390 args : Span (TypedLocal ),
381391 body : FnBody ,
382392 ret : Type.TypeId ,
@@ -392,6 +402,7 @@ pub const FnBody = union(enum) {
392402pub const NestedDef = struct {
393403 symbol : Common.Symbol ,
394404 fn_def : FnTemplate ,
405+ fn_id : FnId ,
395406 args : Span (TypedLocal ),
396407 body : ExprId ,
397408 ret : Type.TypeId ,
@@ -425,6 +436,7 @@ pub const Program = struct {
425436 names : names.NameStore ,
426437 next_symbol : u32 ,
427438 types : Type.Store ,
439+ fns : std .ArrayList (Fn ),
428440 defs : std .ArrayList (Def ),
429441 nested_defs : std .ArrayList (NestedDef ),
430442 exprs : std .ArrayList (Expr ),
@@ -465,6 +477,7 @@ pub const Program = struct {
465477 .names = names .NameStore .init (allocator ),
466478 .next_symbol = 0 ,
467479 .types = Type .Store .init (allocator ),
480+ .fns = .empty ,
468481 .defs = .empty ,
469482 .nested_defs = .empty ,
470483 .exprs = .empty ,
@@ -521,10 +534,23 @@ pub const Program = struct {
521534 self .exprs .deinit (self .allocator );
522535 self .nested_defs .deinit (self .allocator );
523536 self .defs .deinit (self .allocator );
537+ self .fns .deinit (self .allocator );
524538 self .types .deinit ();
525539 self .names .deinit ();
526540 }
527541
542+ pub fn addFn (self : * Program , source : FnTemplate ) std.mem.Allocator.Error ! FnId {
543+ const id : FnId = @enumFromInt (@as (u32 , @intCast (self .fns .items .len )));
544+ try self .fns .append (self .allocator , .{ .source = source });
545+ return id ;
546+ }
547+
548+ pub fn fnSource (self : * const Program , id : FnId ) FnTemplate {
549+ const raw = @intFromEnum (id );
550+ if (raw >= self .fns .items .len ) Common .invariant ("Monotype function id referenced a missing specialization" );
551+ return self .fns .items [raw ].source ;
552+ }
553+
528554 pub fn addExpr (self : * Program , expr : Expr ) std.mem.Allocator.Error ! ExprId {
529555 const id : ExprId = @enumFromInt (@as (u32 , @intCast (self .exprs .items .len )));
530556 try self .exprs .append (self .allocator , expr );
@@ -632,6 +658,15 @@ pub const Program = struct {
632658 return self .local_names .items [@intFromEnum (id )];
633659 }
634660
661+ pub fn setLocalType (self : * Program , id : LocalId , ty : Type.TypeId ) void {
662+ self .locals .items [@intFromEnum (id )].ty = ty ;
663+ for (self .typed_locals .items ) | * typed_local | {
664+ if (typed_local .local == id ) {
665+ typed_local .ty = ty ;
666+ }
667+ }
668+ }
669+
635670 pub fn addExprSpan (self : * Program , ids : []const ExprId ) std.mem.Allocator.Error ! Span (ExprId ) {
636671 const start : u32 = @intCast (self .expr_ids .items .len );
637672 try self .expr_ids .appendSlice (self .allocator , ids );
@@ -646,7 +681,11 @@ pub const Program = struct {
646681
647682 pub fn addTypedLocalSpan (self : * Program , values : []const TypedLocal ) std.mem.Allocator.Error ! Span (TypedLocal ) {
648683 const start : u32 = @intCast (self .typed_locals .items .len );
649- try self .typed_locals .appendSlice (self .allocator , values );
684+ try self .typed_locals .ensureUnusedCapacity (self .allocator , values .len );
685+ for (values ) | value | {
686+ const local_ty = self .locals .items [@intFromEnum (value .local )].ty ;
687+ self .typed_locals .appendAssumeCapacity (.{ .local = value .local , .ty = local_ty });
688+ }
650689 return .{ .start = start , .len = @intCast (values .len ) };
651690 }
652691
0 commit comments