mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[rust] Workspace hygiene
I've primarily used what Cargo calls virtual workspaces, where the top-level
Cargo.toml just lists a bunch of packages and they each have their own
dependencies. This is fine, but i've noticed that more repos are using real
workspaces and they offer a bunch of benefits. You define the dependencies in
the top-level Cargo.toml and then can easily refer to them from multiple crates,
ensuring all the versions match up. It makes it easier to refer to other crates
in the workspace, too, because you define the path once at the root, then every
other crate can just say `forget_foo = { workspace = true }`.
I also renamed all the crates to be prefixed with `forget_`, in some cases
removing the redundant `hir` name, So `hir-optimization` became
`forget_optimization`, `hir-ssa` became `forget_ssa`. Also note the switch from
hyphenated names to underscores everywhere, since at the end of the day you have
to write the name with underscores in source code.
I also deleted the demo crate that i started with since we don't need it
anymore.
And finally, i added an explicit publish = false to all the crates just to
prevent mistakes.
This commit is contained in:
Generated
+151
-285
@@ -233,18 +233,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-hir"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"estree",
|
||||
"hir",
|
||||
"indexmap 2.0.0",
|
||||
"miette 5.9.0",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.13.0"
|
||||
@@ -393,15 +381,6 @@ version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "elsa"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e0aca8dce8856e420195bd13b6a64de3334235ccc9214e824b86b12bf26283"
|
||||
dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
@@ -456,12 +435,35 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "estree"
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "forget_build_hir"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"elsa",
|
||||
"estree-codegen",
|
||||
"forget_estree",
|
||||
"forget_hir",
|
||||
"indexmap 2.0.0",
|
||||
"miette 5.9.0",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "forget_estree"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"forget_estree_codegen",
|
||||
"insta",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -469,7 +471,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "estree-codegen"
|
||||
name = "forget_estree_codegen"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"indexmap 2.0.0",
|
||||
@@ -481,40 +483,74 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "estree-swc"
|
||||
name = "forget_estree_swc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"estree",
|
||||
"forget_estree",
|
||||
"swc",
|
||||
"swc_core 0.79.9",
|
||||
"swc_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "fixtures"
|
||||
name = "forget_fixtures"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"build-hir",
|
||||
"bumpalo",
|
||||
"estree",
|
||||
"estree-swc",
|
||||
"hir",
|
||||
"hir-optimization",
|
||||
"hir-ssa",
|
||||
"forget_build_hir",
|
||||
"forget_estree",
|
||||
"forget_estree_swc",
|
||||
"forget_hir",
|
||||
"forget_optimization",
|
||||
"forget_ssa",
|
||||
"insta",
|
||||
"miette 5.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
name = "forget_hir"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"forget_estree",
|
||||
"forget_utils",
|
||||
"indexmap 2.0.0",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "forget_optimization"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"forget_build_hir",
|
||||
"forget_estree",
|
||||
"forget_hir",
|
||||
"forget_ssa",
|
||||
"forget_utils",
|
||||
"indexmap 2.0.0",
|
||||
"miette 5.9.0",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "forget_ssa"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"forget_hir",
|
||||
"forget_utils",
|
||||
"indexmap 2.0.0",
|
||||
"miette 5.9.0",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "forget_utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"stacker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
@@ -630,44 +666,6 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "hir"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"estree",
|
||||
"indexmap 2.0.0",
|
||||
"serde",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hir-optimization"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"build-hir",
|
||||
"bumpalo",
|
||||
"estree",
|
||||
"hir",
|
||||
"hir-ssa",
|
||||
"indexmap 2.0.0",
|
||||
"miette 5.9.0",
|
||||
"thiserror",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hir-ssa"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"hir",
|
||||
"indexmap 2.0.0",
|
||||
"miette 5.9.0",
|
||||
"thiserror",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.57"
|
||||
@@ -1783,20 +1781,20 @@ dependencies = [
|
||||
"swc_cached",
|
||||
"swc_common",
|
||||
"swc_config",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
"swc_ecma_ext_transforms",
|
||||
"swc_ecma_lints",
|
||||
"swc_ecma_loader",
|
||||
"swc_ecma_minifier",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_preset_env",
|
||||
"swc_ecma_transforms",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_compat",
|
||||
"swc_ecma_transforms_optimization",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"swc_error_reporters",
|
||||
"swc_node_comments",
|
||||
"swc_timer",
|
||||
@@ -1805,18 +1803,6 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc-demo"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"swc_common",
|
||||
"swc_core 0.78.28",
|
||||
"swc_ecma_parser 0.136.8",
|
||||
"swc_ecma_transforms_base 0.129.15",
|
||||
"swc_ecma_visit 0.92.5",
|
||||
"swc_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_atoms"
|
||||
version = "0.5.6"
|
||||
@@ -1852,9 +1838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6414bd4e553f5638961d39b07075ffd37a3d63176829592f4a5900260d94ca1"
|
||||
dependencies = [
|
||||
"ahash 0.8.3",
|
||||
"anyhow",
|
||||
"ast_node",
|
||||
"atty",
|
||||
"better_scoped_tls",
|
||||
"cfg-if",
|
||||
"either",
|
||||
@@ -1871,7 +1855,6 @@ dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_eq_ignore_macros",
|
||||
"swc_visit",
|
||||
"termcolor",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
"url",
|
||||
@@ -1902,15 +1885,6 @@ dependencies = [
|
||||
"syn 2.0.23",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_core"
|
||||
version = "0.78.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e38b2fd17f97d84f1152eb82d7ebc089e98ddd02b5b750af37a0c91dec81c87"
|
||||
dependencies = [
|
||||
"vergen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_core"
|
||||
version = "0.79.9"
|
||||
@@ -1920,29 +1894,13 @@ dependencies = [
|
||||
"swc",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_visit",
|
||||
"vergen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_ast"
|
||||
version = "0.106.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebf4d6804b1da4146c4c0359d129e3dd43568d321f69d7953d9abbca4ded76ba"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"is-macro",
|
||||
"num-bigint",
|
||||
"scoped-tls",
|
||||
"string_enum",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"unicode-id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_ast"
|
||||
version = "0.107.0"
|
||||
@@ -1974,7 +1932,7 @@ dependencies = [
|
||||
"sourcemap",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen_macros",
|
||||
"tracing",
|
||||
]
|
||||
@@ -2001,9 +1959,9 @@ dependencies = [
|
||||
"phf",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2022,9 +1980,9 @@ dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_config",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2072,38 +2030,18 @@ dependencies = [
|
||||
"swc_cached",
|
||||
"swc_common",
|
||||
"swc_config",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_optimization",
|
||||
"swc_ecma_usage_analyzer",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"swc_timer",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.136.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45d40421c607d7a48334f78a9b24a5cbde1f36250f9986746ec082208d68b39f"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lexical",
|
||||
"num-bigint",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"smartstring",
|
||||
"stacker",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.106.6",
|
||||
"tracing",
|
||||
"typed-arena",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.137.1"
|
||||
@@ -2119,7 +2057,7 @@ dependencies = [
|
||||
"stacker",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"tracing",
|
||||
"typed-arena",
|
||||
]
|
||||
@@ -2143,10 +2081,10 @@ dependencies = [
|
||||
"string_enum",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_transforms",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2157,39 +2095,16 @@ checksum = "a4f578a16ff264c1f306d38a10b900256b33f636426ebeb5eab980205e8fc9f5"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_compat",
|
||||
"swc_ecma_transforms_module",
|
||||
"swc_ecma_transforms_optimization",
|
||||
"swc_ecma_transforms_proposal",
|
||||
"swc_ecma_transforms_react",
|
||||
"swc_ecma_transforms_typescript",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_base"
|
||||
version = "0.129.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7707e724db259cd93150fd5bc04559ace997edbce968d29be9c881e317c9b3fb"
|
||||
dependencies = [
|
||||
"better_scoped_tls",
|
||||
"bitflags 2.3.3",
|
||||
"indexmap 1.9.3",
|
||||
"once_cell",
|
||||
"phf",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.106.6",
|
||||
"swc_ecma_parser 0.136.8",
|
||||
"swc_ecma_utils 0.119.10",
|
||||
"swc_ecma_visit 0.92.5",
|
||||
"tracing",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2208,10 +2123,10 @@ dependencies = [
|
||||
"smallvec",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -2223,10 +2138,10 @@ checksum = "a288e0d1a702f1944df7c1b57468f505a9549d7d7a51d89dfa18d8f956abdbf5"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2245,12 +2160,12 @@ dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_config",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_classes",
|
||||
"swc_ecma_transforms_macros",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"swc_trace_macro",
|
||||
"tracing",
|
||||
]
|
||||
@@ -2287,12 +2202,12 @@ dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_cached",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_loader",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -2311,12 +2226,12 @@ dependencies = [
|
||||
"serde_json",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_macros",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"swc_fast_graph",
|
||||
"tracing",
|
||||
]
|
||||
@@ -2333,12 +2248,12 @@ dependencies = [
|
||||
"smallvec",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_classes",
|
||||
"swc_ecma_transforms_macros",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2358,12 +2273,12 @@ dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_config",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_parser 0.137.1",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_macros",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2375,11 +2290,11 @@ dependencies = [
|
||||
"serde",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_transforms_base 0.130.1",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_transforms_base",
|
||||
"swc_ecma_transforms_react",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2393,31 +2308,13 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_utils 0.120.1",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
"swc_timer",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.119.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "452c66399edeb88a97bfdc3bbf11e45db85fdf883bfd4fc8bdd93abb92152b9b"
|
||||
dependencies = [
|
||||
"indexmap 1.9.3",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"rustc-hash",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.106.6",
|
||||
"swc_ecma_visit 0.92.5",
|
||||
"tracing",
|
||||
"unicode-id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.120.1"
|
||||
@@ -2430,26 +2327,12 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_visit 0.93.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_visit",
|
||||
"tracing",
|
||||
"unicode-id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_visit"
|
||||
version = "0.92.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f61da6cac0ec3b7e62d367cfbd9e38e078a4601271891ad94f0dac5ff69f839"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.106.6",
|
||||
"swc_visit",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_visit"
|
||||
version = "0.93.0"
|
||||
@@ -2459,7 +2342,7 @@ dependencies = [
|
||||
"num-bigint",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast 0.107.0",
|
||||
"swc_ecma_ast",
|
||||
"swc_visit",
|
||||
"tracing",
|
||||
]
|
||||
@@ -2591,15 +2474,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
@@ -2802,14 +2676,6 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"stacker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vergen"
|
||||
version = "7.5.1"
|
||||
|
||||
+49
-12
@@ -1,17 +1,54 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/build-hir",
|
||||
"crates/fixtures",
|
||||
"crates/hir",
|
||||
"crates/hir-ssa",
|
||||
"crates/hir-optimization",
|
||||
"crates/swc-demo",
|
||||
"crates/estree",
|
||||
"crates/estree-codegen",
|
||||
"crates/estree-swc",
|
||||
"crates/utils"
|
||||
]
|
||||
members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
authors = ["The React Team https://react.dev/community/team"]
|
||||
description = "React Forget Compiler"
|
||||
edition = "2021"
|
||||
homepage = "https://github.com/facebook/react-forget"
|
||||
keywords = ["JavaScript", "TypeScript", "React", "React Forget", "Forget", "Compiler"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/facebook/react-forget"
|
||||
|
||||
[workspace.dependencies]
|
||||
# workspace crates
|
||||
forget_build_hir = { path = "crates/forget_build_hir" }
|
||||
forget_estree = { path = "crates/forget_estree" }
|
||||
forget_estree_codegen = { path = "crates/forget_estree_codegen" }
|
||||
forget_estree_swc = { path = "crates/forget_estree_swc" }
|
||||
forget_fixtures = { path = "crates/forget_fixtures" }
|
||||
forget_hir = { path = "crates/forget_hir" }
|
||||
forget_optimization = { path = "crates/forget_optimization" }
|
||||
forget_ssa = { path = "crates/forget_ssa" }
|
||||
forget_swc_demo = { path = "crates/forget_swc_demo" }
|
||||
forget_utils = { path = "crates/forget_utils" }
|
||||
|
||||
# dependencies
|
||||
bumpalo = { version = "3.13.0", features = ["boxed", "collections"] }
|
||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||
insta = { version = "1.30.0", features = ["glob"] }
|
||||
miette = { version = "5.9.0" }
|
||||
prettyplease = "0.2.10"
|
||||
quote = "1.0.29"
|
||||
serde = { version = "1.0.167", features = ["serde_derive"] }
|
||||
serde_json = "1.0.100"
|
||||
stacker = "0.1.15"
|
||||
static_assertions = "1.1.0"
|
||||
swc = "0.264.8"
|
||||
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"] }
|
||||
syn = "2.0.23"
|
||||
thiserror = "1.0.41"
|
||||
|
||||
[profile.release]
|
||||
# configuration adapted from oxc
|
||||
# https://github.com/Boshen/oxc/blob/ea85ee9f2d64dd284c5b7410f491d81fb879abae/Cargo.toml#L89-L97
|
||||
opt-level = 3
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
strip = "symbols"
|
||||
debug = false
|
||||
panic = "abort" # Let it crash and force ourselves to write safe Rust.
|
||||
|
||||
# Make insta run faster by compiling with release mode optimizations
|
||||
# https://docs.rs/insta/latest/insta/#optional-faster-runs
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "build-hir"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
hir = { path = "../hir" }
|
||||
estree = { path = "../estree" }
|
||||
indexmap = "2.0.0"
|
||||
bumpalo = "3.13.0"
|
||||
miette = { version = "5.9.0" }
|
||||
thiserror = "1.0.41"
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "estree-codegen"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||
prettyplease = "0.2.10"
|
||||
quote = "1.0.29"
|
||||
serde = { version = "1.0.167", features = ["serde_derive"] }
|
||||
serde_json = "1.0.100"
|
||||
syn = "2.0.23"
|
||||
@@ -1,11 +0,0 @@
|
||||
[package]
|
||||
name = "estree-swc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
estree = { path = "../estree" }
|
||||
swc = "0.264.8"
|
||||
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"] }
|
||||
@@ -1,522 +0,0 @@
|
||||
use std::{io::stderr, num::NonZeroU32, sync::Arc};
|
||||
|
||||
use estree::{Binding, BindingId};
|
||||
use swc::Compiler;
|
||||
use swc_core::common::errors::Handler;
|
||||
use swc_core::common::source_map::Pos;
|
||||
use swc_core::common::{FileName, FilePathMapping, Mark, SourceMap, Span, SyntaxContext, GLOBALS};
|
||||
use swc_core::ecma::ast::{
|
||||
AssignOp, BinaryOp, BlockStmt, Decl, EsVersion, Expr, Function, Ident, Lit, MemberExpr,
|
||||
MemberProp, ModuleItem, Pat, PatOrExpr, Program, Stmt, UnaryOp, VarDecl, VarDeclKind,
|
||||
VarDeclOrExpr,
|
||||
};
|
||||
use swc_core::ecma::parser::Syntax;
|
||||
use swc_core::ecma::transforms::base::resolver;
|
||||
use swc_core::ecma::visit::FoldWith;
|
||||
|
||||
/// Parses source text into an estree::Program via SWC, internally performing the parsing
|
||||
/// and SWC -> ESTree conversion.
|
||||
pub fn parse(source: &str, file: &str) -> Result<estree::Program, Box<dyn std::error::Error>> {
|
||||
GLOBALS.set(&Default::default(), || {
|
||||
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let c = Compiler::new(cm);
|
||||
let fm =
|
||||
c.cm.new_source_file(FileName::Real(file.into()), source.to_string());
|
||||
|
||||
let handler = Handler::with_emitter_writer(Box::new(stderr()), Some(c.cm.clone()));
|
||||
|
||||
let comments = c.comments().clone();
|
||||
let module = c.parse_js(
|
||||
fm.clone(),
|
||||
&handler,
|
||||
EsVersion::Es5,
|
||||
Syntax::Typescript(Default::default()),
|
||||
swc::config::IsModule::Bool(true),
|
||||
Some(&comments),
|
||||
)?;
|
||||
|
||||
let context = Context {
|
||||
top_level_mark: Mark::new(),
|
||||
unresolved_mark: Mark::new(),
|
||||
};
|
||||
|
||||
let module = c.run_transform(&handler, false, || {
|
||||
module.fold_with(&mut resolver(
|
||||
context.unresolved_mark,
|
||||
context.top_level_mark,
|
||||
true,
|
||||
))
|
||||
});
|
||||
|
||||
Ok(convert_program(&context, &module))
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Context {
|
||||
unresolved_mark: Mark,
|
||||
top_level_mark: Mark,
|
||||
}
|
||||
|
||||
fn convert_program(cx: &Context, program: &Program) -> estree::Program {
|
||||
let mut program_items: Vec<estree::ModuleItem>;
|
||||
match program {
|
||||
Program::Module(program) => {
|
||||
let body = &program.body;
|
||||
program_items = Vec::with_capacity(body.len());
|
||||
for item in body {
|
||||
program_items.push(convert_module_item(cx, item));
|
||||
}
|
||||
}
|
||||
Program::Script(program) => {
|
||||
let body = &program.body;
|
||||
program_items = Vec::with_capacity(body.len());
|
||||
for item in body {
|
||||
program_items.push(estree::ModuleItem::Statement(convert_statement(cx, item)));
|
||||
}
|
||||
}
|
||||
};
|
||||
estree::Program {
|
||||
source_type: if program.is_script() {
|
||||
estree::SourceType::Script
|
||||
} else {
|
||||
estree::SourceType::Module
|
||||
},
|
||||
body: program_items,
|
||||
// comments: None,
|
||||
loc: None,
|
||||
range: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_module_item(cx: &Context, item: &ModuleItem) -> estree::ModuleItem {
|
||||
match item {
|
||||
ModuleItem::Stmt(item) => estree::ModuleItem::Statement(convert_statement(cx, item)),
|
||||
_ => todo!("translate module item {:#?}", item),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_span(span: &Span) -> Option<estree::SourceRange> {
|
||||
Some(estree::SourceRange {
|
||||
start: span.lo().to_u32(),
|
||||
end: NonZeroU32::new(span.hi().to_u32())?,
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_decl_kind(kind: &VarDeclKind) -> estree::VariableDeclarationKind {
|
||||
match kind {
|
||||
VarDeclKind::Const => estree::VariableDeclarationKind::Const,
|
||||
VarDeclKind::Let => estree::VariableDeclarationKind::Let,
|
||||
VarDeclKind::Var => estree::VariableDeclarationKind::Var,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_block_statement(cx: &Context, stmt: &BlockStmt) -> estree::BlockStatement {
|
||||
let mut body: Vec<estree::Statement> = Vec::with_capacity(stmt.stmts.len());
|
||||
for stmt in &stmt.stmts {
|
||||
body.push(convert_statement(cx, stmt));
|
||||
}
|
||||
estree::BlockStatement {
|
||||
body,
|
||||
loc: None,
|
||||
range: convert_span(&stmt.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_function(cx: &Context, id: Option<&Ident>, fun: &Function) -> estree::Function {
|
||||
estree::Function {
|
||||
id: id.map(|id| estree::Identifier {
|
||||
name: id.sym.to_string(),
|
||||
binding: convert_binding(cx, id.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&id.span),
|
||||
}),
|
||||
params: fun
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| convert_pattern(cx, ¶m.pat))
|
||||
.collect(),
|
||||
body: fun.body.as_ref().map(|body| {
|
||||
estree::FunctionBody::BlockStatement(Box::new(convert_block_statement(cx, body)))
|
||||
}),
|
||||
is_async: fun.is_async,
|
||||
is_generator: fun.is_generator,
|
||||
loc: None,
|
||||
range: convert_span(&fun.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_statement(cx: &Context, stmt: &Stmt) -> estree::Statement {
|
||||
match stmt {
|
||||
Stmt::Decl(Decl::Fn(item)) => {
|
||||
estree::Statement::FunctionDeclaration(Box::new(estree::FunctionDeclaration {
|
||||
function: convert_function(cx, Some(&item.ident), &item.function),
|
||||
loc: None,
|
||||
range: convert_span(&item.function.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Decl(Decl::Var(item)) => {
|
||||
estree::Statement::VariableDeclaration(Box::new(convert_variable_declaration(cx, item)))
|
||||
}
|
||||
Stmt::Block(item) => {
|
||||
estree::Statement::BlockStatement(Box::new(convert_block_statement(cx, item)))
|
||||
}
|
||||
Stmt::Break(item) => estree::Statement::BreakStatement(Box::new(estree::BreakStatement {
|
||||
label: item
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| convert_identifier(cx, label)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
})),
|
||||
Stmt::Continue(item) => {
|
||||
estree::Statement::ContinueStatement(Box::new(estree::ContinueStatement {
|
||||
label: item
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| convert_identifier(cx, label)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Debugger(item) => {
|
||||
estree::Statement::DebuggerStatement(Box::new(estree::DebuggerStatement {
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::DoWhile(item) => {
|
||||
estree::Statement::DoWhileStatement(Box::new(estree::DoWhileStatement {
|
||||
body: convert_statement(cx, &item.body),
|
||||
test: convert_expression(cx, &item.test),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Empty(item) => estree::Statement::EmptyStatement(Box::new(estree::EmptyStatement {
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
})),
|
||||
Stmt::Expr(item) => {
|
||||
let expression = convert_expression(cx, &item.expr);
|
||||
estree::Statement::ExpressionStatement(Box::new(estree::ExpressionStatement {
|
||||
expression,
|
||||
directive: None,
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::For(item) => estree::Statement::ForStatement(Box::new(estree::ForStatement {
|
||||
init: item.init.as_ref().map(|init| match init {
|
||||
VarDeclOrExpr::Expr(init) => {
|
||||
estree::ForInit::Expression(convert_expression(cx, init))
|
||||
}
|
||||
VarDeclOrExpr::VarDecl(init) => {
|
||||
assert_eq!(init.decls.len(), 1);
|
||||
estree::ForInit::VariableDeclaration(Box::new(convert_variable_declaration(
|
||||
cx, init,
|
||||
)))
|
||||
}
|
||||
}),
|
||||
test: item.test.as_ref().map(|test| convert_expression(cx, test)),
|
||||
update: item
|
||||
.update
|
||||
.as_ref()
|
||||
.map(|update| convert_expression(cx, update)),
|
||||
body: convert_statement(cx, &item.body),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
})),
|
||||
Stmt::Return(item) => {
|
||||
estree::Statement::ReturnStatement(Box::new(estree::ReturnStatement {
|
||||
argument: item.arg.as_ref().map(|arg| convert_expression(cx, arg)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Throw(item) => estree::Statement::ThrowStatement(Box::new(estree::ThrowStatement {
|
||||
argument: convert_expression(cx, &item.arg),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
})),
|
||||
Stmt::If(item) => estree::Statement::IfStatement(Box::new(estree::IfStatement {
|
||||
test: convert_expression(cx, &item.test),
|
||||
consequent: convert_statement(cx, &item.cons),
|
||||
alternate: item.alt.as_ref().map(|alt| convert_statement(cx, alt)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
})),
|
||||
_ => todo!("translate statement {:#?}", stmt),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_variable_declaration(cx: &Context, decl: &VarDecl) -> estree::VariableDeclaration {
|
||||
estree::VariableDeclaration {
|
||||
kind: convert_decl_kind(&decl.kind),
|
||||
declarations: decl
|
||||
.decls
|
||||
.iter()
|
||||
.map(|declarator| estree::VariableDeclarator {
|
||||
id: convert_pattern(cx, &declarator.name),
|
||||
init: declarator
|
||||
.init
|
||||
.as_ref()
|
||||
.map(|init| convert_expression(cx, init)),
|
||||
loc: None,
|
||||
range: convert_span(&decl.span),
|
||||
})
|
||||
.collect(),
|
||||
loc: None,
|
||||
range: convert_span(&decl.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_expression(cx: &Context, expr: &Expr) -> estree::Expression {
|
||||
match expr {
|
||||
Expr::Ident(expr) => estree::Expression::Identifier(Box::new(convert_identifier(cx, expr))),
|
||||
Expr::Array(expr) => {
|
||||
estree::Expression::ArrayExpression(Box::new(estree::ArrayExpression {
|
||||
elements: expr
|
||||
.elems
|
||||
.iter()
|
||||
.map(|item| {
|
||||
// TODO: represent holes in array expressions
|
||||
let value = item.as_ref()?;
|
||||
match value.spread {
|
||||
Some(spread) => Some(estree::ExpressionOrSpread::SpreadElement(
|
||||
Box::new(estree::SpreadElement {
|
||||
argument: convert_expression(cx, &value.expr),
|
||||
loc: None,
|
||||
range: convert_span(&spread),
|
||||
}),
|
||||
)),
|
||||
None => Some(estree::ExpressionOrSpread::Expression(
|
||||
convert_expression(cx, &value.expr),
|
||||
)),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Expr::Await(_expr) => {
|
||||
// estree::Expression::AwaitExpression(Box::new(estree::AwaitExpression {
|
||||
// argument: convert_expression(cx, &expr.arg),
|
||||
// loc: None,
|
||||
// range: convert_span(&expr.span),
|
||||
// }))
|
||||
todo!("await expression")
|
||||
}
|
||||
Expr::Unary(expr) => {
|
||||
estree::Expression::UnaryExpression(Box::new(estree::UnaryExpression {
|
||||
operator: convert_unary_operator(expr.op),
|
||||
prefix: false,
|
||||
argument: convert_expression(cx, &expr.arg),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Expr::Bin(expr) => match convert_binary_operator(expr.op) {
|
||||
Operator::Binary(op) => {
|
||||
estree::Expression::BinaryExpression(Box::new(estree::BinaryExpression {
|
||||
operator: op,
|
||||
left: convert_expression(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Operator::Logical(op) => {
|
||||
estree::Expression::LogicalExpression(Box::new(estree::LogicalExpression {
|
||||
operator: op,
|
||||
left: convert_expression(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
},
|
||||
Expr::Lit(expr) => {
|
||||
let (value, range) = match expr {
|
||||
Lit::Bool(expr) => (estree::JsValue::Bool(expr.value), convert_span(&expr.span)),
|
||||
Lit::Num(expr) => (
|
||||
estree::JsValue::Number(expr.value.into()),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Str(expr) => (
|
||||
estree::JsValue::String(expr.value.to_string()),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Null(expr) => (estree::JsValue::Null, convert_span(&expr.span)),
|
||||
_ => todo!(),
|
||||
};
|
||||
estree::Expression::Literal(Box::new(estree::Literal {
|
||||
value,
|
||||
raw: None,
|
||||
loc: None,
|
||||
regex: None,
|
||||
range,
|
||||
}))
|
||||
}
|
||||
Expr::Assign(expr) => {
|
||||
estree::Expression::AssignmentExpression(Box::new(estree::AssignmentExpression {
|
||||
operator: convert_assignment_operator(expr.op),
|
||||
left: convert_assignment_target(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Expr::Member(expr) => {
|
||||
estree::Expression::MemberExpression(Box::new(convert_member_expression(cx, expr)))
|
||||
}
|
||||
Expr::Fn(expr) => {
|
||||
estree::Expression::FunctionExpression(Box::new(estree::FunctionExpression {
|
||||
function: convert_function(cx, expr.ident.as_ref(), &expr.function),
|
||||
loc: None,
|
||||
range: convert_span(&expr.function.span),
|
||||
}))
|
||||
}
|
||||
_ => todo!("translate expression {:#?}", expr),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_assignment_target(cx: &Context, target: &PatOrExpr) -> estree::AssignmentTarget {
|
||||
match target {
|
||||
PatOrExpr::Pat(target) => estree::AssignmentTarget::Pattern(convert_pattern(cx, target)),
|
||||
PatOrExpr::Expr(target) => {
|
||||
match target.as_ref() {
|
||||
Expr::Member(target) => {
|
||||
estree::AssignmentTarget::Expression(estree::Expression::MemberExpression(
|
||||
Box::new(convert_member_expression(cx, target)),
|
||||
))
|
||||
}
|
||||
Expr::Ident(target) => estree::AssignmentTarget::Pattern(
|
||||
estree::Pattern::Identifier(Box::new(convert_identifier(cx, target))),
|
||||
),
|
||||
_ => {
|
||||
panic!("Expected assignment target to be member expression or identifier, got {:#?}", target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> estree::MemberExpression {
|
||||
let (is_computed, property) = match &expr.prop {
|
||||
MemberProp::Ident(prop) => (
|
||||
false,
|
||||
estree::Expression::Identifier(Box::new(convert_identifier(cx, prop))),
|
||||
),
|
||||
MemberProp::Computed(prop) => (true, convert_expression(cx, &prop.expr)),
|
||||
_ => {
|
||||
panic!("PrivateName member expression properties are not supported")
|
||||
}
|
||||
};
|
||||
estree::MemberExpression {
|
||||
object: estree::ExpressionOrSuper::Expression(convert_expression(cx, &expr.obj)),
|
||||
property,
|
||||
computed: is_computed,
|
||||
// optional: false, // TODO
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_unary_operator(op: UnaryOp) -> estree::UnaryOperator {
|
||||
match op {
|
||||
UnaryOp::Bang => estree::UnaryOperator::Negation,
|
||||
UnaryOp::Delete => estree::UnaryOperator::Delete,
|
||||
UnaryOp::Minus => estree::UnaryOperator::Minus,
|
||||
UnaryOp::Plus => estree::UnaryOperator::Plus,
|
||||
UnaryOp::Tilde => estree::UnaryOperator::Tilde,
|
||||
UnaryOp::TypeOf => estree::UnaryOperator::Typeof,
|
||||
UnaryOp::Void => estree::UnaryOperator::Void,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_assignment_operator(op: AssignOp) -> estree::AssignmentOperator {
|
||||
match op {
|
||||
AssignOp::Assign => estree::AssignmentOperator::Equals,
|
||||
AssignOp::AddAssign => estree::AssignmentOperator::PlusEquals,
|
||||
_ => todo!("translate assignment operator"),
|
||||
}
|
||||
}
|
||||
|
||||
enum Operator {
|
||||
Binary(estree::BinaryOperator),
|
||||
Logical(estree::LogicalOperator),
|
||||
}
|
||||
|
||||
fn convert_binary_operator(op: BinaryOp) -> Operator {
|
||||
match op {
|
||||
BinaryOp::Add => Operator::Binary(estree::BinaryOperator::Add),
|
||||
BinaryOp::BitAnd => Operator::Binary(estree::BinaryOperator::BinaryAnd),
|
||||
BinaryOp::BitOr => Operator::Binary(estree::BinaryOperator::BinaryOr),
|
||||
BinaryOp::BitXor => Operator::Binary(estree::BinaryOperator::BinaryXor),
|
||||
BinaryOp::Div => Operator::Binary(estree::BinaryOperator::Divide),
|
||||
BinaryOp::EqEq => Operator::Binary(estree::BinaryOperator::Equals),
|
||||
BinaryOp::EqEqEq => Operator::Binary(estree::BinaryOperator::StrictEquals),
|
||||
// BinaryOp::Exp => Operator::Binary(estree::BinaryOperator::AsteriskAsterisk),
|
||||
BinaryOp::Gt => Operator::Binary(estree::BinaryOperator::GreaterThan),
|
||||
BinaryOp::GtEq => Operator::Binary(estree::BinaryOperator::GreaterThanOrEqual),
|
||||
BinaryOp::In => Operator::Binary(estree::BinaryOperator::In),
|
||||
BinaryOp::InstanceOf => Operator::Binary(estree::BinaryOperator::Instanceof),
|
||||
BinaryOp::LShift => Operator::Binary(estree::BinaryOperator::ShiftLeft),
|
||||
BinaryOp::Lt => Operator::Binary(estree::BinaryOperator::LessThan),
|
||||
BinaryOp::LtEq => Operator::Binary(estree::BinaryOperator::LessThanOrEqual),
|
||||
BinaryOp::Mod => Operator::Binary(estree::BinaryOperator::Modulo),
|
||||
BinaryOp::Mul => Operator::Binary(estree::BinaryOperator::Multiply),
|
||||
BinaryOp::NotEq => Operator::Binary(estree::BinaryOperator::NotEquals),
|
||||
BinaryOp::NotEqEq => Operator::Binary(estree::BinaryOperator::NotStrictEquals),
|
||||
BinaryOp::RShift => Operator::Binary(estree::BinaryOperator::ShiftRight),
|
||||
BinaryOp::Sub => Operator::Binary(estree::BinaryOperator::Subtract),
|
||||
BinaryOp::ZeroFillRShift => Operator::Binary(estree::BinaryOperator::UnsignedShiftRight),
|
||||
|
||||
BinaryOp::LogicalAnd => Operator::Logical(estree::LogicalOperator::And),
|
||||
BinaryOp::LogicalOr => Operator::Logical(estree::LogicalOperator::Or),
|
||||
BinaryOp::NullishCoalescing => Operator::Logical(estree::LogicalOperator::NullCoalescing),
|
||||
|
||||
_ => panic!("Unsupported binary operator `{}`", op),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_pattern(cx: &Context, pat: &Pat) -> estree::Pattern {
|
||||
match pat {
|
||||
Pat::Ident(pat) => estree::Pattern::Identifier(Box::new(estree::Identifier {
|
||||
name: pat.id.sym.to_string(),
|
||||
binding: convert_binding(cx, pat.id.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&pat.span),
|
||||
})),
|
||||
_ => todo!("translate pattern {:#?}", pat),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_binding(context: &Context, binding_cx: SyntaxContext) -> Option<Binding> {
|
||||
let id = BindingId::new(binding_cx.as_u32());
|
||||
if binding_cx.as_u32() == context.top_level_mark.as_u32() {
|
||||
Some(Binding::Global)
|
||||
} else if binding_cx.as_u32() == context.unresolved_mark.as_u32() {
|
||||
Some(Binding::Module(id))
|
||||
} else {
|
||||
Some(Binding::Local(id))
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_identifier(cx: &Context, identifier: &Ident) -> estree::Identifier {
|
||||
let name = identifier.sym.as_ref().to_string();
|
||||
estree::Identifier {
|
||||
name,
|
||||
binding: convert_binding(cx, identifier.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&identifier.span),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "estree"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { version = "3.13.0", features = ["boxed", "collections"] }
|
||||
elsa = "1.8.1"
|
||||
insta = { version = "1.30.0", features = ["glob"] }
|
||||
serde = { version = "1.0.164", features = ["derive"] }
|
||||
serde_json = "1.0.99"
|
||||
static_assertions = "1.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
estree-codegen = { path = "../estree-codegen" }
|
||||
@@ -1,13 +0,0 @@
|
||||
use estree_codegen::estree;
|
||||
|
||||
// Example custom build script.
|
||||
fn main() {
|
||||
// Re-run if the codegen files change
|
||||
println!("cargo:rerun-if-changed=../estree-codegen/src/codegen.rs");
|
||||
println!("cargo:rerun-if-changed=../estree-codegen/src/lib.rs");
|
||||
println!("cargo:rerun-if-changed=../estree-codegen/src/ecmascript.json");
|
||||
println!("cargo:rerun-if-changed=../estree-codegen");
|
||||
|
||||
let src = estree();
|
||||
std::fs::write("src/generated.rs", src).unwrap();
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
[package]
|
||||
name = "fixtures"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
insta = "1.30.0"
|
||||
estree = { path = "../estree" }
|
||||
estree-swc = { path = "../estree-swc" }
|
||||
hir = { path = "../hir" }
|
||||
hir-optimization = { path = "../hir-optimization" }
|
||||
hir-ssa = { path = "../hir-ssa" }
|
||||
build-hir = { path = "../build-hir" }
|
||||
bumpalo = { version = "3.13.0", features = ["collections"] }
|
||||
miette = { version = "5.9.0", features = ["backtrace", "fancy"] }
|
||||
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "forget_build_hir"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
forget_hir = { workspace = true }
|
||||
forget_estree = { workspace = true}
|
||||
indexmap = { workspace = true }
|
||||
bumpalo = { workspace = true }
|
||||
miette = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
+30
-30
@@ -1,12 +1,12 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use bumpalo::{boxed::Box, collections::String};
|
||||
use estree::{
|
||||
use forget_estree::{
|
||||
AssignmentTarget, BinaryExpression, BlockStatement, Expression, ForInit, ForStatement,
|
||||
Function, FunctionExpression, IfStatement, JsValue, Literal, Pattern, Statement,
|
||||
VariableDeclarationKind,
|
||||
};
|
||||
use hir::{
|
||||
use forget_hir::{
|
||||
ArrayElement, BlockKind, BranchTerminal, Environment, ForTerminal, GotoKind, IdentifierOperand,
|
||||
InstrIx, InstructionKind, InstructionValue, LValue, LoadGlobal, LoadLocal, Operand,
|
||||
PrimitiveValue, TerminalValue,
|
||||
@@ -28,14 +28,14 @@ use crate::{
|
||||
pub fn build<'a>(
|
||||
env: &'a Environment<'a>,
|
||||
fun: Function,
|
||||
) -> Result<Box<'a, hir::Function<'a>>, BuildDiagnostic> {
|
||||
) -> Result<Box<'a, forget_hir::Function<'a>>, BuildDiagnostic> {
|
||||
let mut builder = Builder::new(env);
|
||||
|
||||
match fun.body {
|
||||
Some(estree::FunctionBody::BlockStatement(body)) => {
|
||||
Some(forget_estree::FunctionBody::BlockStatement(body)) => {
|
||||
lower_block_statement(env, &mut builder, *body)?
|
||||
}
|
||||
Some(estree::FunctionBody::Expression(body)) => {
|
||||
Some(forget_estree::FunctionBody::Expression(body)) => {
|
||||
lower_expression(env, &mut builder, body)?;
|
||||
}
|
||||
None => {
|
||||
@@ -65,21 +65,21 @@ pub fn build<'a>(
|
||||
// In case the function did not explicitly return, terminate the final
|
||||
// block with an explicit `return undefined`. If the function *did* return,
|
||||
// this will be unreachable and get pruned later.
|
||||
let implicit_return_value = builder.push(InstructionValue::Primitive(hir::Primitive {
|
||||
let implicit_return_value = builder.push(InstructionValue::Primitive(forget_hir::Primitive {
|
||||
value: PrimitiveValue::Undefined,
|
||||
}));
|
||||
builder.terminate(
|
||||
TerminalValue::Return(hir::ReturnTerminal {
|
||||
TerminalValue::Return(forget_hir::ReturnTerminal {
|
||||
value: Operand {
|
||||
ix: implicit_return_value,
|
||||
effect: None,
|
||||
},
|
||||
}),
|
||||
hir::BlockKind::Block,
|
||||
forget_hir::BlockKind::Block,
|
||||
);
|
||||
|
||||
let body = builder.build()?;
|
||||
Ok(env.box_new(hir::Function {
|
||||
Ok(env.box_new(forget_hir::Function {
|
||||
id: fun
|
||||
.id
|
||||
.map(|id| String::from_str_in(&id.name, &env.allocator)),
|
||||
@@ -118,7 +118,7 @@ fn lower_statement<'a>(
|
||||
Statement::BreakStatement(stmt) => {
|
||||
let block = builder.resolve_break(stmt.label.as_ref())?;
|
||||
builder.terminate(
|
||||
TerminalValue::Goto(hir::GotoTerminal {
|
||||
TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block,
|
||||
kind: GotoKind::Break,
|
||||
}),
|
||||
@@ -128,7 +128,7 @@ fn lower_statement<'a>(
|
||||
Statement::ContinueStatement(stmt) => {
|
||||
let block = builder.resolve_continue(stmt.label.as_ref())?;
|
||||
builder.terminate(
|
||||
TerminalValue::Goto(hir::GotoTerminal {
|
||||
TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block,
|
||||
kind: GotoKind::Continue,
|
||||
}),
|
||||
@@ -138,12 +138,12 @@ fn lower_statement<'a>(
|
||||
Statement::ReturnStatement(stmt) => {
|
||||
let ix = match stmt.argument {
|
||||
Some(argument) => lower_expression(env, builder, argument)?,
|
||||
None => builder.push(InstructionValue::Primitive(hir::Primitive {
|
||||
None => builder.push(InstructionValue::Primitive(forget_hir::Primitive {
|
||||
value: PrimitiveValue::Undefined,
|
||||
})),
|
||||
};
|
||||
builder.terminate(
|
||||
TerminalValue::Return(hir::ReturnTerminal {
|
||||
TerminalValue::Return(forget_hir::ReturnTerminal {
|
||||
value: Operand { ix, effect: None },
|
||||
}),
|
||||
BlockKind::Block,
|
||||
@@ -191,7 +191,7 @@ fn lower_statement<'a>(
|
||||
));
|
||||
}
|
||||
};
|
||||
builder.push(InstructionValue::DeclareLocal(hir::DeclareLocal {
|
||||
builder.push(InstructionValue::DeclareLocal(forget_hir::DeclareLocal {
|
||||
lvalue: LValue {
|
||||
identifier: IdentifierOperand {
|
||||
identifier,
|
||||
@@ -218,7 +218,7 @@ fn lower_statement<'a>(
|
||||
|
||||
let consequent_block = builder.enter(BlockKind::Block, |builder| {
|
||||
lower_statement(env, builder, consequent, None)?;
|
||||
Ok(TerminalValue::Goto(hir::GotoTerminal {
|
||||
Ok(TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: fallthrough_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
@@ -228,14 +228,14 @@ fn lower_statement<'a>(
|
||||
if let Some(alternate) = alternate {
|
||||
lower_statement(env, builder, alternate, None)?;
|
||||
}
|
||||
Ok(TerminalValue::Goto(hir::GotoTerminal {
|
||||
Ok(TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: fallthrough_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
})?;
|
||||
|
||||
let test = lower_expression(env, builder, test)?;
|
||||
let terminal = TerminalValue::If(hir::IfTerminal {
|
||||
let terminal = TerminalValue::If(forget_hir::IfTerminal {
|
||||
test: Operand {
|
||||
ix: test,
|
||||
effect: None,
|
||||
@@ -264,7 +264,7 @@ fn lower_statement<'a>(
|
||||
let init_block = builder.enter(BlockKind::Loop, |builder| {
|
||||
if let Some(ForInit::VariableDeclaration(decl)) = init {
|
||||
lower_statement(env, builder, Statement::VariableDeclaration(decl), None)?;
|
||||
Ok(TerminalValue::Goto(hir::GotoTerminal {
|
||||
Ok(TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: test_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
@@ -281,7 +281,7 @@ fn lower_statement<'a>(
|
||||
.map(|update| {
|
||||
builder.enter(BlockKind::Loop, |builder| {
|
||||
lower_expression(env, builder, update)?;
|
||||
Ok(TerminalValue::Goto(hir::GotoTerminal {
|
||||
Ok(TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: test_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
@@ -297,7 +297,7 @@ fn lower_statement<'a>(
|
||||
};
|
||||
builder.enter_loop(loop_, |builder| {
|
||||
lower_statement(env, builder, body, None)?;
|
||||
Ok(TerminalValue::Goto(hir::GotoTerminal {
|
||||
Ok(TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: update_block.unwrap_or(test_block.id),
|
||||
kind: GotoKind::Continue,
|
||||
}))
|
||||
@@ -363,20 +363,20 @@ fn lower_expression<'a>(
|
||||
}),
|
||||
}
|
||||
}
|
||||
Expression::Literal(expr) => InstructionValue::Primitive(hir::Primitive {
|
||||
Expression::Literal(expr) => InstructionValue::Primitive(forget_hir::Primitive {
|
||||
value: lower_primitive(env, builder, *expr),
|
||||
}),
|
||||
Expression::ArrayExpression(expr) => {
|
||||
let mut elements = env.vec_with_capacity(expr.elements.len());
|
||||
for expr in expr.elements {
|
||||
let element = match expr {
|
||||
Some(estree::ExpressionOrSpread::SpreadElement(expr)) => {
|
||||
Some(forget_estree::ExpressionOrSpread::SpreadElement(expr)) => {
|
||||
Some(ArrayElement::Spread(Operand {
|
||||
ix: lower_expression(env, builder, expr.argument)?,
|
||||
effect: None,
|
||||
}))
|
||||
}
|
||||
Some(estree::ExpressionOrSpread::Expression(expr)) => {
|
||||
Some(forget_estree::ExpressionOrSpread::Expression(expr)) => {
|
||||
Some(ArrayElement::Place(Operand {
|
||||
ix: lower_expression(env, builder, expr)?,
|
||||
effect: None,
|
||||
@@ -386,11 +386,11 @@ fn lower_expression<'a>(
|
||||
};
|
||||
elements.push(element);
|
||||
}
|
||||
InstructionValue::Array(hir::Array { elements })
|
||||
InstructionValue::Array(forget_hir::Array { elements })
|
||||
}
|
||||
|
||||
Expression::AssignmentExpression(expr) => match expr.operator {
|
||||
estree::AssignmentOperator::Equals => {
|
||||
forget_estree::AssignmentOperator::Equals => {
|
||||
let right = lower_expression(env, builder, expr.right)?;
|
||||
return Ok(lower_assignment(
|
||||
env,
|
||||
@@ -412,7 +412,7 @@ fn lower_expression<'a>(
|
||||
} = *expr;
|
||||
let left = lower_expression(env, builder, left)?;
|
||||
let right = lower_expression(env, builder, right)?;
|
||||
InstructionValue::Binary(hir::Binary {
|
||||
InstructionValue::Binary(forget_hir::Binary {
|
||||
left: Operand {
|
||||
ix: left,
|
||||
effect: None,
|
||||
@@ -438,7 +438,7 @@ fn lower_function<'a>(
|
||||
env: &'a Environment<'a>,
|
||||
builder: &mut Builder<'a>,
|
||||
expr: FunctionExpression,
|
||||
) -> Result<hir::FunctionExpression<'a>, BuildDiagnostic> {
|
||||
) -> Result<forget_hir::FunctionExpression<'a>, BuildDiagnostic> {
|
||||
let FunctionExpression { function, .. } = expr;
|
||||
println!("get_context_identifiers() ...");
|
||||
let context_identifiers = get_context_identifiers(env, &function);
|
||||
@@ -461,7 +461,7 @@ fn lower_function<'a>(
|
||||
}
|
||||
let mut fun = build(env, function)?;
|
||||
fun.context = context;
|
||||
Ok(hir::FunctionExpression {
|
||||
Ok(forget_hir::FunctionExpression {
|
||||
// TODO: collect dependencies!
|
||||
dependencies: env.vec_new(),
|
||||
lowered_function: fun,
|
||||
@@ -479,7 +479,7 @@ fn lower_assignment<'a>(
|
||||
AssignmentTarget::Pattern(lvalue) => match lvalue {
|
||||
Pattern::Identifier(lvalue) => {
|
||||
let identifier = lower_identifier_for_assignment(env, builder, kind, *lvalue)?;
|
||||
builder.push(InstructionValue::StoreLocal(hir::StoreLocal {
|
||||
builder.push(InstructionValue::StoreLocal(forget_hir::StoreLocal {
|
||||
lvalue: LValue { identifier, kind },
|
||||
value: Operand {
|
||||
ix: value,
|
||||
@@ -497,7 +497,7 @@ fn lower_identifier_for_assignment<'a>(
|
||||
_env: &'a Environment<'a>,
|
||||
builder: &mut Builder<'a>,
|
||||
_kind: InstructionKind,
|
||||
identifier: estree::Identifier,
|
||||
identifier: forget_estree::Identifier,
|
||||
) -> Result<IdentifierOperand<'a>, BuildDiagnostic> {
|
||||
let binding = builder.resolve_identifier(&identifier)?;
|
||||
match binding {
|
||||
+11
-11
@@ -4,7 +4,7 @@ use bumpalo::{
|
||||
};
|
||||
use std::{cell::RefCell, collections::HashSet, rc::Rc};
|
||||
|
||||
use hir::{
|
||||
use forget_hir::{
|
||||
BasicBlock, BlockId, BlockKind, Environment, GotoKind, Identifier, IdentifierData, InstrIx,
|
||||
Instruction, InstructionIdGenerator, InstructionValue, Terminal, TerminalValue, Type, HIR,
|
||||
};
|
||||
@@ -197,7 +197,7 @@ impl<'a> Builder<'a> {
|
||||
Err(error) => (
|
||||
Err(error),
|
||||
// TODO: add a `Terminal::Error` variant
|
||||
TerminalValue::Goto(hir::GotoTerminal {
|
||||
TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: current.id,
|
||||
kind: GotoKind::Break,
|
||||
}),
|
||||
@@ -242,8 +242,8 @@ impl<'a> Builder<'a> {
|
||||
/// we synthesize a temporary identifier to store the possibly-missing value
|
||||
/// into, and emit a later StoreLocal for the original identifier
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn make_temporary(&self) -> hir::Identifier<'a> {
|
||||
hir::Identifier {
|
||||
pub(crate) fn make_temporary(&self) -> forget_hir::Identifier<'a> {
|
||||
forget_hir::Identifier {
|
||||
id: self.environment.next_identifier_id(),
|
||||
name: None,
|
||||
data: Rc::new(RefCell::new(IdentifierData {
|
||||
@@ -259,7 +259,7 @@ impl<'a> Builder<'a> {
|
||||
/// provided but cannot be resolved.
|
||||
pub(crate) fn resolve_break(
|
||||
&self,
|
||||
label: Option<&estree::Identifier>,
|
||||
label: Option<&forget_estree::Identifier>,
|
||||
) -> Result<BlockId, BuildDiagnostic> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
match (label, scope.label()) {
|
||||
@@ -285,7 +285,7 @@ impl<'a> Builder<'a> {
|
||||
/// provided but cannot be resolved.
|
||||
pub(crate) fn resolve_continue(
|
||||
&self,
|
||||
label: Option<&estree::Identifier>,
|
||||
label: Option<&forget_estree::Identifier>,
|
||||
) -> Result<BlockId, BuildDiagnostic> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
match scope {
|
||||
@@ -327,16 +327,16 @@ impl<'a> Builder<'a> {
|
||||
|
||||
pub(crate) fn resolve_identifier(
|
||||
&mut self,
|
||||
identifier: &estree::Identifier,
|
||||
identifier: &forget_estree::Identifier,
|
||||
) -> Result<Binding<'a>, BuildDiagnostic> {
|
||||
match &identifier.binding {
|
||||
Some(binding) => Ok(match binding {
|
||||
estree::Binding::Global => Binding::Global,
|
||||
estree::Binding::Local(id) => Binding::Local(
|
||||
forget_estree::Binding::Global => Binding::Global,
|
||||
forget_estree::Binding::Local(id) => Binding::Local(
|
||||
self.environment
|
||||
.resolve_binding_identifier(&identifier.name, *id),
|
||||
),
|
||||
estree::Binding::Module(id) => Binding::Module(
|
||||
forget_estree::Binding::Module(id) => Binding::Module(
|
||||
self.environment
|
||||
.resolve_binding_identifier(&identifier.name, *id),
|
||||
),
|
||||
@@ -454,7 +454,7 @@ pub fn remove_unreachable_do_while_statements<'a>(hir: &mut HIR<'a>) {
|
||||
for block in hir.blocks.values_mut() {
|
||||
if let TerminalValue::DoWhile(terminal) = &mut block.terminal.value {
|
||||
if !block_ids.contains(&terminal.test) {
|
||||
block.terminal.value = TerminalValue::Goto(hir::GotoTerminal {
|
||||
block.terminal.value = TerminalValue::Goto(forget_hir::GotoTerminal {
|
||||
block: terminal.body,
|
||||
kind: GotoKind::Break,
|
||||
});
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use estree::{Binding, BindingId, Expression, ExpressionOrSuper, Function, Identifier, Visitor};
|
||||
use hir::Environment;
|
||||
use forget_estree::{Binding, BindingId, Function, Identifier, Visitor};
|
||||
use forget_hir::Environment;
|
||||
|
||||
pub(crate) fn get_context_identifiers<'a, 'ast>(
|
||||
_env: &'a Environment<'a>,
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
use estree::SourceRange;
|
||||
use hir::BlockId;
|
||||
use forget_estree::SourceRange;
|
||||
use forget_hir::BlockId;
|
||||
use miette::{ByteOffset, Diagnostic, SourceSpan};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "forget_estree"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { workspace = true }
|
||||
insta = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
static_assertions = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
forget_estree_codegen = { workspace = true }
|
||||
@@ -0,0 +1,13 @@
|
||||
use forget_estree_codegen::estree;
|
||||
|
||||
// Example custom build script.
|
||||
fn main() {
|
||||
// Re-run if the codegen files change
|
||||
println!("cargo:rerun-if-changed=../forget_estree_codegen/src/codegen.rs");
|
||||
println!("cargo:rerun-if-changed=../forget_estree_codegen/src/lib.rs");
|
||||
println!("cargo:rerun-if-changed=../forget_estree_codegen/src/ecmascript.json");
|
||||
println!("cargo:rerun-if-changed=../forget_estree_codegen");
|
||||
|
||||
let src = estree();
|
||||
std::fs::write("src/generated.rs", src).unwrap();
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/estree/src/lib.rs
|
||||
source: crates/forget_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/estree/src/fixtures/for-statement.json
|
||||
input_file: crates/forget_estree/src/fixtures/for-statement.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/estree/src/lib.rs
|
||||
source: crates/forget_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/estree/src/fixtures/import.json
|
||||
input_file: crates/forget_estree/src/fixtures/import.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/estree/src/lib.rs
|
||||
source: crates/forget_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/estree/src/fixtures/simple.json
|
||||
input_file: crates/forget_estree/src/fixtures/simple.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/estree/src/lib.rs
|
||||
source: crates/forget_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/estree/src/fixtures/test.json
|
||||
input_file: crates/forget_estree/src/fixtures/test.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "forget_estree_codegen"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
indexmap = { workspace = true }
|
||||
prettyplease = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
syn = { workspace = true }
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "forget_estree_swc"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
forget_estree = { workspace = true }
|
||||
swc = { workspace = true }
|
||||
swc_core = { workspace = true }
|
||||
@@ -0,0 +1,555 @@
|
||||
use std::{io::stderr, num::NonZeroU32, sync::Arc};
|
||||
|
||||
use forget_estree::{Binding, BindingId};
|
||||
use swc::Compiler;
|
||||
use swc_core::common::errors::Handler;
|
||||
use swc_core::common::source_map::Pos;
|
||||
use swc_core::common::{FileName, FilePathMapping, Mark, SourceMap, Span, SyntaxContext, GLOBALS};
|
||||
use swc_core::ecma::ast::{
|
||||
AssignOp, BinaryOp, BlockStmt, Decl, EsVersion, Expr, Function, Ident, Lit, MemberExpr,
|
||||
MemberProp, ModuleItem, Pat, PatOrExpr, Program, Stmt, UnaryOp, VarDecl, VarDeclKind,
|
||||
VarDeclOrExpr,
|
||||
};
|
||||
use swc_core::ecma::parser::Syntax;
|
||||
use swc_core::ecma::transforms::base::resolver;
|
||||
use swc_core::ecma::visit::FoldWith;
|
||||
|
||||
/// Parses source text into an forget_estree::Program via SWC, internally performing the parsing
|
||||
/// and SWC -> ESTree conversion.
|
||||
pub fn parse(
|
||||
source: &str,
|
||||
file: &str,
|
||||
) -> Result<forget_estree::Program, Box<dyn std::error::Error>> {
|
||||
GLOBALS.set(&Default::default(), || {
|
||||
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let c = Compiler::new(cm);
|
||||
let fm =
|
||||
c.cm.new_source_file(FileName::Real(file.into()), source.to_string());
|
||||
|
||||
let handler = Handler::with_emitter_writer(Box::new(stderr()), Some(c.cm.clone()));
|
||||
|
||||
let comments = c.comments().clone();
|
||||
let module = c.parse_js(
|
||||
fm.clone(),
|
||||
&handler,
|
||||
EsVersion::Es5,
|
||||
Syntax::Typescript(Default::default()),
|
||||
swc::config::IsModule::Bool(true),
|
||||
Some(&comments),
|
||||
)?;
|
||||
|
||||
let context = Context {
|
||||
top_level_mark: Mark::new(),
|
||||
unresolved_mark: Mark::new(),
|
||||
};
|
||||
|
||||
let module = c.run_transform(&handler, false, || {
|
||||
module.fold_with(&mut resolver(
|
||||
context.unresolved_mark,
|
||||
context.top_level_mark,
|
||||
true,
|
||||
))
|
||||
});
|
||||
|
||||
Ok(convert_program(&context, &module))
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Context {
|
||||
unresolved_mark: Mark,
|
||||
top_level_mark: Mark,
|
||||
}
|
||||
|
||||
fn convert_program(cx: &Context, program: &Program) -> forget_estree::Program {
|
||||
let mut program_items: Vec<forget_estree::ModuleItem>;
|
||||
match program {
|
||||
Program::Module(program) => {
|
||||
let body = &program.body;
|
||||
program_items = Vec::with_capacity(body.len());
|
||||
for item in body {
|
||||
program_items.push(convert_module_item(cx, item));
|
||||
}
|
||||
}
|
||||
Program::Script(program) => {
|
||||
let body = &program.body;
|
||||
program_items = Vec::with_capacity(body.len());
|
||||
for item in body {
|
||||
program_items.push(forget_estree::ModuleItem::Statement(convert_statement(
|
||||
cx, item,
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
forget_estree::Program {
|
||||
source_type: if program.is_script() {
|
||||
forget_estree::SourceType::Script
|
||||
} else {
|
||||
forget_estree::SourceType::Module
|
||||
},
|
||||
body: program_items,
|
||||
// comments: None,
|
||||
loc: None,
|
||||
range: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_module_item(cx: &Context, item: &ModuleItem) -> forget_estree::ModuleItem {
|
||||
match item {
|
||||
ModuleItem::Stmt(item) => forget_estree::ModuleItem::Statement(convert_statement(cx, item)),
|
||||
_ => todo!("translate module item {:#?}", item),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_span(span: &Span) -> Option<forget_estree::SourceRange> {
|
||||
Some(forget_estree::SourceRange {
|
||||
start: span.lo().to_u32(),
|
||||
end: NonZeroU32::new(span.hi().to_u32())?,
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_decl_kind(kind: &VarDeclKind) -> forget_estree::VariableDeclarationKind {
|
||||
match kind {
|
||||
VarDeclKind::Const => forget_estree::VariableDeclarationKind::Const,
|
||||
VarDeclKind::Let => forget_estree::VariableDeclarationKind::Let,
|
||||
VarDeclKind::Var => forget_estree::VariableDeclarationKind::Var,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_block_statement(cx: &Context, stmt: &BlockStmt) -> forget_estree::BlockStatement {
|
||||
let mut body: Vec<forget_estree::Statement> = Vec::with_capacity(stmt.stmts.len());
|
||||
for stmt in &stmt.stmts {
|
||||
body.push(convert_statement(cx, stmt));
|
||||
}
|
||||
forget_estree::BlockStatement {
|
||||
body,
|
||||
loc: None,
|
||||
range: convert_span(&stmt.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_function(cx: &Context, id: Option<&Ident>, fun: &Function) -> forget_estree::Function {
|
||||
forget_estree::Function {
|
||||
id: id.map(|id| forget_estree::Identifier {
|
||||
name: id.sym.to_string(),
|
||||
binding: convert_binding(cx, id.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&id.span),
|
||||
}),
|
||||
params: fun
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| convert_pattern(cx, ¶m.pat))
|
||||
.collect(),
|
||||
body: fun.body.as_ref().map(|body| {
|
||||
forget_estree::FunctionBody::BlockStatement(Box::new(convert_block_statement(cx, body)))
|
||||
}),
|
||||
is_async: fun.is_async,
|
||||
is_generator: fun.is_generator,
|
||||
loc: None,
|
||||
range: convert_span(&fun.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_statement(cx: &Context, stmt: &Stmt) -> forget_estree::Statement {
|
||||
match stmt {
|
||||
Stmt::Decl(Decl::Fn(item)) => forget_estree::Statement::FunctionDeclaration(Box::new(
|
||||
forget_estree::FunctionDeclaration {
|
||||
function: convert_function(cx, Some(&item.ident), &item.function),
|
||||
loc: None,
|
||||
range: convert_span(&item.function.span),
|
||||
},
|
||||
)),
|
||||
Stmt::Decl(Decl::Var(item)) => forget_estree::Statement::VariableDeclaration(Box::new(
|
||||
convert_variable_declaration(cx, item),
|
||||
)),
|
||||
Stmt::Block(item) => {
|
||||
forget_estree::Statement::BlockStatement(Box::new(convert_block_statement(cx, item)))
|
||||
}
|
||||
Stmt::Break(item) => {
|
||||
forget_estree::Statement::BreakStatement(Box::new(forget_estree::BreakStatement {
|
||||
label: item
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| convert_identifier(cx, label)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Continue(item) => forget_estree::Statement::ContinueStatement(Box::new(
|
||||
forget_estree::ContinueStatement {
|
||||
label: item
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| convert_identifier(cx, label)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
},
|
||||
)),
|
||||
Stmt::Debugger(item) => forget_estree::Statement::DebuggerStatement(Box::new(
|
||||
forget_estree::DebuggerStatement {
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
},
|
||||
)),
|
||||
Stmt::DoWhile(item) => {
|
||||
forget_estree::Statement::DoWhileStatement(Box::new(forget_estree::DoWhileStatement {
|
||||
body: convert_statement(cx, &item.body),
|
||||
test: convert_expression(cx, &item.test),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Empty(item) => {
|
||||
forget_estree::Statement::EmptyStatement(Box::new(forget_estree::EmptyStatement {
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Expr(item) => {
|
||||
let expression = convert_expression(cx, &item.expr);
|
||||
forget_estree::Statement::ExpressionStatement(Box::new(
|
||||
forget_estree::ExpressionStatement {
|
||||
expression,
|
||||
directive: None,
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
},
|
||||
))
|
||||
}
|
||||
Stmt::For(item) => {
|
||||
forget_estree::Statement::ForStatement(Box::new(forget_estree::ForStatement {
|
||||
init: item.init.as_ref().map(|init| match init {
|
||||
VarDeclOrExpr::Expr(init) => {
|
||||
forget_estree::ForInit::Expression(convert_expression(cx, init))
|
||||
}
|
||||
VarDeclOrExpr::VarDecl(init) => {
|
||||
assert_eq!(init.decls.len(), 1);
|
||||
forget_estree::ForInit::VariableDeclaration(Box::new(
|
||||
convert_variable_declaration(cx, init),
|
||||
))
|
||||
}
|
||||
}),
|
||||
test: item.test.as_ref().map(|test| convert_expression(cx, test)),
|
||||
update: item
|
||||
.update
|
||||
.as_ref()
|
||||
.map(|update| convert_expression(cx, update)),
|
||||
body: convert_statement(cx, &item.body),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Return(item) => {
|
||||
forget_estree::Statement::ReturnStatement(Box::new(forget_estree::ReturnStatement {
|
||||
argument: item.arg.as_ref().map(|arg| convert_expression(cx, arg)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::Throw(item) => {
|
||||
forget_estree::Statement::ThrowStatement(Box::new(forget_estree::ThrowStatement {
|
||||
argument: convert_expression(cx, &item.arg),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
Stmt::If(item) => {
|
||||
forget_estree::Statement::IfStatement(Box::new(forget_estree::IfStatement {
|
||||
test: convert_expression(cx, &item.test),
|
||||
consequent: convert_statement(cx, &item.cons),
|
||||
alternate: item.alt.as_ref().map(|alt| convert_statement(cx, alt)),
|
||||
loc: None,
|
||||
range: convert_span(&item.span),
|
||||
}))
|
||||
}
|
||||
_ => todo!("translate statement {:#?}", stmt),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_variable_declaration(
|
||||
cx: &Context,
|
||||
decl: &VarDecl,
|
||||
) -> forget_estree::VariableDeclaration {
|
||||
forget_estree::VariableDeclaration {
|
||||
kind: convert_decl_kind(&decl.kind),
|
||||
declarations: decl
|
||||
.decls
|
||||
.iter()
|
||||
.map(|declarator| forget_estree::VariableDeclarator {
|
||||
id: convert_pattern(cx, &declarator.name),
|
||||
init: declarator
|
||||
.init
|
||||
.as_ref()
|
||||
.map(|init| convert_expression(cx, init)),
|
||||
loc: None,
|
||||
range: convert_span(&decl.span),
|
||||
})
|
||||
.collect(),
|
||||
loc: None,
|
||||
range: convert_span(&decl.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_expression(cx: &Context, expr: &Expr) -> forget_estree::Expression {
|
||||
match expr {
|
||||
Expr::Ident(expr) => {
|
||||
forget_estree::Expression::Identifier(Box::new(convert_identifier(cx, expr)))
|
||||
}
|
||||
Expr::Array(expr) => {
|
||||
forget_estree::Expression::ArrayExpression(Box::new(forget_estree::ArrayExpression {
|
||||
elements: expr
|
||||
.elems
|
||||
.iter()
|
||||
.map(|item| {
|
||||
// TODO: represent holes in array expressions
|
||||
let value = item.as_ref()?;
|
||||
match value.spread {
|
||||
Some(spread) => Some(forget_estree::ExpressionOrSpread::SpreadElement(
|
||||
Box::new(forget_estree::SpreadElement {
|
||||
argument: convert_expression(cx, &value.expr),
|
||||
loc: None,
|
||||
range: convert_span(&spread),
|
||||
}),
|
||||
)),
|
||||
None => Some(forget_estree::ExpressionOrSpread::Expression(
|
||||
convert_expression(cx, &value.expr),
|
||||
)),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Expr::Await(_expr) => {
|
||||
// forget_estree::Expression::AwaitExpression(Box::new(forget_estree::AwaitExpression {
|
||||
// argument: convert_expression(cx, &expr.arg),
|
||||
// loc: None,
|
||||
// range: convert_span(&expr.span),
|
||||
// }))
|
||||
todo!("await expression")
|
||||
}
|
||||
Expr::Unary(expr) => {
|
||||
forget_estree::Expression::UnaryExpression(Box::new(forget_estree::UnaryExpression {
|
||||
operator: convert_unary_operator(expr.op),
|
||||
prefix: false,
|
||||
argument: convert_expression(cx, &expr.arg),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Expr::Bin(expr) => match convert_binary_operator(expr.op) {
|
||||
Operator::Binary(op) => forget_estree::Expression::BinaryExpression(Box::new(
|
||||
forget_estree::BinaryExpression {
|
||||
operator: op,
|
||||
left: convert_expression(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
},
|
||||
)),
|
||||
Operator::Logical(op) => forget_estree::Expression::LogicalExpression(Box::new(
|
||||
forget_estree::LogicalExpression {
|
||||
operator: op,
|
||||
left: convert_expression(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
},
|
||||
)),
|
||||
},
|
||||
Expr::Lit(expr) => {
|
||||
let (value, range) = match expr {
|
||||
Lit::Bool(expr) => (
|
||||
forget_estree::JsValue::Bool(expr.value),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Num(expr) => (
|
||||
forget_estree::JsValue::Number(expr.value.into()),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Str(expr) => (
|
||||
forget_estree::JsValue::String(expr.value.to_string()),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Null(expr) => (forget_estree::JsValue::Null, convert_span(&expr.span)),
|
||||
_ => todo!(),
|
||||
};
|
||||
forget_estree::Expression::Literal(Box::new(forget_estree::Literal {
|
||||
value,
|
||||
raw: None,
|
||||
loc: None,
|
||||
regex: None,
|
||||
range,
|
||||
}))
|
||||
}
|
||||
Expr::Assign(expr) => forget_estree::Expression::AssignmentExpression(Box::new(
|
||||
forget_estree::AssignmentExpression {
|
||||
operator: convert_assignment_operator(expr.op),
|
||||
left: convert_assignment_target(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
},
|
||||
)),
|
||||
Expr::Member(expr) => forget_estree::Expression::MemberExpression(Box::new(
|
||||
convert_member_expression(cx, expr),
|
||||
)),
|
||||
Expr::Fn(expr) => forget_estree::Expression::FunctionExpression(Box::new(
|
||||
forget_estree::FunctionExpression {
|
||||
function: convert_function(cx, expr.ident.as_ref(), &expr.function),
|
||||
loc: None,
|
||||
range: convert_span(&expr.function.span),
|
||||
},
|
||||
)),
|
||||
_ => todo!("translate expression {:#?}", expr),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_assignment_target(cx: &Context, target: &PatOrExpr) -> forget_estree::AssignmentTarget {
|
||||
match target {
|
||||
PatOrExpr::Pat(target) => {
|
||||
forget_estree::AssignmentTarget::Pattern(convert_pattern(cx, target))
|
||||
}
|
||||
PatOrExpr::Expr(target) => {
|
||||
match target.as_ref() {
|
||||
Expr::Member(target) => forget_estree::AssignmentTarget::Expression(
|
||||
forget_estree::Expression::MemberExpression(Box::new(
|
||||
convert_member_expression(cx, target),
|
||||
)),
|
||||
),
|
||||
Expr::Ident(target) => forget_estree::AssignmentTarget::Pattern(
|
||||
forget_estree::Pattern::Identifier(Box::new(convert_identifier(cx, target))),
|
||||
),
|
||||
_ => {
|
||||
panic!("Expected assignment target to be member expression or identifier, got {:#?}", target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> forget_estree::MemberExpression {
|
||||
let (is_computed, property) = match &expr.prop {
|
||||
MemberProp::Ident(prop) => (
|
||||
false,
|
||||
forget_estree::Expression::Identifier(Box::new(convert_identifier(cx, prop))),
|
||||
),
|
||||
MemberProp::Computed(prop) => (true, convert_expression(cx, &prop.expr)),
|
||||
_ => {
|
||||
panic!("PrivateName member expression properties are not supported")
|
||||
}
|
||||
};
|
||||
forget_estree::MemberExpression {
|
||||
object: forget_estree::ExpressionOrSuper::Expression(convert_expression(cx, &expr.obj)),
|
||||
property,
|
||||
computed: is_computed,
|
||||
// optional: false, // TODO
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_unary_operator(op: UnaryOp) -> forget_estree::UnaryOperator {
|
||||
match op {
|
||||
UnaryOp::Bang => forget_estree::UnaryOperator::Negation,
|
||||
UnaryOp::Delete => forget_estree::UnaryOperator::Delete,
|
||||
UnaryOp::Minus => forget_estree::UnaryOperator::Minus,
|
||||
UnaryOp::Plus => forget_estree::UnaryOperator::Plus,
|
||||
UnaryOp::Tilde => forget_estree::UnaryOperator::Tilde,
|
||||
UnaryOp::TypeOf => forget_estree::UnaryOperator::Typeof,
|
||||
UnaryOp::Void => forget_estree::UnaryOperator::Void,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_assignment_operator(op: AssignOp) -> forget_estree::AssignmentOperator {
|
||||
match op {
|
||||
AssignOp::Assign => forget_estree::AssignmentOperator::Equals,
|
||||
AssignOp::AddAssign => forget_estree::AssignmentOperator::PlusEquals,
|
||||
_ => todo!("translate assignment operator"),
|
||||
}
|
||||
}
|
||||
|
||||
enum Operator {
|
||||
Binary(forget_estree::BinaryOperator),
|
||||
Logical(forget_estree::LogicalOperator),
|
||||
}
|
||||
|
||||
fn convert_binary_operator(op: BinaryOp) -> Operator {
|
||||
match op {
|
||||
BinaryOp::Add => Operator::Binary(forget_estree::BinaryOperator::Add),
|
||||
BinaryOp::BitAnd => Operator::Binary(forget_estree::BinaryOperator::BinaryAnd),
|
||||
BinaryOp::BitOr => Operator::Binary(forget_estree::BinaryOperator::BinaryOr),
|
||||
BinaryOp::BitXor => Operator::Binary(forget_estree::BinaryOperator::BinaryXor),
|
||||
BinaryOp::Div => Operator::Binary(forget_estree::BinaryOperator::Divide),
|
||||
BinaryOp::EqEq => Operator::Binary(forget_estree::BinaryOperator::Equals),
|
||||
BinaryOp::EqEqEq => Operator::Binary(forget_estree::BinaryOperator::StrictEquals),
|
||||
// BinaryOp::Exp => Operator::Binary(forget_estree::BinaryOperator::AsteriskAsterisk),
|
||||
BinaryOp::Gt => Operator::Binary(forget_estree::BinaryOperator::GreaterThan),
|
||||
BinaryOp::GtEq => Operator::Binary(forget_estree::BinaryOperator::GreaterThanOrEqual),
|
||||
BinaryOp::In => Operator::Binary(forget_estree::BinaryOperator::In),
|
||||
BinaryOp::InstanceOf => Operator::Binary(forget_estree::BinaryOperator::Instanceof),
|
||||
BinaryOp::LShift => Operator::Binary(forget_estree::BinaryOperator::ShiftLeft),
|
||||
BinaryOp::Lt => Operator::Binary(forget_estree::BinaryOperator::LessThan),
|
||||
BinaryOp::LtEq => Operator::Binary(forget_estree::BinaryOperator::LessThanOrEqual),
|
||||
BinaryOp::Mod => Operator::Binary(forget_estree::BinaryOperator::Modulo),
|
||||
BinaryOp::Mul => Operator::Binary(forget_estree::BinaryOperator::Multiply),
|
||||
BinaryOp::NotEq => Operator::Binary(forget_estree::BinaryOperator::NotEquals),
|
||||
BinaryOp::NotEqEq => Operator::Binary(forget_estree::BinaryOperator::NotStrictEquals),
|
||||
BinaryOp::RShift => Operator::Binary(forget_estree::BinaryOperator::ShiftRight),
|
||||
BinaryOp::Sub => Operator::Binary(forget_estree::BinaryOperator::Subtract),
|
||||
BinaryOp::ZeroFillRShift => {
|
||||
Operator::Binary(forget_estree::BinaryOperator::UnsignedShiftRight)
|
||||
}
|
||||
|
||||
BinaryOp::LogicalAnd => Operator::Logical(forget_estree::LogicalOperator::And),
|
||||
BinaryOp::LogicalOr => Operator::Logical(forget_estree::LogicalOperator::Or),
|
||||
BinaryOp::NullishCoalescing => {
|
||||
Operator::Logical(forget_estree::LogicalOperator::NullCoalescing)
|
||||
}
|
||||
|
||||
_ => panic!("Unsupported binary operator `{}`", op),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_pattern(cx: &Context, pat: &Pat) -> forget_estree::Pattern {
|
||||
match pat {
|
||||
Pat::Ident(pat) => {
|
||||
forget_estree::Pattern::Identifier(Box::new(forget_estree::Identifier {
|
||||
name: pat.id.sym.to_string(),
|
||||
binding: convert_binding(cx, pat.id.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&pat.span),
|
||||
}))
|
||||
}
|
||||
_ => todo!("translate pattern {:#?}", pat),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_binding(context: &Context, binding_cx: SyntaxContext) -> Option<Binding> {
|
||||
let id = BindingId::new(binding_cx.as_u32());
|
||||
if binding_cx.as_u32() == context.top_level_mark.as_u32() {
|
||||
Some(Binding::Global)
|
||||
} else if binding_cx.as_u32() == context.unresolved_mark.as_u32() {
|
||||
Some(Binding::Module(id))
|
||||
} else {
|
||||
Some(Binding::Local(id))
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_identifier(cx: &Context, identifier: &Ident) -> forget_estree::Identifier {
|
||||
let name = identifier.sym.as_ref().to_string();
|
||||
forget_estree::Identifier {
|
||||
name,
|
||||
binding: convert_binding(cx, identifier.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&identifier.span),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "forget_fixtures"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
insta = { workspace = true }
|
||||
forget_estree = { workspace = true }
|
||||
forget_estree_swc = { workspace = true }
|
||||
forget_hir = { workspace = true }
|
||||
forget_optimization = { workspace = true }
|
||||
forget_ssa = { workspace = true }
|
||||
forget_build_hir = { workspace = true }
|
||||
bumpalo = { workspace = true }
|
||||
miette = { workspace = true, features = ["backtrace", "fancy"] }
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
use std::{env, fmt::Write};
|
||||
|
||||
use build_hir::build;
|
||||
use bumpalo::Bump;
|
||||
use estree::{ModuleItem, Statement};
|
||||
use estree_swc::parse;
|
||||
use hir::{Environment, Print, Registry};
|
||||
use hir_optimization::constant_propagation;
|
||||
use hir_ssa::{eliminate_redundant_phis, enter_ssa};
|
||||
use forget_build_hir::build;
|
||||
use forget_estree::{ModuleItem, Statement};
|
||||
use forget_estree_swc::parse;
|
||||
use forget_hir::{Environment, Features, Print, Registry};
|
||||
use forget_optimization::constant_propagation;
|
||||
use forget_ssa::{eliminate_redundant_phis, enter_ssa};
|
||||
use insta::{assert_snapshot, glob};
|
||||
use miette::{NamedSource, Report};
|
||||
|
||||
@@ -26,7 +26,7 @@ fn fixtures() {
|
||||
let allocator = Bump::new();
|
||||
let environment = allocator.alloc(Environment::new(
|
||||
&allocator,
|
||||
hir::Features {
|
||||
Features {
|
||||
validate_frozen_lambdas: true,
|
||||
},
|
||||
Registry,
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/constant-propagation-constant-if-condition.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/constant-propagation-constant-if-condition.js
|
||||
---
|
||||
Input:
|
||||
function Component() {
|
||||
@@ -95,4 +95,3 @@ bb10 (block)
|
||||
predecessors: bb11
|
||||
[32] #32 = "ok"
|
||||
[33] Return unknown #32
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/constant-propagation.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/constant-propagation.js
|
||||
---
|
||||
Input:
|
||||
function Component(props) {
|
||||
@@ -196,4 +196,3 @@ bb4 (block)
|
||||
[107] #101 = 18000000
|
||||
[108] #102 = <undefined>
|
||||
[109] Return unknown #102
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/error.assign-to-global.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/error.assign-to-global.js
|
||||
---
|
||||
Input:
|
||||
function foo() {
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/for-statement.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/for-statement.js
|
||||
---
|
||||
Input:
|
||||
function foo() {
|
||||
@@ -52,4 +52,3 @@ bb2 (block)
|
||||
predecessors: bb1
|
||||
[20] #15 = LoadLocal unknown x$5
|
||||
[21] Return unknown #15
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/function-expressions.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/function-expressions.js
|
||||
---
|
||||
Input:
|
||||
function Component(props) {
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/identifiers.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/identifiers.js
|
||||
---
|
||||
Input:
|
||||
// import React from "react";
|
||||
@@ -39,4 +39,3 @@ bb0 (block)
|
||||
[8] #8 = LoadLocal unknown z$7
|
||||
[9] #9 = LoadLocal unknown x$4
|
||||
[10] Return unknown #9
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/if-statement.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/if-statement.js
|
||||
---
|
||||
Input:
|
||||
function foo(a, b, c, d) {
|
||||
@@ -38,4 +38,3 @@ bb1 (block)
|
||||
[6] #3 = LoadLocal unknown d$7
|
||||
[7] #4 = <undefined>
|
||||
[8] Return unknown #4
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/simple.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/simple.js
|
||||
---
|
||||
Input:
|
||||
function test() {
|
||||
@@ -25,4 +25,3 @@ bb0 (block)
|
||||
[7] #7 = Array [unknown #0, unknown #1, unknown #2, unknown #3, unknown #4, ...unknown #6]
|
||||
[8] #8 = 2
|
||||
[9] Return unknown #8
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/fixtures/tests/fixtures_test.rs
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/fixtures/tests/fixtures/ssa-reassign-if.js
|
||||
input_file: crates/forget_fixtures/tests/fixtures/ssa-reassign-if.js
|
||||
---
|
||||
Input:
|
||||
function Component(a, b) {
|
||||
@@ -71,4 +71,3 @@ bb1 (block)
|
||||
[24] #18 = LoadLocal unknown z$18
|
||||
[25] #19 = Binary unknown #17 + unknown #18
|
||||
[26] Return unknown #19
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "forget_hir"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { workspace = true }
|
||||
forget_estree = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
forget_utils = { workspace = true }
|
||||
+1
-1
@@ -5,7 +5,7 @@ use std::{
|
||||
};
|
||||
|
||||
use bumpalo::{boxed::Box, collections::Vec, Bump};
|
||||
use estree::BindingId;
|
||||
use forget_estree::BindingId;
|
||||
|
||||
use crate::{
|
||||
BlockId, Features, Identifier, IdentifierData, IdentifierId, Registry, Type, TypeVarId,
|
||||
+1
-1
@@ -4,7 +4,7 @@ use bumpalo::{
|
||||
boxed::Box,
|
||||
collections::{String, Vec},
|
||||
};
|
||||
use estree::BinaryOperator;
|
||||
use forget_estree::BinaryOperator;
|
||||
|
||||
use crate::{Function, IdentifierId, InstrIx, InstructionId, ScopeId, Type};
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
use std::fmt::{Result, Write};
|
||||
|
||||
use utils::ensure_sufficient_stack;
|
||||
use forget_utils::ensure_sufficient_stack;
|
||||
|
||||
use crate::{
|
||||
ArrayElement, BasicBlock, Function, Identifier, IdentifierOperand, Instruction,
|
||||
@@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "forget_optimization"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
forget_estree = { workspace = true }
|
||||
forget_hir = { workspace = true }
|
||||
forget_ssa = { workspace = true }
|
||||
forget_build_hir = { workspace = true }
|
||||
forget_utils = { workspace = true }
|
||||
bumpalo = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
miette = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use build_hir::initialize_hir;
|
||||
use estree::BinaryOperator;
|
||||
use hir::{
|
||||
BlockKind, Environment, Function, GotoKind, IdentifierId, Instruction, InstructionValue,
|
||||
LoadGlobal, Operand, Primitive, PrimitiveValue, TerminalValue,
|
||||
use forget_build_hir::initialize_hir;
|
||||
use forget_estree::BinaryOperator;
|
||||
use forget_hir::{
|
||||
BlockKind, Environment, Function, GotoKind, GotoTerminal, IdentifierId, Instruction,
|
||||
InstructionValue, LoadGlobal, Operand, Primitive, PrimitiveValue, TerminalValue,
|
||||
};
|
||||
use hir_ssa::eliminate_redundant_phis;
|
||||
use forget_ssa::eliminate_redundant_phis;
|
||||
|
||||
pub fn constant_propagation<'a>(env: &Environment<'a>, fun: &mut Function<'a>) {
|
||||
let mut constants = Constants::new();
|
||||
@@ -107,7 +107,7 @@ fn apply_constant_propagation<'a>(
|
||||
} else {
|
||||
terminal.alternate
|
||||
};
|
||||
block.terminal.value = TerminalValue::Goto(hir::GotoTerminal {
|
||||
block.terminal.value = TerminalValue::Goto(GotoTerminal {
|
||||
block: target_block_id,
|
||||
kind: GotoKind::Break,
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "forget_ssa"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
forget_hir = { workspace = true }
|
||||
forget_utils = { workspace = true }
|
||||
bumpalo = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
miette = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
# hir-ssa
|
||||
# forget_ssa
|
||||
|
||||
This crate handles conversion to/from SSA and normal form. This includes a pass to eliminate redundant phi nodes in SSA form.
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use hir::{BlockId, Environment, Function, Identifier, IdentifierId, InstructionValue};
|
||||
use utils::RetainMut;
|
||||
use forget_hir::{BlockId, Environment, Function, Identifier, IdentifierId, InstructionValue};
|
||||
use forget_utils::RetainMut;
|
||||
|
||||
/// Pass to eliminate redundant phi nodes:
|
||||
/// all operands are the same identifier, ie `x2 = phi(x1, x1, x1)`.
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use bumpalo::collections::{CollectIn, Vec};
|
||||
use hir::{
|
||||
use forget_hir::{
|
||||
BasicBlock, BlockId, Blocks, Environment, Function, Identifier, IdentifierData, IdentifierId,
|
||||
IdentifierOperand, Instruction, InstructionValue, LValue, MutableRange, Phi,
|
||||
};
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
use hir::{Environment, HIR};
|
||||
use forget_hir::{Environment, HIR};
|
||||
|
||||
pub fn leave_ssa<'a>(_env: &'a Environment, _hir: &mut HIR<'a>) {
|
||||
todo!("leave_ssa()");
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "forget_utils"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { workspace = true }
|
||||
stacker = { workspace = true }
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "hir-optimization"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
estree = { path = "../estree" }
|
||||
hir = { path = "../hir" }
|
||||
hir-ssa = { path = "../hir-ssa" }
|
||||
build-hir = { path = "../build-hir" }
|
||||
utils = { path = "../utils" }
|
||||
bumpalo = "3.13.0"
|
||||
indexmap = "2.0.0"
|
||||
miette = { version = "5.9.0" }
|
||||
thiserror = "1.0.41"
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "hir-ssa"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
hir = { path = "../hir" }
|
||||
utils = { path = "../utils" }
|
||||
bumpalo = "3.13.0"
|
||||
indexmap = "2.0.0"
|
||||
miette = { version = "5.9.0" }
|
||||
thiserror = "1.0.41"
|
||||
@@ -1,13 +0,0 @@
|
||||
[package]
|
||||
name = "hir"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { version = "3.13.0", features = ["boxed", "collections"] }
|
||||
estree = { path = "../estree" }
|
||||
indexmap = "2.0.0"
|
||||
serde = "1.0.164"
|
||||
utils = { path = "../utils" }
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "swc-demo"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
swc_common = { version = "0.31.12", features = ["tty-emitter", "sourcemap", "anyhow"] }
|
||||
swc_core = "0.78.15"
|
||||
swc_ecma_parser = "0.136.2"
|
||||
swc_ecma_transforms_base = "0.129.8"
|
||||
swc_ecma_visit = "0.92.1"
|
||||
swc_visit = "0.5.6"
|
||||
@@ -1,59 +0,0 @@
|
||||
use swc_common::sync::Lrc;
|
||||
use swc_common::Mark;
|
||||
use swc_common::{
|
||||
errors::{ColorConfig, Handler},
|
||||
FileName, SourceMap,
|
||||
};
|
||||
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
|
||||
use swc_ecma_transforms_base::resolver;
|
||||
use swc_ecma_visit::swc_ecma_ast::Program;
|
||||
use swc_ecma_visit::VisitMutWith;
|
||||
|
||||
fn main() {
|
||||
let cm: Lrc<SourceMap> = Default::default();
|
||||
let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone()));
|
||||
|
||||
// Real usage
|
||||
// let fm = cm
|
||||
// .load_file(Path::new("test.js"))
|
||||
// .expect("failed to load test.js");
|
||||
let fm = cm.new_source_file(
|
||||
FileName::Custom("test.js".into()),
|
||||
"function foo(x: number, y: number): number { return x + y}".into(),
|
||||
);
|
||||
let lexer = Lexer::new(
|
||||
// We want to parse ecmascript
|
||||
Syntax::Typescript(swc_ecma_parser::TsConfig {
|
||||
tsx: true,
|
||||
decorators: true,
|
||||
..Default::default()
|
||||
}),
|
||||
// EsVersion defaults to es5
|
||||
Default::default(),
|
||||
StringInput::from(&*fm),
|
||||
None,
|
||||
);
|
||||
|
||||
let mut parser = Parser::new_from(lexer);
|
||||
|
||||
for e in parser.take_errors() {
|
||||
e.into_diagnostic(&handler).emit();
|
||||
}
|
||||
|
||||
let module = parser
|
||||
.parse_module()
|
||||
.map_err(|e| {
|
||||
// Unrecoverable fatal error occurred
|
||||
e.into_diagnostic(&handler).emit()
|
||||
})
|
||||
.expect("failed to parser module");
|
||||
|
||||
let mut module = Program::Module(module);
|
||||
|
||||
let _result = swc_common::GLOBALS.set(&swc_common::Globals::new(), || {
|
||||
let mut resolved = resolver(Mark::new(), Mark::new(), true);
|
||||
module.visit_mut_with(&mut resolved)
|
||||
});
|
||||
|
||||
println!("{:#?}", module);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
[package]
|
||||
name = "utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { version = "3.13.0", features = ["boxed", "collections"] }
|
||||
stacker = "0.1.15"
|
||||
Reference in New Issue
Block a user