Documentation
¶
Overview ¶
Package engine 是 waiton-script 运行时的引擎层(Supervisor Actor + 内嵌调度器)。
对应主设计文档 §8.7 Phase A(环缓冲+位图调度器)与 plugin-engine-draft.md §1.1/§5.1。 不做 Phase B(定时器安全点抢占),不做 Phase C(WIT 可插拔)。
架构:engine 导入 interp;interp 通过 Env.SpawnFunc 回调让 engine 控制 Actor 注册。 Scheduler 是独立的调度器组件,Engine 是顶层 Supervisor。
presenter_gdi_stub.go — GDI 呈现器非 Windows 占位(CI Linux 构建跳过 presenter_gdi.go;调用返回错误而非编译失败)。
Package engine 是 waiton-script 运行时的引擎层(Supervisor Actor + 内嵌调度器)。
对应主设计文档 §8.7 Phase A(环缓冲+位图调度器)与 plugin-engine-draft.md §1.1/§5.1。 不做 Phase B(定时器安全点抢占),不做 Phase C(WIT 可插拔)。
架构:engine 导入 interp;interp 通过 Env.SpawnFunc 回调让 engine 控制 Actor 注册。
Index ¶
- Constants
- func RegisterGDIPresenter(e *Engine) error
- func RegisterUIHost(e *Engine, ui *uiEngine)
- func RegisterWebPresenter(e *Engine, outDir string, mode WebHostMode) (string, error)
- type CacheStats
- type Engine
- func (e *Engine) ActorCount() int64
- func (e *Engine) HostFns() map[string]interp.HostBinding
- func (e *Engine) Load(buf []byte, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
- func (e *Engine) LoadDir(dir string, worldArgs map[string]string) (string, error)
- func (e *Engine) LoadDirVM(dir string, worldArgs map[string]string) (string, error)
- func (e *Engine) LoadFile(path string, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
- func (e *Engine) LoadFileVM(path string, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
- func (e *Engine) LoadResident(buf []byte, worldArgs map[string]string, opts ...interp.LoadOption) (*ScriptHandle, error)
- func (e *Engine) LoadResidentFile(path string, worldArgs map[string]string, opts ...interp.LoadOption) (*ScriptHandle, error)
- func (e *Engine) LoadVM(buf []byte, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
- func (e *Engine) NextID() int64
- func (e *Engine) ReconcileNow(tomlPath, cborPath string)
- func (e *Engine) RegisterHostFn(name string, sig []interp.HostSig, fn interp.HostFn, ...) error
- func (e *Engine) RegisterHostFnVariadic(name string, fn interp.HostFn)
- func (e *Engine) RegisterHostFnVariadicVersion(name string, version string, fn interp.HostFn, ...)
- func (e *Engine) RegisterHostFnVersion(name string, version string, sig []interp.HostSig, fn interp.HostFn, ...) error
- func (e *Engine) Registry() *registry.Registry
- func (e *Engine) Scheduler() *Scheduler
- func (e *Engine) SetCacheDir(dir string)
- func (e *Engine) SetRegistry(r *registry.Registry)
- func (e *Engine) SetSpawnHook(hook func(ref *interp.ActorRef))
- func (e *Engine) SpawnFunc() func(ref *interp.ActorRef)
- func (e *Engine) Start()
- func (e *Engine) StartReconciler(every time.Duration, tomlPath, cborPath string) error
- func (e *Engine) Stop(timeout time.Duration)
- func (e *Engine) StopReconciler()
- func (e *Engine) WaitScheduler()
- func (e *Engine) Watch(h *ScriptHandle, interval time.Duration, ...) *Watcher
- type Priority
- type Scheduler
- type ScriptHandle
- func (h *ScriptHandle) Call(name string, args []interp.Value) (interp.Value, error)
- func (h *ScriptHandle) Close() error
- func (h *ScriptHandle) EffectLog() []interp.EffectRecord
- func (h *ScriptHandle) ExportNames() []string
- func (h *ScriptHandle) HotReload(newSrc string) ([]string, int, error)
- func (h *ScriptHandle) Output() string
- func (h *ScriptHandle) Path() string
- func (h *ScriptHandle) ReloadFromFile() ([]string, int, error)
- func (h *ScriptHandle) ScriptID() string
- func (h *ScriptHandle) SetRevertMode(m interp.RevertMode)
- func (h *ScriptHandle) SetUnloadHandler(fn func(scriptID string))
- func (h *ScriptHandle) SetUnwindHandler(fn func(sig interp.UnwindSignal))
- func (h *ScriptHandle) Unload() error
- func (h *ScriptHandle) Version() int
- type StuckConfig
- type StuckPolicy
- type Watcher
- type WebHostMode
Constants ¶
const ( WebHostLocal = hostLocal // 直播式:本机主播,浏览器全部只读 WebHostFirstConn = hostFirstConn // 演示式:首个连接者为主持人,掉线移交 )
Variables ¶
This section is empty.
Functions ¶
func RegisterGDIPresenter ¶
RegisterGDIPresenter 非 Windows 平台返回错误(GDI 呈现器仅 Windows 可用)。
func RegisterUIHost ¶
func RegisterUIHost(e *Engine, ui *uiEngine)
RegisterUIHost 把模拟 UI 引擎注册进 host.ui.* 命名空间(§3.3.2)。 导出供 CLI 等外部入口演示宿主互操作;测试直接调用。
func RegisterWebPresenter ¶
func RegisterWebPresenter(e *Engine, outDir string, mode WebHostMode) (string, error)
RegisterWebPresenter 注册 Web 呈现器进 host.present.* 命名空间(§2 契约)。 outDir 为 HTML 输出目录(相对 cwd;不存在自动创建)。纯 Go 跨平台。 mode 选择多客户端主持人模式:WebHostLocal 直播式(本机主播,浏览器 只读,默认)或 WebHostFirstConn 演示式(首个连接者主持,掉线移交)。 返回本地页面 URL(浏览器打开可实时查看 + 事件交互)。
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine 是 waiton-script 运行时引擎(Supervisor Actor + 内嵌调度器)。 对应 plugin-engine-draft.md §1.1 / §5.1:引擎持有全部脚本 Actor、 监控状态、崩溃策略,并内嵌轻量调度器。
func NewUIDemoEngine ¶
func NewUIDemoEngine() (*Engine, *uiEngine)
NewUIDemoEngine 创建一个预置模拟 UI 渲染引擎的引擎实例(宿主互操作演示)。
func (*Engine) HostFns ¶
func (e *Engine) HostFns() map[string]interp.HostBinding
HostFns 返回宿主注册的 host 函数绑定表快照(加载时注入)。
func (*Engine) Load ¶
func (e *Engine) Load(buf []byte, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
Load 接受字节缓冲区(waiton-script 源码)加载执行(§1.4 / §6.1)。 这是引擎的统一加载入口:不绑定文件/目录,字节流直接进加载流程。 worldArgs 为注入的 world 字段(name->string 值,按需转换)。 宿主经 RegisterHostFn 注册的 host 函数自动注入本次加载(§3.3.2)。 opts 为加载期选项(§数据重要性分层:interp.WithTrustCap 信任上限等)。 2026-08-22 全面 VM:默认走字节码路径(LoadVM)——FallbackFuncs 清零后 全部表达式形态有字节码覆盖,语义与 AST 路径等价(parity 测试证明)。 目录包(LoadDir)与驻留(LoadResident)暂仍 AST(见各自注释)。
func (*Engine) LoadDir ¶
LoadDir 加载并执行一个目录(包根)下的 waiton-script 包(§2.6 包模型)。 2026-08-22 全面 VM:默认走字节码路径(LoadDirVM)——目录包合并符号后 vm.Compile(mainFile) + BuildEnv(pkg) + vm.Exec;跨包调用(lib.mymath.square) 走 OpCall 委托 interp.EvalCall(env 注入包符号表),use 子路径由 BuildEnv 的 loadPackage 解析——与 AST 路径语义等价。
func (*Engine) LoadDirVM ¶
LoadDirVM 字节码路径加载目录包(2026-08-22 全面 VM C1)。
func (*Engine) LoadFile ¶
func (e *Engine) LoadFile(path string, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
LoadFile 读取并加载一个 .wos 文件(文件形态:匿名 world 类型名 = 文件名去扩展名)。 2026-08-22 全面 VM:默认走字节码路径(LoadFileVM,含 AOT 缓存)。
func (*Engine) LoadFileVM ¶
func (e *Engine) LoadFileVM(path string, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
LoadFileVM 字节码路径加载 .wos 文件(文件形态:匿名 world 类型名 = 文件名去扩展名)。 AOT 编译 + 缓存 + vm.Exec 执行(语义与 LoadFile 的 AST 路径等价)。
func (*Engine) LoadResident ¶
func (e *Engine) LoadResident(buf []byte, worldArgs map[string]string, opts ...interp.LoadOption) (*ScriptHandle, error)
LoadResident 加载脚本为驻留形态(§3.6 反向调用):构建 env、收集 #export 导出表,不执行 main。宿主经返回句柄按名调用脚本导出函数(§3.6「按名字查 导出表」)。宿主注册的 host 函数(RegisterHostFn)自动注入本次加载。 用完须 Close() 回收(等待 spawn 的 actor 收尾)。 脚本自动分配唯一 script_id(script#N,§6.2 卸载信号携带),宿主可经 SetRevertMode 选择卸载回滚粒度(§9.5:默认 coarse)。 2026-08-22 C2 全面 VM:注入字节码执行回调(Call 走 vm.ExecArgs,编译失败 静默回退 AST——语义不丢)。
func (*Engine) LoadResidentFile ¶
func (e *Engine) LoadResidentFile(path string, worldArgs map[string]string, opts ...interp.LoadOption) (*ScriptHandle, error)
LoadResidentFile 加载 .wos 文件为驻留形态(§3.6)。文件形态:匿名 world 类型名 = 文件名去扩展名。支持 use <pkg> 跨文件引入。 2026-08-22 C2 全面 VM:注入字节码执行回调(同 LoadResident)。
func (*Engine) LoadVM ¶
func (e *Engine) LoadVM(buf []byte, worldArgs map[string]string, opts ...interp.LoadOption) (string, error)
LoadVM 字节码路径加载(§4.6 三级执行:AOT 编译 + JIT 缓存 + 解释执行)。 与 Load 语义一致(源码字符串形态,匿名 world 报错),但额外:
- 前端将源码编译为字节码(AOT),字节码存入内容寻址缓存(.woscache/,可复用跨进程)
LoadVM 字节码路径加载执行(§4.1 统一枢纽:源码→字节码→执行)。 AOT:编译为字节码并写入索引缓存(内容寻址 sha256 → .woscache/,gob 落盘)。 执行:buildEnv 构建运行时环境后,用 vm.Exec 执行字节码(含 fallback 到 interp)。 与 AST 路径(Load)语义等价——world 构造/host 注入/actor 生命周期一致。
返回输出与缓存统计(hits/misses/compiled funcs)。
func (*Engine) ReconcileNow ¶
ReconcileNow 手动触发一轮对账(同步执行)。未启动对账器也可用 (需已挂载注册表),等价于一次性对账注入 + 写回。
func (*Engine) RegisterHostFn ¶
func (e *Engine) RegisterHostFn(name string, sig []interp.HostSig, fn interp.HostFn, opts ...func(*interp.HostBinding)) error
RegisterHostFn 把宿主函数注册进引擎的 host 命名空间(§3.3.2 非 waiton 宿主支)。 等价 C ABI 版 engine_register_host_fn(engine, "host.print_line", &fn, HOST_SIG_2(STR, STR, VOID)):
- name:脚本侧完整限定名(§2.2 use 路径规则,如 "fs.read_file" / "time.now")
- sig:参数类型序列,最后一位是返回类型(interp.HostSig,语言无关编码)
- fn:宿主实现(Go 绑定,值级封送)
注册后在所有后续 Load/LoadFile 中生效(脚本 `use host` 后可调 host.<name>)。 同名重复注册覆盖(宿主运行时重配 host 命名空间,§8.1 Coeffect 拦截预留)。 opts 为注册选项(2026-08-22:interp.WithBlocking 阻塞型标注等,透传 Version 注册)。
func (*Engine) RegisterHostFnVariadic ¶
RegisterHostFnVariadic 注册变参宿主函数(§3.3.2 变参形态,如 print_line): 不按固定签名校验,实参求值后直接传给宿主实现。
func (*Engine) RegisterHostFnVariadicVersion ¶
func (e *Engine) RegisterHostFnVariadicVersion(name string, version string, fn interp.HostFn, opts ...func(*interp.HostBinding))
RegisterHostFnVariadicVersion §9.4 版本化变参注册。
func (*Engine) RegisterHostFnVersion ¶
func (e *Engine) RegisterHostFnVersion(name string, version string, sig []interp.HostSig, fn interp.HostFn, opts ...func(*interp.HostBinding)) error
RegisterHostFnVersion §9.4 版本化注册:带接口版本段。 version 如 "v1"/"v2"(空 = 无版本)。宿主可并行注册多版本, 脚本 `host.<pkg>.<vN>.<fn>` 显式绑定;drift 检测(接口哈希)据此进行。
func (*Engine) Registry ¶
Registry 返回当前挂载的注册表(nil 表示未启用)。
func (*Engine) SetCacheDir ¶
SetCacheDir 设置字节码缓存落盘目录(空 = 默认 .woscache/)。
func (*Engine) SetRegistry ¶
SetRegistry 挂载分层注册表(§9.6)。nil 可解除挂载。 启用后,后续 Load 系列会给每个脚本分配独立 realm 视图(写隔离)。
func (*Engine) SetSpawnHook ¶
SetSpawnHook 设置 Actor 注册钩子(测试/宿主监控用)。
func (*Engine) SpawnFunc ¶
SpawnFunc 返回 interp.SpawnFunc 回调,注入到 Env 中。 引擎层通过此回调控制 Actor 注册到调度器。
func (*Engine) StartReconciler ¶
StartReconciler 启动对账协程(§9.3 对账循环):周期 + Trigger 触发 「期望态 config.toml ↔ 实际态注册表树」对账。需要已挂载注册表 (SetRegistry)。every<=0 表示仅手动 Trigger(ReconcileNow)触发。 tomlPath/cborPath 为空时用注册表自带路径。
func (*Engine) Watch ¶
func (e *Engine) Watch(h *ScriptHandle, interval time.Duration, onReload func(names []string, version int), onError func(err error)) *Watcher
Watch 启动对 path 源文件的轮询 watch(§9.2 文件 watch 触发)。 检测到文件变更(mtime/大小)即对 h 执行 ReloadFromFile(原子热替换)。 interval 为轮询间隔(<=0 默认 500ms)。onReload 在每次成功热替换后回调 (入参为新导出表与版本号);onError 在 reload 失败时回调(错误保留旧版本)。 返回 Watcher 供 Stop。
注意:Watch 会占用 h,停止 watch 前请勿 Unload/Close h。
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler 调度器(§8.7 Phase A:环缓冲+位图)。
原型期执行模型:Actor 由 goroutine 自驱动(interp engine.spawn 的 worker goroutine), 调度器不抢占执行,而是承担三件事:
- 就绪队列(环缓冲+位图):Actor 注册时按优先级入队,监控循环按优先级检查
- 看门狗:监控 Actor 总执行时长(从注册到完成/被杀),超阈值触发 stuck 策略
- 生命周期记账:activeCount 跟踪存活 Actor,Shutdown 等待回收
func (*Scheduler) Preempt ¶
Preempt 置位指定 Actor 的安全点抢占标志(§8.7B)。 宿主可调用此方法请求让出某 Actor——Actor 在下个循环回边挂起,调度器稍后恢复。
func (*Scheduler) Run ¶
func (s *Scheduler) Run()
Run 启动调度器监控循环(阻塞,应在 goroutine 中运行)。
循环语义(原型期 goroutine 自驱动模型):
- 按优先级轮询就绪队列:检查每个 Actor 的执行状态(完成/取消/超时)
- 看门狗:从注册起算,执行超过 Threshold 的 Actor 触发 stuck 策略(kill/notify)
- 未完成的 Actor 重新入队(保持优先级轮询);完成的出队并回收计数
每次轮询空转间隔 10ms,避免 busy loop;Actor 注册时经 wakeCh 立即唤醒。
func (*Scheduler) Schedule ¶
Schedule 将 Actor 注册到就绪队列(按 base_priority 入队)。 实现 interp.SpawnFunc 签名,由 interp 的 engine.spawn 调用。 若配置了步数配额(StepBudget > 0),注册时应用到 Actor(§8.7B)。
type ScriptHandle ¶
type ScriptHandle struct {
// contains filtered or unexported fields
}
ScriptHandle 一个已加载的驻留脚本句柄(§3.6 反向调用)。 宿主经 LoadResident 获得,按名调用脚本导出函数。
func (*ScriptHandle) Call ¶
Call 按名调用脚本函数(§3.6 反向调用)。name 为脚本顶层函数名 (#export 导出或任意顶层函数);args 为实参(宿主 Go 侧构造 interp.Value)。
func (*ScriptHandle) Close ¶
func (h *ScriptHandle) Close() error
Close 回收脚本:等待 spawn 的 actor 收尾,句柄失效。
func (*ScriptHandle) EffectLog ¶
func (h *ScriptHandle) EffectLog() []interp.EffectRecord
EffectLog 返回当前 effect 痕迹日志(诊断;fine 模式才有内容)。
func (*ScriptHandle) ExportNames ¶
func (h *ScriptHandle) ExportNames() []string
ExportNames 返回脚本导出函数名列表(§3.6「按名字查导出表」)。
func (*ScriptHandle) HotReload ¶
func (h *ScriptHandle) HotReload(newSrc string) ([]string, int, error)
HotReload 以新源码热替换本脚本(§9.2 运行期 HMR)。 语义见 interp.Script.Reload:原子替换(校验失败保留旧版本)、状态迁移 (输出历史 + 并发状态经 shared 继承)、不发卸载信号(HMR 是替换不是卸载)。 成功后 version 递增;返回新导出表与当前版本号。
func (*ScriptHandle) Output ¶
func (h *ScriptHandle) Output() string
Output 返回脚本运行至今的输出缓冲内容(host.console 输出)。
func (*ScriptHandle) ReloadFromFile ¶
func (h *ScriptHandle) ReloadFromFile() ([]string, int, error)
ReloadFromFile 重新读取文件路径并热替换(§9.2 文件 watch 触发路径)。 仅 LoadResidentFile 形态(保存了 path)可用;源码字符串形态报错。
func (*ScriptHandle) ScriptID ¶
func (h *ScriptHandle) ScriptID() string
ScriptID 返回本脚本的 script_id(script#N,§6.2 卸载信号携带)。
func (*ScriptHandle) SetRevertMode ¶
func (h *ScriptHandle) SetRevertMode(m interp.RevertMode)
SetRevertMode 设置卸载回滚粒度(§9.5 可选开关)。默认 RevertCoarse。 RevertFine 启用 effect 痕迹日志(脚本每次调 host 函数记一条),卸载时按逆序 发细粒度卸载信号;RevertCoarse 不记日志、发一次粗粒度信号。
func (*ScriptHandle) SetUnloadHandler ¶
func (h *ScriptHandle) SetUnloadHandler(fn func(scriptID string))
SetUnloadHandler 注册粗粒度卸载回调(§6.2 on_script_unload)。 卸载时调用一次,入参为脚本 id;宿主凭自身资源账本整体回滚该脚本全部副作用。
func (*ScriptHandle) SetUnwindHandler ¶
func (h *ScriptHandle) SetUnwindHandler(fn func(sig interp.UnwindSignal))
SetUnwindHandler 注册细粒度逆序回调(§9.5 on_script_effect_unwind)。 卸载时按 effect 逆序调用多次,每次入参一条 interp.UnwindSignal; 宿主对每个信号执行对应逆操作(关定时器/关文件/注销回调)。 仅 RevertFine 模式下生效。
func (*ScriptHandle) Unload ¶
func (h *ScriptHandle) Unload() error
Unload 撤销脚本:按 revertMode 触发卸载信号(§6.2 粗 / §9.5 细), 然后回收(等待 spawn 的 actor 收尾,句柄失效)。 宿主撤销脚本 Actor 时调用(§6.2:引擎撤销某脚本 Actor 时向宿主发卸载信号)。
func (*ScriptHandle) Version ¶
func (h *ScriptHandle) Version() int
Version 返回脚本当前 HMR 版本号(§9.2)。初始 0,每次 HotReload 成功 +1。
type StuckConfig ¶
type StuckConfig struct {
Threshold time.Duration
Policy StuckPolicy
OnStuck func(actorID int64, elapsed time.Duration)
// StepBudget 步数配额(§8.7B):每个 Actor 每循环迭代扣 1,耗尽 → 安全点抢占终止;
// 0 = 不限(默认)。纯计算死循环的兜底(循环回边精确计数,不等总时长轮询)。
StepBudget int64
}
StuckConfig 看门狗配置。
type StuckPolicy ¶
type StuckPolicy int
StuckPolicy 看门狗 stuck 策略(§8.7)。
const ( StuckKill StuckPolicy = iota StuckRestart StuckNotify )
type Watcher ¶
type Watcher struct {
// contains filtered or unexported fields
}
Watcher 一个文件 watch 会话(§9.2 文件 watch 触发)。Stop 停止轮询。
type WebHostMode ¶
type WebHostMode = webHostMode
WebHostMode 导出别名(RegisterWebPresenter 参数;cmd/wos 等外部包使用)。
Source Files
¶
- engine.go
- hot_reload.go
- load.go
- presenter_gdi_stub.go
- presenter_web.go
- scheduler.go
- ui_engine.go
- vm_cache.go