diff --git a/README.md b/README.md
index 40bbb9bc..7ed93b2b 100644
--- a/README.md
+++ b/README.md
@@ -127,12 +127,12 @@ bazelisk test //maldoca/js/ir/conversion/...
### Run the `jsir_gen` tool
-Convert a JavaScript source file to JSHIR:
+Convert a JavaScript source file to JSIR:
```shell
bazelisk run //maldoca/js/ir:jsir_gen --\
--input_file=$(pwd)/maldoca/js/ir/conversion/tests/if_statement/input.js \
- --passes=source2ast,ast2hir
+ --passes=source2ast,ast2jsir
```
## Other links
diff --git a/docs/dataflow_analysis.md b/docs/dataflow_analysis.md
index bccd7c5e..983e491c 100644
--- a/docs/dataflow_analysis.md
+++ b/docs/dataflow_analysis.md
@@ -264,7 +264,7 @@ The JSIR for the code above is as follows:
```
...
%cond = jsir.identifier{"cond"}
-jshir.if_statement (%cond) ({
+jsir.if_statement (%cond) ({
%a_ref_true = jsir.identifier_ref{"a"}
%1 = jsir.numeric_literal{1}
%assign_true = jsir.assignment_expression (%a_ref_true, %1)
@@ -288,14 +288,14 @@ preserves the nested structures. We can see that the two branches of the
> more than 1 block in any region.
The JSIR dataflow analysis API understands the branching behaviors of
-`jshir.if_statement`, and builds **CFG (control flow graph) edges** to represent
+`jsir.if_statement`, and builds **CFG (control flow graph) edges** to represent
them internally:
```
...
%cond = jsir.identifier{"cond"}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ %a_ref_true = jsir.identifier_ref{"a"}
│ %1 = jsir.numeric_literal{1}
@@ -334,7 +334,7 @@ reaching `B1`, i.e. right **B**efore the `if`-statement.
// state[%cond] = Unknown
// state[B1] = {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ <IR for `a = 1;`>
│ ┌────◄
@@ -359,7 +359,7 @@ to two program points: `T0` and `F0`, which represent the entry points of the
// state[%cond] = Unknown
// state[B1] = {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ // state[T0] = {}
│ <IR for `a = 1;`>
@@ -412,7 +412,7 @@ propagation before, we will consequently visit all ops in the region.
// state[%cond] = Unknown
// state[B1] = {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ // state[T0] = {}
│ %a_ref_true = jsir.identifier_ref{"a"}
@@ -452,7 +452,7 @@ the CFG edge and propagate its state to `E0`, i.e. the end of the
// state[%cond] = Unknown
// state[B1] = {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ // state[T0] = {}
│ <IR for `a = 1;`>
@@ -485,7 +485,7 @@ compute states up to `state[F4]`:
// state[%cond] = Unknown
// state[B1] = {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ // state[T0] = {}
│ <IR for `a = 1;`>
@@ -526,7 +526,7 @@ propagate its state to `E0`.
// state[%cond] = Unknown
// state[B1] = {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ // state[T0] = {}
│ <IR for `a = 1;`>
@@ -604,7 +604,7 @@ The final result of the analysis, in full detail, is as follows:
// state[%cond] = Unknown
// state[B1] = [default = Unknown] {}
┌─────◄
-│ jshir.if_statement (%cond) ({
+│ jsir.if_statement (%cond) ({
├───────►
│ // state[T0] = [default = Unknown] {}
│ %a_ref_true = jsir.identifier_ref{"a"}
@@ -684,7 +684,7 @@ the combination of all iterations.
Now, similar to the previous examples, we convert the code into JSIR:
```
-jshir.while_statement ({
+jsir.while_statement ({
// The `test` region
// IR for `cond()`:
%cond_id = jsir.identifier {"cond"}
@@ -711,7 +711,7 @@ Then, we build CFG edges to represent control flow branches:
%assign_before = jsir.assignment_expression (%a_ref_before, %1)
jsir.expression_statement (%assign_before)
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // IR for `cond()`:
│ %cond = ...
@@ -739,7 +739,7 @@ Similar to the handling of the `if`-statement, we compute the states before the
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Const{1}}
│ // IR for `cond()`:
@@ -773,7 +773,7 @@ don't know the return value of `cond()`, so we can only assign `Unknown` to
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Const{1}}
│ // IR for `cond()`:
@@ -804,7 +804,7 @@ possible to enter the loop body and exit the loop. Therefore, we propagate
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Const{1}}
│ %cond = <IR for `cond()`>
@@ -840,7 +840,7 @@ first iteration of the loop body, which changes `a` from `1` to `3`.
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Const{1}}
│ %cond = <IR for `cond()`>
@@ -867,7 +867,7 @@ At the end of the loop body, we jump back to the `test` region, which `Join`s
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Const{1} Unknown}
│ %cond = <IR for `cond()`>
@@ -896,7 +896,7 @@ again with this new state, and propagate it to `I0` and `E0`.
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Unknown}
│ %cond = <IR for `cond()`>
@@ -929,7 +929,7 @@ end of the `body` region `I6` becomes `{a: Unknown}`.
<IR for `a = 1;`>
// state[B4] = {a: Const{1}}
┌─────◄
-│ jshir.while_statement ({
+│ jsir.while_statement ({
├───────►
│ // state[T0] = {a: Unknown}
│ // IR for `cond()`:
diff --git a/docs/intermediate_representation_design.md b/docs/intermediate_representation_design.md
index d207cd93..d853d2ea 100644
--- a/docs/intermediate_representation_design.md
+++ b/docs/intermediate_representation_design.md
@@ -211,10 +211,10 @@ semantic meanings:
## Representing control flows
-As mentioned above, JSIR seeks to have a nearly one-to-one mapping from the
-AST. Therefore, to preserve all information about the original control flow
+As mentioned above, JSIR seeks to have a nearly one-to-one mapping from the AST.
+Therefore, to preserve all information about the original control flow
structures, we define a separate op for each control flow structure (e.g.
-`jshir.if_statement`, `jshir.while_statement`, etc.). The nested code blocks are
+`jsir.if_statement`, `jsir.while_statement`, etc.). The nested code blocks are
represented as MLIR [regions](https://mlir.llvm.org/docs/LangRef/#regions).
### Example: `if`-statement
@@ -247,7 +247,7 @@ And, its corresponding JSIR is as follows:
```mlir
%cond = jsir.identifier {"cond"}
-jshir.if_statement (%cond) ({
+jsir.if_statement (%cond) ({
%a = jsir.identifier {"a"}
jsir.expression_statement (%a)
}, {
@@ -289,7 +289,7 @@ WhileStatement {
Its corresponding JSIR is as follows:
```mlir
-jshir.while_statement ({
+jsir.while_statement ({
%cond_id = jsir.identifier {"cond"}
%cond_call = jsir.call_expression (%cond_id)
jsir.expr_region_end (%cond_call)
@@ -300,11 +300,11 @@ jshir.while_statement ({
})
```
-Note that unlike `jshir.if_statement`, the condition in a
-`jshir.while_statement` is represented as a region rather than a normal SSA
-value (`%cond`). This is because the condition is evaluated in each iteration
-**within** the `while`-statement, whereas the condition is evaluated only once
-**before** the `if`-statement.
+Note that unlike `jsir.if_statement`, the condition in a `jsir.while_statement`
+is represented as a region rather than a normal SSA value (`%cond`). This is
+because the condition is evaluated in each iteration **within** the
+`while`-statement, whereas the condition is evaluated only once **before** the
+`if`-statement.
### Example: logical expression
@@ -333,7 +333,7 @@ Its corresponding JSIR is as follows:
```mlir
%x_ref = jsir.identifier_ref {"x"}
%a = jsir.identifier {"a"}
-%and = jshir.logical_expression (%a) ({
+%and = jsir.logical_expression (%a) ({
%b = jsir.identifier {"b"}
jsir.expr_region_end (%b)
})
@@ -341,7 +341,7 @@ Its corresponding JSIR is as follows:
jsir.expression_statement (%assign)
```
-Note that in `jshir.logical_expression`, `left` is an SSA value, and `right` is
-a region. This is because `left` is always evaluated first, whereas `right` is
+Note that in `jsir.logical_expression`, `left` is an SSA value, and `right` is a
+region. This is because `left` is always evaluated first, whereas `right` is
only evaluated if the result of `left` is truthy, and omitted if `left` is falsy
due to the short-circuit behavior.
diff --git a/maldoca/astgen/ast_def.cc b/maldoca/astgen/ast_def.cc
index 6debce86..0e253c1f 100644
--- a/maldoca/astgen/ast_def.cc
+++ b/maldoca/astgen/ast_def.cc
@@ -225,7 +225,7 @@ std::optional NodeDef::ir_op_name(absl::string_view lang_name,
return std::nullopt;
}
- auto ir_name = absl::StrCat(lang_name, has_control_flow() ? "hir" : "ir");
+ auto ir_name = absl::StrCat(lang_name, "ir");
Symbol result{ir_name};
diff --git a/maldoca/astgen/ast_def.h b/maldoca/astgen/ast_def.h
index c8be0376..c5d02ca0 100644
--- a/maldoca/astgen/ast_def.h
+++ b/maldoca/astgen/ast_def.h
@@ -218,22 +218,15 @@ class NodeDef {
return aggregated_kinds_;
}
- // Whether this node has control-flow-related information.
- //
- // A node is considered to have control-flow-related information if it
- // contains some branch semantics.
- //
- // Example: IfStatement, BreakStatement.
- //
- // When this is true, we define two ops, one in HIR (high-level IR), one in
- // LIR (low-level IR).
- bool has_control_flow() const { return has_control_flow_; }
+ // Deprecated: No longer used for dialect splitting. Merged HIR into IR.
+ [[deprecated("Merged HIR into IR")]]
+ bool has_control_flow() const {
+ return has_control_flow_;
+ }
// The MLIR op name (C++ class name).
//
- // :
- // has_control_flow: hir
- // !has_control_flow: ir
+ // : ir
//
// - Non-leaf type: "OpInterface"
// - Leaf type:
diff --git a/maldoca/astgen/ast_def.proto b/maldoca/astgen/ast_def.proto
index c6071136..5c42041d 100644
--- a/maldoca/astgen/ast_def.proto
+++ b/maldoca/astgen/ast_def.proto
@@ -295,9 +295,8 @@ message NodeDefPb {
// Supported kinds. Each kind leads to a different IR op.
repeated FieldKind kinds = 6;
- // Whether this op has control flow. If so, we will define a high-level IR op,
- // and a low-level IR op.
- optional bool has_control_flow = 7;
+ // Deprecated: No longer used for dialect splitting. Merged HIR into IR.
+ optional bool has_control_flow = 7 [deprecated = true];
// [Optional] Custom MLIR op name.
//
diff --git a/maldoca/astgen/ir_table_gen_printer.cc b/maldoca/astgen/ir_table_gen_printer.cc
index 031ecddf..2244ea1e 100644
--- a/maldoca/astgen/ir_table_gen_printer.cc
+++ b/maldoca/astgen/ir_table_gen_printer.cc
@@ -204,8 +204,6 @@ void IrTableGenPrinter::PrintAst(const AstDef& ast, absl::string_view ir_path) {
void IrTableGenPrinter::PrintNode(const AstDef& ast, const NodeDef& node,
FieldKind kind) {
auto ir_name = absl::StrCat(ast.lang_name(), "ir");
- auto hir_name =
- absl::StrCat(ast.lang_name(), node.has_control_flow() ? "hir" : "ir");
auto vars = WithVars({
{"OpName", node.ir_op_name(ast.lang_name(), kind).value().ToPascalCase()},
@@ -213,7 +211,6 @@ void IrTableGenPrinter::PrintNode(const AstDef& ast, const NodeDef& node,
{"Name", node.name()},
{"name", Symbol(node.name()).ToCcVarName()},
{"IrName", Symbol(ir_name).ToPascalCase()},
- {"HirName", Symbol(hir_name).ToPascalCase()},
});
std::vector traits;
@@ -295,7 +292,7 @@ void IrTableGenPrinter::PrintNode(const AstDef& ast, const NodeDef& node,
// ]> {
// ```
Print(
- "def $OpName$ : $HirName$_Op<\n"
+ "def $OpName$ : $IrName$_Op<\n"
" \"$op_mnemonic$\", [\n");
{
diff --git a/maldoca/js/ast/BUILD b/maldoca/js/ast/BUILD
index 5863f5e2..844ac91c 100644
--- a/maldoca/js/ast/BUILD
+++ b/maldoca/js/ast/BUILD
@@ -24,6 +24,25 @@ package(
default_visibility = JSIR_ALLOWED_USERS,
)
+cc_test(
+ name = "ast_gen_test",
+ srcs = ["ast_gen_test.cc"],
+ data = [
+ "ast.generated.cc",
+ "ast.generated.h",
+ "ast_def.textproto",
+ "ast_from_json.generated.cc",
+ "ast_to_json.generated.cc",
+ "//maldoca/js/ir:jsir_ops.generated.td",
+ "//maldoca/js/ir/conversion:ast_to_jsir.generated.cc",
+ "//maldoca/js/ir/conversion:jsir_to_ast.generated.cc",
+ ],
+ deps = [
+ "//maldoca/astgen/test:ast_gen_test_util",
+ "@googletest//:gtest_main",
+ ],
+)
+
cc_library(
name = "ast",
srcs = [
diff --git a/maldoca/js/ast/ast_def.textproto b/maldoca/js/ast/ast_def.textproto
new file mode 100644
index 00000000..a01deb6a
--- /dev/null
+++ b/maldoca/js/ast/ast_def.textproto
@@ -0,0 +1,3408 @@
+# proto-file: third_party/maldoca/astgen/ast_def.proto
+# proto-message: AstDefPb
+
+# To update the generated code:
+#
+# blaze build //third_party/maldoca/astgen:ast_gen_main
+#
+# ./blaze-bin/third_party/maldoca/astgen/ast_gen_main \
+# --ast_def_path="third_party/maldoca/js/ast/ast_def.textproto" \
+# --cc_namespace="maldoca" \
+# --ast_path="third_party/maldoca/js/ast" \
+# --ir_path="third_party/maldoca/js/ir"
+
+lang_name: "js"
+
+# enum UnaryOperator {
+# "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" | "throw"
+# }
+enums {
+ name: "UnaryOperator"
+ members {
+ name: "Minus"
+ string_value: "-"
+ }
+ members {
+ name: "Plus"
+ string_value: "+"
+ }
+ members {
+ name: "Not"
+ string_value: "!"
+ }
+ members {
+ name: "BitwiseNot"
+ string_value: "~"
+ }
+ members {
+ name: "TypeOf"
+ string_value: "typeof"
+ }
+ members {
+ name: "Void"
+ string_value: "void"
+ }
+ members {
+ name: "Delete"
+ string_value: "delete"
+ }
+ members {
+ name: "Throw"
+ string_value: "throw"
+ }
+}
+
+# enum UpdateOperator {
+# "++" | "--"
+# }
+enums {
+ name: "UpdateOperator"
+ members {
+ name: "Increment"
+ string_value: "++"
+ }
+ members {
+ name: "Decrement"
+ string_value: "--"
+ }
+}
+
+# enum BinaryOperator {
+# "==" | "!=" | "===" | "!=="
+# | "<" | "<=" | ">" | ">="
+# | "<<" | ">>" | ">>>"
+# | "+" | "-" | "*" | "/" | "%"
+# | "**" | "|" | "^" | "&" | "in"
+# | "instanceof"
+# | "|>"
+# }
+enums {
+ name: "BinaryOperator"
+ members {
+ name: "Equal"
+ string_value: "=="
+ }
+ members {
+ name: "NotEqual"
+ string_value: "!="
+ }
+ members {
+ name: "StrictEqual"
+ string_value: "==="
+ }
+ members {
+ name: "StrictNotEqual"
+ string_value: "!=="
+ }
+ members {
+ name: "LessThan"
+ string_value: "<"
+ }
+ members {
+ name: "LessEqual"
+ string_value: "<="
+ }
+ members {
+ name: "GreaterThan"
+ string_value: ">"
+ }
+ members {
+ name: "GreaterEqual"
+ string_value: ">="
+ }
+ members {
+ name: "LeftShift"
+ string_value: "<<"
+ }
+ members {
+ name: "RightShift"
+ string_value: ">>"
+ }
+ members {
+ name: "UnsignedRightShift"
+ string_value: ">>>"
+ }
+ members {
+ name: "Add"
+ string_value: "+"
+ }
+ members {
+ name: "Subtract"
+ string_value: "-"
+ }
+ members {
+ name: "Multiply"
+ string_value: "*"
+ }
+ members {
+ name: "Divide"
+ string_value: "/"
+ }
+ members {
+ name: "Mod"
+ string_value: "%"
+ }
+ members {
+ name: "Exp"
+ string_value: "**"
+ }
+ members {
+ name: "BitwiseOr"
+ string_value: "|"
+ }
+ members {
+ name: "BitwiseXor"
+ string_value: "^"
+ }
+ members {
+ name: "BitwiseAnd"
+ string_value: "&"
+ }
+ members {
+ name: "In"
+ string_value: "in"
+ }
+ members {
+ name: "InstanceOf"
+ string_value: "instanceof"
+ }
+ members {
+ name: "Pipeline"
+ string_value: "|>"
+ }
+}
+
+# enum AssignmentOperator {
+# "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**="
+# | "<<=" | ">>=" | ">>>="
+# | "|=" | "^=" | "&="
+# | "||=" | "&&=" | "??="
+# }
+enums {
+ name: "AssignmentOperator"
+ members {
+ name: "Assign"
+ string_value: "="
+ }
+ members {
+ name: "AddAssign"
+ string_value: "+="
+ }
+ members {
+ name: "SubtractAssign"
+ string_value: "-="
+ }
+ members {
+ name: "MultiplyAssign"
+ string_value: "*="
+ }
+ members {
+ name: "DivideAssign"
+ string_value: "/="
+ }
+ members {
+ name: "ModAssign"
+ string_value: "%="
+ }
+ members {
+ name: "ExpAssign"
+ string_value: "**="
+ }
+ members {
+ name: "LeftShiftAssign"
+ string_value: "<<="
+ }
+ members {
+ name: "RightShiftAssign"
+ string_value: ">>="
+ }
+ members {
+ name: "UnsignedRightShiftAssign"
+ string_value: ">>>="
+ }
+ members {
+ name: "BitwiseOrAssign"
+ string_value: "|="
+ }
+ members {
+ name: "BitwiseXorAssign"
+ string_value: "^="
+ }
+ members {
+ name: "BitwiseAndAssign"
+ string_value: "&="
+ }
+ members {
+ name: "OrAssign"
+ string_value: "||="
+ }
+ members {
+ name: "AndAssign"
+ string_value: "&&="
+ }
+ members {
+ name: "NullishCoalesceAssign"
+ string_value: "??="
+ }
+}
+
+# enum LogicalOperator {
+# "||" | "&&" | "??"
+# }
+enums {
+ name: "LogicalOperator"
+ members {
+ name: "Or"
+ string_value: "||"
+ }
+ members {
+ name: "And"
+ string_value: "&&"
+ }
+ members {
+ name: "NullishCoalesce"
+ string_value: "??"
+ }
+}
+
+# interface Comment {
+# type: string;
+# loc: SourceLocation;
+# value: string;
+# start: number;
+# end: number;
+# }
+nodes {
+ name: "Comment"
+ fields {
+ name: "loc"
+ type { class: "SourceLocation" }
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ }
+ fields {
+ name: "value"
+ type { string {} }
+ }
+ fields {
+ name: "start"
+ type { int64 {} }
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ }
+ fields {
+ name: "end"
+ type { int64 {} }
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ }
+}
+
+# interface CommentBlock <: Comment {
+# type: "CommentBlock";
+# }
+nodes {
+ name: "CommentBlock"
+ type: "CommentBlock"
+ parents: "Comment"
+}
+
+# interface CommentLine <: Comment {
+# type: "CommentLine";
+# }
+nodes {
+ name: "CommentLine"
+ type: "CommentLine"
+ parents: "Comment"
+}
+
+# interface SymbolId {
+# name: string;
+# defScopeUid?: number;
+# }
+nodes {
+ name: "SymbolId"
+ fields {
+ name: "name"
+ type { string {} }
+ }
+ fields {
+ name: "defScopeUid"
+ type { int64 {} }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ }
+ should_generate_ir_op: false
+}
+
+# interface Node {
+# type: string;
+# loc: SourceLocation | null;
+# start: number | null;
+# end: number | null;
+# leadingCommentUids?: [Comment];
+# trailingCommentUids?: [Comment];
+# innerCommentUids?: [Comment];
+# scopeUid?: number;
+# referencedSymbol?: SymbolId;
+# definedSymbol?: SymbolId;
+# }
+nodes {
+ name: "Node"
+ fields {
+ name: "loc"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "SourceLocation" }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "start"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { int64 {} }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "end"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { int64 {} }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "leadingCommentUids"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type { int64 {} }
+ }
+ }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "trailingCommentUids"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type { int64 {} }
+ }
+ }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "innerCommentUids"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type { int64 {} }
+ }
+ }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "scopeUid"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type { int64 {} }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "referencedSymbol"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type { class: "SymbolId" }
+ ignore_in_ir: true
+ }
+ fields {
+ name: "definedSymbols"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type { class: "SymbolId" }
+ }
+ }
+ ignore_in_ir: true
+ }
+}
+
+# interface File <: Node {
+# type: "File";
+# program: Program;
+# comments?: Array | null;
+# tokens?: Array | null;
+# }
+# TODO(tzx)
+nodes {
+ name: "File"
+ parents: "Node"
+ type: "File"
+ fields {
+ name: "program"
+ type { class: "Program" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "comments"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type {
+ class: "Comment"
+ }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_ISOLATED_FROM_ABOVE
+}
+
+# interface SourceLocation {
+# // source: string | null;
+# start: Position;
+# end: Position;
+# identifierName?: string;
+# }
+nodes {
+ name: "SourceLocation"
+ fields {
+ name: "start"
+ type { class: "Position" }
+ }
+ fields {
+ name: "end"
+ type { class: "Position" }
+ }
+ fields {
+ name: "identifierName"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type { string {} }
+ }
+}
+
+# interface Position {
+# line: number; // >= 1
+# column: number; // >= 0
+# }
+nodes {
+ name: "Position"
+ fields: {
+ name: "line"
+ type { int64 {} }
+ }
+ fields: {
+ name: "column"
+ type { int64 {} }
+ }
+}
+
+# // interface Identifier <: Expression, Pattern {
+# // type: "Identifier";
+# // name: string;
+# // }
+# interface Identifier <: Expression, Pattern, LVal {
+# type: "Identifier";
+# name: string;
+# }
+nodes {
+ name: "Identifier"
+ type: "Identifier"
+ parents: "Expression"
+ parents: "Pattern"
+ parents: "LVal"
+ fields {
+ name: "name"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface PrivateName <: Node {
+# type: "PrivateName";
+# id: Identifier;
+# }
+nodes {
+ name: "PrivateName"
+ type: "PrivateName"
+ parents: "Node"
+ fields {
+ name: "id"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+}
+
+# interface Literal <: Expression { }
+nodes {
+ name: "Literal"
+ parents: "Expression"
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface RegExpLiteral <: Literal {
+# type: "RegExpLiteral";
+# pattern: string;
+# flags: string;
+# extra?: {
+# raw: string;
+# }
+# }
+nodes {
+ name: "RegExpLiteralExtra"
+ type: "RegExpLiteralExtra"
+ fields {
+ name: "raw"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+}
+nodes {
+ name: "RegExpLiteral"
+ type: "RegExpLiteral"
+ parents: "Literal"
+ fields {
+ name: "pattern"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "flags"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "extra"
+ type { class: "RegExpLiteralExtra" }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# interface NullLiteral <: Literal {
+# type: "NullLiteral";
+# }
+nodes {
+ name: "NullLiteral"
+ type: "NullLiteral"
+ parents: "Literal"
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# interface StringLiteral <: Literal {
+# type: "StringLiteral";
+# value: string; // does not include quotes
+# extra?: {
+# raw: string; // includes quotes
+# rawValue: string; // does not include quotes
+# }
+# }
+nodes {
+ name: "StringLiteralExtra"
+ type: "StringLiteralExtra"
+ fields {
+ name: "raw"
+ type: { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "rawValue"
+ type: { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+}
+
+nodes {
+ name: "StringLiteral"
+ type: "StringLiteral"
+ parents: "Literal"
+ fields {
+ name: "value"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "extra"
+ type { class: "StringLiteralExtra" }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# interface BooleanLiteral <: Literal {
+# type: "BooleanLiteral";
+# value: boolean;
+# }
+nodes {
+ name: "BooleanLiteral"
+ type: "BooleanLiteral"
+ parents: "Literal"
+ fields {
+ name: "value"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# interface NumericLiteral <: Literal {
+# type: "NumericLiteral";
+# value: number;
+# extra?: {
+# raw: string;
+# rawValue: number;
+# }
+# }
+nodes {
+ name: "NumericLiteralExtra"
+ type: "NumericLiteralExtra"
+ fields {
+ name: "raw"
+ type: { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "rawValue"
+ type: { double {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+}
+
+nodes {
+ name: "NumericLiteral"
+ type: "NumericLiteral"
+ parents: "Literal"
+ fields {
+ name: "value"
+ type { double {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "extra"
+ type { class: "NumericLiteralExtra" }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# interface BigIntLiteral <: Literal {
+# type: "BigIntLiteral";
+# value: string;
+# extra?: {
+# raw: string; // includes the suffix "n"
+# rawValue: string; // does not include the suffix "n"
+# }
+# }
+nodes {
+ name: "BigIntLiteralExtra"
+ type: "BigIntLiteralExtra"
+ fields {
+ name: "raw"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "rawValue"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+}
+nodes {
+ name: "BigIntLiteral"
+ type: "BigIntLiteral"
+ parents: "Literal"
+ fields {
+ name: "value"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "extra"
+ type { class: "BigIntLiteralExtra" }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# // interface DecimalLiteral <: Literal {
+# // type: "DecimalLiteral";
+# // value: string;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "decimal" plugin.
+# ------------------------------------------------------------------------------
+
+# interface Program <: Node {
+# type: "Program";
+# interpreter: InterpreterDirective | null;
+# sourceType: "script" | "module";
+# body: [ Statement | ModuleDeclaration ];
+# directives: [ Directive ];
+# }
+# TODO(tzx)
+
+union_types {
+ name: "ProgramBodyElement"
+ parents: "Node"
+ types: "Statement"
+ types: "ModuleDeclaration"
+ kinds: FIELD_KIND_STMT
+ # should_generate_ir_op: true
+}
+
+nodes {
+ name: "Program"
+ parents: "Node"
+ type: "Program"
+ fields {
+ name: "interpreter"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "InterpreterDirective" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "sourceType"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "body"
+ type {
+ list {
+ element_type {
+ class: "ProgramBodyElement"
+ }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "directives"
+ type {
+ list {
+ element_type { class: "Directive" }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
+
+# // interface Function <: Node {
+# // id: Identifier | null;
+# // params: [ Pattern ];
+# // body: BlockStatement;
+# // generator: boolean;
+# // async: boolean;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: In ArrowFunctionExpression, the type of "body" is overrideen to
+# "BlockStatement | Expression".
+#
+# interface Function <: Node {
+# id: Identifier | null;
+# params: [ Pattern ];
+# generator: boolean;
+# async: boolean;
+# }
+# interface BlockStatementFunction <: Function {
+# body: BlockStatement;
+# }
+nodes {
+ name: "Function"
+ parents: "Node"
+ fields {
+ name: "id"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "params"
+ type {
+ list {
+ element_type { class: "Pattern" }
+ }
+ }
+ kind: FIELD_KIND_LVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "generator"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "async"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ # Note: We cannot specify FIELD_KIND_STMT here because FunctionExpression is
+ # a FIELD_KIND_EXPR
+}
+nodes {
+ name: "BlockStatementFunction"
+ parents: "Function"
+ fields {
+ name: "body"
+ type { class: "BlockStatement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+}
+
+# interface Statement <: Node { }
+nodes {
+ name: "Statement"
+ parents: "Node"
+ kinds: FIELD_KIND_STMT
+}
+
+# interface ExpressionStatement <: Statement {
+# type: "ExpressionStatement";
+# expression: Expression;
+# }
+nodes {
+ name: "ExpressionStatement"
+ type: "ExpressionStatement"
+ parents: "Statement"
+ fields {
+ name: "expression"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface BlockStatement <: Statement {
+# type: "BlockStatement";
+# body: [ Statement ];
+# directives: [ Directive ];
+# }
+nodes {
+ name: "BlockStatement"
+ parents: "Statement"
+ type: "BlockStatement"
+ fields {
+ name: "body"
+ type {
+ list {
+ element_type { class: "Statement" }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "directives"
+ type {
+ list {
+ element_type { class: "Directive" }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface EmptyStatement <: Statement {
+# type: "EmptyStatement";
+# }
+nodes {
+ name: "EmptyStatement"
+ parents: "Statement"
+ type: "EmptyStatement"
+ should_generate_ir_op: true
+}
+
+# interface DebuggerStatement <: Statement {
+# type: "DebuggerStatement";
+# }
+nodes {
+ name: "DebuggerStatement"
+ parents: "Statement"
+ type: "DebuggerStatement"
+ should_generate_ir_op: true
+}
+
+# interface WithStatement <: Statement {
+# type: "WithStatement";
+# object: Expression;
+# body: Statement;
+# }
+nodes {
+ name: "WithStatement"
+ parents: "Statement"
+ type: "WithStatement"
+ fields {
+ name: "object"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface ReturnStatement <: Statement {
+# type: "ReturnStatement";
+# argument: Expression | null;
+# }
+nodes {
+ name: "ReturnStatement"
+ parents: "Statement"
+ type: "ReturnStatement"
+ fields {
+ name: "argument"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface LabeledStatement <: Statement {
+# type: "LabeledStatement";
+# label: Identifier;
+# body: Statement;
+# }
+nodes {
+ name: "LabeledStatement"
+ parents: "Statement"
+ type: "LabeledStatement"
+ fields {
+ name: "label"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface BreakStatement <: Statement {
+# type: "BreakStatement";
+# label: Identifier | null;
+# }
+nodes {
+ name: "BreakStatement"
+ parents: "Statement"
+ type: "BreakStatement"
+ fields {
+ name: "label"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ has_control_flow: true
+}
+
+# interface ContinueStatement <: Statement {
+# type: "ContinueStatement";
+# label: Identifier | null;
+# }
+nodes {
+ name: "ContinueStatement"
+ parents: "Statement"
+ type: "ContinueStatement"
+ fields {
+ name: "label"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ has_control_flow: true
+}
+
+# interface IfStatement <: Statement {
+# type: "IfStatement";
+# test: Expression;
+# consequent: Statement;
+# alternate: Statement | null;
+# }
+nodes {
+ name: "IfStatement"
+ parents: "Statement"
+ type: "IfStatement"
+ fields {
+ name: "test"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "consequent"
+ type { class: "Statement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "alternate"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Statement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface SwitchStatement <: Statement {
+# type: "SwitchStatement";
+# discriminant: Expression;
+# cases: [ SwitchCase ];
+# }
+nodes {
+ name: "SwitchStatement"
+ parents: "Statement"
+ type: "SwitchStatement"
+ fields {
+ name: "discriminant"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "cases"
+ type {
+ list {
+ element_type { class: "SwitchCase" }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface SwitchCase <: Node {
+# type: "SwitchCase";
+# test: Expression | null;
+# consequent: [ Statement ];
+# }
+nodes {
+ name: "SwitchCase"
+ parents: "Node"
+ type: "SwitchCase"
+ fields {
+ name: "test"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "consequent"
+ type {
+ list {
+ element_type { class: "Statement" }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface ThrowStatement <: Statement {
+# type: "ThrowStatement";
+# argument: Expression;
+# }
+nodes {
+ name: "ThrowStatement"
+ parents: "Statement"
+ type: "ThrowStatement"
+ fields {
+ name: "argument"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface TryStatement <: Statement {
+# type: "TryStatement";
+# block: BlockStatement;
+# handler: CatchClause | null;
+# finalizer: BlockStatement | null;
+# }
+nodes {
+ name: "TryStatement"
+ parents: "Statement"
+ type: "TryStatement"
+ fields {
+ name: "block"
+ type { class: "BlockStatement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "handler"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "CatchClause" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "finalizer"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "BlockStatement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# // interface CatchClause <: Node {
+# // type: "CatchClause";
+# // param?: Pattern;
+# // body: BlockStatement;
+# // }
+# interface CatchClause <: Node {
+# type: "CatchClause";
+# param: Pattern | null;
+# body: BlockStatement;
+# }
+nodes {
+ name: "CatchClause"
+ type: "CatchClause"
+ parents: "Node"
+ fields {
+ name: "param"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Pattern" }
+ kind: FIELD_KIND_LVAL
+ }
+ fields {
+ name: "body"
+ type { class: "BlockStatement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface WhileStatement <: Statement {
+# type: "WhileStatement";
+# test: Expression;
+# body: Statement;
+# }
+nodes {
+ name: "WhileStatement"
+ parents: "Statement"
+ type: "WhileStatement"
+ fields {
+ name: "test"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface DoWhileStatement <: Statement {
+# type: "DoWhileStatement";
+# body: Statement;
+# test: Expression;
+# }
+nodes {
+ name: "DoWhileStatement"
+ parents: "Statement"
+ type: "DoWhileStatement"
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "test"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface ForStatement <: Statement {
+# type: "ForStatement";
+# init: VariableDeclaration | Expression | null;
+# test: Expression | null;
+# update: Expression | null;
+# body: Statement;
+# }
+nodes {
+ name: "ForStatement"
+ parents: "Statement"
+ type: "ForStatement"
+ fields {
+ name: "init"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type {
+ variant {
+ types { class: "VariableDeclaration" }
+ types { class: "Expression" }
+ }
+ }
+ }
+ fields {
+ name: "test"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ }
+ fields {
+ name: "update"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ }
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ }
+ has_control_flow: true
+ should_generate_ir_op: false
+}
+
+# // interface ForInStatement <: Statement {
+# // type: "ForInStatement";
+# // left: VariableDeclaration | Expression;
+# // right: Expression;
+# // body: Statement;
+# // }
+# interface ForInStatement <: Statement {
+# type: "ForInStatement";
+# left: VariableDeclaration | LVal;
+# right: Expression;
+# body: Statement;
+# }
+nodes {
+ name: "ForInStatement"
+ parents: "Statement"
+ type: "ForInStatement"
+ fields {
+ name: "left"
+ type {
+ variant {
+ types { class: "VariableDeclaration" }
+ types { class: "LVal" }
+ }
+ }
+ }
+ fields {
+ name: "right"
+ type { class: "Expression" }
+ }
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ }
+ has_control_flow: true
+ should_generate_ir_op: false
+}
+
+# // interface ForOfStatement <: ForInStatement {
+# // type: "ForOfStatement";
+# // await: boolean;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We shouldn't override a leaf type.
+# ------------------------------------------------------------------------------
+# interface ForOfStatement <: Statement {
+# type: "ForOfStatement";
+# left: VariableDeclaration | LVal;
+# right: Expression;
+# body: Statement;
+# await: boolean;
+# }
+nodes {
+ name: "ForOfStatement"
+ parents: "Statement"
+ type: "ForOfStatement"
+ fields {
+ name: "left"
+ type {
+ variant {
+ types { class: "VariableDeclaration" }
+ types { class: "LVal" }
+ }
+ }
+ }
+ fields {
+ name: "right"
+ type { class: "Expression" }
+ }
+ fields {
+ name: "body"
+ type { class: "Statement" }
+ }
+ fields {
+ name: "await"
+ type { bool {} }
+ }
+ has_control_flow: true
+ should_generate_ir_op: false
+}
+
+# interface Declaration <: Statement { }
+nodes {
+ name: "Declaration"
+ parents: "Statement"
+}
+
+# // interface FunctionDeclaration <: Function, Declaration {
+# // type: "FunctionDeclaration";
+# // id: Identifier;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: Sometimes id is optional.
+# interface FunctionDeclaration <: BlockStatementFunction, Declaration {
+# type: "FunctionDeclaration";
+# }
+nodes {
+ name: "FunctionDeclaration"
+ parents: "BlockStatementFunction"
+ parents: "Declaration"
+ type: "FunctionDeclaration"
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
+
+# interface VariableDeclaration <: Declaration {
+# type: "VariableDeclaration";
+# declarations: [ VariableDeclarator ];
+# kind: "var" | "let" | "const";
+# }
+nodes {
+ name: "VariableDeclaration"
+ parents: "Declaration"
+ type: "VariableDeclaration"
+ fields {
+ name: "declarations"
+ type {
+ list {
+ element_type { class: "VariableDeclarator" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "kind"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
+
+# // interface VariableDeclarator <: Node {
+# // type: "VariableDeclarator";
+# // id: Pattern;
+# // init: Expression | null;
+# // }
+# interface VariableDeclarator <: Node {
+# type: "VariableDeclarator";
+# id: LVal;
+# init: Expression | null;
+# }
+nodes {
+ name: "VariableDeclarator"
+ parents: "Node"
+ type: "VariableDeclarator"
+ fields {
+ name: "id"
+ type { class: "LVal" }
+ kind: FIELD_KIND_LVAL
+ }
+ fields {
+ name: "init"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+}
+
+# // interface Decorator <: Node {
+# // type: "Decorator";
+# // expression: Expression;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "decorators" plugin.
+# ------------------------------------------------------------------------------
+
+# interface Directive <: Node {
+# type: "Directive";
+# value: DirectiveLiteral;
+# }
+# ------------------------------------------------------------------------------
+# Example:
+# "use strict"
+# ------------------------------------------------------------------------------
+nodes {
+ name: "Directive"
+ parents: "Node"
+ type: "Directive"
+ fields {
+ name: "value"
+ type { class: "DirectiveLiteral" }
+ kind: FIELD_KIND_RVAL
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
+
+# // interface DirectiveLiteral <: StringLiteral {
+# // type: "DirectiveLiteral";
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We shouldn't override a leaf type.
+# ------------------------------------------------------------------------------
+# interface DirectiveLiteral <: Node {
+# type: "DirectiveLiteral";
+# value: string;
+# extra?: {
+# raw: string;
+# rawValue: string;
+# }
+# }
+nodes {
+ name: "DirectiveLiteralExtra"
+ type: "DirectiveLiteralExtra"
+ fields {
+ name: "raw"
+ type: { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "rawValue"
+ type: { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+}
+
+nodes {
+ name: "DirectiveLiteral"
+ parents: "Node"
+ type: "DirectiveLiteral"
+ fields {
+ name: "value"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "extra"
+ type { class: "DirectiveLiteralExtra" }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+#
+# interface InterpreterDirective <: StringLiteral {
+# type: "InterpreterDirective";
+# }
+#
+# ------------------------------------------------------------------------------
+# NOTE: We shouldn't override a leaf type.
+# ------------------------------------------------------------------------------
+# interface InterpreterDirective <: Node {
+# type: "InterpreterDirective";
+# value: string;
+# }
+# ------------------------------------------------------------------------------
+# Example:
+# #!/usr/bin/env node
+# ------------------------------------------------------------------------------
+nodes {
+ name: "InterpreterDirective"
+ parents: "Node"
+ type: "InterpreterDirective"
+ fields {
+ name: "value"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+ should_generate_ir_op: false
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface Expression <: Node { }
+nodes {
+ name: "Expression"
+ parents: "Node"
+ kinds: FIELD_KIND_RVAL
+}
+
+# (From @babel/types)
+# type LVal =
+# | Identifier (is Pattern)
+# | MemberExpression (is Pattern)
+# | RestElement (is Pattern)
+# | AssignmentPattern
+# | ArrayPattern
+# | ObjectPattern
+# | TSParameterProperty
+nodes {
+ name: "LVal"
+ parents: "Node"
+ kinds: FIELD_KIND_LVAL
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface Super <: Node {
+# type: "Super";
+# }
+# ------------------------------------------------------------------------------
+# NOTE: A `super` pseudo-expression.
+#
+# Only used in:
+# - MemberExpression::object
+# - CallExpression::callee
+# - NewExpression::callee
+#
+# Example:
+# return super.foo;
+# ~~~~~
+# ------------------------------------------------------------------------------
+nodes {
+ name: "Super"
+ parents: "Node"
+ type: "Super"
+ should_generate_ir_op: true
+ kinds: FIELD_KIND_RVAL
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface Import <: Node {
+# type: "Import";
+# }
+# ------------------------------------------------------------------------------
+# NOTE: A `import` pseudo-expression.
+#
+# Only used in:
+# - CallExpression::callee
+# - NewExpression::callee
+#
+# Example:
+# import('test.js');
+# ~~~~~~
+# ------------------------------------------------------------------------------
+nodes {
+ name: "Import"
+ parents: "Node"
+ type: "Import"
+ should_generate_ir_op: true
+ kinds: FIELD_KIND_RVAL
+}
+
+# interface ThisExpression <: Expression {
+# type: "ThisExpression";
+# }
+nodes {
+ name: "ThisExpression"
+ parents: "Expression"
+ type: "ThisExpression"
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface ArrowFunctionExpression <: Function, Expression {
+# type: "ArrowFunctionExpression";
+# body: BlockStatement | Expression;
+# }
+nodes {
+ name: "ArrowFunctionExpression"
+ parents: "Function"
+ parents: "Expression"
+ type: "ArrowFunctionExpression"
+ fields {
+ name: "body"
+ type {
+ variant {
+ types { class: "BlockStatement" }
+ types { class: "Expression" }
+ }
+ }
+ }
+ should_generate_ir_op: false
+}
+
+# interface YieldExpression <: Expression {
+# type: "YieldExpression";
+# argument: Expression | null;
+# delegate: boolean;
+# }
+nodes {
+ name: "YieldExpression"
+ type: "YieldExpression"
+ parents: "Expression"
+ fields {
+ name: "argument"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "delegate"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface AwaitExpression <: Expression {
+# type: "AwaitExpression";
+# argument: Expression | null;
+# }
+nodes {
+ name: "AwaitExpression"
+ parents: "Expression"
+ type: "AwaitExpression"
+ fields {
+ name: "argument"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface ArrayExpression <: Expression {
+# type: "ArrayExpression";
+# elements: [ Expression | SpreadElement | null ];
+# }
+nodes {
+ name: "ArrayExpression"
+ parents: "Expression"
+ type: "ArrayExpression"
+ fields {
+ name: "elements"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "Expression" }
+ types { class: "SpreadElement" }
+ }
+ }
+ element_maybe_null: true
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface ObjectExpression <: Expression {
+# type: "ObjectExpression";
+# properties: [ ObjectProperty | ObjectMethod | SpreadElement ];
+# }
+nodes {
+ name: "ObjectExpression"
+ type: "ObjectExpression"
+ parents: "Expression"
+ fields {
+ name: "properties"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "ObjectProperty" }
+ types { class: "ObjectMethod" }
+ types { class: "SpreadElement" }
+ }
+ }
+ }
+ }
+ }
+ should_generate_ir_op: false
+}
+
+# // interface ObjectMember <: Node {
+# // key: Expression;
+# // computed: boolean;
+# // decorators: [ Decorator ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "decorators" plugin.
+# ------------------------------------------------------------------------------
+# interface ObjectMember <: Node {
+# key: Expression;
+# computed: boolean;
+# }
+nodes {
+ name: "ObjectMember"
+ parents: "Node"
+ fields {
+ name: "key"
+ type { class: "Expression" }
+ }
+ fields {
+ name: "computed"
+ type { bool {} }
+ }
+}
+
+# // interface ObjectProperty <: ObjectMember {
+# // type: "ObjectProperty";
+# // shorthand: boolean;
+# // value: Expression;
+# // }
+# interface ObjectProperty <: ObjectMember {
+# type: "ObjectProperty";
+# shorthand: boolean;
+# value: Expression | Pattern;
+# }
+nodes {
+ name: "ObjectProperty"
+ parents: "ObjectMember"
+ type: "ObjectProperty"
+ fields {
+ name: "shorthand"
+ type { bool {} }
+ }
+ fields {
+ name: "value"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "Pattern" }
+ }
+ }
+ }
+ kinds: FIELD_KIND_LVAL
+ kinds: FIELD_KIND_RVAL
+}
+
+#
+# interface ObjectMethod <: ObjectMember, Function {
+# type: "ObjectMethod";
+# kind: "get" | "set" | "method";
+# }
+#
+# ------------------------------------------------------------------------------
+# interface ObjectMethod <: ObjectMember, BlockStatementFunction {
+# type: "ObjectMethod";
+# kind: "get" | "set" | "method";
+# }
+nodes {
+ name: "ObjectMethod"
+ type: "ObjectMethod"
+ parents: "ObjectMember"
+ parents: "BlockStatementFunction"
+ fields {
+ name: "kind"
+ type { string {} }
+ }
+}
+
+# // interface RecordExpression <: Expression {
+# // type: "RecordExpression";
+# // properties: [ ObjectProperty | ObjectMethod | SpreadElement ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "recordAndTuple" plugin.
+# ------------------------------------------------------------------------------
+
+# // interface TupleExpression <: Expression {
+# // type: "TupleExpression";
+# // elements: [ Expression | SpreadElement | null ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "recordAndTuple" plugin.
+# ------------------------------------------------------------------------------
+
+# interface FunctionExpression <: BlockStatementFunction, Expression {
+# type: "FunctionExpression";
+# }
+nodes {
+ name: "FunctionExpression"
+ type: "FunctionExpression"
+ parents: "BlockStatementFunction"
+ parents: "Expression"
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+}
+
+# interface UnaryExpression <: Expression {
+# type: "UnaryExpression";
+# operator: UnaryOperator;
+# prefix: boolean;
+# argument: Expression;
+# }
+# enum UnaryOperator {
+# "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" | "throw"
+# }
+nodes {
+ name: "UnaryExpression"
+ type: "UnaryExpression"
+ parents: "Expression"
+ fields {
+ name: "operator"
+ type { enum: "UnaryOperator" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "prefix"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "argument"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+ has_fold: true
+}
+
+# // Original:
+# // interface UpdateExpression <: Expression {
+# // type: "UpdateExpression";
+# // operator: UpdateOperator;
+# // argument: Expression;
+# // prefix: boolean;
+# // }
+# interface UpdateExpression <: Expression {
+# type: "UpdateExpression";
+# operator: UpdateOperator;
+# argument: LVal;
+# prefix: boolean;
+# }
+# enum UpdateOperator {
+# "++" | "--"
+# }
+nodes {
+ name: "UpdateExpression"
+ type: "UpdateExpression"
+ parents: "Expression"
+ fields {
+ name: "operator"
+ type { enum: "UpdateOperator" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "argument"
+ type { class: "LVal" }
+ kind: FIELD_KIND_LVAL
+ }
+ fields {
+ name: "prefix"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface BinaryExpression <: Expression {
+# type: "BinaryExpression";
+# operator: BinaryOperator;
+# left: Expression | PrivateName;
+# right: Expression;
+# }
+# enum BinaryOperator {
+# "==" | "!=" | "===" | "!=="
+# | "<" | "<=" | ">" | ">="
+# | "<<" | ">>" | ">>>"
+# | "+" | "-" | "*" | "/" | "%"
+# | "**" | "|" | "^" | "&" | "in"
+# | "instanceof"
+# | "|>"
+# }
+nodes {
+ name: "BinaryExpression"
+ type: "BinaryExpression"
+ parents: "Expression"
+ fields {
+ name: "operator"
+ type { enum: "BinaryOperator" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "left"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "PrivateName" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "right"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+ has_fold: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# // interface AssignmentExpression <: Expression {
+# // type: "AssignmentExpression";
+# // operator: AssignmentOperator;
+# // left: Pattern | Expression;
+# // right: Expression;
+# // }
+# interface AssignmentExpression <: Expression {
+# type: "AssignmentExpression";
+# operator: AssignmentOperator;
+# left: LVal;
+# right: Expression;
+# }
+# enum AssignmentOperator {
+# "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**="
+# | "<<=" | ">>=" | ">>>="
+# | "|=" | "^=" | "&="
+# | "||=" | "&&=" | "??="
+# }
+nodes {
+ name: "AssignmentExpression"
+ parents: "Expression"
+ type: "AssignmentExpression"
+ fields {
+ name: "operator"
+ type { enum: "AssignmentOperator" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "left"
+ type { class: "LVal" }
+ kind: FIELD_KIND_LVAL
+ }
+ fields {
+ name: "right"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface LogicalExpression <: Expression {
+# type: "LogicalExpression";
+# operator: LogicalOperator;
+# left: Expression;
+# right: Expression;
+# }
+# enum LogicalOperator {
+# "||" | "&&" | "??"
+# }
+nodes {
+ name: "LogicalExpression"
+ parents: "Expression"
+ type: "LogicalExpression"
+ fields {
+ name: "operator"
+ type { enum: "LogicalOperator" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "left"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "right"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ should_generate_ir_op: true
+ has_control_flow: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface SpreadElement <: Node {
+# type: "SpreadElement";
+# argument: Expression;
+# }
+# ------------------------------------------------------------------------------
+# Example:
+# func(...a)
+# ~~~~
+# ------------------------------------------------------------------------------
+nodes {
+ name: "SpreadElement"
+ parents: "Node"
+ type: "SpreadElement"
+ fields {
+ name: "argument"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# // interface ArgumentPlaceholder <: Node {
+# // type: "ArgumentPlaceholder";
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "partialApplication" plugin.
+# ------------------------------------------------------------------------------
+
+# // interface MemberExpression <: Expression, Pattern {
+# // type: "MemberExpression";
+# // object: Expression | Super;
+# // property: Expression | PrivateName;
+# // computed: boolean;
+# // }
+# interface MemberExpression <: Expression, Pattern, LVal {
+# type: "MemberExpression";
+# object: Expression | Super;
+# property: Expression | PrivateName;
+# computed: boolean;
+# }
+# ------------------------------------------------------------------------------
+# NOTE: A member expression.
+# - If `computed` is `true`, the node corresponds to a computed (`a[b]`) member
+# expression and `property` is an `Expression`.
+# - If `computed` is `false`, the node corresponds to a static (`a.b`) member
+# expression and `property` is an `Identifier` or a `PrivateName`.
+# ------------------------------------------------------------------------------
+nodes {
+ name: "MemberExpression"
+ parents: "Expression"
+ parents: "Pattern"
+ parents: "LVal"
+ type: "MemberExpression"
+ fields {
+ name: "object"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "Super" }
+ }
+ }
+ }
+ fields {
+ name: "property"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "PrivateName" }
+ }
+ }
+ }
+ fields {
+ name: "computed"
+ type { bool {} }
+ }
+ should_generate_ir_op: false
+}
+
+# interface OptionalMemberExpression <: Expression {
+# type: "OptionalMemberExpression";
+# object: Expression;
+# property: Expression | PrivateName;
+# computed: boolean;
+# optional: boolean;
+# }
+# TODO(tzx) Why not used anywhere?
+# ------------------------------------------------------------------------------
+# NOTE: An optional member expression is a part of the optional chain.
+#
+# When `optional` is `true`, it is the starting element of the optional chain.
+#
+# In `a?.b.c`:
+# - `?.b` is an optional member expression with `optional: true`
+# - `.c` is an optional member expression
+#
+# See https://gist.github.com/JLHwung/567fb29fa2b82bbe164ad9067ff3290f for more
+# AST examples.
+# ------------------------------------------------------------------------------
+nodes {
+ name: "OptionalMemberExpression"
+ parents: "Expression"
+ type: "OptionalMemberExpression"
+ fields {
+ name: "object"
+ type { class: "Expression" }
+ }
+ fields {
+ name: "property"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "PrivateName" }
+ }
+ }
+ }
+ fields {
+ name: "computed"
+ type { bool {} }
+ }
+ fields {
+ name: "optional"
+ type { bool {} }
+ }
+ should_generate_ir_op: false
+}
+
+# // interface BindExpression <: Expression {
+# // type: "BindExpression";
+# // object: Expression | null;
+# // callee: Expression;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "functionBind" plugin.
+# ------------------------------------------------------------------------------
+
+# interface PipelineBody <: NodeBase {
+# type: "PipelineBody";
+# }
+
+# interface PipelineBody <: NodeBase {
+# type: "PipelineBareFunctionBody";
+# callee: Expression;
+# }
+
+# interface PipelineBareConstructorBody <: NodeBase {
+# type: "PipelineBareConstructorBody";
+# callee: Expression;
+# }
+
+# interface PipelineBareConstructorBody <: NodeBase {
+# type: "PipelineTopicBody";
+# expression: Expression;
+# }
+
+# interface PipelineBareConstructorBody <: NodeBase {
+# type: "PipelineBareAwaitedFunctionBody";
+# callee: Expression;
+# }
+
+# interface ConditionalExpression <: Expression {
+# type: "ConditionalExpression";
+# test: Expression;
+# alternate: Expression;
+# consequent: Expression;
+# }
+nodes {
+ name: "ConditionalExpression"
+ type: "ConditionalExpression"
+ parents: "Expression"
+ fields {
+ name: "test"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "alternate"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "consequent"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ has_control_flow: true
+ should_generate_ir_op: true
+}
+
+# interface CallExpression <: Expression {
+# type: "CallExpression";
+# callee: Expression | Super | Import;
+# arguments: [ Expression | SpreadElement ];
+# }
+nodes {
+ name: "CallExpression"
+ parents: "Expression"
+ type: "CallExpression"
+ fields {
+ name: "callee"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "Super" }
+ types { class: "Import" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "arguments"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "Expression" }
+ types { class: "SpreadElement" }
+ }
+ }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface OptionalCallExpression <: Expression {
+# type: "OptionalCallExpression";
+# callee: Expression;
+# arguments: [ Expression | SpreadElement ];
+# optional: boolean;
+# }
+nodes {
+ name: "OptionalCallExpression"
+ parents: "Expression"
+ type: "OptionalCallExpression"
+ fields {
+ name: "callee"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "arguments"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "Expression" }
+ types { class: "SpreadElement" }
+ }
+ }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "optional"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# // interface NewExpression <: CallExpression {
+# // type: "NewExpression";
+# // }
+# interface NewExpression <: Expression {
+# type: "NewExpression";
+# callee: Expression | Super | Import;
+# arguments: [ Expression | SpreadElement ];
+# }
+nodes {
+ name: "NewExpression"
+ type: "NewExpression"
+ parents: "Expression"
+ fields {
+ name: "callee"
+ type {
+ variant {
+ types { class: "Expression" }
+ types { class: "Super" }
+ types { class: "Import" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "arguments"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "Expression" }
+ types { class: "SpreadElement" }
+ }
+ }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# interface SequenceExpression <: Expression {
+# type: "SequenceExpression";
+# expressions: [ Expression ];
+# }
+nodes {
+ name: "SequenceExpression"
+ parents: "Expression"
+ type: "SequenceExpression"
+ fields {
+ name: "expressions"
+ type {
+ list {
+ element_type { class: "Expression" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# // Original:
+# // interface ParenthesizedExpression <: Expression {
+# // type "ParenthesizedExpression";
+# // expression: Expression;
+# // }
+# interface ParenthesizedExpression <: Expression, Pattern, LVal {
+# type "ParenthesizedExpression";
+# expression: Expression;
+# }
+nodes {
+ name: "ParenthesizedExpression"
+ parents: "Expression"
+ parents: "Pattern"
+ parents: "LVal"
+ type: "ParenthesizedExpression"
+ fields {
+ name: "expression"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: false
+ has_fold: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# // interface DoExpression <: Expression {
+# // type: "DoExpression";
+# // body: BlockStatement;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "doExpression" plugin.
+# ------------------------------------------------------------------------------
+
+# // interface ModuleExpression <: Expression {
+# // type: "ModuleExpression";
+# // body: Program
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "moduleBlocks" plugin.
+# ------------------------------------------------------------------------------
+
+# interface TemplateLiteral <: Expression {
+# type: "TemplateLiteral";
+# quasis: [ TemplateElement ];
+# expressions: [ Expression ];
+# }
+# ------------------------------------------------------------------------------
+# Example:
+# `a${b}c${d}`
+# ~~~~~~~~~~~~ TemplateLiteral
+# ~ ~ ~ quasis (including the last "")
+# ~~~~ ~~~~ expressions
+# ------------------------------------------------------------------------------
+nodes {
+ name: "TemplateLiteral"
+ parents: "Expression"
+ type: "TemplateLiteral"
+ fields {
+ name: "quasis"
+ type {
+ list {
+ element_type { class: "TemplateElement" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "expressions"
+ type {
+ list {
+ element_type { class: "Expression" }
+ }
+ }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface TaggedTemplateExpression <: Expression {
+# type: "TaggedTemplateExpression";
+# tag: Expression;
+# quasi: TemplateLiteral;
+# }
+# ------------------------------------------------------------------------------
+# Example:
+# raw`42`
+# ~~~~~~~ TaggedTemplateExpression
+# ~~~ tag
+# ~~~~ quasi
+# ------------------------------------------------------------------------------
+nodes {
+ name: "TaggedTemplateExpression"
+ parents: "Expression"
+ type: "TaggedTemplateExpression"
+ fields {
+ name: "tag"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "quasi"
+ type { class: "TemplateLiteral" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface TemplateElement <: Node {
+# type: "TemplateElement";
+# tail: boolean;
+# value: {
+# cooked: string | null;
+# raw: string;
+# };
+# }
+nodes {
+ name: "TemplateElementValue"
+ fields {
+ name: "cooked"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "raw"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+}
+nodes {
+ name: "TemplateElement"
+ parents: "Node"
+ type: "TemplateElement"
+ fields {
+ name: "tail"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "value"
+ type { class: "TemplateElementValue" }
+ kind: FIELD_KIND_RVAL
+ }
+ kinds: FIELD_KIND_RVAL
+ should_generate_ir_op: true
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# interface Pattern <: Node { }
+nodes {
+ name: "Pattern"
+ parents: "Node"
+ kinds: FIELD_KIND_LVAL
+ additional_mlir_traits: MLIR_TRAIT_PURE
+}
+
+# // interface AssignmentProperty <: ObjectProperty {
+# // value: Pattern;
+# // }
+# Note: ObjectProperty is already a leaf type. Here the spec tries to override
+# the type of "value" from "Expression" to "Pattern".
+# Therefore, we just let "value" be "Expression | Pattern" in ObjectProperty,
+# and thus delete AssignmentProperty.
+
+# // interface ObjectPattern <: Pattern {
+# // type: "ObjectPattern";
+# // properties: [ AssignmentProperty | RestElement ];
+# // }
+# interface ObjectPattern <: Pattern, LVal {
+# type: "ObjectPattern";
+# properties: [ ObjectProperty | RestElement ];
+# }
+nodes {
+ name: "ObjectPattern"
+ type: "ObjectPattern"
+ parents: "Pattern"
+ parents: "LVal"
+ fields {
+ name: "properties"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "ObjectProperty" }
+ types { class: "RestElement" }
+ }
+ }
+ }
+ }
+ kind: FIELD_KIND_LVAL
+ enclose_in_region: true
+ }
+ should_generate_ir_op: true
+}
+
+# // interface ArrayPattern <: Pattern {
+# // type: "ArrayPattern";
+# // elements: [ Pattern | null ];
+# // }
+# interface ArrayPattern <: Pattern, LVal {
+# type: "ArrayPattern";
+# elements: [ Pattern | null ];
+# }
+nodes {
+ name: "ArrayPattern"
+ type: "ArrayPattern"
+ parents: "Pattern"
+ parents: "LVal"
+ fields {
+ name: "elements"
+ type {
+ list {
+ element_type { class: "Pattern" }
+ element_maybe_null: true
+ }
+ }
+ kind: FIELD_KIND_LVAL
+ }
+ should_generate_ir_op: true
+}
+
+# // interface RestElement <: Pattern {
+# // type: "RestElement";
+# // argument: Pattern;
+# // }
+# interface RestElement <: Pattern, LVal {
+# type: "RestElement";
+# argument: LVal;
+# }
+nodes {
+ name: "RestElement"
+ parents: "Pattern"
+ parents: "LVal"
+ type: "RestElement"
+ fields {
+ name: "argument"
+ type { class: "LVal" }
+ kind: FIELD_KIND_LVAL
+ }
+ should_generate_ir_op: true
+}
+
+# // interface AssignmentPattern <: Pattern {
+# // type: "AssignmentPattern";
+# // left: Pattern;
+# // right: Expression;
+# // }
+# interface AssignmentPattern <: Pattern, LVal {
+# type: "AssignmentPattern";
+# left: Pattern;
+# right: Expression;
+# }
+nodes {
+ name: "AssignmentPattern"
+ parents: "Pattern"
+ parents: "LVal"
+ type: "AssignmentPattern"
+ fields {
+ name: "left"
+ type { class: "Pattern" }
+ kind: FIELD_KIND_LVAL
+ }
+ fields {
+ name: "right"
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ should_generate_ir_op: true
+}
+
+# // interface Class <: Node {
+# // id: Identifier | null;
+# // superClass: Expression | null;
+# // body: ClassBody;
+# // decorators: [ Decorator ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "decorators" plugin.
+# ------------------------------------------------------------------------------
+# interface Class <: Node {
+# superClass: Expression | null;
+# body: ClassBody;
+# }
+nodes {
+ name: "Class"
+ parents: "Node"
+ fields {
+ name: "superClass"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ }
+ fields {
+ name: "body"
+ type { class: "ClassBody" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+}
+
+# // interface ClassBody <: Node {
+# // type: "ClassBody";
+# // body: [ ClassMethod | ClassPrivateMethod | ClassProperty | ClassPrivateProperty | StaticBlock ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "classStaticBlock" plugin.
+# ------------------------------------------------------------------------------
+# interface ClassBody <: Node {
+# type: "ClassBody";
+# body: [ ClassMethod | ClassPrivateMethod | ClassProperty | ClassPrivateProperty ];
+# }
+nodes {
+ name: "ClassBody"
+ type: "ClassBody"
+ parents: "Node"
+ fields {
+ name: "body"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "ClassMethod" }
+ types { class: "ClassPrivateMethod" }
+ types { class: "ClassProperty" }
+ types { class: "ClassPrivateProperty" }
+ }
+ }
+ }
+ }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
+
+# // interface ClassMethod <: Function {
+# // type: "ClassMethod";
+# // key: Expression;
+# // kind: "constructor" | "method" | "get" | "set";
+# // computed: boolean;
+# // static: boolean;
+# // decorators: [ Decorator ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "decorators" plugin.
+# ------------------------------------------------------------------------------
+# interface ClassMethod <: BodyStatementFunction {
+# type: "ClassMethod";
+# key: Expression;
+# kind: "constructor" | "method" | "get" | "set";
+# computed: boolean;
+# static: boolean;
+# }
+#
+# NOTE:
+# - If computed is false, key must be one of:
+# - Identifier
+# - StringLiteral
+# - NumericLiteral
+#
+# Example:
+# ```
+# class MyClass {
+# foo() {} // Identifier
+# "bar"() {} // StringLiteral
+# 1.0() {} // NumericLiteral
+# }
+#
+# let obj = new MyClass();
+# console.log(obj.foo);
+# console.log(obj["foo"]);
+# console.log(obj.bar);
+# console.log(obj["bar"]);
+# console.log(obj[1.0]);
+# ```
+#
+# Reference: https://tc39.es/ecma262/#prod-LiteralPropertyName
+#
+# - If computed is true, key can be any expression (rvalue).
+#
+# Example:
+# ```
+# let foo = "oof";
+# let bar = "rab";
+# let baz = "zab";
+#
+# class MyClass {
+# [foo]() {}
+# [bar + baz]() {}
+# [1.0]() {}
+# }
+#
+# let obj = new MyClass();
+# console.log(obj.oof);
+# console.log(obj["oof"]);
+# console.log(obj.zabrab);
+# console.log(obj["zabrab"]);
+# console.log(obj[1.0]);
+# ```
+#
+# Reference: https://tc39.es/ecma262/#prod-ComputedPropertyName
+nodes {
+ name: "ClassMethod"
+ parents: "BlockStatementFunction"
+ type: "ClassMethod"
+ fields {
+ name: "key"
+ type { class: "Expression" }
+ }
+ fields {
+ name: "kind"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "computed"
+ type { bool {} }
+ }
+ fields {
+ name: "static"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: false
+}
+
+# // interface ClassPrivateMethod <: Function {
+# // type: "ClassPrivateMethod";
+# // key: PrivateName;
+# // kind: "method" | "get" | "set";
+# // static: boolean;
+# // decorators: [ Decorator ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "decorators" plugin.
+# ------------------------------------------------------------------------------
+# interface ClassPrivateMethod <: BlockStatementFunction {
+# type: "ClassPrivateMethod";
+# key: PrivateName;
+# kind: "method" | "get" | "set";
+# static: boolean;
+# computed?: boolean; # Actually always false
+# }
+nodes {
+ name: "ClassPrivateMethod"
+ parents: "BlockStatementFunction"
+ type: "ClassPrivateMethod"
+ fields {
+ name: "key"
+ type { class: "PrivateName" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "kind"
+ type { string {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "static"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "computed"
+ type { bool {} }
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: false
+}
+
+# // interface ClassProperty <: Node {
+# // type: "ClassProperty";
+# // key: Expression;
+# // value: Expression;
+# // static: boolean;
+# // computed: boolean;
+# // }
+# interface ClassProperty <: Node {
+# type: "ClassProperty";
+# key: Expression;
+# value: Expression | null;
+# static: boolean;
+# computed: boolean;
+# }
+#
+# NOTE:
+# - If computed is false, key must be one of:
+# - Identifier
+# - StringLiteral
+# - NumericLiteral
+#
+# Example:
+# ```
+# class MyClass {
+# foo = 1 // Identifier
+# "bar" = 1 // StringLiteral
+# 1.0 = 1 // NumericLiteral
+# }
+#
+# let obj = new MyClass();
+# console.log(obj.foo);
+# console.log(obj["foo"]);
+# console.log(obj.bar);
+# console.log(obj["bar"]);
+# console.log(obj[1.0]);
+# ```
+#
+# Reference: https://tc39.es/ecma262/#prod-LiteralPropertyName
+#
+# - If computed is true, key can be any expression (rvalue).
+#
+# Example:
+# ```
+# let foo = "oof";
+# let bar = "rab";
+# let baz = "zab";
+#
+# class MyClass {
+# [foo] = 1
+# [bar + baz] = 1
+# [1.0] = 1
+# }
+#
+# let obj = new MyClass();
+# console.log(obj.oof);
+# console.log(obj["oof"]);
+# console.log(obj.zabrab);
+# console.log(obj["zabrab"]);
+# console.log(obj[1.0]);
+# ```
+#
+# Reference: https://tc39.es/ecma262/#prod-ComputedPropertyName
+nodes {
+ name: "ClassProperty"
+ parents: "Node"
+ type: "ClassProperty"
+ fields {
+ name: "key"
+ type { class: "Expression" }
+ }
+ fields {
+ name: "value"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "static"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "computed"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: false
+}
+
+# // interface ClassPrivateProperty <: Node {
+# // type: "ClassPrivateProperty";
+# // key: PrivateName;
+# // value: Expression;
+# // static: boolean;
+# // }
+# interface ClassPrivateProperty <: Node {
+# type: "ClassPrivateProperty";
+# key: PrivateName;
+# value: Expression | null;
+# static: boolean;
+# }
+nodes {
+ name: "ClassPrivateProperty"
+ parents: "Node"
+ type: "ClassPrivateProperty"
+ fields {
+ name: "key"
+ type { class: "PrivateName" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "value"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Expression" }
+ kind: FIELD_KIND_RVAL
+ enclose_in_region: true
+ }
+ fields {
+ name: "static"
+ type { bool {} }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
+
+# // interface StaticBlock <: Node {
+# // type: "StaticBlock";
+# // body: [ Statement ];
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: We don't enable the Babel "classStaticBlock" plugin.
+# ------------------------------------------------------------------------------
+
+# // interface ClassDeclaration <: Class, Declaration {
+# // type: "ClassDeclaration";
+# // id: Identifier;
+# // }
+# ------------------------------------------------------------------------------
+# NOTE: The spec also has OptClassDeclaration where id: Identifier | null.
+# We can't support field type override.
+# Therefore, we always let id: Identifier | null, and delete
+# OptClassDeclaration.
+# ------------------------------------------------------------------------------
+# interface ClassDeclaration <: Class, Declaration {
+# type: "ClassDeclaration";
+# id: Identifier | null;
+# }
+nodes {
+ name: "ClassDeclaration"
+ parents: "Class"
+ parents: "Declaration"
+ type: "ClassDeclaration"
+ fields {
+ name: "id"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface ClassExpression <: Class, Expression {
+# type: "ClassExpression";
+# }
+# ------------------------------------------------------------------------------
+# NOTE: ???
+# ------------------------------------------------------------------------------
+# interface ClassExpression <: Class, Expression {
+# type: "ClassExpression";
+# id: string | null
+# }
+nodes {
+ name: "ClassExpression"
+ parents: "Class"
+ parents: "Expression"
+ type: "ClassExpression"
+ fields {
+ name: "id"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface MetaProperty <: Expression {
+# type: "MetaProperty";
+# meta: Identifier;
+# property: Identifier;
+# }
+# ------------------------------------------------------------------------------
+# NOTE:
+# MetaProperty is used for special "." expressions.
+# Normally, "." would be represented by MemberExpression.
+#
+# Currently, only the following are meta properties:
+# - import.meta
+# - new.target
+# - function.sent
+# (will be a SyntaxError, since it requires the "functionSent" Babel plugin)
+# ------------------------------------------------------------------------------
+nodes {
+ name: "MetaProperty"
+ parents: "Expression"
+ type: "MetaProperty"
+ fields {
+ name: "meta"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "property"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface ModuleDeclaration <: Node { }
+nodes {
+ name: "ModuleDeclaration"
+ parents: "Node"
+ kinds: FIELD_KIND_STMT
+}
+
+# // interface ModuleSpecifier <: Node {
+# // local: Identifier;
+# // }
+# ------------------------------------------------------------------------------
+# Note: "ExportSpecifier", which extends "ModuleSpecifier", has
+# "local?: Identifier | StringLiteral";
+# ------------------------------------------------------------------------------
+# interface ModuleSpecifier <: Node {}
+nodes {
+ name: "ModuleSpecifier"
+ parents: "Node"
+ kinds: FIELD_KIND_ATTR
+}
+
+# // interface ImportDeclaration <: ModuleDeclaration {
+# // type: "ImportDeclaration";
+# // importKind: null | "type" | "typeof" | "value";
+# // specifiers: [ ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier ];
+# // source: StringLiteral;
+# // assertions?: [ ImportAttribute ];
+# // }
+# ------------------------------------------------------------------------------
+# Note: "importKind" is only populated with the "flow" plugin enabled
+# ------------------------------------------------------------------------------
+# interface ImportDeclaration <: ModuleDeclaration {
+# type: "ImportDeclaration";
+# specifiers: [ ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier ];
+# source: StringLiteral;
+# assertions?: [ ImportAttribute ];
+# }
+nodes {
+ name: "ImportDeclaration"
+ type: "ImportDeclaration"
+ parents: "ModuleDeclaration"
+ fields {
+ name: "specifiers"
+ type {
+ list {
+ element_type {
+ variant {
+ types { class: "ImportSpecifier" }
+ types { class: "ImportDefaultSpecifier" }
+ types { class: "ImportNamespaceSpecifier" }
+ }
+ }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "source"
+ type { class: "StringLiteral" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "assertions"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type { class: "ImportAttribute" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# // interface ImportSpecifier <: ModuleSpecifier {
+# // type: "ImportSpecifier";
+# // imported: Identifier | StringLiteral;
+# // }
+# interface ImportSpecifier <: ModuleSpecifier {
+# type: "ImportSpecifier";
+# imported: Identifier | StringLiteral;
+# local: Identifier;
+# }
+nodes {
+ name: "ImportSpecifier"
+ parents: "ModuleSpecifier"
+ type: "ImportSpecifier"
+ fields {
+ name: "imported"
+ type {
+ variant {
+ types { class: "Identifier" }
+ types { class: "StringLiteral" }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "local"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: false
+}
+
+# // interface ImportDefaultSpecifier <: ModuleSpecifier {
+# // type: "ImportDefaultSpecifier";
+# // }
+# interface ImportDefaultSpecifier <: ModuleSpecifier {
+# type: "ImportDefaultSpecifier";
+# local: Identifier;
+# }
+nodes {
+ name: "ImportDefaultSpecifier"
+ parents: "ModuleSpecifier"
+ type: "ImportDefaultSpecifier"
+ fields {
+ name: "local"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: false
+}
+
+# // interface ImportNamespaceSpecifier <: ModuleSpecifier {
+# // type: "ImportNamespaceSpecifier";
+# // }
+# interface ImportNamespaceSpecifier <: ModuleSpecifier {
+# type: "ImportNamespaceSpecifier";
+# local: Identifier;
+# }
+nodes {
+ name: "ImportNamespaceSpecifier"
+ parents: "ModuleSpecifier"
+ type: "ImportNamespaceSpecifier"
+ fields {
+ name: "local"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: false
+}
+
+# interface ImportAttribute <: Node {
+# type: "ImportAttribute";
+# key: Identifier;
+# value: StringLiteral;
+# }
+nodes {
+ name: "ImportAttribute"
+ parents: "Node"
+ type: "ImportAttribute"
+ fields {
+ name: "key"
+ type { class: "Identifier" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "value"
+ type { class: "StringLiteral" }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_ATTR
+ should_generate_ir_op: false
+}
+
+# interface ExportNamedDeclaration <: ModuleDeclaration {
+# type: "ExportNamedDeclaration";
+# declaration: Declaration | null;
+# specifiers: [ ExportSpecifier ];
+# source: StringLiteral | null;
+# assertions?: [ ImportAttribute ];
+# }
+nodes {
+ name: "ExportNamedDeclaration"
+ type: "ExportNamedDeclaration"
+ parents: "ModuleDeclaration"
+ fields {
+ name: "declaration"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "Declaration" }
+ kind: FIELD_KIND_STMT
+ enclose_in_region: true
+ }
+ fields {
+ name: "specifiers"
+ type {
+ list {
+ element_type { class: "ExportSpecifier" }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "source"
+ optionalness: OPTIONALNESS_MAYBE_NULL
+ type { class: "StringLiteral" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "assertions"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type { class: "ImportAttribute" }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: true
+}
+
+# interface ExportSpecifier <: ModuleSpecifier {
+# type: "ExportSpecifier";
+# exported: Identifier | StringLiteral;
+# local?: Identifier | StringLiteral;
+# }
+nodes {
+ name: "ExportSpecifier"
+ type: "ExportSpecifier"
+ parents: "ModuleSpecifier"
+ fields {
+ name: "exported"
+ type {
+ variant {
+ types {
+ class: "Identifier"
+ }
+ types {
+ class: "StringLiteral"
+ }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "local"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ variant {
+ types {
+ class: "Identifier"
+ }
+ types {
+ class: "StringLiteral"
+ }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ should_generate_ir_op: false
+}
+
+# // interface OptFunctionDeclaration <: FunctionDeclaration {
+# // id: Identifier | null;
+# // }
+# NOTE: "FunctionDeclaration" is already a leaf type.
+# Here the spec tries to override the type of "id" from "Identifier" to
+# "Identifier | null".
+# However, we can't support field type override. Therefore, we let "id" to be
+# always nullable (even in FunctionDeclaration) and thus delete
+# OptFunctionDeclaration.
+
+# // interface OptClassDeclaration <: ClassDeclaration {
+# // id: Identifier | null;
+# // }
+# NOTE: "ClassDeclaration" is already a leaf type.
+# Here the spec tries to override the type of "id" from "Identifier" to
+# "Identifier | null".
+# However, we can't support field type override. Therefore, we let "id" to be
+# always nullable (even in ClassDeclaration) and thus delete
+# OptClassDeclaration.
+
+# // interface ExportDefaultDeclaration <: ModuleDeclaration {
+# // type: "ExportDefaultDeclaration";
+# // declaration: OptFunctionDeclaration | OptClassDeclaration | Expression;
+# // }
+# interface ExportDefaultDeclaration <: ModuleDeclaration {
+# type: "ExportDefaultDeclaration";
+# declaration: FunctionDeclaration | ClassDeclaration | Expression;
+# }
+nodes {
+ name: "ExportDefaultDeclaration"
+ parents: "ModuleDeclaration"
+ type: "ExportDefaultDeclaration"
+ fields {
+ name: "declaration"
+ type {
+ variant {
+ types { class: "FunctionDeclaration" }
+ types { class: "ClassDeclaration" }
+ types { class: "Expression" }
+ }
+ }
+ }
+ should_generate_ir_op: false
+}
+
+# interface ExportAllDeclaration <: ModuleDeclaration {
+# type: "ExportAllDeclaration";
+# source: StringLiteral;
+# assertions?: [ ImportAttribute ];
+# }
+nodes {
+ name: "ExportAllDeclaration"
+ type: "ExportAllDeclaration"
+ parents: "ModuleDeclaration"
+ fields {
+ name: "source"
+ type { class: "StringLiteral" }
+ kind: FIELD_KIND_ATTR
+ }
+ fields {
+ name: "assertions"
+ optionalness: OPTIONALNESS_MAYBE_UNDEFINED
+ type {
+ list {
+ element_type { class: "ImportAttribute" }
+ }
+ }
+ kind: FIELD_KIND_ATTR
+ }
+ kinds: FIELD_KIND_STMT
+ should_generate_ir_op: true
+}
diff --git a/maldoca/js/ast/ast_gen_test.cc b/maldoca/js/ast/ast_gen_test.cc
new file mode 100644
index 00000000..628dcb56
--- /dev/null
+++ b/maldoca/js/ast/ast_gen_test.cc
@@ -0,0 +1,50 @@
+// Copyright 2024 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "maldoca/astgen/test/ast_gen_test_util.h"
+
+namespace maldoca {
+namespace astgen {
+namespace {
+
+INSTANTIATE_TEST_SUITE_P(
+ JavaScript, AstGenTest,
+ ::testing::Values(AstGenTestParam{
+ .ast_def_path =
+ "maldoca/js/ast/ast_def.textproto",
+ .cc_namespace = "maldoca",
+ .ast_path = "maldoca/js/ast",
+ .ir_path = "maldoca/js/ir",
+ .expected_ast_header_path =
+ "maldoca/js/ast/ast.generated.h",
+ .expected_ast_source_path =
+ "maldoca/js/ast/ast.generated.cc",
+ .expected_ast_to_json_path =
+ "maldoca/js/ast/ast_to_json.generated.cc",
+ .expected_ast_from_json_path =
+ "maldoca/js/ast/ast_from_json.generated.cc",
+ .expected_ir_tablegen_path =
+ "maldoca/js/ir/jsir_ops.generated.td",
+ .expected_ast_to_ir_source_path =
+ "maldoca/js/ir/conversion/"
+ "ast_to_jsir.generated.cc",
+ .expected_ir_to_ast_source_path =
+ "maldoca/js/ir/conversion/"
+ "jsir_to_ast.generated.cc",
+ }));
+
+} // namespace
+} // namespace astgen
+} // namespace maldoca
diff --git a/maldoca/js/driver/conversion.cc b/maldoca/js/driver/conversion.cc
index 26ebcd48..07437206 100644
--- a/maldoca/js/driver/conversion.cc
+++ b/maldoca/js/driver/conversion.cc
@@ -69,12 +69,11 @@ absl::StatusOr ToJsAstRepr::FromJsAstStringRepr(
// AST -> HIR
// -----------------------------------------------------------------------------
-absl::StatusOr ToJsHirRepr::FromJsAstRepr(
- const JsAstRepr &ast_repr,
- mlir::MLIRContext &mlir_context) {
+absl::StatusOr ToJsirRepr::FromJsAstRepr(
+ const JsAstRepr& ast_repr, mlir::MLIRContext& mlir_context) {
ABSL_ASSIGN_OR_RETURN(mlir::OwningOpRef op,
- AstToJshirFile(*ast_repr.ast, mlir_context));
- return JsHirRepr{std::move(op), ast_repr.scopes, ast_repr.source_map};
+ AstToJsirFile(*ast_repr.ast, mlir_context));
+ return JsirRepr{std::move(op), ast_repr.scopes, ast_repr.source_map};
}
// -----------------------------------------------------------------------------
@@ -96,29 +95,28 @@ absl::StatusOr ToJsAstRepr::FromJsSourceRepr(
// Source -> AST string -> AST -> HIR
// -----------------------------------------------------------------------------
-absl::StatusOr ToJsHirRepr::FromJsSourceRepr(
- const JsSourceRepr &source_repr, BabelParseRequest parse_request,
+absl::StatusOr ToJsirRepr::FromJsSourceRepr(
+ const JsSourceRepr& source_repr, BabelParseRequest parse_request,
absl::Duration timeout, std::optional recursion_depth_limit,
- Babel &babel, mlir::MLIRContext &mlir_context) {
+ Babel& babel, mlir::MLIRContext& mlir_context) {
ABSL_ASSIGN_OR_RETURN(
JsAstRepr ast,
ToJsAstRepr::FromJsSourceRepr(source_repr, parse_request, timeout,
recursion_depth_limit, babel));
- return ToJsHirRepr::FromJsAstRepr(ast, mlir_context);
+ return ToJsirRepr::FromJsAstRepr(ast, mlir_context);
}
// -----------------------------------------------------------------------------
// AST string -> AST -> HIR
// -----------------------------------------------------------------------------
-absl::StatusOr ToJsHirRepr::FromJsAstStringRepr(
- const JsAstStringRepr &ast_string_repr,
- std::optional recursion_depth_limit,
- mlir::MLIRContext &mlir_context) {
+absl::StatusOr ToJsirRepr::FromJsAstStringRepr(
+ const JsAstStringRepr& ast_string_repr,
+ std::optional recursion_depth_limit, mlir::MLIRContext& mlir_context) {
ABSL_ASSIGN_OR_RETURN(
JsAstRepr ast,
ToJsAstRepr::FromJsAstStringRepr(ast_string_repr, recursion_depth_limit));
- return ToJsHirRepr::FromJsAstRepr(ast, mlir_context);
+ return ToJsirRepr::FromJsAstRepr(ast, mlir_context);
}
// =============================================================================
@@ -129,11 +127,10 @@ absl::StatusOr ToJsHirRepr::FromJsAstStringRepr(
// HIR -> AST
// -----------------------------------------------------------------------------
-absl::StatusOr ToJsAstRepr::FromJsHirRepr(
- const JsHirRepr &hir_repr) {
+absl::StatusOr ToJsAstRepr::FromJsirRepr(const JsirRepr& ir_repr) {
ABSL_ASSIGN_OR_RETURN(std::unique_ptr ast,
- JshirFileToAst(hir_repr.op.get()));
- return JsAstRepr{std::move(ast), hir_repr.scopes, hir_repr.source_map};
+ JsirFileToAst(ir_repr.op.get()));
+ return JsAstRepr{std::move(ast), ir_repr.scopes, ir_repr.source_map};
}
// -----------------------------------------------------------------------------
@@ -166,9 +163,9 @@ absl::StatusOr ToJsSourceRepr::FromJsAstStringRepr(
// HIR -> AST -> AST string
// -----------------------------------------------------------------------------
-absl::StatusOr ToJsAstStringRepr::FromJsHirRepr(
- const JsHirRepr &hir_repr) {
- ABSL_ASSIGN_OR_RETURN(JsAstRepr ast, ToJsAstRepr::FromJsHirRepr(hir_repr));
+absl::StatusOr ToJsAstStringRepr::FromJsirRepr(
+ const JsirRepr& ir_repr) {
+ ABSL_ASSIGN_OR_RETURN(JsAstRepr ast, ToJsAstRepr::FromJsirRepr(ir_repr));
return ToJsAstStringRepr::FromJsAstRepr(ast);
}
@@ -176,11 +173,11 @@ absl::StatusOr ToJsAstStringRepr::FromJsHirRepr(
// HIR -> AST -> AST string -> Source
// -----------------------------------------------------------------------------
-absl::StatusOr ToJsSourceRepr::FromJsHirRepr(
- const JsHirRepr &hir_repr, BabelGenerateOptions generate_options,
- absl::Duration timeout, Babel &babel) {
+absl::StatusOr ToJsSourceRepr::FromJsirRepr(
+ const JsirRepr& ir_repr, BabelGenerateOptions generate_options,
+ absl::Duration timeout, Babel& babel) {
ABSL_ASSIGN_OR_RETURN(JsAstStringRepr ast_string,
- ToJsAstStringRepr::FromJsHirRepr(hir_repr));
+ ToJsAstStringRepr::FromJsirRepr(ir_repr));
return ToJsSourceRepr::FromJsAstStringRepr(ast_string,
generate_options, timeout, babel);
}
diff --git a/maldoca/js/driver/conversion.h b/maldoca/js/driver/conversion.h
index b1301212..6882d2e7 100644
--- a/maldoca/js/driver/conversion.h
+++ b/maldoca/js/driver/conversion.h
@@ -48,9 +48,9 @@ struct ToJsSourceRepr {
const JsAstRepr &ast_repr, BabelGenerateOptions generate_options,
absl::Duration timeout, Babel &babel);
- static absl::StatusOr FromJsHirRepr(
- const JsHirRepr &hir_repr, BabelGenerateOptions generate_options,
- absl::Duration timeout, Babel &babel);
+ static absl::StatusOr FromJsirRepr(
+ const JsirRepr& ir_repr, BabelGenerateOptions generate_options,
+ absl::Duration timeout, Babel& babel);
};
struct ToJsAstStringRepr {
@@ -61,8 +61,7 @@ struct ToJsAstStringRepr {
static absl::StatusOr FromJsAstRepr(
const JsAstRepr &ast_repr);
- static absl::StatusOr FromJsHirRepr(
- const JsHirRepr &hir_repr);
+ static absl::StatusOr FromJsirRepr(const JsirRepr& ir_repr);
};
struct ToJsAstRepr {
@@ -75,23 +74,22 @@ struct ToJsAstRepr {
const JsAstStringRepr &ast_string_repr,
std::optional recursion_depth_limit);
- static absl::StatusOr FromJsHirRepr(const JsHirRepr &hir_repr);
+ static absl::StatusOr FromJsirRepr(const JsirRepr& ir_repr);
};
-struct ToJsHirRepr {
- static absl::StatusOr FromJsSourceRepr(
- const JsSourceRepr &source_repr, BabelParseRequest parse_request,
+struct ToJsirRepr {
+ static absl::StatusOr FromJsSourceRepr(
+ const JsSourceRepr& source_repr, BabelParseRequest parse_request,
absl::Duration timeout, std::optional recursion_depth_limit,
- Babel &babel, mlir::MLIRContext &mlir_context);
+ Babel& babel, mlir::MLIRContext& mlir_context);
- static absl::StatusOr FromJsAstStringRepr(
- const JsAstStringRepr &ast_string_repr,
+ static absl::StatusOr FromJsAstStringRepr(
+ const JsAstStringRepr& ast_string_repr,
std::optional recursion_depth_limit,
- mlir::MLIRContext &mlir_context);
+ mlir::MLIRContext& mlir_context);
- static absl::StatusOr FromJsAstRepr(
- const JsAstRepr &ast_repr,
- mlir::MLIRContext &mlir_context);
+ static absl::StatusOr FromJsAstRepr(
+ const JsAstRepr& ast_repr, mlir::MLIRContext& mlir_context);
};
} // namespace maldoca
diff --git a/maldoca/js/driver/conversion_test.cc b/maldoca/js/driver/conversion_test.cc
index ff303a75..14426725 100644
--- a/maldoca/js/driver/conversion_test.cc
+++ b/maldoca/js/driver/conversion_test.cc
@@ -64,7 +64,7 @@ struct TestCase {
// Note: `hir_repr` is not constructed by parsing the golden file. Instead, it
// is constructed by converting the `ast` above. This is because the golden
// file does not contain loc information.
- JsHirRepr hir_repr;
+ JsirRepr hir_repr;
std::string hir_dump;
BabelAstString lifted_babel_ast_string;
@@ -120,8 +120,8 @@ absl::StatusOr GetTestCase() {
auto mlir_context = std::make_unique();
LoadNecessaryDialects(*mlir_context);
- ABSL_ASSIGN_OR_RETURN(JsHirRepr hir_repr,
- ToJsHirRepr::FromJsAstRepr(ast_repr, *mlir_context));
+ ABSL_ASSIGN_OR_RETURN(JsirRepr hir_repr,
+ ToJsirRepr::FromJsAstRepr(ast_repr, *mlir_context));
ABSL_ASSIGN_OR_RETURN(auto hir_str, load_content("test_hir.mlir.test"));
BabelAstString lifted_babel_ast_string;
@@ -184,14 +184,14 @@ TEST(ConversionTest, AstStringToAst) {
CheckAst(repr, test_case);
}
-TEST(ConversionTest, AstToHir) {
+TEST(ConversionTest, AstToJsir) {
MALDOCA_ASSERT_OK_AND_ASSIGN(TestCase test_case, GetTestCase());
mlir::MLIRContext mlir_context;
LoadNecessaryDialects(mlir_context);
MALDOCA_ASSERT_OK_AND_ASSIGN(
- JsHirRepr repr, ToJsHirRepr::FromJsAstRepr(test_case.ast, mlir_context));
+ JsirRepr repr, ToJsirRepr::FromJsAstRepr(test_case.ast, mlir_context));
EXPECT_EQ(mlir::debugString(*repr.op), test_case.hir_dump);
EXPECT_THAT(repr.scopes, EqualsProto(test_case.scopes));
@@ -215,7 +215,7 @@ TEST(ConversionTest, SourceToAst) {
CheckAst(repr, test_case);
}
-TEST(ConversionTest, SourceToHir) {
+TEST(ConversionTest, SourceToJsir) {
MALDOCA_ASSERT_OK_AND_ASSIGN(TestCase test_case, GetTestCase());
QuickJsBabel babel;
@@ -228,8 +228,8 @@ TEST(ConversionTest, SourceToHir) {
LoadNecessaryDialects(mlir_context);
MALDOCA_ASSERT_OK_AND_ASSIGN(
- JsHirRepr repr,
- ToJsHirRepr::FromJsSourceRepr(
+ JsirRepr repr,
+ ToJsirRepr::FromJsSourceRepr(
source_repr, parse_request, absl::InfiniteDuration(),
/*recursion_depth_limit=*/std::nullopt, babel, mlir_context));
@@ -237,7 +237,7 @@ TEST(ConversionTest, SourceToHir) {
EXPECT_THAT(repr.scopes, EqualsProto(test_case.scopes));
}
-TEST(ConversionTest, AstStringToHir) {
+TEST(ConversionTest, AstStringToJsir) {
MALDOCA_ASSERT_OK_AND_ASSIGN(TestCase test_case, GetTestCase());
JsAstStringRepr ast_string_repr{test_case.parsed_babel_ast_string,
@@ -247,10 +247,9 @@ TEST(ConversionTest, AstStringToHir) {
LoadNecessaryDialects(mlir_context);
MALDOCA_ASSERT_OK_AND_ASSIGN(
- JsHirRepr repr,
- ToJsHirRepr::FromJsAstStringRepr(ast_string_repr,
- /*recursion_depth_limit=*/std::nullopt,
- mlir_context));
+ JsirRepr repr, ToJsirRepr::FromJsAstStringRepr(
+ ast_string_repr,
+ /*recursion_depth_limit=*/std::nullopt, mlir_context));
EXPECT_EQ(mlir::debugString(*repr.op), test_case.hir_dump);
EXPECT_THAT(repr.scopes, EqualsProto(test_case.scopes));
@@ -260,11 +259,11 @@ TEST(ConversionTest, AstStringToHir) {
// Lifting conversions
// =============================================================================
-TEST(ConversionTest, HirToAst) {
+TEST(ConversionTest, JsirToAst) {
MALDOCA_ASSERT_OK_AND_ASSIGN(TestCase test_case, GetTestCase());
MALDOCA_ASSERT_OK_AND_ASSIGN(JsAstRepr repr,
- ToJsAstRepr::FromJsHirRepr(test_case.hir_repr));
+ ToJsAstRepr::FromJsirRepr(test_case.hir_repr));
CheckAst(repr, test_case);
}
@@ -298,25 +297,25 @@ TEST(ConversionTest, AstStringToSource) {
EXPECT_EQ(repr.source, test_case.source);
}
-TEST(ConversionTest, HirToAstString) {
+TEST(ConversionTest, JsirToAstString) {
MALDOCA_ASSERT_OK_AND_ASSIGN(TestCase test_case, GetTestCase());
MALDOCA_ASSERT_OK_AND_ASSIGN(
JsAstStringRepr repr,
- ToJsAstStringRepr::FromJsHirRepr(test_case.hir_repr));
+ ToJsAstStringRepr::FromJsirRepr(test_case.hir_repr));
EXPECT_THAT(repr.ast_string, EqualsProto(test_case.lifted_babel_ast_string));
}
-TEST(ConversionTest, HirToSource) {
+TEST(ConversionTest, JsirToSource) {
MALDOCA_ASSERT_OK_AND_ASSIGN(TestCase test_case, GetTestCase());
QuickJsBabel babel;
MALDOCA_ASSERT_OK_AND_ASSIGN(
JsSourceRepr repr,
- ToJsSourceRepr::FromJsHirRepr(test_case.hir_repr, BabelGenerateOptions(),
- absl::InfiniteDuration(), babel));
+ ToJsSourceRepr::FromJsirRepr(test_case.hir_repr, BabelGenerateOptions(),
+ absl::InfiniteDuration(), babel));
EXPECT_EQ(repr.source, test_case.source);
}
diff --git a/maldoca/js/driver/driver.cc b/maldoca/js/driver/driver.cc
index 42e92cf7..bb7b0709 100644
--- a/maldoca/js/driver/driver.cc
+++ b/maldoca/js/driver/driver.cc
@@ -51,8 +51,8 @@ std::ostream &operator<<(std::ostream &os, JsReprKind kind) {
return os << "AstString";
case JsReprKind::kAst:
return os << "Ast";
- case JsReprKind::kJshir:
- return os << "Jshir";
+ case JsReprKind::kJsir:
+ return os << "Jsir";
}
}
@@ -72,7 +72,7 @@ absl::StatusOr> JsRepr::FromProto(
case JsReprPb::kBabelAstString:
return std::make_unique(proto.babel_ast_string(),
std::move(source_map));
- case JsReprPb::kJsHir:
+ case JsReprPb::kJsIr:
return absl::UnimplementedError("JSIR parsing not supported");
}
}
@@ -95,9 +95,9 @@ absl::StatusOr JsAstStringRepr::ToProto() const {
return proto;
}
-absl::StatusOr JsHirRepr::ToProto() const {
+absl::StatusOr JsirRepr::ToProto() const {
JsReprPb proto;
- proto.set_js_hir(mlir::debugString(*op));
+ proto.set_js_ir(mlir::debugString(*op));
if (source_map.has_value()) {
proto.set_source_map(*source_map);
}
diff --git a/maldoca/js/driver/driver.h b/maldoca/js/driver/driver.h
index c405a1ce..7e2ec25a 100644
--- a/maldoca/js/driver/driver.h
+++ b/maldoca/js/driver/driver.h
@@ -59,7 +59,7 @@ enum class JsReprKind {
kJsSource,
kAstString,
kAst,
- kJshir,
+ kJsir,
};
std::ostream& operator<<(std::ostream& os, JsReprKind kind);
@@ -178,28 +178,17 @@ struct JsirRepr : JsRepr {
mlir::OwningOpRef op;
BabelScopes scopes;
- static bool classof(const JsRepr* repr) {
- return repr->kind == JsReprKind::kJshir;
- }
-
std::string Dump() const override { return mlir::debugString(*op); }
- protected:
- JsirRepr(JsReprKind kind, mlir::OwningOpRef op,
- BabelScopes scopes, std::optional source_map)
- : JsRepr(kind, std::move(source_map)),
+ public:
+ JsirRepr(mlir::OwningOpRef op, BabelScopes scopes,
+ std::optional source_map)
+ : JsRepr(JsReprKind::kJsir, std::move(source_map)),
op(std::move(op)),
scopes(std::move(scopes)) {}
-};
-
-struct JsHirRepr : JsirRepr {
- JsHirRepr(mlir::OwningOpRef op, BabelScopes scopes,
- std::optional source_map)
- : JsirRepr(JsReprKind::kJshir, std::move(op), std::move(scopes),
- std::move(source_map)) {}
static bool classof(const JsRepr* repr) {
- return repr->kind == JsReprKind::kJshir;
+ return repr->kind == JsReprKind::kJsir;
}
absl::StatusOr ToProto() const override;
diff --git a/maldoca/js/driver/driver.proto b/maldoca/js/driver/driver.proto
index 6e24ddda..e6bd2fc8 100644
--- a/maldoca/js/driver/driver.proto
+++ b/maldoca/js/driver/driver.proto
@@ -31,7 +31,7 @@ message JsReprPb {
oneof kind {
string js_source = 1;
BabelAstString babel_ast_string = 2;
- string js_hir = 3;
+ string js_ir = 3;
}
optional string source_map = 7;
@@ -52,8 +52,8 @@ message JsConversionConfig {
JsAstToAstStringConfig js_ast_to_ast_string = 4;
// ast <=> hir
- JsAstToHirConfig js_ast_to_hir = 5;
- JsHirToAstConfig js_hir_to_ast = 6;
+ JsAstToJsirConfig js_ast_to_jsir = 5;
+ JsirToAstConfig jsir_to_ast = 6;
}
}
@@ -73,9 +73,9 @@ message JsAstStringToAstConfig {
message JsAstToAstStringConfig {}
-message JsAstToHirConfig {}
+message JsAstToJsirConfig {}
-message JsHirToAstConfig {}
+message JsirToAstConfig {}
// =============================================================================
// Analysis
diff --git a/maldoca/js/driver/internal/conversions.cc b/maldoca/js/driver/internal/conversions.cc
index e40b0ddf..c6ff1103 100644
--- a/maldoca/js/driver/internal/conversions.cc
+++ b/maldoca/js/driver/internal/conversions.cc
@@ -72,13 +72,13 @@ absl::StatusOr> JsConversion::Create(
return std::make_unique();
}
- case JsConversionConfig::KindCase::kJsAstToHir: {
+ case JsConversionConfig::KindCase::kJsAstToJsir: {
MALDOCA_RET_CHECK(mlir_context != nullptr);
- return std::make_unique(mlir_context);
+ return std::make_unique(mlir_context);
}
- case JsConversionConfig::KindCase::kJsHirToAst: {
- return std::make_unique();
+ case JsConversionConfig::KindCase::kJsirToAst: {
+ return std::make_unique();
}
}
}
@@ -168,20 +168,20 @@ absl::StatusOr> JsAstToAstString::Convert(
// JsAstToHir
// =============================================================================
-absl::StatusOr> JsAstToHir::Convert(
- const JsAstRepr &from) {
- ABSL_ASSIGN_OR_RETURN(auto op, AstToJshirFile(*from.ast, mlir_context_));
- return std::make_unique(std::move(op), from.scopes,
- from.source_map);
+absl::StatusOr> JsAstToJsir::Convert(
+ const JsAstRepr& from) {
+ ABSL_ASSIGN_OR_RETURN(auto op, AstToJsirFile(*from.ast, mlir_context_));
+ return std::make_unique(std::move(op), from.scopes,
+ from.source_map);
}
// =============================================================================
// JsHirToAst
// =============================================================================
-absl::StatusOr> JsHirToAst::Convert(
- const JsHirRepr &from) {
- ABSL_ASSIGN_OR_RETURN(auto ast, JshirFileToAst(*from.op));
+absl::StatusOr> JsirToAst::Convert(
+ const JsirRepr& from) {
+ ABSL_ASSIGN_OR_RETURN(auto ast, JsirFileToAst(*from.op));
return std::make_unique(std::move(ast), from.scopes,
from.source_map);
}
diff --git a/maldoca/js/driver/internal/conversions.h b/maldoca/js/driver/internal/conversions.h
index bfb04203..e0bf77fb 100644
--- a/maldoca/js/driver/internal/conversions.h
+++ b/maldoca/js/driver/internal/conversions.h
@@ -176,16 +176,16 @@ class JsAstToAstString final
// +------+-----------------------------+-------------------------------+
// | To | mlir::OwningOpRef | JavaScript high-level IR |
// +------+-----------------------------+-------------------------------+
-class JsAstToHir final : public JsConversionTmpl {
+class JsAstToJsir final : public JsConversionTmpl {
public:
- explicit JsAstToHir(mlir::MLIRContext *absl_nonnull mlir_context)
+ explicit JsAstToJsir(mlir::MLIRContext* absl_nonnull mlir_context)
: mlir_context_(*mlir_context) {}
- std::string name() const override { return "JsAstToHir"; }
+ std::string name() const override { return "JsAstToJsir"; }
private:
- absl::StatusOr> Convert(
- const JsAstRepr &from) override;
+ absl::StatusOr> Convert(
+ const JsAstRepr& from) override;
mlir::MLIRContext &mlir_context_;
};
@@ -197,15 +197,15 @@ class JsAstToHir final : public JsConversionTmpl {
// +------+-------------------------------+-------------------------------+
// | To | std::unique_ptr | JavaScript AST |
// +------+-------------------------------+-------------------------------+
-class JsHirToAst final : public JsConversionTmpl {
+class JsirToAst final : public JsConversionTmpl {
public:
- explicit JsHirToAst() = default;
+ explicit JsirToAst() = default;
- std::string name() const override { return "JsHirToAst"; }
+ std::string name() const override { return "JsirToAst"; }
private:
absl::StatusOr> Convert(
- const JsHirRepr &from) override;
+ const JsirRepr& from) override;
};
} // namespace maldoca
diff --git a/maldoca/js/ir/BUILD b/maldoca/js/ir/BUILD
index 7bb11954..55a64391 100644
--- a/maldoca/js/ir/BUILD
+++ b/maldoca/js/ir/BUILD
@@ -86,20 +86,6 @@ gentbl_cc_library(
],
"jsir_dialect.cc.inc",
),
- (
- [
- "-gen-dialect-decls",
- "-dialect=jshir",
- ],
- "jshir_dialect.h.inc",
- ),
- (
- [
- "-gen-dialect-defs",
- "-dialect=jshir",
- ],
- "jshir_dialect.cc.inc",
- ),
],
tblgen = "@llvm-project//mlir:mlir-tblgen",
td_file = "jsir_attrs.td",
@@ -207,31 +193,15 @@ gentbl_cc_library(
(
[
"-gen-op-decls",
- "-op-include-regex=jsir",
],
"jsir_ops.h.inc",
),
(
[
"-gen-op-defs",
- "-op-include-regex=jsir",
],
"jsir_ops.cc.inc",
),
- (
- [
- "-gen-op-decls",
- "-op-include-regex=jshir",
- ],
- "jshir_ops.h.inc",
- ),
- (
- [
- "-gen-op-defs",
- "-op-include-regex=jshir",
- ],
- "jshir_ops.cc.inc",
- ),
],
tblgen = "@llvm-project//mlir:mlir-tblgen",
td_file = "jsir_ops.td",
@@ -244,7 +214,6 @@ cc_library(
name = "ir",
srcs = [
"ir.cc",
- "jshir_ops.cc",
"jsir_ops.cc",
],
hdrs = ["ir.h"],
diff --git a/maldoca/js/ir/analyses/conditional_forward_dataflow_analysis.h b/maldoca/js/ir/analyses/conditional_forward_dataflow_analysis.h
index 78eeda80..ef5ed9e9 100644
--- a/maldoca/js/ir/analyses/conditional_forward_dataflow_analysis.h
+++ b/maldoca/js/ir/analyses/conditional_forward_dataflow_analysis.h
@@ -114,18 +114,17 @@ void JsirConditionalForwardDataFlowAnalysis::VisitOp(
// Don't call the user-defined `VisitOp` if this is an op with a fixed
// standard visitor.
// TODO(b/425421947): Create MLIR trait rather than having a list of ops here.
- if (llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) || llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op) ||
- llvm::isa(op)) {
+ if (llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) ||
+ llvm::isa(op) || llvm::isa(op) ||
+ llvm::isa(op) || llvm::isa(op) ||
+ llvm::isa(op)) {
return;
}
VisitOp(op, operands, before, result_state_refs, after_state_ref);
diff --git a/maldoca/js/ir/analyses/conditional_forward_per_var_dataflow_analysis.h b/maldoca/js/ir/analyses/conditional_forward_per_var_dataflow_analysis.h
index 957b23cb..d4f1d9ae 100644
--- a/maldoca/js/ir/analyses/conditional_forward_per_var_dataflow_analysis.h
+++ b/maldoca/js/ir/analyses/conditional_forward_per_var_dataflow_analysis.h
@@ -67,7 +67,7 @@ class JsirConditionalForwardPerVarDataFlowAnalysis
//
// ```
//
- // jshir.if_statement (%cond) {
+ // jsir.if_statement (%cond) {
//
// }, {
//
diff --git a/maldoca/js/ir/analyses/constant_propagation/tests/and/README.generated.md b/maldoca/js/ir/analyses/constant_propagation/tests/and/README.generated.md
index 58220b3f..397963c7 100644
--- a/maldoca/js/ir/analyses/constant_propagation/tests/and/README.generated.md
+++ b/maldoca/js/ir/analyses/constant_propagation/tests/and/README.generated.md
@@ -3,6 +3,6 @@ To run manually:
```shell
bazel run //maldoca/js/ir:jsir_gen -- \
--input_file $(pwd)/maldoca/js/ir/analyses/constant_propagation/tests/and/input.js \
- --passes "source2ast,ast2hir" \
+ --passes "source2ast,ast2jsir" \
--jsir_analysis constant_propagation
```
diff --git a/maldoca/js/ir/analyses/constant_propagation/tests/and/output.generated.txt b/maldoca/js/ir/analyses/constant_propagation/tests/and/output.generated.txt
index 8dda7939..7ee8093b 100644
--- a/maldoca/js/ir/analyses/constant_propagation/tests/and/output.generated.txt
+++ b/maldoca/js/ir/analyses/constant_propagation/tests/and/output.generated.txt
@@ -1,254 +1,254 @@
-// JSHIR: "jsir.file"() <{comments = []}> ({
-// JSHIR-NEXT: "jsir.program"() <{source_type = "script"}> ({
-// JSHIR-NEXT: "jsir.variable_declaration"() <{kind = "var"}> ({
-// JSHIR-NEXT: %16 = "jsir.identifier_ref"() <{name = "a"}> : () -> !jsir.any
-// JSHIR-NEXT: %17 = "jsir.boolean_literal"() <{value = false}> : () -> !jsir.any
-// JSHIR-NEXT: %18 = "jshir.logical_expression"(%17) <{operator_ = "&&"}> ({
-// JSHIR-NEXT: %20 = "jsir.boolean_literal"() <{value = true}> : () -> !jsir.any
-// JSHIR-NEXT: "jsir.expr_region_end"(%20) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %19 = "jsir.variable_declarator"(%16, %18) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.exprs_region_end"(%19) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : () -> ()
-// JSHIR-NEXT: "jsir.variable_declaration"() <{kind = "var"}> ({
-// JSHIR-NEXT: %16 = "jsir.identifier_ref"() <{name = "b"}> : () -> !jsir.any
-// JSHIR-NEXT: %17 = "jsir.boolean_literal"() <{value = true}> : () -> !jsir.any
-// JSHIR-NEXT: %18 = "jshir.logical_expression"(%17) <{operator_ = "&&"}> ({
-// JSHIR-NEXT: %20 = "jsir.boolean_literal"() <{value = false}> : () -> !jsir.any
-// JSHIR-NEXT: "jsir.expr_region_end"(%20) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %19 = "jsir.variable_declarator"(%16, %18) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.exprs_region_end"(%19) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : () -> ()
-// JSHIR-NEXT: "jsir.variable_declaration"() <{kind = "var"}> ({
-// JSHIR-NEXT: %16 = "jsir.identifier_ref"() <{name = "c"}> : () -> !jsir.any
-// JSHIR-NEXT: %17 = "jsir.identifier"() <{name = "x"}> : () -> !jsir.any
-// JSHIR-NEXT: %18 = "jshir.logical_expression"(%17) <{operator_ = "&&"}> ({
-// JSHIR-NEXT: %20 = "jsir.boolean_literal"() <{value = true}> : () -> !jsir.any
-// JSHIR-NEXT: "jsir.expr_region_end"(%20) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %19 = "jsir.variable_declarator"(%16, %18) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.exprs_region_end"(%19) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : () -> ()
-// JSHIR-NEXT: "jsir.variable_declaration"() <{kind = "var"}> ({
-// JSHIR-NEXT: %16 = "jsir.identifier_ref"() <{name = "d"}> : () -> !jsir.any
-// JSHIR-NEXT: %17 = "jsir.identifier"() <{name = "x"}> : () -> !jsir.any
-// JSHIR-NEXT: %18 = "jshir.logical_expression"(%17) <{operator_ = "&&"}> ({
-// JSHIR-NEXT: %20 = "jsir.boolean_literal"() <{value = false}> : () -> !jsir.any
-// JSHIR-NEXT: "jsir.expr_region_end"(%20) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %19 = "jsir.variable_declarator"(%16, %18) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.exprs_region_end"(%19) : (!jsir.any) -> ()
-// JSHIR-NEXT: }) : () -> ()
-// JSHIR-NEXT: %0 = "jsir.identifier"() <{name = "console"}> : () -> !jsir.any
-// JSHIR-NEXT: %1 = "jsir.member_expression"(%0) <{literal_property = #jsir, , "log", 93, 96, 0, "log">}> : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %2 = "jsir.identifier"() <{name = "a"}> : () -> !jsir.any
-// JSHIR-NEXT: %3 = "jsir.call_expression"(%1, %2) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.expression_statement"(%3) : (!jsir.any) -> ()
-// JSHIR-NEXT: %4 = "jsir.identifier"() <{name = "console"}> : () -> !jsir.any
-// JSHIR-NEXT: %5 = "jsir.member_expression"(%4) <{literal_property = #jsir, , "log", 109, 112, 0, "log">}> : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %6 = "jsir.identifier"() <{name = "b"}> : () -> !jsir.any
-// JSHIR-NEXT: %7 = "jsir.call_expression"(%5, %6) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.expression_statement"(%7) : (!jsir.any) -> ()
-// JSHIR-NEXT: %8 = "jsir.identifier"() <{name = "console"}> : () -> !jsir.any
-// JSHIR-NEXT: %9 = "jsir.member_expression"(%8) <{literal_property = #jsir, , "log", 125, 128, 0, "log">}> : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %10 = "jsir.identifier"() <{name = "c"}> : () -> !jsir.any
-// JSHIR-NEXT: %11 = "jsir.call_expression"(%9, %10) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.expression_statement"(%11) : (!jsir.any) -> ()
-// JSHIR-NEXT: %12 = "jsir.identifier"() <{name = "console"}> : () -> !jsir.any
-// JSHIR-NEXT: %13 = "jsir.member_expression"(%12) <{literal_property = #jsir, , "log", 141, 144, 0, "log">}> : (!jsir.any) -> !jsir.any
-// JSHIR-NEXT: %14 = "jsir.identifier"() <{name = "d"}> : () -> !jsir.any
-// JSHIR-NEXT: %15 = "jsir.call_expression"(%13, %14) : (!jsir.any, !jsir.any) -> !jsir.any
-// JSHIR-NEXT: "jsir.expression_statement"(%15) : (!jsir.any) -> ()
-// JSHIR-NEXT: }, {
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: }) : () -> ()
-// JSHIR-NEXT: }) : () -> ()
-// JSHIR-NEXT: jsir.file {[]} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.program {"script"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.variable_declaration {"var"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %16 = jsir.identifier_ref {"a"}
-// JSHIR-NEXT: // %16 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %17 = jsir.boolean_literal {false}
-// JSHIR-NEXT: // %17 = false
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %18 = jshir.logical_expression (%17) {"&&"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %20 = jsir.boolean_literal {true}
-// JSHIR-NEXT: // %20 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.expr_region_end (%20)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // %18 = false
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %19 = jsir.variable_declarator (%16, %18)
-// JSHIR-NEXT: // %19 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.exprs_region_end (%19)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.variable_declaration {"var"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %16 = jsir.identifier_ref {"b"}
-// JSHIR-NEXT: // %16 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %17 = jsir.boolean_literal {true}
-// JSHIR-NEXT: // %17 = true
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %18 = jshir.logical_expression (%17) {"&&"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %20 = jsir.boolean_literal {false}
-// JSHIR-NEXT: // %20 = false
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.expr_region_end (%20)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // %18 = false
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %19 = jsir.variable_declarator (%16, %18)
-// JSHIR-NEXT: // %19 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.exprs_region_end (%19)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.variable_declaration {"var"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %16 = jsir.identifier_ref {"c"}
-// JSHIR-NEXT: // %16 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %17 = jsir.identifier {"x"}
-// JSHIR-NEXT: // %17 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %18 = jshir.logical_expression (%17) {"&&"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %20 = jsir.boolean_literal {true}
-// JSHIR-NEXT: // %20 = true
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.expr_region_end (%20)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // %18 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %19 = jsir.variable_declarator (%16, %18)
-// JSHIR-NEXT: // %19 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.exprs_region_end (%19)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.variable_declaration {"var"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %16 = jsir.identifier_ref {"d"}
-// JSHIR-NEXT: // %16 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %17 = jsir.identifier {"x"}
-// JSHIR-NEXT: // %17 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %18 = jshir.logical_expression (%17) {"&&"} ({
-// JSHIR-NEXT: ^bb0:
-// JSHIR-NEXT: //
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %20 = jsir.boolean_literal {false}
-// JSHIR-NEXT: // %20 = false
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.expr_region_end (%20)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // %18 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %19 = jsir.variable_declarator (%16, %18)
-// JSHIR-NEXT: // %19 =
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: jsir.exprs_region_end (%19)
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: })
-// JSHIR-NEXT: // State [default = ] { }
-// JSHIR-NEXT: %0 = jsir.identifier {"console"}
-// JSHIR-NEXT: // %0 =
-// JSHIR-NEXT: // State [default = ] {