diff --git a/Cargo.lock b/Cargo.lock index 59def53..f0516e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,15 +14,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "cbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b" -dependencies = [ - "num-traits", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -146,19 +137,10 @@ version = "0.0.0" dependencies = [ "expect-test", "la-arena", - "rnix", "rowan", "salsa", "smol_str", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", + "syntax", ] [[package]] @@ -241,15 +223,6 @@ version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" -[[package]] -name = "rnix" -version = "0.11.0-dev" -source = "git+https://github.com/oxalica/rnix-parser.git#80fabb304defc3b488f21d225128bde0758d1eb3" -dependencies = [ - "cbitset", - "rowan", -] - [[package]] name = "rowan" version = "0.15.6" diff --git a/Cargo.toml b/Cargo.toml index dd9103f..0f4e2ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,11 +5,12 @@ edition = "2021" [dependencies] la-arena = "0.2.1" -rnix = { git = "https://github.com/oxalica/rnix-parser.git" } rowan = "0.15.6" salsa = "0.17.0-pre.2" smol_str = "0.1.23" +syntax = { path = "./syntax" } + [dev-dependencies] expect-test = "1.3.0" diff --git a/src/def/lower.rs b/src/def/lower.rs index 9189714..ced4370 100644 --- a/src/def/lower.rs +++ b/src/def/lower.rs @@ -1,17 +1,15 @@ -use super::{AstPtr, Expr, ExprId, Literal, Module, ModuleSourceMap, Path, PathAnchor}; +use super::{AstPtr, Expr, ExprId, Literal, Module, ModuleSourceMap}; use crate::source::{FileId, InFile}; -use rnix::types::{ParsedType, Root, TokenWrapper, TypedNode, Wrapper}; -use rnix::value::Anchor; -use rnix::{NixValue, SyntaxNode, AST}; +use rowan::ast::AstNode; +use syntax::ast::{self, LiteralKind}; -pub(super) fn lower(ast: InFile) -> (Module, ModuleSourceMap) { +pub(super) fn lower(root: InFile) -> (Module, ModuleSourceMap) { let mut ctx = LowerCtx { - file_id: ast.file_id, + file_id: root.file_id, module: Module::default(), source_map: ModuleSourceMap::default(), }; - let node = Root::cast(ast.value.node()).map(|root| root.node().clone()); - ctx.lower_node_opt(node); + ctx.lower_expr_opt(root.value.expr()); (ctx.module, ctx.source_map) } @@ -29,83 +27,60 @@ impl LowerCtx { id } - fn lower_node_opt(&mut self, node: Option) -> ExprId { - if let Some(node) = node { - if let Ok(expr) = ParsedType::try_from(node) { - return self.lower_expr(expr); - } + fn lower_expr_opt(&mut self, expr: Option) -> ExprId { + if let Some(expr) = expr { + return self.lower_expr(expr); } // Synthetic syntax has no coresponding text. self.module.exprs.alloc(Expr::Missing) } - fn lower_path(&mut self, anchor: Anchor, segments: &str, ptr: AstPtr) -> ExprId { - let anchor = match anchor { - Anchor::Relative => PathAnchor::Relative(self.file_id), - Anchor::Absolute => todo!(), - Anchor::Home => todo!(), - Anchor::Store => todo!(), - }; - let path = Path { - anchor, - raw_segments: segments.into(), - }; - self.alloc_expr(Expr::Literal(Literal::Path(path)), ptr) + fn lower_expr(&mut self, expr: ast::Expr) -> ExprId { + let ptr = AstPtr::new(expr.syntax()); + match expr { + ast::Expr::Literal(e) => { + let lit = self.lower_literal(e); + self.alloc_expr(lit.map_or(Expr::Missing, Expr::Literal), ptr) + } + ast::Expr::Name(e) => { + let name = e.token().map_or_else(|| "".into(), |tok| tok.text().into()); + self.alloc_expr(Expr::Ident(name), ptr) + } + ast::Expr::Apply(e) => { + let func = self.lower_expr_opt(e.function()); + let arg = self.lower_expr_opt(e.argument()); + self.alloc_expr(Expr::Apply(func, arg), ptr) + } + ast::Expr::Paren(e) => self.lower_expr_opt(e.expr()), + ast::Expr::Assert(_) => todo!(), + ast::Expr::AttrSet(_) => todo!(), + ast::Expr::BinaryOp(_) => todo!(), + ast::Expr::HasAttr(_) => todo!(), + ast::Expr::IfThenElse(_) => todo!(), + ast::Expr::IndentString(_) => todo!(), + ast::Expr::Lambda(_) => todo!(), + ast::Expr::LetIn(_) => todo!(), + ast::Expr::List(_) => todo!(), + ast::Expr::Select(_) => todo!(), + ast::Expr::String(_) => todo!(), + ast::Expr::UnaryOp(_) => todo!(), + ast::Expr::With(_) => todo!(), + } } - fn lower_expr(&mut self, expr: ParsedType) -> ExprId { - let ptr = AstPtr::new(expr.node()); - let expr = match expr { - ParsedType::Root(e) => return self.lower_node_opt(e.inner()), - ParsedType::Paren(e) => return self.lower_node_opt(e.inner()), - ParsedType::Ident(e) => { - let ident = e.to_inner_string(); - Expr::Ident(ident.into()) - } - ParsedType::Value(e) => match e.to_value() { - Ok(v) => { - let lit = match v { - NixValue::Integer(x) => Literal::Int(x), - NixValue::Float(_) => todo!(), - NixValue::String(s) => Literal::String(s.into()), - NixValue::Path(anchor, path) => return self.lower_path(anchor, &path, ptr), - }; - Expr::Literal(lit) - } - Err(_) => Expr::Missing, - }, - ParsedType::Apply(e) => { - let lam = self.lower_node_opt(e.lambda()); - let arg = self.lower_node_opt(e.value()); - Expr::Apply(lam, arg) - } - ParsedType::Assert(_) => todo!(), - ParsedType::IfElse(_) => todo!(), - ParsedType::Select(_) => todo!(), - ParsedType::Inherit(_) => todo!(), - ParsedType::InheritFrom(_) => todo!(), - ParsedType::Lambda(_) => todo!(), - ParsedType::LegacyLet(_) => todo!(), - ParsedType::LetIn(_) => todo!(), - ParsedType::List(_) => todo!(), - ParsedType::BinOp(_) => todo!(), - ParsedType::OrDefault(_) => todo!(), - ParsedType::AttrSet(_) => todo!(), - ParsedType::KeyValue(_) => todo!(), - ParsedType::Str(_) => todo!(), - ParsedType::StrInterpol(_) => todo!(), - ParsedType::UnaryOp(_) => todo!(), - ParsedType::With(_) => todo!(), - ParsedType::PathWithInterpol(_) => todo!(), + fn lower_literal(&mut self, lit: ast::Literal) -> Option { + let kind = lit.kind()?; + let tok = lit.token().unwrap(); + let text = tok.text(); - // Invalid nodes in expression location. - ParsedType::Pattern(_) - | ParsedType::PatBind(_) - | ParsedType::PatEntry(_) - | ParsedType::Key(_) - | ParsedType::Dynamic(_) - | ParsedType::Error(_) => Expr::Missing, - }; - self.alloc_expr(expr, ptr) + Some(match kind { + LiteralKind::Int => Literal::Int(text.parse::().ok()?), + LiteralKind::Float => todo!(), + LiteralKind::Uri => Literal::String(text.into()), + LiteralKind::RelativePath => todo!(), + LiteralKind::AbsolutePath => todo!(), + LiteralKind::HomePath => todo!(), + LiteralKind::SearchPath => todo!(), + }) } } diff --git a/src/def/mod.rs b/src/def/mod.rs index 0456f95..ce7db15 100644 --- a/src/def/mod.rs +++ b/src/def/mod.rs @@ -23,8 +23,8 @@ fn module_with_source_map( db: &dyn DefDatabase, file_id: FileId, ) -> (Arc, Arc) { - let root = db.parse(file_id); - let (module, source_map) = lower::lower(root); + let parse = db.parse(file_id); + let (module, source_map) = lower::lower(parse.map(|p| p.root())); (Arc::new(module), Arc::new(source_map)) } @@ -50,7 +50,7 @@ impl ops::Index for Module { } } -pub type AstPtr = rowan::ast::SyntaxNodePtr; +pub type AstPtr = rowan::ast::SyntaxNodePtr; #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct ModuleSourceMap { diff --git a/src/def/tests.rs b/src/def/tests.rs index 7f39f76..dee3a5d 100644 --- a/src/def/tests.rs +++ b/src/def/tests.rs @@ -4,15 +4,11 @@ use expect_test::expect; #[test] fn module_basic() { - let (db, root_id) = TestDB::from_file( - r#" - foo 123 ./bar.nix - "#, - ); + let (db, root_id) = TestDB::from_file("foo 123"); expect![[r#" Module { exprs: Arena { - len: 5, + len: 3, data: [ Ident( Name( @@ -28,22 +24,6 @@ fn module_basic() { Idx::(0), Idx::(1), ), - Literal( - Path( - Path { - anchor: Relative( - FileId( - 0, - ), - ), - raw_segments: "./bar.nix", - }, - ), - ), - Apply( - Idx::(2), - Idx::(3), - ), ], }, } @@ -57,24 +37,16 @@ fn module_basic() { expect![[r#" [ SyntaxNodePtr { - kind: NODE_IDENT, - range: 9..12, + kind: NAME, + range: 0..3, }, SyntaxNodePtr { - kind: NODE_LITERAL, - range: 13..16, + kind: LITERAL, + range: 4..7, }, SyntaxNodePtr { - kind: NODE_APPLY, - range: 9..16, - }, - SyntaxNodePtr { - kind: NODE_LITERAL, - range: 17..26, - }, - SyntaxNodePtr { - kind: NODE_APPLY, - range: 9..26, + kind: APPLY, + range: 0..7, }, ] "#]] diff --git a/src/source.rs b/src/source.rs index dea52b5..f7106ba 100644 --- a/src/source.rs +++ b/src/source.rs @@ -1,5 +1,5 @@ -use rnix::AST; use std::sync::Arc; +use syntax::Parse; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FileId(pub u32); @@ -31,12 +31,12 @@ pub trait SourceDatabase { #[salsa::input] fn file_content(&self, file_id: FileId) -> Arc<[u8]>; - fn parse(&self, file_id: FileId) -> InFile; + fn parse(&self, file_id: FileId) -> InFile; } -fn parse(db: &dyn SourceDatabase, file_id: FileId) -> InFile { +fn parse(db: &dyn SourceDatabase, file_id: FileId) -> InFile { let content = db.file_content(file_id); let content = std::str::from_utf8(&content).unwrap_or_default(); - let ast = rnix::parse(content); - InFile::new(file_id, ast) + let parse = syntax::parse_file(content); + InFile::new(file_id, parse) }