Refactor UseStatement to an enum type; remove UseStatementLast.
This commit is contained in:
parent
9f5e27b289
commit
6f727e1cdf
@ -427,29 +427,37 @@ fn build_namespace(file_id: usize, namespace_pair: Pair<Rule>) -> FullyQualified
|
||||
|
||||
fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement {
|
||||
let as_span = use_statement_pair.as_span();
|
||||
let range = Range {
|
||||
start: as_span.start(),
|
||||
end: as_span.end(),
|
||||
};
|
||||
|
||||
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;
|
||||
let mut prefixes = vec![];
|
||||
let mut built: Option<UseStatement> = None;
|
||||
|
||||
for (i, inner_pair) in inner.into_iter().enumerate() {
|
||||
if i != inner_length - 2 {
|
||||
identifiers.push(Box::new(expect_and_use(
|
||||
prefixes.push(inner_pair.as_str());
|
||||
} else {
|
||||
built = Some(match inner_pair.as_rule() {
|
||||
Rule::Identifier => UseStatement::Concrete(ConcreteUseStatement::new(
|
||||
prefixes.iter().map(|s| s.to_string()).collect(),
|
||||
vec![Box::new(expect_and_use(
|
||||
file_id,
|
||||
inner_pair,
|
||||
Rule::Identifier,
|
||||
build_identifier,
|
||||
)));
|
||||
} else {
|
||||
last = Some(Box::new(match inner_pair.as_rule() {
|
||||
Rule::Identifier => {
|
||||
UseStatementLast::Identifier(Box::new(build_identifier(file_id, inner_pair)))
|
||||
}
|
||||
Rule::Star => UseStatementLast::Star,
|
||||
Rule::UseList => UseStatementLast::Identifiers(
|
||||
))],
|
||||
file_id,
|
||||
range,
|
||||
)),
|
||||
Rule::UseList => UseStatement::Concrete(ConcreteUseStatement::new(
|
||||
prefixes.iter().map(|s| s.to_string()).collect(),
|
||||
inner_pair
|
||||
.into_inner()
|
||||
.map(|identifier_pair| {
|
||||
@ -461,21 +469,20 @@ fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseSta
|
||||
))
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
file_id,
|
||||
range,
|
||||
)),
|
||||
Rule::Star => UseStatement::Star(StarUseStatement::new(
|
||||
prefixes.iter().map(|s| s.to_string()).collect(),
|
||||
file_id,
|
||||
range,
|
||||
)),
|
||||
_ => unreachable!(),
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
UseStatement::new(
|
||||
identifiers,
|
||||
last.unwrap(),
|
||||
file_id,
|
||||
Range {
|
||||
start: as_span.start(),
|
||||
end: as_span.end(),
|
||||
},
|
||||
)
|
||||
built.unwrap()
|
||||
}
|
||||
|
||||
fn build_module_level_declaration(file_id: usize, pair: Pair<Rule>) -> ModuleLevelDeclaration {
|
||||
|
@ -319,21 +319,14 @@ impl NodeInner for CompilationUnit {
|
||||
impl NodeInner for UseStatement {
|
||||
fn children(&self) -> Vec<NodeRef> {
|
||||
let mut children = vec![];
|
||||
children.extend(
|
||||
self.identifiers()
|
||||
match self {
|
||||
UseStatement::Concrete(concrete_use_statement) => children.extend(
|
||||
concrete_use_statement
|
||||
.identifiers()
|
||||
.iter()
|
||||
.map(|identifier| NodeRef::Identifier(*identifier)),
|
||||
);
|
||||
match self.last() {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
children.push(NodeRef::Identifier(identifier))
|
||||
}
|
||||
UseStatementLast::Identifiers(identifiers) => children.extend(
|
||||
identifiers
|
||||
.iter()
|
||||
.map(|identifier| NodeRef::Identifier(identifier.clone())),
|
||||
.map(|identifier| NodeRef::Identifier(*identifier))
|
||||
),
|
||||
UseStatementLast::Star => {}
|
||||
UseStatement::Star(_) => {}
|
||||
}
|
||||
children
|
||||
}
|
||||
|
@ -1,75 +1,48 @@
|
||||
use crate::ast::node::named::Named;
|
||||
use crate::ast::node::names::Identifier;
|
||||
use std::borrow::Cow;
|
||||
use std::range::Range;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UseStatement {
|
||||
pub enum UseStatement {
|
||||
Concrete(ConcreteUseStatement),
|
||||
Star(StarUseStatement),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConcreteUseStatement {
|
||||
prefixes: Vec<String>,
|
||||
identifiers: Vec<Box<Identifier>>,
|
||||
last: Box<UseStatementLast>,
|
||||
file_id: usize,
|
||||
range: Range<usize>,
|
||||
}
|
||||
|
||||
impl UseStatement {
|
||||
impl ConcreteUseStatement {
|
||||
pub fn new(
|
||||
prefixes: Vec<String>,
|
||||
identifiers: Vec<Box<Identifier>>,
|
||||
last: Box<UseStatementLast>,
|
||||
file_id: usize,
|
||||
range: Range<usize>,
|
||||
) -> Self {
|
||||
UseStatement {
|
||||
ConcreteUseStatement {
|
||||
prefixes,
|
||||
identifiers,
|
||||
last,
|
||||
file_id,
|
||||
range,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_name(&self) -> Cow<'_, str> {
|
||||
use UseStatementLast::*;
|
||||
if self.identifiers.is_empty() {
|
||||
match self.last.as_ref() {
|
||||
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 prefixes(&self) -> &Vec<String> {
|
||||
&self.prefixes
|
||||
}
|
||||
|
||||
pub fn is_star(&self) -> bool {
|
||||
match self.last.as_ref() {
|
||||
UseStatementLast::Star => true,
|
||||
_ => false,
|
||||
}
|
||||
pub fn join_prefixes(&self) -> String {
|
||||
self.prefixes.join("::")
|
||||
}
|
||||
|
||||
pub fn identifiers(&self) -> Vec<&Identifier> {
|
||||
self.identifiers.iter().map(Box::as_ref).collect()
|
||||
}
|
||||
|
||||
pub fn identifiers_mut(&mut self) -> Vec<&mut Identifier> {
|
||||
self.identifiers.iter_mut().map(Box::as_mut).collect()
|
||||
}
|
||||
|
||||
pub fn last(&self) -> &UseStatementLast {
|
||||
&self.last
|
||||
}
|
||||
|
||||
pub fn last_mut(&mut self) -> &mut UseStatementLast {
|
||||
&mut self.last
|
||||
}
|
||||
|
||||
pub fn file_id(&self) -> usize {
|
||||
self.file_id
|
||||
}
|
||||
@ -80,8 +53,34 @@ impl UseStatement {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UseStatementLast {
|
||||
Identifier(Box<Identifier>),
|
||||
Identifiers(Vec<Box<Identifier>>),
|
||||
Star,
|
||||
pub struct StarUseStatement {
|
||||
prefixes: Vec<String>,
|
||||
file_id: usize,
|
||||
range: Range<usize>,
|
||||
}
|
||||
|
||||
impl StarUseStatement {
|
||||
pub fn new(prefixes: Vec<String>, file_id: usize, range: Range<usize>) -> Self {
|
||||
Self {
|
||||
prefixes,
|
||||
file_id,
|
||||
range,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefixes(&self) -> &Vec<String> {
|
||||
&self.prefixes
|
||||
}
|
||||
|
||||
pub fn join_prefixes(&self) -> String {
|
||||
self.prefixes.join("::")
|
||||
}
|
||||
|
||||
pub fn file_id(&self) -> usize {
|
||||
self.file_id
|
||||
}
|
||||
|
||||
pub fn range(&self) -> Range<usize> {
|
||||
self.range
|
||||
}
|
||||
}
|
||||
|
@ -320,6 +320,28 @@ impl PrettyPrint for CompilationUnit {
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for UseStatement {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.writeln_indented("UseStatement")?;
|
||||
writer.increase_indent();
|
||||
match self {
|
||||
UseStatement::Concrete(concrete_use_statement) => {
|
||||
writer.writeln_indented(&format!("ConcreteUseStatement(prefixes = {})", concrete_use_statement.join_prefixes()))?;
|
||||
writer.increase_indent();
|
||||
for identifier in concrete_use_statement.identifiers() {
|
||||
identifier.pretty_print(writer)?;
|
||||
}
|
||||
writer.decrease_indent();
|
||||
}
|
||||
UseStatement::Star(star_use_statement) => {
|
||||
writer.writeln_indented(&format!("StarUseStatement(prefixes = {})", star_use_statement.join_prefixes()))?;
|
||||
}
|
||||
}
|
||||
writer.decrease_indent();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for ModuleLevelDeclaration {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
use crate::ast::node::level::ModuleLevelDeclaration::*;
|
||||
@ -618,39 +640,6 @@ 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 {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.writeln_indented("BlockStatement")?;
|
||||
|
@ -410,23 +410,13 @@ impl Unparse for CompilationUnit {
|
||||
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) => {
|
||||
UseStatement::Concrete(concrete_use_statement) => {
|
||||
writer.write(&format!("{}::", concrete_use_statement.join_prefixes()))?;
|
||||
let identifiers = concrete_use_statement.identifiers();
|
||||
if identifiers.len() == 1 {
|
||||
identifiers[0].unparse(writer)?;
|
||||
} else {
|
||||
writer.write("{")?;
|
||||
for (i, identifier) in identifiers.iter().enumerate() {
|
||||
identifier.unparse(writer)?;
|
||||
@ -435,11 +425,14 @@ impl Unparse for UseStatementLast {
|
||||
}
|
||||
}
|
||||
writer.write("}")?;
|
||||
}
|
||||
},
|
||||
UseStatement::Star(star_use_statement) => {
|
||||
writer.write(&format!("{}::*", star_use_statement.join_prefixes()))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
UseStatementLast::Identifier(i) => i.unparse(writer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Declarations allowed in each level */
|
||||
|
@ -364,22 +364,8 @@ fn gather_use_statement(
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
if use_statement.is_star() {
|
||||
todo!()
|
||||
}
|
||||
let base_name = use_statement.base_name().to_string();
|
||||
match use_statement.last_mut() {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
handle_use_statement_import(symbol_table, &base_name, identifier, diagnostics)
|
||||
}
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
for identifier in identifiers {
|
||||
handle_use_statement_import(symbol_table, &base_name, identifier, diagnostics)
|
||||
}
|
||||
}
|
||||
UseStatementLast::Star => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
/* Declarations allowed in each level */
|
||||
|
||||
|
@ -56,7 +56,6 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::ast::build::build_ast;
|
||||
use crate::ast::children::NodeRef;
|
||||
use crate::ast::node::use_statement::UseStatementLast;
|
||||
use crate::ast::walk::walk_depth_first;
|
||||
use crate::parser::{DeimosParser, Rule};
|
||||
use crate::std_core::add_std_core_symbols;
|
||||
@ -126,25 +125,7 @@ mod tests {
|
||||
panic!("{:?} does not have a saved symbol.", fqn)
|
||||
}
|
||||
}
|
||||
NodeRef::UseStatement(use_statement) => match use_statement.last() {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
if identifier.saved_symbol().is_none() {
|
||||
panic!(
|
||||
"UseStatement {:?} does not have a saved symbol.",
|
||||
identifier
|
||||
)
|
||||
}
|
||||
}
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
for identifier in identifiers {
|
||||
if identifier.saved_symbol().is_none() {
|
||||
panic!(
|
||||
"UseStatement {:?} does not have a saved symbol.",
|
||||
identifier
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
NodeRef::UseStatement(use_statement) => match use_statement {
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => {}
|
||||
@ -153,35 +134,7 @@ mod tests {
|
||||
|
||||
fn assert_resolved_symbols(compilation_unit: &CompilationUnit) {
|
||||
walk_depth_first(compilation_unit, &mut |node_ref| match node_ref {
|
||||
NodeRef::UseStatement(use_statement) => match use_statement.last() {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
let use_statement_symbol = identifier
|
||||
.saved_symbol()
|
||||
.unwrap()
|
||||
.unwrap_use_statement_symbol();
|
||||
let borrowed = use_statement_symbol.borrow();
|
||||
if borrowed.referenced_symbol().is_none() {
|
||||
panic!(
|
||||
"{:?} does not have a referenced symbol.",
|
||||
use_statement_symbol
|
||||
)
|
||||
}
|
||||
}
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
for identifier in identifiers {
|
||||
let use_statement_symbol = identifier
|
||||
.saved_symbol()
|
||||
.unwrap()
|
||||
.unwrap_use_statement_symbol();
|
||||
let borrowed = use_statement_symbol.borrow();
|
||||
if borrowed.referenced_symbol().is_none() {
|
||||
panic!(
|
||||
"{:?} does not have a referenced symbol.",
|
||||
use_statement_symbol
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
NodeRef::UseStatement(use_statement) => match use_statement {
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => {}
|
||||
|
@ -260,36 +260,7 @@ fn resolve_use_statement(
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let file_id = use_statement.file_id();
|
||||
let use_statement_range = use_statement.range();
|
||||
let base_name = use_statement.base_name().to_string();
|
||||
|
||||
match use_statement.last_mut() {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
handle_use_statement_identifier(
|
||||
identifier.deref_mut(),
|
||||
&base_name,
|
||||
symbol_table,
|
||||
diagnostics,
|
||||
file_id,
|
||||
use_statement_range,
|
||||
);
|
||||
}
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
for identifier in identifiers {
|
||||
let identifier_range = identifier.range();
|
||||
handle_use_statement_identifier(
|
||||
identifier.deref_mut(),
|
||||
&base_name,
|
||||
symbol_table,
|
||||
diagnostics,
|
||||
file_id,
|
||||
identifier_range,
|
||||
)
|
||||
}
|
||||
}
|
||||
UseStatementLast::Star => todo!("star imports"),
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
/* Declarations allowed in each level */
|
||||
|
@ -29,14 +29,6 @@ impl SourceDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(note = "Use identifier instead.")]
|
||||
pub fn from_use_statement(use_statement: &UseStatement) -> Self {
|
||||
SourceDefinition {
|
||||
file_id: use_statement.file_id(),
|
||||
range: use_statement.range(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_id(&self) -> usize {
|
||||
self.file_id
|
||||
}
|
||||
|
@ -333,6 +333,20 @@ Namespace = {
|
||||
~ FullyQualifiedName
|
||||
}
|
||||
|
||||
UseStatement = {
|
||||
Use
|
||||
~ Identifier
|
||||
~ ( "::" ~ Identifier )*
|
||||
~ ( "::" ~ ( Star | UseList ) )?
|
||||
}
|
||||
|
||||
UseList = {
|
||||
"{"
|
||||
~ Identifier
|
||||
~ ( "," ~ Identifier )*
|
||||
~ "}"
|
||||
}
|
||||
|
||||
// Organizational declarations
|
||||
|
||||
ModuleLevelDeclaration = {
|
||||
@ -523,20 +537,6 @@ Field = {
|
||||
|
||||
// Statements
|
||||
|
||||
UseStatement = {
|
||||
Use
|
||||
~ Identifier
|
||||
~ ( "::" ~ Identifier )*
|
||||
~ ( "::" ~ ( Star | UseList ) )?
|
||||
}
|
||||
|
||||
UseList = {
|
||||
"{"
|
||||
~ Identifier
|
||||
~ ( "," ~ Identifier )*
|
||||
~ "}"
|
||||
}
|
||||
|
||||
BlockStatement = {
|
||||
"{"
|
||||
~ Statement*
|
||||
|
Loading…
Reference in New Issue
Block a user