vm

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: 9 Imported by: 0

Documentation

Overview

Package vm 是 waiton-script 子集的字节码虚拟机(§4.6 三级执行统一枢纽)。

对应 plugin-engine-draft.md §4.1/§4.6/§4.7:

  • 源码(字节缓冲区)经引擎前端编译为子集字节码(compiler)
  • 解释器以字节码为唯一输入(源码从不被直接解释)
  • AOT/JIT 都产出字节码并落盘索引缓存(gob 序列化,平台无关、跨架构复用)
  • 机器码(若有)仅运行期加速、永不落盘

选型:栈式 VM(§4.6「轻量」)。指令 = 1 字节 opcode + 可选操作数。 值复用 interp.Value(避免两套运行时值系统)。

Index

Constants

This section is empty.

Variables

View Source
var MaxSteps = 0

MaxSteps 执行步数上限(调试防死循环,0 = 不限)。临时。

View Source
var OpNames = map[Opcode]string{
	OpPushInt: "PUSH_INT", OpPushFloat: "PUSH_FLOAT", OpPushStr: "PUSH_STR",
	OpPushBool: "PUSH_BOOL", OpPushNone: "PUSH_NONE", OpDup: "DUP",
	OpLoadLocal: "LOAD_LOCAL", OpStoreLocal: "STORE_LOCAL",
	OpLoadSelf: "LOAD_SELF", OpStoreSelf: "STORE_SELF",
	OpPushScope: "PUSH_SCOPE", OpPopScope: "POP_SCOPE",
	OpJmp: "JMP", OpJmpIfFalse: "JMP_IF_FALSE", OpJmpIfTrue: "JMP_IF_TRUE",
	OpRet: "RET", OpRetNone: "RET_NONE",
	OpCall: "CALL", OpCallHost: "CALL_HOST", OpCallEng: "CALL_ENG",
	OpMakeVariant: "MAKE_VARIANT", OpMakeEnum: "MAKE_ENUM",
	OpAdd: "ADD", OpSub: "SUB", OpMul: "MUL", OpDiv: "DIV", OpMod: "MOD",
	OpEq: "EQ", OpNe: "NE", OpLt: "LT", OpGt: "GT", OpLe: "LE", OpGe: "GE",
	OpAnd: "AND", OpOr: "OR", OpNot: "NOT", OpNeg: "NEG", OpConcat: "CONCAT",
	OpMakeRecord: "MAKE_RECORD", OpGetField: "GET_FIELD", OpMakeRange: "MAKE_RANGE", OpMakeRecordSpread: "MAKE_RECORD_SPREAD",
	OpLenSlice: "LEN_SLICE", OpIndexSlice: "INDEX_SLICE", OpIndexRange: "INDEX_RANGE", OpMakeSlice: "MAKE_SLICE", OpMakeSliceSpread: "MAKE_SLICE_SPREAD",
	OpStoreIndex: "STORE_INDEX",
	OpSafePoint:  "SAFEPOINT", OpMatch: "MATCH", OpNop: "NOP", OpQuestion: "QUESTION",
}

OpNames 调试用指令名表。

View Source
var Trace = false

Trace 调试开关(导出,临时)。

Functions

func BinOp

func BinOp(op Opcode, l, r interp.Value) interp.Value

BinOp 按 op 分派二元运算(覆盖算术/比较/逻辑/拼接)。 与主 run 的 Op* 分支语义一致;非二元运算返回零值。供 bench 包自包含执行器复用。

func FuncMap

func FuncMap(file *ast.File) map[string]*ast.FuncDecl

FuncMap 顶层函数表(bench 专用):包装 vm_test 的 funcMap helper。 基准用 Env.SetFuncs 注入,使脚本函数调用可解析。

func IsTruthy

func IsTruthy(v interp.Value) bool

IsTruthy 真值判定(bench 专用):包装 isTruthyVal。

func NameOfSlot

func NameOfSlot(c *Code, slot uint16) string

NameOfSlot 槽位号 → 变量名(bench 专用):包装 nameOfSlot。

Types

type Block

type Block struct {
	Start int // 起始指令索引(Instrs 下标)
	End   int // 结束指令索引(不含,即块内 [Start, End))
	// Next 顺序后继块索引(无跳转的 fall-through),-1 表示无(块尾是返回/跳转)
	Next int
	// Jump 本块是否以条件跳转结尾:true 时 JumpTo 为「条件成立」目标块,
	// Next 为「条件不成立」的 fall-through 块;false 时 JumpTo 为无条件跳转目标
	// (Next 应为 -1)。
	Jump   bool
	JumpTo int // 跳转目标块索引
	// EndIdx 块尾跳转指令在 Instrs 的索引(OpJmp/OpJmpIfFalse/OpJmpIfTrue)
	JumpInstr int
	// Ret 本块是否以 RET/RET_NONE 结尾(函数出口)
	Ret bool
}

Block 一个基本块。

func BuildBlocks

func BuildBlocks(ins []Instr, entryOffsets []int) ([]Block, map[int]int)

