Help us shape the future of Go! Take the 2026 Go Developer Survey

ir

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package ir is the compiler's intermediate representation, and everything that operates on it: Parse and Dump convert to and from the textual format (see ir-textual-format.md), Typecheck checks register types, Assemble lowers to a vm.Program. The grammar's AST is internal, so callers only see instructions.

Index

Constants

This section is empty.

Variables

View Source
var ErrProgramTooLarge = errors.New("program too large")

ErrProgramTooLarge is the assembler refusing a program whose instruction stream outgrows what a jump target can address — the encoding's uint16 operand limit. Like ErrRegisterBankOverflow, a capacity bound of the compiled engine, not a semantic rejection of the script.

View Source
var ErrRegisterBankOverflow = errors.New("register bank overflow")

ErrRegisterBankOverflow is the assembler refusing a program that needs more than maxReg simultaneously-live registers in one bank — the instruction encoding's one-byte operand limit. It is a capacity bound of the compiled engine, not a semantic rejection of the script.

Functions

func Assemble

func Assemble(instrs []Instr) (vm.Program, error)

func Dump

func Dump(code []Instr) string

Dump renders a program: labels flush-left, instructions indented.

func Parse

func Parse(src string) ([]Instr, []Error)

Parse reads an IR text into the instruction stream it describes.

It checks the grammar and everything the grammar can't express: that instructions exist and take the arguments they were given, that labels resolve and are unique, and that jumps go forward. It does not typecheck the registers — that's Typecheck.

func Typecheck

func Typecheck(instrs []Instr) error

Types

type AssertLeftover

type AssertLeftover struct {
	Portion Reg  // the allotment leftover (1 - sum of the given Portions)
	Exact   bool // no `remaining` clause: leftover must be exactly 0, else >= 0
}

func (AssertLeftover) String

func (i AssertLeftover) String() string

type AssertNonNegativeAmount

type AssertNonNegativeAmount struct{ Amount Reg } // int (a sent/saved amount, not tied to an account)

func (AssertNonNegativeAmount) String

func (i AssertNonNegativeAmount) String() string

type AssertNonNegativeBalance

type AssertNonNegativeBalance struct{ Balance, Account Reg } // int (the amount), str

func (AssertNonNegativeBalance) String

func (i AssertNonNegativeBalance) String() string

type AssertNonNegativePortion

type AssertNonNegativePortion struct{ Portion Reg } // portion (an allotment clause portion)

func (AssertNonNegativePortion) String

func (i AssertNonNegativePortion) String() string

type AssertSameAsset

type AssertSameAsset struct{ Left, Right Reg } // str, str

func (AssertSameAsset) String

func (i AssertSameAsset) String() string

type AssertUnscoped

type AssertUnscoped struct{ Scope, Account Reg } // str, str

func (AssertUnscoped) String

func (i AssertUnscoped) String() string

type AssertValidAccount

type AssertValidAccount struct{ Account Reg } // str

func (AssertValidAccount) String

func (i AssertValidAccount) String() string

type AssertValidColor

type AssertValidColor struct{ Color Reg } // str

func (AssertValidColor) String

func (i AssertValidColor) String() string

type AssertValidScope

type AssertValidScope struct{ Scope Reg } // str

func (AssertValidScope) String

func (i AssertValidScope) String() string

type BinKind

type BinKind interface {
	fmt.Stringer
	// contains filtered or unexported methods
}

type BinaryOp

type BinaryOp struct {
	Op                BinKind
	Dest, Left, Right Reg
}

func (BinaryOp) String

func (i BinaryOp) String() string

type Builder

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

Builder accumulates an instruction stream, handing out the registers and labels it needs.

func (*Builder) FreshLabel

func (b *Builder) FreshLabel(prefix string) Label

FreshLabel suffixes prefix with a counter: "inorder_end" -> #inorder_end_0.

func (*Builder) FreshReg

func (b *Builder) FreshReg() Reg

func (*Builder) Instrs

func (b *Builder) Instrs() []Instr

func (*Builder) Push

func (b *Builder) Push(instr Instr)

func (*Builder) PushWithDest

func (b *Builder) PushWithDest(getInstr func(dest Reg) Instr) Reg

PushWithDest allocates the register the instruction writes to. Allocating here rather than up front keeps registers numbered in emission order, which is what makes a Dump of the result parse back to the same program.

type CheckEnoughFunds

type CheckEnoughFunds struct{ Got, Needed Reg } // int

func (CheckEnoughFunds) String

func (i CheckEnoughFunds) String() string

type ConstBool

type ConstBool struct {
	Dest  Reg
	Value bool
}

ConstBool assembles to Op_ConstTrue or Op_ConstFalse: the value is in the opcode, so there is no pool entry.

func (ConstBool) String

