AST API compiles
This commit is contained in:
@@ -17,13 +17,50 @@
|
||||
use std::{convert::Infallible, fmt::Display, str::FromStr, sync::Arc};
|
||||
|
||||
use ir::EnumParse;
|
||||
use strum::EnumIter;
|
||||
use strum::{EnumDiscriminants, EnumIter};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
// TODO: migrate AST logic (after redesigning grammar)
|
||||
// TODO: AST unit tests? executing on examples may be sufficient
|
||||
|
||||
/// Retrieves, but does not parse, all top-level items in a file.
|
||||
// TODO: is `Vec` the most efficient to incrementally update here?
|
||||
#[salsa::tracked]
|
||||
pub fn items<'db>(db: &'db dyn Database, file: workspace::File) -> Vec<ItemMeta<'db>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Parses an [ItemMeta] into its corresponding [Item].
|
||||
pub fn item<'db>(db: &'db dyn Database, meta: ItemMeta<'db>) -> WithAst<Item<'db>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Common information on top-level items.
|
||||
#[salsa::tracked]
|
||||
pub struct ItemMeta<'db> {
|
||||
/// Documentation comments on this item.
|
||||
pub docs: Vec<AstNode>,
|
||||
|
||||
/// The AST node of the item itself.
|
||||
pub ast: AstNode,
|
||||
|
||||
/// The kind of item this is.
|
||||
pub kind: ItemKind,
|
||||
}
|
||||
|
||||
/// The contents of a top-level item.
|
||||
#[derive(EnumDiscriminants)]
|
||||
#[strum_discriminants(name(ItemKind))]
|
||||
#[strum_discriminants(derive(Hash))]
|
||||
pub enum Item<'db> {
|
||||
TypeAlias(TypeAlias<'db>),
|
||||
Import,
|
||||
Relation(Relation<'db>),
|
||||
Rule,
|
||||
Assumption,
|
||||
}
|
||||
|
||||
/// Parse an expression from the AST.
|
||||
#[salsa::tracked]
|
||||
pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
@@ -32,12 +69,12 @@ pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
// parse the kind depending on which field is selected
|
||||
let kind = if let Some(tuple) = ast.get_field(db, "tuple") {
|
||||
let els = tuple.get_fields(db, "el").map(|el| expr(db, el)).collect();
|
||||
ExprKind::Extra(ExprExtra::Tuple(els))
|
||||
ExprKind::Extra(Arc::new(ExprExtra::Tuple(els)))
|
||||
} else if let Some(val) = ast.get_field(db, "value") {
|
||||
ExprKind::Value(parse_value(db, val))
|
||||
ExprKind::Value(value(db, val))
|
||||
} else if let Some(var) = ast.get_field(db, "variable") {
|
||||
let name = var.contents(db).to_string();
|
||||
ExprKind::Extra(ExprExtra::VariableName(name))
|
||||
ExprKind::Extra(Arc::new(ExprExtra::VariableName(name)))
|
||||
} else if let Some(binary) = ast.get_field(db, "binary") {
|
||||
let op = binary.expect_field(db, "op").expect_parse(db);
|
||||
let lhs = Arc::new(expr(db, binary.expect_field(db, "lhs")));
|
||||
@@ -51,7 +88,7 @@ pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
let head = atom.expect_field(db, "head");
|
||||
let head = WithAst::new(head, head.contents(db).to_string());
|
||||
let body = expr(db, atom.expect_field(db, "body"));
|
||||
ExprKind::Extra(ExprExtra::Atom { head, body })
|
||||
ExprKind::Extra(Arc::new(ExprExtra::Atom { head, body }))
|
||||
} else if let Some(parens) = ast.get_field(db, "parens") {
|
||||
return expr(db, parens);
|
||||
} else {
|
||||
@@ -62,6 +99,27 @@ pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
Expr { meta: ast, kind }
|
||||
}
|
||||
|
||||
/// Parses a value from an AST.
|
||||
fn value(db: &dyn Database, ast: AstNode) -> ir::Value {
|
||||
use ir::Value::*;
|
||||
if ast.get_field(db, "true").is_some() {
|
||||
Boolean(true)
|
||||
} else if ast.get_field(db, "false").is_some() {
|
||||
Boolean(false)
|
||||
} else if let Some(sym) = ast.get_field(db, "symbol") {
|
||||
todo!()
|
||||
} else {
|
||||
let int = ast.expect_field(db, "integer");
|
||||
match int.contents(db).to_string().parse() {
|
||||
Ok(val) => Integer(val),
|
||||
Err(_) => {
|
||||
diagnostic::SimpleError::new(int, "failed to parse integer literal").accumulate(db);
|
||||
Integer(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A type alias for parse stage [Expr].
|
||||
pub type Expr = ir::Expr<AstProgramInfo>;
|
||||
|
||||
@@ -77,7 +135,7 @@ impl ir::ProgramInfo for AstProgramInfo {
|
||||
type ExprMeta = AstNode;
|
||||
type BinaryOp = BinaryOpKind;
|
||||
type UnaryOp = ir::UnaryOpKind;
|
||||
type ExprExtra = ExprExtra;
|
||||
type ExprExtra = Arc<ExprExtra>;
|
||||
}
|
||||
|
||||
/// Extra [ExprKind] variants in the parse stage.
|
||||
|
||||
Reference in New Issue
Block a user