Compare commits
	
		
			No commits in common. "d5ac6dfc2d2a1319371b193e5b6e75c4077ac781" and "e578250ee652b5f00f71700464070edd0484cefd" have entirely different histories.
		
	
	
		
			d5ac6dfc2d
			...
			e578250ee6
		
	
		
| @ -36,8 +36,8 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { | ||||
|                     } | ||||
|                 } | ||||
|                 MemberChildBuild::Boolean(_) => None, | ||||
|                 MemberChildBuild::Special(_) => None, | ||||
|             }, | ||||
|             StructChild::Special(_) => None, | ||||
|         }) | ||||
|         .filter(Option::is_some) | ||||
|         .map(Option::unwrap) | ||||
|  | ||||
| @ -1,44 +1,8 @@ | ||||
| use crate::deserialize::util::{make_build_fn_name, make_build_pair}; | ||||
| use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, VecChild, VecChildBuild}; | ||||
| use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild}; | ||||
| use proc_macro2::{Ident, TokenStream}; | ||||
| use quote::{format_ident, quote}; | ||||
| 
 | ||||
| fn make_preamble(spec: &StructSpec, pair_ident: &Ident) -> TokenStream { | ||||
|     if spec.children().any(StructChild::is_special) { | ||||
|         quote! { | ||||
|             let as_span = #pair_ident.as_span(); | ||||
|         } | ||||
|     } else { | ||||
|         quote! {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_special_children(spec: &StructSpec) -> Vec<TokenStream> { | ||||
|     spec.children() | ||||
|         .map(StructChild::unwrap_special) | ||||
|         .filter(Option::is_some) | ||||
|         .map(Option::unwrap) | ||||
|         .map(|special_child| { | ||||
|             let child_ident = format_ident!("{}", special_child.name()); | ||||
|             match special_child.kind() { | ||||
|                 SpecialChildKind::FileId => { | ||||
|                     quote! { | ||||
|                         let #child_ident = file_id | ||||
|                     } | ||||
|                 } | ||||
|                 SpecialChildKind::Range => { | ||||
|                     quote! { | ||||
|                         let #child_ident = Range { | ||||
|                             start: as_span.start(), | ||||
|                             end: as_span.end() | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         .collect::<Vec<_>>() | ||||
| } | ||||
| 
 | ||||
| fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream { | ||||
|     let child_ident = format_ident!("{}", vec_child.name()); | ||||
|     match vec_child.build() { | ||||
| @ -80,8 +44,8 @@ fn make_child_holder(child_spec: &StructChild) -> Option<TokenStream> { | ||||
|                 Some(make_node_child_holder(member_child.name(), node_child)) | ||||
|             } | ||||
|             MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())), | ||||
|             MemberChildBuild::Special(_) => None, | ||||
|         }, | ||||
|         StructChild::Special(_) => None, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -120,12 +84,7 @@ fn make_boolean_member_child_match_action(name: &str) -> TokenStream { | ||||
| 
 | ||||
| fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {    
 | ||||
|     match child_spec { | ||||
|         StructChild::SkipChild(skip_child) => { | ||||
|             let rule_ident = format_ident!("{}", skip_child.rule()); | ||||
|             Some(quote! { | ||||
|                 Rule::#rule_ident => {} | ||||
|             }) | ||||
|         }, | ||||
|         StructChild::SkipChild(_) => None, | ||||
|         StructChild::VecChild(vec_child) => { | ||||
|             let rule_ident = format_ident!("{}", vec_child.rule()); | ||||
|             let action = make_vec_child_match_action(vec_child); | ||||
| @ -152,9 +111,9 @@ fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> { | ||||
|                         Rule::#rule_ident => { #action } | ||||
|                     }) | ||||
|                 } | ||||
|                 MemberChildBuild::Special(_) => None | ||||
|             } | ||||
|         } | ||||
|         }, | ||||
|         StructChild::Special(_) => None | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -187,11 +146,6 @@ fn make_boolean_member_child_arg(name: &str) -> TokenStream { | ||||
|     quote! { #child_ident } | ||||
| } | ||||
| 
 | ||||
| fn make_special_child_arg(special_child: &SpecialChild) -> TokenStream { | ||||
|     let child_ident = format_ident!("{}", special_child.name()); | ||||
|     quote! { #child_ident } | ||||
| } | ||||
| 
 | ||||
| fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> { | ||||
|     match child_spec { | ||||
|         StructChild::SkipChild(_) => None, | ||||
| @ -205,8 +159,22 @@ fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenS | ||||
|             MemberChildBuild::Boolean(_) => { | ||||
|                 Some(make_boolean_member_child_arg(member_child.name())) | ||||
|             }, | ||||
|             MemberChildBuild::Special(special_member_build) => { | ||||
|                 match special_member_build { | ||||
|                     SpecialMemberBuild::FileId => { | ||||
|                         Some(quote! { file_id }) | ||||
|                     } | ||||
|                     SpecialMemberBuild::Range => { | ||||
|                         Some(quote! { 
 | ||||
|                             Range { | ||||
|                                 start: #pair_ident.as_span().start(), | ||||
|                                 end: #pair_ident.as_span().end(), | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|         }, | ||||
|         StructChild::Special(special_child) => Some(make_special_child_arg(special_child)), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -231,10 +199,6 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream { | ||||
|     let pair_ident = format_ident!("{}", make_build_pair(build_spec.build())); | ||||
|     let return_type_ident = format_ident!("{}", build_spec.build()); | ||||
| 
 | ||||
|     let preamble = make_preamble(build_spec, &pair_ident); | ||||
|     
 | ||||
|     let special_children = make_special_children(build_spec); | ||||
| 
 | ||||
|     let child_holders = build_spec | ||||
|         .children() | ||||
|         .map(|child_spec| make_child_holder(child_spec)) | ||||
| @ -260,10 +224,6 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream { | ||||
| 
 | ||||
|     quote! { | ||||
|         fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident { | ||||
|             #preamble | ||||
|             
 | ||||
|             #(#special_children;)* | ||||
|             
 | ||||
|             #(#child_holders;)* | ||||
| 
 | ||||
|             #iter_stream | ||||
|  | ||||
| @ -56,6 +56,12 @@ fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> Membe | ||||
|         } else { | ||||
|             panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name); | ||||
|         } | ||||
|     } else if props["special"].is_hash() { | ||||
|         match props["special"]["kind"].as_str().unwrap() { | ||||
|             "file_id" => MemberChildBuild::Special(SpecialMemberBuild::FileId), | ||||
|             "range" => MemberChildBuild::Special(SpecialMemberBuild::Range), | ||||
|             _ => panic!(), | ||||
|         } | ||||
|     } else { | ||||
|         panic!( | ||||
|             "Expected one of 'node', 'boolean', or 'special' in 'build' in {}", | ||||
| @ -92,14 +98,6 @@ fn deserialize_member_child(child_name: &str, props: &Yaml) -> StructChild { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn deserialize_special_child(name: &str, props: &Yaml) -> StructChild { | ||||
|     match props["kind"].as_str().unwrap() { | ||||
|         "file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)), | ||||
|         "range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)), | ||||
|         _ => panic!("Invalid special child kind {} in {}", props["kind"].as_str().unwrap(), name), | ||||
|     }    
 | ||||
| } | ||||
| 
 | ||||
| fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild { | ||||
|     if props["skip"].is_hash() { | ||||
|         deserialize_skip_child(&props["skip"]) | ||||
| @ -107,8 +105,6 @@ fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild { | ||||
|         deserialize_vec_child(name, &props["vec"]) | ||||
|     } else if props["member"].is_hash() { | ||||
|         deserialize_member_child(name, &props["member"]) | ||||
|     } else if props["special"].is_hash() { | ||||
|         deserialize_special_child(name, &props["special"])    
 | ||||
|     } else { | ||||
|         panic!("Expected 'skip' or 'vec' in 'member' in {}", name); | ||||
|     } | ||||
|  | ||||
| @ -231,8 +231,8 @@ fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream { | ||||
|                         writer.writeln_indented(&format!(#format_string, self.#child_ident()))?; | ||||
|                     }) | ||||
|                 } | ||||
|                 MemberChildBuild::Special(_) => None | ||||
|             }, | ||||
|             StructChild::Special(_) => None | ||||
|         }) | ||||
|         .filter(Option::is_some) | ||||
|         .map(Option::unwrap) | ||||
|  | ||||
| @ -26,25 +26,6 @@ pub enum StructChild { | ||||
|     SkipChild(SkipChild), | ||||
|     VecChild(VecChild), | ||||
|     MemberChild(MemberChild), | ||||
|     Special(SpecialChild), | ||||
| } | ||||
| 
 | ||||
| impl StructChild { | ||||
|     pub fn is_special(&self) -> bool { | ||||
|         match self { | ||||
|             StructChild::Special(_) => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
|     
 | ||||
|     pub fn unwrap_special(&self) -> Option<&SpecialChild> { | ||||
|         match self { | ||||
|             StructChild::Special(special_child) => { | ||||
|                 Some(special_child) | ||||
|             }, | ||||
|             _ => None | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct SkipChild { | ||||
| @ -179,6 +160,7 @@ impl MemberChild { | ||||
| pub enum MemberChildBuild { | ||||
|     Node(NodeMemberBuild), | ||||
|     Boolean(BooleanMemberBuild), | ||||
|     Special(SpecialMemberBuild), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| @ -233,30 +215,7 @@ pub enum BooleanMemberBuildOn { | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SpecialChild { | ||||
|     name: String, | ||||
|     kind: SpecialChildKind, | ||||
| } | ||||
| 
 | ||||
| impl SpecialChild { | ||||
|     pub fn new(name: &str, kind: SpecialChildKind) -> Self { | ||||
|         Self { | ||||
|             name: name.to_string(), | ||||
|             kind | ||||
|         } | ||||
|     } | ||||
|     
 | ||||
|     pub fn name(&self) -> &str { | ||||
|         &self.name | ||||
|     } | ||||
|     
 | ||||
|     pub fn kind(&self) -> &SpecialChildKind { | ||||
|         &self.kind | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum SpecialChildKind { | ||||
| pub enum SpecialMemberBuild { | ||||
|     FileId, | ||||
|     Range, | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::spec::struct_spec::{ | ||||
|     MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, | ||||
|     VecChild, VecChildBuild, | ||||
|     MemberChild, MemberChildBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, | ||||
|     VecChildBuild, | ||||
| }; | ||||
| use proc_macro2::{Ident, TokenStream}; | ||||
| use quote::{format_ident, quote}; | ||||
| @ -76,26 +76,22 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_special_child_accessors(special_child: &SpecialChild) -> TokenStream { | ||||
|     let child_ident = format_ident!("{}", special_child.name()); | ||||
|     match special_child.kind() { | ||||
|         SpecialChildKind::FileId => { | ||||
|         MemberChildBuild::Special(special_member_build) => match special_member_build { | ||||
|             SpecialMemberBuild::FileId => { | ||||
|                 quote! { | ||||
|                 pub fn #child_ident(&self) -> usize { | ||||
|                     self.#child_ident | ||||
|                     pub fn file_id(&self) -> usize { | ||||
|                         self.file_id | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         SpecialChildKind::Range => { | ||||
|             SpecialMemberBuild::Range => { | ||||
|                 quote! { | ||||
|                 pub fn #child_ident(&self) -> Range<usize> { | ||||
|                     self.#child_ident | ||||
|                     pub fn range(&self) -> Range<usize> { | ||||
|                         self.range | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -104,7 +100,6 @@ fn make_accessors(child: &StructChild) -> Option<TokenStream> { | ||||
|         StructChild::SkipChild(_) => None, | ||||
|         StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)), | ||||
|         StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)), | ||||
|         StructChild::Special(special_child) => Some(make_special_child_accessors(special_child)), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -113,7 +108,6 @@ fn make_member_ident(child: &StructChild) -> Option<Ident> { | ||||
|         StructChild::SkipChild(_) => None, | ||||
|         StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())), | ||||
|         StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())), | ||||
|         StructChild::Special(special_child) => Some(format_ident!("{}", special_child.name())), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -141,6 +135,10 @@ fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream { | ||||
|         MemberChildBuild::Boolean(_) => { | ||||
|             quote! { bool } | ||||
|         } | ||||
|         MemberChildBuild::Special(special_member_build) => match special_member_build { | ||||
|             SpecialMemberBuild::FileId => quote! { usize }, | ||||
|             SpecialMemberBuild::Range => quote! { Range<usize> }, | ||||
|         }, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -158,17 +156,6 @@ fn make_member_child_annotated_member(member_child: &MemberChild) -> TokenStream | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_special_child_annotated_member(special_child: &SpecialChild) -> TokenStream { | ||||
|     let child_ident = format_ident!("{}", special_child.name()); | ||||
|     let child_type_ident = match special_child.kind() { | ||||
|         SpecialChildKind::FileId => quote! { usize }, | ||||
|         SpecialChildKind::Range => quote! { Range<usize> }, | ||||
|     }; | ||||
|     quote! { | ||||
|         #child_ident: #child_type_ident | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_annotated_member(child: &StructChild) -> Option<TokenStream> { | ||||
|     match child { | ||||
|         StructChild::SkipChild(_) => None, | ||||
| @ -176,9 +163,6 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> { | ||||
|         StructChild::MemberChild(member_child) => { | ||||
|             Some(make_member_child_annotated_member(member_child)) | ||||
|         } | ||||
|         StructChild::Special(special_child) => { | ||||
|             Some(make_special_child_annotated_member(special_child)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| fn main() | ||||
|     let n = 1 + 2 * 3 + 4 | ||||
|     println n | ||||
|     1 + 2 * 3 + 4 | ||||
| end | ||||
| @ -1,5 +0,0 @@ | ||||
| fn main() -> Void | ||||
|     $0 = 2 * 3 | ||||
|     $1 = 1 + $0 | ||||
|     $2 = $1 + 4 | ||||
|     call std::core::println($2) | ||||
| @ -1,89 +0,0 @@ | ||||
| struct World | ||||
|     pub String* name | ||||
|     pub String* color | ||||
| end | ||||
| 
 | ||||
| void World::ctor(World *self, String* name, String* color) | ||||
|     self.name = move name | ||||
|     self.color = move color | ||||
| end | ||||
| 
 | ||||
| const String %s0 = 'Mercury' | ||||
| const String %s1 = 'Red' | ||||
| const String %s2 = 'Earth' | ||||
| const String %s3 = 'Blue' | ||||
| const String %s4 = 'Jupiter' | ||||
| const String %s5 = 'Orange' | ||||
| 
 | ||||
| List<World> *getWorlds() | ||||
|     List<World> *$0 = alloc std::list::ArrayList | ||||
|     call std::list::ArrayList::ctor($0) | ||||
|     World *$1 = alloc World | ||||
|     call World::ctor($1, %s0, %s1) | ||||
|     call std::list::ArrayList::add($0, $1) | ||||
|     World *$2 = alloc World | ||||
|     call World::ctor($2, %s2, %s3) | ||||
|     call std::list::ArrayList::add($0, $2) | ||||
|     World *$3 = alloc World | ||||
|     call World::ctor($3, %s4, %s5) | ||||
|     call std::list::ArrayList::add($0, $3) | ||||
|     ret $0 | ||||
| end | ||||
| 
 | ||||
| struct __findWorldByColor__cl0_captures | ||||
|     pub String* color | ||||
| end | ||||
| 
 | ||||
| Boolean __findWorldByColor_cl0(__findWorldByColor__cl0_captures *__captures, World *it) | ||||
|     String *$0 = it.color | ||||
|     String *$1 = __captures.color | ||||
|     Boolean $2 = *$0 == *$1 | ||||
|     ret $2 | ||||
| end | ||||
| 
 | ||||
| String* __findWorldByColor_cl1(World* it) | ||||
|     $0 = it.name | ||||
|     ret $0 | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| String *findWorldByColor(List<World> *worlds, String *color) | ||||
|     __findWorldByColor__cl0_captures *$0 = alloc __findWorldByColor__cl0_captures | ||||
|     $0.color = color | ||||
|     Closure(__findWorldByColor__cl0_captures*)(World*)<Boolean> $1 | ||||
|         = closure(__findWorldByColor_cl0, $0) | ||||
|     List<World> $2 = call std::list::ArrayList_impl_Find::find(worlds, $1) | ||||
|     Closure()(World*)<String*> $3 = closure(__findWorldByColor_cl1) | ||||
|     Option<String*> $4 = call std::list::ArrayList_impl_Monad($2, $3) | ||||
| 
 | ||||
|     Display*[1] $5 = alloc Display[1] | ||||
|     $5[0] = color | ||||
|     DString *$6 = alloc DString | ||||
|     call DString::ctor($6, { }, $5) | ||||
|     String *$7 = call DString::toString($6) | ||||
| 
 | ||||
|     String* $8 = call option::Option::expect($4, $7) | ||||
| 
 | ||||
|     drop $0 | ||||
|     drop $1 | ||||
|     drop $2 | ||||
|     drop $3 | ||||
|     drop $5 | ||||
|     drop $6 | ||||
| 
 | ||||
|     ret $8 | ||||
| end | ||||
| 
 | ||||
| const String %s7 = 'Blue' | ||||
| const String[2] %sa0 = { 'Hello, ', '!' } | ||||
| 
 | ||||
| void main() | ||||
|     List<World> *$0 = call getWorlds() | ||||
|     World *$1 = call findWorldByColor($0, %s7) | ||||
|     Display[1] $2 = alloc Display[1] | ||||
|     $2[0] = move $1 | ||||
|     std::string::DString *$3 = alloc std::string::DString | ||||
|     call std::string::DString::ctor($3, %sa0, $2) | ||||
|     String *$4 = call std::DString::toString($3) | ||||
|     call std::core::println($4) | ||||
| end | ||||
| @ -5,13 +5,13 @@ use deimos::ast::build::build_ast; | ||||
| use deimos::name_analysis::analyze_names; | ||||
| use deimos::name_analysis::symbol_table::SymbolTable; | ||||
| use deimos::parser::{DeimosParser, Rule}; | ||||
| use deimos::std_core::add_std_core_symbols; | ||||
| use pest::Parser; | ||||
| use std::path::PathBuf; | ||||
| use deimos::std_core::add_std_core_symbols; | ||||
| 
 | ||||
| pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> { | ||||
|     let mut compilation_units = vec![]; | ||||
|     let mut files: SimpleFiles<String, String> = SimpleFiles::new(); | ||||
|     let mut files = SimpleFiles::new(); | ||||
|     
 | ||||
|     for path in paths { | ||||
|         let src = std::fs::read_to_string(path).unwrap(); | ||||
| @ -31,10 +31,13 @@ pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Err | ||||
|     let mut symbol_table = SymbolTable::new(); | ||||
|     add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); | ||||
|     
 | ||||
|     let diagnostics = analyze_names(compilation_units.as_mut_slice(), &files, &mut symbol_table); | ||||
|     let diagnostics = analyze_names( | ||||
|         compilation_units.as_mut_slice(), | ||||
|         &mut symbol_table | ||||
|     ); | ||||
|     if diagnostics.is_empty() { | ||||
|         println!("Name analysis complete."); | ||||
|         println!("{}", symbol_table); | ||||
|         println!("Symbol table\n-------\n{}", symbol_table); | ||||
|     } else { | ||||
|         let writer = StandardStream::stderr(ColorChoice::Always); | ||||
|         let config = term::Config::default(); | ||||
|  | ||||
							
								
								
									
										199
									
								
								src/ir/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								src/ir/mod.rs
									
									
									
									
									
								
							| @ -1,199 +0,0 @@ | ||||
| pub enum DvmIr { | ||||
|     Struct(Box<DvmIrStruct>), | ||||
|     Function(DvmIrFunction), | ||||
|     Const(DvmIrConst), | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrStruct { | ||||
|     name: String, | ||||
|     kind: Box<DvmIrKind>, | ||||
|     is_public: bool, | ||||
|     members: Vec<Box<DvmIrStructMember>> | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrStructMember { | ||||
|     name: String, | ||||
|     kind: Box<DvmIrKind>, | ||||
|     is_public: bool, | ||||
|     is_mut: bool, | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrKind { | ||||
|     Primitive(Box<DvmIrPrimitiveKind>), | ||||
|     Struct(Box<DvmIrStructKind>), | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrPrimitiveKind { | ||||
|     I8, | ||||
|     I16, | ||||
|     I32, | ||||
|     I64, | ||||
|     I128, | ||||
|     ISize, | ||||
|     U8, | ||||
|     U16, | ||||
|     U32, | ||||
|     U64, | ||||
|     U128, | ||||
|     USize, | ||||
|     Boolean, | ||||
|     Array(Box<DvmIrKind>), | ||||
|     String, | ||||
|     Closure(Box<DvmIrClosureKind>), | ||||
|     Ref(Box<DvmIrKind>), | ||||
|     Void, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrStructKind { | ||||
|     name: String, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrClosureKind { | ||||
|     captures_name: String, | ||||
|     parameters: Vec<Box<DvmIrKind>>, | ||||
|     return_type: Box<DvmIrKind>, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrFunction { | ||||
|     name: String, | ||||
|     parameters: Vec<Box<DvmIrKind>>, | ||||
|     return_type: Box<DvmIrKind>, | ||||
|     statements: Vec<Box<DvmIrStatement>>, | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrStatement { | ||||
|     Alloc(DvmIrAlloc), | ||||
|     Call(DvmIrCallStmt), | ||||
|     Ret(DvmIrRet), | ||||
|     Assign(DvmIrAssign), | ||||
|     MakeClosure(DvmIrMakeClosure), | ||||
|     Drop(DvmIrDrop), | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrAllocable { | ||||
|     Struct(Box<DvmIrStructKind>), | ||||
|     Array(Box<DvmIrArrayKind>), | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrArrayKind { | ||||
|     StaticSize(Box<DvmIrStaticArrayKind>), | ||||
|     DynamicSize(Box<DvmIrDynamicArrayKind>) | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrStaticArrayKind { | ||||
|     inner_kind: Box<DvmIrKind>, | ||||
|     size: usize, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrDynamicArrayKind { | ||||
|     inner_kind: Box<DvmIrKind>, | ||||
|     size_expr: Box<DvmIrExpr> | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrAlloc { | ||||
|     declared_kind: Box<DvmIrAllocable>, | ||||
|     name: String, | ||||
|     kind_to_alloc: Box<DvmIrAllocable>, | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrConst { | ||||
|     String(DvmIrStringConst), | ||||
|     StringArray(DvmIrStringArrayConst), | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrStringConst { | ||||
|     name: String, | ||||
|     value: String, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrStringArrayConst { | ||||
|     name: String, | ||||
|     value: Vec<String>, | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrExpr { | ||||
|     Call(Box<DvmIrCallExpr>), | ||||
|     Variable(Box<DvmIrVariable>), | ||||
|     ConstRef(Box<DvmIrConstRef>), | ||||
|     Literal(Box<DvmIrLiteral>) | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrVariable { | ||||
|     name: String, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrConstRef { | ||||
|     name: String,    
 | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrLiteral { | ||||
|     I8(i8), | ||||
|     I16(i16), | ||||
|     I32(i32), | ||||
|     I64(i64), | ||||
|     I128(i128), | ||||
|     ISize(isize), | ||||
|     U8(u8), | ||||
|     U16(u16), | ||||
|     U32(u32), | ||||
|     U64(u64), | ||||
|     U128(u128), | ||||
|     USize(usize), | ||||
|     Boolean(bool), | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrCallStmt { | ||||
|     declared_type: Box<DvmIrKind>, | ||||
|     name: String, | ||||
|     call_expr: Box<DvmIrCallExpr>, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrCallExpr { | ||||
|     name: String, | ||||
|     arguments: Vec<Box<DvmIrExpr>>, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrAssign { | ||||
|     lhs: Box<DvmIrAssignLhs>, | ||||
|     rhs: Box<DvmIrExpr> | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrAssignLhs { | ||||
|     base: Box<DvmIrVariable>, | ||||
|     suffixes: Vec<Box<DvmIrAssignLhsSuffix>> | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrAssignLhsSuffix { | ||||
|     Index(DvmIrAssignLhsIndex), | ||||
|     Property(DvmIrAssignLhsProperty) | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrAssignLhsIndex { | ||||
|     expr: Box<DvmIrExpr>, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrAssignLhsProperty { | ||||
|     name: String, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrRet { | ||||
|     value: Box<DvmIrReturnable> | ||||
| } | ||||
| 
 | ||||
| pub enum DvmIrReturnable { | ||||
|     Variable(DvmIrVariable), | ||||
|     Literal(DvmIrLiteral) | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrMakeClosure { | ||||
|     captures_kind: Option<Box<DvmIrStructKind>>, | ||||
|     parameters: Vec<Box<DvmIrKind>>, | ||||
|     return_type: Box<DvmIrKind>, | ||||
|     name: String, | ||||
|     fn_name: String, | ||||
|     captures_variable: Box<DvmIrVariable>, | ||||
| } | ||||
| 
 | ||||
| pub struct DvmIrDrop { | ||||
|     variable: Box<DvmIrVariable>, | ||||
| } | ||||
| @ -11,4 +11,3 @@ pub mod parser; | ||||
| pub mod std_core; | ||||
| pub mod util; | ||||
| pub mod vm; | ||||
| pub mod ir; | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| pub struct FqnContext { | ||||
| pub(super) struct FqnContext { | ||||
|     stack: Vec<String>, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,76 +1,62 @@ | ||||
| use crate::ast::ast_node::{AstNode, AstNodeRef}; | ||||
| use crate::ast::node::{ | ||||
|     Class, CompilationUnit, Function, FunctionBlockBody, FunctionBody, Identifier, Interface, | ||||
|     Module, Namespace, Statement, UseStatement, UseStatementSuffix, VariableDeclaration, | ||||
| }; | ||||
| use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix}; | ||||
| use crate::diagnostic::DmDiagnostic; | ||||
| use crate::name_analysis::fqn_context::FqnContext; | ||||
| use crate::name_analysis::symbol::function_symbol::FunctionSymbol; | ||||
| use crate::name_analysis::symbol::module_symbol::ModuleSymbol; | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use crate::name_analysis::symbol::type_symbol::{ | ||||
|     ConcreteTypeSymbol, ConcreteTypeSymbolKind, TypeSymbol, | ||||
| }; | ||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | ||||
| use crate::name_analysis::symbol::variable_symbol::VariableSymbol; | ||||
| use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | ||||
| use codespan_reporting::diagnostic::{Diagnostic, Label}; | ||||
| use std::range::Range; | ||||
| use crate::name_analysis::symbol::use_symbol::StarUseStatementSymbol; | ||||
| use crate::name_analysis::symbol::UseStatementSymbol; | ||||
| use crate::name_analysis::symbol_table::SymbolTable; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| fn handle_insert_error( | ||||
|     err: SymbolInsertError, | ||||
|     error_symbol_name: &str, | ||||
|     error_file_id: usize, | ||||
|     error_range: Range<usize>, | ||||
|     symbol_types: &str, | ||||
| fn gather_identifier( | ||||
|     identifier: &Identifier, | ||||
|     symbol_table: &SymbolTable, | ||||
|     identifier_scope_ids: &mut HashMap<Identifier, usize>, | ||||
| ) { | ||||
|     identifier_scope_ids.insert(identifier.clone(), symbol_table.current_scope_id()); | ||||
| } | ||||
| 
 | ||||
| fn gather_use_statement( | ||||
|     use_statement: &UseStatement, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     match err { | ||||
|         SymbolInsertError::SymbolAlreadyDefined(s) => { | ||||
|             let mut diagnostic = Diagnostic::error() | ||||
|                 .with_message(format!( | ||||
|                     "{} symbol '{}' already defined in the current scope.", | ||||
|                     symbol_types, error_symbol_name, | ||||
|                 )) | ||||
|                 .with_label( | ||||
|                     Label::primary(error_file_id, error_range) | ||||
|                         .with_message("Symbol duplicated here."), | ||||
|                 ); | ||||
| 
 | ||||
|             if let Some(source_definition) = s.definition() { | ||||
|                 diagnostic = diagnostic.with_label( | ||||
|                     Label::secondary(source_definition.file_id(), source_definition.range()) | ||||
|                         .with_message("Symbol defined here."), | ||||
|                 ); | ||||
|     let mut fully_qualified_name = String::new(); | ||||
|     for prefix in use_statement.prefixes() { | ||||
|         fully_qualified_name.push_str(&format!("{}::", prefix.identifier().name())); | ||||
|     } | ||||
| 
 | ||||
|             diagnostics.push(diagnostic); | ||||
|     match use_statement.suffix() { | ||||
|         UseStatementSuffix::Identifier(identifier) => {} | ||||
|         UseStatementSuffix::Star => { | ||||
|             let symbol_inner = StarUseStatementSymbol::new( | ||||
|                 &fully_qualified_name, | ||||
|                 Some(SourceDefinition::from_use_statement(use_statement)), | ||||
|             ); | ||||
|             let symbol = UseStatementSymbol::Star(symbol_inner); | ||||
|             symbol_table.insert_use_statement_symbol(symbol); | ||||
|             todo!() | ||||
|         } | ||||
|         UseStatementSuffix::UseList(use_list) => {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn gather_node_children( | ||||
|     node: &impl AstNode, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     for child in node.children() { | ||||
|         gather_node(child, symbol_table, fqn_context, diagnostics); | ||||
|         gather_node(child, symbol_table, diagnostics); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn gather_node( | ||||
|     node: AstNodeRef, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     match node { | ||||
|         AstNodeRef::Operator(_) => {} | ||||
|         AstNodeRef::Identifier(_) => { | ||||
|             unreachable!() | ||||
|         } | ||||
|         AstNodeRef::Identifier(_) => {} | ||||
|         AstNodeRef::FullyQualifiedName(_) => {} | ||||
|         AstNodeRef::TypeUseList(_) => {} | ||||
|         AstNodeRef::IdentifierList(_) => {} | ||||
| @ -89,114 +75,36 @@ fn gather_node( | ||||
|         AstNodeRef::Parameter(_) => {} | ||||
|         AstNodeRef::ReturnType(_) => {} | ||||
|         AstNodeRef::CompilationUnit(compilation_unit) => { | ||||
|             gather_node_children(compilation_unit, symbol_table, fqn_context, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::Namespace(namespace) => { | ||||
|             gather_namespace(namespace, fqn_context); | ||||
|             gather_node_children(compilation_unit, symbol_table, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::ParentMod(_) => {} | ||||
|         AstNodeRef::UseStatement(use_statement) => { | ||||
|             gather_use_statement(use_statement, symbol_table, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::UseStatementPrefix(_) => { | ||||
|             unreachable!() | ||||
|         } | ||||
|         AstNodeRef::UseStatementSuffix(_) => { | ||||
|             unreachable!() | ||||
|         } | ||||
|         AstNodeRef::UseList(_) => { | ||||
|             unreachable!() | ||||
|         } | ||||
|         AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => { | ||||
|             gather_node_children( | ||||
|                 module_level_declaration, | ||||
|                 symbol_table, | ||||
|                 fqn_context, | ||||
|                 diagnostics, | ||||
|             ); | ||||
|         } | ||||
|         AstNodeRef::InterfaceLevelDeclaration(interface_level_declaration) => { | ||||
|             gather_node_children( | ||||
|                 interface_level_declaration, | ||||
|                 symbol_table, | ||||
|                 fqn_context, | ||||
|                 diagnostics, | ||||
|             ); | ||||
|         } | ||||
|         AstNodeRef::ClassLevelDeclaration(class_level_declaration) => { | ||||
|             gather_node_children( | ||||
|                 class_level_declaration, | ||||
|                 symbol_table, | ||||
|                 fqn_context, | ||||
|                 diagnostics, | ||||
|             ); | ||||
|         } | ||||
|         AstNodeRef::Module(module) => { | ||||
|             gather_module(module, symbol_table, fqn_context, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::Interface(interface) => { | ||||
|             gather_interface(interface, symbol_table, fqn_context, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::Class(class) => { | ||||
|             gather_class(class, symbol_table, fqn_context, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::Function(function) => { | ||||
|             gather_function(function, symbol_table, fqn_context, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::UseStatementPrefix(_) => {} | ||||
|         AstNodeRef::UseStatementSuffix(_) => {} | ||||
|         AstNodeRef::UseList(_) => {} | ||||
|         AstNodeRef::ModuleLevelDeclaration(_) => {} | ||||
|         AstNodeRef::InterfaceLevelDeclaration(_) => {} | ||||
|         AstNodeRef::ClassLevelDeclaration(_) => {} | ||||
|         AstNodeRef::Module(_) => {} | ||||
|         AstNodeRef::CompanionModule(_) => {} | ||||
|         AstNodeRef::Interface(_) => {} | ||||
|         AstNodeRef::Class(_) => {} | ||||
|         AstNodeRef::Function(_) => {} | ||||
|         AstNodeRef::OperatorFunction(_) => {} | ||||
|         AstNodeRef::PlatformFunction(_) => {} | ||||
|         AstNodeRef::InterfaceFunction(_) => {} | ||||
|         AstNodeRef::InterfaceDefaultFunction(_) => {} | ||||
|         AstNodeRef::InterfaceOperatorFunction(_) => {} | ||||
|         AstNodeRef::InterfaceDefaultOperatorFunction(_) => {} | ||||
|         AstNodeRef::FunctionBody(function_body) => match function_body { | ||||
|             FunctionBody::FunctionAliasBody(alias_body) => { | ||||
|                 gather_node( | ||||
|                     alias_body.as_node_ref(), | ||||
|                     symbol_table, | ||||
|                     fqn_context, | ||||
|                     diagnostics, | ||||
|                 ); | ||||
|             } | ||||
|             FunctionBody::FunctionEqualsBody(equals_body) => { | ||||
|                 gather_node( | ||||
|                     equals_body.as_node_ref(), | ||||
|                     symbol_table, | ||||
|                     fqn_context, | ||||
|                     diagnostics, | ||||
|                 ); | ||||
|             } | ||||
|             FunctionBody::FunctionBlockBody(block_body) => { | ||||
|                 gather_node( | ||||
|                     block_body.as_node_ref(), | ||||
|                     symbol_table, | ||||
|                     fqn_context, | ||||
|                     diagnostics, | ||||
|                 ); | ||||
|             } | ||||
|         }, | ||||
|         AstNodeRef::FunctionBody(_) => {} | ||||
|         AstNodeRef::FunctionEqualsBody(_) => {} | ||||
|         AstNodeRef::FunctionAliasBody(_) => {} | ||||
|         AstNodeRef::FunctionBlockBody(block_body) => { | ||||
|             gather_function_block_body(block_body, symbol_table, fqn_context, diagnostics); | ||||
|         } | ||||
|         AstNodeRef::FunctionBlockBody(_) => {} | ||||
|         AstNodeRef::ClassConstructor(_) => {} | ||||
|         AstNodeRef::Member(_) => {} | ||||
|         AstNodeRef::Statement(statement) => match statement { | ||||
|             Statement::VariableDeclaration(variable_declaration) => { | ||||
|                 gather_node( | ||||
|                     variable_declaration.as_node_ref(), | ||||
|                     symbol_table, | ||||
|                     fqn_context, | ||||
|                     diagnostics, | ||||
|                 ); | ||||
|             } | ||||
|             Statement::AssignmentStatement(_) => {} | ||||
|             Statement::ExpressionStatement(_) => {} | ||||
|             Statement::UseStatement(_) => {} | ||||
|             Statement::IfStatement(_) => {} | ||||
|             Statement::WhileStatement(_) => {} | ||||
|             Statement::ForStatement(_) => {} | ||||
|         }, | ||||
|         AstNodeRef::Statement(_) => {} | ||||
|         AstNodeRef::VariableDeclaration(_) => {} | ||||
|         AstNodeRef::AssignmentStatement(_) => {} | ||||
|         AstNodeRef::ExpressionStatement(_) => {} | ||||
| @ -249,284 +157,9 @@ fn gather_node( | ||||
| 
 | ||||
| pub fn gather_compilation_unit( | ||||
|     compilation_unit: &mut CompilationUnit, | ||||
|     file_name: &str, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     identifier_scope_ids: &mut HashMap<Identifier, usize>, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let mut fqn_context = FqnContext::new(); | ||||
|     symbol_table.push_scope(&format!("FileScope {}", file_name)); | ||||
|     gather_node( | ||||
|         compilation_unit.as_node_ref(), | ||||
|         symbol_table, | ||||
|         &mut fqn_context, | ||||
|         diagnostics, | ||||
|     ); | ||||
|     symbol_table.pop_scope(); | ||||
| } | ||||
| 
 | ||||
| fn gather_namespace(namespace: &Namespace, fqn_context: &mut FqnContext) { | ||||
|     for identifier in namespace.fqn().identifiers() { | ||||
|         fqn_context.push(identifier.name()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn gather_use_statement( | ||||
|     use_statement: &UseStatement, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let base_fqn = use_statement | ||||
|         .prefixes() | ||||
|         .map(|prefix| prefix.identifier().name()) | ||||
|         .collect::<Vec<_>>() | ||||
|         .join("::"); | ||||
| 
 | ||||
|     match use_statement.suffix() { | ||||
|         UseStatementSuffix::Identifier(identifier) => { | ||||
|             gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics); | ||||
|         } | ||||
|         UseStatementSuffix::Star => { | ||||
|             let symbol = StarUseSymbol::new( | ||||
|                 &base_fqn, | ||||
|                 Some(SourceDefinition::from_use_statement(use_statement)), | ||||
|             ); | ||||
|             let insert_result = symbol_table.insert_star_use_symbol(symbol); | ||||
|             if let Err(error) = insert_result { | ||||
|                 handle_insert_error( | ||||
|                     error, | ||||
|                     &base_fqn, | ||||
|                     use_statement.file_id(), | ||||
|                     use_statement.range(), | ||||
|                     "Use Statement", | ||||
|                     diagnostics, | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         UseStatementSuffix::UseList(use_list) => { | ||||
|             for identifier in use_list.identifiers() { | ||||
|                 gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn gather_concrete_use_symbol( | ||||
|     base_fqn: &str, | ||||
|     identifier: &Identifier, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let symbol = ConcreteUseSymbol::new( | ||||
|         base_fqn, | ||||
|         identifier.name(), | ||||
|         Some(SourceDefinition::from_identifier(identifier)), | ||||
|     ); | ||||
|     if let Err(insert_error) = symbol_table.insert_concrete_use_symbol(symbol) { | ||||
|         handle_insert_error( | ||||
|             insert_error, | ||||
|             &base_fqn, | ||||
|             identifier.file_id(), | ||||
|             identifier.range(), | ||||
|             "Use Statement", | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn gather_module( | ||||
|     module: &Module, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let module_symbol = ModuleSymbol::new( | ||||
|         &fqn_context.resolve(module.identifier().name()), | ||||
|         module.identifier().name(), | ||||
|         module.is_public(), | ||||
|         Some(SourceDefinition::from_identifier(module.identifier())), | ||||
|     ); | ||||
|     if let Err(symbol_insert_error) = symbol_table.insert_module_symbol(module_symbol) { | ||||
|         handle_insert_error( | ||||
|             symbol_insert_error, | ||||
|             module.identifier().name(), | ||||
|             module.identifier().file_id(), | ||||
|             module.identifier().range(), | ||||
|             "Module", | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     fqn_context.push(module.identifier().name()); | ||||
|     symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name())); | ||||
| 
 | ||||
|     for declaration in module.declarations() { | ||||
|         gather_node( | ||||
|             declaration.as_node_ref(), | ||||
|             symbol_table, | ||||
|             fqn_context, | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     symbol_table.pop_scope(); | ||||
|     fqn_context.pop(); | ||||
| } | ||||
| 
 | ||||
| fn gather_interface( | ||||
|     interface: &Interface, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let type_symbol = ConcreteTypeSymbol::new( | ||||
|         &fqn_context.resolve(interface.identifier().name()), | ||||
|         interface.identifier().name(), | ||||
|         interface.is_public(), | ||||
|         ConcreteTypeSymbolKind::Interface, | ||||
|         Some(SourceDefinition::from_identifier(interface.identifier())), | ||||
|     ); | ||||
|     if let Err(symbol_insert_error) = | ||||
|         symbol_table.insert_type_symbol(TypeSymbol::Concrete(type_symbol)) | ||||
|     { | ||||
|         handle_insert_error( | ||||
|             symbol_insert_error, | ||||
|             interface.identifier().name(), | ||||
|             interface.identifier().file_id(), | ||||
|             interface.identifier().range(), | ||||
|             "Interface", | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     fqn_context.push(interface.identifier().name()); | ||||
|     symbol_table.push_scope(&format!("InterfaceScope {}", interface.identifier().name())); | ||||
| 
 | ||||
|     for declaration in interface.declarations() { | ||||
|         gather_node( | ||||
|             declaration.as_node_ref(), | ||||
|             symbol_table, | ||||
|             fqn_context, | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     symbol_table.pop_scope(); | ||||
|     fqn_context.pop(); | ||||
| } | ||||
| 
 | ||||
| fn gather_class( | ||||
|     class: &Class, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let class_symbol = ConcreteTypeSymbol::new( | ||||
|         &fqn_context.resolve(class.identifier().name()), | ||||
|         class.identifier().name(), | ||||
|         class.is_public(), | ||||
|         ConcreteTypeSymbolKind::Class, | ||||
|         Some(SourceDefinition::from_identifier(class.identifier())), | ||||
|     ); | ||||
|     if let Err(symbol_insert_error) = | ||||
|         symbol_table.insert_type_symbol(TypeSymbol::Concrete(class_symbol)) | ||||
|     { | ||||
|         handle_insert_error( | ||||
|             symbol_insert_error, | ||||
|             class.identifier().name(), | ||||
|             class.identifier().file_id(), | ||||
|             class.identifier().range(), | ||||
|             "Class", | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     fqn_context.push(class.identifier().name()); | ||||
|     symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name())); | ||||
| 
 | ||||
|     for declaration in class.class_level_declarations() { | ||||
|         gather_node( | ||||
|             declaration.as_node_ref(), | ||||
|             symbol_table, | ||||
|             fqn_context, | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     symbol_table.pop_scope(); | ||||
|     fqn_context.pop(); | ||||
| } | ||||
| 
 | ||||
| fn gather_function( | ||||
|     function: &Function, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let function_symbol = FunctionSymbol::without_parameters_or_return_type( | ||||
|         &fqn_context.resolve(function.identifier().name()), | ||||
|         function.identifier().name(), | ||||
|         function.is_public(), | ||||
|         false, | ||||
|         Some(SourceDefinition::from_identifier(function.identifier())), | ||||
|     ); | ||||
|     if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) { | ||||
|         handle_insert_error( | ||||
|             insert_error, | ||||
|             function.identifier().name(), | ||||
|             function.identifier().file_id(), | ||||
|             function.identifier().range(), | ||||
|             "Function", | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
|     gather_node( | ||||
|         function.function_body().as_node_ref(), | ||||
|         symbol_table, | ||||
|         fqn_context, | ||||
|         diagnostics, | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| fn gather_function_block_body( | ||||
|     function_block_body: &FunctionBlockBody, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     symbol_table.push_scope("FunctionBlockBody"); | ||||
|     gather_node_children(function_block_body, symbol_table, fqn_context, diagnostics); | ||||
|     symbol_table.pop_scope(); | ||||
| } | ||||
| 
 | ||||
| fn gather_variable_declaration( | ||||
|     variable_declaration: &VariableDeclaration, | ||||
|     symbol_table: &mut SymbolTable, | ||||
|     fqn_context: &mut FqnContext, | ||||
|     diagnostics: &mut Vec<DmDiagnostic>, | ||||
| ) { | ||||
|     let variable_symbol = VariableSymbol::new( | ||||
|         variable_declaration.identifier().name(), | ||||
|         variable_declaration.is_mut(), | ||||
|         Some(SourceDefinition::from_identifier( | ||||
|             variable_declaration.identifier(), | ||||
|         )), | ||||
|     ); | ||||
|     if let Err(insert_error) = symbol_table.insert_variable_symbol(variable_symbol) { | ||||
|         handle_insert_error( | ||||
|             insert_error, | ||||
|             variable_declaration.identifier().name(), | ||||
|             variable_declaration.identifier().file_id(), | ||||
|             variable_declaration.identifier().range(), | ||||
|             "Variable", | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
|     if let Some(expression) = variable_declaration.expression() { | ||||
|         gather_node( | ||||
|             expression.as_node_ref(), | ||||
|             symbol_table, | ||||
|             fqn_context, | ||||
|             diagnostics, | ||||
|         ); | ||||
|     } | ||||
|     gather_node(compilation_unit.as_node_ref(), symbol_table, diagnostics); | ||||
| } | ||||
|  | ||||
| @ -24,18 +24,16 @@ use crate::diagnostic::DmDiagnostic; | ||||
| use crate::name_analysis::gather::gather_compilation_unit; | ||||
| // use crate::name_analysis::resolve::resolve_compilation_unit;
 | ||||
| use crate::name_analysis::symbol_table::SymbolTable; | ||||
| use codespan_reporting::files::Files; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| pub(self) mod fqn_context; | ||||
| mod fqn_context; | ||||
| mod gather; | ||||
| // mod resolve;
 | ||||
| pub mod symbol; | ||||
| pub mod symbol_table; | ||||
| 
 | ||||
| pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( | ||||
| pub fn analyze_names( | ||||
|     compilation_units: &mut [Box<CompilationUnit>], | ||||
|     files: &'a F, | ||||
|     symbol_table: &mut SymbolTable, | ||||
| ) -> Vec<DmDiagnostic> { | ||||
|     let mut diagnostics = vec![]; | ||||
| @ -43,8 +41,12 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( | ||||
| 
 | ||||
|     // gather symbols
 | ||||
|     for compilation_unit in compilation_units.iter_mut() { | ||||
|         let file_name = files.name(compilation_unit.file_id()).unwrap(); | ||||
|         gather_compilation_unit(compilation_unit, &file_name, symbol_table, &mut diagnostics); | ||||
|         gather_compilation_unit( | ||||
|             compilation_unit, | ||||
|             symbol_table, | ||||
|             &mut identifier_scope_ids, | ||||
|             &mut diagnostics, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     // resolve symbols
 | ||||
|  | ||||
| @ -1,45 +0,0 @@ | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct ClassMemberSymbol { | ||||
|     declared_name: String, | ||||
|     is_field: bool, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ClassMemberSymbol { | ||||
|     pub fn new( | ||||
|         declared_name: &str, | ||||
|         is_field: bool, | ||||
|         source_definition: Option<SourceDefinition>, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_field, | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_field(&self) -> bool { | ||||
|         self.is_field | ||||
|     } | ||||
| 
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ClassMemberSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ClassMemberSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_field", &self.is_field) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| @ -1,101 +0,0 @@ | ||||
| use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct FunctionSymbol { | ||||
|     fqn: String, | ||||
|     declared_name: String, | ||||
|     is_public: bool, | ||||
|     is_platform: bool, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
|     parameters: Vec<ParameterSymbol>, | ||||
|     return_type: Option<ConcreteTypeSymbol>, // todo: can we use TypeSymbol?
 | ||||
| } | ||||
| 
 | ||||
| impl FunctionSymbol { | ||||
|     pub fn without_parameters_or_return_type( | ||||
|         fqn: &str, | ||||
|         declared_name: &str, | ||||
|         is_public: bool, | ||||
|         is_platform: bool, | ||||
|         source_definition: Option<SourceDefinition>, | ||||
|     ) -> FunctionSymbol { | ||||
|         FunctionSymbol { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_public, | ||||
|             is_platform, | ||||
|             source_definition, | ||||
|             parameters: Vec::new(), | ||||
|             return_type: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_parameters(self, parameters: Vec<ParameterSymbol>) -> Self { | ||||
|         Self { | ||||
|             fqn: self.fqn, | ||||
|             declared_name: self.declared_name, | ||||
|             is_public: self.is_public, | ||||
|             is_platform: self.is_platform, | ||||
|             source_definition: self.source_definition, | ||||
|             parameters, | ||||
|             return_type: self.return_type, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_return_type(self, return_type: ConcreteTypeSymbol) -> Self { | ||||
|         Self { | ||||
|             fqn: self.fqn, | ||||
|             declared_name: self.declared_name, | ||||
|             is_public: self.is_public, | ||||
|             is_platform: self.is_platform, | ||||
|             source_definition: self.source_definition, | ||||
|             parameters: self.parameters, | ||||
|             return_type: Some(return_type), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn fqn(&self) -> &str { | ||||
|         &self.fqn | ||||
|     } | ||||
| 
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_public(&self) -> bool { | ||||
|         self.is_public | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_platform(&self) -> bool { | ||||
|         self.is_platform | ||||
|     } | ||||
| 
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| 
 | ||||
|     pub fn parameters(&self) -> &[ParameterSymbol] { | ||||
|         &self.parameters | ||||
|     } | ||||
| 
 | ||||
|     pub fn return_type(&self) -> Option<&ConcreteTypeSymbol> { | ||||
|         self.return_type.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for FunctionSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("FunctionSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_public", &self.is_public) | ||||
|             .field("is_platform", &self.is_platform) | ||||
|             .field("parameters", &self.parameters) | ||||
|             .field("return_type", &self.return_type) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| @ -1,46 +1,445 @@ | ||||
| pub(crate) mod class_member_symbol; | ||||
| pub(crate) mod function_symbol; | ||||
| pub(crate) mod module_symbol; | ||||
| pub(crate) mod parameter_symbol; | ||||
| pub(crate) mod source_definition; | ||||
| pub(crate) mod type_symbol; | ||||
| pub(crate) mod use_symbol; | ||||
| pub(crate) mod variable_symbol; | ||||
| pub(super) mod source_definition; | ||||
| pub(super) mod use_symbol; | ||||
| 
 | ||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | ||||
| use class_member_symbol::ClassMemberSymbol; | ||||
| use function_symbol::FunctionSymbol; | ||||
| use module_symbol::ModuleSymbol; | ||||
| use parameter_symbol::ParameterSymbol; | ||||
| use crate::ast::node::Identifier; | ||||
| use source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Display}; | ||||
| use std::cell::RefCell; | ||||
| use std::fmt::{Debug, Display, Formatter}; | ||||
| use std::ops::Deref; | ||||
| use type_symbol::TypeSymbol; | ||||
| use variable_symbol::VariableSymbol; | ||||
| use std::rc::Rc; | ||||
| 
 | ||||
| pub trait SymbolInner { | ||||
|     fn declared_name(&self) -> &str; | ||||
|     fn definition(&self) -> Option<SourceDefinition>; | ||||
| } | ||||
| 
 | ||||
| /* Symbol */ | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Symbol { | ||||
|     ConcreteUse(ConcreteUseSymbol), | ||||
|     StarUse(StarUseSymbol), | ||||
|     Module(ModuleSymbol), | ||||
|     Type(TypeSymbol), | ||||
|     Function(FunctionSymbol), | ||||
|     Parameter(ParameterSymbol), | ||||
|     Variable(VariableSymbol), | ||||
|     ClassMember(ClassMemberSymbol), | ||||
|     UseStatement(Rc<RefCell<UseStatementSymbol>>), | ||||
|     Module(Rc<ModuleSymbol>), | ||||
|     Type(Rc<TypeSymbol>), | ||||
|     Function(Rc<RefCell<FunctionSymbol>>), | ||||
|     Parameter(Rc<ParameterSymbol>), | ||||
|     Variable(Rc<VariableSymbol>), | ||||
|     ClassMember(Rc<ClassMemberSymbol>), | ||||
| } | ||||
| 
 | ||||
| impl Symbol { | ||||
|     pub fn definition(&self) -> Option<&SourceDefinition> { | ||||
|     pub fn definition(&self) -> Option<SourceDefinition> { | ||||
|         match self { | ||||
|             Symbol::ConcreteUse(concrete) => concrete.source_definition(), | ||||
|             Symbol::StarUse(star) => star.source_definition(), | ||||
|             Symbol::Module(module) => module.source_definition(), | ||||
|             Symbol::Type(type_symbol) => type_symbol.source_definition(), | ||||
|             Symbol::Function(function_symbol) => function_symbol.source_definition(), | ||||
|             Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition(), | ||||
|             Symbol::Variable(variable_symbol) => variable_symbol.source_definition(), | ||||
|             Symbol::ClassMember(class_member_symbol) => class_member_symbol.source_definition(), | ||||
|             Symbol::UseStatement(s) => s.borrow().definition(), | ||||
|             Symbol::Module(s) => s.definition(), | ||||
|             Symbol::Type(s) => match s.deref() { | ||||
|                 TypeSymbol::Concrete(cts) => cts.definition(), | ||||
|                 TypeSymbol::Generic(gts) => gts.definition(), | ||||
|             }, | ||||
|             Symbol::Function(s) => s.borrow().definition(), | ||||
|             Symbol::Parameter(s) => s.definition(), | ||||
|             Symbol::Variable(s) => s.definition(), | ||||
|             Symbol::ClassMember(s) => s.definition(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn unwrap_use_statement_symbol(&self) -> Rc<RefCell<UseStatementSymbol>> { | ||||
|         match self { | ||||
|             Symbol::UseStatement(s) => s.clone(), | ||||
|             _ => panic!("unwrap_use_statement_symbol called on non-use statement symbol"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Use-statement */ | ||||
| 
 | ||||
| pub struct UseStatementSymbol { | ||||
|     pub fqn: String, | ||||
|     pub declared_name: String, | ||||
|     definition: Option<SourceDefinition>, | ||||
|     referenced_symbol: Option<Box<Symbol>>, | ||||
| } | ||||
| 
 | ||||
| impl UseStatementSymbol { | ||||
|     pub fn new(fqn: &str, declared_name: &str, identifier: Option<&Identifier>) -> Self { | ||||
|         UseStatementSymbol { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             definition: identifier.map(SourceDefinition::from_identifier), | ||||
|             referenced_symbol: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_referenced_symbol(&mut self, referenced_symbol: Symbol) { | ||||
|         self.referenced_symbol = Some(Box::new(referenced_symbol)); | ||||
|     } | ||||
| 
 | ||||
|     pub fn referenced_symbol(&self) -> Option<Box<Symbol>> { | ||||
|         self.referenced_symbol.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for UseStatementSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for UseStatementSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("UseStatementSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("referenced_symbol", &self.referenced_symbol) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Module */ | ||||
| 
 | ||||
| pub struct ModuleSymbol { | ||||
|     fqn: String, | ||||
|     declared_name: String, | ||||
|     is_public: bool, | ||||
|     definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ModuleSymbol { | ||||
|     pub fn new( | ||||
|         fqn: &str, | ||||
|         declared_name: &str, | ||||
|         is_public: bool, | ||||
|         identifier: Option<&Identifier>, | ||||
|     ) -> ModuleSymbol { | ||||
|         ModuleSymbol { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_public, | ||||
|             definition: identifier.map(SourceDefinition::from_identifier), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for ModuleSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         self.declared_name.as_str() | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ModuleSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ModuleSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_public", &self.is_public) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* TypeSymbol */ | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum TypeSymbol { | ||||
|     Concrete(ConcreteTypeSymbol), | ||||
|     Generic(GenericTypeSymbol), | ||||
| } | ||||
| 
 | ||||
| impl TypeSymbol { | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         match self { | ||||
|             TypeSymbol::Concrete(t) => t.declared_name(), | ||||
|             TypeSymbol::Generic(t) => t.declared_name(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ConcreteTypeSymbol { | ||||
|     fqn: String, | ||||
|     declared_name: String, | ||||
|     is_public: bool, | ||||
|     definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ConcreteTypeSymbol { | ||||
|     pub fn new( | ||||
|         fqn: &str, | ||||
|         declared_name: &str, | ||||
|         is_public: bool, | ||||
|         identifier: Option<&Identifier>, | ||||
|     ) -> Self { | ||||
|         ConcreteTypeSymbol { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_public, | ||||
|             definition: identifier.map(SourceDefinition::from_identifier), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn fqn(&self) -> &str { | ||||
|         &self.fqn | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_public(&self) -> bool { | ||||
|         self.is_public | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for ConcreteTypeSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ConcreteTypeSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("TypeSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_public", &self.is_public) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct GenericTypeSymbol { | ||||
|     declared_name: String, | ||||
|     source_definition: SourceDefinition, | ||||
| } | ||||
| 
 | ||||
| impl GenericTypeSymbol { | ||||
|     pub fn new(declared_name: &str, source_definition: SourceDefinition) -> Self { | ||||
|         GenericTypeSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for GenericTypeSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         self.declared_name.as_str() | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         Some(self.source_definition.clone()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for GenericTypeSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("GenericTypeSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Function */ | ||||
| 
 | ||||
| pub struct FunctionSymbol { | ||||
|     fqn: String, | ||||
|     declared_name: String, | ||||
|     is_public: bool, | ||||
|     is_platform: bool, | ||||
|     definition: Option<SourceDefinition>, | ||||
|     parameters: Vec<Rc<ParameterSymbol>>, | ||||
|     return_type: Option<Rc<ConcreteTypeSymbol>>, | ||||
| } | ||||
| 
 | ||||
| impl FunctionSymbol { | ||||
|     pub fn new( | ||||
|         fqn: &str, | ||||
|         declared_name: &str, | ||||
|         is_public: bool, | ||||
|         is_platform: bool, | ||||
|         identifier: Option<&Identifier>, | ||||
|     ) -> FunctionSymbol { | ||||
|         FunctionSymbol { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_public, | ||||
|             is_platform, | ||||
|             definition: identifier.map(SourceDefinition::from_identifier), | ||||
|             parameters: Vec::new(), | ||||
|             return_type: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_parameters(self, parameters: Vec<ParameterSymbol>) -> Self { | ||||
|         Self { | ||||
|             fqn: self.fqn, | ||||
|             declared_name: self.declared_name, | ||||
|             is_public: self.is_public, | ||||
|             is_platform: self.is_platform, | ||||
|             definition: self.definition, | ||||
|             parameters: parameters | ||||
|                 .into_iter() | ||||
|                 .map(|parameter| Rc::new(parameter)) | ||||
|                 .collect(), | ||||
|             return_type: self.return_type, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_return_type(self, return_type: ConcreteTypeSymbol) -> Self { | ||||
|         Self { | ||||
|             fqn: self.fqn, | ||||
|             declared_name: self.declared_name, | ||||
|             is_public: self.is_public, | ||||
|             is_platform: self.is_platform, | ||||
|             definition: self.definition, | ||||
|             parameters: self.parameters, | ||||
|             return_type: Some(Rc::new(return_type)), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn fqn(&self) -> &str { | ||||
|         &self.fqn | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_parameters(&mut self, parameters: Vec<Rc<ParameterSymbol>>) { | ||||
|         self.parameters = parameters; | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_return_type(&mut self, return_type: Rc<ConcreteTypeSymbol>) { | ||||
|         self.return_type = Some(return_type); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for FunctionSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         self.declared_name.as_str() | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for FunctionSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("FunctionSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_public", &self.is_public) | ||||
|             .field("is_platform", &self.is_platform) | ||||
|             .field("parameters", &self.parameters) | ||||
|             .field("return_type", &self.return_type) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Parameter */ | ||||
| 
 | ||||
| pub struct ParameterSymbol { | ||||
|     declared_name: String, | ||||
|     definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ParameterSymbol { | ||||
|     pub fn new(declared_name: &str, identifier: Option<&Identifier>) -> Self { | ||||
|         ParameterSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             definition: identifier.map(SourceDefinition::from_identifier), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for ParameterSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ParameterSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ParameterSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Variable */ | ||||
| 
 | ||||
| pub struct VariableSymbol { | ||||
|     declared_name: String, | ||||
|     is_mutable: bool, | ||||
|     definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl VariableSymbol { | ||||
|     pub fn new(declared_name: &str, is_mutable: bool, identifier: Option<&Identifier>) -> Self { | ||||
|         VariableSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_mutable, | ||||
|             definition: identifier.map(SourceDefinition::from_identifier), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for VariableSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         self.declared_name.as_str() | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for VariableSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("VariableSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_mutable", &self.is_mutable) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Class Member */ | ||||
| 
 | ||||
| pub struct ClassMemberSymbol { | ||||
|     declared_name: String, | ||||
|     is_field: bool, | ||||
|     definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ClassMemberSymbol { | ||||
|     pub fn new(declared_name: &str, is_field: bool, definition: Option<SourceDefinition>) -> Self { | ||||
|         ClassMemberSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_field, | ||||
|             definition, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SymbolInner for ClassMemberSymbol { | ||||
|     fn declared_name(&self) -> &str { | ||||
|         self.declared_name.as_str() | ||||
|     } | ||||
| 
 | ||||
|     fn definition(&self) -> Option<SourceDefinition> { | ||||
|         self.definition.clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ClassMemberSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ClassMemberSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,53 +0,0 @@ | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct ModuleSymbol { | ||||
|     fqn: String, | ||||
|     declared_name: String, | ||||
|     is_public: bool, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ModuleSymbol { | ||||
|     pub fn new( | ||||
|         fqn: &str, | ||||
|         declared_name: &str, | ||||
|         is_public: bool, | ||||
|         source_definition: Option<SourceDefinition>, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_public, | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn fqn(&self) -> &str { | ||||
|         &self.fqn | ||||
|     } | ||||
| 
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_public(&self) -> bool { | ||||
|         self.is_public | ||||
|     } | ||||
| 
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ModuleSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ModuleSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_public", &self.is_public) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| @ -1,34 +0,0 @@ | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct ParameterSymbol { | ||||
|     declared_name: String, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ParameterSymbol { | ||||
|     pub fn new(declared_name: &str, source_definition: Option<SourceDefinition>) -> Self { | ||||
|         ParameterSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
|     
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
|     
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ParameterSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ParameterSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| @ -1,121 +0,0 @@ | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub enum TypeSymbol { | ||||
|     Concrete(ConcreteTypeSymbol), | ||||
|     Generic(GenericTypeSymbol), | ||||
| } | ||||
| 
 | ||||
| impl TypeSymbol { | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         match self { | ||||
|             TypeSymbol::Concrete(t) => t.declared_name(), | ||||
|             TypeSymbol::Generic(t) => t.declared_name(), | ||||
|         } | ||||
|     } | ||||
|     
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         match self { | ||||
|             TypeSymbol::Concrete(t) => t.source_definition(), | ||||
|             TypeSymbol::Generic(t) => t.source_definition(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct ConcreteTypeSymbol { | ||||
|     fqn: String, | ||||
|     declared_name: String, | ||||
|     is_public: bool, | ||||
|     kind: ConcreteTypeSymbolKind, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl ConcreteTypeSymbol { | ||||
|     pub fn new( | ||||
|         fqn: &str, | ||||
|         declared_name: &str, | ||||
|         is_public: bool, | ||||
|         kind: ConcreteTypeSymbolKind, | ||||
|         source_definition: Option<SourceDefinition>, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             fqn: fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_public, | ||||
|             kind, | ||||
|             source_definition | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn fqn(&self) -> &str { | ||||
|         &self.fqn | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_public(&self) -> bool { | ||||
|         self.is_public | ||||
|     } | ||||
|     
 | ||||
|     pub fn kind(&self) -> &ConcreteTypeSymbolKind { | ||||
|         &self.kind | ||||
|     } | ||||
|     
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
|     
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ConcreteTypeSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("TypeSymbol") | ||||
|             .field("fqn", &self.fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_public", &self.is_public) | ||||
|             .field("kind", &self.kind) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub enum ConcreteTypeSymbolKind { | ||||
|     Interface, | ||||
|     Class | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct GenericTypeSymbol { | ||||
|     declared_name: String, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl GenericTypeSymbol { | ||||
|     pub fn new(declared_name: &str, source_definition: Option<SourceDefinition>) -> Self { | ||||
|         GenericTypeSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
|     
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
|     
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for GenericTypeSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("GenericTypeSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| @ -1,56 +1,16 @@ | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct ConcreteUseSymbol { | ||||
|     base_fqn: String, | ||||
|     declared_name: String, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| pub enum UseStatementSymbol { | ||||
|     Concrete, | ||||
|     Star(StarUseStatementSymbol), | ||||
| } | ||||
| 
 | ||||
| impl ConcreteUseSymbol { | ||||
|     pub fn new( | ||||
|         base_fqn: &str, | ||||
|         declared_name: &str, | ||||
|         source_definition: Option<SourceDefinition>, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             base_fqn: base_fqn.to_string(), | ||||
|             declared_name: declared_name.to_string(), | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn base_fqn(&self) -> &str { | ||||
|         &self.base_fqn | ||||
|     } | ||||
| 
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
| 
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for ConcreteUseSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("ConcreteUseStatementSymbol") | ||||
|             .field("base_fqn", &self.base_fqn) | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct StarUseSymbol { | ||||
| pub struct StarUseStatementSymbol { | ||||
|     base_fqn: String, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl StarUseSymbol { | ||||
| impl StarUseStatementSymbol { | ||||
|     pub fn new(base_fqn: &str, source_definition: Option<SourceDefinition>) -> Self { | ||||
|         Self { | ||||
|             base_fqn: base_fqn.to_string(), | ||||
| @ -66,12 +26,3 @@ impl StarUseSymbol { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for StarUseSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("StarUseStatementSymbol") | ||||
|             .field("base_fqn", &self.base_fqn) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,41 +0,0 @@ | ||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||
| use std::fmt::{Debug, Formatter}; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct VariableSymbol { | ||||
|     declared_name: String, | ||||
|     is_mutable: bool, | ||||
|     source_definition: Option<SourceDefinition>, | ||||
| } | ||||
| 
 | ||||
| impl VariableSymbol { | ||||
|     pub fn new(declared_name: &str, is_mutable: bool, source_definition: Option<SourceDefinition>) -> Self { | ||||
|         VariableSymbol { | ||||
|             declared_name: declared_name.to_string(), | ||||
|             is_mutable, | ||||
|             source_definition, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn declared_name(&self) -> &str { | ||||
|         &self.declared_name | ||||
|     } | ||||
|     
 | ||||
|     pub fn is_mutable(&self) -> bool { | ||||
|         self.is_mutable | ||||
|     } | ||||
|     
 | ||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||
|         self.source_definition.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Debug for VariableSymbol { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_struct("VariableSymbol") | ||||
|             .field("declared_name", &self.declared_name) | ||||
|             .field("is_mutable", &self.is_mutable) | ||||
|             .field("source_definition", &self.source_definition) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
							
								
								
									
										468
									
								
								src/name_analysis/symbol_table.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										468
									
								
								src/name_analysis/symbol_table.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,468 @@ | ||||
| use crate::name_analysis::symbol::*; | ||||
| use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; | ||||
| use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; | ||||
| use std::cell::RefCell; | ||||
| use std::collections::HashMap; | ||||
| use std::fmt::Display; | ||||
| use std::ops::Deref; | ||||
| use std::rc::Rc; | ||||
| 
 | ||||
| /* Scope */ | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| struct Scope { | ||||
|     parent: Option<usize>, | ||||
|     use_statement_symbols: HashMap<String, Rc<RefCell<UseStatementSymbol>>>, | ||||
|     module_symbols: HashMap<String, Rc<ModuleSymbol>>, | ||||
|     type_symbols: HashMap<String, Rc<TypeSymbol>>, | ||||
|     function_symbols: HashMap<String, Rc<RefCell<FunctionSymbol>>>, | ||||
|     parameter_symbols: HashMap<String, Rc<ParameterSymbol>>, | ||||
|     variable_symbols: HashMap<String, Rc<VariableSymbol>>, | ||||
|     class_member_symbols: HashMap<String, Rc<ClassMemberSymbol>>, | ||||
|     debug_name: String, | ||||
| } | ||||
| 
 | ||||
| impl Scope { | ||||
|     pub fn new(parent: Option<usize>, debug_name: String) -> Scope { | ||||
|         Scope { | ||||
|             parent, | ||||
|             use_statement_symbols: HashMap::new(), | ||||
|             module_symbols: HashMap::new(), | ||||
|             type_symbols: HashMap::new(), | ||||
|             function_symbols: HashMap::new(), | ||||
|             parameter_symbols: HashMap::new(), | ||||
|             variable_symbols: HashMap::new(), | ||||
|             class_member_symbols: HashMap::new(), | ||||
|             debug_name, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> { | ||||
|         for module_symbol in self.module_symbols.values() { | ||||
|             if module_symbol.declared_name() == name { | ||||
|                 return Some(module_symbol.clone()); | ||||
|             } | ||||
|         } | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     fn get_type_symbol_by_declared_name(&self, declared_name: &str) -> Option<Rc<TypeSymbol>> { | ||||
|         if let Some(type_symbol) = self.type_symbols.get(declared_name) { | ||||
|             Some(type_symbol.clone()) | ||||
|         } else { | ||||
|             for use_statement_symbol in self.use_statement_symbols.values() { | ||||
|                 let borrowed = use_statement_symbol.borrow(); | ||||
|                 if borrowed.declared_name() == declared_name { | ||||
|                     if let Some(referenced_symbol) = borrowed.referenced_symbol() { | ||||
|                         match *referenced_symbol { | ||||
|                             Symbol::Type(type_symbol) => return Some(type_symbol.clone()), | ||||
|                             _ => continue, | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_type_symbol_by_fqn(&self, fqn: &str) -> Option<Rc<TypeSymbol>> { | ||||
|         self.type_symbols | ||||
|             .values() | ||||
|             .find(|s| match s.deref().deref() { | ||||
|                 TypeSymbol::Concrete(cts) => cts.fqn() == fqn, | ||||
|                 _ => false, | ||||
|             }) | ||||
|             .cloned() | ||||
|     } | ||||
| 
 | ||||
|     fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> { | ||||
|         for function_symbol in self.function_symbols.values() { | ||||
|             if function_symbol.borrow().fqn() == fqn { | ||||
|                 return Some(Symbol::Function(function_symbol.clone())); | ||||
|             } | ||||
|         } | ||||
|         for type_symbol in self.type_symbols.values() { | ||||
|             match type_symbol.deref() { | ||||
|                 TypeSymbol::Concrete(concrete_type_symbol) => { | ||||
|                     if concrete_type_symbol.fqn() == fqn { | ||||
|                         return Some(Symbol::Type(type_symbol.clone())); | ||||
|                     } | ||||
|                 } | ||||
|                 _ => continue, | ||||
|             } | ||||
|         } | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> { | ||||
|         for function_symbol in self.function_symbols.values() { | ||||
|             if function_symbol.borrow().declared_name() == declared_name { | ||||
|                 return Some(Symbol::Function(function_symbol.clone())); | ||||
|             } | ||||
|         } | ||||
|         for type_symbol in self.type_symbols.values() { | ||||
|             if type_symbol.declared_name() == declared_name { | ||||
|                 return Some(Symbol::Type(type_symbol.clone())); | ||||
|             } | ||||
|         } | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     fn get_value_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> { | ||||
|         for variable_symbol in self.variable_symbols.values() { | ||||
|             if variable_symbol.declared_name() == declared_name { | ||||
|                 return Some(Symbol::Variable(variable_symbol.clone())); | ||||
|             } | ||||
|         } | ||||
|         for parameter_symbol in self.parameter_symbols.values() { | ||||
|             if parameter_symbol.declared_name() == declared_name { | ||||
|                 return Some(Symbol::Parameter(parameter_symbol.clone())); | ||||
|             } | ||||
|         } | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     fn get_expressible_by_declared_name(&self, declared_name: &str) -> Option<Symbol> { | ||||
|         self.variable_symbols | ||||
|             .get(declared_name) | ||||
|             .map(|s| Symbol::Variable(s.clone())) | ||||
|             .or_else(|| { | ||||
|                 self.parameter_symbols | ||||
|                     .get(declared_name) | ||||
|                     .map(|p| Symbol::Parameter(p.clone())) | ||||
|             }) | ||||
|             .or_else(|| { | ||||
|                 self.class_member_symbols | ||||
|                     .get(declared_name) | ||||
|                     .map(|cms| Symbol::ClassMember(cms.clone())) | ||||
|             }) | ||||
|             .or_else(|| { | ||||
|                 self.function_symbols | ||||
|                     .get(declared_name) | ||||
|                     .map(|f| Symbol::Function(f.clone())) | ||||
|             }) | ||||
|             .or_else(|| { | ||||
|                 self.type_symbols | ||||
|                     .get(declared_name) | ||||
|                     .map(|t| Symbol::Type(t.clone())) | ||||
|             }) | ||||
|             .or_else(|| { | ||||
|                 self.use_statement_symbols | ||||
|                     .get(declared_name) | ||||
|                     .map(|us| Symbol::UseStatement(us.clone())) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     fn get_expressible_by_fqn(&self, fqn: &str) -> Option<Symbol> { | ||||
|         self.function_symbols | ||||
|             .values() | ||||
|             .find(|fs| fs.borrow().fqn() == fqn) | ||||
|             .map(|f| Symbol::Function(f.clone())) | ||||
|             .or_else(|| { | ||||
|                 self.get_type_symbol_by_fqn(fqn) | ||||
|                     .map(|ts| Symbol::Type(ts.clone())) | ||||
|             }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Symbol table */ | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum SymbolInsertError { | ||||
|     SymbolAlreadyDefined(Symbol), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum SymbolLookupError { | ||||
|     NoDefinition, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SymbolTable { | ||||
|     scopes: Vec<Scope>, | ||||
|     current_scope_id: usize, | ||||
| } | ||||
| 
 | ||||
| /// Contains a vec of scopes, like a flattened tree
 | ||||
| impl SymbolTable { | ||||
|     pub fn new() -> Self { | ||||
|         let mut t = SymbolTable { | ||||
|             scopes: vec![Scope::new(None, String::from("GlobalScope"))], | ||||
|             current_scope_id: 0, | ||||
|         }; | ||||
|         t | ||||
|     } | ||||
| 
 | ||||
|     pub fn current_scope_id(&self) -> usize { | ||||
|         self.current_scope_id | ||||
|     } | ||||
| 
 | ||||
|     pub fn scopes(&self) -> &Vec<Scope> { | ||||
|         &self.scopes | ||||
|     } | ||||
| 
 | ||||
|     pub fn push_scope(&mut self, debug_name: &str) { | ||||
|         let id = self.scopes.len(); | ||||
|         self.scopes.push(Scope::new( | ||||
|             Some(self.current_scope_id), | ||||
|             debug_name.to_string(), | ||||
|         )); | ||||
|         self.current_scope_id = id; | ||||
|     } | ||||
| 
 | ||||
|     pub fn pop_scope(&mut self) { | ||||
|         if let Some(parent_id) = self.scopes[self.current_scope_id].parent { | ||||
|             self.current_scope_id = parent_id; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_use_statement_symbol( | ||||
|         &mut self, | ||||
|         use_statement_symbol: UseStatementSymbol, | ||||
|     ) -> Result<Rc<RefCell<UseStatementSymbol>>, SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             let declared_name = use_statement_symbol.declared_name().to_string(); | ||||
|             let to_insert = Rc::new(RefCell::new(use_statement_symbol)); | ||||
|             let to_return = to_insert.clone(); | ||||
|             current_scope | ||||
|                 .use_statement_symbols | ||||
|                 .insert(declared_name, to_insert); | ||||
|             Ok(to_return) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_module_symbol( | ||||
|         &mut self, | ||||
|         module_symbol: ModuleSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_module_symbol_by_declared_name(module_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(Symbol::Module(defined_symbol.clone()))) | ||||
|         } else { | ||||
|             current_scope.module_symbols.insert( | ||||
|                 module_symbol.declared_name().to_string(), | ||||
|                 Rc::new(module_symbol), | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_usable_symbol_by_declared_name(type_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             current_scope.type_symbols.insert( | ||||
|                 type_symbol.declared_name().to_string(), | ||||
|                 Rc::new(type_symbol), | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_function_symbol( | ||||
|         &mut self, | ||||
|         function_symbol: FunctionSymbol, | ||||
|     ) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             let declared_name = function_symbol.declared_name().to_string(); | ||||
|             let to_insert = Rc::new(RefCell::new(function_symbol)); | ||||
|             let to_return = to_insert.clone(); | ||||
|             current_scope | ||||
|                 .function_symbols | ||||
|                 .insert(declared_name, to_insert); | ||||
|             Ok(to_return) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_parameter_symbol( | ||||
|         &mut self, | ||||
|         parameter_symbol: ParameterSymbol, | ||||
|     ) -> Result<Rc<ParameterSymbol>, SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             let to_insert = Rc::new(parameter_symbol); | ||||
|             let to_return = to_insert.clone(); | ||||
|             current_scope | ||||
|                 .parameter_symbols | ||||
|                 .insert(to_insert.declared_name().to_string(), to_insert); | ||||
|             Ok(to_return) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_variable_symbol( | ||||
|         &mut self, | ||||
|         variable_symbol: VariableSymbol, | ||||
|     ) -> Result<Rc<VariableSymbol>, SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_value_symbol_by_declared_name(variable_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             let declared_name = variable_symbol.declared_name().to_string(); | ||||
|             let to_insert = Rc::new(variable_symbol); | ||||
|             let to_return = to_insert.clone(); | ||||
|             current_scope | ||||
|                 .variable_symbols | ||||
|                 .insert(declared_name, to_insert); | ||||
|             Ok(to_return) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_class_member_symbol( | ||||
|         &mut self, | ||||
|         class_member_symbol: ClassMemberSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||
|         if let Some(defined_symbol) = | ||||
|             current_scope.get_expressible_by_declared_name(class_member_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             current_scope.class_member_symbols.insert( | ||||
|                 class_member_symbol.declared_name().to_string(), | ||||
|                 Rc::new(class_member_symbol), | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_type_by_declared_name( | ||||
|         &self, | ||||
|         declared_name: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<Rc<TypeSymbol>, SymbolLookupError> { | ||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||
|         while let Some(scope) = scope_opt { | ||||
|             if let Some(symbol) = scope.get_type_symbol_by_declared_name(declared_name) { | ||||
|                 return Ok(symbol); | ||||
|             } | ||||
|             scope_opt = if let Some(parent_id) = scope.parent { | ||||
|                 Some(&self.scopes[parent_id]) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_type_by_fqn( | ||||
|         &self, | ||||
|         fqn: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<Rc<TypeSymbol>, SymbolLookupError> { | ||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||
|         while let Some(scope) = scope_opt { | ||||
|             if let Some(symbol) = scope.get_type_symbol_by_fqn(fqn) { | ||||
|                 return Ok(symbol); | ||||
|             } | ||||
|             scope_opt = if let Some(parent_id) = scope.parent { | ||||
|                 Some(&self.scopes[parent_id]) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_usable_by_fqn( | ||||
|         &self, | ||||
|         fully_qualified_name: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<Symbol, SymbolLookupError> { | ||||
|         for scope in &self.scopes { | ||||
|             if let Some(symbol) = scope.get_usable_symbol_by_fqn(fully_qualified_name) { | ||||
|                 return Ok(symbol); | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_expressible_by_declared_name( | ||||
|         &self, | ||||
|         declared_name: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<Symbol, SymbolLookupError> { | ||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||
|         while let Some(scope) = scope_opt { | ||||
|             if let Some(symbol) = scope.get_expressible_by_declared_name(declared_name) { | ||||
|                 return Ok(symbol); | ||||
|             } | ||||
|             scope_opt = if let Some(parent_id) = scope.parent { | ||||
|                 Some(&self.scopes[parent_id]) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_expressible_by_fqn( | ||||
|         &self, | ||||
|         fqn: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<Symbol, SymbolLookupError> { | ||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||
|         while let Some(scope) = scope_opt { | ||||
|             if let Some(symbol) = scope.get_expressible_by_fqn(fqn) { | ||||
|                 return Ok(symbol); | ||||
|             } | ||||
|             scope_opt = if let Some(parent_id) = scope.parent { | ||||
|                 Some(&self.scopes[parent_id]) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for SymbolTable { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||||
|         writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; | ||||
|         for (i, scope) in self.scopes.iter().enumerate() { | ||||
|             writeln!(f, "----Scope {} {}----", i, scope.debug_name)?; | ||||
|             for symbol in scope.use_statement_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol.borrow())?; | ||||
|             } | ||||
|             for symbol in scope.module_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol)?; | ||||
|             } | ||||
|             for symbol in scope.type_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol)?; | ||||
|             } | ||||
|             for symbol in scope.function_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol.borrow())?; | ||||
|             } | ||||
|             for symbol in scope.parameter_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol)?; | ||||
|             } | ||||
|             for symbol in scope.variable_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol)?; | ||||
|             } | ||||
|             for symbol in scope.class_member_symbols.values() { | ||||
|                 writeln!(f, "{:#?}", symbol)?; | ||||
|             } | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @ -1,333 +0,0 @@ | ||||
| use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol; | ||||
| use crate::name_analysis::symbol::function_symbol::FunctionSymbol; | ||||
| use crate::name_analysis::symbol::module_symbol::ModuleSymbol; | ||||
| use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; | ||||
| use crate::name_analysis::symbol::type_symbol::TypeSymbol; | ||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | ||||
| use crate::name_analysis::symbol::variable_symbol::VariableSymbol; | ||||
| use crate::name_analysis::symbol::*; | ||||
| use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; | ||||
| use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; | ||||
| use scope::Scope; | ||||
| use std::fmt::Display; | ||||
| use std::ops::Deref; | ||||
| 
 | ||||
| mod scope; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum SymbolInsertError { | ||||
|     SymbolAlreadyDefined(Symbol), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum SymbolLookupError { | ||||
|     NoDefinition, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SymbolTable { | ||||
|     scopes: Vec<Scope>, | ||||
|     current_scope_id: usize, | ||||
| } | ||||
| 
 | ||||
| /// Contains a vec of scopes, like a flattened tree
 | ||||
| impl SymbolTable { | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             scopes: vec![Scope::new(None, 0, String::from("GlobalScope"))], | ||||
|             current_scope_id: 0, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn current_scope_id(&self) -> usize { | ||||
|         self.current_scope_id | ||||
|     } | ||||
| 
 | ||||
|     pub fn push_scope(&mut self, debug_name: &str) { | ||||
|         let id = self.scopes.len(); | ||||
|         self.scopes | ||||
|             .push(Scope::new(Some(self.current_scope_id), id, debug_name.to_string())); | ||||
|         self.current_scope_id = id; | ||||
|     } | ||||
| 
 | ||||
|     pub fn pop_scope(&mut self) { | ||||
|         if let Some(parent_id) = self.scopes[self.current_scope_id].parent() { | ||||
|             self.current_scope_id = parent_id; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn current_scope(&self) -> &Scope { | ||||
|         self.scopes.last().unwrap() | ||||
|     } | ||||
| 
 | ||||
|     fn current_scope_mut(&mut self) -> &mut Scope { | ||||
|         self.scopes.last_mut().unwrap() | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_concrete_use_symbol( | ||||
|         &self, | ||||
|         declared_name: &str, | ||||
|     ) -> Option<&ConcreteUseSymbol> { | ||||
|         self.current_scope() | ||||
|             .concrete_use_symbols() | ||||
|             .get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_star_use_symbol(&self, base_fqn: &str) -> Option<&StarUseSymbol> { | ||||
|         self.current_scope().star_use_symbols().get(base_fqn) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_type_symbol(&self, declared_name: &str) -> Option<&TypeSymbol> { | ||||
|         self.current_scope().type_symbols().get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_module_symbol(&self, declared_name: &str) -> Option<&ModuleSymbol> { | ||||
|         self.current_scope().module_symbols().get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_parameter_symbol(&self, declared_name: &str) -> Option<&ParameterSymbol> { | ||||
|         self.current_scope().parameter_symbols().get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_variable_symbol(&self, declared_name: &str) -> Option<&VariableSymbol> { | ||||
|         self.current_scope().variable_symbols().get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_class_member_symbol( | ||||
|         &self, | ||||
|         declared_name: &str, | ||||
|     ) -> Option<&ClassMemberSymbol> { | ||||
|         self.current_scope() | ||||
|             .class_member_symbols() | ||||
|             .get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_variable_or_parameter_symbol( | ||||
|         &self, | ||||
|         declared_name: &str, | ||||
|     ) -> Option<Symbol> { | ||||
|         self.find_current_scope_variable_symbol(declared_name) | ||||
|             .map(|variable_symbol| Symbol::Variable(variable_symbol.clone())) | ||||
|             .or_else(|| { | ||||
|                 self.find_current_scope_parameter_symbol(declared_name) | ||||
|                     .map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone())) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     fn find_current_scope_usable_symbol(&self, declared_name: &str) -> Option<Symbol> { | ||||
|         self.find_current_scope_concrete_use_symbol(declared_name) | ||||
|             .map(|concrete_use_symbol| Symbol::ConcreteUse(concrete_use_symbol.clone())) | ||||
|             .or_else(|| { | ||||
|                 self.find_current_scope_type_symbol(declared_name) | ||||
|                     .map(|type_symbol| Symbol::Type(type_symbol.clone())) | ||||
|             }) | ||||
|             .or_else(|| { | ||||
|                 self.find_current_scope_module_symbol(declared_name) | ||||
|                     .map(|module_symbol| Symbol::Module(module_symbol.clone())) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_concrete_use_symbol( | ||||
|         &mut self, | ||||
|         concrete_use_symbol: ConcreteUseSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             self.current_scope_mut().concrete_use_symbols_mut().insert( | ||||
|                 concrete_use_symbol.declared_name().to_string(), | ||||
|                 concrete_use_symbol, | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_star_use_symbol( | ||||
|         &mut self, | ||||
|         star_use_symbol: StarUseSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(Symbol::StarUse( | ||||
|                 defined_symbol.clone(), | ||||
|             ))) | ||||
|         } else { | ||||
|             self.current_scope_mut() | ||||
|                 .star_use_symbols_mut() | ||||
|                 .insert(star_use_symbol.base_fqn().to_string(), star_use_symbol); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_module_symbol( | ||||
|         &mut self, | ||||
|         module_symbol: ModuleSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_usable_symbol(module_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             self.current_scope_mut() | ||||
|                 .module_symbols_mut() | ||||
|                 .insert(module_symbol.declared_name().to_string(), module_symbol); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_usable_symbol(type_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             self.current_scope_mut() | ||||
|                 .type_symbols_mut() | ||||
|                 .insert(type_symbol.declared_name().to_string(), type_symbol); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_function_symbol( | ||||
|         &mut self, | ||||
|         function_symbol: FunctionSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_usable_symbol(function_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             self.current_scope_mut() | ||||
|                 .function_symbols_mut() | ||||
|                 .insert(function_symbol.declared_name().to_string(), function_symbol); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_parameter_symbol( | ||||
|         &mut self, | ||||
|         parameter_symbol: ParameterSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_parameter_symbol(parameter_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(Symbol::Parameter( | ||||
|                 defined_symbol.clone(), | ||||
|             ))) | ||||
|         } else { | ||||
|             self.current_scope_mut().parameter_symbols_mut().insert( | ||||
|                 parameter_symbol.declared_name().to_string(), | ||||
|                 parameter_symbol, | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_variable_symbol( | ||||
|         &mut self, | ||||
|         variable_symbol: VariableSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_variable_or_parameter_symbol(variable_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(defined_symbol)) | ||||
|         } else { | ||||
|             self.current_scope_mut() | ||||
|                 .variable_symbols_mut() | ||||
|                 .insert(variable_symbol.declared_name().to_string(), variable_symbol); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn insert_class_member_symbol( | ||||
|         &mut self, | ||||
|         class_member_symbol: ClassMemberSymbol, | ||||
|     ) -> Result<(), SymbolInsertError> { | ||||
|         if let Some(defined_symbol) = | ||||
|             self.find_current_scope_class_member_symbol(class_member_symbol.declared_name()) | ||||
|         { | ||||
|             Err(SymbolAlreadyDefined(Symbol::ClassMember( | ||||
|                 defined_symbol.clone(), | ||||
|             ))) | ||||
|         } else { | ||||
|             self.current_scope_mut().class_member_symbols_mut().insert( | ||||
|                 class_member_symbol.declared_name().to_string(), | ||||
|                 class_member_symbol, | ||||
|             ); | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn lookup_type_in_scope_by_declared_name<'a>( | ||||
|         scope: &'a Scope, | ||||
|         declared_name: &str, | ||||
|     ) -> Option<&'a TypeSymbol> { | ||||
|         scope.type_symbols().get(declared_name) | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_type_by_declared_name( | ||||
|         &self, | ||||
|         declared_name: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<&TypeSymbol, SymbolLookupError> { | ||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||
|         while let Some(scope) = scope_opt { | ||||
|             if let Some(symbol) = Self::lookup_type_in_scope_by_declared_name(scope, declared_name) | ||||
|             { | ||||
|                 return Ok(symbol); | ||||
|             } | ||||
|             scope_opt = if let Some(parent_id) = scope.parent() { | ||||
|                 Some(&self.scopes[parent_id]) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| 
 | ||||
|     fn lookup_type_in_scope_by_fqn<'a>(scope: &'a Scope, fqn: &str) -> Option<&'a TypeSymbol> { | ||||
|         for type_symbol in scope.type_symbols().values() { | ||||
|             match type_symbol { | ||||
|                 TypeSymbol::Concrete(concrete_type_symbol) => { | ||||
|                     if concrete_type_symbol.fqn() == fqn { | ||||
|                         return Some(type_symbol); | ||||
|                     } | ||||
|                 } | ||||
|                 TypeSymbol::Generic(_) => {} | ||||
|             } | ||||
|         } | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     pub fn lookup_type_by_fqn( | ||||
|         &self, | ||||
|         fqn: &str, | ||||
|         scope_id: usize, | ||||
|     ) -> Result<&TypeSymbol, SymbolLookupError> { | ||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||
|         while let Some(scope) = scope_opt { | ||||
|             if let Some(type_symbol) = Self::lookup_type_in_scope_by_fqn(scope, fqn) { | ||||
|                 return Ok(type_symbol); | ||||
|             } | ||||
|             scope_opt = if let Some(parent_id) = scope.parent() { | ||||
|                 Some(&self.scopes[parent_id]) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } | ||||
|         Err(NoDefinition) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for SymbolTable { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||||
|         writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; | ||||
|         for scope in &self.scopes { | ||||
|             writeln!(f, "{}", scope)?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @ -1,141 +0,0 @@ | ||||
| use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol; | ||||
| use crate::name_analysis::symbol::function_symbol::FunctionSymbol; | ||||
| use crate::name_analysis::symbol::module_symbol::ModuleSymbol; | ||||
| use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; | ||||
| use crate::name_analysis::symbol::type_symbol::TypeSymbol; | ||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | ||||
| use crate::name_analysis::symbol::variable_symbol::VariableSymbol; | ||||
| use std::collections::HashMap; | ||||
| use std::fmt::{Display, Formatter}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct Scope { | ||||
|     parent: Option<usize>, | ||||
|     id: usize, | ||||
|     concrete_use_symbols: HashMap<String, ConcreteUseSymbol>, | ||||
|     star_use_symbols: HashMap<String, StarUseSymbol>, | ||||
|     module_symbols: HashMap<String, ModuleSymbol>, | ||||
|     type_symbols: HashMap<String, TypeSymbol>, | ||||
|     function_symbols: HashMap<String, FunctionSymbol>, | ||||
|     parameter_symbols: HashMap<String, ParameterSymbol>, | ||||
|     variable_symbols: HashMap<String, VariableSymbol>, | ||||
|     class_member_symbols: HashMap<String, ClassMemberSymbol>, | ||||
|     debug_name: String, | ||||
| } | ||||
| 
 | ||||
| impl Scope { | ||||
|     pub fn new(parent: Option<usize>, id: usize, debug_name: String) -> Self { | ||||
|         Self { | ||||
|             parent, | ||||
|             id, | ||||
|             concrete_use_symbols: HashMap::new(), | ||||
|             star_use_symbols: HashMap::new(), | ||||
|             module_symbols: HashMap::new(), | ||||
|             type_symbols: HashMap::new(), | ||||
|             function_symbols: HashMap::new(), | ||||
|             parameter_symbols: HashMap::new(), | ||||
|             variable_symbols: HashMap::new(), | ||||
|             class_member_symbols: HashMap::new(), | ||||
|             debug_name, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn parent(&self) -> Option<usize> { | ||||
|         self.parent | ||||
|     } | ||||
| 
 | ||||
|     pub fn id(&self) -> usize { | ||||
|         self.id | ||||
|     } | ||||
| 
 | ||||
|     pub fn concrete_use_symbols(&self) -> &HashMap<String, ConcreteUseSymbol> { | ||||
|         &self.concrete_use_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn concrete_use_symbols_mut(&mut self) -> &mut HashMap<String, ConcreteUseSymbol> { | ||||
|         &mut self.concrete_use_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn star_use_symbols(&self) -> &HashMap<String, StarUseSymbol> { | ||||
|         &self.star_use_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn star_use_symbols_mut(&mut self) -> &mut HashMap<String, StarUseSymbol> { | ||||
|         &mut self.star_use_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn module_symbols(&self) -> &HashMap<String, ModuleSymbol> { | ||||
|         &self.module_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn module_symbols_mut(&mut self) -> &mut HashMap<String, ModuleSymbol> { | ||||
|         &mut self.module_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn type_symbols(&self) -> &HashMap<String, TypeSymbol> { | ||||
|         &self.type_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn type_symbols_mut(&mut self) -> &mut HashMap<String, TypeSymbol> { | ||||
|         &mut self.type_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> { | ||||
|         &self.function_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn function_symbols_mut(&mut self) -> &mut HashMap<String, FunctionSymbol> { | ||||
|         &mut self.function_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn parameter_symbols(&self) -> &HashMap<String, ParameterSymbol> { | ||||
|         &self.parameter_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn parameter_symbols_mut(&mut self) -> &mut HashMap<String, ParameterSymbol> { | ||||
|         &mut self.parameter_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn variable_symbols(&self) -> &HashMap<String, VariableSymbol> { | ||||
|         &self.variable_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn variable_symbols_mut(&mut self) -> &mut HashMap<String, VariableSymbol> { | ||||
|         &mut self.variable_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn class_member_symbols(&self) -> &HashMap<String, ClassMemberSymbol> { | ||||
|         &self.class_member_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn class_member_symbols_mut(&mut self) -> &mut HashMap<String, ClassMemberSymbol> { | ||||
|         &mut self.class_member_symbols | ||||
|     } | ||||
| 
 | ||||
|     pub fn debug_name(&self) -> &str { | ||||
|         &self.debug_name | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| macro_rules! write_symbols { | ||||
|     ( $f:expr, $symbols:expr ) => { | ||||
|         for symbol in $symbols.values() { | ||||
|             writeln!($f, "{:#?}", symbol)?; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| impl Display for Scope { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||
|         writeln!(f, "----Scope {} {}----", self.id(), self.debug_name())?; | ||||
|         write_symbols!(f, self.concrete_use_symbols()); | ||||
|         write_symbols!(f, self.star_use_symbols()); | ||||
|         write_symbols!(f, self.module_symbols()); | ||||
|         write_symbols!(f, self.type_symbols()); | ||||
|         write_symbols!(f, self.function_symbols()); | ||||
|         write_symbols!(f, self.parameter_symbols()); | ||||
|         write_symbols!(f, self.variable_symbols()); | ||||
|         write_symbols!(f, self.class_member_symbols()); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @ -88,7 +88,6 @@ $defs: | ||||
|       - $ref: "#/$defs/StructChildSkipHash" | ||||
|       - $ref: "#/$defs/StructChildVecHash" | ||||
|       - $ref: "#/$defs/StructChildMemberHash" | ||||
|       - $ref: "#/$defs/StructChildSpecialHash" | ||||
|   StructChildSkipHash: | ||||
|     type: object | ||||
|     additionalProperties: false | ||||
| @ -149,6 +148,7 @@ $defs: | ||||
|     oneOf: | ||||
|       - $ref: "#/$defs/StructChildMemberBuildNodeHash" | ||||
|       - $ref: "#/$defs/StructChildMemberBuildBooleanHash" | ||||
|       - $ref: "#/$defs/StructChildMemberBuildSpecialHash" | ||||
|   StructChildMemberBuildNodeHash: | ||||
|     type: object | ||||
|     additionalProperties: false | ||||
| @ -191,7 +191,7 @@ $defs: | ||||
|           - rule_present | ||||
|     required: | ||||
|       - on | ||||
|   StructChildSpecialHash: | ||||
|   StructChildMemberBuildSpecialHash: | ||||
|     type: object | ||||
|     additionalProperties: false | ||||
|     description: A special member to be built. | ||||
|  | ||||
| @ -181,7 +181,7 @@ ReturnType: | ||||
| CompilationUnit: | ||||
|   struct: | ||||
|     children: | ||||
|       - namespace: | ||||
|       - parent_mod: | ||||
|           member: | ||||
|             optional: true | ||||
|       - use_statements: | ||||
| @ -193,15 +193,12 @@ CompilationUnit: | ||||
|       - eoi: | ||||
|           skip: | ||||
|             rule: EOI | ||||
|       - file_id: | ||||
|           special: | ||||
|             kind: file_id | ||||
| Namespace: | ||||
| ParentMod: | ||||
|   struct: | ||||
|     children: | ||||
|       - ns_kw: | ||||
|       - mod_kw: | ||||
|           skip: | ||||
|             rule: Ns | ||||
|             rule: Mod | ||||
|       - fqn: | ||||
|           member: | ||||
|             rule: FullyQualifiedName | ||||
| @ -218,9 +215,13 @@ UseStatement: | ||||
|           member: | ||||
|             rule: UseStatementSuffix | ||||
|       - file_id: | ||||
|           member:  | ||||
|             build: | ||||
|               special: | ||||
|                 kind: file_id | ||||
|       - range: | ||||
|           member:  | ||||
|             build: | ||||
|               special: | ||||
|                 kind: range | ||||
| UseStatementPrefix: | ||||
| @ -253,6 +254,7 @@ ModuleLevelDeclaration: | ||||
| InterfaceLevelDeclaration: | ||||
|   tree_enum: | ||||
|     rules: | ||||
|       - CompanionModule | ||||
|       - Interface | ||||
|       - Class | ||||
|       - InterfaceFunction | ||||
| @ -262,6 +264,7 @@ InterfaceLevelDeclaration: | ||||
| ClassLevelDeclaration: | ||||
|   tree_enum: | ||||
|     rules: | ||||
|       - CompanionModule | ||||
|       - Interface | ||||
|       - Class | ||||
|       - Function | ||||
| @ -288,6 +291,21 @@ Module: | ||||
|       - end_kw: | ||||
|           skip: | ||||
|             rule: End | ||||
| CompanionModule: | ||||
|   struct: | ||||
|     children: | ||||
|       - companion_kw: | ||||
|           skip: | ||||
|             rule: Companion | ||||
|       - mod_kw: | ||||
|           skip: | ||||
|             rule: Mod | ||||
|       - declarations: | ||||
|           vec: | ||||
|             rule: ModuleLevelDeclaration | ||||
|       - end_kw: | ||||
|           skip: | ||||
|             rule: End | ||||
| Interface: | ||||
|   struct: | ||||
|     children: | ||||
|  | ||||
| @ -307,13 +307,13 @@ ReturnType = { | ||||
| 
 | ||||
| CompilationUnit = { | ||||
|       SOI | ||||
|     ~ Namespace? | ||||
|     ~ ParentMod? | ||||
|     ~ ( UseStatement | ModuleLevelDeclaration )* | ||||
|     ~ EOI | ||||
| } | ||||
| 
 | ||||
| Namespace = { | ||||
|       Ns | ||||
| ParentMod = { | ||||
|       Mod | ||||
|     ~ FullyQualifiedName | ||||
| } | ||||
| 
 | ||||
| @ -352,7 +352,8 @@ ModuleLevelDeclaration = { | ||||
| } | ||||
| 
 | ||||
| InterfaceLevelDeclaration = { | ||||
|       Interface | ||||
|       CompanionModule | ||||
|     | Interface | ||||
|     | Class | ||||
|     | InterfaceFunction | ||||
|     | InterfaceDefaultFunction | ||||
| @ -361,7 +362,8 @@ InterfaceLevelDeclaration = { | ||||
| } | ||||
| 
 | ||||
| ClassLevelDeclaration = { | ||||
|       Interface | ||||
|       CompanionModule | ||||
|     | Interface | ||||
|     | Class | ||||
|     | Function | ||||
|     | OperatorFunction | ||||
| @ -378,6 +380,13 @@ Module = { | ||||
|     ~ End | ||||
| } | ||||
| 
 | ||||
| CompanionModule = { | ||||
|       Companion | ||||
|     ~ Mod | ||||
|     ~ ModuleLevelDeclaration* | ||||
|     ~ End | ||||
| } | ||||
| 
 | ||||
| Interface = { | ||||
|       Pub? | ||||
|     ~ IntKw | ||||
|  | ||||
| @ -1,26 +1,13 @@ | ||||
| use crate::name_analysis::symbol::function_symbol::FunctionSymbol; | ||||
| use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; | ||||
| use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol}; | ||||
| use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | ||||
| 
 | ||||
| pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { | ||||
|     symbol_table.insert_function_symbol( | ||||
|         FunctionSymbol::without_parameters_or_return_type( | ||||
|             "std::core::println", | ||||
|             "println", | ||||
|             true, | ||||
|             true, | ||||
|             None, | ||||
|         ) | ||||
|         FunctionSymbol::new("std::core::println", "println", true, true, None) | ||||
|             .with_parameters(vec![ParameterSymbol::new("msg", None)]), | ||||
|     )?; | ||||
|     symbol_table.insert_function_symbol( | ||||
|         FunctionSymbol::without_parameters_or_return_type( | ||||
|             "std::core::print", | ||||
|             "print", | ||||
|             true, | ||||
|             true, | ||||
|             None, | ||||
|         ) | ||||
|         FunctionSymbol::new("std::core::print", "print", true, true, None) | ||||
|             .with_parameters(vec![ParameterSymbol::new("msg", None)]), | ||||
|     )?; | ||||
|     Ok(()) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user