BuildBlocks 把指令流划分为基本块(bench 专用):包装 buildBlocks。 返回块列表 + 每指令 → 块索引映射(与主 blocks.go 完全一致)。

type Code

type Code struct {
	// 常量池(平台无关、跨架构复用)
	Ints    []int64
	Floats  []float64
	Strings []string
	// 符号表
	Funcs  []FuncRef // 函数池
	Fields []string  // self/record 字段名表(LOAD_SELF/GET_FIELD 索引 → 名)
	Types  []string  // record/variant/enum 类型名表
	Enums  []string  // 枚举成员名表
	// 指令流
	Instrs []Instr
	// 函数入口表:函数名 → 指令流偏移
	Entry map[string]int
	// SlotNames 槽位 → 变量名(LOAD_LOCAL/STORE_LOCAL 的 A 索引解析)
	SlotNames []string
	// CallExprs 委托调用表达式表(OpCall/OpCallHost/OpCallEng 的 A 索引 → AST CallExpr,
	// 运行时委托 interp.EvalCall/EvalBuiltin/CallHostFunc 求值)
	CallExprs []ast.Expr
	// RecordFields record 构造字段名表(MAKE_RECORD 的 A 索引 → 字段名列表,正序)
	RecordFields [][]string
	// Matches match 描述符表(OpMatch 的 A 索引 → 描述符)。每个描述符描述一个
	// match 语句的 tag 分发:每 case 的 tag("_" 为通配)、payload 绑定变量名、
	// case body 入口偏移与 match 结束偏移(相对 OpMatch 指令位置)。
	Matches []MatchDesc
	// FallbackFuncs 需回落 interp 的函数集合(含未覆盖节点:match/record-lit/变参等)
	FallbackFuncs map[string]bool
	// contains filtered or unexported fields
}

Code 一段编译产物(统一枢纽:解释器输入 + AOT/JIT 落盘格式)。

func Compile

func Compile(file *ast.File) (*Code, error)

Compile 把 AST 文件编译为字节码(§4.1 前端:源码 → 字节码)。 返回的 Code 可被解释器执行,也可 gob 序列化落盘(AOT/JIT 索引缓存)。 含未覆盖节点(match/record-lit/变参/泛型调用等)的函数登记到 FallbackFuncs, 不生成字节码——执行时该函数整体回落 interp(语义不丢)。

func Decode

func Decode(b []byte) (*Code, error)

Decode 从字节反序列化 Code(gob)。 注意:CallExprs/RecordFields 依赖 AST,反序列化后为空,需调用方 (编译期)重新关联——纯字节码执行(无 AST)时这些指令会委托失败。 实际使用:Decode 后用于 inspect/缓存命中判定;执行仍需 AST(v1 混合模型)。

func (*Code) Disasm

func (c *Code) Disasm() string

Disasm 反汇编字节码为可读文本。调试用:查看编译产物、对比 AST/VM 语义、 定位跳转回填错误等。

func (*Code) Encode

func (c *Code) Encode() ([]byte, error)

Encode 把 Code 序列化为字节(gob,平台无关、跨架构复用,§4.6 落盘格式)。 AOT 提前编译的字节码经此落盘索引缓存;JIT 懒编译产物同样可落盘。

func (*Code) EntryOffsets

func (c *Code) EntryOffsets() []int

EntryOffsets 返回所有函数入口的指令偏移(bench 专用):包装 entryOffsets。

type FuncRef

type FuncRef struct {
	Name    string
	Pkg     string
	Host    bool
	Engine  bool
	Generic string
}

FuncRef 函数池条目(保留:未来函数池直接调用用)。

type Instr

type Instr struct {
	Op  Opcode
	A   uint16
	B   uint16
	Off int32
}

Instr 一条指令。操作数按指令语义解释:A/B 为 u16,Off 为跳转偏移(i32)。

type MatchDesc

type MatchDesc struct {
	// Tags 每 case 的 tag("_" 表示通配,匹配任意 subject)
	Tags []string
	// BindNames 每 case 的 payload 绑定变量名(如 int_val(i) 的 "i";无载荷 case 为空)。
	// 命中时 OpMatch 执行 env.Set(BindNames[j], subject.Payload[j])。
	BindNames [][]string
	// Entries 每 case body 入口相对 OpMatch 指令的偏移(pc += Entries[i] 落到 case body)
	Entries []int32
	// End 未命中任何 case 时跳转偏移(pc += End 落到 match 结束标记)
	End int32
}

MatchDesc 一条 match 语句的字节码描述(§4.6 三级执行:match variant 解构下沉)。

type Opcode

type Opcode byte

Opcode 字节码指令。1 字节。

