-
-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better typed api #105
Better typed api #105
Changes from 24 commits
9f56e12
61211a3
3743c07
6706b12
6590dea
ae449c1
acabaa3
46148ba
57bb3f1
8a3ad43
f9d4281
91717e2
e2c669f
dc58b01
3f8bfb6
460b07e
ef22d2c
62052fb
3e6c10f
1ea3f7b
f0fda83
9a1cee9
fcaa745
4bb1ccd
141ea37
b0a5d72
d87d171
63952e3
340fd89
059206d
518df53
ecd0ca8
7ef4dd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,13 @@ | ||
use rnix::types::*; | ||
use std::{io, io::Read}; | ||
|
||
fn main() { | ||
let mut content = String::new(); | ||
io::stdin().read_to_string(&mut content).expect("could not read nix from stdin"); | ||
let ast = rnix::parse(&content); | ||
let ast = rnix::Root::parse(&content); | ||
|
||
for error in ast.errors() { | ||
println!("error: {}", error); | ||
} | ||
|
||
println!("{}", ast.root().dump()); | ||
println!("{}", ast.tree()); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
//! Provides a type system for the AST, in some sense | ||
|
||
mod expr_ext; | ||
mod node_ext; | ||
mod nodes; | ||
mod operators; | ||
mod tokens; | ||
|
||
use crate::{NixLanguage, SyntaxKind, SyntaxToken}; | ||
|
||
pub use nodes::*; | ||
pub use operators::{BinOpKind, UnaryOpKind}; | ||
pub use tokens::*; | ||
|
||
pub trait AstNode: rowan::ast::AstNode<Language = NixLanguage> {} | ||
|
||
impl<T> AstNode for T where T: rowan::ast::AstNode<Language = NixLanguage> {} | ||
|
||
mod support { | ||
use rowan::ast::AstChildren; | ||
|
||
use super::{AstNode, AstToken}; | ||
use crate::{SyntaxElement, SyntaxKind, SyntaxToken}; | ||
|
||
pub(super) fn nth<N: AstNode, NN: AstNode>(parent: &N, n: usize) -> Option<NN> { | ||
parent.syntax().children().flat_map(NN::cast).nth(n) | ||
} | ||
|
||
pub(super) fn children<N: AstNode, NN: AstNode>(parent: &N) -> AstChildren<NN> { | ||
rowan::ast::support::children(parent.syntax()) | ||
} | ||
|
||
pub(super) fn token<N: AstNode, T: AstToken>(parent: &N) -> Option<T> { | ||
children_tokens(parent).find_map(T::cast) | ||
} | ||
|
||
/// Token untyped | ||
pub(super) fn token_u<N: AstNode>(parent: &N, kind: SyntaxKind) -> Option<SyntaxToken> { | ||
children_tokens(parent).find(|it| it.kind() == kind) | ||
} | ||
|
||
pub(super) fn children_tokens<N: AstNode>(parent: &N) -> impl Iterator<Item = SyntaxToken> { | ||
parent.syntax().children_with_tokens().filter_map(SyntaxElement::into_token) | ||
} | ||
|
||
pub(super) fn children_tokens_u<N: AstNode>(parent: &N) -> impl Iterator<Item = SyntaxToken> { | ||
parent.syntax().children_with_tokens().filter_map(SyntaxElement::into_token) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the intended difference between these two functions? The first one should ne ,pre typed, right? But it currently isn't? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this is fixed now. |
||
} | ||
|
||
pub trait AstToken { | ||
fn can_cast(from: SyntaxKind) -> bool | ||
where | ||
Self: Sized; | ||
|
||
/// Cast an untyped token into this strongly-typed token. This will return | ||
/// None if the type was not correct. | ||
fn cast(from: SyntaxToken) -> Option<Self> | ||
where | ||
Self: Sized; | ||
|
||
fn syntax(&self) -> &SyntaxToken; | ||
} | ||
|
||
pub struct Another; | ||
pub struct My; | ||
|
||
impl From<Another> for Option<My> { | ||
fn from(_: Another) -> Self { | ||
None | ||
} | ||
} | ||
oberblastmeister marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
fn test() { | ||
let test = <Option<My>>::from(Another).unwrap(); | ||
} | ||
oberblastmeister marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use crate::ast::{self, support::*}; | ||
|
||
// this is a separate type because it mixes tokens and nodes | ||
// for example, a Str is a node because it can contain nested subexpressions but an Integer is a token. | ||
// This means that we have to write it out manually instead of using the macro to create the type for us. | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
pub enum LiteralKind { | ||
oberblastmeister marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Float(ast::Float), | ||
Integer(ast::Integer), | ||
Path(ast::Path), | ||
Uri(ast::Uri), | ||
} | ||
|
||
impl ast::Literal { | ||
pub fn kind(&self) -> LiteralKind { | ||
oberblastmeister marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if let Some(it) = token(self) { | ||
return LiteralKind::Float(it); | ||
} | ||
|
||
if let Some(it) = token(self) { | ||
return LiteralKind::Integer(it); | ||
} | ||
|
||
if let Some(it) = token(self) { | ||
return LiteralKind::Path(it); | ||
} | ||
|
||
if let Some(it) = token(self) { | ||
return LiteralKind::Uri(it); | ||
} | ||
oberblastmeister marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
unreachable!() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
||
oberblastmeister marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.