Compare commits
	
		
			6 Commits
		
	
	
		
			f0772fbf11
			...
			d09d945323
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d09d945323 | ||
|   | 34fae6ccca | ||
|   | dd249dd5bd | ||
|   | 6b206605c1 | ||
|   | b47dea9136 | ||
|   | 2b5be6ca49 | 
| @ -16,7 +16,7 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream { | |||||||
|                             let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake)); |                             let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake)); | ||||||
|                             quote! { |                             quote! { | ||||||
|                                 #type_ident::#rule_ident(#child_ident) => vec![ |                                 #type_ident::#rule_ident(#child_ident) => vec![ | ||||||
|                                     #child_ident.as_node_ref() |                                     #child_ident | ||||||
|                                 ] |                                 ] | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
| @ -35,14 +35,14 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream { | |||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
|     
 |     
 | ||||||
|     quote! { |     quote! { | ||||||
|         impl AstNode for #type_ident { |         impl<'a> AstNode<'a> for #type_ident { | ||||||
|             fn children(&self) -> Vec<AstNodeRef> { |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { | ||||||
|                 match self { |                 match self { | ||||||
|                     #(#match_arms,)* |                     #(#match_arms,)* | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef { |             fn as_node_ref(&'a self) -> AstNodeRef<'a> { | ||||||
|                 AstNodeRef::#type_ident(&self) |                 AstNodeRef::#type_ident(&self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,16 +1,16 @@ | |||||||
|  | use crate::spec::leaf_enum_spec::LeafEnumBuildSpec; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use quote::{format_ident, quote}; | use quote::{format_ident, quote}; | ||||||
| use crate::spec::leaf_enum_spec::LeafEnumBuildSpec; |  | ||||||
| 
 | 
 | ||||||
| pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream { | pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream { | ||||||
|     let type_ident = format_ident!("{}", spec.build()); |     let type_ident = format_ident!("{}", spec.build()); | ||||||
|     quote! { |     quote! { | ||||||
|         impl AstNode for #type_ident { |         impl<'a> AstNode<'a> for #type_ident { | ||||||
|             fn children(&self) -> Vec<AstNodeRef> { |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { | ||||||
|                 vec![] |                 vec![] | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef { |             fn as_node_ref(&'a self) -> AstNodeRef<'a> { | ||||||
|                 AstNodeRef::#type_ident(&self) |                 AstNodeRef::#type_ident(&self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -5,12 +5,12 @@ use quote::{format_ident, quote}; | |||||||
| pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream { | pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream { | ||||||
|     let type_ident = format_ident!("{}", spec.build()); |     let type_ident = format_ident!("{}", spec.build()); | ||||||
|     quote! { |     quote! { | ||||||
|         impl AstNode for #type_ident { |         impl<'a> AstNode<'a> for #type_ident { | ||||||
|             fn children(&self) -> Vec<AstNodeRef> { |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { | ||||||
|                 vec![] |                 vec![] | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef { |             fn as_node_ref(&'a self) -> AstNodeRef<'a> { | ||||||
|                 AstNodeRef::#type_ident(&self) |                 AstNodeRef::#type_ident(&self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -71,3 +71,34 @@ pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> { | |||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | pub fn make_ast_node_ref_unwrapper(build_spec: &BuildSpec) -> Option<TokenStream> { | ||||||
|  |     match build_spec { | ||||||
|  |         BuildSpec::Enum(enum_spec) => { | ||||||
|  |             Some(format_ident!("{}", enum_spec.build())) | ||||||
|  |         } | ||||||
|  |         BuildSpec::LeafEnum(leaf_enum) => { | ||||||
|  |             Some(format_ident!("{}", leaf_enum.build())) | ||||||
|  |         } | ||||||
|  |         BuildSpec::Struct(struct_spec) => { | ||||||
|  |             Some(format_ident!("{}", struct_spec.build())) | ||||||
|  |         } | ||||||
|  |         BuildSpec::LeafStruct(leaf_struct) => { | ||||||
|  |             Some(format_ident!("{}", leaf_struct.build())) | ||||||
|  |         } | ||||||
|  |         BuildSpec::Production(_) => None, | ||||||
|  |         BuildSpec::NodeProduction(_) => None, | ||||||
|  |         BuildSpec::PolymorphicType(polymorphic_type) => { | ||||||
|  |             Some(format_ident!("{}", polymorphic_type.name())) | ||||||
|  |         } | ||||||
|  |         BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => { | ||||||
|  |             Some(format_ident!("{}", polymorphic_enum_loop.name())) | ||||||
|  |         } | ||||||
|  |         BuildSpec::PolymorphicPassThrough(_) => None | ||||||
|  |     } | ||||||
|  |         .map(|type_ident| { | ||||||
|  |             quote! { | ||||||
|  |                 AstNodeRef::#type_ident(inner) => *inner | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  | } | ||||||
| @ -28,20 +28,20 @@ pub fn make_polymorphic_enum_loop_ast_node_impl( | |||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
|             quote! { |             quote! { | ||||||
|                 children.push(self.#child_ident().as_node_ref()) |                 children.push(self.#child_ident() as &dyn AstNode); | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|     quote! { |     quote! { | ||||||
|         impl AstNode for #type_ident { |         impl<'a> AstNode<'a> for #type_ident { | ||||||
|             fn children(&self) -> Vec<AstNodeRef> { |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { | ||||||
|                 let mut children: Vec<AstNodeRef> = vec![]; |                 let mut children = vec![]; | ||||||
|                 #(#child_adders;)* |                 #(#child_adders;)* | ||||||
|                 children |                 children | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef { |             fn as_node_ref(&'a self) -> AstNodeRef<'a> { | ||||||
|                 AstNodeRef::#type_ident(&self) |                 AstNodeRef::#type_ident(&self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -11,20 +11,20 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T | |||||||
|             let variant_ident = format_ident!("{}", variant.name()); |             let variant_ident = format_ident!("{}", variant.name()); | ||||||
|             let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake)); |             let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake)); | ||||||
|             quote! { |             quote! { | ||||||
|                 #type_ident::#variant_ident(#child_ident) => vec![#child_ident.as_node_ref()] |                 #type_ident::#variant_ident(#child_ident) => vec![#child_ident] | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|     quote! { |     quote! { | ||||||
|         impl AstNode for #type_ident { |         impl<'a> AstNode<'a> for #type_ident { | ||||||
|             fn children(&self) -> Vec<AstNodeRef> { |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { | ||||||
|                 match self { |                 match self { | ||||||
|                     #(#match_arms,)* |                     #(#match_arms,)* | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef { |             fn as_node_ref(&'a self) -> AstNodeRef<'a> { | ||||||
|                 AstNodeRef::#type_ident(&self) |                 AstNodeRef::#type_ident(&self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -13,8 +13,8 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { | |||||||
|                 VecChildBuild::Node(_) => { |                 VecChildBuild::Node(_) => { | ||||||
|                     let child_ident = format_ident!("{}", vec_child.name()); |                     let child_ident = format_ident!("{}", vec_child.name()); | ||||||
|                     let children_stream = quote! { |                     let children_stream = quote! { | ||||||
|                         for child in self.#child_ident().map(AstNode::as_node_ref) { |                         for child in self.#child_ident() { | ||||||
|                             children.push(child); |                             children.push(child as &dyn AstNode); | ||||||
|                         } |                         } | ||||||
|                     }; |                     }; | ||||||
|                     Some(children_stream) |                     Some(children_stream) | ||||||
| @ -26,12 +26,12 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { | |||||||
|                     if member_child.optional() { |                     if member_child.optional() { | ||||||
|                         Some(quote! { |                         Some(quote! { | ||||||
|                             if let Some(#child_ident) = self.#child_ident() { |                             if let Some(#child_ident) = self.#child_ident() { | ||||||
|                                 children.push(#child_ident.as_node_ref()); |                                 children.push(#child_ident as &dyn AstNode); | ||||||
|                             } |                             } | ||||||
|                         }) |                         }) | ||||||
|                     } else { |                     } else { | ||||||
|                         Some(quote! { |                         Some(quote! { | ||||||
|                             children.push(self.#child_ident().as_node_ref()) |                             children.push(self.#child_ident() as &dyn AstNode) | ||||||
|                         }) |                         }) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @ -44,14 +44,14 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { | |||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|     quote! { |     quote! { | ||||||
|         impl AstNode for #type_ident { |         impl<'a> AstNode<'a> for #type_ident { | ||||||
|             fn children(&self) -> Vec<AstNodeRef> { |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>> { | ||||||
|                 let mut children: Vec<AstNodeRef> = vec![]; |                 let mut children = vec![]; | ||||||
|                 #(#child_adders;)* |                 #(#child_adders;)* | ||||||
|                 children |                 children | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef { |             fn as_node_ref(&'a self) -> AstNodeRef<'a> { | ||||||
|                 AstNodeRef::#type_ident(&self) |                 AstNodeRef::#type_ident(&self) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ mod spec; | |||||||
| mod type_gen; | mod type_gen; | ||||||
| mod walk; | mod walk; | ||||||
| 
 | 
 | ||||||
| use crate::ast_node::{make_ast_enum_member, make_ast_node_impl}; | use crate::ast_node::{make_ast_enum_member, make_ast_node_impl, make_ast_node_ref_unwrapper}; | ||||||
| use crate::build_fn::make_build_fn; | use crate::build_fn::make_build_fn; | ||||||
| use crate::deserialize::deserialize_yaml_spec; | use crate::deserialize::deserialize_yaml_spec; | ||||||
| use crate::pretty_print::make_pretty_print_impl; | use crate::pretty_print::make_pretty_print_impl; | ||||||
| @ -165,6 +165,13 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { | |||||||
|         .map(Option::unwrap) |         .map(Option::unwrap) | ||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|  |     let inner_unwrappers = build_specs | ||||||
|  |         .iter() | ||||||
|  |         .map(|build_spec| make_ast_node_ref_unwrapper(build_spec)) | ||||||
|  |         .filter(Option::is_some) | ||||||
|  |         .map(Option::unwrap) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|     let combined = quote! { |     let combined = quote! { | ||||||
|         use crate::ast::node::*; |         use crate::ast::node::*; | ||||||
| 
 | 
 | ||||||
| @ -172,10 +179,18 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { | |||||||
|             #(#ast_enum_members,)* |             #(#ast_enum_members,)* | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pub trait AstNode { |         impl<'a> AstNodeRef<'a> { | ||||||
|             fn children(&self) -> Vec<AstNodeRef>; |             pub fn inner(&self) -> &dyn AstNode<'a> { | ||||||
|  |                 match self { | ||||||
|  |                     #(#inner_unwrappers,)* | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             fn as_node_ref(&self) -> AstNodeRef; |         pub trait AstNode<'a> { | ||||||
|  |             fn children(&'a self) -> Vec<&'a dyn AstNode<'a>>; | ||||||
|  | 
 | ||||||
|  |             fn as_node_ref(&'a self) -> AstNodeRef<'a>; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         #(#impls)* |         #(#impls)* | ||||||
|  | |||||||
| @ -1,59 +1,16 @@ | |||||||
| use crate::spec::BuildSpec; | use crate::spec::BuildSpec; | ||||||
| use convert_case::{Case, Casing}; |  | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use quote::{format_ident, quote}; | use quote::quote; | ||||||
| 
 | 
 | ||||||
| pub fn make_walk_fn(specs: &[BuildSpec]) -> TokenStream { | pub fn make_walk_fn(specs: &[BuildSpec]) -> TokenStream { | ||||||
|     let child_match_arms = specs |  | ||||||
|         .iter() |  | ||||||
|         .map(|spec| match spec { |  | ||||||
|             BuildSpec::Enum(enum_spec) => Some(( |  | ||||||
|                 format_ident!("{}", enum_spec.build()), |  | ||||||
|                 format_ident!("{}", enum_spec.build().to_case(Case::Snake)), |  | ||||||
|             )), |  | ||||||
|             BuildSpec::LeafEnum(leaf_enum) => Some(( |  | ||||||
|                 format_ident!("{}", leaf_enum.build()), |  | ||||||
|                 format_ident!("{}", leaf_enum.build().to_case(Case::Snake)), |  | ||||||
|             )), |  | ||||||
|             BuildSpec::Struct(struct_spec) => Some(( |  | ||||||
|                 format_ident!("{}", struct_spec.build()), |  | ||||||
|                 format_ident!("{}", struct_spec.build().to_case(Case::Snake)), |  | ||||||
|             )), |  | ||||||
|             BuildSpec::LeafStruct(leaf_struct) => Some(( |  | ||||||
|                 format_ident!("{}", leaf_struct.build()), |  | ||||||
|                 format_ident!("{}", leaf_struct.build().to_case(Case::Snake)), |  | ||||||
|             )), |  | ||||||
|             BuildSpec::Production(_) => None, |  | ||||||
|             BuildSpec::NodeProduction(_) => None, |  | ||||||
|             BuildSpec::PolymorphicType(polymorphic_type) => Some(( |  | ||||||
|                 format_ident!("{}", polymorphic_type.name()), |  | ||||||
|                 format_ident!("{}", polymorphic_type.name().to_case(Case::Snake)), |  | ||||||
|             )), |  | ||||||
|             BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some(( |  | ||||||
|                 format_ident!("{}", polymorphic_enum_loop.name()), |  | ||||||
|                 format_ident!("{}", polymorphic_enum_loop.name().to_case(Case::Snake)), |  | ||||||
|             )), |  | ||||||
|             BuildSpec::PolymorphicPassThrough(_) => None, |  | ||||||
|         }) |  | ||||||
|         .filter(Option::is_some) |  | ||||||
|         .map(Option::unwrap) |  | ||||||
|         .map(|(type_ident, inner_ident)| { |  | ||||||
|             quote! { |  | ||||||
|                 #type_ident(#inner_ident) => walk_depth_first(#inner_ident, f) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|         .collect::<Vec<_>>(); |  | ||||||
| 
 |  | ||||||
|     quote! { |     quote! { | ||||||
|         use crate::ast::node::*; |         use crate::ast::node::*; | ||||||
|         use crate::ast::ast_node::*; |         use crate::ast::ast_node::*; | ||||||
| 
 | 
 | ||||||
|         pub fn walk_depth_first(node: &impl AstNode, f: &mut impl FnMut(AstNodeRef)) { |         pub fn walk_depth_first<'a>(node: &'a dyn AstNode<'a>, f: &mut impl FnMut(AstNodeRef<'a>)) { | ||||||
|             use AstNodeRef::*; |             use AstNodeRef::*; | ||||||
|             for child in node.children() { |             for child in node.children() { | ||||||
|                 match child { |                 walk_depth_first(child, f); | ||||||
|                     #(#child_match_arms,)* |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             f(node.as_node_ref()); |             f(node.as_node_ref()); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -7,8 +7,8 @@ fn getWorlds() -> List<World> = [ | |||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| fn findWorldByColor(worlds: List<World>, color: String) -> String | fn findWorldByColor(worlds: List<World>, color: String) -> String | ||||||
|     worlds.find { it.color == color } |     worlds.find { it -> it.color == color } | ||||||
|         .map { it.name } |         .map { it -> it.name } | ||||||
|         .expect "No world has the given color ${color}" |         .expect "No world has the given color ${color}" | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ 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(compilation_units.as_mut_slice(), &files, &mut symbol_table); |     let diagnostics = analyze_names(&compilation_units, &files, &mut symbol_table); | ||||||
|     if diagnostics.is_empty() { |     if diagnostics.is_empty() { | ||||||
|         println!("Name analysis complete."); |         println!("Name analysis complete."); | ||||||
|         println!("{}", symbol_table); |         println!("{}", symbol_table); | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -19,42 +19,46 @@ The resolve phase has one main responsibility: resolve all references based on t | |||||||
| `scope_id` property. | `scope_id` property. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| use crate::ast::node::{CompilationUnit, VariableUse}; | // use crate::name_analysis::resolve::resolve_compilation_unit;
 | ||||||
|  | use crate::ast::ast_node::AstNode; | ||||||
|  | use crate::ast::node::CompilationUnit; | ||||||
| use crate::diagnostic::DmDiagnostic; | 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::symbol_table::SymbolTable; | use crate::name_analysis::symbol_table::SymbolTable; | ||||||
| use codespan_reporting::files::Files; | use codespan_reporting::files::Files; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
|  | use std::hash::Hash; | ||||||
|  | use crate::name_analysis::scope_table::ScopeTable; | ||||||
| 
 | 
 | ||||||
| pub(self) 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; | ||||||
|  | mod scope_table; | ||||||
| 
 | 
 | ||||||
| pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( | pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( | ||||||
|     compilation_units: &mut [Box<CompilationUnit>], |     compilation_units: &[Box<CompilationUnit>], | ||||||
|     files: &'a F, |     files: &'a F, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| ) -> Vec<DmDiagnostic> { | ) -> Vec<DmDiagnostic> { | ||||||
|     let mut diagnostics = vec![]; |     let mut diagnostics = vec![]; | ||||||
|     let mut scope_ids: HashMap<VariableUse, usize> = HashMap::new(); |     let mut scope_table = ScopeTable::new(); | ||||||
| 
 | 
 | ||||||
|     // gather symbols
 |     // gather symbols
 | ||||||
|     for compilation_unit in compilation_units.iter_mut() { |     for compilation_unit in compilation_units { | ||||||
|         let file_name = files.name(compilation_unit.file_id()).unwrap(); |         let file_name = files.name(compilation_unit.file_id()).unwrap(); | ||||||
|         gather_compilation_unit( |         gather_compilation_unit( | ||||||
|             compilation_unit, |             compilation_unit, | ||||||
|             &file_name, |             &file_name, | ||||||
|             symbol_table, |             symbol_table, | ||||||
|             &mut scope_ids, |             &mut scope_table, | ||||||
|             &mut diagnostics, |             &mut diagnostics, | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // resolve symbols
 |     // resolve symbols
 | ||||||
|     for compilation_unit in compilation_units.iter_mut() { |     for compilation_unit in compilation_units { | ||||||
|         // resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
 |         // resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										32
									
								
								src/name_analysis/scope_table/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/name_analysis/scope_table/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | use crate::ast::node::{FullyQualifiedName, VariableUse}; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | pub struct ScopeTable<'a> { | ||||||
|  |     variable_use_scopes: HashMap<&'a VariableUse, usize>, | ||||||
|  |     fqn_scopes: HashMap<&'a FullyQualifiedName, usize>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'a> ScopeTable<'a> { | ||||||
|  |     pub fn new() -> Self { | ||||||
|  |         Self { | ||||||
|  |             variable_use_scopes: HashMap::new(), | ||||||
|  |             fqn_scopes: HashMap::new(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn insert_variable_use_scope(&mut self, variable_use: &'a VariableUse, scope_id: usize) { | ||||||
|  |         self.variable_use_scopes.insert(variable_use, scope_id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn insert_fqn_scope(&mut self, fqn: &'a FullyQualifiedName, scope_id: usize) { | ||||||
|  |         self.fqn_scopes.insert(fqn, scope_id); | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     pub fn variable_use_scope(&self, variable_use: &'a VariableUse) -> Option<usize> { | ||||||
|  |         self.variable_use_scopes.get(&variable_use).copied() | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     pub fn fqn_scope(&self, fqn: &'a FullyQualifiedName) -> Option<usize> { | ||||||
|  |         self.fqn_scopes.get(&fqn).copied() | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -45,8 +45,11 @@ impl SymbolTable { | |||||||
| 
 | 
 | ||||||
|     pub fn push_scope(&mut self, debug_name: &str) { |     pub fn push_scope(&mut self, debug_name: &str) { | ||||||
|         let id = self.scopes.len(); |         let id = self.scopes.len(); | ||||||
|         self.scopes |         self.scopes.push(Scope::new( | ||||||
|             .push(Scope::new(Some(self.current_scope_id), id, debug_name.to_string())); |             Some(self.current_scope_id), | ||||||
|  |             id, | ||||||
|  |             debug_name.to_string(), | ||||||
|  |         )); | ||||||
|         self.current_scope_id = id; |         self.current_scope_id = id; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -316,7 +319,61 @@ impl SymbolTable { | |||||||
|                 Some(&self.scopes[parent_id]) |                 Some(&self.scopes[parent_id]) | ||||||
|             } else { |             } else { | ||||||
|                 None |                 None | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         Err(NoDefinition) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn lookup_addressable_in_scope_by_identifier( | ||||||
|  |         scope: &Scope, | ||||||
|  |         identifier: &str, | ||||||
|  |     ) -> Option<Symbol> { | ||||||
|  |         scope | ||||||
|  |             .variable_symbols() | ||||||
|  |             .get(identifier) | ||||||
|  |             .map(|variable_symbol| Symbol::Variable(variable_symbol.clone())) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 scope | ||||||
|  |                     .parameter_symbols() | ||||||
|  |                     .get(identifier) | ||||||
|  |                     .map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone())) | ||||||
|  |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 scope | ||||||
|  |                     .class_member_symbols() | ||||||
|  |                     .get(identifier) | ||||||
|  |                     .map(|class_member_symbol| Symbol::ClassMember(class_member_symbol.clone())) | ||||||
|  |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 scope | ||||||
|  |                     .function_symbols() | ||||||
|  |                     .get(identifier) | ||||||
|  |                     .map(|function_symbol| Symbol::Function(function_symbol.clone())) | ||||||
|  |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 scope | ||||||
|  |                     .type_symbols() | ||||||
|  |                     .get(identifier) | ||||||
|  |                     .map(|type_symbol| Symbol::Type(type_symbol.clone())) | ||||||
|  |             }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn lookup_addressable_by_identifier( | ||||||
|  |         &self, | ||||||
|  |         identifier: &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) = Self::lookup_addressable_in_scope_by_identifier(scope, identifier) | ||||||
|  |             { | ||||||
|  |                 return Ok(symbol); | ||||||
|             } |             } | ||||||
|  |             scope_opt = if let Some(parent_id) = scope.parent() { | ||||||
|  |                 Some(&self.scopes[parent_id]) | ||||||
|  |             } else { | ||||||
|  |                 None | ||||||
|  |             }; | ||||||
|         } |         } | ||||||
|         Err(NoDefinition) |         Err(NoDefinition) | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -50,7 +50,6 @@ Identifier: | |||||||
|       - range: |       - range: | ||||||
|           kind: range |           kind: range | ||||||
|     derive: |     derive: | ||||||
|       - Clone |  | ||||||
|       - PartialEq |       - PartialEq | ||||||
|       - Eq |       - Eq | ||||||
|       - Hash |       - Hash | ||||||
| @ -60,6 +59,10 @@ FullyQualifiedName: | |||||||
|       - identifiers: |       - identifiers: | ||||||
|           vec: |           vec: | ||||||
|             rule: Identifier |             rule: Identifier | ||||||
|  |     derive: | ||||||
|  |       - PartialEq | ||||||
|  |       - Eq | ||||||
|  |       - Hash | ||||||
| 
 | 
 | ||||||
| # Lists | # Lists | ||||||
| TypeUseList: | TypeUseList: | ||||||
| @ -74,7 +77,7 @@ IdentifierList: | |||||||
|       - identifiers: |       - identifiers: | ||||||
|           vec: |           vec: | ||||||
|             rule: Identifier |             rule: Identifier | ||||||
| ParenthesesOptionalTypeUseList: | ParenthesesTypeUseList: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
|       - type_use_list: |       - type_use_list: | ||||||
| @ -90,19 +93,29 @@ TypeUse: | |||||||
|       - TupleTypeUse |       - TupleTypeUse | ||||||
|       - FunctionTypeUse |       - FunctionTypeUse | ||||||
| PrimitiveType: | PrimitiveType: | ||||||
|   leaf_enum: |   tree_enum: | ||||||
|     rules: |     rules: | ||||||
|       - Byte |       - Byte: | ||||||
|       - Short |           child: false | ||||||
|       - Char |       - Short: | ||||||
|       - Int |           child: false | ||||||
|       - Long |       - Char: | ||||||
|       - Double |           child: false | ||||||
|       - Bool |       - Int: | ||||||
|       - String |           child: false | ||||||
|  |       - Long: | ||||||
|  |           child: false | ||||||
|  |       - Double: | ||||||
|  |           child: false | ||||||
|  |       - Bool: | ||||||
|  |           child: false | ||||||
|  |       - String: | ||||||
|  |           child: false | ||||||
|       - TypedArray |       - TypedArray | ||||||
|       - Any |       - Any: | ||||||
|       - Void |           child: false | ||||||
|  |       - Void: | ||||||
|  |           child: false | ||||||
| TypedArray: | TypedArray: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
| @ -160,7 +173,7 @@ GenericParameters: | |||||||
| TupleArguments: | TupleArguments: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
|       - parentheses_optional_type_use_list |       - parentheses_type_use_list | ||||||
| 
 | 
 | ||||||
| # Implements List | # Implements List | ||||||
| ImplementsList: | ImplementsList: | ||||||
| @ -656,7 +669,7 @@ IfClause: | |||||||
|           skip: |           skip: | ||||||
|             rule: Then |             rule: Then | ||||||
|       - statements: |       - statements: | ||||||
|           skip: |           vec: | ||||||
|             rule: Statement |             rule: Statement | ||||||
| IfElseIf: | IfElseIf: | ||||||
|   struct: |   struct: | ||||||
| @ -704,7 +717,7 @@ ForStatement: | |||||||
|       - do_kw: |       - do_kw: | ||||||
|           skip: |           skip: | ||||||
|             rule: Do |             rule: Do | ||||||
|       - statement: |       - statements: | ||||||
|           vec: |           vec: | ||||||
|             rule: Statement |             rule: Statement | ||||||
|       - end_kw: |       - end_kw: | ||||||
| @ -731,7 +744,6 @@ VariableUse: | |||||||
|     children: |     children: | ||||||
|       - identifier |       - identifier | ||||||
|     derive: |     derive: | ||||||
|       - Clone |  | ||||||
|       - PartialEq |       - PartialEq | ||||||
|       - Eq |       - Eq | ||||||
|       - Hash |       - Hash | ||||||
|  | |||||||
| @ -199,7 +199,7 @@ IdentifierList = { | |||||||
|     ~ ( "," ~ Identifier )* |     ~ ( "," ~ Identifier )* | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParenthesesOptionalTypeUseList = { | ParenthesesTypeUseList = { | ||||||
|       "(" |       "(" | ||||||
|     ~ TypeUseList? |     ~ TypeUseList? | ||||||
|     ~ ")" |     ~ ")" | ||||||
| @ -272,7 +272,7 @@ GenericParameters = { | |||||||
| // Tuple Arguments | // Tuple Arguments | ||||||
| 
 | 
 | ||||||
| TupleArguments = { | TupleArguments = { | ||||||
|     ParenthesesOptionalTypeUseList |     ParenthesesTypeUseList | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Implements list | // Implements list | ||||||
|  | |||||||
							
								
								
									
										205
									
								
								src/vm/mem/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								src/vm/mem/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,205 @@ | |||||||
|  | use std::cell::RefCell; | ||||||
|  | use std::marker::PhantomData; | ||||||
|  | use std::ops::Mul; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct Gc<T> { | ||||||
|  |     inner: *mut GcInner, | ||||||
|  |     data: *const T, | ||||||
|  |     _phantom: PhantomData<T>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct GcInner { | ||||||
|  |     color: GcColor, | ||||||
|  |     size: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl GcInner { | ||||||
|  |     pub fn new(size: usize) -> Self { | ||||||
|  |         Self { | ||||||
|  |             color: GcColor::White, | ||||||
|  |             size, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(PartialEq, Eq, Copy, Clone, Debug)] | ||||||
|  | pub enum GcColor { | ||||||
|  |     White, | ||||||
|  |     Black, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T> Gc<T> { | ||||||
|  |     pub fn new(data: T) -> Self { | ||||||
|  |         let inner = Box::into_raw(Box::new(GcInner::new(size_of::<T>()))); | ||||||
|  |         let boxed_data = Box::into_raw(Box::new(data)) as *const T; | ||||||
|  |         Self { | ||||||
|  |             inner, | ||||||
|  |             data: boxed_data, | ||||||
|  |             _phantom: PhantomData, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn set_color(&mut self, color: GcColor) { | ||||||
|  |         unsafe { | ||||||
|  |             (*self.inner).color = color; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn color(&self) -> GcColor { | ||||||
|  |         unsafe { (*self.inner).color } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn size(&self) -> usize { | ||||||
|  |         unsafe { (*self.inner).size } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn data(&self) -> &T { | ||||||
|  |         unsafe { &*self.data } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn dealloc(&mut self) { | ||||||
|  |         unsafe { | ||||||
|  |             drop(Box::from_raw(self.inner)); | ||||||
|  |             drop(Box::from_raw(self.data as *mut T)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T> Clone for Gc<T> { | ||||||
|  |     fn clone(&self) -> Self { | ||||||
|  |         Self { | ||||||
|  |             inner: self.inner, | ||||||
|  |             data: self.data, | ||||||
|  |             _phantom: PhantomData, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | enum DvmValue { | ||||||
|  |     Primitive(usize), | ||||||
|  |     Object(Gc<RefCell<DvmObject>>), | ||||||
|  |     Nil, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct DvmObject { | ||||||
|  |     fields: Vec<DvmValue>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl DvmObject { | ||||||
|  |     pub fn new() -> Self { | ||||||
|  |         Self { fields: vec![] } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn fields(&self) -> &[DvmValue] { | ||||||
|  |         &self.fields | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn fields_mut(&mut self) -> &mut Vec<DvmValue> { | ||||||
|  |         &mut self.fields | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn collect_garbage( | ||||||
|  |     next_gc: &mut usize, | ||||||
|  |     current_size: &mut usize, | ||||||
|  |     stack: &Vec<DvmValue>, | ||||||
|  |     gcs: &mut Vec<Gc<RefCell<DvmObject>>>, | ||||||
|  | ) { | ||||||
|  |     let mut gray_stack: Vec<Gc<RefCell<DvmObject>>> = vec![]; | ||||||
|  | 
 | ||||||
|  |     for stack_value in stack { | ||||||
|  |         match stack_value { | ||||||
|  |             DvmValue::Object(gc) => { | ||||||
|  |                 if gc.color() == GcColor::White { | ||||||
|  |                     gray_stack.push(gc.clone()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => {} | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     while let Some(mut current) = gray_stack.pop() { | ||||||
|  |         for field in current.data().borrow().fields() { | ||||||
|  |             match field { | ||||||
|  |                 DvmValue::Object(object) => { | ||||||
|  |                     gray_stack.push(object.clone()); | ||||||
|  |                 } | ||||||
|  |                 _ => {} | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         current.set_color(GcColor::Black); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let mut collected_size: usize = 0; | ||||||
|  | 
 | ||||||
|  |     for i in (0..gcs.len()).rev() { | ||||||
|  |         if gcs[i].color() == GcColor::White { | ||||||
|  |             let mut gc = gcs.remove(i); | ||||||
|  |             let size = gc.size(); | ||||||
|  |             *current_size -= size; | ||||||
|  |             collected_size += size; | ||||||
|  |             gc.dealloc(); | ||||||
|  |         } else { | ||||||
|  |             gcs[i].set_color(GcColor::White); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     *next_gc = std::cmp::max(1024 * 1024, current_size.mul(2)); | ||||||
|  |     println!( | ||||||
|  |         "collected_size: {}, current_size: {}, next_gc: {}", | ||||||
|  |         collected_size, current_size, next_gc | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn maybe_collect_garbage( | ||||||
|  |     next_gc: &mut usize, | ||||||
|  |     current_size: &mut usize, | ||||||
|  |     stack: &Vec<DvmValue>, | ||||||
|  |     gcs: &mut Vec<Gc<RefCell<DvmObject>>>, | ||||||
|  | ) { | ||||||
|  |     if current_size > next_gc { | ||||||
|  |         collect_garbage(next_gc, current_size, stack, gcs); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn alloc_dvm_object( | ||||||
|  |     next_gc: &mut usize, | ||||||
|  |     current_size: &mut usize, | ||||||
|  |     stack: &Vec<DvmValue>, | ||||||
|  |     gcs: &mut Vec<Gc<RefCell<DvmObject>>>, | ||||||
|  | ) -> Gc<RefCell<DvmObject>> { | ||||||
|  |     maybe_collect_garbage(next_gc, current_size, stack, gcs); | ||||||
|  |     let mut object = DvmObject::new(); | ||||||
|  |     object.fields_mut().push(DvmValue::Nil); | ||||||
|  |     let gc = Gc::new(RefCell::new(object)); | ||||||
|  |     *current_size += gc.size(); | ||||||
|  |     gcs.push(gc.clone()); | ||||||
|  |     gc | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn set_field(obj: &mut Gc<RefCell<DvmObject>>, field_index: usize, value: DvmValue) { | ||||||
|  |     let mut binding = obj.data().borrow_mut(); | ||||||
|  |     binding.fields_mut()[field_index] = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use crate::vm::mem::{alloc_dvm_object, collect_garbage, DvmObject, DvmValue, Gc}; | ||||||
|  |     use std::cell::RefCell; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test() { | ||||||
|  |         let mut stack: Vec<DvmValue> = vec![]; | ||||||
|  |         let mut heap: Vec<Gc<RefCell<DvmObject>>> = vec![]; | ||||||
|  |         let mut next_gc: usize = 1024 * 1024; | ||||||
|  |         let mut current_size: usize = 0; | ||||||
|  |         for i in 0..100_000_000 { | ||||||
|  |             let mut o = alloc_dvm_object(&mut next_gc, &mut current_size, &stack, &mut heap); | ||||||
|  |         } | ||||||
|  |         collect_garbage(&mut next_gc, &mut current_size, &stack, &mut heap); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -6,6 +6,7 @@ pub mod implementation; | |||||||
| pub mod instruction; | pub mod instruction; | ||||||
| pub mod interface; | pub mod interface; | ||||||
| pub mod lib; | pub mod lib; | ||||||
|  | mod mem; | ||||||
| pub mod method; | pub mod method; | ||||||
| pub mod object; | pub mod object; | ||||||
| pub mod op_codes; | pub mod op_codes; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user