engine

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MulanPSL-2.0 Imports: 23 Imported by: 0

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

View Source
const (
	WebHostLocal     = hostLocal     // 直播式:本机主播,浏览器全部只读
	WebHostFirstConn = hostFirstConn // 演示式:首个连接者为主持人,掉线移交
)

Variables

This section is empty.

Functions

func RegisterGDIPresenter

func RegisterGDIPresenter(e *Engine) error

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 CacheStats

type CacheStats struct {
	Hits   int
	Misses int
}

CacheStats 字节码缓存命中统计。

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 New

func New(stuck StuckConfig) *Engine

New 创建引擎实例。

func NewUIDemoEngine

func NewUIDemoEngine() (*Engine, *uiEngine)

NewUIDemoEngine 创建一个预置模拟 UI 渲染引擎的引擎实例(宿主互操作演示)。

func (*Engine) ActorCount

func (e *Engine) ActorCount() int64

ActorCount 返回当前存活 Actor 数。

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

func (e *Engine) LoadDir(dir string, worldArgs map[string]string) (string, error)

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

func (e *Engine) LoadDirVM(dir string, worldArgs map[string]string) (string, error)

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) NextID

func (e *Engine) NextID() int64

NextID 分配下一个 Actor ID。

func (*Engine) ReconcileNow

func (e *Engine) ReconcileNow(tomlPath, cborPath string)

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

func (e *Engine) RegisterHostFnVariadic(name string, fn interp.HostFn)

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

func (e *Engine) Registry() *registry.Registry

Registry 返回当前挂载的注册表(nil 表示未启用)。

func (*Engine) Scheduler

func (e *Engine) Scheduler() *Scheduler

Scheduler 返回引擎的调度器。

func (*Engine) SetCacheDir

func (e *Engine) SetCacheDir(dir string)

SetCacheDir 设置字节码缓存落盘目录(空 = 默认 .woscache/)。

func (*Engine) SetRegistry

func (e *Engine) SetRegistry(r *registry.Registry)

SetRegistry 挂载分层注册表(§9.6)。nil 可解除挂载。 启用后,后续 Load 系列会给每个脚本分配独立 realm 视图(写隔离)。

func (*Engine) SetSpawnHook

func (e *Engine) SetSpawnHook(hook func(ref *interp.ActorRef))

SetSpawnHook 设置 Actor 注册钩子(测试/宿主监控用)。

func (*Engine) SpawnFunc

func (e *Engine) SpawnFunc() func(ref *interp.ActorRef)

SpawnFunc 返回 interp.SpawnFunc 回调,注入到 Env 中。 引擎层通过此回调控制 Actor 注册到调度器。

func (*Engine) Start

func (e *Engine) Start()

Start 启动引擎(启动调度器事件循环)。幂等。

func (*Engine) StartReconciler

func (e *Engine) StartReconciler(every time.Duration, tomlPath, cborPath string) error

StartReconciler 启动对账协程(§9.3 对账循环):周期 + Trigger 触发 「期望态 config.toml ↔ 实际态注册表树」对账。需要已挂载注册表 (SetRegistry)。every<=0 表示仅手动 Trigger(ReconcileNow)触发。 tomlPath/cborPath 为空时用注册表自带路径。

func (*Engine) Stop

func (e *Engine) Stop(timeout time.Duration)

Stop 停止引擎:优雅关闭调度器,等待所有 Actor 完成。

func (*Engine) StopReconciler

func (e *Engine) StopReconciler()

StopReconciler 停止对账协程。

func (*Engine) WaitScheduler

func (e *Engine) WaitScheduler()

WaitScheduler 等待调度器事件循环退出(Stop 后)。

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 Priority

type Priority uint8

Priority 调度优先级(0=最高,255=最低,128=默认)。

const (
	PriorityMax     Priority = 0
	PriorityDefault Priority = 128
	PriorityMin     Priority = 255
)

type Scheduler

type Scheduler struct {
	// contains filtered or unexported fields
}

Scheduler 调度器(§8.7 Phase A:环缓冲+位图)。

原型期执行模型:Actor 由 goroutine 自驱动(interp engine.spawn 的 worker goroutine), 调度器不抢占执行,而是承担三件事:

  1. 就绪队列(环缓冲+位图):Actor 注册时按优先级入队,监控循环按优先级检查
  2. 看门狗:监控 Actor 总执行时长(从注册到完成/被杀),超阈值触发 stuck 策略
  3. 生命周期记账:activeCount 跟踪存活 Actor,Shutdown 等待回收

func NewScheduler

func NewScheduler(stuck StuckConfig) *Scheduler

NewScheduler 创建调度器。

func (*Scheduler) ActiveCount

func (s *Scheduler) ActiveCount() int64

ActiveCount 返回当前存活 Actor 数。

func (*Scheduler) Preempt

func (s *Scheduler) Preempt(ref *interp.ActorRef)

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

func (s *Scheduler) Schedule(ref *interp.ActorRef)

Schedule 将 Actor 注册到就绪队列(按 base_priority 入队)。 实现 interp.SpawnFunc 签名,由 interp 的 engine.spawn 调用。 若配置了步数配额(StepBudget > 0),注册时应用到 Actor(§8.7B)。

func (*Scheduler) Shutdown

func (s *Scheduler) Shutdown(timeout time.Duration)

Shutdown 优雅关闭调度器:等待所有 Actor 完成或超时。

type ScriptHandle

type ScriptHandle struct {
	// contains filtered or unexported fields
}

ScriptHandle 一个已加载的驻留脚本句柄(§3.6 反向调用)。 宿主经 LoadResident 获得,按名调用脚本导出函数。

func (*ScriptHandle) Call

func (h *ScriptHandle) Call(name string, args []interp.Value) (interp.Value, error)

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) Path

func (h *ScriptHandle) Path() string

Path 返回脚本来源文件路径(源码字符串形态为空)。

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 停止轮询。

func (*Watcher) Stop

func (w *Watcher) Stop()

Stop 停止 watch 轮询,等待轮询协程退出后返回。幂等。

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL