easter 0.0.5

Type definitions for ECMAScript abstract syntax trees.
Documentation
use joker::track::*;

use id::Id;
use fun::Fun;
use patt::{Patt, CompoundPatt};
use expr::Expr;

#[derive(Debug, PartialEq)]
pub enum Decl {
    Fun(Fun)
}

impl TrackingRef for Decl {
    fn tracking_ref(&self) -> &Option<Span> {
        let Decl::Fun(ref fun) = *self;
        fun.tracking_ref()
    }
}

impl TrackingMut for Decl {
    fn tracking_mut(&mut self) -> &mut Option<Span> {
        let Decl::Fun(ref mut fun) = *self;
        fun.tracking_mut()
    }
}

impl Untrack for Decl {
    fn untrack(&mut self) {
        let Decl::Fun(ref mut fun) = *self;
        fun.untrack();
    }
}

#[derive(Debug, PartialEq)]
pub enum Dtor {
    Simple(Option<Span>, Id, Option<Expr>),
    Compound(Option<Span>, CompoundPatt<Id>, Expr)
}

impl TrackingRef for Dtor {
    fn tracking_ref(&self) -> &Option<Span> {
        match *self {
            Dtor::Simple(ref location, _, _)
          | Dtor::Compound(ref location, _, _) => location
        }
    }
}

impl TrackingMut for Dtor {
    fn tracking_mut(&mut self) -> &mut Option<Span> {
        match *self {
            Dtor::Simple(ref mut location, _, _)
          | Dtor::Compound(ref mut location, _, _) => location
        }
    }
}

impl Untrack for Dtor {
    fn untrack(&mut self) {
        match *self {
            Dtor::Simple(ref mut location, ref mut id, ref mut init) => {
                *location = None;
                id.untrack();
                init.untrack();
            }
            Dtor::Compound(ref mut location, ref mut patt, ref mut init) => {
                *location = None;
                patt.untrack();
                init.untrack();
            }
        }
    }
}

pub trait DtorExt {
    fn from_simple_init(Id, Expr) -> Dtor;
    fn from_compound_init(CompoundPatt<Id>, Expr) -> Dtor;
    fn from_init(Patt<Id>, Expr) -> Dtor;
    fn from_init_opt(Patt<Id>, Option<Expr>) -> Result<Dtor, CompoundPatt<Id>>;
}

impl DtorExt for Dtor {
    fn from_compound_init(lhs: CompoundPatt<Id>, rhs: Expr) -> Dtor {
        Dtor::Compound(span(&lhs, &rhs), lhs, rhs)
    }

    fn from_simple_init(lhs: Id, rhs: Expr) -> Dtor {
        Dtor::Simple(span(&lhs, &rhs), lhs, Some(rhs))
    }

    fn from_init(lhs: Patt<Id>, rhs: Expr) -> Dtor {
        let loc = span(&lhs, &rhs);
        match lhs {
            Patt::Simple(id) => Dtor::Simple(loc, id, Some(rhs)),
            Patt::Compound(patt) => Dtor::Compound(loc, patt, rhs)
        }
    }

    fn from_init_opt(lhs: Patt<Id>, rhs: Option<Expr>) -> Result<Dtor, CompoundPatt<Id>> {
        match (lhs, rhs) {
            (Patt::Simple(id), rhs) => {
                Ok(Dtor::Simple(*id.tracking_ref(), id, rhs))
            }
            (Patt::Compound(patt), None) => Err(patt),
            (Patt::Compound(patt), Some(rhs)) => {
                Ok(Dtor::Compound(span(&patt, &rhs), patt, rhs))
            }
        }
    }
}