goscript_parser/
scope.rs

1use super::ast::Node;
2use super::objects::*;
3use super::position;
4use std::collections::HashMap;
5use std::fmt;
6
7#[derive(Debug, Clone)]
8pub enum EntityKind {
9    Bad,
10    Pkg,
11    Con,
12    Typ,
13    Var,
14    Fun,
15    Lbl,
16}
17
18impl EntityKind {
19    pub fn kind_text(&self) -> &str {
20        match self {
21            EntityKind::Bad => "bad",
22            EntityKind::Pkg => "package",
23            EntityKind::Con => "const",
24            EntityKind::Typ => "type",
25            EntityKind::Var => "var",
26            EntityKind::Fun => "func",
27            EntityKind::Lbl => "label",
28        }
29    }
30}
31
32#[derive(Debug, Clone)]
33pub enum DeclObj {
34    Field(FieldKey),
35    Spec(SpecKey),
36    FuncDecl(FuncDeclKey),
37    LabeledStmt(LabeledStmtKey),
38    AssignStmt(AssignStmtKey),
39    NoDecl,
40}
41
42#[derive(Debug, Clone)]
43pub enum EntityData {
44    PkgScope(ScopeKey),
45    ConIota(isize),
46    NoData,
47}
48
49// An Entity describes a named language entity such as a package,
50// constant, type, variable, function (incl. methods), or label.
51#[derive(Debug, Clone)]
52pub struct Entity {
53    pub kind: EntityKind,
54    pub name: String,
55    pub decl: DeclObj,
56    pub data: EntityData,
57}
58
59impl Entity {
60    pub fn new(kind: EntityKind, name: String, decl: DeclObj, data: EntityData) -> Entity {
61        Entity {
62            kind: kind,
63            name: name,
64            decl: decl,
65            data: data,
66        }
67    }
68
69    pub fn with_no_data(kind: EntityKind, name: String, decl: DeclObj) -> Entity {
70        Entity::new(kind, name, decl, EntityData::NoData)
71    }
72
73    pub fn pos(&self, arena: &Objects) -> position::Pos {
74        match &self.decl {
75            DeclObj::Field(i) => i.pos(arena),
76            DeclObj::Spec(i) => arena.specs[*i].pos(arena),
77            DeclObj::FuncDecl(i) => arena.fdecls[*i].pos(arena),
78            DeclObj::LabeledStmt(i) => arena.l_stmts[*i].pos(arena),
79            DeclObj::AssignStmt(i) => arena.a_stmts[*i].pos(arena),
80            DeclObj::NoDecl => 0,
81        }
82    }
83}
84
85pub struct Scope {
86    pub outer: Option<ScopeKey>,
87    pub entities: HashMap<String, EntityKey>,
88}
89
90impl Scope {
91    pub fn new(outer: Option<ScopeKey>) -> Scope {
92        Scope {
93            outer: outer,
94            entities: HashMap::new(),
95        }
96    }
97
98    pub fn look_up(&self, name: &String) -> Option<&EntityKey> {
99        self.entities.get(name)
100    }
101
102    pub fn insert(&mut self, name: String, entity: EntityKey) -> Option<EntityKey> {
103        self.entities.insert(name, entity)
104    }
105
106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107        match write!(f, "scope {:p} {{\n", self) {
108            Err(e) => {
109                return Err(e);
110            }
111            Ok(_) => {}
112        };
113        for (k, _) in self.entities.iter() {
114            match write!(f, "\t{}\n", k) {
115                Err(e) => {
116                    return Err(e);
117                }
118                Ok(_) => {}
119            }
120        }
121        write!(f, "}}\n")
122    }
123}
124
125#[cfg(test)]
126mod test {
127    //use super::*;
128    //use generational_arena as ar;
129
130    /*
131    pub struct ScopeDebug<'a> {
132        scope: &'a Scope,
133        arena: &'a Arena<Entity>,
134    }
135
136    impl<'a> ScopeDebug<'a> {
137        fn new(scope: &'a Scope, arena: &'a Arena<Entity>) -> ScopeDebug<'a> {
138            ScopeDebug{scope: scope, arena: arena}
139        }
140    }
141
142    impl<'a> fmt::Debug for ScopeDebug<'a> {
143        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144            match write!(f, "scope {:p} {{\n", self.scope) {
145                Err(e) => { return Err(e); },
146                Ok(_) => {},
147            };
148            for (k, v) in self.scope.entities.iter() {
149                let entity = &self.arena[*v];
150                match write!(f, "\t{} {}\n", entity.kind.kind_text(), k) {
151                    Err(e) => { return Err(e); },
152                    Ok(_) => {},
153                }
154            };
155            write!(f, "}}\n")
156        }
157    }
158
159    pub fn insert_new<'a>(sel: &mut Scope, e: Entity, arena: &'a mut Arena<Entity>) ->
160        Option<&'a mut Entity> {
161        match sel.entities.get(&e.name) {
162            Some(&i) => arena.get_mut(i),
163            None => {
164                let name = e.name.to_string();
165                let index = arena.insert(e);
166                sel.entities.insert(name, index);
167                None
168            }
169        }
170    }
171    */
172
173    #[test]
174    fn test_scope() {
175        /*
176        let mut arena_s = ar::Arena::new();
177        let scope = Scope::new(None);
178        let s = arena_s.insert(scope);
179        let e = Entity::with_no_data(EntityKind::Fun, "test_entity".to_string(), DeclObj::NoDecl);
180        let mut arena = ar::Arena::new();
181        insert_new(&mut arena_s[s], e, &mut arena);
182
183        println!("scope: {:?}", ScopeDebug::new(&arena_s[s], &arena));
184        */
185    }
186}