diff --git a/crates/frontend/src/ast.rs b/crates/frontend/src/ast.rs index b677117..94d6ff6 100644 --- a/crates/frontend/src/ast.rs +++ b/crates/frontend/src/ast.rs @@ -22,18 +22,63 @@ 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> { - todo!() + // track running documentation comments + let mut docs = Vec::new(); + + // iterate over each top-level AST node + let mut items = Vec::new(); + for ast in file.ast(db).get_children(db) { + // convert the AST symbol into an item kind + let kind = match ast.symbol(db) { + // if there is an empty line, clear ongoing doc comments + "newline" => { + docs.clear(); + continue; + } + + // if this is a comment, add it to the doc comments + "comment" => { + docs.push(ast); + continue; + } + + // otherwise, convert the symbol directly into the item kind + "type_alias" => ItemKind::TypeAlias, + "import" => ItemKind::Import, + "definition" => ItemKind::Relation, // TODO: rename grammar node + "rule" => ItemKind::Rule, + "assumption" => ItemKind::Assumption, + + // any other symbol should be impossible by conentional means + symbol => unimplemented!("unrecognized top-level AST symbol {symbol:?}"), + }; + + // create an item from the kind + let item = ItemMeta::new(db, docs.clone(), ast, kind); + items.push(item); + + // reset docs for next item + docs.clear(); + } + + // return the completed items + items } /// Parses an [ItemMeta] into its corresponding [Item]. pub fn item<'db>(db: &'db dyn Database, meta: ItemMeta<'db>) -> WithAst> { - todo!() + match meta.kind(db) { + ItemKind::Relation => todo!(), + ItemKind::TypeAlias => todo!(), + ItemKind::Import => todo!(), + ItemKind::Rule => todo!(), + ItemKind::Assumption => todo!(), + } } /// Common information on top-level items. @@ -54,13 +99,51 @@ pub struct ItemMeta<'db> { #[strum_discriminants(name(ItemKind))] #[strum_discriminants(derive(Hash))] pub enum Item<'db> { - TypeAlias(TypeAlias<'db>), - Import, Relation(Relation<'db>), - Rule, - Assumption, + TypeAlias(TypeAlias<'db>), + Import(Import<'db>), + Rule(Rule<'db>), + Assumption(Assumption<'db>), } +/// A definition of a relation. +#[salsa::tracked] +pub struct Relation<'db> { + /// The name of this relation. + pub name: WithAst, + + /// Whether this relation is a decision. + pub is_decision: bool, + + /// The IO of this relation. + pub io: ir::RelationIO, + + /// This relation's abstract type (pure syntax). + pub ty: WithAst, +} + +/// An abstract type alias (syntax representation). +#[salsa::tracked] +pub struct TypeAlias<'db> { + /// The type alias's name. + pub name: WithAst, + + /// The type alias's abstract type. + pub ty: WithAst, +} + +/// An abstract rule. +#[salsa::tracked] +pub struct Rule<'db> {} + +/// An abstract import item. +#[salsa::tracked] +pub struct Import<'db> {} + +/// An abstract assumption. +#[salsa::tracked] +pub struct Assumption<'db> {} + /// Parse an expression from the AST. #[salsa::tracked] pub fn expr(db: &dyn Database, ast: AstNode) -> Expr { @@ -234,41 +317,6 @@ impl ir::EnumRepr for RedundantBinaryOpKind { } } -/// A definition of a relation. -// TODO: add commment above definition AST node for documentation -#[salsa::tracked] -#[derive(Debug)] -pub struct Relation<'db> { - /// The AST node this relation corresponds to. - pub ast: AstNode, - - /// The name of this relation. - pub name: WithAst, - - /// Whether this relation is a decision. - pub is_decision: bool, - - /// The IO of this relation. - pub io: ir::RelationIO, - - /// This relation's abstract type (pure syntax). - pub ty: WithAst, -} - -/// An abstract type alias (syntax representation). -#[salsa::tracked] -#[derive(Debug)] -pub struct TypeAlias<'db> { - /// The AST node of this type alias. - pub ast: AstNode, - - /// The type alias's name. - pub name: WithAst, - - /// The type alias's abstract type. - pub ty: WithAst, -} - /// An abstract type definition. /// /// This just represents the literal, syntactic type representation, without