Much work on grammar, AST building and unparsing.
This commit is contained in:
		
							parent
							
								
									e8aff842ed
								
							
						
					
					
						commit
						82af6b4dfb
					
				
							
								
								
									
										530
									
								
								src/ast/build.rs
									
									
									
									
									
								
							
							
						
						
									
										530
									
								
								src/ast/build.rs
									
									
									
									
									
								
							| @ -1,374 +1,208 @@ | |||||||
| use crate::ast::{ | use crate::ast::{CompilationUnit, DelegateOrIdentifier, Fqn, FunctionModifier, FunctionTypeUse, GenericArgument, GenericArguments, GenericParameter, GenericParameters, Identifier, InputArgument, InputArguments, InterfaceOrClassTypeUse, Reference, References, ReturnType, TupleTypeUse, TypeUse, VoidOrTypeUse}; | ||||||
|     BlockStatement, CompilationUnit, Declaration, Fqn, FunctionDeclaration, GenericArgument, | use crate::parser::Rule; | ||||||
|     GenericParameter, Identifier, ClassConstructor, Parameter, TypeDeclaration, TypeUse, |  | ||||||
| }; |  | ||||||
| use crate::parser::{DeimosParser, Rule}; |  | ||||||
| use crate::vm::source_code_location::SourceCodeLocation; |  | ||||||
| use pest::iterators::Pair; | use pest::iterators::Pair; | ||||||
| use pest::Parser; |  | ||||||
| 
 | 
 | ||||||
