Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

声明环境记录/函数环境记录/全局环境记录/对象环境记录/词法环境 #762

Open
cisen opened this issue Nov 10, 2019 · 0 comments

Comments

@cisen
Copy link
Owner

cisen commented Nov 10, 2019

总结

  • boa 源码相关 #758
  • 关系
    • 声明环境记录(基础)<-- Map<string, 声明环境值>
    • 函数环境记录 <-- Map<string, 声明环境记录>
    • 对象环境记录 <-- 词法环境记录
    • 词法环境记录 <-- VecDeque(GC(声明环境记录))
    • 全局环境记录 <- - 对象环境&声明环境

(基础)声明环境记录

// 单个值
pub struct DeclarativeEnvironmentRecordBinding {
    // 值
    pub value: Option<Value>,
    // 是否可删除
    pub can_delete: bool,
    // 可变
    pub mutable: bool,
    // 严格模式
    pub strict: bool,
}
// 整个声明环境记录
pub struct DeclarativeEnvironmentRecord {
    // 将所有变量存到hashmap里面
    pub env_rec: HashMap<String, DeclarativeEnvironmentRecordBinding>,
    // 指向外部环境
    pub outer_env: Option<Environment>,
}
/// 基础环境变量包括的方法
pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
    /// 确定环境记录是否具有字符串值N的绑定。如果有,则返回true,否则返回false。
    fn has_binding(&self, name: &str) -> bool;
    /// 在环境记录中创建一个新的但未初始化的可变绑定。 字符串值N是绑定名称的文本。
    /// 如果布尔参数删除为true,则可以随后删除绑定。
    fn create_mutable_binding(&mut self, name: String, deletion: bool);
    /// 在环境记录中创建一个新的但未初始化的不可变绑定。 字符串值N是绑定名称的文本。
    /// 如果strict为true,则无论初始化该绑定的操作的严格模式设置如何,在初始化它后尝试对其进行设置总是会引发异常。
    fn create_immutable_binding(&mut self, name: String, strict: bool) -> bool;
    /// 设置环境记录中已经存在但未初始化的绑定的值。 字符串值N是绑定名称的文本。 V是绑定的值,并且是任何ECMAScript语言类型的值。
    fn initialize_binding(&mut self, name: &str, value: Value);
    /// 设置环境记录中已经存在的可变绑定的值。 字符串值“名称”是绑定名称的文本。 value是绑定的“值”,并且可以是任何ECMAScript语言类型的值。
    ///  S是一个布尔型标志,如果`strict`为true并且不能设置绑定,则抛出TypeError异常。
    fn set_mutable_binding(&mut self, name: &str, value: Value, strict: bool);
    /// 返回环境记录中已经存在的绑定的值。 字符串值N是绑定名称的文本。 S用于标识源自严格模式代码或其他需要严格模式引用语义的引用。
    fn get_binding_value(&self, name: &str, strict: bool) -> Value;
    /// 从环境记录中删除绑定。 字符串值名称是绑定名称的文本。 如果存在名称绑定,请删除该绑定并返回true。
    /// 如果绑定存在但无法删除,则返回false。 如果绑定不存在,则返回true。
    fn delete_binding(&mut self, name: &str) -> bool;
    /// 确定环境记录是否建立了此绑定。 如果是,则返回true;否则,则返回false。
    fn has_this_binding(&self) -> bool;
    /// 确定环境记录是否建立了超级方法绑定。 如果是,则返回true;否则,则返回false。
    fn has_super_binding(&self) -> bool;
    /// 如果此环境记录与with语句关联,则返回with对象。 否则,返回未定义。
    fn with_base_object(&self) -> Value;

    /// Get the next environment up
    fn get_outer_environment(&self) -> Option<Environment>;

    /// Set the next environment up
    fn set_outer_environment(&mut self, env: Environment);

    /// Get the type of environment this is
    fn get_environment_type(&self) -> EnvironmentType;

    /// Fetch global variable
    fn get_global_object(&self) -> Option<Value>;
}
  • 该结构是“const”,“ let”,“class”,“module”,“import”,“函数声明”的基础环境
  • 该环境实现所有变量统一存储到map
    • 函数环境是在这个环境基础上加上下面的变量
  • 该结构的方法主要包括增删改查和初始化

