use joker::word::Name;
use joker::track::{TrackingRef, TrackingMut, Untrack, Span};

use expr::Expr;
use decl::Dtor;
use patt::Patt;

#[derive(Debug, Eq, PartialEq, Clone, TrackingRef, TrackingMut)]
pub struct Id {
    pub location: Option<Span>,
    pub name: Name
}

impl Untrack for Id {
    fn untrack(&mut self) { self.location = None; }
}

pub trait IdExt {
    fn new(Name, Option<Span>) -> Id;
    fn into_patt(self) -> Patt<Id>;
    fn into_expr(self) -> Expr;
    fn into_dtor(self) -> Dtor;
}

impl IdExt for Id {
    fn new(name: Name, location: Option<Span>) -> Id {
        Id {
            location: location,
            name: name
        }
    }

    fn into_patt(self) -> Patt<Id> {
        Patt::Simple(self)
    }

    fn into_expr(self) -> Expr {
        Expr::Id(self)
    }

    fn into_dtor(self) -> Dtor {
        Dtor::Simple(*self.tracking_ref(), self, None)
    }
}

use std::ops::{Deref, DerefMut};
use joker::word::Name;
use joker::track::{TrackingRef, TrackingMut, Untrack, Span};

use expr::Expr;
use decl::Dtor;
use patt::Patt;

#[derive(Debug, Eq, PartialEq, Clone, TrackingRef, TrackingMut)]
pub struct Id {
    pub location: Option<Span>,
    pub name: Name
}

impl Deref for Id {
    type Target = Option<Span>;

    fn deref(&self) -> &Option<Span> {
        &self.location
    }
}

impl DerefMut for Id {
    fn deref_mut(&mut self) -> &mut Option<Span> {
        &mut self.location
    }
}

impl Untrack for Id {
    fn untrack(&mut self) { self.location = None; }
}

pub trait IdExt {
    fn new(Name, Option<Span>) -> Id;
    fn into_patt(self) -> Patt<Id>;
    fn into_expr(self) -> Expr;
    fn into_dtor(self) -> Dtor;
}

impl IdExt for Id {
    fn new(name: Name, location: Option<Span>) -> Id {
        Id {
            location: location,
            name: name
        }
    }

    fn into_patt(self) -> Patt<Id> {
        Patt::Simple(self)
    }

    fn into_expr(self) -> Expr {
        Expr::Id(self)
    }

    fn into_dtor(self) -> Dtor {
        Dtor::Simple(*self.tracking_ref(), self, None)
    }
}

--- 
+++ 
@@ -1,4 +1,3 @@
-use std::ops::{Deref, DerefMut};
 use joker::word::Name;
 use joker::track::{TrackingRef, TrackingMut, Untrack, Span};
 
@@ -10,20 +9,6 @@
 pub struct Id {
     pub location: Option<Span>,
     pub name: Name
-}
-
-impl Deref for Id {
-    type Target = Option<Span>;
-
-    fn deref(&self) -> &Option<Span> {
-        &self.location
-    }
-}
-
-impl DerefMut for Id {
-    fn deref_mut(&mut self) -> &mut Option<Span> {
-        &mut self.location
-    }
 }
 
 impl Untrack for Id {
Remove Id -> Option<Span> deref

This is somewhat implicit (not very obvious) way of coversion, and we
don't do this for any other types, so  I guess we should prefer API
consumer to get locations via explicit .tracking_ref() / .tracking_mut().
