Compare commits
	
		
			7 Commits
		
	
	
		
			e578250ee6
			...
			d5ac6dfc2d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d5ac6dfc2d | ||
|   | 36e28ae4a9 | ||
|   | 9731bb38fe | ||
|   | 8969186467 | ||
|   | e879ad2d90 | ||
|   | 54882b187c | ||
|   | 1f5d17ef79 | 
| @ -36,8 +36,8 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 MemberChildBuild::Boolean(_) => None, |                 MemberChildBuild::Boolean(_) => None, | ||||||
|                 MemberChildBuild::Special(_) => None, |  | ||||||
|             }, |             }, | ||||||
|  |             StructChild::Special(_) => None, | ||||||
|         }) |         }) | ||||||
|         .filter(Option::is_some) |         .filter(Option::is_some) | ||||||
|         .map(Option::unwrap) |         .map(Option::unwrap) | ||||||
|  | |||||||
| @ -1,8 +1,44 @@ | |||||||
| use crate::deserialize::util::{make_build_fn_name, make_build_pair}; | use crate::deserialize::util::{make_build_fn_name, make_build_pair}; | ||||||
| use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild}; | use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, VecChild, VecChildBuild}; | ||||||
| use proc_macro2::{Ident, TokenStream}; | use proc_macro2::{Ident, TokenStream}; | ||||||
| use quote::{format_ident, quote}; | 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 { | fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream { | ||||||
|     let child_ident = format_ident!("{}", vec_child.name()); |     let child_ident = format_ident!("{}", vec_child.name()); | ||||||
|     match vec_child.build() { |     match vec_child.build() { | ||||||
| @ -44,8 +80,8 @@ fn make_child_holder(child_spec: &StructChild) -> Option<TokenStream> { | |||||||
|                 Some(make_node_child_holder(member_child.name(), node_child)) |                 Some(make_node_child_holder(member_child.name(), node_child)) | ||||||
|             } |             } | ||||||
|             MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())), |             MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())), | ||||||
|             MemberChildBuild::Special(_) => None, |  | ||||||
|         }, |         }, | ||||||
|  |         StructChild::Special(_) => None, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -84,7 +120,12 @@ fn make_boolean_member_child_match_action(name: &str) -> TokenStream { | |||||||
| 
 | 
 | ||||||
| fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {    
 | fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {    
 | ||||||
|     match child_spec { |     match child_spec { | ||||||
|         StructChild::SkipChild(_) => None, |         StructChild::SkipChild(skip_child) => { | ||||||
|  |             let rule_ident = format_ident!("{}", skip_child.rule()); | ||||||
|  |             Some(quote! { | ||||||
|  |                 Rule::#rule_ident => {} | ||||||
|  |             }) | ||||||
|  |         }, | ||||||
|         StructChild::VecChild(vec_child) => { |         StructChild::VecChild(vec_child) => { | ||||||
|             let rule_ident = format_ident!("{}", vec_child.rule()); |             let rule_ident = format_ident!("{}", vec_child.rule()); | ||||||
|             let action = make_vec_child_match_action(vec_child); |             let action = make_vec_child_match_action(vec_child); | ||||||
| @ -111,9 +152,9 @@ fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> { | |||||||
|                         Rule::#rule_ident => { #action } |                         Rule::#rule_ident => { #action } | ||||||
|                     }) |                     }) | ||||||
|                 } |                 } | ||||||
|                 MemberChildBuild::Special(_) => None |  | ||||||
|             } |  | ||||||
|             } |             } | ||||||
|  |         }, | ||||||
|  |         StructChild::Special(_) => None | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -146,6 +187,11 @@ fn make_boolean_member_child_arg(name: &str) -> TokenStream { | |||||||
|     quote! { #child_ident } |     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> { | fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> { | ||||||
|     match child_spec { |     match child_spec { | ||||||
|         StructChild::SkipChild(_) => None, |         StructChild::SkipChild(_) => None, | ||||||
| @ -159,22 +205,8 @@ fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenS | |||||||
|             MemberChildBuild::Boolean(_) => { |             MemberChildBuild::Boolean(_) => { | ||||||
|                 Some(make_boolean_member_child_arg(member_child.name())) |                 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)), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -199,6 +231,10 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream { | |||||||
|     let pair_ident = format_ident!("{}", make_build_pair(build_spec.build())); |     let pair_ident = format_ident!("{}", make_build_pair(build_spec.build())); | ||||||
|     let return_type_ident = format_ident!("{}", 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 |     let child_holders = build_spec | ||||||
|         .children() |         .children() | ||||||
|         .map(|child_spec| make_child_holder(child_spec)) |         .map(|child_spec| make_child_holder(child_spec)) | ||||||
| @ -224,6 +260,10 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream { | |||||||
| 
 | 
 | ||||||
|     quote! { |     quote! { | ||||||
|         fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident { |         fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident { | ||||||
|  |             #preamble | ||||||
|  |             
 | ||||||
|  |             #(#special_children;)* | ||||||
|  |             
 | ||||||
|             #(#child_holders;)* |             #(#child_holders;)* | ||||||
| 
 | 
 | ||||||
|             #iter_stream |             #iter_stream | ||||||
|  | |||||||
| @ -56,12 +56,6 @@ fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> Membe | |||||||
|         } else { |         } else { | ||||||
|             panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name); |             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 { |     } else { | ||||||
|         panic!( |         panic!( | ||||||
|             "Expected one of 'node', 'boolean', or 'special' in 'build' in {}", |             "Expected one of 'node', 'boolean', or 'special' in 'build' in {}", | ||||||
| @ -98,6 +92,14 @@ 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 { | fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild { | ||||||
|     if props["skip"].is_hash() { |     if props["skip"].is_hash() { | ||||||
|         deserialize_skip_child(&props["skip"]) |         deserialize_skip_child(&props["skip"]) | ||||||
| @ -105,6 +107,8 @@ fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild { | |||||||
|         deserialize_vec_child(name, &props["vec"]) |         deserialize_vec_child(name, &props["vec"]) | ||||||
|     } else if props["member"].is_hash() { |     } else if props["member"].is_hash() { | ||||||
|         deserialize_member_child(name, &props["member"]) |         deserialize_member_child(name, &props["member"]) | ||||||
|  |     } else if props["special"].is_hash() { | ||||||
|  |         deserialize_special_child(name, &props["special"])    
 | ||||||
|     } else { |     } else { | ||||||
|         panic!("Expected 'skip' or 'vec' in 'member' in {}", name); |         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()))?; |                         writer.writeln_indented(&format!(#format_string, self.#child_ident()))?; | ||||||
|                     }) |                     }) | ||||||
|                 } |                 } | ||||||
|                 MemberChildBuild::Special(_) => None |  | ||||||
|             }, |             }, | ||||||
|  |             StructChild::Special(_) => None | ||||||
|         }) |         }) | ||||||
|         .filter(Option::is_some) |         .filter(Option::is_some) | ||||||
|         .map(Option::unwrap) |         .map(Option::unwrap) | ||||||
|  | |||||||
| @ -26,6 +26,25 @@ pub enum StructChild { | |||||||
|     SkipChild(SkipChild), |     SkipChild(SkipChild), | ||||||
|     VecChild(VecChild), |     VecChild(VecChild), | ||||||
|     MemberChild(MemberChild), |     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 { | pub struct SkipChild { | ||||||
| @ -160,7 +179,6 @@ impl MemberChild { | |||||||
| pub enum MemberChildBuild { | pub enum MemberChildBuild { | ||||||
|     Node(NodeMemberBuild), |     Node(NodeMemberBuild), | ||||||
|     Boolean(BooleanMemberBuild), |     Boolean(BooleanMemberBuild), | ||||||
|     Special(SpecialMemberBuild), |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -215,7 +233,30 @@ pub enum BooleanMemberBuildOn { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum SpecialMemberBuild { | 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 { | ||||||
|     FileId, |     FileId, | ||||||
|     Range, |     Range, | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| use crate::spec::struct_spec::{ | use crate::spec::struct_spec::{ | ||||||
|     MemberChild, MemberChildBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, |     MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, | ||||||
|     VecChildBuild, |     VecChild, VecChildBuild, | ||||||
| }; | }; | ||||||
| use proc_macro2::{Ident, TokenStream}; | use proc_macro2::{Ident, TokenStream}; | ||||||
| use quote::{format_ident, quote}; | use quote::{format_ident, quote}; | ||||||
| @ -76,22 +76,26 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         MemberChildBuild::Special(special_member_build) => match special_member_build { |     } | ||||||
|             SpecialMemberBuild::FileId => { | } | ||||||
|  | 
 | ||||||
|  | fn make_special_child_accessors(special_child: &SpecialChild) -> TokenStream { | ||||||
|  |     let child_ident = format_ident!("{}", special_child.name()); | ||||||
|  |     match special_child.kind() { | ||||||
|  |         SpecialChildKind::FileId => { | ||||||
|             quote! { |             quote! { | ||||||
|                     pub fn file_id(&self) -> usize { |                 pub fn #child_ident(&self) -> usize { | ||||||
|                         self.file_id |                     self.#child_ident | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|             SpecialMemberBuild::Range => { |         SpecialChildKind::Range => { | ||||||
|             quote! { |             quote! { | ||||||
|                     pub fn range(&self) -> Range<usize> { |                 pub fn #child_ident(&self) -> Range<usize> { | ||||||
|                         self.range |                     self.#child_ident | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         }, |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -100,6 +104,7 @@ fn make_accessors(child: &StructChild) -> Option<TokenStream> { | |||||||
|         StructChild::SkipChild(_) => None, |         StructChild::SkipChild(_) => None, | ||||||
|         StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)), |         StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)), | ||||||
|         StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)), |         StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)), | ||||||
|  |         StructChild::Special(special_child) => Some(make_special_child_accessors(special_child)), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -108,6 +113,7 @@ fn make_member_ident(child: &StructChild) -> Option<Ident> { | |||||||
|         StructChild::SkipChild(_) => None, |         StructChild::SkipChild(_) => None, | ||||||
|         StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())), |         StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())), | ||||||
|         StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())), |         StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())), | ||||||
|  |         StructChild::Special(special_child) => Some(format_ident!("{}", special_child.name())), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -135,10 +141,6 @@ fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream { | |||||||
|         MemberChildBuild::Boolean(_) => { |         MemberChildBuild::Boolean(_) => { | ||||||
|             quote! { bool } |             quote! { bool } | ||||||
|         } |         } | ||||||
|         MemberChildBuild::Special(special_member_build) => match special_member_build { |  | ||||||
|             SpecialMemberBuild::FileId => quote! { usize }, |  | ||||||
|             SpecialMemberBuild::Range => quote! { Range<usize> }, |  | ||||||
|         }, |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -156,6 +158,17 @@ 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> { | fn make_annotated_member(child: &StructChild) -> Option<TokenStream> { | ||||||
|     match child { |     match child { | ||||||
|         StructChild::SkipChild(_) => None, |         StructChild::SkipChild(_) => None, | ||||||
| @ -163,6 +176,9 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> { | |||||||
|         StructChild::MemberChild(member_child) => { |         StructChild::MemberChild(member_child) => { | ||||||
|             Some(make_member_child_annotated_member(member_child)) |             Some(make_member_child_annotated_member(member_child)) | ||||||
|         } |         } | ||||||
|  |         StructChild::Special(special_child) => { | ||||||
|  |             Some(make_special_child_annotated_member(special_child)) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
| fn main() | fn main() | ||||||
|     1 + 2 * 3 + 4 |     let n = 1 + 2 * 3 + 4 | ||||||
|  |     println n | ||||||
| end | end | ||||||
							
								
								
									
										5
									
								
								examples/op_prec.dvm_ir
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								examples/op_prec.dvm_ir
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | fn main() -> Void | ||||||
|  |     $0 = 2 * 3 | ||||||
|  |     $1 = 1 + $0 | ||||||
|  |     $2 = $1 + 4 | ||||||
|  |     call std::core::println($2) | ||||||
							
								
								
									
										89
									
								
								examples/worlds.dvm_ir
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								examples/worlds.dvm_ir
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | |||||||
|  | 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::analyze_names; | ||||||
| use deimos::name_analysis::symbol_table::SymbolTable; | use deimos::name_analysis::symbol_table::SymbolTable; | ||||||
| use deimos::parser::{DeimosParser, Rule}; | use deimos::parser::{DeimosParser, Rule}; | ||||||
|  | use deimos::std_core::add_std_core_symbols; | ||||||
| use pest::Parser; | use pest::Parser; | ||||||
| use std::path::PathBuf; | 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>> { | pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> { | ||||||
|     let mut compilation_units = vec![]; |     let mut compilation_units = vec![]; | ||||||
|     let mut files = SimpleFiles::new(); |     let mut files: SimpleFiles<String, String> = SimpleFiles::new(); | ||||||
| 
 | 
 | ||||||
|     for path in paths { |     for path in paths { | ||||||
|         let src = std::fs::read_to_string(path).unwrap(); |         let src = std::fs::read_to_string(path).unwrap(); | ||||||
| @ -31,13 +31,10 @@ pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Err | |||||||
|     let mut symbol_table = SymbolTable::new(); |     let mut symbol_table = SymbolTable::new(); | ||||||
|     add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); |     add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); | ||||||
| 
 | 
 | ||||||
|     let diagnostics = analyze_names( |     let diagnostics = analyze_names(compilation_units.as_mut_slice(), &files, &mut symbol_table); | ||||||
|         compilation_units.as_mut_slice(), |  | ||||||
|         &mut symbol_table |  | ||||||
|     ); |  | ||||||
|     if diagnostics.is_empty() { |     if diagnostics.is_empty() { | ||||||
|         println!("Name analysis complete."); |         println!("Name analysis complete."); | ||||||
|         println!("Symbol table\n-------\n{}", symbol_table); |         println!("{}", symbol_table); | ||||||
|     } else { |     } else { | ||||||
|         let writer = StandardStream::stderr(ColorChoice::Always); |         let writer = StandardStream::stderr(ColorChoice::Always); | ||||||
|         let config = term::Config::default(); |         let config = term::Config::default(); | ||||||
|  | |||||||
							
								
								
									
										199
									
								
								src/ir/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/ir/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | |||||||
|  | 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,3 +11,4 @@ pub mod parser; | |||||||
| pub mod std_core; | pub mod std_core; | ||||||
| pub mod util; | pub mod util; | ||||||
| pub mod vm; | pub mod vm; | ||||||
|  | pub mod ir; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| pub(super) struct FqnContext { | pub struct FqnContext { | ||||||
|     stack: Vec<String>, |     stack: Vec<String>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,62 +1,76 @@ | |||||||
| use crate::ast::ast_node::{AstNode, AstNodeRef}; | use crate::ast::ast_node::{AstNode, AstNodeRef}; | ||||||
| use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix}; | use crate::ast::node::{ | ||||||
|  |     Class, CompilationUnit, Function, FunctionBlockBody, FunctionBody, Identifier, Interface, | ||||||
|  |     Module, Namespace, Statement, UseStatement, UseStatementSuffix, VariableDeclaration, | ||||||
|  | }; | ||||||
| use crate::diagnostic::DmDiagnostic; | 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::source_definition::SourceDefinition; | ||||||
| use crate::name_analysis::symbol::use_symbol::StarUseStatementSymbol; | use crate::name_analysis::symbol::type_symbol::{ | ||||||
| use crate::name_analysis::symbol::UseStatementSymbol; |     ConcreteTypeSymbol, ConcreteTypeSymbolKind, TypeSymbol, | ||||||
| use crate::name_analysis::symbol_table::SymbolTable; | }; | ||||||
| use std::collections::HashMap; | 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; | ||||||
| 
 | 
 | ||||||
| fn gather_identifier( | fn handle_insert_error( | ||||||
|     identifier: &Identifier, |     err: SymbolInsertError, | ||||||
|     symbol_table: &SymbolTable, |     error_symbol_name: &str, | ||||||
|     identifier_scope_ids: &mut HashMap<Identifier, usize>, |     error_file_id: usize, | ||||||
| ) { |     error_range: Range<usize>, | ||||||
|     identifier_scope_ids.insert(identifier.clone(), symbol_table.current_scope_id()); |     symbol_types: &str, | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn gather_use_statement( |  | ||||||
|     use_statement: &UseStatement, |  | ||||||
|     symbol_table: &mut SymbolTable, |  | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     let mut fully_qualified_name = String::new(); |     match err { | ||||||
|     for prefix in use_statement.prefixes() { |         SymbolInsertError::SymbolAlreadyDefined(s) => { | ||||||
|         fully_qualified_name.push_str(&format!("{}::", prefix.identifier().name())); |             let mut diagnostic = Diagnostic::error() | ||||||
|     } |                 .with_message(format!( | ||||||
|     match use_statement.suffix() { |                     "{} symbol '{}' already defined in the current scope.", | ||||||
|         UseStatementSuffix::Identifier(identifier) => {} |                     symbol_types, error_symbol_name, | ||||||
|         UseStatementSuffix::Star => { |                 )) | ||||||
|             let symbol_inner = StarUseStatementSymbol::new( |                 .with_label( | ||||||
|                 &fully_qualified_name, |                     Label::primary(error_file_id, error_range) | ||||||
|                 Some(SourceDefinition::from_use_statement(use_statement)), |                         .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 symbol = UseStatementSymbol::Star(symbol_inner); |  | ||||||
|             symbol_table.insert_use_statement_symbol(symbol); |  | ||||||
|             todo!() |  | ||||||
|             } |             } | ||||||
|         UseStatementSuffix::UseList(use_list) => {} | 
 | ||||||
|  |             diagnostics.push(diagnostic); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_node_children( | fn gather_node_children( | ||||||
|     node: &impl AstNode, |     node: &impl AstNode, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     for child in node.children() { |     for child in node.children() { | ||||||
|         gather_node(child, symbol_table, diagnostics); |         gather_node(child, symbol_table, fqn_context, diagnostics); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_node( | fn gather_node( | ||||||
|     node: AstNodeRef, |     node: AstNodeRef, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     match node { |     match node { | ||||||
|         AstNodeRef::Operator(_) => {} |         AstNodeRef::Operator(_) => {} | ||||||
|         AstNodeRef::Identifier(_) => {} |         AstNodeRef::Identifier(_) => { | ||||||
|  |             unreachable!() | ||||||
|  |         } | ||||||
|         AstNodeRef::FullyQualifiedName(_) => {} |         AstNodeRef::FullyQualifiedName(_) => {} | ||||||
|         AstNodeRef::TypeUseList(_) => {} |         AstNodeRef::TypeUseList(_) => {} | ||||||
|         AstNodeRef::IdentifierList(_) => {} |         AstNodeRef::IdentifierList(_) => {} | ||||||
| @ -75,36 +89,114 @@ fn gather_node( | |||||||
|         AstNodeRef::Parameter(_) => {} |         AstNodeRef::Parameter(_) => {} | ||||||
|         AstNodeRef::ReturnType(_) => {} |         AstNodeRef::ReturnType(_) => {} | ||||||
|         AstNodeRef::CompilationUnit(compilation_unit) => { |         AstNodeRef::CompilationUnit(compilation_unit) => { | ||||||
|             gather_node_children(compilation_unit, symbol_table, diagnostics); |             gather_node_children(compilation_unit, symbol_table, fqn_context, diagnostics); | ||||||
|  |         } | ||||||
|  |         AstNodeRef::Namespace(namespace) => { | ||||||
|  |             gather_namespace(namespace, fqn_context); | ||||||
|         } |         } | ||||||
|         AstNodeRef::ParentMod(_) => {} |  | ||||||
|         AstNodeRef::UseStatement(use_statement) => { |         AstNodeRef::UseStatement(use_statement) => { | ||||||
|             gather_use_statement(use_statement, symbol_table, diagnostics); |             gather_use_statement(use_statement, symbol_table, diagnostics); | ||||||
|         } |         } | ||||||
|         AstNodeRef::UseStatementPrefix(_) => {} |         AstNodeRef::UseStatementPrefix(_) => { | ||||||
|         AstNodeRef::UseStatementSuffix(_) => {} |             unreachable!() | ||||||
|         AstNodeRef::UseList(_) => {} |         } | ||||||
|         AstNodeRef::ModuleLevelDeclaration(_) => {} |         AstNodeRef::UseStatementSuffix(_) => { | ||||||
|         AstNodeRef::InterfaceLevelDeclaration(_) => {} |             unreachable!() | ||||||
|         AstNodeRef::ClassLevelDeclaration(_) => {} |         } | ||||||
|         AstNodeRef::Module(_) => {} |         AstNodeRef::UseList(_) => { | ||||||
|         AstNodeRef::CompanionModule(_) => {} |             unreachable!() | ||||||
|         AstNodeRef::Interface(_) => {} |         } | ||||||
|         AstNodeRef::Class(_) => {} |         AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => { | ||||||
|         AstNodeRef::Function(_) => {} |             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::OperatorFunction(_) => {} |         AstNodeRef::OperatorFunction(_) => {} | ||||||
|         AstNodeRef::PlatformFunction(_) => {} |         AstNodeRef::PlatformFunction(_) => {} | ||||||
|         AstNodeRef::InterfaceFunction(_) => {} |         AstNodeRef::InterfaceFunction(_) => {} | ||||||
|         AstNodeRef::InterfaceDefaultFunction(_) => {} |         AstNodeRef::InterfaceDefaultFunction(_) => {} | ||||||
|         AstNodeRef::InterfaceOperatorFunction(_) => {} |         AstNodeRef::InterfaceOperatorFunction(_) => {} | ||||||
|         AstNodeRef::InterfaceDefaultOperatorFunction(_) => {} |         AstNodeRef::InterfaceDefaultOperatorFunction(_) => {} | ||||||
|         AstNodeRef::FunctionBody(_) => {} |         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::FunctionEqualsBody(_) => {} |         AstNodeRef::FunctionEqualsBody(_) => {} | ||||||
|         AstNodeRef::FunctionAliasBody(_) => {} |         AstNodeRef::FunctionAliasBody(_) => {} | ||||||
|         AstNodeRef::FunctionBlockBody(_) => {} |         AstNodeRef::FunctionBlockBody(block_body) => { | ||||||
|  |             gather_function_block_body(block_body, symbol_table, fqn_context, diagnostics); | ||||||
|  |         } | ||||||
|         AstNodeRef::ClassConstructor(_) => {} |         AstNodeRef::ClassConstructor(_) => {} | ||||||
|         AstNodeRef::Member(_) => {} |         AstNodeRef::Member(_) => {} | ||||||
|         AstNodeRef::Statement(_) => {} |         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::VariableDeclaration(_) => {} |         AstNodeRef::VariableDeclaration(_) => {} | ||||||
|         AstNodeRef::AssignmentStatement(_) => {} |         AstNodeRef::AssignmentStatement(_) => {} | ||||||
|         AstNodeRef::ExpressionStatement(_) => {} |         AstNodeRef::ExpressionStatement(_) => {} | ||||||
| @ -157,9 +249,284 @@ fn gather_node( | |||||||
| 
 | 
 | ||||||
| pub fn gather_compilation_unit( | pub fn gather_compilation_unit( | ||||||
|     compilation_unit: &mut CompilationUnit, |     compilation_unit: &mut CompilationUnit, | ||||||
|  |     file_name: &str, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     identifier_scope_ids: &mut HashMap<Identifier, usize>, |  | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     gather_node(compilation_unit.as_node_ref(), symbol_table, diagnostics); |     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, | ||||||
|  |         ); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -24,16 +24,18 @@ use crate::diagnostic::DmDiagnostic; | |||||||
| use crate::name_analysis::gather::gather_compilation_unit; | use crate::name_analysis::gather::gather_compilation_unit; | ||||||
| // use crate::name_analysis::resolve::resolve_compilation_unit;
 | // use crate::name_analysis::resolve::resolve_compilation_unit;
 | ||||||
| use crate::name_analysis::symbol_table::SymbolTable; | use crate::name_analysis::symbol_table::SymbolTable; | ||||||
|  | use codespan_reporting::files::Files; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| 
 | 
 | ||||||
| mod fqn_context; | pub(self) mod fqn_context; | ||||||
| mod gather; | mod gather; | ||||||
| // mod resolve;
 | // mod resolve;
 | ||||||
| pub mod symbol; | pub mod symbol; | ||||||
| pub mod symbol_table; | pub mod symbol_table; | ||||||
| 
 | 
 | ||||||
| pub fn analyze_names( | pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( | ||||||
|     compilation_units: &mut [Box<CompilationUnit>], |     compilation_units: &mut [Box<CompilationUnit>], | ||||||
|  |     files: &'a F, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| ) -> Vec<DmDiagnostic> { | ) -> Vec<DmDiagnostic> { | ||||||
|     let mut diagnostics = vec![]; |     let mut diagnostics = vec![]; | ||||||
| @ -41,12 +43,8 @@ pub fn analyze_names( | |||||||
| 
 | 
 | ||||||
|     // gather symbols
 |     // gather symbols
 | ||||||
|     for compilation_unit in compilation_units.iter_mut() { |     for compilation_unit in compilation_units.iter_mut() { | ||||||
|         gather_compilation_unit( |         let file_name = files.name(compilation_unit.file_id()).unwrap(); | ||||||
|             compilation_unit, |         gather_compilation_unit(compilation_unit, &file_name, symbol_table, &mut diagnostics); | ||||||
|             symbol_table, |  | ||||||
|             &mut identifier_scope_ids, |  | ||||||
|             &mut diagnostics, |  | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // resolve symbols
 |     // resolve symbols
 | ||||||
|  | |||||||
							
								
								
									
										45
									
								
								src/name_analysis/symbol/class_member_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/name_analysis/symbol/class_member_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | 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() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										101
									
								
								src/name_analysis/symbol/function_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/name_analysis/symbol/function_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | |||||||
|  | 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,445 +1,46 @@ | |||||||
| pub(super) mod source_definition; | pub(crate) mod class_member_symbol; | ||||||
| pub(super) mod use_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; | ||||||
| 
 | 
 | ||||||
| use crate::ast::node::Identifier; | 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 source_definition::SourceDefinition; | use source_definition::SourceDefinition; | ||||||
| use std::cell::RefCell; | use std::fmt::{Debug, Display}; | ||||||
| use std::fmt::{Debug, Display, Formatter}; |  | ||||||
| use std::ops::Deref; | use std::ops::Deref; | ||||||
| use std::rc::Rc; | use type_symbol::TypeSymbol; | ||||||
| 
 | use variable_symbol::VariableSymbol; | ||||||
| pub trait SymbolInner { |  | ||||||
|     fn declared_name(&self) -> &str; |  | ||||||
|     fn definition(&self) -> Option<SourceDefinition>; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Symbol */ |  | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub enum Symbol { | pub enum Symbol { | ||||||
|     UseStatement(Rc<RefCell<UseStatementSymbol>>), |     ConcreteUse(ConcreteUseSymbol), | ||||||
|     Module(Rc<ModuleSymbol>), |     StarUse(StarUseSymbol), | ||||||
|     Type(Rc<TypeSymbol>), |     Module(ModuleSymbol), | ||||||
|     Function(Rc<RefCell<FunctionSymbol>>), |     Type(TypeSymbol), | ||||||
|     Parameter(Rc<ParameterSymbol>), |     Function(FunctionSymbol), | ||||||
|     Variable(Rc<VariableSymbol>), |     Parameter(ParameterSymbol), | ||||||
|     ClassMember(Rc<ClassMemberSymbol>), |     Variable(VariableSymbol), | ||||||
|  |     ClassMember(ClassMemberSymbol), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Symbol { | impl Symbol { | ||||||
|     pub fn definition(&self) -> Option<SourceDefinition> { |     pub fn definition(&self) -> Option<&SourceDefinition> { | ||||||
|         match self { |         match self { | ||||||
|             Symbol::UseStatement(s) => s.borrow().definition(), |             Symbol::ConcreteUse(concrete) => concrete.source_definition(), | ||||||
|             Symbol::Module(s) => s.definition(), |             Symbol::StarUse(star) => star.source_definition(), | ||||||
|             Symbol::Type(s) => match s.deref() { |             Symbol::Module(module) => module.source_definition(), | ||||||
|                 TypeSymbol::Concrete(cts) => cts.definition(), |             Symbol::Type(type_symbol) => type_symbol.source_definition(), | ||||||
|                 TypeSymbol::Generic(gts) => gts.definition(), |             Symbol::Function(function_symbol) => function_symbol.source_definition(), | ||||||
|             }, |             Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition(), | ||||||
|             Symbol::Function(s) => s.borrow().definition(), |             Symbol::Variable(variable_symbol) => variable_symbol.source_definition(), | ||||||
|             Symbol::Parameter(s) => s.definition(), |             Symbol::ClassMember(class_member_symbol) => class_member_symbol.source_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() |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										53
									
								
								src/name_analysis/symbol/module_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/name_analysis/symbol/module_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | 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() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								src/name_analysis/symbol/parameter_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/name_analysis/symbol/parameter_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | 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() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										121
									
								
								src/name_analysis/symbol/type_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/name_analysis/symbol/type_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | 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,16 +1,56 @@ | |||||||
| use crate::name_analysis::symbol::source_definition::SourceDefinition; | use crate::name_analysis::symbol::source_definition::SourceDefinition; | ||||||
|  | use std::fmt::{Debug, Formatter}; | ||||||
| 
 | 
 | ||||||
| pub enum UseStatementSymbol { | #[derive(Clone)] | ||||||
|     Concrete, | pub struct ConcreteUseSymbol { | ||||||
|     Star(StarUseStatementSymbol), |     base_fqn: String, | ||||||
|  |     declared_name: String, | ||||||
|  |     source_definition: Option<SourceDefinition>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct 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 { | ||||||
|     base_fqn: String, |     base_fqn: String, | ||||||
|     source_definition: Option<SourceDefinition>, |     source_definition: Option<SourceDefinition>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl StarUseStatementSymbol { | impl StarUseSymbol { | ||||||
|     pub fn new(base_fqn: &str, source_definition: Option<SourceDefinition>) -> Self { |     pub fn new(base_fqn: &str, source_definition: Option<SourceDefinition>) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             base_fqn: base_fqn.to_string(), |             base_fqn: base_fqn.to_string(), | ||||||
| @ -26,3 +66,12 @@ impl StarUseStatementSymbol { | |||||||
|         self.source_definition.as_ref() |         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() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								src/name_analysis/symbol/variable_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/name_analysis/symbol/variable_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | 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() | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,468 +0,0 @@ | |||||||
| 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(()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										333
									
								
								src/name_analysis/symbol_table/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								src/name_analysis/symbol_table/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,333 @@ | |||||||
|  | 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(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										141
									
								
								src/name_analysis/symbol_table/scope.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/name_analysis/symbol_table/scope.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | |||||||
|  | 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,6 +88,7 @@ $defs: | |||||||
|       - $ref: "#/$defs/StructChildSkipHash" |       - $ref: "#/$defs/StructChildSkipHash" | ||||||
|       - $ref: "#/$defs/StructChildVecHash" |       - $ref: "#/$defs/StructChildVecHash" | ||||||
|       - $ref: "#/$defs/StructChildMemberHash" |       - $ref: "#/$defs/StructChildMemberHash" | ||||||
|  |       - $ref: "#/$defs/StructChildSpecialHash" | ||||||
|   StructChildSkipHash: |   StructChildSkipHash: | ||||||
|     type: object |     type: object | ||||||
|     additionalProperties: false |     additionalProperties: false | ||||||
| @ -148,7 +149,6 @@ $defs: | |||||||
|     oneOf: |     oneOf: | ||||||
|       - $ref: "#/$defs/StructChildMemberBuildNodeHash" |       - $ref: "#/$defs/StructChildMemberBuildNodeHash" | ||||||
|       - $ref: "#/$defs/StructChildMemberBuildBooleanHash" |       - $ref: "#/$defs/StructChildMemberBuildBooleanHash" | ||||||
|       - $ref: "#/$defs/StructChildMemberBuildSpecialHash" |  | ||||||
|   StructChildMemberBuildNodeHash: |   StructChildMemberBuildNodeHash: | ||||||
|     type: object |     type: object | ||||||
|     additionalProperties: false |     additionalProperties: false | ||||||
| @ -191,7 +191,7 @@ $defs: | |||||||
|           - rule_present |           - rule_present | ||||||
|     required: |     required: | ||||||
|       - on |       - on | ||||||
|   StructChildMemberBuildSpecialHash: |   StructChildSpecialHash: | ||||||
|     type: object |     type: object | ||||||
|     additionalProperties: false |     additionalProperties: false | ||||||
|     description: A special member to be built. |     description: A special member to be built. | ||||||
|  | |||||||
| @ -181,7 +181,7 @@ ReturnType: | |||||||
| CompilationUnit: | CompilationUnit: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
|       - parent_mod: |       - namespace: | ||||||
|           member: |           member: | ||||||
|             optional: true |             optional: true | ||||||
|       - use_statements: |       - use_statements: | ||||||
| @ -193,12 +193,15 @@ CompilationUnit: | |||||||
|       - eoi: |       - eoi: | ||||||
|           skip: |           skip: | ||||||
|             rule: EOI |             rule: EOI | ||||||
| ParentMod: |       - file_id: | ||||||
|  |           special: | ||||||
|  |             kind: file_id | ||||||
|  | Namespace: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
|       - mod_kw: |       - ns_kw: | ||||||
|           skip: |           skip: | ||||||
|             rule: Mod |             rule: Ns | ||||||
|       - fqn: |       - fqn: | ||||||
|           member: |           member: | ||||||
|             rule: FullyQualifiedName |             rule: FullyQualifiedName | ||||||
| @ -215,13 +218,9 @@ UseStatement: | |||||||
|           member: |           member: | ||||||
|             rule: UseStatementSuffix |             rule: UseStatementSuffix | ||||||
|       - file_id: |       - file_id: | ||||||
|           member:  |  | ||||||
|             build: |  | ||||||
|           special: |           special: | ||||||
|             kind: file_id |             kind: file_id | ||||||
|       - range: |       - range: | ||||||
|           member:  |  | ||||||
|             build: |  | ||||||
|           special: |           special: | ||||||
|             kind: range |             kind: range | ||||||
| UseStatementPrefix: | UseStatementPrefix: | ||||||
| @ -254,7 +253,6 @@ ModuleLevelDeclaration: | |||||||
| InterfaceLevelDeclaration: | InterfaceLevelDeclaration: | ||||||
|   tree_enum: |   tree_enum: | ||||||
|     rules: |     rules: | ||||||
|       - CompanionModule |  | ||||||
|       - Interface |       - Interface | ||||||
|       - Class |       - Class | ||||||
|       - InterfaceFunction |       - InterfaceFunction | ||||||
| @ -264,7 +262,6 @@ InterfaceLevelDeclaration: | |||||||
| ClassLevelDeclaration: | ClassLevelDeclaration: | ||||||
|   tree_enum: |   tree_enum: | ||||||
|     rules: |     rules: | ||||||
|       - CompanionModule |  | ||||||
|       - Interface |       - Interface | ||||||
|       - Class |       - Class | ||||||
|       - Function |       - Function | ||||||
| @ -291,21 +288,6 @@ Module: | |||||||
|       - end_kw: |       - end_kw: | ||||||
|           skip: |           skip: | ||||||
|             rule: End |             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: | Interface: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
|  | |||||||
| @ -307,13 +307,13 @@ ReturnType = { | |||||||
| 
 | 
 | ||||||
| CompilationUnit = { | CompilationUnit = { | ||||||
|       SOI |       SOI | ||||||
|     ~ ParentMod? |     ~ Namespace? | ||||||
|     ~ ( UseStatement | ModuleLevelDeclaration )* |     ~ ( UseStatement | ModuleLevelDeclaration )* | ||||||
|     ~ EOI |     ~ EOI | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParentMod = { | Namespace = { | ||||||
|       Mod |       Ns | ||||||
|     ~ FullyQualifiedName |     ~ FullyQualifiedName | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -352,8 +352,7 @@ ModuleLevelDeclaration = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| InterfaceLevelDeclaration = { | InterfaceLevelDeclaration = { | ||||||
|       CompanionModule |       Interface | ||||||
|     | Interface |  | ||||||
|     | Class |     | Class | ||||||
|     | InterfaceFunction |     | InterfaceFunction | ||||||
|     | InterfaceDefaultFunction |     | InterfaceDefaultFunction | ||||||
| @ -362,8 +361,7 @@ InterfaceLevelDeclaration = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ClassLevelDeclaration = { | ClassLevelDeclaration = { | ||||||
|       CompanionModule |       Interface | ||||||
|     | Interface |  | ||||||
|     | Class |     | Class | ||||||
|     | Function |     | Function | ||||||
|     | OperatorFunction |     | OperatorFunction | ||||||
| @ -380,13 +378,6 @@ Module = { | |||||||
|     ~ End |     ~ End | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CompanionModule = { |  | ||||||
|       Companion |  | ||||||
|     ~ Mod |  | ||||||
|     ~ ModuleLevelDeclaration* |  | ||||||
|     ~ End |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Interface = { | Interface = { | ||||||
|       Pub? |       Pub? | ||||||
|     ~ IntKw |     ~ IntKw | ||||||
|  | |||||||
| @ -1,13 +1,26 @@ | |||||||
| use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol}; | use crate::name_analysis::symbol::function_symbol::FunctionSymbol; | ||||||
|  | use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; | ||||||
| use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | ||||||
| 
 | 
 | ||||||
| pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { | pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { | ||||||
|     symbol_table.insert_function_symbol( |     symbol_table.insert_function_symbol( | ||||||
|         FunctionSymbol::new("std::core::println", "println", true, true, None) |         FunctionSymbol::without_parameters_or_return_type( | ||||||
|  |             "std::core::println", | ||||||
|  |             "println", | ||||||
|  |             true, | ||||||
|  |             true, | ||||||
|  |             None, | ||||||
|  |         ) | ||||||
|         .with_parameters(vec![ParameterSymbol::new("msg", None)]), |         .with_parameters(vec![ParameterSymbol::new("msg", None)]), | ||||||
|     )?; |     )?; | ||||||
|     symbol_table.insert_function_symbol( |     symbol_table.insert_function_symbol( | ||||||
|         FunctionSymbol::new("std::core::print", "print", true, true, None) |         FunctionSymbol::without_parameters_or_return_type( | ||||||
|  |             "std::core::print", | ||||||
|  |             "print", | ||||||
|  |             true, | ||||||
|  |             true, | ||||||
|  |             None, | ||||||
|  |         ) | ||||||
|         .with_parameters(vec![ParameterSymbol::new("msg", None)]), |         .with_parameters(vec![ParameterSymbol::new("msg", None)]), | ||||||
|     )?; |     )?; | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user