@@ -8,16 +8,104 @@ use crate::{
88 function:: { FuncMeta , FunctionBody , HirFunction , Parameters } ,
99 stmt:: HirPattern ,
1010 } ,
11- node_interner:: { DefinitionKind , FuncId , FunctionModifiers , TypeId } ,
11+ node_interner:: { DefinitionKind , ExprId , FunctionModifiers , GlobalValue , TypeId } ,
1212 token:: Attributes ,
1313 DataType , Shared , Type ,
1414} ;
1515
1616use super :: Elaborator ;
1717
1818impl Elaborator < ' _ > {
19+ /// Defines the value of an enum variant that we resolve an enum
20+ /// variant expression to. E.g. `Foo::Bar` in `Foo::Bar(baz)`.
21+ ///
22+ /// If the variant requires arguments we should define a function,
23+ /// otherwise we define a polymorphic global containing the tag value.
1924 #[ allow( clippy:: too_many_arguments) ]
20- pub ( super ) fn define_enum_variant_function (
25+ pub ( super ) fn define_enum_variant_constructor (
26+ & mut self ,
27+ enum_ : & NoirEnumeration ,
28+ type_id : TypeId ,
29+ variant : & EnumVariant ,
30+ variant_arg_types : Option < Vec < Type > > ,
31+ variant_index : usize ,
32+ datatype : & Shared < DataType > ,
33+ self_type : & Type ,
34+ self_type_unresolved : UnresolvedType ,
35+ ) {
36+ match variant_arg_types {
37+ Some ( args) => self . define_enum_variant_function (
38+ enum_,
39+ type_id,
40+ variant,
41+ args,
42+ variant_index,
43+ datatype,
44+ self_type,
45+ self_type_unresolved,
46+ ) ,
47+ None => self . define_enum_variant_global (
48+ enum_,
49+ type_id,
50+ variant,
51+ variant_index,
52+ datatype,
53+ self_type,
54+ ) ,
55+ }
56+ }
57+
58+ #[ allow( clippy:: too_many_arguments) ]
59+ fn define_enum_variant_global (
60+ & mut self ,
61+ enum_ : & NoirEnumeration ,
62+ type_id : TypeId ,
63+ variant : & EnumVariant ,
64+ variant_index : usize ,
65+ datatype : & Shared < DataType > ,
66+ self_type : & Type ,
67+ ) {
68+ let name = & variant. name ;
69+ let location = Location :: new ( variant. name . span ( ) , self . file ) ;
70+
71+ let global_id = self . interner . push_empty_global (
72+ name. clone ( ) ,
73+ type_id. local_module_id ( ) ,
74+ type_id. krate ( ) ,
75+ self . file ,
76+ Vec :: new ( ) ,
77+ false ,
78+ false ,
79+ ) ;
80+
81+ let mut typ = self_type. clone ( ) ;
82+ if !datatype. borrow ( ) . generics . is_empty ( ) {
83+ let typevars = vecmap ( & datatype. borrow ( ) . generics , |generic| generic. type_var . clone ( ) ) ;
84+ typ = Type :: Forall ( typevars, Box :: new ( typ) ) ;
85+ }
86+
87+ let definition_id = self . interner . get_global ( global_id) . definition_id ;
88+ self . interner . push_definition_type ( definition_id, typ. clone ( ) ) ;
89+
90+ let no_parameters = Parameters ( Vec :: new ( ) ) ;
91+ let global_body =
92+ self . make_enum_variant_constructor ( datatype, variant_index, & no_parameters, location) ;
93+ let let_statement = crate :: hir_def:: stmt:: HirStatement :: Expression ( global_body) ;
94+
95+ let statement_id = self . interner . get_global ( global_id) . let_statement ;
96+ self . interner . replace_statement ( statement_id, let_statement) ;
97+
98+ self . interner . get_global_mut ( global_id) . value = GlobalValue :: Resolved (
99+ crate :: hir:: comptime:: Value :: Enum ( variant_index, Vec :: new ( ) , typ) ,
100+ ) ;
101+
102+ Self :: get_module_mut ( self . def_maps , type_id. module_id ( ) )
103+ . declare_global ( name. clone ( ) , enum_. visibility , global_id)
104+ . ok ( ) ;
105+ }
106+
107+ #[ allow( clippy:: too_many_arguments) ]
108+ fn define_enum_variant_function (
21109 & mut self ,
22110 enum_ : & NoirEnumeration ,
23111 type_id : TypeId ,
@@ -48,7 +136,10 @@ impl Elaborator<'_> {
48136
49137 let hir_name = HirIdent :: non_trait_method ( definition_id, location) ;
50138 let parameters = self . make_enum_variant_parameters ( variant_arg_types, location) ;
51- self . push_enum_variant_function_body ( id, datatype, variant_index, & parameters, location) ;
139+
140+ let body =
141+ self . make_enum_variant_constructor ( datatype, variant_index, & parameters, location) ;
142+ self . interner . update_fn ( id, HirFunction :: unchecked_from_expr ( body) ) ;
52143
53144 let function_type =
54145 datatype_ref. variant_function_type_with_forall ( variant_index, datatype. clone ( ) ) ;
@@ -106,14 +197,13 @@ impl Elaborator<'_> {
106197 // }
107198 // }
108199 // ```
109- fn push_enum_variant_function_body (
200+ fn make_enum_variant_constructor (
110201 & mut self ,
111- id : FuncId ,
112202 self_type : & Shared < DataType > ,
113203 variant_index : usize ,
114204 parameters : & Parameters ,
115205 location : Location ,
116- ) {
206+ ) -> ExprId {
117207 // Each parameter of the enum variant function is used as a parameter of the enum
118208 // constructor expression
119209 let arguments = vecmap ( & parameters. 0 , |( pattern, typ, _) | match pattern {
@@ -126,18 +216,18 @@ impl Elaborator<'_> {
126216 _ => unreachable ! ( ) ,
127217 } ) ;
128218
129- let enum_generics = self_type. borrow ( ) . generic_types ( ) ;
130- let construct_variant = HirExpression :: EnumConstructor ( HirEnumConstructorExpression {
219+ let constructor = HirExpression :: EnumConstructor ( HirEnumConstructorExpression {
131220 r#type : self_type. clone ( ) ,
132221 arguments,
133222 variant_index,
134223 } ) ;
135- let body = self . interner . push_expr ( construct_variant) ;
136- self . interner . update_fn ( id, HirFunction :: unchecked_from_expr ( body) ) ;
137224
225+ let body = self . interner . push_expr ( constructor) ;
226+ let enum_generics = self_type. borrow ( ) . generic_types ( ) ;
138227 let typ = Type :: DataType ( self_type. clone ( ) , enum_generics) ;
139228 self . interner . push_expr_type ( body, typ) ;
140229 self . interner . push_expr_location ( body, location. span , location. file ) ;
230+ body
141231 }
142232
143233 fn make_enum_variant_parameters (
0 commit comments