[rust][wip] Codegen conversion from HermesParser (C++)

This commit is contained in:
Joe Savona
2023-08-01 13:55:13 -07:00
parent ce2725eda5
commit e353f3702e
15 changed files with 4311 additions and 187 deletions
+1
View File
@@ -528,6 +528,7 @@ version = "0.1.0"
dependencies = [
"forget_diagnostics",
"forget_estree",
"forget_estree_codegen",
"hermes",
"juno_support",
]
@@ -65,4 +65,8 @@ impl<'ast> Visitor<'ast> for ContextVisitor<'ast> {
_ => {}
}
}
fn visit_literal(&mut self, _literal: &'ast forget_estree::Literal) {
// no-op
}
}
@@ -3,7 +3,7 @@
use std::num::NonZeroU32;
use serde::ser::{Serializer, SerializeMap};
use serde::{Serialize, Deserialize};
use crate::{JsValue, Binding, SourceRange};
use crate::{JsValue, Binding, SourceRange, Number};
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct SourceLocation {
@@ -19,6 +19,14 @@ pub struct Position {
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Class {
pub id: Option<Identifier>,
#[serde(rename = "superClass")]
pub super_class: Option<Expression>,
pub body: ClassBody,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Function {
pub id: Option<Identifier>,
pub params: Vec<Pattern>,
@@ -101,6 +109,88 @@ impl Serialize for Literal {
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct NumericLiteral {
pub value: Number,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for NumericLiteral {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "NumericLiteral")?;
state.serialize_entry("value", &self.value)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct BooleanLiteral {
pub value: bool,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for BooleanLiteral {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "BooleanLiteral")?;
state.serialize_entry("value", &self.value)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct NullLiteral {
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for NullLiteral {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "NullLiteral")?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct StringLiteral {
pub value: String,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for StringLiteral {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "StringLiteral")?;
state.serialize_entry("value", &self.value)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct Program {
pub body: Vec<ModuleItem>,
#[serde(rename = "sourceType")]
@@ -610,32 +700,6 @@ impl Serialize for FunctionDeclaration {
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct Class {
pub id: Option<Identifier>,
#[serde(rename = "superClass")]
pub super_class: Option<Expression>,
pub body: ClassBody,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
pub range: Option<SourceRange>,
}
impl Serialize for Class {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(None)?;
state.serialize_entry("type", "Class")?;
state.serialize_entry("id", &self.id)?;
state.serialize_entry("superClass", &self.super_class)?;
state.serialize_entry("body", &self.body)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
}
}
#[derive(Deserialize, Clone, Debug)]
pub struct ClassDeclaration {
#[serde(flatten)]
pub class: Class,
@@ -1062,9 +1126,6 @@ pub struct MemberExpression {
pub property: Expression,
#[serde(rename = "computed")]
pub is_computed: bool,
#[serde(rename = "optional")]
#[serde(default)]
pub is_optional: bool,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
@@ -1080,7 +1141,6 @@ impl Serialize for MemberExpression {
state.serialize_entry("object", &self.object)?;
state.serialize_entry("property", &self.property)?;
state.serialize_entry("computed", &self.is_computed)?;
state.serialize_entry("optional", &self.is_optional)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
@@ -1115,9 +1175,6 @@ impl Serialize for ConditionalExpression {
pub struct CallExpression {
pub callee: ExpressionOrSuper,
pub arguments: Vec<ExpressionOrSpread>,
#[serde(rename = "optional")]
#[serde(default)]
pub is_optional: bool,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
@@ -1132,7 +1189,6 @@ impl Serialize for CallExpression {
state.serialize_entry("type", "CallExpression")?;
state.serialize_entry("callee", &self.callee)?;
state.serialize_entry("arguments", &self.arguments)?;
state.serialize_entry("optional", &self.is_optional)?;
state.serialize_entry("loc", &self.loc)?;
state.serialize_entry("range", &self.range)?;
state.end()
@@ -1250,7 +1306,7 @@ impl Serialize for YieldExpression {
#[derive(Deserialize, Clone, Debug)]
pub struct ImportDeclaration {
pub specifiers: Vec<ImportDeclarationSpecifier>,
pub source: Literal,
pub source: _Literal,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
@@ -1339,7 +1395,7 @@ impl Serialize for ImportNamespaceSpecifier {
pub struct ExportNamedDeclaration {
pub declaration: Option<Declaration>,
pub specifiers: Vec<ExportSpecifier>,
pub source: Option<Literal>,
pub source: Option<_Literal>,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
@@ -1404,7 +1460,7 @@ impl Serialize for ExportDefaultDeclaration {
}
#[derive(Deserialize, Clone, Debug)]
pub struct ExportAllDeclaration {
pub source: Literal,
pub source: _Literal,
#[serde(default)]
pub exported: Option<Identifier>,
#[serde(default)]
@@ -1704,7 +1760,7 @@ pub struct JSXFragment {
pub opening_fragment: JSXOpeningFragment,
pub children: Vec<JSXChildItem>,
#[serde(rename = "closingFragment")]
pub closing_fragment: Option<JSXClosingFragment>,
pub closing_fragment: JSXClosingFragment,
#[serde(default)]
pub loc: Option<SourceLocation>,
#[serde(default)]
@@ -2013,7 +2069,7 @@ impl Serialize for ChainExpression {
#[derive(Deserialize, Clone, Debug)]
pub struct OptionalMemberExpression {
pub object: Expression,
pub property: Identifier,
pub property: Expression,
#[serde(rename = "computed")]
pub is_computed: bool,
#[serde(rename = "optional")]
@@ -2328,6 +2384,7 @@ pub enum Expression {
AssignmentExpression(Box<AssignmentExpression>),
AwaitExpression(Box<AwaitExpression>),
BinaryExpression(Box<BinaryExpression>),
BooleanLiteral(Box<BooleanLiteral>),
CallExpression(Box<CallExpression>),
ChainExpression(Box<ChainExpression>),
ClassExpression(Box<ClassExpression>),
@@ -2341,10 +2398,13 @@ pub enum Expression {
MemberExpression(Box<MemberExpression>),
MetaProperty(Box<MetaProperty>),
NewExpression(Box<NewExpression>),
NullLiteral(Box<NullLiteral>),
NumericLiteral(Box<NumericLiteral>),
ObjectExpression(Box<ObjectExpression>),
OptionalCallExpression(Box<OptionalCallExpression>),
OptionalMemberExpression(Box<OptionalMemberExpression>),
SequenceExpression(Box<SequenceExpression>),
StringLiteral(Box<StringLiteral>),
TaggedTemplateExpression(Box<TaggedTemplateExpression>),
TemplateLiteral(Box<TemplateLiteral>),
ThisExpression(Box<ThisExpression>),
@@ -2359,6 +2419,7 @@ enum __ExpressionTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -2372,10 +2433,13 @@ enum __ExpressionTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -2435,6 +2499,14 @@ impl<'de> serde::Deserialize<'de> for Expression {
)?;
Ok(Expression::BinaryExpression(node))
}
__ExpressionTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(Expression::BooleanLiteral(node))
}
__ExpressionTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -2539,6 +2611,22 @@ impl<'de> serde::Deserialize<'de> for Expression {
)?;
Ok(Expression::NewExpression(node))
}
__ExpressionTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(Expression::NullLiteral(node))
}
__ExpressionTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(Expression::NumericLiteral(node))
}
__ExpressionTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -2571,6 +2659,14 @@ impl<'de> serde::Deserialize<'de> for Expression {
)?;
Ok(Expression::SequenceExpression(node))
}
__ExpressionTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(Expression::StringLiteral(node))
}
__ExpressionTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -2624,6 +2720,78 @@ impl<'de> serde::Deserialize<'de> for Expression {
}
#[derive(Serialize, Clone, Debug)]
#[serde(untagged)]
pub enum _Literal {
BooleanLiteral(Box<BooleanLiteral>),
Literal(Box<Literal>),
NullLiteral(Box<NullLiteral>),
NumericLiteral(Box<NumericLiteral>),
StringLiteral(Box<StringLiteral>),
}
#[derive(Deserialize, Debug)]
enum ___LiteralTag {
Literal,
BooleanLiteral,
NullLiteral,
StringLiteral,
NumericLiteral,
}
impl<'de> serde::Deserialize<'de> for _Literal {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let tagged = serde::Deserializer::deserialize_any(
deserializer,
serde::__private::de::TaggedContentVisitor::<
___LiteralTag,
>::new("type", "_Literal"),
)?;
match tagged.0 {
___LiteralTag::Literal => {
let node: Box<Literal> = <Box<
Literal,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(_Literal::Literal(node))
}
___LiteralTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(_Literal::BooleanLiteral(node))
}
___LiteralTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(_Literal::NullLiteral(node))
}
___LiteralTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(_Literal::StringLiteral(node))
}
___LiteralTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(_Literal::NumericLiteral(node))
}
}
}
}
#[derive(Serialize, Clone, Debug)]
#[serde(untagged)]
pub enum Declaration {
ClassDeclaration(Box<ClassDeclaration>),
FunctionDeclaration(Box<FunctionDeclaration>),
@@ -3066,6 +3234,7 @@ enum __ExpressionOrSuperTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -3079,10 +3248,13 @@ enum __ExpressionOrSuperTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -3147,6 +3319,14 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSuper {
)?;
Ok(ExpressionOrSuper::Expression(Expression::BinaryExpression(node)))
}
__ExpressionOrSuperTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSuper::Expression(Expression::BooleanLiteral(node)))
}
__ExpressionOrSuperTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -3255,6 +3435,22 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSuper {
)?;
Ok(ExpressionOrSuper::Expression(Expression::NewExpression(node)))
}
__ExpressionOrSuperTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSuper::Expression(Expression::NullLiteral(node)))
}
__ExpressionOrSuperTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSuper::Expression(Expression::NumericLiteral(node)))
}
__ExpressionOrSuperTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -3295,6 +3491,14 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSuper {
)?;
Ok(ExpressionOrSuper::Expression(Expression::SequenceExpression(node)))
}
__ExpressionOrSuperTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSuper::Expression(Expression::StringLiteral(node)))
}
__ExpressionOrSuperTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -3371,6 +3575,7 @@ enum __ExpressionOrSpreadTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -3384,10 +3589,13 @@ enum __ExpressionOrSpreadTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -3456,6 +3664,14 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSpread {
)?;
Ok(ExpressionOrSpread::Expression(Expression::BinaryExpression(node)))
}
__ExpressionOrSpreadTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSpread::Expression(Expression::BooleanLiteral(node)))
}
__ExpressionOrSpreadTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -3564,6 +3780,22 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSpread {
)?;
Ok(ExpressionOrSpread::Expression(Expression::NewExpression(node)))
}
__ExpressionOrSpreadTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSpread::Expression(Expression::NullLiteral(node)))
}
__ExpressionOrSpreadTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSpread::Expression(Expression::NumericLiteral(node)))
}
__ExpressionOrSpreadTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -3604,6 +3836,14 @@ impl<'de> serde::Deserialize<'de> for ExpressionOrSpread {
)?;
Ok(ExpressionOrSpread::Expression(Expression::SequenceExpression(node)))
}
__ExpressionOrSpreadTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ExpressionOrSpread::Expression(Expression::StringLiteral(node)))
}
__ExpressionOrSpreadTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -3681,6 +3921,7 @@ enum __FunctionBodyTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -3694,10 +3935,13 @@ enum __FunctionBodyTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -3765,6 +4009,14 @@ impl<'de> serde::Deserialize<'de> for FunctionBody {
)?;
Ok(FunctionBody::Expression(Expression::BinaryExpression(node)))
}
__FunctionBodyTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(FunctionBody::Expression(Expression::BooleanLiteral(node)))
}
__FunctionBodyTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -3869,6 +4121,22 @@ impl<'de> serde::Deserialize<'de> for FunctionBody {
)?;
Ok(FunctionBody::Expression(Expression::NewExpression(node)))
}
__FunctionBodyTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(FunctionBody::Expression(Expression::NullLiteral(node)))
}
__FunctionBodyTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(FunctionBody::Expression(Expression::NumericLiteral(node)))
}
__FunctionBodyTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -3901,6 +4169,14 @@ impl<'de> serde::Deserialize<'de> for FunctionBody {
)?;
Ok(FunctionBody::Expression(Expression::SequenceExpression(node)))
}
__FunctionBodyTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(FunctionBody::Expression(Expression::StringLiteral(node)))
}
__FunctionBodyTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -4037,6 +4313,7 @@ enum __ForInitTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -4050,10 +4327,13 @@ enum __ForInitTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -4114,6 +4394,14 @@ impl<'de> serde::Deserialize<'de> for ForInit {
)?;
Ok(ForInit::Expression(Expression::BinaryExpression(node)))
}
__ForInitTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ForInit::Expression(Expression::BooleanLiteral(node)))
}
__ForInitTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -4218,6 +4506,22 @@ impl<'de> serde::Deserialize<'de> for ForInit {
)?;
Ok(ForInit::Expression(Expression::NewExpression(node)))
}
__ForInitTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ForInit::Expression(Expression::NullLiteral(node)))
}
__ForInitTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ForInit::Expression(Expression::NumericLiteral(node)))
}
__ForInitTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -4250,6 +4554,14 @@ impl<'de> serde::Deserialize<'de> for ForInit {
)?;
Ok(ForInit::Expression(Expression::SequenceExpression(node)))
}
__ForInitTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(ForInit::Expression(Expression::StringLiteral(node)))
}
__ForInitTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -4526,6 +4838,7 @@ enum __AssignmentTargetTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -4539,10 +4852,13 @@ enum __AssignmentTargetTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -4610,6 +4926,14 @@ impl<'de> serde::Deserialize<'de> for AssignmentTarget {
)?;
Ok(AssignmentTarget::Expression(Expression::BinaryExpression(node)))
}
__AssignmentTargetTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(AssignmentTarget::Expression(Expression::BooleanLiteral(node)))
}
__AssignmentTargetTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -4714,6 +5038,22 @@ impl<'de> serde::Deserialize<'de> for AssignmentTarget {
)?;
Ok(AssignmentTarget::Expression(Expression::NewExpression(node)))
}
__AssignmentTargetTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(AssignmentTarget::Expression(Expression::NullLiteral(node)))
}
__AssignmentTargetTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(AssignmentTarget::Expression(Expression::NumericLiteral(node)))
}
__AssignmentTargetTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -4754,6 +5094,14 @@ impl<'de> serde::Deserialize<'de> for AssignmentTarget {
)?;
Ok(AssignmentTarget::Expression(Expression::SequenceExpression(node)))
}
__AssignmentTargetTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(AssignmentTarget::Expression(Expression::StringLiteral(node)))
}
__AssignmentTargetTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -4938,6 +5286,7 @@ enum __JSXExpressionOrEmptyTag {
AssignmentExpression,
AwaitExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ChainExpression,
ClassExpression,
@@ -4951,10 +5300,13 @@ enum __JSXExpressionOrEmptyTag {
MemberExpression,
MetaProperty,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
OptionalCallExpression,
OptionalMemberExpression,
SequenceExpression,
StringLiteral,
TaggedTemplateExpression,
TemplateLiteral,
ThisExpression,
@@ -5023,6 +5375,14 @@ impl<'de> serde::Deserialize<'de> for JSXExpressionOrEmpty {
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::BinaryExpression(node)))
}
__JSXExpressionOrEmptyTag::BooleanLiteral => {
let node: Box<BooleanLiteral> = <Box<
BooleanLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::BooleanLiteral(node)))
}
__JSXExpressionOrEmptyTag::CallExpression => {
let node: Box<CallExpression> = <Box<
CallExpression,
@@ -5135,6 +5495,22 @@ impl<'de> serde::Deserialize<'de> for JSXExpressionOrEmpty {
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::NewExpression(node)))
}
__JSXExpressionOrEmptyTag::NullLiteral => {
let node: Box<NullLiteral> = <Box<
NullLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::NullLiteral(node)))
}
__JSXExpressionOrEmptyTag::NumericLiteral => {
let node: Box<NumericLiteral> = <Box<
NumericLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::NumericLiteral(node)))
}
__JSXExpressionOrEmptyTag::ObjectExpression => {
let node: Box<ObjectExpression> = <Box<
ObjectExpression,
@@ -5179,6 +5555,14 @@ impl<'de> serde::Deserialize<'de> for JSXExpressionOrEmpty {
),
)
}
__JSXExpressionOrEmptyTag::StringLiteral => {
let node: Box<StringLiteral> = <Box<
StringLiteral,
> as Deserialize>::deserialize(
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
)?;
Ok(JSXExpressionOrEmpty::Expression(Expression::StringLiteral(node)))
}
__JSXExpressionOrEmptyTag::TaggedTemplateExpression => {
let node: Box<TaggedTemplateExpression> = <Box<
TaggedTemplateExpression,
@@ -7,7 +7,7 @@ mod visit;
pub use binding::{Binding, BindingId};
pub use generated::*;
pub use js_value::JsValue;
pub use js_value::{JsValue, Number};
pub use range::SourceRange;
pub use visit::*;
@@ -286,7 +286,6 @@ Output:
}
},
"computed": false,
"optional": false,
"loc": {
"source": null,
"start": {
@@ -3,7 +3,7 @@ use crate::{
ExportDefaultDeclaration, ExportNamedDeclaration, Expression, ExpressionOrSpread,
ExpressionOrSuper, ForInInit, ForInit, Function, FunctionBody, Identifier, ImportDeclaration,
ImportDeclarationSpecifier, ImportOrExportDeclaration, Literal, MethodDefinition, ModuleItem,
Pattern, Program, Statement, SwitchCase, VariableDeclarator,
Pattern, Program, Statement, SwitchCase, VariableDeclarator, _Literal,
};
/// Trait for visiting an estree
@@ -97,7 +97,7 @@ pub trait Visitor<'ast> {
fn visit_import_declaration_specifier(
&mut self,
specifier: &'ast ImportDeclarationSpecifier,
_source: &'ast Literal,
_source: &'ast _Literal,
) {
match specifier {
ImportDeclarationSpecifier::ImportSpecifier(specifier) => {
@@ -406,17 +406,22 @@ pub trait Visitor<'ast> {
fn visit_identifier(&mut self, _identifier: &'ast Identifier) {
// nothing to do unless overridden
todo!("Implement visit_identifier()")
}
fn visit_import_source(&mut self, literal: &'ast Literal) {
self.visit_literal(literal);
fn visit_import_source(&mut self, literal: &'ast _Literal) {
self.visit_any_literal(literal);
}
fn visit_export_source(&mut self, literal: &'ast Literal) {
self.visit_literal(literal);
fn visit_export_source(&mut self, literal: &'ast _Literal) {
self.visit_any_literal(literal);
}
fn visit_any_literal(&mut self, _literal: &'ast _Literal) {
todo!("Implement visit_any_literal()")
}
fn visit_literal(&mut self, _literal: &'ast Literal) {
// nothing to do unless overridden
todo!("Implement visit_literal()")
}
}
@@ -20,6 +20,21 @@ pub fn estree() -> String {
)
}
/// Returns prettyplease-formatted Rust source for converting HermesParser results
/// into estree
pub fn estree_hermes() -> String {
let src = include_str!("./ecmascript.json");
let grammar: Grammar = serde_json::from_str(src).unwrap();
let raw = grammar.codegen_hermes().to_string();
let parsed = syn::parse_file(&raw).unwrap();
format!(
"// {}generated\n#![cfg_attr(rustfmt, rustfmt_skip)]\n{}",
'\u{0040}',
prettyplease::unparse(&parsed)
)
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Grammar {
@@ -59,7 +74,7 @@ impl Grammar {
use std::num::NonZeroU32;
use serde::ser::{Serializer, SerializeMap};
use serde::{Serialize,Deserialize};
use crate::{JsValue, Binding, SourceRange};
use crate::{JsValue, Binding, SourceRange, Number};
#(#objects)*
@@ -70,6 +85,42 @@ impl Grammar {
#(#operators)*
}
}
pub fn codegen_hermes(self) -> TokenStream {
let nodes: Vec<_> = self
.nodes
.iter()
.filter(|(_, node)| !node.skip_hermes_codegen)
.map(|(name, node)| node.codegen_hermes(name))
.collect();
let enums: Vec<_> = self
.enums
.iter()
.map(|(name, enum_)| enum_.codegen_hermes(name, &self))
.collect();
let operators: Vec<_> = self
.operators
.iter()
.map(|(name, operator)| operator.codegen_hermes(name))
.collect();
quote! {
#![allow(dead_code)]
#![allow(unused_variables)]
use forget_estree::*;
use hermes;
use hermes::parser::{NodePtr, NodeKind, NodeLabel };
use hermes::utf::{utf8_with_surrogates_to_string};
use crate::generated_extension::*;
#(#nodes)*
#(#enums)*
#(#operators)*
}
}
}
#[derive(Serialize, Deserialize, Debug)]
@@ -107,6 +158,12 @@ pub struct Node {
#[serde(default)]
pub fields: IndexMap<String, Field>,
#[serde(default)]
pub skip_hermes_codegen: bool,
#[serde(default)]
pub skip_hermes_enum_variant: bool,
}
impl Node {
@@ -175,11 +232,108 @@ impl Node {
}
}
}
pub fn codegen_hermes(&self, name: &str) -> TokenStream {
let name_str = name;
let name = format_ident!("{}", name);
let field_names: Vec<_> = self
.fields
.iter()
.map(|(name, _field)| format_ident!("{}", name))
.collect();
let fields: Vec<_> = self
.fields
.iter()
.map(|(name, field)| {
let (type_name_str, type_kind) = parse_type(&field.type_).unwrap();
let camelcase_name = field.rename.as_ref().unwrap_or(name);
let field_name = format_ident!("{}", name);
let helper = format_ident!("hermes_get_{}_{}", name_str, camelcase_name);
let type_name = format_ident!("{}", type_name_str);
if field.skip || field.hermes_default {
return quote! {
let #field_name = Default::default();
};
}
if let Some(convert_with) = &field.hermes_convert_with {
let convert_with = format_ident!("{}", convert_with);
return quote! {
let #field_name = #convert_with(cx, unsafe { hermes::parser::#helper(node) } );
}
}
match type_kind {
TypeKind::Named => {
match type_name_str.as_ref() {
"bool" => {
quote! {
let #field_name = unsafe { hermes::parser::#helper(node) };
}
}
"Number" => {
quote! {
let #field_name = convert_number(unsafe { hermes::parser::#helper(node) });
}
}
"String" => {
quote! {
let #field_name = convert_string(cx, unsafe { hermes::parser::#helper(node) });
}
}
_ => {
quote! {
let #field_name = #type_name::convert(cx, unsafe { hermes::parser::#helper(node) });
}
}
}
}
TypeKind::Option => {
match type_name_str.as_ref() {
"String" => {
quote! {
let #field_name = convert_option_string(cx, unsafe { hermes::parser::#helper(node) });
}
}
_ => {
quote! {
let #field_name = convert_option(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
}
}
}
}
TypeKind::Vec => {
quote! {
let #field_name = convert_vec(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
}
}
TypeKind::VecOfOption => {
quote! {
let #field_name = convert_vec_of_option(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
}
}
}
})
.collect();
quote! {
impl FromHermes for #name {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let range = convert_range(node);
#(#fields)*
Self {
#(#field_names,)*
loc: None,
range: Some(range),
}
}
}
}
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Field {
// TODO: deserialize with `parse_type` into a custom type
#[serde(rename = "type")]
pub type_: String,
@@ -198,11 +352,18 @@ pub struct Field {
#[serde(default)]
#[serde(rename = "TODO")]
pub todo: Option<String>,
#[serde(default)]
pub hermes_convert_with: Option<String>,
#[serde(default)]
pub hermes_default: bool,
}
impl Field {
pub fn codegen(&self, name: &str) -> TokenStream {
let name = format_ident!("{}", name);
parse_type(&self.type_).unwrap();
let type_name: Type = syn::parse_str(&self.type_)
.unwrap_or_else(|_| panic!("Expected a type name, got `{}`", &self.type_));
@@ -237,6 +398,7 @@ impl Field {
pub fn codegen_node(&self, name: &str) -> TokenStream {
let name = format_ident!("{}", name);
parse_type(&self.type_).unwrap();
let type_name: Type = syn::parse_str(&self.type_)
.unwrap_or_else(|_| panic!("Expected a type name, got `{}`", &self.type_));
let type_ = quote!(#type_name);
@@ -386,6 +548,86 @@ impl Enum {
}
}
}
pub fn codegen_hermes(&self, name: &str, grammar: &Grammar) -> TokenStream {
let name = format_ident!("{}", name);
let mut tag_matches = Vec::new();
let mut seen = HashSet::new();
// Imagine a case like:
// enum ModuleItem {
// ImportDeclaration, // struct
// Statement // another enum
// }
// We need to generate matches for all the possible *concrete* `type` values, which means
// we have to expand nested enums such as `Statement`
for variant in self.variants.iter() {
if let Some(nested_enum) = grammar.enums.get(variant) {
let outer_variant = format_ident!("{}", variant);
for variant in nested_enum.variants.iter() {
// Skip variants that appear in multiple nested enums, we deserialize
// as the first listed outer variant
if !seen.insert(variant.to_string()) {
continue;
}
// Modeling ESTree only requires a single level of nested enums,
// so that's all we support. Though in theory we could support arbitrary nesting,
// since ultimately we're matching based on the final concrete types.
assert!(!grammar.enums.contains_key(variant));
let node = grammar.nodes.get(variant).unwrap();
if node.skip_hermes_enum_variant {
continue;
}
let inner_variant = format_ident!("{}", variant);
let node_variant_name = node.type_.as_ref().unwrap_or(variant);
let node_variant = format_ident!("{}", node_variant_name);
tag_matches.push(quote! {
NodeKind::#node_variant => {
let node = #inner_variant::convert(cx, node);
#name::#outer_variant(#outer_variant::#inner_variant(Box::new(node)))
}
});
}
} else {
if !seen.insert(variant.to_string()) {
panic!(
"Concrete variant {} was already added by a nested enum",
variant
);
}
let variant_name = format_ident!("{}", variant);
let node = grammar.nodes.get(variant).unwrap();
if node.skip_hermes_enum_variant {
continue;
}
let node_variant_name = node.type_.as_ref().unwrap_or(variant);
let node_variant = format_ident!("{}", node_variant_name);
tag_matches.push(quote! {
NodeKind::#node_variant => {
let node = #variant_name::convert(cx, node);
#name::#variant_name(Box::new(node))
}
})
}
}
quote! {
impl FromHermes for #name {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let node_ref = node.as_ref();
match node_ref.kind {
#(#tag_matches),*
_ => panic!("Unexpected node")
}
}
}
}
}
}
#[derive(Serialize, Deserialize, Debug)]
@@ -457,4 +699,67 @@ impl Operator {
}
}
}
pub fn codegen_hermes(&self, name: &str) -> TokenStream {
let mut sorted_variants: Vec<_> = self.variants.iter().collect();
sorted_variants.sort();
let name = format_ident!("{}", name);
quote! {
impl FromHermesLabel for #name {
fn convert(cx: &mut Context, label: NodeLabel) -> Self {
let utf_str = utf8_with_surrogates_to_string(label.as_slice()).unwrap();
utf_str.parse().unwrap()
}
}
}
}
}
enum TypeKind {
/// T
Named,
/// Option<T>
Option,
/// Vec<T>
Vec,
/// Vec<Option<T>>
VecOfOption,
}
/// Parses a given type into the underlying type name plus a descriptor of the
/// kind of type. Only a subset of Rust types are supported:
/// - T
/// - Option<T>
/// - Vec<T>
/// - Vec<Option<T>>
fn parse_type(type_: &str) -> Result<(String, TypeKind), String> {
let mut current = type_;
let mut is_list = false;
let mut is_option = false;
if current.starts_with("Vec<") {
current = &current[4..current.len() - 1];
is_list = true;
}
if current.starts_with("Option<") {
current = &current[7..current.len() - 1];
is_option = true;
}
if current.contains("<") {
Err(format!(
"Unsupported type `{current}` expected named type (`Identifier`), optional type (`Option<Identifier>`), list type (`Vec<Identifier>`), or optional list (`Vec<Option<Identifier>>`)"
))
} else {
let kind = match (is_list, is_option) {
(true, true) => TypeKind::VecOfOption,
(true, false) => TypeKind::Vec,
(false, true) => TypeKind::Option,
(false, false) => TypeKind::Named,
};
Ok((current.to_string(), kind))
}
}
@@ -23,6 +23,20 @@
}
}
},
"Class": {
"fields": {
"id": {
"type": "Option<Identifier>"
},
"super_class": {
"type": "Option<Expression>",
"rename": "superClass"
},
"body": {
"type": "ClassBody"
}
}
},
"Function": {
"fields": {
"id": {
@@ -89,6 +103,8 @@
}
},
"Literal": {
"skip_hermes_codegen": true,
"skip_hermes_enum_variant": true,
"fields": {
"value": {
"type": "JsValue"
@@ -107,6 +123,29 @@
}
}
},
"NumericLiteral": {
"fields": {
"value": {
"type": "Number"
}
}
},
"BooleanLiteral": {
"fields": {
"value": {
"type": "bool"
}
}
},
"NullLiteral": {},
"StringLiteral": {
"fields": {
"value": {
"type": "String",
"hermes_convert_with": "convert_string_value"
}
}
},
"Program": {
"fields": {
"body": {
@@ -115,7 +154,8 @@
"source_type": {
"type": "SourceType",
"optional": true,
"rename": "sourceType"
"rename": "sourceType",
"hermes_default": true
}
}
},
@@ -126,7 +166,8 @@
},
"directive": {
"type": "Option<String>",
"optional": true
"optional": true,
"hermes_default": true
}
}
},
@@ -311,6 +352,7 @@
}
},
"FunctionDeclaration": {
"skip_hermes_codegen": true,
"fields": {
"function": {
"type": "Function",
@@ -318,21 +360,8 @@
}
}
},
"Class": {
"fields": {
"id": {
"type": "Option<Identifier>"
},
"super_class": {
"type": "Option<Expression>",
"rename": "superClass"
},
"body": {
"type": "ClassBody"
}
}
},
"ClassDeclaration": {
"skip_hermes_codegen": true,
"fields": {
"class": {
"type": "Class",
@@ -341,6 +370,7 @@
}
},
"ClassExpression": {
"skip_hermes_codegen": true,
"fields": {
"class": {
"type": "Class",
@@ -400,7 +430,8 @@
"ArrayExpression": {
"fields": {
"elements": {
"type": "Vec<Option<ExpressionOrSpread>>"
"type": "Vec<Option<ExpressionOrSpread>>",
"hermes_convert_with": "convert_array_expression_elements"
}
}
},
@@ -437,6 +468,7 @@
}
},
"FunctionExpression": {
"skip_hermes_codegen": true,
"fields": {
"function": {
"type": "Function",
@@ -445,6 +477,7 @@
}
},
"ArrowFunctionExpression": {
"skip_hermes_codegen": true,
"fields": {
"function": {
"type": "Function",
@@ -532,11 +565,6 @@
"is_computed": {
"type": "bool",
"rename": "computed"
},
"is_optional": {
"type": "bool",
"optional": true,
"rename": "optional"
}
}
},
@@ -560,11 +588,6 @@
},
"arguments": {
"type": "Vec<ExpressionOrSpread>"
},
"is_optional": {
"type": "bool",
"optional": true,
"rename": "optional"
}
}
},
@@ -611,7 +634,7 @@
"type": "Vec<ImportDeclarationSpecifier>"
},
"source": {
"type": "Literal"
"type": "_Literal"
}
}
},
@@ -648,7 +671,7 @@
"type": "Vec<ExportSpecifier>"
},
"source": {
"type": "Option<Literal>"
"type": "Option<_Literal>"
}
}
},
@@ -669,11 +692,12 @@
"ExportAllDeclaration": {
"fields": {
"source": {
"type": "Literal"
"type": "_Literal"
},
"exported": {
"type": "Option<Identifier>",
"optional": true
"optional": true,
"hermes_default": true
}
}
},
@@ -765,7 +789,8 @@
"JSXText": {
"fields": {
"value": {
"type": "String"
"type": "String",
"hermes_convert_with": "convert_string_value"
},
"raw": {
"type": "String"
@@ -797,7 +822,7 @@
"type": "Vec<JSXChildItem>"
},
"closing_fragment": {
"type": "Option<JSXClosingFragment>",
"type": "JSXClosingFragment",
"rename": "closingFragment"
}
}
@@ -819,6 +844,7 @@
}
},
"AssignmentProperty": {
"skip_hermes_codegen": true,
"type": "Property",
"fields": {
"key": {
@@ -865,6 +891,7 @@
}
},
"TemplateElement": {
"skip_hermes_codegen": true,
"fields": {
"tail": {
"type": "bool"
@@ -902,6 +929,8 @@
}
},
"ChainExpression": {
"skip_hermes_codegen": true,
"skip_hermes_enum_variant": true,
"fields": {
"expression": {
"type": "ChainElement"
@@ -914,7 +943,7 @@
"type": "Expression"
},
"property": {
"type": "Identifier"
"type": "Expression"
},
"is_computed": {
"type": "bool",
@@ -980,6 +1009,7 @@
"AssignmentExpression",
"AwaitExpression",
"BinaryExpression",
"BooleanLiteral",
"CallExpression",
"ChainExpression",
"ClassExpression",
@@ -993,10 +1023,13 @@
"MemberExpression",
"MetaProperty",
"NewExpression",
"NullLiteral",
"NumericLiteral",
"ObjectExpression",
"OptionalCallExpression",
"OptionalMemberExpression",
"SequenceExpression",
"StringLiteral",
"TaggedTemplateExpression",
"TemplateLiteral",
"ThisExpression",
@@ -1004,6 +1037,13 @@
"UpdateExpression",
"YieldExpression"
],
"_Literal": [
"Literal",
"BooleanLiteral",
"NullLiteral",
"StringLiteral",
"NumericLiteral"
],
"Declaration": [
"ClassDeclaration",
"FunctionDeclaration",
@@ -1,3 +1,3 @@
mod codegen;
pub use codegen::estree;
pub use codegen::{estree, estree_hermes};
@@ -340,7 +340,6 @@ fn convert_expression(cx: &Context, expr: &Expr) -> forget_estree::Expression {
_ => todo!(),
},
arguments: convert_arguments(cx, &expr.args),
is_optional: false,
loc: None,
range: convert_span(&expr.span),
}))
@@ -452,9 +451,9 @@ fn convert_expression(cx: &Context, expr: &Expr) -> forget_estree::Expression {
}),
),
OptChainBase::Member(base) => {
let mut member = convert_member_expression(cx, base);
let mut member = convert_optional_member_expression(cx, base);
member.is_optional = expr.optional;
forget_estree::Expression::MemberExpression(Box::new(member))
forget_estree::Expression::OptionalMemberExpression(Box::new(member))
}
},
Expr::JSXElement(expr) => {
@@ -779,6 +778,29 @@ fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> forget_estree::
object: forget_estree::ExpressionOrSuper::Expression(convert_expression(cx, &expr.obj)),
property,
is_computed,
loc: None,
range: convert_span(&expr.span),
}
}
fn convert_optional_member_expression(
cx: &Context,
expr: &MemberExpr,
) -> forget_estree::OptionalMemberExpression {
let (is_computed, property) = match &expr.prop {
MemberProp::Ident(prop) => (
false,
forget_estree::Expression::Identifier(Box::new(convert_identifier(cx, prop))),
),
MemberProp::Computed(prop) => (true, convert_expression(cx, &prop.expr)),
_ => {
panic!("PrivateName member expression properties are not supported")
}
};
forget_estree::OptionalMemberExpression {
object: convert_expression(cx, &expr.obj),
property,
is_computed,
is_optional: false,
loc: None,
range: convert_span(&expr.span),
@@ -15,4 +15,7 @@ repository.workspace = true
forget_diagnostics = { workspace = true }
forget_estree = { workspace = true }
hermes = { workspace = true }
juno_support = { workspace = true }
juno_support = { workspace = true }
[build-dependencies]
forget_estree_codegen = { workspace = true }
@@ -0,0 +1,13 @@
use forget_estree_codegen::estree_hermes;
// Example custom build script.
fn main() {
// Re-run if the codegen files change
println!("cargo:rerun-if-changed=../forget_estree_codegen/src/codegen.rs");
println!("cargo:rerun-if-changed=../forget_estree_codegen/src/lib.rs");
println!("cargo:rerun-if-changed=../forget_estree_codegen/src/ecmascript.json");
println!("cargo:rerun-if-changed=../forget_estree_codegen");
let src = estree_hermes();
std::fs::write("src/generated.rs", src).unwrap();
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,288 @@
use forget_estree::{
ArrowFunctionExpression, AssignmentProperty, Class, ClassBody, ClassDeclaration,
ClassExpression, Expression, ExpressionOrSpread, Function, FunctionBody, FunctionDeclaration,
FunctionExpression, Identifier, Number, Pattern, SourceRange, TemplateElement,
TemplateElementValue,
};
use hermes::parser::{
hermes_get_ArrowFunctionExpression_async, hermes_get_ArrowFunctionExpression_body,
hermes_get_ArrowFunctionExpression_expression, hermes_get_ArrowFunctionExpression_id,
hermes_get_ArrowFunctionExpression_params, hermes_get_ClassDeclaration_body,
hermes_get_ClassDeclaration_id, hermes_get_ClassDeclaration_superClass,
hermes_get_ClassExpression_body, hermes_get_ClassExpression_id,
hermes_get_ClassExpression_superClass, hermes_get_FunctionDeclaration_async,
hermes_get_FunctionDeclaration_body, hermes_get_FunctionDeclaration_generator,
hermes_get_FunctionDeclaration_id, hermes_get_FunctionDeclaration_params,
hermes_get_FunctionExpression_async, hermes_get_FunctionExpression_body,
hermes_get_FunctionExpression_generator, hermes_get_FunctionExpression_id,
hermes_get_FunctionExpression_params, hermes_get_Property_key, hermes_get_Property_kind,
hermes_get_Property_method, hermes_get_Property_value, NodeKind, NodeLabel, NodeLabelOpt,
NodeListRef, NodePtr, NodePtrOpt, NodeString, NodeStringOpt, SMRange,
};
use hermes::utf::utf8_with_surrogates_to_string;
pub struct Context;
impl Context {
pub fn new() -> Self {
Self
}
}
pub trait FromHermes {
fn convert(cx: &mut Context, node: NodePtr) -> Self;
}
pub trait FromHermesLabel {
fn convert(cx: &mut Context, label: NodeLabel) -> Self;
}
pub fn convert_option<F, T>(node: NodePtrOpt, mut f: F) -> Option<T>
where
F: FnMut(NodePtr) -> T,
{
node.as_node_ptr().map(|node| f(node))
}
pub fn convert_vec<F, T>(node: NodeListRef, mut f: F) -> Vec<T>
where
F: FnMut(NodePtr) -> T,
{
node.iter().map(|node| f(NodePtr::new(node))).collect()
}
pub fn convert_vec_of_option<F, T>(node: NodeListRef, mut f: F) -> Vec<Option<T>>
where
F: FnMut(NodePtr) -> T,
{
node.iter()
.map(|node| {
let node = NodePtr::new(node);
let node_ref = node.as_ref();
match node_ref.kind {
NodeKind::Empty => None,
_ => Some(f(node)),
}
})
.collect()
}
pub fn convert_range(node: NodePtr) -> SourceRange {
let _range = node.as_ref().source_range;
todo!()
}
#[allow(dead_code)]
pub fn convert_smrange(_range: SMRange) -> SourceRange {
todo!()
}
pub fn convert_string(_cx: &mut Context, label: NodeLabel) -> String {
utf8_with_surrogates_to_string(label.as_slice()).unwrap()
}
#[allow(dead_code)]
pub fn convert_option_string(cx: &mut Context, label: NodeLabelOpt) -> Option<String> {
label.as_node_label().map(|label| convert_string(cx, label))
}
pub fn convert_string_value(_cx: &mut Context, label: NodeString) -> String {
utf8_with_surrogates_to_string(label.as_slice()).unwrap()
}
pub fn convert_option_string_value(_cx: &mut Context, label: NodeStringOpt) -> Option<String> {
label
.as_node_string()
.map(|label| utf8_with_surrogates_to_string(label.as_slice()).unwrap())
}
pub fn convert_number(value: f64) -> Number {
value.into()
}
pub fn convert_array_expression_elements(
cx: &mut Context,
node: NodeListRef,
) -> Vec<Option<ExpressionOrSpread>> {
convert_vec_of_option(node, |node| ExpressionOrSpread::convert(cx, node))
}
impl FromHermes for TemplateElement {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let range = convert_range(node);
let tail = unsafe { hermes::parser::hermes_get_TemplateElement_tail(node) };
let value = TemplateElementValue {
cooked: convert_option_string_value(cx, unsafe {
hermes::parser::hermes_get_TemplateElement_cooked(node)
}),
raw: convert_string(cx, unsafe {
hermes::parser::hermes_get_TemplateElement_raw(node)
}),
};
Self {
tail,
value,
loc: None,
range: Some(range),
}
}
}
impl FromHermes for AssignmentProperty {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let key = FromHermes::convert(cx, unsafe { hermes_get_Property_key(node) });
let value = FromHermes::convert(cx, unsafe { hermes_get_Property_value(node) });
let kind = FromHermesLabel::convert(cx, unsafe { hermes_get_Property_kind(node) });
let method = unsafe { hermes_get_Property_method(node) };
let loc = None;
let range = convert_range(node);
AssignmentProperty {
key,
value,
kind,
method,
loc,
range: Some(range),
}
}
}
impl FromHermes for FunctionDeclaration {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let id = convert_option(unsafe { hermes_get_FunctionDeclaration_id(node) }, |node| {
Identifier::convert(cx, node)
});
let params = convert_vec(
unsafe { hermes_get_FunctionDeclaration_params(node) },
|node| Pattern::convert(cx, node),
);
let body = FunctionBody::convert(cx, unsafe { hermes_get_FunctionDeclaration_body(node) });
let is_generator = unsafe { hermes_get_FunctionDeclaration_generator(node) };
let is_async = unsafe { hermes_get_FunctionDeclaration_async(node) };
let loc = None;
let range = convert_range(node);
FunctionDeclaration {
function: Function {
id,
params,
body: Some(body),
is_generator,
is_async,
loc: loc.clone(),
range: Some(range),
},
loc,
range: Some(range),
}
}
}
impl FromHermes for FunctionExpression {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let id = convert_option(unsafe { hermes_get_FunctionExpression_id(node) }, |node| {
Identifier::convert(cx, node)
});
let params = convert_vec(
unsafe { hermes_get_FunctionExpression_params(node) },
|node| Pattern::convert(cx, node),
);
let body = FunctionBody::convert(cx, unsafe { hermes_get_FunctionExpression_body(node) });
let is_generator = unsafe { hermes_get_FunctionExpression_generator(node) };
let is_async = unsafe { hermes_get_FunctionExpression_async(node) };
let loc = None;
let range = convert_range(node);
FunctionExpression {
function: Function {
id,
params,
body: Some(body),
is_generator,
is_async,
loc: loc.clone(),
range: Some(range),
},
loc,
range: Some(range),
}
}
}
impl FromHermes for ArrowFunctionExpression {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let id = convert_option(
unsafe { hermes_get_ArrowFunctionExpression_id(node) },
|node| Identifier::convert(cx, node),
);
let params = convert_vec(
unsafe { hermes_get_ArrowFunctionExpression_params(node) },
|node| Pattern::convert(cx, node),
);
let body =
FunctionBody::convert(cx, unsafe { hermes_get_ArrowFunctionExpression_body(node) });
let is_generator = unsafe { hermes_get_FunctionExpression_generator(node) };
let is_async = unsafe { hermes_get_ArrowFunctionExpression_async(node) };
let is_expression = unsafe { hermes_get_ArrowFunctionExpression_expression(node) };
let loc = None;
let range = convert_range(node);
ArrowFunctionExpression {
function: Function {
id,
params,
body: Some(body),
is_generator,
is_async,
loc: loc.clone(),
range: Some(range),
},
is_expression,
loc,
range: Some(range),
}
}
}
impl FromHermes for ClassDeclaration {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let id = convert_option(unsafe { hermes_get_ClassDeclaration_id(node) }, |node| {
Identifier::convert(cx, node)
});
let super_class = convert_option(
unsafe { hermes_get_ClassDeclaration_superClass(node) },
|node| Expression::convert(cx, node),
);
let body = ClassBody::convert(cx, unsafe { hermes_get_ClassDeclaration_body(node) });
let loc = None;
let range = convert_range(node);
ClassDeclaration {
class: Class {
id,
super_class,
body,
},
loc,
range: Some(range),
}
}
}
impl FromHermes for ClassExpression {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let id = convert_option(unsafe { hermes_get_ClassExpression_id(node) }, |node| {
Identifier::convert(cx, node)
});
let super_class = convert_option(
unsafe { hermes_get_ClassExpression_superClass(node) },
|node| Expression::convert(cx, node),
);
let body = ClassBody::convert(cx, unsafe { hermes_get_ClassExpression_body(node) });
let loc = None;
let range = convert_range(node);
ClassExpression {
class: Class {
id,
super_class,
body,
},
loc,
range: Some(range),
}
}
}
@@ -1,14 +1,14 @@
mod generated;
mod generated_extension;
use forget_diagnostics::Diagnostic;
use hermes::parser::{
hermes_get_BlockStatement_body, hermes_get_DeclareFunction_id,
hermes_get_FunctionDeclaration_async, hermes_get_FunctionDeclaration_body,
hermes_get_FunctionDeclaration_generator, hermes_get_Program_body, HermesParser, NodeKind,
NodePtr, ParserDialect, ParserFlags,
};
use juno_support::source_manager::SourceRange;
use forget_estree::Program;
use generated_extension::{Context, FromHermes};
use hermes::parser::{HermesParser, ParserDialect, ParserFlags};
use hermes::utf::utf8_with_surrogates_to_string;
use juno_support::NullTerminatedBuf;
pub fn parse(source: &str, file: &str) -> Result<forget_estree::Program, Vec<Diagnostic>> {
pub fn parse(source: &str, _file: &str) -> Result<Program, Vec<Diagnostic>> {
let buf = NullTerminatedBuf::from_str_check(source);
let result = HermesParser::parse(
ParserFlags {
@@ -19,98 +19,17 @@ pub fn parse(source: &str, file: &str) -> Result<forget_estree::Program, Vec<Dia
},
&buf,
);
let mut cx = Context::new();
if result.has_errors() {
let error_messages = result.messages();
return Err(todo!("construct diagnostics"));
return Err(error_messages
.into_iter()
.map(|diag| {
let message = utf8_with_surrogates_to_string(diag.message.as_slice()).unwrap();
Diagnostic::invalid_syntax(message, None)
})
.collect());
}
Ok(unsafe { convert_program(result.root().unwrap()) })
}
unsafe fn convert_program(node: NodePtr) -> forget_estree::Program {
let node_ref = node.as_ref();
let body = hermes_get_Program_body(node);
let body: Vec<_> = body
.iter()
.map(|node| convert_module_item(NodePtr::new(node)))
.collect();
forget_estree::Program {
body,
source_type: forget_estree::SourceType::Module,
loc: None,
range: None,
}
}
unsafe fn convert_module_item(node: NodePtr) -> forget_estree::ModuleItem {
let node_ref = node.as_ref();
match node_ref.kind {
NodeKind::FunctionDeclaration => {
forget_estree::ModuleItem::Statement(forget_estree::Statement::FunctionDeclaration(
Box::new(convert_function_declaration(node)),
))
}
_ => todo!(),
}
}
unsafe fn convert_function_declaration(node: NodePtr) -> forget_estree::FunctionDeclaration {
let id = None; //hermes_get_DeclareFunction_id(node);
let params = Vec::new();
let body = forget_estree::FunctionBody::BlockStatement(Box::new(convert_block_statement(
hermes_get_FunctionDeclaration_body(node),
)));
let is_generator = hermes_get_FunctionDeclaration_generator(node);
let is_async = hermes_get_FunctionDeclaration_async(node);
forget_estree::FunctionDeclaration {
function: forget_estree::Function {
id,
params,
body: Some(body),
is_generator,
is_async,
loc: None,
range: None,
},
loc: None,
range: None,
}
}
unsafe fn convert_block_statement(node: NodePtr) -> forget_estree::BlockStatement {
let body = hermes_get_BlockStatement_body(node);
let body: Vec<_> = body
.iter()
.map(|node| convert_statement(NodePtr::new(node)))
.collect();
forget_estree::BlockStatement {
body,
loc: None,
range: None,
}
}
unsafe fn convert_statement(node: NodePtr) -> forget_estree::Statement {
let node_ref = node.as_ref();
match node_ref.kind {
NodeKind::ReturnStatement => {
forget_estree::Statement::ReturnStatement(Box::new(forget_estree::ReturnStatement {
argument: None,
loc: None,
range: None,
}))
}
_ => todo!(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fixtures() {
let res = parse("function foo() { return }", "hello.js");
println!("{:#?}", res);
}
Ok(FromHermes::convert(&mut cx, result.root().unwrap()))
}