pub mod array;
pub mod block;
pub mod break_node;
pub mod conditional;
pub mod declaration;
pub mod expression;
pub mod field;
pub mod identifier;
pub mod iteration;
pub mod object;
pub mod operator;
pub mod return_smt;
pub mod spread;
pub mod statement_list;
pub mod switch;
pub mod throw;
pub mod try_node;
pub use self::{
array::ArrayDecl,
block::Block,
break_node::Break,
conditional::{ConditionalOp, If},
declaration::{
ArrowFunctionDecl, ConstDecl, ConstDeclList, FunctionDecl, FunctionExpr, LetDecl,
LetDeclList, VarDecl, VarDeclList,
},
expression::{Call, New},
field::{GetConstField, GetField},
identifier::Identifier,
iteration::{Continue, DoWhileLoop, ForLoop, WhileLoop},
object::Object,
operator::{Assign, BinOp, UnaryOp},
return_smt::Return,
spread::Spread,
statement_list::{RcStatementList, StatementList},
switch::{Case, Switch},
throw::Throw,
try_node::{Catch, Finally, Try},
};
use super::Const;
use gc::{unsafe_empty_trace, Finalize, Trace};
use std::{
cmp::Ordering,
fmt::{self, Display},
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub enum Node {
ArrayDecl(ArrayDecl),
ArrowFunctionDecl(ArrowFunctionDecl),
Assign(Assign),
BinOp(BinOp),
Block(Block),
Break(Break),
Call(Call),
ConditionalOp(ConditionalOp),
Const(Const),
ConstDeclList(ConstDeclList),
Continue(Continue),
DoWhileLoop(DoWhileLoop),
FunctionDecl(FunctionDecl),
FunctionExpr(FunctionExpr),
GetConstField(GetConstField),
GetField(GetField),
ForLoop(ForLoop),
If(If),
LetDeclList(LetDeclList),
Identifier(Identifier),
New(New),
Object(Object),
Return(Return),
Switch(Switch),
Spread(Spread),
Throw(Throw),
Try(Try),
This,
UnaryOp(UnaryOp),
VarDeclList(VarDeclList),
WhileLoop(WhileLoop),
}
impl Display for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}
impl From<Const> for Node {
fn from(c: Const) -> Self {
Self::Const(c)
}
}
impl Node {
pub(crate) fn hoistable_order(a: &Node, b: &Node) -> Ordering {
match (a, b) {
(Node::FunctionDecl(_), Node::FunctionDecl(_)) => Ordering::Equal,
(_, Node::FunctionDecl(_)) => Ordering::Greater,
(Node::FunctionDecl(_), _) => Ordering::Less,
(_, _) => Ordering::Equal,
}
}
pub fn this() -> Self {
Self::This
}
fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
let indent = " ".repeat(indentation);
match *self {
Self::Block(_) => {}
_ => write!(f, "{}", indent)?,
}
match *self {
Self::Const(ref c) => write!(f, "{}", c),
Self::ConditionalOp(ref cond_op) => Display::fmt(cond_op, f),
Self::ForLoop(ref for_loop) => for_loop.display(f, indentation),
Self::This => write!(f, "this"),
Self::Try(ref try_catch) => try_catch.display(f, indentation),
Self::Break(ref break_smt) => Display::fmt(break_smt, f),
Self::Continue(ref cont) => Display::fmt(cont, f),
Self::Spread(ref spread) => Display::fmt(spread, f),
Self::Block(ref block) => block.display(f, indentation),
Self::Identifier(ref s) => Display::fmt(s, f),
Self::GetConstField(ref get_const_field) => Display::fmt(get_const_field, f),
Self::GetField(ref get_field) => Display::fmt(get_field, f),
Self::Call(ref expr) => Display::fmt(expr, f),
Self::New(ref expr) => Display::fmt(expr, f),
Self::WhileLoop(ref while_loop) => while_loop.display(f, indentation),
Self::DoWhileLoop(ref do_while) => do_while.display(f, indentation),
Self::If(ref if_smt) => if_smt.display(f, indentation),
Self::Switch(ref switch) => switch.display(f, indentation),
Self::Object(ref obj) => obj.display(f, indentation),
Self::ArrayDecl(ref arr) => Display::fmt(arr, f),
Self::VarDeclList(ref list) => Display::fmt(list, f),
Self::FunctionDecl(ref decl) => decl.display(f, indentation),
Self::FunctionExpr(ref expr) => expr.display(f, indentation),
Self::ArrowFunctionDecl(ref decl) => decl.display(f, indentation),
Self::BinOp(ref op) => Display::fmt(op, f),
Self::UnaryOp(ref op) => Display::fmt(op, f),
Self::Return(ref ret) => Display::fmt(ret, f),
Self::Throw(ref throw) => Display::fmt(throw, f),
Self::Assign(ref op) => Display::fmt(op, f),
Self::LetDeclList(ref decl) => Display::fmt(decl, f),
Self::ConstDeclList(ref decl) => Display::fmt(decl, f),
}
}
}
fn join_nodes<N>(f: &mut fmt::Formatter<'_>, nodes: &[N]) -> fmt::Result
where
N: Display,
{
let mut first = true;
for e in nodes {
if !first {
f.write_str(", ")?;
}
first = false;
Display::fmt(e, f)?;
}
Ok(())
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Trace, Finalize)]
pub struct FormalParameter {
name: Box<str>,
init: Option<Node>,
is_rest_param: bool,
}
impl FormalParameter {
pub(in crate::syntax) fn new<N>(name: N, init: Option<Node>, is_rest_param: bool) -> Self
where
N: Into<Box<str>>,
{
Self {
name: name.into(),
init,
is_rest_param,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn init(&self) -> Option<&Node> {
self.init.as_ref()
}
pub fn is_rest_param(&self) -> bool {
self.is_rest_param
}
}
impl Display for FormalParameter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_rest_param {
write!(f, "...")?;
}
write!(f, "{}", self.name)?;
if let Some(n) = self.init.as_ref() {
write!(f, " = {}", n)?;
}
Ok(())
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Trace, Finalize)]
pub enum PropertyDefinition {
IdentifierReference(Box<str>),
Property(Box<str>, Node),
MethodDefinition(MethodDefinitionKind, Box<str>, FunctionExpr),
SpreadObject(Node),
}
impl PropertyDefinition {
pub fn identifier_reference<I>(ident: I) -> Self
where
I: Into<Box<str>>,
{
Self::IdentifierReference(ident.into())
}
pub fn property<N, V>(name: N, value: V) -> Self
where
N: Into<Box<str>>,
V: Into<Node>,
{
Self::Property(name.into(), value.into())
}
pub fn method_definition<N>(kind: MethodDefinitionKind, name: N, body: FunctionExpr) -> Self
where
N: Into<Box<str>>,
{
Self::MethodDefinition(kind, name.into(), body)
}
pub fn spread_object<O>(obj: O) -> Self
where
O: Into<Node>,
{
Self::SpreadObject(obj.into())
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Copy, Finalize)]
pub enum MethodDefinitionKind {
Get,
Set,
Ordinary,
}
unsafe impl Trace for MethodDefinitionKind {
unsafe_empty_trace!();
}