函数环境记录

pub struct FunctionEnvironmentRecord {
    pub env_rec: HashMap<String, DeclarativeEnvironmentRecordBinding>,
    /// 给函数调用的this值
    pub this_value: Value,
    /// 如何是lex值,这是一个箭头函数,而且没有this值
    pub this_binding_status: BindingStatus,
    /// 调用导致创建此环境记录的函数对象。
    pub function_object: Value,
    /// 如果关联的函数具有超级属性访问权限,并且不是箭头函数,则[[HomeObject]]是该函数作为方法绑定到的对象。
    /// [[HomeObject]]的默认值是不确定的。
    pub home_object: Value,
    /// 如果此环境记录是通过[[Construct]]内部方法创建的,则[[NewTarget]]是[[Construct]] newTarget参数的值。
    /// 否则,其值是不确定的。
    pub new_target: Value,
    /// 需要引用外部环境以帮助作用域链,因为在我们知道外部环境是什么之前可以创建一些环境,所以需要选择类型
    pub outer_env: Option<Environment>,
}

pub enum BindingStatus {
    /// 如果是lexical,则说明这个是箭头函数而且没有this
    Lexical,
    /// 如果初始化完成,函数环境记录已经绑定this的值
    Initialized,
    /// 如果没有初始化完成,函数环境记录没有绑定this值
    Uninitialized,
}
  • 继承自声明环境记录
  • 包括的方法有
    • 增删改查初始化可变/不可变的binding
    • 通过outer_env获取/修改外部环境
    • 递归outer_env获取全局对象

对象环境变量

pub type Environment = Gc<GcCell<Box<dyn EnvironmentRecordTrait>>>;

pub struct ObjectEnvironmentRecord {
    pub bindings: Value,
    pub with_environment: bool,
    // 带GC的基础环境
    pub outer_env: Option<Environment>,
}
  • 就是基础环境再使用GC包裹一下

全局环境记录

pub struct GlobalEnvironmentRecord {
    // 对象
    pub object_record: Box<ObjectEnvironmentRecord>,
    pub global_this_binding: Value,
    // 普通的变量声明(let/const/function/object)等使用box
    pub declarative_record: Box<DeclarativeEnvironmentRecord>,
    // 对var声明的变量特殊处理,存储到set中
    pub var_names: HashSet<String>,
}

// 该环境拥有的特殊方法
impl GlobalEnvironmentRecord {
    pub fn get_this_binding(&self) -> Value {
    }

    pub fn has_var_declaration(&self, name: &str) -> bool {
    }

    pub fn has_lexical_declaration(&self, name: &str) -> bool {
    }

    pub fn has_restricted_global_property(&self, name: &str) -> bool {
    }

    pub fn create_global_var_binding(&mut self, name: String, deletion: bool) {
    }

    pub fn create_global_function_binding(&mut self, name: &str, value: Value, deletion: bool) {
    }
}
  • 包含对象环境记录/声明函数记录,var声明特殊存储set

词法环境

  • 就是词法作用域,由一对{}括号开辟
// 带GC的基础环境
pub type Environment = Gc<GcCell<Box<dyn EnvironmentRecordTrait>>>;

// 词法环境的类型
pub enum EnvironmentType {
    Declarative,
    Function,
    Global,
    Object,
}

// 函数作用域和块作用域
pub enum VariableScope {
    /// The variable declaration is scoped to the current block (`let` and `const`)
    Block,
    /// The variable declaration is scoped to the current function (`var`)
    Function,
}

// 词法环境栈/栈帧
pub struct LexicalEnvironment {
    environment_stack: VecDeque<Environment>,
}
  • 就是lexer生成tocken过程中的变量环境,有可能是声明/函数/全局/对象环境,可能包括块作用域或者函数作用域
  • 包含多个用GC封装的声明环境记录,用VecDeque存储
@cisen cisen changed the title 声明环境记录/函数环境记录/全局环境记录/对象环境记录 lex环境 声明环境记录/函数环境记录/全局环境记录/对象环境记录/词法环境 Nov 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant