Compare commits
	
		
			6 Commits
		
	
	
		
			c606432be2
			...
			f614d00575
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f614d00575 | ||
|   | 4c68d0dc28 | ||
|   | 88270e0cdd | ||
|   | 02d6a16cf8 | ||
|   | 0c2d9f8b2f | ||
|   | abb7aab3a4 | 
| @ -1,17 +1,5 @@ | |||||||
| ns greeter | ns greeter; | ||||||
| 
 |  | ||||||
| fn main(x: String) { |  | ||||||
|     let x = 'Hello'; |  | ||||||
|     let y = 'World'; |  | ||||||
|     { |  | ||||||
|         let test = 'test'; |  | ||||||
|         let x = 'x'; |  | ||||||
|         let y = 'y'; |  | ||||||
|         let z = 'z'; |  | ||||||
|         let test = 'oops.'; |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub mod test { |  | ||||||
| 
 | 
 | ||||||
|  | fn main(args: Array<String>) { | ||||||
|  |     println(args); | ||||||
| } | } | ||||||
							
								
								
									
										7
									
								
								sketching/may_2025/std_core.dm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								sketching/may_2025/std_core.dm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | ns std::core; | ||||||
|  | 
 | ||||||
|  | class Array<T> {} | ||||||
|  | 
 | ||||||
|  | class String {} | ||||||
|  | 
 | ||||||
|  | platform fn println(msg: Any) -> Void; | ||||||
| @ -1,3 +1 @@ | |||||||
| use std::core::println; |  | ||||||
| use std::core::*; |  | ||||||
| use std::core::{print, println}; | use std::core::{print, println}; | ||||||
|  | |||||||
| @ -55,7 +55,9 @@ fn build_fqn(file_id: usize, fqn_pair: Pair<Rule>) -> FullyQualifiedName { | |||||||
| fn build_type_use(file_id: usize, type_use_pair: Pair<Rule>) -> TypeUse { | fn build_type_use(file_id: usize, type_use_pair: Pair<Rule>) -> TypeUse { | ||||||
|     let inner_pair = type_use_pair.into_inner().next().unwrap(); |     let inner_pair = type_use_pair.into_inner().next().unwrap(); | ||||||
|     match inner_pair.as_rule() { |     match inner_pair.as_rule() { | ||||||
|         Rule::Void => TypeUse::Void, |         Rule::PrimitiveType => { | ||||||
|  |             TypeUse::Primitive(build_primitive_type(file_id, inner_pair)) | ||||||
|  |         }, | ||||||
|         Rule::InterfaceOrClassTypeUse => { |         Rule::InterfaceOrClassTypeUse => { | ||||||
|             TypeUse::InterfaceOrClass(build_interface_or_class_type_use(file_id, inner_pair)) |             TypeUse::InterfaceOrClass(build_interface_or_class_type_use(file_id, inner_pair)) | ||||||
|         } |         } | ||||||
| @ -65,6 +67,35 @@ fn build_type_use(file_id: usize, type_use_pair: Pair<Rule>) -> TypeUse { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn build_primitive_type( | ||||||
|  |     file_id: usize, | ||||||
|  |     primitive_type_pair: Pair<Rule>, | ||||||
|  | ) -> PrimitiveTypeUse { | ||||||
|  |     let mut inner = primitive_type_pair.into_inner(); | ||||||
|  |     match inner.next().unwrap().as_rule() { | ||||||
|  |         Rule::Byte => PrimitiveTypeUse::Byte, | ||||||
|  |         Rule::Short => PrimitiveTypeUse::Short, | ||||||
|  |         Rule::Char => PrimitiveTypeUse::Char, | ||||||
|  |         Rule::Int => PrimitiveTypeUse::Int, | ||||||
|  |         Rule::Long => PrimitiveTypeUse::Long, | ||||||
|  |         Rule::Double => PrimitiveTypeUse::Double, | ||||||
|  |         Rule::Bool => PrimitiveTypeUse::Bool, | ||||||
|  |         Rule::String => PrimitiveTypeUse::String, | ||||||
|  |         Rule::Array => { | ||||||
|  |             if let Some(generic_arguments_pair) = inner.next() { | ||||||
|  |                 PrimitiveTypeUse::Array( | ||||||
|  |                     Some(Box::new(build_generic_arguments(file_id, generic_arguments_pair))) | ||||||
|  |                 ) | ||||||
|  |             } else { | ||||||
|  |                 PrimitiveTypeUse::Array(None) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Rule::Any => PrimitiveTypeUse::Any, | ||||||
|  |         Rule::Void => PrimitiveTypeUse::Void, | ||||||
|  |         _ => unreachable!(), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn build_interface_or_class_type_use(file_id: usize, pair: Pair<Rule>) -> InterfaceOrClassTypeUse { | fn build_interface_or_class_type_use(file_id: usize, pair: Pair<Rule>) -> InterfaceOrClassTypeUse { | ||||||
|     let mut borrow_count = 0; |     let mut borrow_count = 0; | ||||||
|     let mut is_mutable = false; |     let mut is_mutable = false; | ||||||
|  | |||||||
							
								
								
									
										241
									
								
								src/ast/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										241
									
								
								src/ast/mod.rs
									
									
									
									
									
								
							| @ -10,7 +10,8 @@ pub mod build; | |||||||
| pub mod named; | pub mod named; | ||||||
| pub mod pretty_print; | pub mod pretty_print; | ||||||
| pub mod unparse; | pub mod unparse; | ||||||
| // Operators
 | 
 | ||||||
|  | /* Operators */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum Operator { | pub enum Operator { | ||||||
| @ -56,13 +57,13 @@ pub enum SuffixUnaryOperator { | |||||||
| 
 | 
 | ||||||
| /* Names */ | /* Names */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug)] | ||||||
| pub struct Identifier { | pub struct Identifier { | ||||||
|     pub name: String, |     name: String, | ||||||
|     pub file_id: usize, |     file_id: usize, | ||||||
|     pub range: Range<usize>, |     range: Range<usize>, | ||||||
|     scope_id: Option<usize>, |     scope_id: Option<usize>, | ||||||
|     symbol: Option<Symbol>, |     saved_symbol: Option<Symbol>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Identifier { | impl Identifier { | ||||||
| @ -72,38 +73,18 @@ impl Identifier { | |||||||
|             file_id, |             file_id, | ||||||
|             range, |             range, | ||||||
|             scope_id: None, |             scope_id: None, | ||||||
|             symbol: None, |             saved_symbol: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     pub fn set_scope_id(&mut self, id: usize) { |  | ||||||
|         self.scope_id = Some(id); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn scope_id(&self) -> Option<usize> { |  | ||||||
|         self.scope_id |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn set_symbol(&mut self, symbol: Symbol) { |  | ||||||
|         self.symbol = Some(symbol); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn symbol(&self) -> &Option<Symbol> { |  | ||||||
|         &self.symbol |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn symbol_mut(&mut self) -> Option<Symbol> { |  | ||||||
|         self.symbol.clone() |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct FullyQualifiedName { | pub struct FullyQualifiedName { | ||||||
|     pub identifiers: Vec<Identifier>, |     identifiers: Vec<Identifier>, | ||||||
|     pub file_id: usize, |     file_id: usize, | ||||||
|     pub range: Range<usize>, |     range: Range<usize>, | ||||||
|     scope_id: Option<usize>, |     scope_id: Option<usize>, | ||||||
|     symbol: Option<Symbol>, |     saved_symbol: Option<Symbol>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl FullyQualifiedName { | impl FullyQualifiedName { | ||||||
| @ -113,24 +94,25 @@ impl FullyQualifiedName { | |||||||
|             range, |             range, | ||||||
|             file_id, |             file_id, | ||||||
|             scope_id: None, |             scope_id: None, | ||||||
|             symbol: None, |             saved_symbol: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn set_scope_id(&mut self, scope_id: usize) { |     pub fn last(&self) -> &Identifier { | ||||||
|         self.scope_id = Some(scope_id); |         &self.identifiers[self.identifiers.len() - 1] | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn scope_id(&self) -> Option<usize> { |     pub fn last_mut(&mut self) -> &mut Identifier { | ||||||
|         self.scope_id |         let last_index = self.identifiers.len() - 1; | ||||||
|  |         &mut self.identifiers[last_index] | ||||||
|     } |     } | ||||||
|     
 |     
 | ||||||
|     pub fn set_symbol(&mut self, symbol: Symbol) { |     pub fn len(&self) -> usize { | ||||||
|         self.symbol = Some(symbol); |         self.identifiers.len() | ||||||
|     } |     } | ||||||
|     
 |     
 | ||||||
|     pub fn symbol(&self) -> &Option<Symbol> { |     pub fn is_single_identifier(&self) -> bool { | ||||||
|         &self.symbol |         self.identifiers.len() == 1 | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -138,12 +120,27 @@ impl FullyQualifiedName { | |||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum TypeUse { | pub enum TypeUse { | ||||||
|     Void, |     Primitive(PrimitiveTypeUse), | ||||||
|     InterfaceOrClass(InterfaceOrClassTypeUse), |     InterfaceOrClass(InterfaceOrClassTypeUse), | ||||||
|     Tuple(TupleTypeUse), |     Tuple(TupleTypeUse), | ||||||
|     Function(FunctionTypeUse), |     Function(FunctionTypeUse), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub enum PrimitiveTypeUse { | ||||||
|  |     Byte, | ||||||
|  |     Short, | ||||||
|  |     Char, | ||||||
|  |     Int, | ||||||
|  |     Long, | ||||||
|  |     Double, | ||||||
|  |     Bool, | ||||||
|  |     String, | ||||||
|  |     Array(Option<Box<GenericArguments>>), | ||||||
|  |     Any, | ||||||
|  |     Void, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct InterfaceOrClassTypeUse { | pub struct InterfaceOrClassTypeUse { | ||||||
|     pub borrow_count: usize, |     pub borrow_count: usize, | ||||||
| @ -168,7 +165,7 @@ pub struct FunctionTypeUse { | |||||||
|     pub return_type: ReturnType, |     pub return_type: ReturnType, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Generic arguments
 | /* Generic arguments */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct GenericArguments(pub Vec<TypeUse>); | pub struct GenericArguments(pub Vec<TypeUse>); | ||||||
| @ -268,7 +265,7 @@ pub struct ReturnType { | |||||||
| impl ReturnType { | impl ReturnType { | ||||||
|     pub fn void() -> Self { |     pub fn void() -> Self { | ||||||
|         ReturnType { |         ReturnType { | ||||||
|             declared_type: Box::new(TypeUse::Void), |             declared_type: Box::new(TypeUse::Primitive(PrimitiveTypeUse::Void)), | ||||||
|             references: References::default(), |             references: References::default(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -302,7 +299,68 @@ pub struct CompilationUnit { | |||||||
|     pub declarations: Vec<ModuleLevelDeclaration>, |     pub declarations: Vec<ModuleLevelDeclaration>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Declarations allowed in each level
 | /* Use Statement */ | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct UseStatement { | ||||||
|  |     pub identifiers: Vec<Identifier>, | ||||||
|  |     pub last: UseStatementLast, | ||||||
|  |     pub file_id: usize, | ||||||
|  |     pub range: Range<usize>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl UseStatement { | ||||||
|  |     pub fn new( | ||||||
|  |         identifiers: Vec<Identifier>, | ||||||
|  |         last: UseStatementLast, | ||||||
|  |         file_id: usize, | ||||||
|  |         range: Range<usize>, | ||||||
|  |     ) -> Self { | ||||||
|  |         UseStatement { | ||||||
|  |             identifiers, | ||||||
|  |             last, | ||||||
|  |             file_id, | ||||||
|  |             range, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn base_name(&self) -> Cow<'_, str> { | ||||||
|  |         use UseStatementLast::*; | ||||||
|  |         if self.identifiers.is_empty() { | ||||||
|  |             match &self.last { | ||||||
|  |                 Identifier(_) => Cow::from(""), | ||||||
|  |                 Star | Identifiers(_) => panic!(), // should never get here because of grammar
 | ||||||
|  |             } | ||||||
|  |         } else if self.identifiers.len() == 1 { | ||||||
|  |             self.identifiers[0].name() | ||||||
|  |         } else { | ||||||
|  |             let mut acc = String::new(); | ||||||
|  |             for (i, identifier) in self.identifiers.iter().enumerate() { | ||||||
|  |                 acc.push_str(&identifier.name()); | ||||||
|  |                 if i != self.identifiers.len() - 1 { | ||||||
|  |                     acc.push_str("::"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Cow::from(acc) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn is_star(&self) -> bool { | ||||||
|  |         match &self.last { | ||||||
|  |             UseStatementLast::Star => true, | ||||||
|  |             _ => false, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub enum UseStatementLast { | ||||||
|  |     Identifier(Rc<RefCell<Identifier>>), | ||||||
|  |     Identifiers(Vec<Rc<RefCell<Identifier>>>), | ||||||
|  |     Star, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Declarations allowed in each level */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum ModuleLevelDeclaration { | pub enum ModuleLevelDeclaration { | ||||||
| @ -334,7 +392,7 @@ pub enum ClassLevelDeclaration { | |||||||
|     Field(FieldDeclaration), |     Field(FieldDeclaration), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Declarations
 | /* Main Declarations */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct ModuleDeclaration { | pub struct ModuleDeclaration { | ||||||
| @ -362,7 +420,7 @@ pub struct ClassDeclaration { | |||||||
|     pub declarations: Vec<ClassLevelDeclaration>, |     pub declarations: Vec<ClassLevelDeclaration>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Function declarations and components
 | /* Function declarations and components */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct FunctionDefinition { | pub struct FunctionDefinition { | ||||||
| @ -432,7 +490,7 @@ pub enum FunctionBody { | |||||||
|     Alias(Identifier), |     Alias(Identifier), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Class components
 | /* Class components */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct ClassConstructor(pub Vec<ClassConstructorParameter>); | pub struct ClassConstructor(pub Vec<ClassConstructorParameter>); | ||||||
| @ -457,92 +515,7 @@ pub struct FieldDeclaration { | |||||||
|     pub declared_type: TypeUse, |     pub declared_type: TypeUse, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Statements
 | /* Statements */ | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct UseStatement { |  | ||||||
|     pub identifiers: Vec<Identifier>, |  | ||||||
|     pub last: UseStatementLast, |  | ||||||
|     pub file_id: usize, |  | ||||||
|     pub range: Range<usize>, |  | ||||||
|     scope_id: Option<usize>, |  | ||||||
|     symbol: Option<Symbol>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct UseStatementImport<'a> { |  | ||||||
|     pub declared_name: String, |  | ||||||
|     pub fqn: String, |  | ||||||
|     pub identifier: &'a mut Identifier, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl UseStatement { |  | ||||||
|     pub fn new( |  | ||||||
|         identifiers: Vec<Identifier>, |  | ||||||
|         last: UseStatementLast, |  | ||||||
|         file_id: usize, |  | ||||||
|         range: Range<usize>, |  | ||||||
|     ) -> Self { |  | ||||||
|         UseStatement { |  | ||||||
|             identifiers, |  | ||||||
|             last, |  | ||||||
|             file_id, |  | ||||||
|             range, |  | ||||||
|             scope_id: None, |  | ||||||
|             symbol: None, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn base_name(&self) -> Cow<'_, str> { |  | ||||||
|         use UseStatementLast::*; |  | ||||||
|         if self.identifiers.is_empty() { |  | ||||||
|             match &self.last { |  | ||||||
|                 Identifier(_) => Cow::from(""), |  | ||||||
|                 Star | Identifiers(_) => panic!(), // should never get here because of grammar
 |  | ||||||
|             } |  | ||||||
|         } else if self.identifiers.len() == 1 { |  | ||||||
|             self.identifiers[0].name() |  | ||||||
|         } else { |  | ||||||
|             let mut acc = String::new(); |  | ||||||
|             for (i, identifier) in self.identifiers.iter().enumerate() { |  | ||||||
|                 acc.push_str(&identifier.name()); |  | ||||||
|                 if i != self.identifiers.len() - 1 { |  | ||||||
|                     acc.push_str("::"); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             Cow::from(acc) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn is_star(&self) -> bool { |  | ||||||
|         match &self.last { |  | ||||||
|             UseStatementLast::Star => true, |  | ||||||
|             _ => false, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn set_scope_id(&mut self, scope_id: usize) { |  | ||||||
|         self.scope_id = Some(scope_id); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn scope_id(&self) -> Option<usize> { |  | ||||||
|         self.scope_id |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn set_symbol(&mut self, symbol: Symbol) { |  | ||||||
|         self.symbol = Some(symbol); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn symbol(&self) -> &Option<Symbol> { |  | ||||||
|         &self.symbol |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub enum UseStatementLast { |  | ||||||
|     Identifier(Rc<RefCell<Identifier>>), |  | ||||||
|     Identifiers(Vec<Rc<RefCell<Identifier>>>), |  | ||||||
|     Star, |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct BlockStatement { | pub struct BlockStatement { | ||||||
| @ -615,7 +588,7 @@ pub struct ForStatement { | |||||||
|     pub body: BlockStatement, |     pub body: BlockStatement, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Expressions
 | /* Expressions */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum Expression { | pub enum Expression { | ||||||
|  | |||||||
| @ -1,14 +1,49 @@ | |||||||
| use crate::ast::{FullyQualifiedName, Identifier}; | use crate::ast::{FullyQualifiedName, Identifier}; | ||||||
|  | use crate::name_analysis::symbol::Symbol; | ||||||
| use std::borrow::Cow; | use std::borrow::Cow; | ||||||
|  | use std::range::Range; | ||||||
| 
 | 
 | ||||||
| pub trait Named { | pub trait Named { | ||||||
|     fn name(&self) -> Cow<'_, str>; |     fn name(&self) -> Cow<'_, str>; | ||||||
|  |     
 | ||||||
|  |     fn file_id(&self) -> usize; | ||||||
|  |     fn range(&self) -> Range<usize>; | ||||||
|  | 
 | ||||||
|  |     fn set_scope_id(&mut self, scope_id: usize); | ||||||
|  |     fn scope_id(&self) -> Option<usize>; | ||||||
|  | 
 | ||||||
|  |     fn set_saved_symbol(&mut self, symbol: Symbol); | ||||||
|  |     fn saved_symbol(&self) -> Option<Symbol>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Named for Identifier { | impl Named for Identifier { | ||||||
|     fn name(&self) -> Cow<'_, str> { |     fn name(&self) -> Cow<'_, str> { | ||||||
|         Cow::Borrowed(&self.name) |         Cow::Borrowed(&self.name) | ||||||
|     } |     } | ||||||
|  |     
 | ||||||
|  |     fn file_id(&self) -> usize { | ||||||
|  |         self.file_id | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     fn range(&self) -> Range<usize> { | ||||||
|  |         self.range | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_scope_id(&mut self, id: usize) { | ||||||
|  |         self.scope_id = Some(id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn scope_id(&self) -> Option<usize> { | ||||||
|  |         self.scope_id | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_saved_symbol(&mut self, saved_symbol: Symbol) { | ||||||
|  |         self.saved_symbol = Some(saved_symbol); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn saved_symbol(&self) -> Option<Symbol> { | ||||||
|  |         self.saved_symbol.clone() | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Named for FullyQualifiedName { | impl Named for FullyQualifiedName { | ||||||
| @ -26,4 +61,28 @@ impl Named for FullyQualifiedName { | |||||||
|             Cow::Owned(acc) |             Cow::Owned(acc) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     
 | ||||||
|  |     fn file_id(&self) -> usize { | ||||||
|  |         self.file_id | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     fn range(&self) -> Range<usize> { | ||||||
|  |         self.range | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_scope_id(&mut self, id: usize) { | ||||||
|  |         self.scope_id = Some(id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn scope_id(&self) -> Option<usize> { | ||||||
|  |         self.scope_id | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_saved_symbol(&mut self, symbol: Symbol) { | ||||||
|  |         self.saved_symbol = Some(symbol); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn saved_symbol(&self) -> Option<Symbol> { | ||||||
|  |         self.saved_symbol.clone() | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ use deimos::name_analysis::symbol_table::SymbolTable; | |||||||
| use deimos::parser::{DeimosParser, Rule}; | use deimos::parser::{DeimosParser, Rule}; | ||||||
| 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![]; | ||||||
| @ -29,6 +30,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."); | ||||||
|     
 |     
 | ||||||
|     let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table); |     let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table); | ||||||
|     if diagnostics.is_empty() { |     if diagnostics.is_empty() { | ||||||
|  | |||||||
| @ -6,6 +6,6 @@ pub mod module; | |||||||
| pub mod name_analysis; | pub mod name_analysis; | ||||||
| pub mod object_file; | pub mod object_file; | ||||||
| pub mod parser; | pub mod parser; | ||||||
| mod std_core; | pub mod std_core; | ||||||
| pub mod util; | pub mod util; | ||||||
| pub mod vm; | pub mod vm; | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ use crate::name_analysis::symbol::*; | |||||||
| use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | ||||||
| use codespan_reporting::diagnostic::{Diagnostic, Label}; | use codespan_reporting::diagnostic::{Diagnostic, Label}; | ||||||
| use std::cell::RefCell; | use std::cell::RefCell; | ||||||
|  | use std::ops::DerefMut; | ||||||
| use std::range::Range; | use std::range::Range; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| @ -41,13 +42,21 @@ fn handle_insert_error( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Names */ | ||||||
|  | 
 | ||||||
|  | fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) { | ||||||
|  |     identifier.set_scope_id(symbol_table.current_scope_id()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn gather_fully_qualified_name( | fn gather_fully_qualified_name( | ||||||
|     fully_qualified_name: &mut FullyQualifiedName, |     fully_qualified_name: &mut FullyQualifiedName, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| ) { | ) { | ||||||
|     fully_qualified_name.set_scope_id(symbol_table.current_scope_id()); |     gather_identifier(fully_qualified_name.last_mut(), symbol_table); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Type Use */ | ||||||
|  | 
 | ||||||
| fn gather_type_use( | fn gather_type_use( | ||||||
|     type_use: &mut TypeUse, |     type_use: &mut TypeUse, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -55,7 +64,9 @@ fn gather_type_use( | |||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     match type_use { |     match type_use { | ||||||
|         TypeUse::Void => {} |         TypeUse::Primitive(primitive_type_use) => { | ||||||
|  |             gather_primitive_type_use(primitive_type_use, symbol_table, fqn_context, diagnostics) | ||||||
|  |         } | ||||||
|         TypeUse::InterfaceOrClass(interface_or_class_type_use) => { |         TypeUse::InterfaceOrClass(interface_or_class_type_use) => { | ||||||
|             gather_interface_or_class_type_use( |             gather_interface_or_class_type_use( | ||||||
|                 interface_or_class_type_use, |                 interface_or_class_type_use, | ||||||
| @ -73,6 +84,22 @@ fn gather_type_use( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn gather_primitive_type_use( | ||||||
|  |     primitive_type_use: &mut PrimitiveTypeUse, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     match primitive_type_use { | ||||||
|  |         PrimitiveTypeUse::Array(generic_arguments_opt) => { | ||||||
|  |             if let Some(generic_arguments) = generic_arguments_opt { | ||||||
|  |                 gather_generic_arguments(generic_arguments, symbol_table, fqn_context, diagnostics); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         _ => {} | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn gather_interface_or_class_type_use( | fn gather_interface_or_class_type_use( | ||||||
|     interface_or_class_type_use: &mut InterfaceOrClassTypeUse, |     interface_or_class_type_use: &mut InterfaceOrClassTypeUse, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -105,9 +132,28 @@ fn gather_function_type_use( | |||||||
|     fqn_context: &mut FqnContext, |     fqn_context: &mut FqnContext, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     todo!() |     gather_generic_parameters( | ||||||
|  |         &mut function_type_use.generics, | ||||||
|  |         symbol_table, | ||||||
|  |         fqn_context, | ||||||
|  |         diagnostics, | ||||||
|  |     ); | ||||||
|  |     gather_parameters( | ||||||
|  |         &mut function_type_use.parameters, | ||||||
|  |         symbol_table, | ||||||
|  |         fqn_context, | ||||||
|  |         diagnostics, | ||||||
|  |     ); | ||||||
|  |     gather_return_type( | ||||||
|  |         &mut function_type_use.return_type, | ||||||
|  |         symbol_table, | ||||||
|  |         fqn_context, | ||||||
|  |         diagnostics, | ||||||
|  |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Generic Arguments */ | ||||||
|  | 
 | ||||||
| fn gather_generic_arguments( | fn gather_generic_arguments( | ||||||
|     generic_arguments: &mut GenericArguments, |     generic_arguments: &mut GenericArguments, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -119,6 +165,123 @@ fn gather_generic_arguments( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Generic Parameters */ | ||||||
|  | 
 | ||||||
|  | fn gather_generic_parameters( | ||||||
|  |     generic_parameters: &mut GenericParameters, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!("Add each Identifier as a type to the current scope; make sure caller's push/pop before/after") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Implements List */ | ||||||
|  | 
 | ||||||
|  | fn gather_implements_list( | ||||||
|  |     implements_list: &mut ImplementsList, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     for type_use in &mut implements_list.0 { | ||||||
|  |         gather_type_use(type_use, symbol_table, fqn_context, diagnostics); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Function Parameters */ | ||||||
|  | 
 | ||||||
|  | fn gather_parameters( | ||||||
|  |     parameters: &mut Parameters, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) -> Option<Vec<Rc<ParameterSymbol>>> { | ||||||
|  |     parameters | ||||||
|  |         .0 | ||||||
|  |         .iter_mut() | ||||||
|  |         .map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics)) | ||||||
|  |         .collect() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_parameter( | ||||||
|  |     parameter: &mut Parameter, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) -> Option<Rc<ParameterSymbol>> { | ||||||
|  |     let parameter_name = parameter.identifier.name(); | ||||||
|  | 
 | ||||||
|  |     let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( | ||||||
|  |         ¶meter_name, | ||||||
|  |         Some(¶meter.identifier), | ||||||
|  |     )); | ||||||
|  | 
 | ||||||
|  |     match insert_result { | ||||||
|  |         Ok(parameter_symbol) => { | ||||||
|  |             parameter | ||||||
|  |                 .identifier | ||||||
|  |                 .set_scope_id(symbol_table.current_scope_id()); | ||||||
|  | 
 | ||||||
|  |             gather_type_use( | ||||||
|  |                 &mut parameter.type_use, | ||||||
|  |                 symbol_table, | ||||||
|  |                 fqn_context, | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  |             Some(parameter_symbol) | ||||||
|  |         } | ||||||
|  |         Err(err) => { | ||||||
|  |             handle_insert_error( | ||||||
|  |                 err, | ||||||
|  |                 ¶meter_name, | ||||||
|  |                 parameter.identifier.file_id(), | ||||||
|  |                 parameter.identifier.range(), | ||||||
|  |                 "function/variable", | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  |             None | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Return Type */ | ||||||
|  | 
 | ||||||
|  | fn gather_return_type( | ||||||
|  |     return_type: &mut ReturnType, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     gather_type_use( | ||||||
|  |         &mut return_type.declared_type, | ||||||
|  |         symbol_table, | ||||||
|  |         fqn_context, | ||||||
|  |         diagnostics, | ||||||
|  |     ); | ||||||
|  |     gather_references( | ||||||
|  |         &mut return_type.references, | ||||||
|  |         symbol_table, | ||||||
|  |         fqn_context, | ||||||
|  |         diagnostics, | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* References */ | ||||||
|  | 
 | ||||||
|  | fn gather_references( | ||||||
|  |     references: &mut References, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     for identifier in &mut references.0 { | ||||||
|  |         gather_identifier(identifier, symbol_table); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Compilation Unit/Top-level construct */ | ||||||
|  | 
 | ||||||
| pub(super) fn gather_compilation_unit( | pub(super) fn gather_compilation_unit( | ||||||
|     compilation_unit: &mut CompilationUnit, |     compilation_unit: &mut CompilationUnit, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -140,6 +303,8 @@ pub(super) fn gather_compilation_unit( | |||||||
|     assert_eq!(symbol_table.current_scope_id(), 0); |     assert_eq!(symbol_table.current_scope_id(), 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Use Statement */ | ||||||
|  | 
 | ||||||
| fn handle_use_statement_import( | fn handle_use_statement_import( | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     base_name: &str, |     base_name: &str, | ||||||
| @ -153,28 +318,29 @@ fn handle_use_statement_import( | |||||||
|         &declared_name, |         &declared_name, | ||||||
|         Some(identifier.clone()), |         Some(identifier.clone()), | ||||||
|     )); |     )); | ||||||
|     if let Err(err) = insert_result { | 
 | ||||||
|         handle_insert_error( |     match insert_result { | ||||||
|             err, |         Ok(use_statement_symbol) => { | ||||||
|             &declared_name, |             drop(borrowed_identifier); | ||||||
|             borrowed_identifier.file_id, | 
 | ||||||
|             borrowed_identifier.range, |             let mut mutable_borrowed_identifier = identifier.borrow_mut(); | ||||||
|             "Use statement", | 
 | ||||||
|             diagnostics, |             gather_identifier(mutable_borrowed_identifier.deref_mut(), symbol_table); | ||||||
|         ); | 
 | ||||||
|  |             mutable_borrowed_identifier | ||||||
|  |                 .set_saved_symbol(Symbol::UseStatement(use_statement_symbol)); | ||||||
|  |         } | ||||||
|  |         Err(err) => { | ||||||
|  |             handle_insert_error( | ||||||
|  |                 err, | ||||||
|  |                 &declared_name, | ||||||
|  |                 borrowed_identifier.file_id(), | ||||||
|  |                 borrowed_identifier.range(), | ||||||
|  |                 "Use statement", | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     drop(borrowed_identifier); |  | ||||||
|     let mut mutable_borrowed_identifier = identifier.borrow_mut(); |  | ||||||
|     mutable_borrowed_identifier.set_scope_id(symbol_table.current_scope_id()); |  | ||||||
| 
 |  | ||||||
|     let use_statement_symbol = symbol_table |  | ||||||
|         .lookup( |  | ||||||
|             &declared_name, |  | ||||||
|             mutable_borrowed_identifier.scope_id().unwrap(), |  | ||||||
|         ) |  | ||||||
|         .unwrap(); |  | ||||||
| 
 |  | ||||||
|     mutable_borrowed_identifier.set_symbol(use_statement_symbol); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_use_statement( | fn gather_use_statement( | ||||||
| @ -205,6 +371,8 @@ fn gather_use_statement( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Declarations allowed in each level */ | ||||||
|  | 
 | ||||||
| fn gather_module_level_declaration( | fn gather_module_level_declaration( | ||||||
|     declaration: &mut ModuleLevelDeclaration, |     declaration: &mut ModuleLevelDeclaration, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -234,6 +402,26 @@ fn gather_module_level_declaration( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn gather_interface_level_declaration( | ||||||
|  |     declaration: &mut InterfaceLevelDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_class_level_declaration( | ||||||
|  |     declaration: &mut ClassLevelDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Main Declarations */ | ||||||
|  | 
 | ||||||
| fn gather_module_declaration( | fn gather_module_declaration( | ||||||
|     declaration: &mut ModuleDeclaration, |     declaration: &mut ModuleDeclaration, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -259,8 +447,8 @@ fn gather_module_declaration( | |||||||
|         handle_insert_error( |         handle_insert_error( | ||||||
|             err, |             err, | ||||||
|             &module_name, |             &module_name, | ||||||
|             declaration.identifier.file_id, |             declaration.identifier.file_id(), | ||||||
|             declaration.identifier.range, |             declaration.identifier.range(), | ||||||
|             "module/type", |             "module/type", | ||||||
|             diagnostics, |             diagnostics, | ||||||
|         ) |         ) | ||||||
| @ -294,8 +482,8 @@ fn gather_class_declaration( | |||||||
|         handle_insert_error( |         handle_insert_error( | ||||||
|             err, |             err, | ||||||
|             &declared_name, |             &declared_name, | ||||||
|             class_declaration.identifier.file_id, |             class_declaration.identifier.file_id(), | ||||||
|             class_declaration.identifier.range, |             class_declaration.identifier.range(), | ||||||
|             "interface/class", |             "interface/class", | ||||||
|             diagnostics, |             diagnostics, | ||||||
|         ); |         ); | ||||||
| @ -304,6 +492,8 @@ fn gather_class_declaration( | |||||||
|     // todo: scopes, generics, etc.
 |     // todo: scopes, generics, etc.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Function declarations and components */ | ||||||
|  | 
 | ||||||
| fn gather_function_definition( | fn gather_function_definition( | ||||||
|     function: &mut FunctionDefinition, |     function: &mut FunctionDefinition, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -321,30 +511,64 @@ fn gather_function_definition( | |||||||
|         Some(&function.identifier), |         Some(&function.identifier), | ||||||
|     )); |     )); | ||||||
| 
 | 
 | ||||||
|     if let Err(err) = insert_result { |     match insert_result { | ||||||
|         handle_insert_error( |         Ok(function_symbol) => { | ||||||
|             err, |             function | ||||||
|             &declared_name, |                 .identifier | ||||||
|             function.identifier.file_id, |                 .set_scope_id(symbol_table.current_scope_id()); | ||||||
|             function.identifier.range, | 
 | ||||||
|             "function/variable", |             symbol_table.push_scope(&format!("FunctionParameterScope({})", resolved_name)); | ||||||
|             diagnostics, | 
 | ||||||
|         ) |             let parameters_result = gather_parameters( | ||||||
|  |                 &mut function.parameters, | ||||||
|  |                 symbol_table, | ||||||
|  |                 fqn_context, | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             match parameters_result { | ||||||
|  |                 Some(parameter_symbols) => { | ||||||
|  |                     function_symbol | ||||||
|  |                         .borrow_mut() | ||||||
|  |                         .set_parameters(parameter_symbols); | ||||||
|  |                 } | ||||||
|  |                 None => {} | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             gather_return_type( | ||||||
|  |                 &mut function.return_type, | ||||||
|  |                 symbol_table, | ||||||
|  |                 fqn_context, | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             symbol_table.push_scope(&format!("FunctionBodyScope({})", resolved_name)); | ||||||
|  | 
 | ||||||
|  |             gather_function_body(&mut function.body, symbol_table, fqn_context, diagnostics); | ||||||
|  | 
 | ||||||
|  |             symbol_table.pop_scope(); // body
 | ||||||
|  |             symbol_table.pop_scope(); // parameters
 | ||||||
|  |         } | ||||||
|  |         Err(err) => { | ||||||
|  |             handle_insert_error( | ||||||
|  |                 err, | ||||||
|  |                 &declared_name, | ||||||
|  |                 function.identifier.file_id(), | ||||||
|  |                 function.identifier.range(), | ||||||
|  |                 "function/variable", | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     function | fn gather_operator_function_definition( | ||||||
|         .identifier |     operator_function_definition: &mut OperatorFunctionDefinition, | ||||||
|         .set_scope_id(symbol_table.current_scope_id()); |     symbol_table: &mut SymbolTable, | ||||||
| 
 |     fqn_context: &mut FqnContext, | ||||||
|     symbol_table.push_scope(&format!("FunctionScope({})", resolved_name)); |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|     gather_parameters( | ) { | ||||||
|         &mut function.parameters, |     todo!() | ||||||
|         symbol_table, |  | ||||||
|         fqn_context, |  | ||||||
|         diagnostics, |  | ||||||
|     ); |  | ||||||
|     gather_function_body(&mut function.body, symbol_table, fqn_context, diagnostics); |  | ||||||
|     symbol_table.pop_scope(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_platform_function_definition( | fn gather_platform_function_definition( | ||||||
| @ -364,78 +588,74 @@ fn gather_platform_function_definition( | |||||||
|         Some(&platform_function_declaration.identifier), |         Some(&platform_function_declaration.identifier), | ||||||
|     )); |     )); | ||||||
| 
 | 
 | ||||||
|     if let Err(err) = insert_result { |     match insert_result { | ||||||
|         handle_insert_error( |         Ok(function_symbol) => { | ||||||
|             err, |             let declared_name_as_string = | ||||||
|             &declared_name, |                 platform_function_declaration.identifier.name().to_string(); | ||||||
|             platform_function_declaration.identifier.file_id, | 
 | ||||||
|             platform_function_declaration.identifier.range, |             platform_function_declaration | ||||||
|             "(Platform-) Function", |                 .identifier | ||||||
|             diagnostics, |                 .set_scope_id(symbol_table.current_scope_id()); | ||||||
|         ); | 
 | ||||||
|  |             symbol_table.push_scope(&format!( | ||||||
|  |                 "FunctionParameterScope({})", | ||||||
|  |                 declared_name_as_string | ||||||
|  |             )); | ||||||
|  | 
 | ||||||
|  |             let parameter_symbols_result = gather_parameters( | ||||||
|  |                 &mut platform_function_declaration.parameters, | ||||||
|  |                 symbol_table, | ||||||
|  |                 fqn_context, | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             match parameter_symbols_result { | ||||||
|  |                 Some(parameter_symbols) => { | ||||||
|  |                     function_symbol | ||||||
|  |                         .borrow_mut() | ||||||
|  |                         .set_parameters(parameter_symbols); | ||||||
|  |                 } | ||||||
|  |                 None => {} | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             gather_return_type( | ||||||
|  |                 &mut platform_function_declaration.return_type, | ||||||
|  |                 symbol_table, | ||||||
|  |                 fqn_context, | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             symbol_table.pop_scope(); | ||||||
|  |         } | ||||||
|  |         Err(err) => { | ||||||
|  |             handle_insert_error( | ||||||
|  |                 err, | ||||||
|  |                 &declared_name, | ||||||
|  |                 platform_function_declaration.identifier.file_id(), | ||||||
|  |                 platform_function_declaration.identifier.range(), | ||||||
|  |                 "(Platform-) Function", | ||||||
|  |                 diagnostics, | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     let declared_name_as_string = platform_function_declaration.identifier.name().to_string(); |  | ||||||
| 
 |  | ||||||
|     platform_function_declaration |  | ||||||
|         .identifier |  | ||||||
|         .set_scope_id(symbol_table.current_scope_id()); |  | ||||||
| 
 |  | ||||||
|     symbol_table.push_scope(&format!("FunctionScope({})", declared_name_as_string)); |  | ||||||
|     gather_parameters( |  | ||||||
|         &mut platform_function_declaration.parameters, |  | ||||||
|         symbol_table, |  | ||||||
|         fqn_context, |  | ||||||
|         diagnostics, |  | ||||||
|     ); |  | ||||||
|     symbol_table.pop_scope(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_parameters( | fn gather_interface_function_declaration( | ||||||
|     parameters: &mut Parameters, |     declaration: &mut InterfaceFunctionDeclaration, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     fqn_context: &mut FqnContext, |     fqn_context: &mut FqnContext, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     for parameter in &mut parameters.0 { |     todo!() | ||||||
|         gather_parameter(parameter, symbol_table, fqn_context, diagnostics); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_parameter( | fn gather_interface_operator_function_declaration( | ||||||
|     parameter: &mut Parameter, |     declaration: &mut InterfaceOperatorFunctionDeclaration, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     fqn_context: &mut FqnContext, |     fqn_context: &mut FqnContext, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     let parameter_name = parameter.identifier.name(); |     todo!() | ||||||
| 
 |  | ||||||
|     let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( |  | ||||||
|         ¶meter_name, |  | ||||||
|         Some(¶meter.identifier), |  | ||||||
|     )); |  | ||||||
| 
 |  | ||||||
|     if let Err(err) = insert_result { |  | ||||||
|         handle_insert_error( |  | ||||||
|             err, |  | ||||||
|             ¶meter_name, |  | ||||||
|             parameter.identifier.file_id, |  | ||||||
|             parameter.identifier.range, |  | ||||||
|             "function/variable", |  | ||||||
|             diagnostics, |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     parameter |  | ||||||
|         .identifier |  | ||||||
|         .set_scope_id(symbol_table.current_scope_id()); |  | ||||||
| 
 |  | ||||||
|     gather_type_use( |  | ||||||
|         &mut parameter.type_use, |  | ||||||
|         symbol_table, |  | ||||||
|         fqn_context, |  | ||||||
|         diagnostics, |  | ||||||
|     ) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn gather_function_body( | fn gather_function_body( | ||||||
| @ -451,6 +671,37 @@ fn gather_function_body( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Class Components */ | ||||||
|  | 
 | ||||||
|  | fn gather_class_constructor( | ||||||
|  |     class_constructor: &mut ClassConstructor, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_property_declaration( | ||||||
|  |     property_declaration: &mut PropertyDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_field_declaration( | ||||||
|  |     field_declaration: &mut FieldDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Statements */ | ||||||
|  | 
 | ||||||
| fn gather_block_statement( | fn gather_block_statement( | ||||||
|     block: &mut BlockStatement, |     block: &mut BlockStatement, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -517,8 +768,8 @@ fn gather_variable_declaration( | |||||||
|         handle_insert_error( |         handle_insert_error( | ||||||
|             err, |             err, | ||||||
|             &variable_name, |             &variable_name, | ||||||
|             variable_declaration.identifier.file_id, |             variable_declaration.identifier.file_id(), | ||||||
|             variable_declaration.identifier.range, |             variable_declaration.identifier.range(), | ||||||
|             "function/variable", |             "function/variable", | ||||||
|             diagnostics, |             diagnostics, | ||||||
|         ) |         ) | ||||||
| @ -551,6 +802,55 @@ fn gather_call_statement( | |||||||
|     gather_expression(&mut call_statement.0, symbol_table, diagnostics); |     gather_expression(&mut call_statement.0, symbol_table, diagnostics); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn gather_return_statement( | ||||||
|  |     return_statement: &mut ReturnStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     if let Some(expression) = &mut return_statement.0 { | ||||||
|  |         gather_expression(expression, symbol_table, diagnostics); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_if_statement( | ||||||
|  |     if_statement: &mut IfStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_if_else_statement( | ||||||
|  |     if_else_statement: &mut IfElseStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_while_statement( | ||||||
|  |     while_statement: &mut WhileStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn gather_for_statement( | ||||||
|  |     for_statement: &mut ForStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     fqn_context: &mut FqnContext, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Expressions */ | ||||||
|  | 
 | ||||||
| fn gather_expression( | fn gather_expression( | ||||||
|     expression: &mut Expression, |     expression: &mut Expression, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -673,7 +973,8 @@ fn gather_object_access( | |||||||
|                 gather_expression(index_expression, symbol_table, diagnostics); |                 gather_expression(index_expression, symbol_table, diagnostics); | ||||||
|             } |             } | ||||||
|             ObjectNavigation::Identifier(identifier) => { |             ObjectNavigation::Identifier(identifier) => { | ||||||
|                 identifier.set_scope_id(symbol_table.current_scope_id()); |                 // TODO: use a special gather for names belonging to a struct
 | ||||||
|  |                 gather_identifier(identifier, symbol_table); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -685,8 +986,18 @@ fn gather_literal( | |||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     match literal { |     match literal { | ||||||
|         Literal::DString(d_string) => todo!(), |         Literal::DString(d_string) => gather_d_string(d_string, symbol_table, diagnostics), | ||||||
|         Literal::BacktickString(backtick_string) => todo!(), |         Literal::BacktickString(backtick_string) => { | ||||||
|  |             gather_d_string(backtick_string, symbol_table, diagnostics) | ||||||
|  |         } | ||||||
|         _ => {} |         _ => {} | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn gather_d_string( | ||||||
|  |     d_string: &mut DString, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,3 +1,24 @@ | |||||||
|  | /*! | ||||||
|  | # Name Analysis | ||||||
|  | 
 | ||||||
|  | There are two phases in name analysis. | ||||||
|  | 
 | ||||||
|  | ## 1. Gather | ||||||
|  | 
 | ||||||
|  | The gather phases has three responsibilities: | ||||||
|  | 
 | ||||||
|  | 1. Add all declared symbols to the symbol table. | ||||||
|  | 2. Set the `scope_id` property of all identifiers and fully-qualified-names. | ||||||
|  | 3. For the main identifiers of `UseStatement`s (i.e., the last identifier in the `UseStatement`): | ||||||
|  |    set a 'linking' symbol on the identifier, which will later be filled in with the linked-to | ||||||
|  |    symbol (probably in another file, or from the standard library). | ||||||
|  | 
 | ||||||
|  | ## 2. Resolve | ||||||
|  | 
 | ||||||
|  | The resolve phase has one main responsibility: resolve all references based on the identifier's | ||||||
|  | `scope_id` property. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
| use crate::ast::named::Named; | use crate::ast::named::Named; | ||||||
| use crate::ast::CompilationUnit; | use crate::ast::CompilationUnit; | ||||||
| use crate::diagnostic::DmDiagnostic; | use crate::diagnostic::DmDiagnostic; | ||||||
| @ -43,7 +64,11 @@ mod tests { | |||||||
|     use pest::Parser; |     use pest::Parser; | ||||||
|     use std::collections::HashMap; |     use std::collections::HashMap; | ||||||
| 
 | 
 | ||||||
|     fn assert_no_diagnostics(sources: HashMap<&str, &str>) -> SymbolTable { |     fn assert_number_of_diagnostics( | ||||||
|  |         sources: HashMap<&str, &str>, | ||||||
|  |         symbol_table: &mut SymbolTable, | ||||||
|  |         n_diagnostics: usize, | ||||||
|  |     ) { | ||||||
|         let mut files = SimpleFiles::new(); |         let mut files = SimpleFiles::new(); | ||||||
|         let mut compilation_units = vec![]; |         let mut compilation_units = vec![]; | ||||||
| 
 | 
 | ||||||
| @ -61,10 +86,7 @@ mod tests { | |||||||
|             compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap())) |             compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap())) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let mut symbol_table = SymbolTable::new(); |         let diagnostics = analyze_names(&mut compilation_units, symbol_table); | ||||||
|         add_std_core_symbols(&mut symbol_table).expect("Failed to add std_core_symbols"); |  | ||||||
| 
 |  | ||||||
|         let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table); |  | ||||||
| 
 | 
 | ||||||
|         if !diagnostics.is_empty() { |         if !diagnostics.is_empty() { | ||||||
|             let writer = StandardStream::stderr(ColorChoice::Always); |             let writer = StandardStream::stderr(ColorChoice::Always); | ||||||
| @ -75,14 +97,17 @@ mod tests { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             eprintln!("{}", symbol_table); |             eprintln!("{}", symbol_table); | ||||||
|             panic!("Diagnostics was not empty!"); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         assert_eq!(n_diagnostics, diagnostics.len()); | ||||||
|  | 
 | ||||||
|         for compilation_unit in &compilation_units { |         for compilation_unit in &compilation_units { | ||||||
|             dbg!(compilation_unit); |             dbg!(compilation_unit); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         symbol_table |     fn assert_no_diagnostics(sources: HashMap<&str, &str>, symbol_table: &mut SymbolTable) { | ||||||
|  |         assert_number_of_diagnostics(sources, symbol_table, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -95,7 +120,7 @@ mod tests { | |||||||
|             }"},
 |             }"},
 | ||||||
|         )]); |         )]); | ||||||
| 
 | 
 | ||||||
|         assert_no_diagnostics(sources); |         assert_no_diagnostics(sources, &mut SymbolTable::new()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -105,10 +130,6 @@ mod tests { | |||||||
|                 "main.dm", |                 "main.dm", | ||||||
|                 indoc! {" |                 indoc! {" | ||||||
|                 use test::Greeter; |                 use test::Greeter; | ||||||
| 
 |  | ||||||
|                 fn main(args: Array<String>) { |  | ||||||
|                     println(\"Hello, World!\");
 |  | ||||||
|                 } |  | ||||||
|             "},
 |             "},
 | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
| @ -121,6 +142,81 @@ mod tests { | |||||||
|             ), |             ), | ||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         assert_no_diagnostics(sources); |         assert_no_diagnostics(sources, &mut SymbolTable::new()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn sees_std_core_println() { | ||||||
|  |         let sources: HashMap<&str, &str> = HashMap::from([( | ||||||
|  |             "main.dm", | ||||||
|  |             indoc! {" | ||||||
|  |                 fn main(args: Array<String>) { | ||||||
|  |                     println(args) | ||||||
|  |                 } | ||||||
|  |             "},
 | ||||||
|  |         )]); | ||||||
|  | 
 | ||||||
|  |         let mut symbol_table = SymbolTable::new(); | ||||||
|  |         add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); | ||||||
|  |         assert_no_diagnostics(sources, &mut symbol_table); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn sees_duplicate_fn() { | ||||||
|  |         let sources: HashMap<&str, &str> = HashMap::from([( | ||||||
|  |             "main.dm", | ||||||
|  |             indoc! {" | ||||||
|  |                 fn main(args: Array<String>) {} | ||||||
|  |                 fn main(args: Array<String>) {} | ||||||
|  |             "},
 | ||||||
|  |         )]); | ||||||
|  |         assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_class_from_other_file() { | ||||||
|  |         let sources: HashMap<&str, &str> = HashMap::from([ | ||||||
|  |             ( | ||||||
|  |                 "main.dm", | ||||||
|  |                 indoc! {" | ||||||
|  |                     use greeter::Greeter; | ||||||
|  | 
 | ||||||
|  |                     fn test(greeter: Greeter) {} | ||||||
|  |                 "},
 | ||||||
|  |             ), | ||||||
|  |             ( | ||||||
|  |                 "greeter.dm", | ||||||
|  |                 indoc! {" | ||||||
|  |                     ns greeter; | ||||||
|  | 
 | ||||||
|  |                     class Greeter {} | ||||||
|  |                 "},
 | ||||||
|  |             ), | ||||||
|  |         ]); | ||||||
|  |         let mut symbol_table = SymbolTable::new(); | ||||||
|  |         assert_no_diagnostics(sources, &mut symbol_table); | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     #[test] | ||||||
|  |     fn shadow_import() { | ||||||
|  |         let sources: HashMap<&str, &str> = HashMap::from([ | ||||||
|  |             ( | ||||||
|  |                 "main.dm", | ||||||
|  |                 indoc! {" | ||||||
|  |                     use greeter::Greeter; | ||||||
|  | 
 | ||||||
|  |                     class Greeter {} | ||||||
|  |                 "}
 | ||||||
|  |             ), | ||||||
|  |             ( | ||||||
|  |                 "greeter.dm", | ||||||
|  |                 indoc! {" | ||||||
|  |                     ns greeter; | ||||||
|  | 
 | ||||||
|  |                     class Greeter {} | ||||||
|  |                 "}
 | ||||||
|  |             ) | ||||||
|  |         ]); | ||||||
|  |         assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,38 +1,14 @@ | |||||||
| use crate::ast::named::Named; | use crate::ast::named::Named; | ||||||
| use crate::ast::*; | use crate::ast::*; | ||||||
| use crate::diagnostic::DmDiagnostic; | use crate::diagnostic::DmDiagnostic; | ||||||
| use crate::name_analysis::symbol_table::SymbolTable; | use crate::name_analysis::symbol::Symbol; | ||||||
|  | use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; | ||||||
| use codespan_reporting::diagnostic::{Diagnostic, Label}; | use codespan_reporting::diagnostic::{Diagnostic, Label}; | ||||||
|  | use std::cell::RefCell; | ||||||
|  | use std::range::Range; | ||||||
|  | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| fn resolve_fully_qualified_name( | /* Type Use */ | ||||||
|     fully_qualified_name: &mut FullyQualifiedName, |  | ||||||
|     symbol_table: &mut SymbolTable, |  | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |  | ||||||
| ) { |  | ||||||
|     let lookup_result = symbol_table.lookup( |  | ||||||
|         fully_qualified_name.name().as_ref(), |  | ||||||
|         fully_qualified_name.scope_id().expect(&format!( |  | ||||||
|             "FullyQualifiedName has no scope_id set: {:?}", |  | ||||||
|             fully_qualified_name |  | ||||||
|         )), |  | ||||||
|     ); |  | ||||||
|     match lookup_result { |  | ||||||
|         Ok(symbol) => { |  | ||||||
|             fully_qualified_name.set_symbol(symbol.clone()); |  | ||||||
|         } |  | ||||||
|         Err(e) => diagnostics.push( |  | ||||||
|             Diagnostic::error() |  | ||||||
|                 .with_message(format!( |  | ||||||
|                     "No symbol with name '{}' found in current scope.", |  | ||||||
|                     fully_qualified_name.name() |  | ||||||
|                 )) |  | ||||||
|                 .with_label(Label::primary( |  | ||||||
|                     fully_qualified_name.file_id, |  | ||||||
|                     fully_qualified_name.range, |  | ||||||
|                 )), |  | ||||||
|         ), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| fn resolve_type_use( | fn resolve_type_use( | ||||||
|     type_use: &mut TypeUse, |     type_use: &mut TypeUse, | ||||||
| @ -40,7 +16,9 @@ fn resolve_type_use( | |||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     match type_use { |     match type_use { | ||||||
|         TypeUse::Void => {} |         TypeUse::Primitive(primitive_type_use) => { | ||||||
|  |             resolve_primitive_type_use(primitive_type_use, symbol_table, diagnostics) | ||||||
|  |         } | ||||||
|         TypeUse::InterfaceOrClass(interface_or_class_type_use) => { |         TypeUse::InterfaceOrClass(interface_or_class_type_use) => { | ||||||
|             resolve_interface_or_class_type_use( |             resolve_interface_or_class_type_use( | ||||||
|                 interface_or_class_type_use, |                 interface_or_class_type_use, | ||||||
| @ -57,16 +35,56 @@ fn resolve_type_use( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn resolve_primitive_type_use( | ||||||
|  |     primitive_type_use: &mut PrimitiveTypeUse, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     match primitive_type_use { | ||||||
|  |         PrimitiveTypeUse::Array(generic_arguments_opt) => { | ||||||
|  |             if let Some(generic_arguments) = generic_arguments_opt { | ||||||
|  |                 resolve_generic_arguments(generic_arguments, symbol_table, diagnostics); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         _ => {} | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn resolve_interface_or_class_type_use( | fn resolve_interface_or_class_type_use( | ||||||
|     interface_or_class_type_use: &mut InterfaceOrClassTypeUse, |     interface_or_class_type_use: &mut InterfaceOrClassTypeUse, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     resolve_fully_qualified_name( |     // 1. handle main name
 | ||||||
|         &mut interface_or_class_type_use.fqn, |     let fqn = &mut interface_or_class_type_use.fqn; | ||||||
|         symbol_table, |     let lookup_result = if fqn.is_single_identifier() { | ||||||
|         diagnostics, |         let identifier = fqn.last(); | ||||||
|     ); |         symbol_table.lookup_type_by_declared_name( | ||||||
|  |             &identifier.name(), | ||||||
|  |             identifier | ||||||
|  |                 .scope_id() | ||||||
|  |                 .expect("Identifier's scope id not set."), | ||||||
|  |         ) | ||||||
|  |     } else { | ||||||
|  |         todo!("Fully-qualified-name type uses sensitive to imports and so on") | ||||||
|  |     }; | ||||||
|  |     match lookup_result { | ||||||
|  |         Ok(type_symbol) => { | ||||||
|  |             fqn.last_mut().set_saved_symbol(Symbol::Type(type_symbol)); | ||||||
|  |         } | ||||||
|  |         Err(_) => { | ||||||
|  |             diagnostics.push( | ||||||
|  |                 Diagnostic::error() | ||||||
|  |                     .with_message(&format!( | ||||||
|  |                         "No type symbol '{}' found in current scope.", | ||||||
|  |                         fqn.name() | ||||||
|  |                     )) | ||||||
|  |                     .with_label(Label::primary(fqn.file_id(), fqn.range())), | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // 2. generics
 | ||||||
|     resolve_generic_arguments( |     resolve_generic_arguments( | ||||||
|         &mut interface_or_class_type_use.generics, |         &mut interface_or_class_type_use.generics, | ||||||
|         symbol_table, |         symbol_table, | ||||||
| @ -95,6 +113,8 @@ fn resolve_function_type_use( | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Generic arguments */ | ||||||
|  | 
 | ||||||
| fn resolve_generic_arguments( | fn resolve_generic_arguments( | ||||||
|     generic_arguments: &mut GenericArguments, |     generic_arguments: &mut GenericArguments, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -105,6 +125,10 @@ fn resolve_generic_arguments( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Generic parameters: todo: no resolution needed? */ | ||||||
|  | 
 | ||||||
|  | /* Tuple arguments */ | ||||||
|  | 
 | ||||||
| fn resolve_tuple_arguments( | fn resolve_tuple_arguments( | ||||||
|     tuple_type_use: &mut TupleArguments, |     tuple_type_use: &mut TupleArguments, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -115,6 +139,8 @@ fn resolve_tuple_arguments( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Implements list */ | ||||||
|  | 
 | ||||||
| fn resolve_implements_list( | fn resolve_implements_list( | ||||||
|     implements_list: &mut ImplementsList, |     implements_list: &mut ImplementsList, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -123,6 +149,8 @@ fn resolve_implements_list( | |||||||
|     todo!() |     todo!() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Function parameters */ | ||||||
|  | 
 | ||||||
| fn resolve_parameters( | fn resolve_parameters( | ||||||
|     parameters: &mut Parameters, |     parameters: &mut Parameters, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -133,6 +161,8 @@ fn resolve_parameters( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Return Type */ | ||||||
|  | 
 | ||||||
| fn resolve_return_type( | fn resolve_return_type( | ||||||
|     return_type: &mut ReturnType, |     return_type: &mut ReturnType, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -142,6 +172,8 @@ fn resolve_return_type( | |||||||
|     resolve_references(&mut return_type.references, symbol_table, diagnostics); |     resolve_references(&mut return_type.references, symbol_table, diagnostics); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* References */ | ||||||
|  | 
 | ||||||
| fn resolve_references( | fn resolve_references( | ||||||
|     references: &mut References, |     references: &mut References, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -152,46 +184,7 @@ fn resolve_references( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn resolve_use_statement( | /* Compilation Unit/Top-level construct */ | ||||||
|     use_statement: &mut UseStatement, |  | ||||||
|     symbol_table: &mut SymbolTable, |  | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |  | ||||||
| ) { |  | ||||||
|     if use_statement.is_star() { |  | ||||||
|         todo!() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let base_name = use_statement.base_name().to_string(); |  | ||||||
| 
 |  | ||||||
|     match &use_statement.last { |  | ||||||
|         UseStatementLast::Identifier(identifier) => { |  | ||||||
|             let borrowed_identifier = identifier.borrow(); |  | ||||||
|             let declared_name = borrowed_identifier.name().to_string(); |  | ||||||
|             let fqn = format!("{}::{}", &base_name, &declared_name); |  | ||||||
|             let lookup_result = |  | ||||||
|                 symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap()); |  | ||||||
|             drop(borrowed_identifier); |  | ||||||
| 
 |  | ||||||
|             if let Err(_) = lookup_result { |  | ||||||
|                 diagnostics.push( |  | ||||||
|                     Diagnostic::error() |  | ||||||
|                         .with_message(&format!("Unable to find symbol '{}'.", fqn)) |  | ||||||
|                         .with_label(Label::primary(use_statement.file_id, use_statement.range)), |  | ||||||
|                 ); |  | ||||||
|             } else { |  | ||||||
|                 let mut mutable_borrowed_identifier = identifier.borrow_mut(); |  | ||||||
|                 let use_statement_symbol = mutable_borrowed_identifier |  | ||||||
|                     .symbol_mut() |  | ||||||
|                     .unwrap() |  | ||||||
|                     .unwrap_use_statement_symbol(); |  | ||||||
|                 let mut mutable_borrowed_use_statement_symbol = use_statement_symbol.borrow_mut(); |  | ||||||
|                 mutable_borrowed_use_statement_symbol.set_referenced_symbol(lookup_result.unwrap()) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         UseStatementLast::Identifiers(identifiers) => {} |  | ||||||
|         UseStatementLast::Star => panic!(), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| pub(super) fn resolve_compilation_unit( | pub(super) fn resolve_compilation_unit( | ||||||
|     compilation_unit: &mut CompilationUnit, |     compilation_unit: &mut CompilationUnit, | ||||||
| @ -206,7 +199,79 @@ pub(super) fn resolve_compilation_unit( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub(super) fn resolve_module_level_declaration( | /* Use Statement */ | ||||||
|  | 
 | ||||||
|  | fn handle_use_statement_identifier( | ||||||
|  |     identifier: Rc<RefCell<Identifier>>, | ||||||
|  |     base_name: &str, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  |     file_id: usize, | ||||||
|  |     error_range: Range<usize>, | ||||||
|  | ) { | ||||||
|  |     let borrowed_identifier = identifier.borrow(); | ||||||
|  |     let declared_name = borrowed_identifier.name().to_string(); | ||||||
|  |     let fqn = format!("{}::{}", base_name, &declared_name); | ||||||
|  |     let lookup_result = | ||||||
|  |         symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap()); | ||||||
|  | 
 | ||||||
|  |     match lookup_result { | ||||||
|  |         Ok(referenced_symbol) => { | ||||||
|  |             let saved_symbol = borrowed_identifier | ||||||
|  |                 .saved_symbol() | ||||||
|  |                 .expect("Identifier's saved_symbol is not set."); | ||||||
|  |             let use_statement_symbol = saved_symbol.unwrap_use_statement_symbol(); | ||||||
|  |             use_statement_symbol | ||||||
|  |                 .borrow_mut() | ||||||
|  |                 .set_referenced_symbol(referenced_symbol); | ||||||
|  |         } | ||||||
|  |         Err(_) => { | ||||||
|  |             diagnostics.push( | ||||||
|  |                 Diagnostic::error() | ||||||
|  |                     .with_message(&format!("Unable to find symbol '{}'.", fqn)) | ||||||
|  |                     .with_label(Label::primary(file_id, error_range)), | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_use_statement( | ||||||
|  |     use_statement: &mut UseStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     let base_name = use_statement.base_name().to_string(); | ||||||
|  | 
 | ||||||
|  |     match &use_statement.last { | ||||||
|  |         UseStatementLast::Identifier(identifier) => { | ||||||
|  |             handle_use_statement_identifier( | ||||||
|  |                 identifier.clone(), | ||||||
|  |                 &base_name, | ||||||
|  |                 symbol_table, | ||||||
|  |                 diagnostics, | ||||||
|  |                 use_statement.file_id, | ||||||
|  |                 use_statement.range, | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |         UseStatementLast::Identifiers(identifiers) => { | ||||||
|  |             for identifier in identifiers { | ||||||
|  |                 handle_use_statement_identifier( | ||||||
|  |                     identifier.clone(), | ||||||
|  |                     &base_name, | ||||||
|  |                     symbol_table, | ||||||
|  |                     diagnostics, | ||||||
|  |                     use_statement.file_id, | ||||||
|  |                     identifier.borrow().range(), | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         UseStatementLast::Star => todo!("star imports"), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Declarations allowed in each level */ | ||||||
|  | 
 | ||||||
|  | fn resolve_module_level_declaration( | ||||||
|     declaration: &mut ModuleLevelDeclaration, |     declaration: &mut ModuleLevelDeclaration, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| @ -228,6 +293,65 @@ pub(super) fn resolve_module_level_declaration( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn resolve_interface_level_declaration( | ||||||
|  |     declaration: &mut InterfaceLevelDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_class_level_declaration( | ||||||
|  |     declaration: &mut ClassLevelDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Main Declarations */ | ||||||
|  | 
 | ||||||
|  | fn resolve_module_declaration( | ||||||
|  |     module_declaration: &mut ModuleDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     for declaration in &mut module_declaration.declarations { | ||||||
|  |         resolve_module_level_declaration(declaration, symbol_table, diagnostics); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_interface_declaration( | ||||||
|  |     interface_declaration: &mut InterfaceDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     resolve_implements_list( | ||||||
|  |         &mut interface_declaration.implements, | ||||||
|  |         symbol_table, | ||||||
|  |         diagnostics, | ||||||
|  |     ); | ||||||
|  |     for declaration in &mut interface_declaration.declarations { | ||||||
|  |         resolve_interface_level_declaration(declaration, symbol_table, diagnostics); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_class_declaration( | ||||||
|  |     class_declaration: &mut ClassDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     if let Some(class_constructor) = &mut class_declaration.class_constructor { | ||||||
|  |         resolve_class_constructor(class_constructor, symbol_table, diagnostics); | ||||||
|  |     } | ||||||
|  |     resolve_implements_list(&mut class_declaration.implements, symbol_table, diagnostics); | ||||||
|  |     for declaration in &mut class_declaration.declarations { | ||||||
|  |         resolve_class_level_declaration(declaration, symbol_table, diagnostics); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Function declarations and components */ | ||||||
|  | 
 | ||||||
| fn resolve_function_definition( | fn resolve_function_definition( | ||||||
|     function_definition: &mut FunctionDefinition, |     function_definition: &mut FunctionDefinition, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -246,6 +370,14 @@ fn resolve_function_definition( | |||||||
|     resolve_function_body(&mut function_definition.body, symbol_table, diagnostics); |     resolve_function_body(&mut function_definition.body, symbol_table, diagnostics); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn resolve_operator_function_definition( | ||||||
|  |     operator_function_definition: &mut OperatorFunctionDefinition, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn resolve_platform_function_declaration( | fn resolve_platform_function_declaration( | ||||||
|     platform_function_declaration: &mut PlatformFunctionDeclaration, |     platform_function_declaration: &mut PlatformFunctionDeclaration, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -263,6 +395,22 @@ fn resolve_platform_function_declaration( | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn resolve_interface_function_declaration( | ||||||
|  |     interface_function_declaration: &mut InterfaceFunctionDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_interface_operator_function_declaration( | ||||||
|  |     interface_operator_function_declaration: &mut InterfaceOperatorFunctionDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn resolve_function_body( | fn resolve_function_body( | ||||||
|     function_body: &mut FunctionBody, |     function_body: &mut FunctionBody, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -270,12 +418,49 @@ fn resolve_function_body( | |||||||
| ) { | ) { | ||||||
|     use crate::ast::FunctionBody::*; |     use crate::ast::FunctionBody::*; | ||||||
|     match function_body { |     match function_body { | ||||||
|         Block(block) => resolve_block(block, symbol_table, diagnostics), |         Equals(expression) => resolve_expression(expression, symbol_table, diagnostics), | ||||||
|         _ => todo!(), |         Block(block) => resolve_block_statement(block, symbol_table, diagnostics), | ||||||
|  |         Alias(identifier) => resolve_function_alias(identifier, symbol_table, diagnostics), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn resolve_block( | fn resolve_function_alias( | ||||||
|  |     identifier: &mut Identifier, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Class components */ | ||||||
|  | 
 | ||||||
|  | fn resolve_class_constructor( | ||||||
|  |     class_constructor: &mut ClassConstructor, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_property_declaration( | ||||||
|  |     property_declaration: &mut PropertyDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_field_declaration( | ||||||
|  |     field_declaration: &mut FieldDeclaration, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Statements */ | ||||||
|  | 
 | ||||||
|  | fn resolve_block_statement( | ||||||
|     block_statement: &mut BlockStatement, |     block_statement: &mut BlockStatement, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| @ -295,7 +480,7 @@ fn resolve_statement( | |||||||
| ) { | ) { | ||||||
|     use crate::ast::Statement::*; |     use crate::ast::Statement::*; | ||||||
|     match statement { |     match statement { | ||||||
|         BlockStatement(block) => resolve_block(block, symbol_table, diagnostics), |         BlockStatement(block) => resolve_block_statement(block, symbol_table, diagnostics), | ||||||
|         VariableDeclarationStatement(variable_declaration) => { |         VariableDeclarationStatement(variable_declaration) => { | ||||||
|             resolve_variable_declaration(variable_declaration, symbol_table, diagnostics) |             resolve_variable_declaration(variable_declaration, symbol_table, diagnostics) | ||||||
|         } |         } | ||||||
| @ -336,6 +521,42 @@ fn resolve_call_statement( | |||||||
|     resolve_expression(&mut call_statement.0, symbol_table, diagnostics) |     resolve_expression(&mut call_statement.0, symbol_table, diagnostics) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn resolve_return_statement( | ||||||
|  |     return_statement: &mut ReturnStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     if let Some(expression) = &mut return_statement.0 { | ||||||
|  |         resolve_expression(expression, symbol_table, diagnostics); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_if_statement( | ||||||
|  |     if_statement: &mut IfStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_while_statement( | ||||||
|  |     while_statement: &mut WhileStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_for_statement( | ||||||
|  |     for_statement: &mut ForStatement, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Expressions */ | ||||||
|  | 
 | ||||||
| fn resolve_expression( | fn resolve_expression( | ||||||
|     expression: &mut Expression, |     expression: &mut Expression, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -361,7 +582,13 @@ fn resolve_expression( | |||||||
|         ObjectAccess(object_access) => { |         ObjectAccess(object_access) => { | ||||||
|             resolve_object_access(object_access, symbol_table, diagnostics); |             resolve_object_access(object_access, symbol_table, diagnostics); | ||||||
|         } |         } | ||||||
|         FullyQualifiedName(fqn) => resolve_fully_qualified_name(fqn, symbol_table, diagnostics), |         FullyQualifiedName(fqn) => { | ||||||
|  |             if fqn.is_single_identifier() { | ||||||
|  |                 resolve_identifier_expression(fqn.last_mut(), symbol_table, diagnostics); | ||||||
|  |             } else { | ||||||
|  |                 resolve_fqn_expression(fqn, symbol_table, diagnostics); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         Literal(literal) => { |         Literal(literal) => { | ||||||
|             resolve_literal(literal, symbol_table, diagnostics); |             resolve_literal(literal, symbol_table, diagnostics); | ||||||
|         } |         } | ||||||
| @ -371,6 +598,48 @@ fn resolve_expression( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn handle_named_lookup_result( | ||||||
|  |     lookup_result: Result<Symbol, SymbolLookupError>, | ||||||
|  |     named: &mut impl Named, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     match lookup_result { | ||||||
|  |         Ok(referenced_symbol) => { | ||||||
|  |             named.set_saved_symbol(referenced_symbol); | ||||||
|  |         } | ||||||
|  |         Err(_) => { | ||||||
|  |             diagnostics.push( | ||||||
|  |                 DmDiagnostic::error() | ||||||
|  |                     .with_message(&format!( | ||||||
|  |                         "Unable to find expressible symbol {} in current scope.", | ||||||
|  |                         named.name() | ||||||
|  |                     )) | ||||||
|  |                     .with_label(Label::primary(named.file_id(), named.range())), | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_identifier_expression( | ||||||
|  |     identifier: &mut Identifier, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     let lookup_result = symbol_table | ||||||
|  |         .lookup_expressible_by_declared_name(&identifier.name(), identifier.scope_id().unwrap()); | ||||||
|  |     handle_named_lookup_result(lookup_result, identifier, diagnostics); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn resolve_fqn_expression( | ||||||
|  |     fqn: &mut FullyQualifiedName, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     let lookup_result = | ||||||
|  |         symbol_table.lookup_expressible_by_fqn(&fqn.name(), fqn.last().scope_id().unwrap()); | ||||||
|  |     handle_named_lookup_result(lookup_result, fqn, diagnostics); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn resolve_ternary_expression( | fn resolve_ternary_expression( | ||||||
|     ternary_expression: &mut TernaryExpression, |     ternary_expression: &mut TernaryExpression, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -431,7 +700,7 @@ fn resolve_turbo_fish( | |||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
| ) { | ) { | ||||||
|     todo!() |     resolve_generic_arguments(&mut turbo_fish.0, symbol_table, diagnostics); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn resolve_call_arguments( | fn resolve_call_arguments( | ||||||
|  | |||||||
| @ -1,8 +1,9 @@ | |||||||
| use std::cell::RefCell; |  | ||||||
| use crate::ast::{Identifier, UseStatement}; | use crate::ast::{Identifier, UseStatement}; | ||||||
| use std::fmt::Display; | use std::cell::RefCell; | ||||||
|  | use std::fmt::{Debug, Display, Formatter}; | ||||||
| use std::range::Range; | use std::range::Range; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
|  | use crate::ast::named::Named; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub struct SourceDefinition { | pub struct SourceDefinition { | ||||||
| @ -13,16 +14,16 @@ pub struct SourceDefinition { | |||||||
| impl SourceDefinition { | impl SourceDefinition { | ||||||
|     pub fn from_identifier(identifier: &Identifier) -> Self { |     pub fn from_identifier(identifier: &Identifier) -> Self { | ||||||
|         SourceDefinition { |         SourceDefinition { | ||||||
|             file_id: identifier.file_id, |             file_id: identifier.file_id(), | ||||||
|             range: identifier.range, |             range: identifier.range(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self { |     pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self { | ||||||
|         let borrowed = identifier.borrow(); |         let borrowed = identifier.borrow(); | ||||||
|         SourceDefinition { |         SourceDefinition { | ||||||
|             file_id: borrowed.file_id, |             file_id: borrowed.file_id(), | ||||||
|             range: borrowed.range, |             range: borrowed.range(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -55,7 +56,7 @@ pub enum Symbol { | |||||||
|     UseStatement(Rc<RefCell<UseStatementSymbol>>), |     UseStatement(Rc<RefCell<UseStatementSymbol>>), | ||||||
|     Module(Rc<ModuleSymbol>), |     Module(Rc<ModuleSymbol>), | ||||||
|     Type(Rc<TypeSymbol>), |     Type(Rc<TypeSymbol>), | ||||||
|     Function(Rc<FunctionSymbol>), |     Function(Rc<RefCell<FunctionSymbol>>), | ||||||
|     Parameter(Rc<ParameterSymbol>), |     Parameter(Rc<ParameterSymbol>), | ||||||
|     Variable(Rc<VariableSymbol>), |     Variable(Rc<VariableSymbol>), | ||||||
| } | } | ||||||
| @ -63,10 +64,10 @@ pub enum Symbol { | |||||||
| 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.clone(), |             Symbol::UseStatement(s) => s.borrow().definition(), | ||||||
|             Symbol::Module(s) => s.definition(), |             Symbol::Module(s) => s.definition(), | ||||||
|             Symbol::Type(s) => s.definition(), |             Symbol::Type(s) => s.definition(), | ||||||
|             Symbol::Function(s) => s.definition(), |             Symbol::Function(s) => s.borrow().definition(), | ||||||
|             Symbol::Parameter(s) => s.definition(), |             Symbol::Parameter(s) => s.definition(), | ||||||
|             Symbol::Variable(s) => s.definition(), |             Symbol::Variable(s) => s.definition(), | ||||||
|         } |         } | ||||||
| @ -80,32 +81,21 @@ impl Symbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for Symbol { |  | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |  | ||||||
|         use Symbol::*; |  | ||||||
|         match self { |  | ||||||
|             UseStatement(use_statement_symbol) => write!(f, "{}", use_statement_symbol.borrow()), |  | ||||||
|             Module(module_symbol) => write!(f, "{}", module_symbol), |  | ||||||
|             Type(class_symbol) => write!(f, "{}", class_symbol), |  | ||||||
|             Function(function_symbol) => write!(f, "{}", function_symbol), |  | ||||||
|             Parameter(parameter_symbol) => write!(f, "{}", parameter_symbol), |  | ||||||
|             Variable(variable_symbol) => write!(f, "{}", variable_symbol), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Use-statement */ | /* Use-statement */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub struct UseStatementSymbol { | pub struct UseStatementSymbol { | ||||||
|     pub fqn: String, |     pub fqn: String, | ||||||
|     pub declared_name: String, |     pub declared_name: String, | ||||||
|     definition: Option<SourceDefinition>, |     definition: Option<SourceDefinition>, | ||||||
|     referenced_symbol: Option<Box<Symbol>> |     referenced_symbol: Option<Box<Symbol>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl UseStatementSymbol { | impl UseStatementSymbol { | ||||||
|     pub fn new(fqn: &str, declared_name: &str, identifier: Option<Rc<RefCell<Identifier>>>) -> Self { |     pub fn new( | ||||||
|  |         fqn: &str, | ||||||
|  |         declared_name: &str, | ||||||
|  |         identifier: Option<Rc<RefCell<Identifier>>>, | ||||||
|  |     ) -> Self { | ||||||
|         UseStatementSymbol { |         UseStatementSymbol { | ||||||
|             fqn: fqn.to_string(), |             fqn: fqn.to_string(), | ||||||
|             declared_name: declared_name.to_string(), |             declared_name: declared_name.to_string(), | ||||||
| @ -133,20 +123,18 @@ impl SymbolInner for UseStatementSymbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for UseStatementSymbol { | impl Debug for UseStatementSymbol { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!( |         f.debug_struct("UseStatementSymbol") | ||||||
|             f, |             .field("fqn", &self.fqn) | ||||||
|             "UseStatementSymbol(fqn = {}, declared_name = {})", |             .field("declared_name", &self.declared_name) | ||||||
|             self.fqn, self.declared_name |             .field("referenced_symbol", &self.referenced_symbol) | ||||||
|         ) |             .finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| /* Module */ | /* Module */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct ModuleSymbol { | pub struct ModuleSymbol { | ||||||
|     fqn: String, |     fqn: String, | ||||||
|     declared_name: String, |     declared_name: String, | ||||||
| @ -180,19 +168,18 @@ impl SymbolInner for ModuleSymbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for ModuleSymbol { | impl Debug for ModuleSymbol { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!( |         f.debug_struct("ModuleSymbol") | ||||||
|             f, |             .field("fqn", &self.fqn) | ||||||
|             "ModuleSymbol(name = {}, is_public = {})", |             .field("declared_name", &self.declared_name) | ||||||
|             self.fqn, self.is_public |             .field("is_public", &self.is_public) | ||||||
|         ) |             .finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Class */ | /* TypeSymbol */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct TypeSymbol { | pub struct TypeSymbol { | ||||||
|     fqn: String, |     fqn: String, | ||||||
|     declared_name: String, |     declared_name: String, | ||||||
| @ -201,7 +188,12 @@ pub struct TypeSymbol { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TypeSymbol { | impl TypeSymbol { | ||||||
|     pub fn new(fqn: &str, declared_name: &str, is_public: bool, identifier: Option<&Identifier>) -> Self { |     pub fn new( | ||||||
|  |         fqn: &str, | ||||||
|  |         declared_name: &str, | ||||||
|  |         is_public: bool, | ||||||
|  |         identifier: Option<&Identifier>, | ||||||
|  |     ) -> Self { | ||||||
|         TypeSymbol { |         TypeSymbol { | ||||||
|             fqn: fqn.to_string(), |             fqn: fqn.to_string(), | ||||||
|             declared_name: declared_name.to_string(), |             declared_name: declared_name.to_string(), | ||||||
| @ -229,25 +221,26 @@ impl SymbolInner for TypeSymbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for TypeSymbol { | impl Debug for TypeSymbol { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!( |         f.debug_struct("TypeSymbol") | ||||||
|             f, |             .field("fqn", &self.fqn) | ||||||
|             "TypeSymbol(fqn = {}, declared_name = {})", |             .field("declared_name", &self.declared_name) | ||||||
|             self.fqn, self.declared_name |             .field("is_public", &self.is_public) | ||||||
|         ) |             .finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Function */ | /* Function */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct FunctionSymbol { | pub struct FunctionSymbol { | ||||||
|     fqn: String, |     fqn: String, | ||||||
|     declared_name: String, |     declared_name: String, | ||||||
|     is_public: bool, |     is_public: bool, | ||||||
|     is_platform: bool, |     is_platform: bool, | ||||||
|     definition: Option<SourceDefinition>, |     definition: Option<SourceDefinition>, | ||||||
|  |     parameters: Vec<Rc<ParameterSymbol>>, | ||||||
|  |     return_type: Option<Rc<TypeSymbol>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl FunctionSymbol { | impl FunctionSymbol { | ||||||
| @ -264,12 +257,49 @@ impl FunctionSymbol { | |||||||
|             is_public, |             is_public, | ||||||
|             is_platform, |             is_platform, | ||||||
|             definition: identifier.map(SourceDefinition::from_identifier), |             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: TypeSymbol) -> 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 { |     pub fn fqn(&self) -> &str { | ||||||
|         &self.fqn |         &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<TypeSymbol>) { | ||||||
|  |         self.return_type = Some(return_type); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl SymbolInner for FunctionSymbol { | impl SymbolInner for FunctionSymbol { | ||||||
| @ -282,19 +312,21 @@ impl SymbolInner for FunctionSymbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for FunctionSymbol { | impl Debug for FunctionSymbol { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!( |         f.debug_struct("FunctionSymbol") | ||||||
|             f, |             .field("fqn", &self.fqn) | ||||||
|             "FunctionSymbol(fqn = {}, declared_name = {}, is_public = {})", |             .field("declared_name", &self.declared_name) | ||||||
|             self.fqn, self.declared_name, self.is_public |             .field("is_public", &self.is_public) | ||||||
|         ) |             .field("is_platform", &self.is_platform) | ||||||
|  |             .field("parameters", &self.parameters) | ||||||
|  |             .field("return_type", &self.return_type) | ||||||
|  |             .finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Parameter */ | /* Parameter */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct ParameterSymbol { | pub struct ParameterSymbol { | ||||||
|     declared_name: String, |     declared_name: String, | ||||||
|     definition: Option<SourceDefinition>, |     definition: Option<SourceDefinition>, | ||||||
| @ -319,19 +351,16 @@ impl SymbolInner for ParameterSymbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for ParameterSymbol { | impl Debug for ParameterSymbol { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!( |         f.debug_struct("ParameterSymbol") | ||||||
|             f, |             .field("declared_name", &self.declared_name) | ||||||
|             "ParameterSymbol({})", |             .finish() | ||||||
|             self.declared_name |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Variable */ | /* Variable */ | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub struct VariableSymbol { | pub struct VariableSymbol { | ||||||
|     declared_name: String, |     declared_name: String, | ||||||
|     is_mutable: bool, |     is_mutable: bool, | ||||||
| @ -358,12 +387,11 @@ impl SymbolInner for VariableSymbol { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for VariableSymbol { | impl Debug for VariableSymbol { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!( |         f.debug_struct("VariableSymbol") | ||||||
|             f, |             .field("declared_name", &self.declared_name) | ||||||
|             "VariableSymbol(name = {}, is_mutable = {})", |             .field("is_mutable", &self.is_mutable) | ||||||
|             self.declared_name, self.is_mutable |             .finish() | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| use std::cell::RefCell; |  | ||||||
| use crate::name_analysis::symbol::{ | use crate::name_analysis::symbol::{ | ||||||
|     FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol, |     FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol, | ||||||
|     UseStatementSymbol, VariableSymbol, |     UseStatementSymbol, VariableSymbol, | ||||||
| }; | }; | ||||||
| use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; | use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; | ||||||
| use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; | use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; | ||||||
|  | use std::cell::RefCell; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| use std::fmt::Display; | use std::fmt::Display; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| @ -16,7 +16,7 @@ struct Scope { | |||||||
|     use_statement_symbols: HashMap<String, Rc<RefCell<UseStatementSymbol>>>, |     use_statement_symbols: HashMap<String, Rc<RefCell<UseStatementSymbol>>>, | ||||||
|     module_symbols: HashMap<String, Rc<ModuleSymbol>>, |     module_symbols: HashMap<String, Rc<ModuleSymbol>>, | ||||||
|     type_symbols: HashMap<String, Rc<TypeSymbol>>, |     type_symbols: HashMap<String, Rc<TypeSymbol>>, | ||||||
|     function_symbols: HashMap<String, Rc<FunctionSymbol>>, |     function_symbols: HashMap<String, Rc<RefCell<FunctionSymbol>>>, | ||||||
|     parameter_symbols: HashMap<String, Rc<ParameterSymbol>>, |     parameter_symbols: HashMap<String, Rc<ParameterSymbol>>, | ||||||
|     variable_symbols: HashMap<String, Rc<VariableSymbol>>, |     variable_symbols: HashMap<String, Rc<VariableSymbol>>, | ||||||
|     debug_name: String, |     debug_name: String, | ||||||
| @ -37,13 +37,34 @@ impl Scope { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn get_any_symbol(&self, name: &str) -> Option<Symbol> { |     fn get_any_symbol(&self, name: &str) -> Option<Symbol> { | ||||||
|         self.variable_symbols.get(name) |         self.variable_symbols | ||||||
|  |             .get(name) | ||||||
|             .map(|s| Symbol::Variable(s.clone())) |             .map(|s| Symbol::Variable(s.clone())) | ||||||
|             .or_else(|| self.parameter_symbols.get(name).map(|s| Symbol::Parameter(s.clone()))) |             .or_else(|| { | ||||||
|             .or_else(|| self.function_symbols.get(name).map(|s| Symbol::Function(s.clone()))) |                 self.parameter_symbols | ||||||
|             .or_else(|| self.type_symbols.get(name).map(|ts| Symbol::Type(ts.clone()))) |                     .get(name) | ||||||
|             .or_else(|| self.module_symbols.get(name).map(|ms| Symbol::Module(ms.clone()))) |                     .map(|s| Symbol::Parameter(s.clone())) | ||||||
|             .or_else(|| self.use_statement_symbols.get(name).map(|us| Symbol::UseStatement(us.clone()))) |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 self.function_symbols | ||||||
|  |                     .get(name) | ||||||
|  |                     .map(|s| Symbol::Function(s.clone())) | ||||||
|  |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 self.type_symbols | ||||||
|  |                     .get(name) | ||||||
|  |                     .map(|ts| Symbol::Type(ts.clone())) | ||||||
|  |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 self.module_symbols | ||||||
|  |                     .get(name) | ||||||
|  |                     .map(|ms| Symbol::Module(ms.clone())) | ||||||
|  |             }) | ||||||
|  |             .or_else(|| { | ||||||
|  |                 self.use_statement_symbols | ||||||
|  |                     .get(name) | ||||||
|  |                     .map(|us| Symbol::UseStatement(us.clone())) | ||||||
|  |             }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> { |     fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> { | ||||||
| @ -55,9 +76,32 @@ impl Scope { | |||||||
|         None |         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| s.fqn() == fqn).cloned() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> { |     fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> { | ||||||
|         for function_symbol in self.function_symbols.values() { |         for function_symbol in self.function_symbols.values() { | ||||||
|             if function_symbol.fqn() == fqn { |             if function_symbol.borrow().fqn() == fqn { | ||||||
|                 return Some(Symbol::Function(function_symbol.clone())); |                 return Some(Symbol::Function(function_symbol.clone())); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -71,7 +115,7 @@ impl Scope { | |||||||
| 
 | 
 | ||||||
|     fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> { |     fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> { | ||||||
|         for function_symbol in self.function_symbols.values() { |         for function_symbol in self.function_symbols.values() { | ||||||
|             if function_symbol.declared_name() == declared_name { |             if function_symbol.borrow().declared_name() == declared_name { | ||||||
|                 return Some(Symbol::Function(function_symbol.clone())); |                 return Some(Symbol::Function(function_symbol.clone())); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -96,6 +140,45 @@ impl Scope { | |||||||
|         } |         } | ||||||
|         None |         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.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.type_symbols | ||||||
|  |                     .values() | ||||||
|  |                     .find(|ts| ts.fqn() == fqn) | ||||||
|  |                     .map(|ts| Symbol::Type(ts.clone())) | ||||||
|  |             }) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Symbol table */ | /* Symbol table */ | ||||||
| @ -152,18 +235,20 @@ impl SymbolTable { | |||||||
|     pub fn insert_use_statement_symbol( |     pub fn insert_use_statement_symbol( | ||||||
|         &mut self, |         &mut self, | ||||||
|         use_statement_symbol: UseStatementSymbol, |         use_statement_symbol: UseStatementSymbol, | ||||||
|     ) -> Result<(), SymbolInsertError> { |     ) -> Result<Rc<RefCell<UseStatementSymbol>>, SymbolInsertError> { | ||||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); |         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||||
|         if let Some(defined_symbol) = |         if let Some(defined_symbol) = | ||||||
|             current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name()) |             current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name()) | ||||||
|         { |         { | ||||||
|             Err(SymbolAlreadyDefined(defined_symbol)) |             Err(SymbolAlreadyDefined(defined_symbol)) | ||||||
|         } else { |         } else { | ||||||
|             current_scope.use_statement_symbols.insert( |             let declared_name = use_statement_symbol.declared_name().to_string(); | ||||||
|                 use_statement_symbol.declared_name().to_string(), |             let to_insert = Rc::new(RefCell::new(use_statement_symbol)); | ||||||
|                 Rc::new(RefCell::new(use_statement_symbol)), |             let to_return = to_insert.clone(); | ||||||
|             ); |             current_scope | ||||||
|             Ok(()) |                 .use_statement_symbols | ||||||
|  |                 .insert(declared_name, to_insert); | ||||||
|  |             Ok(to_return) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -203,36 +288,39 @@ impl SymbolTable { | |||||||
|     pub fn insert_function_symbol( |     pub fn insert_function_symbol( | ||||||
|         &mut self, |         &mut self, | ||||||
|         function_symbol: FunctionSymbol, |         function_symbol: FunctionSymbol, | ||||||
|     ) -> Result<(), SymbolInsertError> { |     ) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolInsertError> { | ||||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); |         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||||
|         if let Some(defined_symbol) = |         if let Some(defined_symbol) = | ||||||
|             current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name()) |             current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name()) | ||||||
|         { |         { | ||||||
|             Err(SymbolAlreadyDefined(defined_symbol)) |             Err(SymbolAlreadyDefined(defined_symbol)) | ||||||
|         } else { |         } else { | ||||||
|             current_scope.function_symbols.insert( |             let declared_name = function_symbol.declared_name().to_string(); | ||||||
|                 function_symbol.declared_name().to_string(), |             let to_insert = Rc::new(RefCell::new(function_symbol)); | ||||||
|                 Rc::new(function_symbol), |             let to_return = to_insert.clone(); | ||||||
|             ); |             current_scope | ||||||
|             Ok(()) |                 .function_symbols | ||||||
|  |                 .insert(declared_name, to_insert); | ||||||
|  |             Ok(to_return) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn insert_parameter_symbol( |     pub fn insert_parameter_symbol( | ||||||
|         &mut self, |         &mut self, | ||||||
|         parameter_symbol: ParameterSymbol, |         parameter_symbol: ParameterSymbol, | ||||||
|     ) -> Result<(), SymbolInsertError> { |     ) -> Result<Rc<ParameterSymbol>, SymbolInsertError> { | ||||||
|         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); |         let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); | ||||||
|         if let Some(defined_symbol) = |         if let Some(defined_symbol) = | ||||||
|             current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name()) |             current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name()) | ||||||
|         { |         { | ||||||
|             Err(SymbolAlreadyDefined(defined_symbol)) |             Err(SymbolAlreadyDefined(defined_symbol)) | ||||||
|         } else { |         } else { | ||||||
|             current_scope.parameter_symbols.insert( |             let to_insert = Rc::new(parameter_symbol); | ||||||
|                 parameter_symbol.declared_name().to_string(), |             let to_return = to_insert.clone(); | ||||||
|                 Rc::new(parameter_symbol), |             current_scope | ||||||
|             ); |                 .parameter_symbols | ||||||
|             Ok(()) |                 .insert(to_insert.declared_name().to_string(), to_insert); | ||||||
|  |             Ok(to_return) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -254,6 +342,7 @@ impl SymbolTable { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[deprecated(note = "Use more specific lookup methods.")] | ||||||
|     pub fn lookup(&self, name: &str, scope_id: usize) -> Result<Symbol, SymbolLookupError> { |     pub fn lookup(&self, name: &str, scope_id: usize) -> Result<Symbol, SymbolLookupError> { | ||||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); |         let mut scope_opt = Some(&self.scopes[scope_id]); | ||||||
|         while let Some(scope) = scope_opt { |         while let Some(scope) = scope_opt { | ||||||
| @ -269,6 +358,44 @@ impl SymbolTable { | |||||||
|         Err(NoDefinition) |         Err(NoDefinition) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     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( |     pub fn lookup_usable_by_fqn( | ||||||
|         &self, |         &self, | ||||||
|         fully_qualified_name: &str, |         fully_qualified_name: &str, | ||||||
| @ -281,27 +408,68 @@ impl SymbolTable { | |||||||
|         } |         } | ||||||
|         Err(NoDefinition) |         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 { | impl Display for SymbolTable { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||||||
|         writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; |         writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; | ||||||
|         for (i, scope) in self.scopes.iter().enumerate() { |         for (i, scope) in self.scopes.iter().enumerate() { | ||||||
|             writeln!(f, "Scope {} {}", i, scope.debug_name)?; |             writeln!(f, "----Scope {} {}----", i, scope.debug_name)?; | ||||||
|             for (name, symbol) in &scope.use_statement_symbols { |             for symbol in scope.use_statement_symbols.values() { | ||||||
|                 writeln!(f, "  {}({})", name, symbol.borrow())?; |                 writeln!(f, "{:#?}", symbol.borrow())?; | ||||||
|             } |             } | ||||||
|             for (name, symbol) in &scope.module_symbols { |             for symbol in scope.module_symbols.values() { | ||||||
|                 writeln!(f, "  {}({})", name, symbol)?; |                 writeln!(f, "{:#?}", symbol)?; | ||||||
|             } |             } | ||||||
|             for (name, symbol) in &scope.type_symbols { |             for symbol in scope.type_symbols.values() { | ||||||
|                 writeln!(f, "  {}({})", name, symbol)?; |                 writeln!(f, "{:#?}", symbol)?; | ||||||
|             } |             } | ||||||
|             for (name, symbol) in &scope.function_symbols { |             for symbol in scope.function_symbols.values() { | ||||||
|                 writeln!(f, "  {}({})", name, symbol)?; |                 writeln!(f, "{:#?}", symbol.borrow())?; | ||||||
|             } |             } | ||||||
|             for (name, symbol) in &scope.variable_symbols { |             for symbol in scope.parameter_symbols.values() { | ||||||
|                 writeln!(f, "  {}({})", name, symbol)?; |                 writeln!(f, "{:#?}", symbol)?; | ||||||
|  |             } | ||||||
|  |             for symbol in scope.variable_symbols.values() { | ||||||
|  |                 writeln!(f, "{:#?}", symbol)?; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| Ns = { "ns" } | Ns = { "ns" } | ||||||
| TypeKw = { "type" } | TypeKw = { "type" } | ||||||
| Mod = { "mod" } | Mod = { "mod" } | ||||||
| Int = { "int" } | IntKw = { "int" } | ||||||
| ClassKw = { "class" } | ClassKw = { "class" } | ||||||
| Platform = { "platform" } | Platform = { "platform" } | ||||||
| Pub = { "pub" } | Pub = { "pub" } | ||||||
| @ -15,7 +15,6 @@ Ref = { "ref" } | |||||||
| Def = { "def" } | Def = { "def" } | ||||||
| Where = { "where" } | Where = { "where" } | ||||||
| Infer = { "infer" } | Infer = { "infer" } | ||||||
| Void = { "Void" } |  | ||||||
| Delegate = { "delegate" } | Delegate = { "delegate" } | ||||||
| Let = { "let" } | Let = { "let" } | ||||||
| Fn = { "fn" } | Fn = { "fn" } | ||||||
| @ -32,12 +31,25 @@ True = { "true" } | |||||||
| False = { "false" } | False = { "false" } | ||||||
| Use = { "use" } | Use = { "use" } | ||||||
| 
 | 
 | ||||||
|  | // Keywords: primitive types | ||||||
|  | Byte = { "Byte" } | ||||||
|  | Short = { "Short" } | ||||||
|  | Char = { "Char" } | ||||||
|  | Int = { "Int" } | ||||||
|  | Long = { "Long" } | ||||||
|  | Double = { "Double" } | ||||||
|  | Bool = { "Bool" } | ||||||
|  | String = { "String" } | ||||||
|  | Array = { "Array" } | ||||||
|  | Any = { "Any" } | ||||||
|  | Void = { "Void" } | ||||||
|  | 
 | ||||||
| // Keywords as a rule (for preventing identifiers with keywords, etc.) | // Keywords as a rule (for preventing identifiers with keywords, etc.) | ||||||
| Keyword = { | Keyword = { | ||||||
|       Ns |       Ns | ||||||
|     | TypeKw |     | TypeKw | ||||||
|     | Mod |     | Mod | ||||||
|     | Int |     | IntKw | ||||||
|     | ClassKw |     | ClassKw | ||||||
|     | Platform |     | Platform | ||||||
|     | Pub |     | Pub | ||||||
| @ -50,7 +62,6 @@ Keyword = { | |||||||
|     | Def |     | Def | ||||||
|     | Where |     | Where | ||||||
|     | Infer |     | Infer | ||||||
|     | Void |  | ||||||
|     | Delegate |     | Delegate | ||||||
|     | Let |     | Let | ||||||
|     | Fn |     | Fn | ||||||
| @ -66,6 +77,17 @@ Keyword = { | |||||||
|     | True |     | True | ||||||
|     | False |     | False | ||||||
|     | Use |     | Use | ||||||
|  |     | Byte | ||||||
|  |     | Short | ||||||
|  |     | Char | ||||||
|  |     | Int | ||||||
|  |     | Long | ||||||
|  |     | Double | ||||||
|  |     | Bool | ||||||
|  |     | String | ||||||
|  |     | Array | ||||||
|  |     | Any | ||||||
|  |     | Void | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Symbols | // Symbols | ||||||
| @ -180,12 +202,26 @@ ParenthesesOptionalTypeUseList = { | |||||||
| // Parameters = declaration | // Parameters = declaration | ||||||
| 
 | 
 | ||||||
| TypeUse = { | TypeUse = { | ||||||
|       Void |       PrimitiveType | ||||||
|     | InterfaceOrClassTypeUse |     | InterfaceOrClassTypeUse | ||||||
|     | TupleTypeUse |     | TupleTypeUse | ||||||
|     | FunctionTypeUse |     | FunctionTypeUse | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | PrimitiveType = { | ||||||
|  |         Byte | ||||||
|  |       | Short | ||||||
|  |       | Char | ||||||
|  |       | Int | ||||||
|  |       | Long | ||||||
|  |       | Double | ||||||
|  |       | Bool | ||||||
|  |       | String | ||||||
|  |       | Array ~ GenericArguments? | ||||||
|  |       | Any | ||||||
|  |       | Void | ||||||
|  | } | ||||||
|  | 
 | ||||||
| InterfaceOrClassTypeUse = { | InterfaceOrClassTypeUse = { | ||||||
|       Borrow* |       Borrow* | ||||||
|     ~ Mut? |     ~ Mut? | ||||||
| @ -335,7 +371,7 @@ Module = { | |||||||
| 
 | 
 | ||||||
| Interface = { | Interface = { | ||||||
|       Pub? |       Pub? | ||||||
|     ~ Int |     ~ IntKw | ||||||
|     ~ Identifier |     ~ Identifier | ||||||
|     ~ GenericParameters? |     ~ GenericParameters? | ||||||
|     ~ ImplementsList? |     ~ ImplementsList? | ||||||
|  | |||||||
| @ -1,23 +1,14 @@ | |||||||
| use crate::name_analysis::symbol::{FunctionSymbol, TypeSymbol}; | use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol, TypeSymbol}; | ||||||
| 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_type_symbol(TypeSymbol::new("std::core:Array", "Array", true, None))?; |     symbol_table.insert_function_symbol( | ||||||
|     // todo: make this primitive
 |         FunctionSymbol::new("std::core::println", "println", true, true, None) | ||||||
|     symbol_table.insert_type_symbol(TypeSymbol::new("std::core::String", "String", true, None))?; |             .with_parameters(vec![ParameterSymbol::new("msg", None)]), | ||||||
|     symbol_table.insert_function_symbol(FunctionSymbol::new( |     )?; | ||||||
|         "std::core::println", |     symbol_table.insert_function_symbol( | ||||||
|         "println", |         FunctionSymbol::new("std::core::print", "print", true, true, None) | ||||||
|         true, |             .with_parameters(vec![ParameterSymbol::new("msg", None)]), | ||||||
|         true, |     )?; | ||||||
|         None, |  | ||||||
|     ))?; |  | ||||||
|     symbol_table.insert_function_symbol(FunctionSymbol::new( |  | ||||||
|         "std::core::print", |  | ||||||
|         "print", |  | ||||||
|         true, |  | ||||||
|         true, |  | ||||||
|         None, |  | ||||||
|     ))?; |  | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user