[rust] Very rough sketch of consuming Hermes parser results
Joe Savona committed
Jul 28, 2023 at 16:12 UTC
ce2725eda5858a642f21390d0fe5ae3d40ba4060
5 files changed
+189
compiler/forget/Cargo.lock
+49
@@ -266,6 +266,15 @@ dependencies = [
266
"winapi",
267
]
268
269
+[[package]]
270
+name = "cmake"
271
+version = "0.1.50"
272
+source = "registry+https://github.com/rust-lang/crates.io-index"
273
+checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
274
+dependencies = [
275
+ "cc",
276
+]
277
+
278
[[package]]
279
name = "console"
280
version = "0.15.7"
@@ -513,6 +522,16 @@ dependencies = [
522
"miette 5.9.0",
523
]
524
525
+[[package]]
526
+name = "forget_hermes_parser"
527
+version = "0.1.0"
528
+dependencies = [
529
+ "forget_diagnostics",
530
+ "forget_estree",
531
+ "hermes",
532
+ "juno_support",
533
+]
534
+
535
[[package]]
536
name = "forget_hir"
537
version = "0.1.0"
@@ -658,6 +677,18 @@ version = "0.14.0"
677
source = "registry+https://github.com/rust-lang/crates.io-index"
678
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
679
680
+[[package]]
681
+name = "hermes"
682
+version = "0.1.0"
683
+source = "git+https://github.com/facebook/hermes.git#b2618410b4093e780a04228a2ce87a3626983506"
684
+dependencies = [
685
+ "cmake",
686
+ "juno_support",
687
+ "libc",
688
+ "libcplusplus",
689
+ "thiserror",
690
+]
691
+
692
[[package]]
693
name = "hermit-abi"
694
version = "0.1.19"
@@ -824,6 +855,19 @@ dependencies = [
855
"serde_json",
856
]
857
858
+[[package]]
859
+name = "juno_support"
860
+version = "0.1.0"
861
+source = "git+https://github.com/facebook/hermes.git#b2618410b4093e780a04228a2ce87a3626983506"
862
+dependencies = [
863
+ "anyhow",
864
+ "base64",
865
+ "cmake",
866
+ "libcplusplus",
867
+ "thiserror",
868
+ "url",
869
+]
870
+
871
[[package]]
872
name = "lazy_static"
873
version = "1.4.0"
@@ -909,6 +953,11 @@ version = "0.2.147"
953
source = "registry+https://github.com/rust-lang/crates.io-index"
954
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
955
956
+[[package]]
957
+name = "libcplusplus"
958
+version = "0.1.0"
959
+source = "git+https://github.com/facebook/hermes.git#b2618410b4093e780a04228a2ce87a3626983506"
960
+
961
[[package]]
962
name = "linked-hash-map"
963
version = "0.5.6"
compiler/forget/Cargo.toml
+3
@@ -19,6 +19,7 @@ forget_estree = { path = "crates/forget_estree" }
19
forget_estree_codegen = { path = "crates/forget_estree_codegen" }
20
forget_estree_swc = { path = "crates/forget_estree_swc" }
21
forget_fixtures = { path = "crates/forget_fixtures" }
22
+forget_hermes_parser = { path = "crates/forget_hermes_parser" }
23
forget_hir = { path = "crates/forget_hir" }
24
forget_optimization = { path = "crates/forget_optimization" }
25
forget_ssa = { path = "crates/forget_ssa" }
@@ -39,6 +40,8 @@ swc = "0.264.8"
40
swc_core = { version = "0.79.9", features = ["swc_ecma_visit", "__ecma_transforms", "swc_ecma_ast", "swc_common", "swc", "swc_ecma_parser", "__ecma", "__common", "ecma_ast", "__visit", "__parser"] }
41
syn = "2.0.23"
42
thiserror = "1.0.41"
43
+hermes = { git = "https://github.com/facebook/hermes.git" }
44
+juno_support = { git = "https://github.com/facebook/hermes.git" }
45
46
[profile.release]
47
# configuration adapted from oxc
compiler/forget/crates/forget_hermes_parser/Cargo.toml
new
+18
@@ -0,0 +1,18 @@
1
+[package]
2
+name = "forget_hermes_parser"
3
+version = "0.1.0"
4
+authors.workspace = true
5
+description.workspace = true
6
+edition.workspace = true
7
+homepage.workspace = true
8
+keywords.workspace = true
9
+license.workspace = true
10
+repository.workspace = true
11
+
12
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
13
+
14
+[dependencies]
15
+forget_diagnostics = { workspace = true }
16
+forget_estree = { workspace = true }
17
+hermes = { workspace = true }
18
+juno_support = { workspace = true }
\ No newline at end of file
compiler/forget/crates/forget_hermes_parser/README.md
new
+3
@@ -0,0 +1,3 @@
1
+# forget_hermes_parser
2
+
3
+Wrapper around the Hermes parser that exposes parse results as a `forget_estree` AST.
\ No newline at end of file
compiler/forget/crates/forget_hermes_parser/src/lib.rs
new
+116
@@ -0,0 +1,116 @@
1
+use forget_diagnostics::Diagnostic;
2
+use hermes::parser::{
3
+ hermes_get_BlockStatement_body, hermes_get_DeclareFunction_id,
4
+ hermes_get_FunctionDeclaration_async, hermes_get_FunctionDeclaration_body,
5
+ hermes_get_FunctionDeclaration_generator, hermes_get_Program_body, HermesParser, NodeKind,
6
+ NodePtr, ParserDialect, ParserFlags,
7
+};
8
+use juno_support::source_manager::SourceRange;
9
+use juno_support::NullTerminatedBuf;
10
+
11
+pub fn parse(source: &str, file: &str) -> Result<forget_estree::Program, Vec<Diagnostic>> {
12
+ let buf = NullTerminatedBuf::from_str_check(source);
13
+ let result = HermesParser::parse(
14
+ ParserFlags {
15
+ dialect: ParserDialect::TypeScript,
16
+ enable_jsx: true,
17
+ store_doc_block: true,
18
+ strict_mode: true,
19
+ },
20
+ &buf,
21
+ );
22
+ if result.has_errors() {
23
+ let error_messages = result.messages();
24
+ return Err(todo!("construct diagnostics"));
25
+ }
26
+
27
+ Ok(unsafe { convert_program(result.root().unwrap()) })
28
+}
29
+
30
+unsafe fn convert_program(node: NodePtr) -> forget_estree::Program {
31
+ let node_ref = node.as_ref();
32
+ let body = hermes_get_Program_body(node);
33
+ let body: Vec<_> = body
34
+ .iter()
35
+ .map(|node| convert_module_item(NodePtr::new(node)))
36
+ .collect();
37
+ forget_estree::Program {
38
+ body,
39
+ source_type: forget_estree::SourceType::Module,
40
+ loc: None,
41
+ range: None,
42
+ }
43
+}
44
+
45
+unsafe fn convert_module_item(node: NodePtr) -> forget_estree::ModuleItem {
46
+ let node_ref = node.as_ref();
47
+ match node_ref.kind {
48
+ NodeKind::FunctionDeclaration => {
49
+ forget_estree::ModuleItem::Statement(forget_estree::Statement::FunctionDeclaration(
50
+ Box::new(convert_function_declaration(node)),
51
+ ))
52
+ }
53
+ _ => todo!(),
54
+ }
55
+}
56
+
57
+unsafe fn convert_function_declaration(node: NodePtr) -> forget_estree::FunctionDeclaration {
58
+ let id = None; //hermes_get_DeclareFunction_id(node);
59
+ let params = Vec::new();
60
+ let body = forget_estree::FunctionBody::BlockStatement(Box::new(convert_block_statement(
61
+ hermes_get_FunctionDeclaration_body(node),
62
+ )));
63
+ let is_generator = hermes_get_FunctionDeclaration_generator(node);
64
+ let is_async = hermes_get_FunctionDeclaration_async(node);
65
+ forget_estree::FunctionDeclaration {
66
+ function: forget_estree::Function {
67
+ id,
68
+ params,
69
+ body: Some(body),
70
+ is_generator,
71
+ is_async,
72
+ loc: None,
73
+ range: None,
74
+ },
75
+ loc: None,
76
+ range: None,
77
+ }
78
+}
79
+
80
+unsafe fn convert_block_statement(node: NodePtr) -> forget_estree::BlockStatement {
81
+ let body = hermes_get_BlockStatement_body(node);
82
+ let body: Vec<_> = body
83
+ .iter()
84
+ .map(|node| convert_statement(NodePtr::new(node)))
85
+ .collect();
86
+ forget_estree::BlockStatement {
87
+ body,
88
+ loc: None,
89
+ range: None,
90
+ }
91
+}
92
+
93
+unsafe fn convert_statement(node: NodePtr) -> forget_estree::Statement {
94
+ let node_ref = node.as_ref();
95
+ match node_ref.kind {
96
+ NodeKind::ReturnStatement => {
97
+ forget_estree::Statement::ReturnStatement(Box::new(forget_estree::ReturnStatement {
98
+ argument: None,
99
+ loc: None,
100
+ range: None,
101
+ }))
102
+ }
103
+ _ => todo!(),
104
+ }
105
+}
106
+
107
+#[cfg(test)]
108
+mod tests {
109
+ use super::*;
110
+
111
+ #[test]
112
+ fn fixtures() {
113
+ let res = parse("function foo() { return }", "hello.js");
114
+ println!("{:#?}", res);
115
+ }
116
+}