From 8065e735985695d241f94ff1b2821026599787ec Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 4 Oct 2024 13:13:46 +0800 Subject: [PATCH] [core] toplevel/composer: Add type analysis for global variables --- nac3core/src/toplevel/composer.rs | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 020c7a8f1..62a544732 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -447,6 +447,7 @@ impl TopLevelComposer { if inference { self.analyze_function_instance()?; } + self.analyze_top_level_variables()?; Ok(()) } @@ -2227,4 +2228,57 @@ impl TopLevelComposer { } Ok(()) } + + /// Step 6. Analyze and populate the types of global variables. + fn analyze_top_level_variables(&mut self) -> Result<(), HashSet> { + let def_list = &self.definition_ast_list; + let temp_def_list = self.extract_def_list(); + let unifier = &mut self.unifier; + let primitives_store = &self.primitives_ty; + + let mut analyze = |variable_def: &Arc>| -> Result<_, HashSet> { + let variable_def = &mut *variable_def.write(); + + let TopLevelDef::Variable { ty: dummy_ty, ty_decl, resolver, loc, .. } = variable_def + else { + // not top level variable def, skip + return Ok(()); + }; + + let resolver = &**resolver.as_ref().unwrap(); + + let ty_annotation = parse_ast_to_type_annotation_kinds( + resolver, + &temp_def_list, + unifier, + primitives_store, + ty_decl, + HashMap::new(), + )?; + let ty_from_ty_annotation = get_type_from_type_annotation_kinds( + &temp_def_list, + unifier, + primitives_store, + &ty_annotation, + &mut None, + )?; + + unifier.unify(*dummy_ty, ty_from_ty_annotation).map_err(|e| { + HashSet::from([e.at(Some(loc.unwrap())).to_display(unifier).to_string()]) + })?; + Ok(()) + }; + + let mut errors = HashSet::new(); + for (variable_def, _) in def_list.iter().skip(self.builtin_num) { + if let Err(e) = analyze(variable_def) { + errors.extend(e); + } + } + if !errors.is_empty() { + return Err(errors); + } + + Ok(()) + } }