use std::fmt;
use std::cell::RefCell;
use std::rc::Rc;
use PType;
use Symbol;
use value::Value;
use sindra::{Type, Typed, Identifier};
use sindra::scope::{Scope, Scoped, MemoryScope, SymbolStore, MemoryStore};
use sindra::value::Coerce;
#[derive(Debug, Clone, PartialEq)]
pub struct Annotation {
scope: Option<Rc<RefCell<MemoryScope<Symbol, Value>>>>,
pub ty: Option<PType>,
pub promote_ty: Option<PType>,
}
impl Default for Annotation {
fn default() -> Annotation {
Annotation {
scope: None,
ty: None,
promote_ty: None,
}
}
}
impl Typed<PType> for Annotation {
fn ty(&self) -> Option<PType> { self.ty.clone() }
fn set_type(&mut self, ty: Option<PType>) { self.ty = ty; }
fn promote_type(&self) -> Option<PType> { self.promote_ty.clone() }
fn set_promote_type(&mut self, ty: Option<PType>) { self.promote_ty = ty; }
fn promoted(&self) -> Option<PType> { self.ty().map(|ty| ty.coerce(self.promote_type())) }
}
impl Scoped<MemoryScope<Symbol, Value>> for Annotation {
fn scope(&self) -> Option<Rc<RefCell<MemoryScope<Symbol, Value>>>> {
match self.scope {
Some(ref sc) => Some(Rc::clone(&sc)),
None => None
}
}
fn set_scope(&mut self, scope: Option<Rc<RefCell<MemoryScope<Symbol, Value>>>>) {
self.scope = scope;
}
}
impl SymbolStore<Symbol> for Annotation {
fn define(&mut self, ident: Identifier, symbol: Symbol) -> Option<Symbol> {
match self.scope {
Some(ref mut scope) => {
scope.borrow_mut().define(ident, symbol)
},
None => None
}
}
fn resolve(&self, ident: &Identifier) -> Option<Symbol> {
match self.scope {
Some(ref scope) => {
scope.borrow().resolve(ident)
},
None => None
}
}
}
impl MemoryStore<Value> for Annotation {
fn set(&mut self, ident: Identifier, value: Value) -> Result<Option<Value>, String> {
match self.scope {
Some(ref mut scope) => {
scope.borrow_mut().set(ident, value)
},
None => Err(format!("variable not found: {}", ident))
}
}
fn get(&self, ident: &Identifier) -> Option<Value> {
match self.scope {
Some(ref scope) => {
scope.borrow().get(ident)
},
None => None
}
}
}
impl fmt::Display for Annotation {
fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
match self.scope {
Some(ref sc) => {
write!(f, "scope:[")?;
write!(f, "{{table}}")?;
fn print_parents<T>(f: &mut fmt::Formatter,
parent: &Rc<RefCell<Scope<T>>>)
-> ::std::result::Result<(), fmt::Error> {
write!(f, "↑[")?;
write!(f, "{{table}}")?;
if let Some(ref p) = parent.borrow().parent {
print_parents(f, &p)?;
}
Ok(())
}
if let Some(ref parent) = sc.borrow().parent {
print_parents(f, &parent)?;
}
write!(f, "]")?;
},
None => {
write!(f, "scope:none")?;
}
};
match self.ty {
Some(ty) => { write!(f, " type:{}", ty.name()) },
None => { write!(f, " type:none") },
}
}
}