aboutsummaryrefslogtreecommitdiff
path: root/xtask/src/codegen
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-07-29 10:48:32 +0100
committerAleksey Kladov <[email protected]>2020-07-29 11:04:22 +0100
commit627eddbc7e5eb13fc17c1c655ee1c3864c6dd4fe (patch)
tree2c0b87a578496194db0e423e8488f9f6d5a57d76 /xtask/src/codegen
parent04d2b7b256657f8e6816f8ed67aa5608bfe9e261 (diff)
Owned AST IR
Diffstat (limited to 'xtask/src/codegen')
-rw-r--r--xtask/src/codegen/gen_syntax.rs29
1 files changed, 15 insertions, 14 deletions
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index 745a25862..5a18b3e2b 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -9,28 +9,29 @@ use proc_macro2::{Punct, Spacing};
9use quote::{format_ident, quote}; 9use quote::{format_ident, quote};
10 10
11use crate::{ 11use crate::{
12 ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, 12 ast_src::{rust_ast, AstSrc, Field, FieldSrc, KindsSrc, KINDS_SRC},
13 codegen::{self, update, Mode}, 13 codegen::{self, update, Mode},
14 project_root, Result, 14 project_root, Result,
15}; 15};
16 16
17pub fn generate_syntax(mode: Mode) -> Result<()> { 17pub fn generate_syntax(mode: Mode) -> Result<()> {
18 let ast = rust_ast();
18 let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); 19 let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS);
19 let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; 20 let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
20 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; 21 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
21 22
22 let ast_tokens_file = project_root().join(codegen::AST_TOKENS); 23 let ast_tokens_file = project_root().join(codegen::AST_TOKENS);
23 let contents = generate_tokens(AST_SRC)?; 24 let contents = generate_tokens(&ast)?;
24 update(ast_tokens_file.as_path(), &contents, mode)?; 25 update(ast_tokens_file.as_path(), &contents, mode)?;
25 26
26 let ast_nodes_file = project_root().join(codegen::AST_NODES); 27 let ast_nodes_file = project_root().join(codegen::AST_NODES);
27 let contents = generate_nodes(KINDS_SRC, AST_SRC)?; 28 let contents = generate_nodes(KINDS_SRC, &ast)?;
28 update(ast_nodes_file.as_path(), &contents, mode)?; 29 update(ast_nodes_file.as_path(), &contents, mode)?;
29 30
30 Ok(()) 31 Ok(())
31} 32}
32 33
33fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> { 34fn generate_tokens(grammar: &AstSrc) -> Result<String> {
34 let tokens = grammar.tokens.iter().map(|token| { 35 let tokens = grammar.tokens.iter().map(|token| {
35 let name = format_ident!("{}", token); 36 let name = format_ident!("{}", token);
36 let kind = format_ident!("{}", to_upper_snake_case(token)); 37 let kind = format_ident!("{}", to_upper_snake_case(token));
@@ -62,13 +63,13 @@ fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> {
62 Ok(pretty) 63 Ok(pretty)
63} 64}
64 65
65fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { 66fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> {
66 let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar 67 let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
67 .nodes 68 .nodes
68 .iter() 69 .iter()
69 .map(|node| { 70 .map(|node| {
70 let name = format_ident!("{}", node.name); 71 let name = format_ident!("{}", node.name);
71 let kind = format_ident!("{}", to_upper_snake_case(node.name)); 72 let kind = format_ident!("{}", to_upper_snake_case(&node.name));
72 let traits = node.traits.iter().map(|trait_name| { 73 let traits = node.traits.iter().map(|trait_name| {
73 let trait_name = format_ident!("{}", trait_name); 74 let trait_name = format_ident!("{}", trait_name);
74 quote!(impl ast::#trait_name for #name {}) 75 quote!(impl ast::#trait_name for #name {})
@@ -192,8 +193,8 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
192 }) 193 })
193 .unzip(); 194 .unzip();
194 195
195 let enum_names = grammar.enums.iter().map(|it| it.name); 196 let enum_names = grammar.enums.iter().map(|it| &it.name);
196 let node_names = grammar.nodes.iter().map(|it| it.name); 197 let node_names = grammar.nodes.iter().map(|it| &it.name);
197 198
198 let display_impls = 199 let display_impls =
199 enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { 200 enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| {
@@ -212,7 +213,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
212 .nodes 213 .nodes
213 .iter() 214 .iter()
214 .map(|kind| to_pascal_case(kind)) 215 .map(|kind| to_pascal_case(kind))
215 .filter(|name| !defined_nodes.contains(name.as_str())) 216 .filter(|name| !defined_nodes.iter().any(|&it| it == name))
216 { 217 {
217 eprintln!("Warning: node {} not defined in ast source", node); 218 eprintln!("Warning: node {} not defined in ast source", node);
218 } 219 }
@@ -236,12 +237,12 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
236 let mut res = String::with_capacity(ast.len() * 2); 237 let mut res = String::with_capacity(ast.len() * 2);
237 238
238 let mut docs = 239 let mut docs =
239 grammar.nodes.iter().map(|it| it.doc).chain(grammar.enums.iter().map(|it| it.doc)); 240 grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc));
240 241
241 for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") { 242 for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") {
242 res.push_str(chunk); 243 res.push_str(chunk);
243 if let Some(doc) = docs.next() { 244 if let Some(doc) = docs.next() {
244 write_doc_comment(doc, &mut res); 245 write_doc_comment(&doc, &mut res);
245 } 246 }
246 } 247 }
247 248
@@ -249,7 +250,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
249 Ok(pretty) 250 Ok(pretty)
250} 251}
251 252
252fn write_doc_comment(contents: &[&str], dest: &mut String) { 253fn write_doc_comment(contents: &[String], dest: &mut String) {
253 for line in contents { 254 for line in contents {
254 writeln!(dest, "///{}", line).unwrap(); 255 writeln!(dest, "///{}", line).unwrap();
255 } 256 }
@@ -413,7 +414,7 @@ fn to_pascal_case(s: &str) -> String {
413 buf 414 buf
414} 415}
415 416
416impl Field<'_> { 417impl Field {
417 fn is_many(&self) -> bool { 418 fn is_many(&self) -> bool {
418 matches!(self, Field::Node { src: FieldSrc::Many(_), .. }) 419 matches!(self, Field::Node { src: FieldSrc::Many(_), .. })
419 } 420 }
@@ -429,7 +430,7 @@ impl Field<'_> {
429 fn method_name(&self) -> proc_macro2::Ident { 430 fn method_name(&self) -> proc_macro2::Ident {
430 match self { 431 match self {
431 Field::Token(name) => { 432 Field::Token(name) => {
432 let name = match *name { 433 let name = match name.as_str() {
433 ";" => "semicolon", 434 ";" => "semicolon",
434 "->" => "thin_arrow", 435 "->" => "thin_arrow",
435 "'{'" => "l_curly", 436 "'{'" => "l_curly",