Skip to content

Commit

Permalink
Merge all var/let/const decl types and remove unsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
0x7D2B committed Mar 17, 2021
1 parent aaa4653 commit 25a55c1
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 225 deletions.
50 changes: 2 additions & 48 deletions boa/src/syntax/ast/node/declaration/const_decl_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node, declaration::DeclarationList},
syntax::ast::node::{declaration::Declaration, join_nodes, Node},
Context, Result, Value,
};
use std::fmt;
Expand Down Expand Up @@ -59,12 +59,6 @@ impl Executable for ConstDeclList {
}
}

impl DeclarationList for ConstDeclList {
fn names(&self) -> Box<dyn Iterator<Item = &str> + '_> {
return Box::new(self.as_ref().iter().map(|i| i.name()))
}
}

impl<T> From<T> for ConstDeclList
where
T: Into<Box<[ConstDecl]>>,
Expand Down Expand Up @@ -105,44 +99,4 @@ impl From<ConstDeclList> for Node {
}
}

/// Individual constant declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct ConstDecl {
name: Identifier,
init: Option<Node>,
}

impl fmt::Display for ConstDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}

impl ConstDecl {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: Option<I>) -> Self
where
N: Into<Identifier>,
I: Into<Node>,
{
Self {
name: name.into(),
init: init.map(|n| n.into()),
}
}

/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}

/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> &Option<Node> {
&self.init
}
}
pub type ConstDecl = Declaration;
50 changes: 2 additions & 48 deletions boa/src/syntax/ast/node/declaration/let_decl_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{declaration::DeclarationList, join_nodes, Identifier, Node},
syntax::ast::node::{declaration::Declaration, join_nodes, Node},
Context, Result, Value,
};
use std::fmt;
Expand Down Expand Up @@ -56,12 +56,6 @@ impl Executable for LetDeclList {
}
}

impl DeclarationList for LetDeclList {
fn names(&self) -> Box<dyn Iterator<Item = &str> + '_> {
return Box::new(self.as_ref().iter().map(|i| i.name()));
}
}

impl<T> From<T> for LetDeclList
where
T: Into<Box<[LetDecl]>>,
Expand Down Expand Up @@ -102,44 +96,4 @@ impl From<LetDeclList> for Node {
}
}

/// Individual constant declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct LetDecl {
name: Identifier,
init: Option<Node>,
}

impl fmt::Display for LetDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}

impl LetDecl {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: I) -> Self
where
N: Into<Identifier>,
I: Into<Option<Node>>,
{
Self {
name: name.into(),
init: init.into(),
}
}

/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}

/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> Option<&Node> {
self.init.as_ref()
}
}
pub type LetDecl = Declaration;
194 changes: 185 additions & 9 deletions boa/src/syntax/ast/node/declaration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,205 @@
//! Declaration nodes
use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
};
use std::fmt;

#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

pub mod arrow_function_decl;
pub mod async_function_decl;
pub mod async_function_expr;
pub mod const_decl_list;
// pub mod const_decl_list;
pub mod function_decl;
pub mod function_expr;
pub mod let_decl_list;
pub mod var_decl_list;
// pub mod let_decl_list;
// pub mod var_decl_list;

pub use self::{
arrow_function_decl::ArrowFunctionDecl,
async_function_decl::AsyncFunctionDecl,
async_function_expr::AsyncFunctionExpr,
const_decl_list::{ConstDecl, ConstDeclList},
// const_decl_list::{ConstDecl, ConstDeclList},
function_decl::FunctionDecl,
function_expr::FunctionExpr,
let_decl_list::{LetDecl, LetDeclList},
var_decl_list::{VarDecl, VarDeclList},
// let_decl_list::{LetDecl, LetDeclList},
// var_decl_list::{VarDecl, VarDeclList},
};

#[cfg(test)]
mod tests;

/// A trait for lists of declarations such as LetDeclList
pub(crate) trait DeclarationList {
fn names(&self) -> Box<dyn Iterator<Item = &str> + '_>;
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub enum DeclarationType {
Let,
Const,
Var,
}

#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct DeclarationList {
#[cfg_attr(feature = "deser", serde(flatten))]
list: Box<[Declaration]>,
declaration_type: DeclarationType,
}

impl Executable for DeclarationList {
fn run(&self, context: &mut Context) -> Result<Value> {
for decl in self.as_ref() {
use DeclarationType::*;
let val = match (&self.declaration_type, decl.init()) {
(Const, None) => {
return context.throw_syntax_error("missing = in const declaration")
}
(_, Some(init)) => init.run(context)?,
(_, None) => Value::undefined(),
};
context
.realm_mut()
.environment
.create_mutable_binding(
decl.name().to_owned(),
false,
match &self.declaration_type {
Var => VariableScope::Function,
_ => VariableScope::Block,
},
)
.map_err(|e| e.to_error(context))?;
context
.realm_mut()
.environment
.initialize_binding(decl.name(), val)
.map_err(|e| e.to_error(context))?;
}
Ok(Value::undefined())
}
}

impl DeclarationList {
pub(in crate::syntax) fn new_let_decl_list<T>(list: T) -> Self
where
T: Into<Box<[Declaration]>>,
{
Self {
list: list.into(),
declaration_type: DeclarationType::Let,
}
}
pub(in crate::syntax) fn new_const_decl_list<T>(list: T) -> Self
where
T: Into<Box<[Declaration]>>,
{
Self {
list: list.into(),
declaration_type: DeclarationType::Const,
}
}
pub(in crate::syntax) fn new_var_decl_list<T>(list: T) -> Self
where
T: Into<Box<[Declaration]>>,
{
Self {
list: list.into(),
declaration_type: DeclarationType::Var,
}
}
}
// impl<T> From<T> for DeclarationList
// where
// T: Into<Box<[LetDecl]>>,
// {
// fn from(list: T) -> Self {
// Self { list: list.into() }
// }
// }

// impl From<LetDecl> for DeclarationList {
// fn from(decl: LetDecl) -> Self {
// Self {
// list: Box::new([decl]),
// }
// }
// }

impl AsRef<[Declaration]> for DeclarationList {
fn as_ref(&self) -> &[Declaration] {
&self.list
}
}

impl fmt::Display for DeclarationList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.list.is_empty() {
use DeclarationType::*;
match &self.declaration_type {
Let => write!(f, "let ")?,
Const => write!(f, "const ")?,
Var => write!(f, "var ")?,
}
join_nodes(f, &self.list)
} else {
Ok(())
}
}
}

impl From<DeclarationList> for Node {
fn from(list: DeclarationList) -> Self {
use DeclarationType::*;
match &list.declaration_type {
Let => Self::LetDeclList(list),
Const => Self::ConstDeclList(list),
Var => Self::VarDeclList(list),
}
}
}

/// Individual declaration.
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Declaration {
name: Identifier,
init: Option<Node>,
}

impl fmt::Display for Declaration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
if let Some(ref init) = self.init {
write!(f, " = {}", init)?;
}
Ok(())
}
}

impl Declaration {
/// Creates a new variable declaration.
pub(in crate::syntax) fn new<N, I>(name: N, init: I) -> Self
where
N: Into<Identifier>,
I: Into<Option<Node>>,
{
Self {
name: name.into(),
init: init.into(),
}
}

/// Gets the name of the variable.
pub fn name(&self) -> &str {
self.name.as_ref()
}

/// Gets the initialization node for the variable, if any.
pub fn init(&self) -> Option<&Node> {
self.init.as_ref()
}
}
8 changes: 1 addition & 7 deletions boa/src/syntax/ast/node/declaration/var_decl_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
environment::lexical_environment::VariableScope,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node, declaration::DeclarationList},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
};
use std::fmt;
Expand Down Expand Up @@ -64,12 +64,6 @@ impl Executable for VarDeclList {
}
}

impl DeclarationList for VarDeclList {
fn names(&self) -> Box<dyn Iterator<Item = &str> + '_> {
return Box::new(self.as_ref().iter().map(|i| i.name()))
}
}

impl<T> From<T> for VarDeclList
where
T: Into<Box<[VarDecl]>>,
Expand Down
Loading

0 comments on commit 25a55c1

Please sign in to comment.