11use anyhow:: bail;
22
3- use crate :: types:: { Definition , Identifier , TypeInfo } ;
3+ use crate :: types:: { Definition , FunctionDefinition , Identifier , TypeInfo } ;
44#[ allow( clippy:: all, unused_imports, dead_code) ]
55use crate :: types:: {
66 Expression , Literal , Location , OperatorKind , SimpleType , SourceFile , Type , TypeArray ,
77} ;
8- use crate :: { arena:: Arena , types:: GenericType } ;
98use std:: collections:: HashMap ;
109use std:: rc:: Rc ;
1110
@@ -24,7 +23,7 @@ struct SymbolTable {
2423}
2524
2625impl SymbolTable {
27- pub fn new ( ) -> Self {
26+ fn new ( ) -> Self {
2827 let mut table = SymbolTable {
2928 types : HashMap :: default ( ) ,
3029 functions : HashMap :: default ( ) ,
@@ -63,7 +62,27 @@ impl SymbolTable {
6362 table
6463 }
6564
66- fn register_type ( & mut self , name : String , type_params : Vec < TypeInfo > ) -> anyhow:: Result < ( ) > {
65+ fn push_scope ( & mut self ) {
66+ self . variables . push ( HashMap :: new ( ) ) ;
67+ }
68+
69+ fn pop_scope ( & mut self ) {
70+ self . variables . pop ( ) ;
71+ }
72+
73+ fn push_variable_to_scope ( & mut self , name : String , var_type : Type ) -> anyhow:: Result < ( ) > {
74+ if let Some ( scope) = self . variables . last_mut ( ) {
75+ if scope. contains_key ( & name) {
76+ bail ! ( "Variable `{name}` already declared in this scope" ) ;
77+ }
78+ scope. insert ( name, var_type) ;
79+ Ok ( ( ) )
80+ } else {
81+ bail ! ( "No active scope to push variables" . to_string( ) )
82+ }
83+ }
84+
85+ fn register_type ( & mut self , name : String , type_params : Vec < String > ) -> anyhow:: Result < ( ) > {
6786 if self . types . contains_key ( & name) {
6887 bail ! ( "Type `{name}` is already defined" )
6988 }
@@ -80,7 +99,7 @@ impl SymbolTable {
8099 return_type : Type ,
81100 ) -> Result < ( ) , String > {
82101 if self . functions . contains_key ( & name) {
83- return Err ( format ! ( "Function `{}` is already defined" , name ) ) ;
102+ return Err ( format ! ( "Function `{name }` is already defined" ) ) ;
84103 }
85104 self . functions . insert (
86105 name. clone ( ) ,
@@ -119,6 +138,14 @@ impl TypeChecker {
119138 if !self . errors . is_empty ( ) {
120139 bail ! ( std:: mem:: take( & mut self . errors) . join( "; " ) ) //TODO: handle it better
121140 }
141+ for source_file in program {
142+ for function_definition in & mut source_file. function_definitions ( ) {
143+ self . infer_variables ( function_definition. clone ( ) ) ;
144+ }
145+ }
146+ if !self . errors . is_empty ( ) {
147+ bail ! ( std:: mem:: take( & mut self . errors) . join( "; " ) ) //TODO: handle it better
148+ }
122149 Ok ( ( ) )
123150 }
124151
@@ -131,13 +158,7 @@ impl TypeChecker {
131158 let type_params = generic_type
132159 . parameters
133160 . iter ( )
134- . map ( |param| {
135- if let Type :: Generic ( generic_param) = param {
136- Self :: construct_generic_type_info ( generic_param. clone ( ) )
137- } else {
138- panic ! ( "Expected a generic type parameter" )
139- }
140- } )
161+ . map ( |param| param. name ( ) )
141162 . collect ( ) ;
142163 self . symbol_table
143164 . register_type ( type_definition. name ( ) , type_params)
@@ -197,42 +218,55 @@ impl TypeChecker {
197218 }
198219 }
199220
200- fn construct_generic_type_info ( generic_type_definition : Rc < GenericType > ) -> TypeInfo {
201- Self :: construct_type_info ( generic_type_definition, vec ! [ ] )
202- }
203-
204- #[ allow( clippy:: needless_pass_by_value) ]
205- fn construct_type_info (
206- generic_type_definition : Rc < GenericType > ,
207- type_params : Vec < TypeInfo > ,
208- ) -> TypeInfo {
209- let name = generic_type_definition. base . name ( ) ;
210- let mut type_info = TypeInfo { name, type_params } ;
211- for param in & generic_type_definition. parameters {
212- if let Type :: Generic ( generic_param) = param {
213- let param_info = Self :: construct_generic_type_info ( generic_param. clone ( ) ) ;
214- type_info. type_params . push ( param_info) ;
215- }
216- }
217- type_info
218- }
219-
220- //TODO continue implementing this function
221221 fn collect_function_and_constant_definitions ( & mut self , program : & mut Vec < SourceFile > ) {
222222 for sf in program {
223223 for definition in & sf. definitions {
224224 match definition {
225225 Definition :: Constant ( constant_definition) => todo ! ( ) ,
226226 Definition :: Function ( function_definition) => {
227227 for param in function_definition. arguments . as_ref ( ) . unwrap_or ( & vec ! [ ] ) {
228- self . validate_type ( & param. ty , None ) ;
228+ self . validate_type (
229+ & param. ty ,
230+ function_definition. type_parameters . as_ref ( ) ,
231+ ) ;
229232 }
230233 if let Some ( return_type) = & function_definition. returns {
231234 self . validate_type (
232235 return_type,
233- function_definition. type_parameters . clone ( ) ,
236+ function_definition. type_parameters . as_ref ( ) ,
234237 ) ;
235238 }
239+ if !self . errors . is_empty ( ) {
240+ continue ;
241+ }
242+ if let Err ( err) = self . symbol_table . register_function (
243+ function_definition. name ( ) ,
244+ function_definition
245+ . type_parameters
246+ . as_ref ( )
247+ . unwrap_or ( & vec ! [ ] )
248+ . iter ( )
249+ . map ( |param| param. name ( ) )
250+ . collect ( ) ,
251+ function_definition
252+ . arguments
253+ . as_ref ( )
254+ . unwrap_or ( & vec ! [ ] )
255+ . iter ( )
256+ . map ( |param| param. ty . clone ( ) )
257+ . collect ( ) ,
258+ function_definition
259+ . returns
260+ . as_ref ( )
261+ . unwrap_or ( & Type :: Simple ( Rc :: new ( SimpleType :: new (
262+ 0 ,
263+ Location :: default ( ) ,
264+ "Unit" . into ( ) ,
265+ ) ) ) )
266+ . clone ( ) ,
267+ ) {
268+ self . errors . push ( err) ;
269+ }
236270 }
237271 Definition :: ExternalFunction ( external_function_definition) => {
238272 todo ! ( )
@@ -245,7 +279,7 @@ impl TypeChecker {
245279 }
246280 }
247281
248- fn validate_type ( & mut self , ty : & Type , type_parameters : Option < Vec < Rc < Type > > > ) {
282+ fn validate_type ( & mut self , ty : & Type , type_parameters : Option < & Vec < Rc < Identifier > > > ) {
249283 match ty {
250284 Type :: Array ( type_array) => self . validate_type ( & type_array. element_type , None ) ,
251285 Type :: Simple ( simple_type) => {
@@ -264,17 +298,26 @@ impl TypeChecker {
264298 . push ( format ! ( "Unknown type `{}`" , generic_type. base. name( ) ) ) ;
265299 }
266300 if let Some ( type_params) = & type_parameters {
301+ if type_params. len ( ) != generic_type. parameters . len ( ) {
302+ self . errors . push ( format ! (
303+ "Type parameter count mismatch for `{}`: expected {}, found {}" ,
304+ generic_type. base. name( ) ,
305+ generic_type. parameters. len( ) ,
306+ type_params. len( )
307+ ) ) ;
308+ }
309+ let generic_param_names: Vec < String > = generic_type
310+ . parameters
311+ . iter ( )
312+ . map ( |param| param. name ( ) )
313+ . collect ( ) ;
267314 for param in & generic_type. parameters {
268- if let Type :: Generic ( generic_param) = param {
269- if !type_params
270- . iter ( )
271- . any ( |tp| tp. name == generic_param. base . name )
272- {
273- self . errors . push ( format ! (
274- "Unknown type parameter `{}` in generic type `{}`" ,
275- generic_param. base. name, generic_type. base. name
276- ) ) ;
277- }
315+ if !generic_param_names. contains ( & param. name ( ) ) {
316+ self . errors . push ( format ! (
317+ "Type parameter `{}` not found in `{}`" ,
318+ param. name( ) ,
319+ generic_type. base. name( )
320+ ) ) ;
278321 }
279322 }
280323 }
@@ -293,6 +336,28 @@ impl TypeChecker {
293336 }
294337 }
295338 }
339+
340+ #[ allow( clippy:: needless_pass_by_value) ]
341+ fn infer_variables ( & mut self , function_definition : Rc < FunctionDefinition > ) {
342+ self . symbol_table . push_scope ( ) ;
343+ // let mut generic_type_param_placeholders: HashMap<String, Option<String>> = HashMap::new();
344+ // if let Some(type_parameters) = &function_definition.type_parameters {
345+ // for tp in type_parameters {
346+ // generic_type_param_placeholders.insert(tp.name(), None);
347+ // }
348+ // }
349+ if let Some ( arguments) = & function_definition. arguments {
350+ for argument in arguments {
351+ if let Err ( err) = self
352+ . symbol_table
353+ . push_variable_to_scope ( argument. name ( ) , argument. ty . clone ( ) )
354+ {
355+ self . errors . push ( err. to_string ( ) ) ;
356+ }
357+ }
358+ }
359+ self . symbol_table . pop_scope ( ) ;
360+ }
296361}
297362
298363// pub struct TypeContext<'a> {
0 commit comments