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;
|
||||||
@ -1690,7 +1750,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"})
|
"})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_with_call_condition() {
|
fn if_with_call_condition() {
|
||||||
assert_builds(indoc! {"
|
assert_builds(indoc! {"
|
||||||
@ -1701,7 +1761,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"})
|
"})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn while_with_call_condition() {
|
fn while_with_call_condition() {
|
||||||
assert_builds(indoc! {"
|
assert_builds(indoc! {"
|
||||||
@ -1712,7 +1772,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"})
|
"})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn for_with_call_iterator() {
|
fn for_with_call_iterator() {
|
||||||
assert_builds(indoc! {"
|
assert_builds(indoc! {"
|
||||||
@ -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) => {{
|
||||||
@ -147,37 +147,58 @@ mod deimos_parser_tests {
|
|||||||
}"},
|
}"},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn while_statement() {
|
fn while_statement() {
|
||||||
parses_to(Rule::WhileStatement, "while (foo) { bar() }");
|
parses_to(Rule::WhileStatement, "while (foo) { bar() }");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn for_statement() {
|
fn for_statement() {
|
||||||
parses_to(Rule::ForStatement, "for (foo in bar) { baz(foo); }");
|
parses_to(Rule::ForStatement, "for (foo in bar) { baz(foo); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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]
|
||||||
fn while_statement_with_call_condition() {
|
fn while_statement_with_call_condition() {
|
||||||
parses_to(Rule::WhileStatement, "while (foo()) { bar(); }")
|
parses_to(Rule::WhileStatement, "while (foo()) { bar(); }")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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