1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! AST annotation structure and associated implementations.

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;

/// Annotation type for piske abstract syntax tree. Contains a symbol scope, memory scope,
/// and typing information.
#[derive(Debug, Clone, PartialEq)]
pub struct Annotation {
    /// The scope for a particular AST node
    scope: Option<Rc<RefCell<MemoryScope<Symbol, Value>>>>,
    /// The original inferred type for this AST node
    pub ty: Option<PType>,
    /// The promoted type for this AST node
    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:[")?;
                // for value in sc.borrow().item.into_iter() {
                //     write!(f, "{}", value)?;
                // }
                write!(f, "{{table}}")?;
                fn print_parents<T>(f: &mut fmt::Formatter,
                        parent: &Rc<RefCell<Scope<T>>>)
                        -> ::std::result::Result<(), fmt::Error> {
                    write!(f, "↑[")?;
                    // for value in parent.borrow().item.into_iter() {
                    //     write!(f, "{}", value)?;
                    // }
                    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") },
        }
    }
}