| fn build_field(field_pair: Pair<Rule>) -> Declaration { | fn expect_and_use<T>(pair: Pair<Rule>, rule: Rule, f: fn(Pair<Rule>) -> T) -> T { | ||||||
|  |     if pair.as_rule() != rule { | ||||||
|  |         panic!("Expected rule {:?} but found {:?}", rule, pair.as_rule()) | ||||||
|  |     } | ||||||
|  |     f(pair) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn build_ast(compilation_unit_pair: Pair<Rule>) -> CompilationUnit { | ||||||
|     todo!() |     todo!() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn build_prop(prop_pair: Pair<Rule>) -> Declaration { | fn build_identifier(identifier_pair: Pair<Rule>) -> Identifier { | ||||||
|     todo!() |     Identifier { | ||||||
| } |         name: identifier_pair.as_str().to_string(), | ||||||
| 
 |  | ||||||
| fn build_generic_argument(generic_argument_pair: Pair<Rule>) -> GenericArgument { |  | ||||||
|     let fqn_pair = generic_argument_pair.into_inner().next().unwrap(); |  | ||||||
|     GenericArgument { |  | ||||||
|         fqn: build_fqn(fqn_pair), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_generic_arguments_declaration( |  | ||||||
|     generic_arguments_declaration_pair: Pair<Rule>, |  | ||||||
| ) -> Vec<GenericArgument> { |  | ||||||
|     let mut generic_arguments: Vec<GenericArgument> = vec![]; |  | ||||||
|     for pair in generic_arguments_declaration_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::GenericArguments => { |  | ||||||
|                 generic_arguments.push(build_generic_argument(pair)); |  | ||||||
|             } |  | ||||||
|             _ => panic!("Expected only generic_argument rules. Found: {}", pair), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     generic_arguments |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_generic_parameter(generic_parameter_pair: Pair<Rule>) -> GenericParameter { |  | ||||||
|     let identifier_pair = generic_parameter_pair.into_inner().next().unwrap(); |  | ||||||
|     GenericParameter { |  | ||||||
|         identifier: build_identifier(identifier_pair), |  | ||||||
|         bound: None, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_type_use(type_pair: Pair<Rule>) -> TypeUse { |  | ||||||
|     let mut fqn: Option<Fqn> = None; |  | ||||||
|     let mut generic_arguments_declaration: Option<Vec<GenericArgument>> = None; |  | ||||||
| 
 |  | ||||||
|     for pair in type_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::FullyQualifiedName => { |  | ||||||
|                 fqn = Some(build_fqn(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::GenericArguments => { |  | ||||||
|                 generic_arguments_declaration = Some(build_generic_arguments_declaration(pair)); |  | ||||||
|             } |  | ||||||
|             _ => panic!( |  | ||||||
|                 "Expected only fqn or generic_arguments_declaration rules. Found: {}", |  | ||||||
|                 pair |  | ||||||
|             ), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     TypeUse { |  | ||||||
|         fqn: fqn.unwrap(), |  | ||||||
|         generics: generic_arguments_declaration.unwrap_or(vec![]), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_generic_parameters_declaration( |  | ||||||
|     generic_parameters_declaration_pair: Pair<Rule>, |  | ||||||
| ) -> Vec<GenericParameter> { |  | ||||||
|     let mut parameters: Vec<GenericParameter> = vec![]; |  | ||||||
|     for pair in generic_parameters_declaration_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Identifier => { |  | ||||||
|                 parameters.push(build_generic_parameter(pair)); |  | ||||||
|             } |  | ||||||
|             _ => panic!("Expected only generic_parameter rule. Found: {}", pair), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     parameters |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_extends_list(extends_list_pair: Pair<Rule>) -> Vec<TypeUse> { |  | ||||||
|     let mut extensions: Vec<TypeUse> = vec![]; |  | ||||||
| 
 |  | ||||||
|     for pair in extends_list_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::TypeUse => { |  | ||||||
|                 extensions.push(build_type_use(pair)); |  | ||||||
|             } |  | ||||||
|             _ => panic!("Expected only type rule. Found: {}", pair), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     extensions |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair<Rule>) -> Declaration { |  | ||||||
|     let mut identifier: Option<Identifier> = None; |  | ||||||
|     let mut generic_parameters: Option<Vec<GenericParameter>> = None; |  | ||||||
|     let mut extends: Option<Vec<TypeUse>> = None; |  | ||||||
|     let mut declarations: Vec<Declaration> = vec![]; |  | ||||||
| 
 |  | ||||||
|     for pair in interface_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Identifier => { |  | ||||||
|                 identifier = Some(build_identifier(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::GenericParameters => { |  | ||||||
|                 generic_parameters = Some(build_generic_parameters_declaration(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::ExtendsList => { |  | ||||||
|                 extends = Some(build_extends_list(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::InterfaceLevelDeclaration => { |  | ||||||
|                 declarations.push(build_module_level_declaration(pair)); |  | ||||||
|             }, |  | ||||||
|             _ => panic!( |  | ||||||
|                 "Expected only identifier, generics_declaration, extends_list, or declaration rules. Found: {}", |  | ||||||
|                 pair |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Declaration::Interface { |  | ||||||
|         identifier: identifier.unwrap(), |  | ||||||
|         is_extern, |  | ||||||
|         is_public, |  | ||||||
|         type_declaration: TypeDeclaration::new( |  | ||||||
|             generic_parameters.unwrap_or(vec![]), |  | ||||||
|             extends.unwrap_or(vec![]), |  | ||||||
|             declarations, |  | ||||||
|         ), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_class_constructor(class_constructor_pair: Pair<Rule>) -> ClassConstructor { |  | ||||||
|     todo!() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_implementation( |  | ||||||
|     is_extern: bool, |  | ||||||
|     is_public: bool, |  | ||||||
|     implementation_pair: Pair<Rule>, |  | ||||||
| ) -> Declaration { |  | ||||||
|     let mut identifier: Option<Identifier> = None; |  | ||||||
|     let mut generic_parameters: Option<Vec<GenericParameter>> = None; |  | ||||||
|     let mut impl_ctor: Option<ClassConstructor> = None; |  | ||||||
|     let mut extends: Option<Vec<TypeUse>> = None; |  | ||||||
|     let mut declarations: Vec<Declaration> = vec![]; |  | ||||||
| 
 |  | ||||||
|     for pair in implementation_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Identifier => { |  | ||||||
|                 identifier = Some(build_identifier(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::GenericParameters => { |  | ||||||
|                 generic_parameters = Some(build_generic_parameters_declaration(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::ClassConstructor => { |  | ||||||
|                 impl_ctor = Some(build_class_constructor(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::ExtendsList => { |  | ||||||
|                 extends = Some(build_extends_list(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::ClassLevelDeclaration => { |  | ||||||
|                 declarations.push(build_module_level_declaration(pair)); |  | ||||||
|             } |  | ||||||
|             _ => panic!("Unexpected rule: {}", pair), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Declaration::Implementation { |  | ||||||
|         identifier: identifier.unwrap(), |  | ||||||
|         is_extern, |  | ||||||
|         is_public, |  | ||||||
|         type_declaration: TypeDeclaration::new( |  | ||||||
|             generic_parameters.unwrap_or(vec![]), |  | ||||||
|             extends.unwrap_or(vec![]), |  | ||||||
|             declarations, |  | ||||||
|         ), |  | ||||||
|         impl_ctor, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_module(is_extern: bool, is_public: bool, pair: Pair<Rule>) -> Declaration { |  | ||||||
|     todo!() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_parameter(pair: Pair<Rule>) -> Parameter { |  | ||||||
|     let mut identifier: Option<Identifier> = None; |  | ||||||
|     let mut declared_type: Option<TypeUse> = None; |  | ||||||
|     for pair in pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Identifier => { |  | ||||||
|                 identifier = Some(build_identifier(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::TypeAnnotation => { |  | ||||||
|                 declared_type = Some(build_type_use(pair)); |  | ||||||
|             } |  | ||||||
|             _ => unreachable!(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     Parameter { |  | ||||||
|         identifier: identifier.unwrap(), |  | ||||||
|         declared_type, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_parameters_list(pair: Pair<Rule>) -> Vec<Parameter> { |  | ||||||
|     let mut parameters: Vec<Parameter> = vec![]; |  | ||||||
|     for pair in pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Parameter => { |  | ||||||
|                 parameters.push(build_parameter(pair)); |  | ||||||
|             } |  | ||||||
|             _ => unreachable!(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     parameters |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_block_statement(pair: Pair<Rule>) -> BlockStatement { |  | ||||||
|     todo!() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_function_equals_body(pair: Pair<Rule>) -> BlockStatement { |  | ||||||
|     todo!() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_function(is_extern: bool, is_public: bool, pair: Pair<Rule>) -> Declaration { |  | ||||||
|     let mut is_implementation = false; |  | ||||||
|     let mut generic_parameters: Option<Vec<GenericParameter>> = None; |  | ||||||
|     let mut identifier: Option<Identifier> = None; |  | ||||||
|     let mut parameters: Option<Vec<Parameter>> = None; |  | ||||||
|     let mut return_type: Option<TypeUse> = None; |  | ||||||
|     let mut statement: Option<BlockStatement> = None; |  | ||||||
| 
 |  | ||||||
|     let (line, col) = pair.line_col(); |  | ||||||
| 
 |  | ||||||
|     for pair in pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Implementation => { |  | ||||||
|                 is_implementation = true; |  | ||||||
|             } |  | ||||||
|             Rule::Identifier => { |  | ||||||
|                 identifier = Some(build_identifier(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::GenericParameters => { |  | ||||||
|                 generic_parameters = Some(build_generic_parameters_declaration(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::Parameters => { |  | ||||||
|                 parameters = Some(build_parameters_list(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::TypeUse => { |  | ||||||
|                 return_type = Some(build_type_use(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::BlockStatement => { |  | ||||||
|                 statement = Some(build_block_statement(pair)); |  | ||||||
|             } |  | ||||||
|             Rule::FunctionEqualsBody => { |  | ||||||
|                 statement = Some(build_function_equals_body(pair)); |  | ||||||
|             } |  | ||||||
|             _ => unreachable!(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Declaration::Function(FunctionDeclaration { |  | ||||||
|         is_extern, |  | ||||||
|         is_public, |  | ||||||
|         identifier: identifier.unwrap(), |  | ||||||
|         parameters: parameters.unwrap(), |  | ||||||
|         declared_type: return_type, |  | ||||||
|         block_statement: statement.unwrap(), |  | ||||||
|         source_code_location: SourceCodeLocation { |  | ||||||
|             source_file_name: "TODO".to_string(), |  | ||||||
|             line, |  | ||||||
|             col, |  | ||||||
|         }, |  | ||||||
|     }) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_module_level_declaration(declaration_pair: Pair<Rule>) -> Declaration { |  | ||||||
|     let mut is_extern = false; |  | ||||||
|     let mut is_public = false; |  | ||||||
|     let mut declaration: Option<Declaration> = None; |  | ||||||
| 
 |  | ||||||
|     for pair in declaration_pair.into_inner() { |  | ||||||
|         match pair.as_rule() { |  | ||||||
|             Rule::Declare => { |  | ||||||
|                 is_extern = true; |  | ||||||
|             } |  | ||||||
|             Rule::Public => { |  | ||||||
|                 is_public = true; |  | ||||||
|             } |  | ||||||
|             Rule::Interface => { |  | ||||||
|                 declaration = Some(build_interface(is_extern, is_public, pair)); |  | ||||||
|             } |  | ||||||
|             Rule::Implementation => { |  | ||||||
|                 declaration = Some(build_implementation(is_extern, is_public, pair)); |  | ||||||
|             } |  | ||||||
|             Rule::Module => { |  | ||||||
|                 declaration = Some(build_module(is_extern, is_public, pair)); |  | ||||||
|             } |  | ||||||
|             Rule::Function => { |  | ||||||
|                 declaration = Some(build_function(is_extern, is_public, pair)); |  | ||||||
|             } |  | ||||||
|             _ => unreachable!(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     declaration.expect("Expected declaration.") |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn build_identifier(pair: Pair<Rule>) -> Identifier { |  | ||||||
|     match pair.as_rule() { |  | ||||||
|         Rule::Identifier => Identifier { |  | ||||||
|             name: String::from(pair.as_str()), |  | ||||||
|         }, |  | ||||||
|         _ => unreachable!(), |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn build_fqn(fqn_pair: Pair<Rule>) -> Fqn { | fn build_fqn(fqn_pair: Pair<Rule>) -> Fqn { | ||||||
|     let mut identifiers: Vec<Identifier> = vec![]; |     let mut identifiers: Vec<Identifier> = vec![]; | ||||||
|     for pair in fqn_pair.into_inner() { |     for identifier_pair in fqn_pair.into_inner() { | ||||||
|         match pair.as_rule() { |         identifiers.push(expect_and_use( | ||||||
|             Rule::Identifier => { |             identifier_pair, | ||||||
|                 identifiers.push(build_identifier(pair)); |             Rule::Identifier, | ||||||
|             } |             build_identifier, | ||||||
|             _ => unreachable!(), |         )); | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     Fqn { identifiers } |     Fqn { identifiers } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn build_compilation_unit(pair: Pair<Rule>) -> CompilationUnit { | fn build_type_use(type_use_pair: Pair<Rule>) -> TypeUse { | ||||||
|     let mut namespace: Option<Fqn> = None; |     let inner_pair = type_use_pair.into_inner().next().unwrap(); | ||||||
|     let mut declarations: Vec<Declaration> = vec![]; |     match inner_pair.as_rule() { | ||||||
|  |         Rule::InterfaceOrClassTypeUse => { | ||||||
|  |             TypeUse::InterfaceOrClass(build_interface_or_class_type_use(inner_pair)) | ||||||
|  |         } | ||||||
|  |         Rule::TupleTypeUse => TypeUse::Tuple(build_tuple_type_use(inner_pair)), | ||||||
|  |         Rule::FunctionTypeUse => TypeUse::Function(build_function_type_use(inner_pair)), | ||||||
|  |         _ => unreachable!(), | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     for pair in pair.into_inner() { | fn build_interface_or_class_type_use(pair: Pair<Rule>) -> InterfaceOrClassTypeUse { | ||||||
|         match pair.as_rule() { |     let mut inner = pair.into_inner(); | ||||||
|             Rule::Namespace => { |     let fqn = expect_and_use(inner.next().unwrap(), Rule::FullyQualifiedName, build_fqn); | ||||||
|                 let fqn_pair = pair.into_inner().next().unwrap(); | 
 | ||||||
|                 namespace = Some(build_fqn(fqn_pair)); |     let generics = inner | ||||||
|  |         .next() | ||||||
|  |         .map(|inner_pair| { | ||||||
|  |             expect_and_use(inner_pair, Rule::GenericArguments, build_generic_arguments) | ||||||
|  |         }) | ||||||
|  |         .unwrap_or(GenericArguments(vec![])); | ||||||
|  | 
 | ||||||
|  |     InterfaceOrClassTypeUse { fqn, generics } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_tuple_type_use(tuple_type_use_pair: Pair<Rule>) -> TupleTypeUse { | ||||||
|  |     TupleTypeUse( | ||||||
|  |         tuple_type_use_pair | ||||||
|  |             .into_inner() | ||||||
|  |             .map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use)) | ||||||
|  |             .collect(), | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_function_type_use(function_pair: Pair<Rule>) -> FunctionTypeUse { | ||||||
|  |     let mut function_modifier: Option<FunctionModifier> = None; | ||||||
|  |     let mut generics: Option<GenericParameters> = None; | ||||||
|  |     let mut parameters: Option<TupleTypeUse> = None; | ||||||
|  |     let mut inputs: Option<InputArguments> = None; | ||||||
|  |     let mut return_type: Option<ReturnType> = None; | ||||||
|  | 
 | ||||||
|  |     for inner_pair in function_pair.into_inner() { | ||||||
|  |         match inner_pair.as_rule() { | ||||||
|  |             Rule::FunctionTypeModifier => { | ||||||
|  |                 function_modifier = Some(build_function_modifier(inner_pair)); | ||||||
|             } |             } | ||||||
|             Rule::ModuleLevelDeclaration => { |             Rule::Fn => {} | ||||||
|                 declarations.push(build_module_level_declaration(pair)); |             Rule::GenericParameters => { | ||||||
|  |                 generics = Some(build_generic_parameters(inner_pair)); | ||||||
|             } |             } | ||||||
|             Rule::EOI => {} // ignore
 |             Rule::TupleTypeUse => { | ||||||
|  |                 parameters = Some(build_tuple_type_use(inner_pair)); | ||||||
|  |             } | ||||||
|  |             Rule::FunctionInputArguments => { | ||||||
|  |                 inputs = Some(build_function_input_arguments(inner_pair)); | ||||||
|  |             } | ||||||
|  |             Rule::ReturnType => { | ||||||
|  |                 return_type = Some(build_return_type(inner_pair)); | ||||||
|  |             }, | ||||||
|             _ => unreachable!(), |             _ => unreachable!(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     CompilationUnit { |     FunctionTypeUse { | ||||||
|         namespace, |         function_modifier, | ||||||
|         declarations, |         generics: generics.unwrap_or(GenericParameters(vec![])), | ||||||
|  |         parameters: parameters.unwrap(), | ||||||
|  |         inputs: inputs.unwrap_or(InputArguments(vec![])), | ||||||
|  |         return_type: return_type.unwrap(), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn build_ast(src: &str) -> CompilationUnit { | fn build_generic_arguments(generic_arguments_pair: Pair<Rule>) -> GenericArguments { | ||||||
|     let pair = DeimosParser::parse(Rule::CompilationUnit, src) |     let mut generic_arguments: Vec<GenericArgument> = vec![]; | ||||||
|         .expect("Unsuccessful parse.") |     for generic_argument_pair in generic_arguments_pair.into_inner() { | ||||||
|         .next() |         generic_arguments.push(expect_and_use( | ||||||
|         .expect("Expected compilation_unit."); |             generic_argument_pair, | ||||||
|     match pair.as_rule() { |             Rule::FullyQualifiedName, | ||||||
|         Rule::CompilationUnit => build_compilation_unit(pair), |             build_generic_argument, | ||||||
|         _ => panic!("Expected compilation_unit rule."), |         )); | ||||||
|  |     } | ||||||
|  |     GenericArguments(generic_arguments) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_generic_argument(fqn_pair: Pair<Rule>) -> GenericArgument { | ||||||
|  |     GenericArgument { | ||||||
|  |         fqn: build_fqn(fqn_pair), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn build_function_modifier(function_modifier_pair: Pair<Rule>) -> FunctionModifier { | ||||||
|  |     let mut inner = function_modifier_pair.into_inner(); | ||||||
|  |     if inner.len() == 2 { | ||||||
|  |         FunctionModifier::MutRef | ||||||
|  |     } else { | ||||||
|  |         match inner.next().unwrap().as_rule() { | ||||||
|  |             Rule::Cons => FunctionModifier::Cons, | ||||||
|  |             Rule::Mut => FunctionModifier::Mut, | ||||||
|  |             Rule::Ref => FunctionModifier::Ref, | ||||||
|  |             _ => unreachable!(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_generic_parameters(generic_parameters_pair: Pair<Rule>) -> GenericParameters { | ||||||
|  |     GenericParameters( | ||||||
|  |         generic_parameters_pair | ||||||
|  |             .into_inner() | ||||||
|  |             .map(|identifier_pair| { | ||||||
|  |                 GenericParameter(expect_and_use( | ||||||
|  |                     identifier_pair, | ||||||
|  |                     Rule::Identifier, | ||||||
|  |                     build_identifier, | ||||||
|  |                 )) | ||||||
|  |             }) | ||||||
|  |             .collect(), | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_function_input_arguments(pair: Pair<Rule>) -> InputArguments { | ||||||
|  |     InputArguments( | ||||||
|  |         pair.into_inner() | ||||||
|  |             .map(|function_input_argument_pair| { | ||||||
|  |                 let mut inner = function_input_argument_pair.into_inner(); | ||||||
|  |                 let lhs_pair = inner.next().unwrap(); | ||||||
|  |                 let lhs = match lhs_pair.as_rule() { | ||||||
|  |                     Rule::Delegate => DelegateOrIdentifier::Delegate, | ||||||
|  |                     Rule::Identifier => { | ||||||
|  |                         DelegateOrIdentifier::Identifier(build_identifier(lhs_pair)) | ||||||
|  |                     } | ||||||
|  |                     _ => unreachable!(), | ||||||
|  |                 }; | ||||||
|  |                 let rhs = build_identifier(inner.next().unwrap()); | ||||||
|  |                 InputArgument { lhs, rhs } | ||||||
|  |             }) | ||||||
|  |             .collect(), | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_return_type(return_type_pair: Pair<Rule>) -> ReturnType { | ||||||
|  |     let mut inner = return_type_pair.into_inner(); | ||||||
|  |     
 | ||||||
|  |     let declared_type_pair = inner.next().unwrap(); | ||||||
|  |     let declared_type = match declared_type_pair.as_rule() { | ||||||
|  |         Rule::Void => VoidOrTypeUse::Void, | ||||||
|  |         Rule::TypeUse => VoidOrTypeUse::TypeUse(Box::new( | ||||||
|  |             build_type_use(declared_type_pair) | ||||||
|  |         )), | ||||||
|  |         _ => unreachable!(), | ||||||
|  |     }; | ||||||
|  |     
 | ||||||
|  |     let references = inner.next().map(|ref_list_pair| { | ||||||
|  |         expect_and_use(ref_list_pair, Rule::RefList, build_references) | ||||||
|  |     }).unwrap_or(References(vec![])); | ||||||
|  |     
 | ||||||
|  |     ReturnType { | ||||||
|  |         declared_type, | ||||||
|  |         references, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_references(ref_list_pair: Pair<Rule>) -> References { | ||||||
|  |     let mut identifiers: Vec<Identifier> = vec![]; | ||||||
|  |     for pair in ref_list_pair.into_inner() { | ||||||
|  |         match pair.as_rule() { | ||||||
|  |             Rule::Ref => {}, | ||||||
|  |             Rule::Identifier => { | ||||||
|  |                 identifiers.push(build_identifier(pair)); | ||||||
|  |             }, | ||||||
|  |             _ => unreachable!(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     References(identifiers.into_iter().map(|identifier| Reference(identifier)).collect()) | ||||||
|  | } | ||||||
|  | |||||||
| @ -64,9 +64,7 @@ impl GenericParameters { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct GenericParameter { | pub struct GenericParameter(Identifier); | ||||||
|     identifier: Identifier, |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // Generic arguments
 | // Generic arguments
 | ||||||
| 
 | 
 | ||||||
| @ -86,10 +84,36 @@ pub struct GenericArgument { | |||||||
| 
 | 
 | ||||||
| // Type-use and components
 | // Type-use and components
 | ||||||
| 
 | 
 | ||||||
|  | // #[derive(Debug)]
 | ||||||
|  | // pub struct TypeUse {
 | ||||||
|  | //     pub fqn: Fqn,
 | ||||||
|  | //     pub arguments: Option<TypeArguments>,
 | ||||||
|  | //     pub inputs: Option<InputArguments>,
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct TypeUse { | pub enum TypeUse { | ||||||
|  |     InterfaceOrClass(InterfaceOrClassTypeUse), | ||||||
|  |     Tuple(TupleTypeUse), | ||||||
|  |     Function(FunctionTypeUse), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct InterfaceOrClassTypeUse { | ||||||
|     pub fqn: Fqn, |     pub fqn: Fqn, | ||||||
|     pub arguments: Option<TypeArguments>, |     pub generics: GenericArguments, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct TupleTypeUse(pub Vec<TypeUse>); | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct FunctionTypeUse { | ||||||
|  |     pub function_modifier: Option<FunctionModifier>, | ||||||
|  |     pub generics: GenericParameters, | ||||||
|  |     pub parameters: TupleTypeUse, | ||||||
|  |     pub inputs: InputArguments, | ||||||
|  |     pub return_type: ReturnType, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -110,7 +134,7 @@ impl TupleArguments { | |||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct FunctionTypeArguments { | pub struct FunctionTypeArguments { | ||||||
|     pub parameters: Parameters, |     pub parameters: TupleParameters, | ||||||
|     pub return_type: Box<TypeUse>, |     pub return_type: Box<TypeUse>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -133,10 +157,16 @@ pub struct Parameter { | |||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct ReturnType { | pub struct ReturnType { | ||||||
|     pub type_use: Box<TypeUse>, |     pub declared_type: VoidOrTypeUse, | ||||||
|     pub references: References, |     pub references: References, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub enum VoidOrTypeUse { | ||||||
|  |     Void, | ||||||
|  |     TypeUse(Box<TypeUse>), | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct References(pub Vec<Reference>); | pub struct References(pub Vec<Reference>); | ||||||
| 
 | 
 | ||||||
| @ -147,9 +177,7 @@ impl References { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct Reference { | pub struct Reference(pub Identifier); | ||||||
|     pub identifier: Identifier, |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // Inputs
 | // Inputs
 | ||||||
| 
 | 
 | ||||||
| @ -180,7 +208,7 @@ impl InputArguments { | |||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct InputArgument { | pub struct InputArgument { | ||||||
|     pub lhs: DelegateOrIdentifier, |     pub lhs: DelegateOrIdentifier, | ||||||
|     pub rhs: Identifier |     pub rhs: Identifier, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Where guards
 | // Where guards
 | ||||||
| @ -197,7 +225,7 @@ impl WhereGuards { | |||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct WhereGuard { | pub struct WhereGuard { | ||||||
|     pub identifier: Identifier, |     pub identifier: Identifier, | ||||||
|     pub implements: ImplementsList |     pub implements: ImplementsList, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Implements
 | // Implements
 | ||||||
| @ -389,7 +417,7 @@ pub struct ClassConstructor(pub Vec<ClassConstructorParameter>); | |||||||
| pub struct ClassConstructorParameter { | pub struct ClassConstructorParameter { | ||||||
|     pub is_field: bool, |     pub is_field: bool, | ||||||
|     pub identifier: Identifier, |     pub identifier: Identifier, | ||||||
|     pub declared_type: TypeUse |     pub declared_type: TypeUse, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -469,7 +497,7 @@ pub enum Expression { | |||||||
|     Unary(UnaryExpression), |     Unary(UnaryExpression), | ||||||
|     Assignment(Box<AssignmentExpression>), |     Assignment(Box<AssignmentExpression>), | ||||||
|     Call(CallExpression), |     Call(CallExpression), | ||||||
|     Literal(Literal) |     Literal(Literal), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -494,7 +522,7 @@ pub struct AssignmentExpression { | |||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct CallExpression { | pub struct CallExpression { | ||||||
|     pub callee: Box<Expression>, |     pub callee: Box<Expression>, | ||||||
|     pub arguments: CallArguments |     pub arguments: CallArguments, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
|  | use std::fmt::write; | ||||||
| use crate::ast::*; | use crate::ast::*; | ||||||
| 
 | 
 | ||||||
| macro_rules! to_unparse_vec { | macro_rules! to_unparse_vec { | ||||||
| @ -161,7 +162,7 @@ impl ListUnparse for GenericParameters { | |||||||
| 
 | 
 | ||||||
| impl Unparse for GenericParameter { | impl Unparse for GenericParameter { | ||||||
|     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|         self.identifier.unparse(buf) |         self.0.unparse(buf) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -195,10 +196,58 @@ impl Unparse for GenericArgument { | |||||||
| 
 | 
 | ||||||
| impl Unparse for TypeUse { | impl Unparse for TypeUse { | ||||||
|     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|         self.fqn.unparse(buf)?; |         use TypeUse::*; | ||||||
|         if let Some(type_arguments) = &self.arguments { |         match self { | ||||||
|             type_arguments.unparse(buf)?; |             InterfaceOrClass(interface_or_class_type_use) => interface_or_class_type_use.unparse(buf), | ||||||
|  |             Tuple(tuple_type_use) => tuple_type_use.unparse(buf), | ||||||
|  |             Function(function_type_use) => function_type_use.unparse(buf), | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Unparse for InterfaceOrClassTypeUse { | ||||||
|  |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|  |         self.fqn.unparse(buf)?; | ||||||
|  |         self.generics.unparse(buf)?; | ||||||
|  |         unparse_ok!() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ListUnparse for TupleTypeUse { | ||||||
|  |     fn prefix() -> &'static str { | ||||||
|  |         "(" | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     fn separator() -> &'static str { | ||||||
|  |         ", " | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     fn suffix() -> &'static str { | ||||||
|  |         ")" | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     fn inner(&self) -> Vec<&dyn Unparse> { | ||||||
|  |         to_unparse_vec!(self.0) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Unparse for FunctionTypeUse { | ||||||
|  |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|  |         if let Some(function_modifier) = &self.function_modifier { | ||||||
|  |             function_modifier.unparse(buf)?; | ||||||
|  |         } | ||||||
|  |         write!(buf, " fn ")?; | ||||||
|  |         if !self.generics.is_empty() { | ||||||
|  |             self.generics.unparse(buf)?; | ||||||
|  |             write!(buf, " ")?; | ||||||
|  |         } | ||||||
|  |         self.parameters.unparse(buf)?; | ||||||
|  |         write!(buf, " ")?; | ||||||
|  |         if !self.inputs.is_empty() { | ||||||
|  |             self.inputs.unparse(buf)?; | ||||||
|  |             write!(buf, " ")?; | ||||||
|  |         } | ||||||
|  |         self.return_type.unparse(buf)?; | ||||||
|         unparse_ok!() |         unparse_ok!() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -273,7 +322,7 @@ impl Unparse for Parameter { | |||||||
| impl Unparse for ReturnType { | impl Unparse for ReturnType { | ||||||
|     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|         write!(buf, "-> ")?; |         write!(buf, "-> ")?; | ||||||
|         self.type_use.unparse(buf)?; |         self.declared_type.unparse(buf)?; | ||||||
|         if !self.references.is_empty() { |         if !self.references.is_empty() { | ||||||
|             self.references.unparse(buf)?; |             self.references.unparse(buf)?; | ||||||
|         } |         } | ||||||
| @ -281,6 +330,16 @@ impl Unparse for ReturnType { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl Unparse for VoidOrTypeUse { | ||||||
|  |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|  |         use VoidOrTypeUse::*; | ||||||
|  |         match self { | ||||||
|  |             Void => write!(buf, "Void"), | ||||||
|  |             TypeUse(type_use) => type_use.unparse(buf), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl ListUnparse for References { | impl ListUnparse for References { | ||||||
|     fn prefix() -> &'static str { |     fn prefix() -> &'static str { | ||||||
|         "ref " |         "ref " | ||||||
| @ -297,7 +356,7 @@ impl ListUnparse for References { | |||||||
| 
 | 
 | ||||||
| impl Unparse for Reference { | impl Unparse for Reference { | ||||||
|     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { |     fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { | ||||||
|         self.identifier.unparse(buf) |         self.0.unparse(buf) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| use crate::ast::{ | use crate::ast::{ | ||||||
|     AssignExpression, BlockStatement, CallExpression, CompilationUnit, Declaration, Expression, |     AssignExpression, BlockStatement, CallExpression, CompilationUnit, Expression, Fqn, | ||||||
|     Fqn, FunctionDeclaration, Identifier, LValue, Statement, |     FunctionDeclaration, Identifier, LValue, ModuleLevelDeclaration, Statement, | ||||||
| }; | }; | ||||||
| use crate::object_file::{DvmObjectFile, DvmPath}; | use crate::object_file::{DvmObjectFile, DvmPath}; | ||||||
| use crate::vm::function::DvmFunction; | use crate::vm::function::DvmFunction; | ||||||
| @ -153,7 +153,7 @@ pub fn convert(file_name: &str, ast: CompilationUnit) -> DvmObjectFile { | |||||||
| 
 | 
 | ||||||
|     for declaration in ast.declarations() { |     for declaration in ast.declarations() { | ||||||
|         match declaration { |         match declaration { | ||||||
|             Declaration::Function(function_declaration) => { |             ModuleLevelDeclaration::Function(function_declaration) => { | ||||||
|                 let function = convert_static_function(&state, &context, function_declaration); |                 let function = convert_static_function(&state, &context, function_declaration); | ||||||
|                 object_file.add_function(function); |                 object_file.add_function(function); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -123,13 +123,39 @@ IdentifierChar = { | |||||||
| // Parameters = declaration | // Parameters = declaration | ||||||
| 
 | 
 | ||||||
| TypeUse = { | TypeUse = { | ||||||
|  |       InterfaceOrClassTypeUse | ||||||
|  |     | TupleTypeUse | ||||||
|  |     | FunctionTypeUse | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | InterfaceOrClassTypeUse = { | ||||||
|       FullyQualifiedName |       FullyQualifiedName | ||||||
|  |     ~ GenericArguments? | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TupleTypeUse = { | ||||||
|  |       "(" | ||||||
|     ~ ( |     ~ ( | ||||||
|           GenericArguments ~ InputArguments? |         TypeUse | ||||||
|         | TupleGenericArguments |         ~ ( "," ~ TypeUse )* | ||||||
|         | FunctionGenericArguments ~ FunctionInputArguments? |  | ||||||
|         | InputArguments |  | ||||||
|       )? |       )? | ||||||
|  |     ~ ")" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FunctionTypeUse = { | ||||||
|  |       FunctionTypeModifier? | ||||||
|  |     ~ Fn | ||||||
|  |     ~ GenericParameters? | ||||||
|  |     ~ TupleTypeUse | ||||||
|  |     ~ FunctionInputArguments? | ||||||
|  |     ~ ReturnType | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FunctionTypeModifier = { | ||||||
|  |       Cons | ||||||
|  |     | Mut ~ Ref | ||||||
|  |     | Mut | ||||||
|  |     | Ref | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| GenericArguments = { | GenericArguments = { | ||||||
| @ -153,27 +179,6 @@ InputArgument = { | |||||||
|     ~ ( "=" ~ Identifier ) |     ~ ( "=" ~ Identifier ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TupleGenericArguments = { |  | ||||||
|       "(" |  | ||||||
|     ~ ( |  | ||||||
|         FullyQualifiedName |  | ||||||
|         ~ ( "," ~ FullyQualifiedName )* |  | ||||||
|       )? |  | ||||||
|     ~ ")" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| FunctionGenericArguments = { |  | ||||||
|       TupleGenericArguments |  | ||||||
|     ~ ReturnTypeGenericArgument |  | ||||||
|     ~ FunctionInputArguments? |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ReturnTypeGenericArgument = { |  | ||||||
|       "->" |  | ||||||
|     ~ ( Void | FullyQualifiedName ) |  | ||||||
|     ~ RefList? |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| RefList = { | RefList = { | ||||||
|       Ref |       Ref | ||||||
|     ~ Identifier |     ~ Identifier | ||||||
| @ -522,7 +527,7 @@ Field = { | |||||||
| FunctionModifier = { | FunctionModifier = { | ||||||
|       Static |       Static | ||||||
|     | Cons |     | Cons | ||||||
|     | Mut? Ref? |     | Mut? ~ Ref? | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FunctionDefinition = { | FunctionDefinition = { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jesse Brault
						Jesse Brault