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

use crate::rc_ref::RcRef;
use crate::vm::isolate::IsolateRef;
use crate::vm::value::Value;


use std::rc::{ Rc, };
use std::cell::{ Cell, Ref, RefMut, RefCell, };
use std::collections::HashMap;


// https://www.ecma-international.org/ecma-262/9.0/index.html#sec-lexical-environments
#[derive(Debug)]
pub enum ScopeLevel {
    Top,      // outside any function, global
    Function, // 
    Class,    // Object
    Block,    // Local
    // Catch,
    // Try
}



pub type ScopeRef = RcRef<Scope>;


#[derive(Debug)]
pub struct Scope {
    isolate_ref: IsolateRef,
    parent: Option<ScopeRef>,
    record: HashMap<std::string::String, Value>,
}

impl Scope {
    pub fn new(isolate_ref: IsolateRef, parent: Option<ScopeRef>) -> Self {
        Scope {
            isolate_ref: isolate_ref,
            parent: parent,
            record: HashMap::new(),
        }
    }
    
    pub fn is_root(&self) -> bool {
        // Global
        self.parent.is_none()
    }

    pub fn isolate_ref(&self) -> &IsolateRef {
        &self.isolate_ref
    }

    pub fn parent(&self) -> &Option<ScopeRef> {
        &self.parent
    }

    pub fn get(&self, key: &str) -> Option<&Value> {
        self.record.get(key)
    }

    pub fn set(&mut self, key: std::string::String, val: Value) -> Option<Value> {
        self.record.insert(key, val)
    }
}


impl ScopeRef {
    pub fn is_root(&self) -> bool {
        self.borrow().is_root()
    }

    pub fn fork(&self) -> ScopeRef {
        let isolate_ref = self.borrow().isolate_ref().clone();
        let parent = self.clone();
        
        ScopeRef::new(Scope::new(isolate_ref, Some(parent)))
    }
}