func (i ConstBool) String() string

type Error

type Error struct {
	Range parser.Range
	Msg   string
}

Error is something wrong with an IR text: either the grammar rejected it, or it doesn't describe a well-formed instruction stream.

func (Error) Error

func (e Error) Error() string

type FetchBalance

type FetchBalance struct {
	Dest           Reg // int (the amount; the asset is the Asset operand)
	Account, Asset Reg // str, str
	Scope          *Reg

} // reads the run-state (impure)

func (FetchBalance) String

func (i FetchBalance) String() string

type Instr

type Instr interface {
	// contains filtered or unexported methods
}

type Jmp

type Jmp struct {
	Target Label
}

func (Jmp) String

func (i Jmp) String() string

type JmpIfFalse

type JmpIfFalse struct {
	Cond   Reg // bool
	Target Label
}

The two conditional jumps differ only in which edge of the bool jumps, so either branch of a condition is one instruction and no negation is needed.

func (JmpIfFalse) String

func (i JmpIfFalse) String() string

type JmpIfTrue

type JmpIfTrue struct {
	Cond   Reg // bool
	Target Label
}

func (JmpIfTrue) String

func (i JmpIfTrue) String() string

type Label

type Label string

func (Label) String

func (l Label) String() string

type LabelMarker

type LabelMarker struct{ Label Label }

func (LabelMarker) String

func (i LabelMarker) String() string

type LoadInt

type LoadInt struct {
	Dest  Reg
	Value big.Int
}

func (LoadInt) String

func (i LoadInt) String() string

type LoadStr

type LoadStr struct {
	Dest  Reg
	Value string
}

func (LoadStr) String

func (i LoadStr) String() string

type LoadVar

type LoadVar struct {
	Dest  Reg
	Typ   VarType
	Index uint16
}

func (LoadVar) String

func (i LoadVar) String() string

type MarkEnd

type MarkEnd struct{ Rewind bool }

MarkEnd closes the innermost region. Rewind undoes what it did; otherwise the region's pulls and postings are committed. Dumps as mark_rewind / mark_commit.

func (MarkEnd) String

func (i MarkEnd) String() string

type MarkPush

type MarkPush struct{} // opens a region at the current source-queue depth

The mark ops, used for oneof backtracking. Neither takes a register: the mark is a source-queue depth on a LIFO the run-state owns, so no operand can name a depth it never marked.

There is no "rewind but keep the mark" instruction: a retry is MarkEnd{Rewind: true} followed by a fresh MarkPush, which after the rollback yields a mark identical to the closed one. Mark depth is therefore a function of position in the instruction stream, so a verifier could decide statically that pushes and ends balance on every path, that no MarkEnd runs at depth 0, and that no SendToAccount, SetCurrentAsset or Save sits at depth > 0. No such pass exists yet — the VM enforces it at execution time — but keep emission verifiable: never emit a mark op on only one side of a branch.

func (MarkPush) String

func (i MarkPush) String() string

type MetaInt

type MetaInt struct{}

func (MetaInt) String

func (MetaInt) String() string

type MetaMonetary

type MetaMonetary struct {
	DestAsset  Reg // str
	DestAmount Reg // int
	Account    Reg // str
	Key        Reg // str
	Scope      *Reg
}

MetaMonetary is meta<monetary>: one store read yields both halves, so it is the only two-destination read and is not a MetaType.

func (MetaMonetary) String

func (i MetaMonetary) String() string

type MetaPortion

type MetaPortion struct{}

func (MetaPortion) String

func (MetaPortion) String() string

type MetaStr

type MetaStr struct{}

func (MetaStr) String

func (MetaStr) String() string

type MetaType

type MetaType interface {
	fmt.Stringer
	// contains filtered or unexported methods
}

type MetaVar

type MetaVar struct {
	Dest         Reg
	Account, Key Reg  // str, str
	Scope        *Reg // str
	Typ          MetaType
}

func (MetaVar) String

func (i MetaVar) String() string

type OpAddInt

type OpAddInt struct{}

func (OpAddInt) String

func (OpAddInt) String() string

type OpAddPortion

type OpAddPortion struct{}

func (OpAddPortion) String

func (OpAddPortion) String() string

type OpAddString

type OpAddString struct{}

func (OpAddString) String

func (OpAddString) String() string

type OpBoolCopy

type OpBoolCopy struct{}

func (OpBoolCopy) String

func (OpBoolCopy) String() string

type OpEqInt

type OpEqInt struct{}

func (OpEqInt) String

func (OpEqInt) String() string

type OpEqPortion

type OpEqPortion struct{}

func (OpEqPortion) String

func (OpEqPortion) String() string

type OpIntCopy

type OpIntCopy struct{}

One copy per register bank. A monetary has none: it is a (str, int) pair, so copying one is a str_copy plus an int_copy.

