2.32. Context

Daslang 环境被组织到上下文中。编译 Daslang 程序会生成 ‘Program’ 对象,然后可以将其模拟到 ‘Context’ 中。

Context 包括
  • 名称和标志

  • 函数代码

  • 全局变量数据

  • 共享全局变量数据

  • 堆栈

  • 动态内存堆

  • 动态字符串堆

  • 常量字符串堆

  • 运行时调试信息

  • 其他查找基础设施

从某种意义上说, `Context`可以被视为 Daslang 虚拟机。它是负责执行代码并保持状态的对象。 它也可以被视为类的实例,当标记为 [export] 时可以访问这些方法。

函数代码、常量字符串堆、运行时调试信息和共享的全局变量在克隆的上下文之间共享。 这允许为 context 实例保留相对较小的配置文件。

可以选择在不同类型的多个上下文之间共享堆栈,以保持内存配置文件更小。

2.32.1. 初始化和关闭

在其生命周期中, Context 会经历初始化和关闭。 上下文初始化在 Context::runInitScript 中实现,关闭在 Context::runShutdownScript 中实现。 这些函数在创建、克隆和销毁 Context 时自动调用。 根据用户应用程序和 CodeOfPolicies,它们也可能在调用 Context::restartContext::restartHeaps 时被调用。

它按以下顺序初始化。
  1. 所有全局变量都按照每个模块的声明顺序进行初始化。

  2. 所有标记为 [init] 的函数都按照每个模块声明的顺序调用,特别排序的函数除外。

  3. 所有标记为 [init] 的特别排序的函数都按照它们在拓扑排序之后出现的顺序被调用。

init 函数的拓扑排序顺序在 init 注释中指定。
  • tag 属性指定函数将在指定传递期间出现

  • before 属性指定函数将出现在指定通道之前

  • after 属性指定函数将出现在指定通道之后

请考虑以下示例:

[init(before="middle")]
def a {
    order |> push("a")
}
[init(tag="middle")]
def b {
    order |> push("b")
}
[init(tag="middle")]
def c {
    order |> push("c")
}
[init(after="middle")]
def d {
    order |> push("d")
}
函数将按
  1. d

  2. b 或 c, 任意顺序

  3. a

Context关闭时按照每个模块声明的顺序运行所有标记为 [finalize] 的函数。

2.32.2. 宏Context

对于每个包含宏的模块,将创建并初始化单独的Context。 除了常规函数之外,在初始化期间还会调用标记为 [macro] 或 [_macro] 的函数。

标记为 [macro_function] 的函数将从常规Context中排除,并且仅显示在宏Context中。

除非宏模块被标记为共享,否则编译完成后会关闭。 共享宏模块在第一次编译期间初始化,并在环境关闭期间关闭。

2.32.3.

Context 包含 recursive_mutex,并且可以使用 lock_contextlock_this_context RAII 块进行专门锁定和解锁。 跨上下文调用 invoke_in_context 会自动锁定目标Context。

2.32.4. 查找

全局变量和函数可以在 Daslang 和 C++ 端按名称或损坏的名称哈希进行查找。

2.32.5. 内存分配和垃圾回收

字符串堆和常规堆的内存分配策略都在 CodeOfPolicies 中指定,以及选项。

要允许从上下文内部进行垃圾回收,以下选项是必需的:

options persistent_heap //  API 支持垃圾回收堆
options gc              //  API 为堆栈上的变量启用垃圾回收

要从上下文内部收集垃圾:

var collect_string_heap = true
var validate_after_collect = false
heap_collect(collect_string_heap, validate_after_collect)

从 C++ 端执行相同的作:

context->collectHeap(dummy_line_info_ptr, collect_string_heap, validate_after_collect);