-
Notifications
You must be signed in to change notification settings - Fork 630
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate Hermes AST visitor keys from AST definitions
Summary: We will need to traverse the Hermes AST in order to convert it to a proper ESTree or Babel AST. Let's autogenerate the information needed to traverse the Hermes AST directly from the Hermes AST definitions similar to how this is done for the JS builder methods. We can use the C preprocessor to generate a map of the visitor keys in JS, mapping from the node's type to an object containing all of its node and node list children (string, boolean, and numeric fields are ignored). This allows us efficiently traverse the AST by looking up the visitor keys for each node when it is visited, and subsequently visiting the node child or all of the node list children. Added autogeneration of these visitor keys to the `build.sh` script, being sure to format and then sign the generated file. Also included a simple implementation of traversing the AST using these visitor keys in `HermesASTVisitor`. This is not yet used, but will be a foundation for the handful of conversions we need to do to modify the AST to be Babel or ESTree compliant. Reviewed By: avp Differential Revision: D23768640 fbshipit-source-id: 6ec34b7505075d3b3298c13f27f385c97e766d15
- Loading branch information
1 parent
d954c8f
commit fe0e3dd
Showing
4 changed files
with
327 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @format | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const SignedSource = require('signedsource'); | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const {execSync} = require('child_process'); | ||
|
||
const OUTPUT_FILE = path.resolve(__dirname, '../build/HermesASTVisitorKeys.js'); | ||
const TEMPLATE_FILE = path.resolve( | ||
__dirname, | ||
'templates/HermesASTVisitorKeys.template', | ||
); | ||
|
||
// Create visitor keys file | ||
const visitorKeys = execSync( | ||
`cpp -P -I "${process.argv[2]}" "${TEMPLATE_FILE}"`, | ||
); | ||
const visitorKeysFileContents = `/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* This file was generated by tools/hermes-parser/js/scripts/build.sh | ||
* | ||
* ${SignedSource.getSigningToken()} | ||
* | ||
* @format | ||
*/ | ||
'use strict'; | ||
const HERMES_AST_VISITOR_KEYS = {}; | ||
const NODE_CHILD = 'Node'; | ||
const NODE_LIST_CHILD = 'NodeList'; | ||
${visitorKeys} | ||
module.exports = { | ||
HERMES_AST_VISITOR_KEYS, | ||
NODE_CHILD, | ||
NODE_LIST_CHILD, | ||
}; | ||
`; | ||
|
||
// Format then sign file and write to disk | ||
const formattedContents = execSync('prettier', { | ||
input: visitorKeysFileContents, | ||
}).toString(); | ||
fs.writeFileSync(OUTPUT_FILE, SignedSource.signFile(formattedContents)); |
216 changes: 216 additions & 0 deletions
216
tools/hermes-parser/js/scripts/templates/HermesASTVisitorKeys.template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
// String, boolean, and number children are leaf nodes in AST and do not need to be visited | ||
#define NodeLabel(ARG) | ||
#define NodeBoolean(ARG) | ||
#define NodeNumber(ARG) | ||
|
||
// Mark node child as single child node that can be visited | ||
#define NodePtr(ARG) ARG: NODE_CHILD, | ||
|
||
// Mark node list children as multiple child nodes that can be visited | ||
#define NodeList(ARG) ARG: NODE_LIST_CHILD, | ||
|
||
#define ESTREE_NODE_0_ARGS( \ | ||
NAME, \ | ||
BASE) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = {}; | ||
|
||
#define ESTREE_NODE_1_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_2_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_3_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT, \ | ||
ARG2TY, \ | ||
ARG2NM, \ | ||
ARG2PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
ARG2TY(ARG2NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_4_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT, \ | ||
ARG2TY, \ | ||
ARG2NM, \ | ||
ARG2PT, \ | ||
ARG3TY, \ | ||
ARG3NM, \ | ||
ARG3PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
ARG2TY(ARG2NM) \ | ||
ARG3TY(ARG3NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_5_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT, \ | ||
ARG2TY, \ | ||
ARG2NM, \ | ||
ARG2PT, \ | ||
ARG3TY, \ | ||
ARG3NM, \ | ||
ARG3PT, \ | ||
ARG4TY, \ | ||
ARG4NM, \ | ||
ARG4PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
ARG2TY(ARG2NM) \ | ||
ARG3TY(ARG3NM) \ | ||
ARG4TY(ARG4NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_6_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT, \ | ||
ARG2TY, \ | ||
ARG2NM, \ | ||
ARG2PT, \ | ||
ARG3TY, \ | ||
ARG3NM, \ | ||
ARG3PT, \ | ||
ARG4TY, \ | ||
ARG4NM, \ | ||
ARG4PT, \ | ||
ARG5TY, \ | ||
ARG5NM, \ | ||
ARG5PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
ARG2TY(ARG2NM) \ | ||
ARG3TY(ARG3NM) \ | ||
ARG4TY(ARG4NM) \ | ||
ARG5TY(ARG5NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_7_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT, \ | ||
ARG2TY, \ | ||
ARG2NM, \ | ||
ARG2PT, \ | ||
ARG3TY, \ | ||
ARG3NM, \ | ||
ARG3PT, \ | ||
ARG4TY, \ | ||
ARG4NM, \ | ||
ARG4PT, \ | ||
ARG5TY, \ | ||
ARG5NM, \ | ||
ARG5PT, \ | ||
ARG6TY, \ | ||
ARG6NM, \ | ||
ARG6PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
ARG2TY(ARG2NM) \ | ||
ARG3TY(ARG3NM) \ | ||
ARG4TY(ARG4NM) \ | ||
ARG5TY(ARG5NM) \ | ||
ARG6TY(ARG6NM) \ | ||
}; | ||
|
||
#define ESTREE_NODE_8_ARGS( \ | ||
NAME, \ | ||
BASE, \ | ||
ARG0TY, \ | ||
ARG0NM, \ | ||
ARG0OPT, \ | ||
ARG1TY, \ | ||
ARG1NM, \ | ||
ARG1PT, \ | ||
ARG2TY, \ | ||
ARG2NM, \ | ||
ARG2PT, \ | ||
ARG3TY, \ | ||
ARG3NM, \ | ||
ARG3PT, \ | ||
ARG4TY, \ | ||
ARG4NM, \ | ||
ARG4PT, \ | ||
ARG5TY, \ | ||
ARG5NM, \ | ||
ARG5PT, \ | ||
ARG6TY, \ | ||
ARG6NM, \ | ||
ARG6PT, \ | ||
ARG7TY, \ | ||
ARG7NM, \ | ||
ARG7PT) \ | ||
HERMES_AST_VISITOR_KEYS[#NAME] = { \ | ||
ARG0TY(ARG0NM) \ | ||
ARG1TY(ARG1NM) \ | ||
ARG2TY(ARG2NM) \ | ||
ARG3TY(ARG3NM) \ | ||
ARG4TY(ARG4NM) \ | ||
ARG5TY(ARG5NM) \ | ||
ARG6TY(ARG6NM) \ | ||
ARG7TY(ARG7NM) \ | ||
}; | ||
|
||
#include "hermes/AST/ESTree.def" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @format | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const { | ||
HERMES_AST_VISITOR_KEYS, | ||
NODE_CHILD, | ||
NODE_LIST_CHILD, | ||
} = require('./HermesASTVisitorKeys'); | ||
|
||
function visitNode(node) { | ||
if (node == null) { | ||
return; | ||
} | ||
|
||
const visitorKeys = HERMES_AST_VISITOR_KEYS[node.type]; | ||
for (const key in visitorKeys) { | ||
const childType = visitorKeys[key]; | ||
if (childType === NODE_CHILD) { | ||
const child = node[key]; | ||
if (child != null) { | ||
visitNode(node[key]); | ||
} | ||
} else if (childType === NODE_LIST_CHILD) { | ||
for (const child of node[key]) { | ||
if (child != null) { | ||
visitNode(child); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
module.exports = visitNode; |