const (
	// ── 值操作 ──
	OpPushInt   Opcode = iota // A: 整数常量池索引 → 压 int
	OpPushFloat               // A: 浮点常量池索引 → 压 float
	OpPushStr                 // A: 字符串常量池索引 → 压 string
	OpPushBool                // A: 0/1 → 压 bool
	OpPushNone                // → 压 none/unit
	OpDup                     // 栈顶复制

	// ── 局部变量 / 环境 ──
	OpLoadLocal  // A: 槽位 → 压局部变量
	OpStoreLocal // A: 槽位 ← 弹栈存储
	OpLoadSelf   // A: 字段索引 → 压 self.x
	OpStoreSelf  // A: 字段索引 ← 弹栈存储 self.x

	// ── 作用域 / 控制流 ──
	OpPushScope
	OpPopScope
	OpJmp        // Off: 无条件跳转(相对偏移)
	OpJmpIfFalse // Off: 栈顶为假则跳转
	OpJmpIfTrue  // Off: 栈顶为真则跳转
	OpRet        // 函数返回(栈顶为返回值)
	OpRetNone    // void 返回 none

	// ── 调用 ──
	OpCall        // A: 调用表达式索引(委托 interp.EvalCall)
	OpCallHost    // A: 调用表达式索引(委托 interp.EvalCall host 支)
	OpCallEng     // A: 调用表达式索引(委托 interp.EvalCall engine 支)
	OpMakeVariant // A: variant 类型索引, B: case 索引 → 构造 variant
	OpMakeEnum    // A: 类型索引, B: 成员索引 → 构造枚举值

	// ── 运算 ──
	OpAdd
	OpSub
	OpMul
	OpDiv
	OpMod
	OpEq
	OpNe
	OpLt
	OpGt
	OpLe
	OpGe
	OpAnd
	OpOr
	OpNot
	OpNeg
	OpConcat

	// ── 复合类型 ──
	OpMakeRecord       // A: record 构造索引, B: 类型索引 → 弹字段值构造 record
	OpGetField         // A: 字段索引 → 弹 record 压字段
	OpMakeRange        // 弹 lo, hi → 压 range
	OpMakeRecordSpread // A: 新字段名表索引, B: 类型索引(0xFFFF = 匿名构造继承 base)→ 弹新字段值 + 弹 base record → 复制字段 + 覆盖 → 新 record(2026-08-22 下沉)

	// ── 切片 ──
	OpLenSlice        // 栈顶 slice → 压长度(int)
	OpIndexSlice      // 弹 idx, slice → 压 slice[idx](2026-08-22 扩展 string 字节索引)
	OpIndexRange      // 弹 hi, lo, X → 压子切片/子串(2026-08-22 下沉)
	OpMakeSlice       // A: 元素个数 → 弹 n 元素 → 压 slice(2026-08-22 下沉)
	OpMakeSliceSpread // A: 元素个数 → 弹 n 元素 + 弹 spread slice → 压拼接 slice(2026-08-22 下沉)
	OpStoreIndex      // 弹 value, idx, slice → slice[idx] = value(原地写,2026-08-23 索引赋值)

	// ── 安全点 ──
	OpSafePoint // §8.7B 循环回边安全点检查

	// ── ? 错误传播 ──
	OpQuestion // ?(§4.3):弹 v——ok/some 解包 payload 继续;err/none 原值提前返回(跳 Off 到函数末尾 RET);非 variant 透传(2026-08-22 下沉)

	// ── match 解构 ──
	OpMatch // A: match 描述符索引 → 按 tag 分发到命中 case body(栈顶弹 subject)

	// ── 特殊 ──
	OpNop
)

type VM

type VM struct {

	// UseFast 是否使用直线执行器(runFast,§4.7 路线 B)。
	// 默认 false 走 run(解释器,稳定);true 走基本块直线执行。
	// benchmark/实验对比用;开启时测试全覆盖验证等价性。
	UseFast bool
	// contains filtered or unexported fields
}

VM 是子集字节码解释器(§4.6 统一枢纽的执行侧)。 混合模型:字节码承担表达式求值,函数调用回落 interp。

func NewVM

func NewVM(code *Code, file *ast.File, env *interp.Env) *VM

NewVM 创建 VM。env 为解释环境(含符号表/世界/输出缓冲)。

func (*VM) Exec

func (vm *VM) Exec(entryName string, self interp.Value) (interp.Value, error)

Exec 执行入口函数(main)。self 为 world 实例(main 有 self 参数时绑定,可为零值)。 返回函数返回值。 若入口函数登记为 FallbackFuncs(含未覆盖节点),委托 interp 执行(语义不丢)。

func (*VM) ExecArgs

func (vm *VM) ExecArgs(entryName string, self interp.Value, args []interp.Value) (interp.Value, error)

ExecArgs 执行入口函数并绑定参数(2026-08-22 C2 驻留脚本 VM 化用)。 普通参数按 fn.Params 顺序 Set 到 env(run 的槽位初始化从 env.vars 查参数值); self 单独 Set(LOAD_SELF 用);fallback 入口委托 CallFunc(self + 参数原样透传)。

Source Files

  • bench_api.go
  • blocks.go
  • compile.go
  • disasm.go
  • exec_fast.go
  • serialize.go
  • vm.go

Jump to

Keyboard shortcuts

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