Parse names with paths
This commit is contained in:
@@ -251,7 +251,7 @@ pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
} else if ast.get_field(db, "false").is_some() {
|
||||
Value(Boolean(false))
|
||||
} else if let Some(sym) = ast.get_field(db, "symbol") {
|
||||
todo!()
|
||||
Extra(Arc::new(ExprExtra::SymbolName(name(db, sym))))
|
||||
} else if let Some(int) = ast.get_field(db, "integer") {
|
||||
Value(match int.contents(db).to_string().parse() {
|
||||
Ok(val) => Integer(val),
|
||||
@@ -304,7 +304,7 @@ pub fn aggregate(db: &dyn Database, ast: AstNode) -> Aggregate {
|
||||
|
||||
/// Parses an application operation.
|
||||
pub fn apply(db: &dyn Database, ast: AstNode) -> Apply {
|
||||
let head = ast.expect_field(db, "head").with_contents(db);
|
||||
let head = name(db, ast.expect_field(db, "head"));
|
||||
let body = expr(db, ast.expect_field(db, "body"));
|
||||
Apply { head, body }
|
||||
}
|
||||
@@ -336,7 +336,13 @@ pub enum ExprExtra {
|
||||
/// A structured tuple of sub-expressions.
|
||||
Tuple(Vec<Expr>),
|
||||
|
||||
/// An unresolved symbol name.
|
||||
SymbolName(Name),
|
||||
|
||||
/// An unresolved variable name.
|
||||
///
|
||||
/// Variables are only locally-scoped, so this is represented as a plain
|
||||
/// string, not a [Name] with a full path.
|
||||
VariableName(String),
|
||||
|
||||
/// An abstract application expression.
|
||||
@@ -373,12 +379,42 @@ pub enum AggregateBody {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Apply {
|
||||
/// The name of the relation to query or function to invoke.
|
||||
pub head: WithAst<String>,
|
||||
pub head: Name,
|
||||
|
||||
/// The parameters to the function or query.
|
||||
pub body: Expr,
|
||||
}
|
||||
|
||||
/// Parses a name.
|
||||
#[salsa::tracked]
|
||||
pub fn name(db: &dyn Database, ast: AstNode) -> Name {
|
||||
Name {
|
||||
ast,
|
||||
path: ast
|
||||
.get_fields(db, "path")
|
||||
.map(|ast| ast.with_contents(db))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A named reference to some object.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Name {
|
||||
/// The AST node of the name.
|
||||
pub ast: AstNode,
|
||||
|
||||
/// The segments of the path to the object.
|
||||
pub path: Vec<WithAst<String>>,
|
||||
}
|
||||
|
||||
impl Display for Name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let segments = self.path.iter().cloned().map(|ast| ast.inner);
|
||||
let path = segments.collect::<Vec<_>>().join(".");
|
||||
write!(f, "{path}")
|
||||
}
|
||||
}
|
||||
|
||||
/// Extends [ir::BinaryOpKind] with the omitted operators to preserve syntax.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum BinaryOpKind {
|
||||
@@ -465,7 +501,7 @@ impl ir::EnumRepr for RedundantBinaryOpKind {
|
||||
/// Parses a type.
|
||||
pub fn ty(db: &dyn Database, ast: AstNode) -> WithAst<Type> {
|
||||
ast.with(if let Some(ast) = ast.get_field(db, "named") {
|
||||
Type::Named(ast.contents(db).to_string())
|
||||
Type::Named(name(db, ast))
|
||||
} else {
|
||||
Type::Tuple(ast.get_fields(db, "tuple").map(|ast| ty(db, ast)).collect())
|
||||
})
|
||||
@@ -477,7 +513,7 @@ pub fn ty(db: &dyn Database, ast: AstNode) -> WithAst<Type> {
|
||||
/// dereferencing any aliases or checking semantic validity.
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Type {
|
||||
Named(String),
|
||||
Named(Name),
|
||||
Tuple(Vec<WithAst<Type>>),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user