diff --git a/ast-generator/src/deserialize/struct_spec.rs b/ast-generator/src/deserialize/struct_spec.rs index bae37c8..9cb5295 100644 --- a/ast-generator/src/deserialize/struct_spec.rs +++ b/ast-generator/src/deserialize/struct_spec.rs @@ -151,5 +151,15 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec { } else { deserialize_error!("array", "children", name); }; - StructSpec::new(name, children) + let derive = if struct_yaml["derive"].is_array() { + struct_yaml["derive"].as_vec() + .unwrap() + .iter() + .map(|derive| derive.as_str().unwrap().to_string()) + .collect() + } else { + vec![] + }; + + StructSpec::new(name, children, derive) } diff --git a/ast-generator/src/spec/struct_spec.rs b/ast-generator/src/spec/struct_spec.rs index e8a593e..aeb97a3 100644 --- a/ast-generator/src/spec/struct_spec.rs +++ b/ast-generator/src/spec/struct_spec.rs @@ -1,13 +1,15 @@ pub struct StructSpec { build: String, children: Vec>, + derive: Vec, } impl StructSpec { - pub fn new(build: &str, children: Vec>) -> Self { + pub fn new(build: &str, children: Vec>, derive: Vec) -> Self { Self { build: build.to_string(), children, + derive, } } @@ -20,6 +22,10 @@ impl StructSpec { pub fn children(&self) -> impl Iterator { self.children.iter().map(Box::as_ref) } + + pub fn derive(&self) -> &[String] { + &self.derive + } } pub enum StructChild { diff --git a/ast-generator/src/type_gen/struct_type.rs b/ast-generator/src/type_gen/struct_type.rs index 72d3f1f..7e42117 100644 --- a/ast-generator/src/type_gen/struct_type.rs +++ b/ast-generator/src/type_gen/struct_type.rs @@ -205,10 +205,30 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream { .map(Option::unwrap) .collect::>(); - quote! { - pub struct #type_ident { - #(#annotated_members),* + let struct_stream = { + let base = quote! { + pub struct #type_ident { + #(#annotated_members),* + } + }; + if !build_spec.derive().is_empty() { + let derives = build_spec + .derive() + .iter() + .map(|derive| format_ident!("{}", derive)) + .collect::>(); + + quote! { + #[derive(#(#derives,)*)] + #base + } + } else { + base } + }; + + quote! { + #struct_stream impl #type_ident { pub fn new(#(#annotated_members),*) -> Self { diff --git a/src/name_analysis/gather.rs b/src/name_analysis/gather.rs index 8fbf08d..b607992 100644 --- a/src/name_analysis/gather.rs +++ b/src/name_analysis/gather.rs @@ -3,7 +3,7 @@ use crate::ast::node::{ Class, CompilationUnit, Function, FunctionBody, Identifier, Interface, InterfaceDefaultFunction, InterfaceDefaultOperatorFunction, InterfaceFunction, InterfaceOperatorFunction, Member, Module, Namespace, OperatorFunction, PlatformFunction, - PlatformOperatorFunction, Statement, UseStatement, UseStatementSuffix, VariableDeclaration, + PlatformOperatorFunction, UseStatement, UseStatementSuffix, VariableDeclaration, VariableUse, }; use crate::diagnostic::DmDiagnostic; use crate::name_analysis::fqn_context::FqnContext; @@ -18,6 +18,7 @@ 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::collections::HashMap; use std::range::Range; fn handle_insert_error( @@ -56,10 +57,11 @@ fn gather_node_children( node: &impl AstNode, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { for child in node.children() { - gather_node(child, symbol_table, fqn_context, diagnostics); + gather_node(child, symbol_table, fqn_context, scope_ids, diagnostics); } } @@ -67,6 +69,7 @@ fn gather_node( node: AstNodeRef, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { match node { @@ -97,7 +100,13 @@ fn gather_node( AstNodeRef::Parameter(_) => {} AstNodeRef::ReturnType(_) => {} AstNodeRef::CompilationUnit(compilation_unit) => { - gather_node_children(compilation_unit, symbol_table, fqn_context, diagnostics); + gather_node_children( + compilation_unit, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::Namespace(namespace) => { gather_namespace(namespace, fqn_context); @@ -119,6 +128,7 @@ fn gather_node( module_level_declaration, symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -127,6 +137,7 @@ fn gather_node( interface_level_declaration, symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -135,43 +146,64 @@ fn gather_node( class_level_declaration, symbol_table, fqn_context, + scope_ids, diagnostics, ); } AstNodeRef::Module(module) => { - gather_module(module, symbol_table, fqn_context, diagnostics); + gather_module(module, symbol_table, fqn_context, scope_ids, diagnostics); } AstNodeRef::Interface(interface) => { - gather_interface(interface, symbol_table, fqn_context, diagnostics); + gather_interface(interface, symbol_table, fqn_context, scope_ids, diagnostics); } AstNodeRef::Class(class) => { - gather_class(class, symbol_table, fqn_context, diagnostics); + gather_class(class, symbol_table, fqn_context, scope_ids, diagnostics); } AstNodeRef::Function(function) => { - gather_function(function, symbol_table, fqn_context, diagnostics); + gather_function(function, symbol_table, fqn_context, scope_ids, diagnostics); } AstNodeRef::OperatorFunction(operator_function) => { - gather_operator_function(operator_function, symbol_table, fqn_context, diagnostics); + gather_operator_function( + operator_function, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::PlatformFunction(platform_function) => { - gather_platform_function(platform_function, symbol_table, fqn_context, diagnostics); + gather_platform_function( + platform_function, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::PlatformOperatorFunction(platform_operator_function) => { gather_platform_operator_function( platform_operator_function, symbol_table, fqn_context, + scope_ids, diagnostics, ); } AstNodeRef::InterfaceFunction(interface_function) => { - gather_interface_function(interface_function, symbol_table, fqn_context, diagnostics); + gather_interface_function( + interface_function, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::InterfaceDefaultFunction(interface_default_function) => { gather_interface_default_function( interface_default_function, symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -180,6 +212,7 @@ fn gather_node( interface_operator_function, symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -188,35 +221,61 @@ fn gather_node( interface_default_operator_function, symbol_table, fqn_context, + scope_ids, diagnostics, ); } AstNodeRef::FunctionBody(function_body) => { - gather_function_body(function_body, symbol_table, fqn_context, diagnostics); + gather_function_body( + function_body, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::FunctionEqualsBody(function_equals_body) => { - gather_node_children(function_equals_body, symbol_table, fqn_context, diagnostics); + gather_node_children( + function_equals_body, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::FunctionAliasBody(_) => { // no-op } AstNodeRef::FunctionBlockBody(function_block_body) => { - gather_node_children(function_block_body, symbol_table, fqn_context, diagnostics); + gather_node_children( + function_block_body, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::ClassConstructor(class_constructor) => { - gather_node_children(class_constructor, symbol_table, fqn_context, diagnostics); + gather_node_children( + class_constructor, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); } AstNodeRef::Member(member) => { - gather_member(member, symbol_table, fqn_context, diagnostics); + gather_member(member, symbol_table, fqn_context, scope_ids, diagnostics); } AstNodeRef::Statement(statement) => { - gather_node_children(statement, symbol_table, fqn_context, diagnostics); + gather_node_children(statement, symbol_table, fqn_context, scope_ids, diagnostics); } AstNodeRef::VariableDeclaration(variable_declaration) => { gather_variable_declaration( variable_declaration, symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -228,9 +287,11 @@ fn gather_node( AstNodeRef::IfElse(_) => {} AstNodeRef::WhileStatement(_) => {} AstNodeRef::ForStatement(_) => {} - AstNodeRef::LValue(_) => {}, - AstNodeRef::LValueSuffix(_) => {}, - AstNodeRef::VariableUse(_) => {}, + AstNodeRef::LValue(_) => {} + AstNodeRef::LValueSuffix(_) => {} + AstNodeRef::VariableUse(variable_use) => { + gather_variable_use(variable_use, symbol_table, scope_ids); + } AstNodeRef::Expression(_) => {} AstNodeRef::TernaryExpression(_) => {} AstNodeRef::TernaryRhs(_) => {} @@ -276,6 +337,7 @@ pub fn gather_compilation_unit( compilation_unit: &mut CompilationUnit, file_name: &str, symbol_table: &mut SymbolTable, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let mut fqn_context = FqnContext::new(); @@ -284,6 +346,7 @@ pub fn gather_compilation_unit( compilation_unit.as_node_ref(), symbol_table, &mut fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -362,6 +425,7 @@ fn gather_module( module: &Module, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let module_symbol = ModuleSymbol::new( @@ -389,6 +453,7 @@ fn gather_module( declaration.as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -401,6 +466,7 @@ fn gather_interface( interface: &Interface, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let type_symbol = ConcreteTypeSymbol::new( @@ -431,6 +497,7 @@ fn gather_interface( declaration.as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -443,6 +510,7 @@ fn gather_class( class: &Class, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let class_symbol = ConcreteTypeSymbol::new( @@ -472,6 +540,7 @@ fn gather_class( class.class_constructor().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); for declaration in class.class_level_declarations() { @@ -479,6 +548,7 @@ fn gather_class( declaration.as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -491,6 +561,7 @@ fn gather_function( function: &Function, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -515,24 +586,28 @@ fn gather_function( function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( function.function_body().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -542,6 +617,7 @@ fn gather_operator_function( operator_function: &OperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -571,24 +647,28 @@ fn gather_operator_function( operator_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( operator_function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( operator_function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( operator_function.function_body().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -598,6 +678,7 @@ fn gather_platform_function( platform_function: &PlatformFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -627,18 +708,21 @@ fn gather_platform_function( platform_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( platform_function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( platform_function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -648,6 +732,7 @@ fn gather_platform_operator_function( platform_operator_function: &PlatformOperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -677,18 +762,21 @@ fn gather_platform_operator_function( platform_operator_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( platform_operator_function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( platform_operator_function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -698,6 +786,7 @@ fn gather_interface_function( interface_function: &InterfaceFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -727,18 +816,21 @@ fn gather_interface_function( interface_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -748,6 +840,7 @@ fn gather_interface_default_function( interface_default_function: &InterfaceDefaultFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -777,24 +870,28 @@ fn gather_interface_default_function( interface_default_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_default_function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_default_function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_default_function.function_body().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -804,6 +901,7 @@ fn gather_interface_operator_function( interface_operator_function: &InterfaceOperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -833,18 +931,21 @@ fn gather_interface_operator_function( interface_operator_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_operator_function.parameters().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( interface_operator_function.return_type().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -854,6 +955,7 @@ fn gather_interface_default_operator_function( interface_default_operator_function: &InterfaceDefaultOperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -897,6 +999,7 @@ fn gather_interface_default_operator_function( interface_default_operator_function.generics().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( @@ -905,6 +1008,7 @@ fn gather_interface_default_operator_function( .as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( @@ -913,6 +1017,7 @@ fn gather_interface_default_operator_function( .as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); gather_node( @@ -921,6 +1026,7 @@ fn gather_interface_default_operator_function( .as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); symbol_table.pop_scope(); @@ -930,35 +1036,17 @@ fn gather_function_body( function_body: &FunctionBody, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { symbol_table.push_scope("FunctionBodyScope"); - 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, - ); - } - } + gather_node_children( + function_body, + symbol_table, + fqn_context, + scope_ids, + diagnostics, + ); symbol_table.pop_scope(); } @@ -966,6 +1054,7 @@ fn gather_member( member: &Member, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let member_symbol = ClassMemberSymbol::new( @@ -988,6 +1077,7 @@ fn gather_member( member.type_use().as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); } @@ -996,6 +1086,7 @@ fn gather_variable_declaration( variable_declaration: &VariableDeclaration, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, + scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { let variable_symbol = VariableSymbol::new( @@ -1020,7 +1111,16 @@ fn gather_variable_declaration( expression.as_node_ref(), symbol_table, fqn_context, + scope_ids, diagnostics, ); } } + +fn gather_variable_use( + variable_use: &VariableUse, + symbol_table: &mut SymbolTable, + scope_ids: &mut HashMap, +) { + scope_ids.insert(variable_use.clone(), symbol_table.current_scope_id()); +} diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index 08fa285..ca6f682 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -19,7 +19,7 @@ The resolve phase has one main responsibility: resolve all references based on t `scope_id` property. */ -use crate::ast::node::{CompilationUnit, Identifier}; +use crate::ast::node::{CompilationUnit, VariableUse}; use crate::diagnostic::DmDiagnostic; use crate::name_analysis::gather::gather_compilation_unit; // use crate::name_analysis::resolve::resolve_compilation_unit; @@ -39,12 +39,18 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( symbol_table: &mut SymbolTable, ) -> Vec { let mut diagnostics = vec![]; - let mut identifier_scope_ids: HashMap = HashMap::new(); + let mut scope_ids: HashMap = HashMap::new(); // gather symbols for compilation_unit in compilation_units.iter_mut() { let file_name = files.name(compilation_unit.file_id()).unwrap(); - gather_compilation_unit(compilation_unit, &file_name, symbol_table, &mut diagnostics); + gather_compilation_unit( + compilation_unit, + &file_name, + symbol_table, + &mut scope_ids, + &mut diagnostics, + ); } // resolve symbols diff --git a/src/parser/ast.yaml b/src/parser/ast.yaml index 1f061b9..604299e 100644 --- a/src/parser/ast.yaml +++ b/src/parser/ast.yaml @@ -730,6 +730,11 @@ VariableUse: struct: children: - identifier + derive: + - Clone + - PartialEq + - Eq + - Hash # Expressions Expression: