use super::{Block, Identifier, Node};
use gc::{Finalize, Trace};
use std::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Try {
block: Block,
catch: Option<Catch>,
finally: Option<Finally>,
}
impl Try {
pub(in crate::syntax) fn new<B>(
block: B,
catch: Option<Catch>,
finally: Option<Finally>,
) -> Self
where
B: Into<Block>,
{
assert!(
catch.is_some() || finally.is_some(),
"one of catch or finally must be pressent"
);
Self {
block: block.into(),
catch,
finally,
}
}
pub fn block(&self) -> &Block {
&self.block
}
pub fn catch(&self) -> Option<&Catch> {
self.catch.as_ref()
}
pub fn finally(&self) -> Option<&Block> {
self.finally.as_ref().map(Finally::block)
}
pub(super) fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
write!(f, "{}try ", " ".repeat(indentation))?;
self.block.display(f, indentation)?;
if let Some(ref catch) = self.catch {
catch.display(f, indentation)?;
}
if let Some(ref finally) = self.finally {
finally.display(f, indentation)?;
}
Ok(())
}
}
impl fmt::Display for Try {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}
impl From<Try> for Node {
fn from(try_catch: Try) -> Self {
Self::Try(try_catch)
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Catch {
parameter: Option<Identifier>,
block: Block,
}
impl Catch {
pub(in crate::syntax) fn new<OI, I, B>(parameter: OI, block: B) -> Self
where
OI: Into<Option<I>>,
I: Into<Identifier>,
B: Into<Block>,
{
Self {
parameter: parameter.into().map(I::into),
block: block.into(),
}
}
pub fn parameter(&self) -> Option<&str> {
self.parameter.as_ref().map(Identifier::as_ref)
}
pub fn block(&self) -> &Block {
&self.block
}
pub(super) fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
f.write_str(" catch")?;
if let Some(ref param) = self.parameter {
write!(f, "({})", param)?;
}
f.write_str(" ")?;
self.block.display(f, indentation)
}
}
impl fmt::Display for Catch {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Finally {
block: Block,
}
impl Finally {
pub fn block(&self) -> &Block {
&self.block
}
pub(super) fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
f.write_str(" finally ")?;
self.block.display(f, indentation)
}
}
impl<T> From<T> for Finally
where
T: Into<Block>,
{
fn from(block: T) -> Self {
Self {
block: block.into(),
}
}
}