Minor tweaks

This commit is contained in:
Aleksey Kladov 2017-12-22 19:21:45 +03:00
parent 80c3e57f96
commit 2c74af7ddc

63
rfc.md
View file

@ -38,8 +38,8 @@ be `0.1.0`.
## Reusability
In theory, parsing can be a pure function, which takes a `&str` as an
input, and produces a `ParseTree` as an output.
In theory, the parser can be a pure function, which takes a `&str` as
an input, and produces a `ParseTree` as an output.
This is great for reusability: for example, you can compile this
function to WASM and use it for fast client-side validation of syntax
@ -64,7 +64,7 @@ Unfortunately, the current libsyntax is far from this ideal. For
example, even the lexer makes use of the `FileMap` which is
essentially a global state of the compiler which represents all know
files. As a data point, it turned out to be easier to move `rustfmt`
inside of main `rustc` repository than to move libsyntax outside!
into the main `rustc` repository than to move libsyntax outside!
## IDE support
@ -86,9 +86,8 @@ necessary to correctly handle certain code-editing actions like
autoindentation or joining lines. IDE also must be able to produce
partial parse trees when some input is missing or invalid.
Currently rustc uses the AST approach, which preserves the source code
information to some extent by storing spans in the AST.
Currently rustc uses the AST approach, and preserves some of the
source code information in the form of spans in the AST.
# Guide-level explanation
@ -114,8 +113,8 @@ compiler.
## Untyped Tree
The main idea is to store the minimal amount of information in the
tree itself, and instead lean heavily on the source code string for
the actual data about identifier names, constant values etc.
tree itself, and instead lean heavily on the source code for the
actual data about identifier names, constant values etc.
All nodes in the tree are of the same type and store a constant for
the syntactic category of the element and a range in the source code.
@ -273,10 +272,12 @@ Note several features of the tree:
It's hard to work with this raw parse tree, because it is untyped:
node containing a struct definition has the same API as the node for
the struct field. But it's possible to add a strongly typed layer on
top of this raw tree, and get a zero-cost typed AST. Here is an
example which adds type-safe wrappers for structs and fields:
top of this raw tree, and get a zero-cost AST. Here is an example
which adds type-safe wrappers for structs and fields:
```rust
// generic infrastructure
pub trait AstNode<'f>: Copy + 'f {
fn new(node: Node<'f>) -> Option<Self>;
fn node(&self) -> Node<'f>;
@ -290,6 +291,8 @@ pub fn ast_children<'f, A: AstNode<'f>>(node: Node<'f>) -> Box<Iterator<Item=A>
Box::new(node.children().filter_map(A::new))
}
// AST elements, specific to Rust
#[derive(Clone, Copy)]
pub struct StructDef<'f>(Node<'f>);
@ -315,22 +318,7 @@ impl<'f> AstNode<'f> for StructDef<'f> {
fn node(&self) -> Node<'f> { self.0 }
}
impl<'f> AstNode<'f> for FieldDef<'f> {
fn new(node: Node<'f>) -> Option<Self> {
if node.kind() == FIELD_DEF { Some(FieldDef(node)) } else { None }
}
fn node(&self) -> Node<'f> { self.0 }
}
impl<'f> AstNode<'f> for TypeRef<'f> {
fn new(node: Node<'f>) -> Option<Self> {
if node.kind() == TYPE_REF { Some(TypeRef(node)) } else { None }
}
fn node(&self) -> Node<'f> { self.0 }
}
impl<'f> NameOwner<'f> for StructDef<'f> {}
impl<'f> NameOwner<'f> for FieldDef<'f> {}
impl<'f> StructDef<'f> {
pub fn fields(&self) -> Box<Iterator<Item=FieldDef<'f>> + 'f> {
@ -338,11 +326,29 @@ impl<'f> StructDef<'f> {
}
}
impl<'f> AstNode<'f> for FieldDef<'f> {
fn new(node: Node<'f>) -> Option<Self> {
if node.kind() == FIELD_DEF { Some(FieldDef(node)) } else { None }
}
fn node(&self) -> Node<'f> { self.0 }
}
impl<'f> FieldDef<'f> {
pub fn type_ref(&self) -> Option<TypeRef<'f>> {
ast_children(self.node()).next()
}
}
impl<'f> NameOwner<'f> for FieldDef<'f> {}
impl<'f> AstNode<'f> for TypeRef<'f> {
fn new(node: Node<'f>) -> Option<Self> {
if node.kind() == TYPE_REF { Some(TypeRef(node)) } else { None }
}
fn node(&self) -> Node<'f> { self.0 }
}
```
@ -371,9 +377,11 @@ plan is suggested:
* RFC discussion about the theoretical feasibility of the proposal.
* Implementation of the proposal as a completely separate crates.io
crate.
crate, by refactoring existing libsyntax source code to produce a
new tree.
* A prototype implementation of the macro expansion on top of the new sytnax tree.
* A prototype implementation of the macro expansion on top of the new
sytnax tree.
* Additional round of discussion/RFC about merging with the mainline
compiler.
@ -392,6 +400,7 @@ plan is suggested:
- Incrementally add more information about source code to the current AST.
- Move the current libsyntax to crates.io as is.
- Explore alternative representations for the parse tree.
- Use parser generator instead of hand written parser.
# Unresolved questions
[unresolved]: #unresolved-questions