func (OpIntCopy) String

func (OpIntCopy) String() string

type OpIntToPortion

type OpIntToPortion struct{}

The two directions across the int/portion boundary. OpIntToPortion is exact; OpPortionToInt floors (big.Rat's denominator is always positive, so big.Int.Div is the floor). Together with OpMulPortion they are what an allotment share is made of.

func (OpIntToPortion) String

func (OpIntToPortion) String() string

type OpIntToString

type OpIntToString struct{}

func (OpIntToString) String

func (OpIntToString) String() string

type OpIsZero

type OpIsZero struct{}

OpIsZero projects an int onto a bool, which is how a quantity reaches a jump: the jumps take a bool, so the projection has to be explicit.

func (OpIsZero) String

func (OpIsZero) String() string

type OpLtInt

type OpLtInt struct{}

The comparisons: only `<` and `==`, per type. `>`, `<=`, `>=` and `!=` are front-end normalisations over these plus OpNot — see the table in internal/vm/instruction.go.

func (OpLtInt) String

func (OpLtInt) String() string

type OpLtPortion

type OpLtPortion struct{}

func (OpLtPortion) String

func (OpLtPortion) String() string

type OpMakePortion

type OpMakePortion struct{}

func (OpMakePortion) String

func (OpMakePortion) String() string

type OpMonetaryToString

type OpMonetaryToString struct{}

OpMonetaryToString takes the asset (str) and the amount (int) of a monetary and produces its "ASSET AMOUNT" form, the inverse of funds.ParseMonetary.

func (OpMonetaryToString) String

func (OpMonetaryToString) String() string

type OpMulPortion

type OpMulPortion struct{}

func (OpMulPortion) String

func (OpMulPortion) String() string

type OpNegInt

type OpNegInt struct{}

func (OpNegInt) String

func (OpNegInt) String() string

type OpNot

type OpNot struct{}

OpNot is the only bool -> bool operation.

func (OpNot) String

func (OpNot) String() string

type OpPortionCopy

type OpPortionCopy struct{}

func (OpPortionCopy) String

func (OpPortionCopy) String() string

type OpPortionToInt

type OpPortionToInt struct{}

func (OpPortionToInt) String

func (OpPortionToInt) String() string

type OpPortionToString

type OpPortionToString struct{}

func (OpPortionToString) String

func (OpPortionToString) String() string

type OpStrCopy

type OpStrCopy struct{}

func (OpStrCopy) String

func (OpStrCopy) String() string

type OpStrEq

type OpStrEq struct{}

OpStrEq yields a bool: it is the one comparison that produces a value rather than trapping, and what the jumps branch on.

func (OpStrEq) String

func (OpStrEq) String() string

type OpSubInt

type OpSubInt struct{}

func (OpSubInt) String

func (OpSubInt) String() string

type OpSubPortion

type OpSubPortion struct{}

func (OpSubPortion) String

func (OpSubPortion) String() string

type PullAccount

type PullAccount struct {
	Dest                         Reg  // int: amount pulled
	Account                      Reg  // str
	Cap, Overdraft, Color, Scope *Reg // int, int, str, str
}

func (PullAccount) String

func (i PullAccount) String() string

type Reg

type Reg uint

func (Reg) String

func (r Reg) String() string

type Save

type Save struct {
	Account Reg  // str
	Asset   Reg  // str
	Amount  *Reg // int; nil = save all
	Scope   *Reg // str
}

func (Save) String

func (i Save) String() string

type SendToAccount

type SendToAccount struct {
	Account, Cap, Scope *Reg // str, int, str
}

func (SendToAccount) String

func (i SendToAccount) String() string

type SetAccountMeta

type SetAccountMeta struct {
	Account, Key, Value Reg  // str, str, str
	Scope               *Reg // str
}

func (SetAccountMeta) String

func (i SetAccountMeta) String() string

type SetCurrentAsset

type SetCurrentAsset struct{ Asset Reg } // str

func (SetCurrentAsset) String

func (i SetCurrentAsset) String() string

type SetTxMeta

type SetTxMeta struct{ Key, Value Reg } // str, str

func (SetTxMeta) String

func (i SetTxMeta) String() string

type UnKind

type UnKind interface {
	fmt.Stringer
	// contains filtered or unexported methods
}

type UnaryOp

type UnaryOp struct {
	Op        UnKind
	Dest, Arg Reg
}

func (UnaryOp) String

func (i UnaryOp) String() string

type VarInt

type VarInt struct{}

func (VarInt) String

func (VarInt) String() string

type VarStr

type VarStr struct{}

func (VarStr) String

func (VarStr) String() string

type VarType

type VarType interface {
	fmt.Stringer
	// contains filtered or unexported methods
}

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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