Add use statements.
This commit is contained in:
		
							parent
							
								
									0c18b976d7
								
							
						
					
					
						commit
						938391ae09
					
				
							
								
								
									
										3
									
								
								sketching/may_2025/use.dm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								sketching/may_2025/use.dm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | use std::core::println; | ||||||
|  | use std::core::*; | ||||||
|  | use std::core::{print, println}; | ||||||
| @ -15,7 +15,11 @@ fn expect_and_use<T>( | |||||||
|     f(file_id, pair) |     f(file_id, pair) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn build_ast(file_name: &str, file_id: usize, compilation_unit_pair: Pair<Rule>) -> CompilationUnit { | pub fn build_ast( | ||||||
|  |     file_name: &str, | ||||||
|  |     file_id: usize, | ||||||
|  |     compilation_unit_pair: Pair<Rule>, | ||||||
|  | ) -> CompilationUnit { | ||||||
|     build_compilation_unit(file_name, file_id, compilation_unit_pair) |     build_compilation_unit(file_name, file_id, compilation_unit_pair) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -293,8 +297,13 @@ fn build_references(file_id: usize, ref_list_pair: Pair<Rule>) -> References { | |||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn build_compilation_unit(file_name: &str, file_id: usize, compilation_unit_pair: Pair<Rule>) -> CompilationUnit { | fn build_compilation_unit( | ||||||
|  |     file_name: &str, | ||||||
|  |     file_id: usize, | ||||||
|  |     compilation_unit_pair: Pair<Rule>, | ||||||
|  | ) -> CompilationUnit { | ||||||
|     let mut namespace = None; |     let mut namespace = None; | ||||||
|  |     let mut use_statements = vec![]; | ||||||
|     let mut declarations = vec![]; |     let mut declarations = vec![]; | ||||||
| 
 | 
 | ||||||
|     for inner_pair in compilation_unit_pair.into_inner() { |     for inner_pair in compilation_unit_pair.into_inner() { | ||||||
| @ -302,10 +311,13 @@ fn build_compilation_unit(file_name: &str, file_id: usize, compilation_unit_pair | |||||||
|             Rule::Namespace => { |             Rule::Namespace => { | ||||||
|                 namespace = Some(build_namespace(file_id, inner_pair)); |                 namespace = Some(build_namespace(file_id, inner_pair)); | ||||||
|             } |             } | ||||||
|  |             Rule::UseStatement => { | ||||||
|  |                 use_statements.push(build_use_statement(file_id, inner_pair)); | ||||||
|  |             } | ||||||
|             Rule::ModuleLevelDeclaration => { |             Rule::ModuleLevelDeclaration => { | ||||||
|                 declarations.push(build_module_level_declaration(file_id, inner_pair)); |                 declarations.push(build_module_level_declaration(file_id, inner_pair)); | ||||||
|             } |             } | ||||||
|             Rule::EOI => {} |             Rule::Semicolon | Rule::EOI => {} | ||||||
|             _ => unreachable!(), |             _ => unreachable!(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -314,6 +326,7 @@ fn build_compilation_unit(file_name: &str, file_id: usize, compilation_unit_pair | |||||||
|         file_name: file_name.to_string(), |         file_name: file_name.to_string(), | ||||||
|         file_id, |         file_id, | ||||||
|         namespace, |         namespace, | ||||||
|  |         use_statements, | ||||||
|         declarations, |         declarations, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -741,6 +754,53 @@ fn build_field_declaration(file_id: usize, field_pair: Pair<Rule>) -> FieldDecla | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement { | ||||||
|  |     let mut inner = use_statement_pair.into_inner(); | ||||||
|  |     let inner_length = inner.len(); | ||||||
|  | 
 | ||||||
|  |     inner.next().unwrap(); // use
 | ||||||
|  | 
 | ||||||
|  |     let mut identifiers = vec![]; | ||||||
|  |     let mut last = None; | ||||||
|  | 
 | ||||||
|  |     for (i, inner_pair) in inner.into_iter().enumerate() { | ||||||
|  |         if i != inner_length - 2 { | ||||||
|  |             identifiers.push(expect_and_use( | ||||||
|  |                 file_id, | ||||||
|  |                 inner_pair, | ||||||
|  |                 Rule::Identifier, | ||||||
|  |                 build_identifier, | ||||||
|  |             )) | ||||||
|  |         } else { | ||||||
|  |             last = Some(match inner_pair.as_rule() { | ||||||
|  |                 Rule::Identifier => { | ||||||
|  |                     UseStatementLast::Identifier(build_identifier(file_id, inner_pair)) | ||||||
|  |                 } | ||||||
|  |                 Rule::Star => UseStatementLast::Star, | ||||||
|  |                 Rule::UseList => UseStatementLast::Identifiers( | ||||||
|  |                     inner_pair | ||||||
|  |                         .into_inner() | ||||||
|  |                         .map(|identifier_pair| { | ||||||
|  |                             expect_and_use( | ||||||
|  |                                 file_id, | ||||||
|  |                                 identifier_pair, | ||||||
|  |                                 Rule::Identifier, | ||||||
|  |                                 build_identifier, | ||||||
|  |                             ) | ||||||
|  |                         }) | ||||||
|  |                         .collect(), | ||||||
|  |                 ), | ||||||
|  |                 _ => unreachable!(), | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     UseStatement { | ||||||
|  |         identifiers, | ||||||
|  |         last: last.unwrap(), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn build_block_statement(file_id: usize, block_statement_pair: Pair<Rule>) -> BlockStatement { | fn build_block_statement(file_id: usize, block_statement_pair: Pair<Rule>) -> BlockStatement { | ||||||
|     let mut statements = vec![]; |     let mut statements = vec![]; | ||||||
|     let mut expression = None; |     let mut expression = None; | ||||||
| @ -1723,4 +1783,19 @@ mod tests { | |||||||
|             } |             } | ||||||
|         "})
 |         "})
 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_statement() { | ||||||
|  |         assert_builds("use std::core::println;"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_star() { | ||||||
|  |         assert_builds("use std::core::*;"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_list() { | ||||||
|  |         assert_builds("use std::core::{print, println};"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -290,6 +290,7 @@ pub struct CompilationUnit { | |||||||
|     pub file_name: String, |     pub file_name: String, | ||||||
|     pub file_id: usize, |     pub file_id: usize, | ||||||
|     pub namespace: Option<FullyQualifiedName>, |     pub namespace: Option<FullyQualifiedName>, | ||||||
|  |     pub use_statements: Vec<UseStatement>, | ||||||
|     pub declarations: Vec<ModuleLevelDeclaration>, |     pub declarations: Vec<ModuleLevelDeclaration>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -450,6 +451,19 @@ pub struct FieldDeclaration { | |||||||
| 
 | 
 | ||||||
| // Statements
 | // Statements
 | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct UseStatement { | ||||||
|  |     pub identifiers: Vec<Identifier>, | ||||||
|  |     pub last: UseStatementLast | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub enum UseStatementLast { | ||||||
|  |     Identifier(Identifier), | ||||||
|  |     Identifiers(Vec<Identifier>), | ||||||
|  |     Star, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct BlockStatement { | pub struct BlockStatement { | ||||||
|     pub statements: Vec<Statement>, |     pub statements: Vec<Statement>, | ||||||
|  | |||||||
| @ -282,6 +282,9 @@ impl PrettyPrint for CompilationUnit { | |||||||
|             namespace.pretty_print(writer)?; |             namespace.pretty_print(writer)?; | ||||||
|             writer.decrease_indent(); |             writer.decrease_indent(); | ||||||
|         } |         } | ||||||
|  |         for use_statement in &self.use_statements { | ||||||
|  |             use_statement.pretty_print(writer)?; | ||||||
|  |         } | ||||||
|         for declaration in &self.declarations { |         for declaration in &self.declarations { | ||||||
|             declaration.pretty_print(writer)?; |             declaration.pretty_print(writer)?; | ||||||
|         } |         } | ||||||
| @ -585,6 +588,39 @@ impl PrettyPrint for FieldDeclaration { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl PrettyPrint for UseStatement { | ||||||
|  |     fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { | ||||||
|  |         writer.writeln_indented("UseStatement")?; | ||||||
|  |         writer.increase_indent(); | ||||||
|  |         for identifier in &self.identifiers { | ||||||
|  |             identifier.pretty_print(writer)?; | ||||||
|  |         } | ||||||
|  |         self.last.pretty_print(writer)?; | ||||||
|  |         writer.decrease_indent(); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PrettyPrint for UseStatementLast { | ||||||
|  |     fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { | ||||||
|  |         writer.writeln_indented("UseStatementLast")?; | ||||||
|  |         writer.increase_indent(); | ||||||
|  |         match self { | ||||||
|  |             UseStatementLast::Identifier(i) => i.pretty_print(writer)?, | ||||||
|  |             UseStatementLast::Identifiers(is) => { | ||||||
|  |                 for i in is { | ||||||
|  |                     i.pretty_print(writer)?; | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             UseStatementLast::Star => { | ||||||
|  |                 writer.writeln_indented("Star")?; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         writer.decrease_indent(); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl PrettyPrint for BlockStatement { | impl PrettyPrint for BlockStatement { | ||||||
|     fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { |     fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { | ||||||
|         writer.writeln_indented("BlockStatement")?; |         writer.writeln_indented("BlockStatement")?; | ||||||
|  | |||||||
| @ -373,7 +373,11 @@ impl Unparse for CompilationUnit { | |||||||
|         if let Some(namespace) = &self.namespace { |         if let Some(namespace) = &self.namespace { | ||||||
|             writer.write("ns ")?; |             writer.write("ns ")?; | ||||||
|             namespace.unparse(writer)?; |             namespace.unparse(writer)?; | ||||||
|             writer.write("\n\n")?; |             writer.write(";\n\n")?; | ||||||
|  |         } | ||||||
|  |         for use_statement in &self.use_statements { | ||||||
|  |             use_statement.unparse(writer)?; | ||||||
|  |             writer.write(";\n")?; | ||||||
|         } |         } | ||||||
|         unparse_list(writer, "\n\n", &to_unparse_vec!(self.declarations))?; |         unparse_list(writer, "\n\n", &to_unparse_vec!(self.declarations))?; | ||||||
|         Ok(()) |         Ok(()) | ||||||
| @ -722,6 +726,41 @@ impl Unparse for FieldDeclaration { | |||||||
| 
 | 
 | ||||||
| /* Statements */ | /* Statements */ | ||||||
| 
 | 
 | ||||||
|  | impl Unparse for UseStatement { | ||||||
|  |     fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> { | ||||||
|  |         writer.write_indented("use ")?; | ||||||
|  |         for (i, identifier) in self.identifiers.iter().enumerate() { | ||||||
|  |             identifier.unparse(writer)?; | ||||||
|  |             if i != self.identifiers.len() - 2 { | ||||||
|  |                 // 2 because of use
 | ||||||
|  |                 writer.write("::")?; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         self.last.unparse(writer)?; | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Unparse for UseStatementLast { | ||||||
|  |     fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> { | ||||||
|  |         match self { | ||||||
|  |             UseStatementLast::Star => writer.write("*"), | ||||||
|  |             UseStatementLast::Identifiers(identifiers) => { | ||||||
|  |                 writer.write("{")?; | ||||||
|  |                 for (i, identifier) in identifiers.iter().enumerate() { | ||||||
|  |                     identifier.unparse(writer)?; | ||||||
|  |                     if i != identifiers.len() - 1 { | ||||||
|  |                         writer.write(", ")?; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 writer.write("}")?; | ||||||
|  |                 Ok(()) | ||||||
|  |             } | ||||||
|  |             UseStatementLast::Identifier(i) => i.unparse(writer), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl Unparse for BlockStatement { | impl Unparse for BlockStatement { | ||||||
|     fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> { |     fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> { | ||||||
|         writer.writeln_indented("{")?; |         writer.writeln_indented("{")?; | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ Move = { "move" } | |||||||
| Alias = { "alias" } | Alias = { "alias" } | ||||||
| True = { "true" } | True = { "true" } | ||||||
| False = { "false" } | False = { "false" } | ||||||
|  | Use = { "use" } | ||||||
| 
 | 
 | ||||||
| // Keywords as a rule (for preventing identifiers with keywords, etc.) | // Keywords as a rule (for preventing identifiers with keywords, etc.) | ||||||
| Keyword = { | Keyword = { | ||||||
| @ -64,6 +65,7 @@ Keyword = { | |||||||
|     | Alias |     | Alias | ||||||
|     | True |     | True | ||||||
|     | False |     | False | ||||||
|  |     | Use | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Symbols | // Symbols | ||||||
| @ -280,7 +282,8 @@ RefList = { | |||||||
| 
 | 
 | ||||||
| CompilationUnit = { | CompilationUnit = { | ||||||
|       SOI |       SOI | ||||||
|     ~ Namespace? |     ~ ( Namespace ~ Semicolon )? | ||||||
|  |     ~ ( UseStatement ~ Semicolon )* | ||||||
|     ~ ModuleLevelDeclaration* |     ~ ModuleLevelDeclaration* | ||||||
|     ~ EOI |     ~ EOI | ||||||
| } | } | ||||||
| @ -479,6 +482,20 @@ Field = { | |||||||
| 
 | 
 | ||||||
| // Statements | // Statements | ||||||
| 
 | 
 | ||||||
|  | UseStatement = { | ||||||
|  |       Use | ||||||
|  |     ~ Identifier | ||||||
|  |     ~ ( "::" ~ Identifier )* | ||||||
|  |     ~ ( "::" ~ ( Star | UseList ) )? | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | UseList = { | ||||||
|  |       "{" | ||||||
|  |     ~ Identifier | ||||||
|  |     ~ ( "," ~ Identifier )* | ||||||
|  |     ~ "}" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BlockStatement = { | BlockStatement = { | ||||||
|       "{" |       "{" | ||||||
|     ~ Statement* |     ~ Statement* | ||||||
| @ -492,6 +509,7 @@ Statement = { | |||||||
|         | AssignmentStatement |         | AssignmentStatement | ||||||
|         | CallStatement |         | CallStatement | ||||||
|         | ReturnStatement |         | ReturnStatement | ||||||
|  |         | UseStatement | ||||||
|       ) |       ) | ||||||
|     ~ Semicolon |     ~ Semicolon | ||||||
|     | ( |     | ( | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ pub struct DeimosParser; | |||||||
| mod deimos_parser_tests { | mod deimos_parser_tests { | ||||||
|     use crate::parser::{DeimosParser, Rule}; |     use crate::parser::{DeimosParser, Rule}; | ||||||
|     use indoc::indoc; |     use indoc::indoc; | ||||||
|     use pest::{parses_to, Parser}; |     use pest::Parser; | ||||||
| 
 | 
 | ||||||
|     macro_rules! fail_rule { |     macro_rules! fail_rule { | ||||||
|         ($pair: expr; $rule:path) => {{ |         ($pair: expr; $rule:path) => {{ | ||||||
| @ -160,11 +160,14 @@ mod deimos_parser_tests { | |||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn if_statement_with_call_condition() { |     fn if_statement_with_call_condition() { | ||||||
|         parses_to(Rule::IfStatement, indoc! {" |         parses_to( | ||||||
|  |             Rule::IfStatement, | ||||||
|  |             indoc! {" | ||||||
|             if (foo()) { |             if (foo()) { | ||||||
|                 bar() |                 bar() | ||||||
|             } |             } | ||||||
|         "})
 |         "},
 | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -174,10 +177,28 @@ mod deimos_parser_tests { | |||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn for_statement_with_call_iterator() { |     fn for_statement_with_call_iterator() { | ||||||
|         parses_to(Rule::ForStatement, indoc! {" |         parses_to( | ||||||
|  |             Rule::ForStatement, | ||||||
|  |             indoc! {" | ||||||
|             for (foo in bar()) { |             for (foo in bar()) { | ||||||
|                 baz(foo); |                 baz(foo); | ||||||
|             } |             } | ||||||
|         "})
 |         "},
 | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_statement() { | ||||||
|  |         parses_to(Rule::UseStatement, "use std::core::println"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_star() { | ||||||
|  |         parses_to(Rule::UseStatement, "use std::core::*") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn use_list() { | ||||||
|  |         parses_to(Rule::UseStatement, "use std::core::{print, println}"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jesse Brault
						Jesse Brault