il

package
v0.0.0-...-fd0897c Latest Latest
Warning

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

Go to latest
Published: Apr 4, 2018 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package il implements the intermediate-language for the config-language interpreter of Mixer. The IL is designed as a 32-bit instruction set. The opcode/argument size of the IL is 32-bits and both are modeled as uint32s. Different instructions can have different number of arguments, but a given instruction will always have a well-defined number of arguments. Each argument can be 1 or 2 uint32s, depending on type.

The IL intrinsically supports the following basic primitive types:

  • String: represents a string value and maps to the native string Go type. Internally, the strings are interned in a StringTable, thus allowing extremely fast equality comparisons. The id of the string in the StringTable is encoded in the ByteCode, when stored, or during execution.
  • Bool: represents a boolean value and maps to the native bool Go type. The boolean values of false and true are represented as uint32(0) and uint32(1), respectively. The VM will consider any non-zero value as true, if it encounters during execution.
  • Integer: represents a signed integer value and maps to the native int64 Go type. The integer is stored in 2 uint32s internally.
  • Double: represents a signed float value and maps to the native float64 Go type. The double is stored in 2 uint32s internally.
  • Record represents a mapping of string-> string and maps to the map[string]string Go Type.

There is no constant representation of Record in il form.

  • Void represents no-value. This is typically used in the return type of a function, to indicate

that the function does not return a result.

In addition to these types, the VM inherently supports errors, based on Go errors. It is possible to raise these errors from within the IL. However, it is not possible to trap or return these as values. Once an error is raised, whether as a program instruction, or due to an invalid evaluation step, it bubbles all the way out of the evaluation context.

The execution model is based on an operand stack and registers. Though most operations work on an operand stack to perform calculations, it is possible to transfer data from registers to stack and vice-versa.

The IL supports a stack-based calling-convention. All the parameters to a function need to be pushed onto the stack before the CALL instruction is invoked. Similarly, the return values need to be pushed onto the stack when RET is called.

Typically, an IL based program is created by a compiler by initializing a Program type and by adding Functions to it, whose bodies are built using the Builder type. Once built, programs can be serialized/deserialized into a textual form for ease of use, using Write* and Read* method in this package.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BoolToByteCode

func BoolToByteCode(b bool) uint32

BoolToByteCode converts a Go bool to its byte-code form.

func ByteCodeToBool

func ByteCodeToBool(o uint32) bool

ByteCodeToBool extracts a Go bool from its byte-code form.

func ByteCodeToDouble

func ByteCodeToDouble(o1, o2 uint32) float64

ByteCodeToDouble extracts a Go float64 from its byte-code form.

func ByteCodeToInteger

func ByteCodeToInteger(o1, o2 uint32) int64

ByteCodeToInteger extracts a Go int64 from its byte-code form.

func DoubleToByteCode

func DoubleToByteCode(d float64) (uint32, uint32)

DoubleToByteCode converts a Go float64 to its byte-code form.

func IntegerToByteCode

func IntegerToByteCode(i int64) (uint32, uint32)

IntegerToByteCode converts a Go int64 to its byte-code form.

func MapGet

func MapGet(tVal interface{}, tStr string) (ret string, found bool)

MapGet abstracts over map[string]string and refcounted stringMap refcounted stringmaps are used by the protobag. standard maps are used by attribute producing adapters.

Types

type Builder

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

Builder is used for building function bodies in a programmatic way.

func NewBuilder

func NewBuilder(s *StringTable) *Builder

NewBuilder creates a new Builder instance. It uses the given StringTable when it needs to allocate ids for strings.

func (*Builder) AEQBool

func (f *Builder) AEQBool(v bool)

AEQBool appends the "ieq_b" instruction to the byte code.

func (*Builder) AEQDouble

func (f *Builder) AEQDouble(v float64)

AEQDouble appends the "ieq_d" instruction to the byte code.

func (*Builder) AEQInteger

func (f *Builder) AEQInteger(v int64)

AEQInteger appends the "eq_i" instruction to the byte code.

func (*Builder) AEQString

func (f *Builder) AEQString(v string)

AEQString appends the "ieq_s" instruction to the byte code.

func (*Builder) ALookup

func (f *Builder) ALookup(v string)

ALookup appends the "alookup" instruction to the byte code.

func (*Builder) ANLookup

func (f *Builder) ANLookup(v string)

ANLookup appends the "anlookup" instruction to the byte code.

func (*Builder) APushBool

func (f *Builder) APushBool(b bool)

APushBool appends the "apush_b" instruction to the byte code.

func (*Builder) APushDouble

func (f *Builder) APushDouble(n float64)

APushDouble appends the "apush_d" instruction to the byte code.

func (*Builder) APushInt

func (f *Builder) APushInt(i int64)

APushInt appends the "apush_i" instruction to the byte code.

func (*Builder) APushStr

func (f *Builder) APushStr(s string)

APushStr appends the "apush_s" instruction to the byte code.

func (*Builder) AllocateLabel

func (f *Builder) AllocateLabel() string

AllocateLabel allocates a new label value for use within the code.

func (*Builder) And

func (f *Builder) And()

And appends the "and" instruction to the byte code.

func (*Builder) Build

func (f *Builder) Build() []uint32

Build completes building a function body and returns the accumulated byte code.

func (*Builder) Call

func (f *Builder) Call(fnName string)

Call appends the "call" instruction to the byte code.

func (*Builder) EQBool

func (f *Builder) EQBool()

EQBool appends the "eq_b" instruction to the byte code.

func (*Builder) EQDouble

func (f *Builder) EQDouble()

EQDouble appends the "eq_d" instruction to the byte code.

func (*Builder) EQInteger

func (f *Builder) EQInteger()

EQInteger appends the "eq_i" instruction to the byte code.

func (*Builder) EQString

func (f *Builder) EQString()

EQString appends the "eq_s" instruction to the byte code.

func (*Builder) Jmp

func (f *Builder) Jmp(label string)

Jmp appends the "jmp" instruction to the byte code, against the given label.

func (*Builder) Jnz

func (f *Builder) Jnz(label string)

Jnz appends the "jnz" instruction to the byte code, against the given label.

func (*Builder) Jz

func (f *Builder) Jz(label string)

Jz appends the "jz" instruction to the byte code, against the given label.

func (*Builder) Lookup

func (f *Builder) Lookup()

Lookup appends the "lookup" instruction to the byte code.

func (*Builder) NLookup

func (f *Builder) NLookup()

NLookup appends the "nlookup" instruction to the byte code.

func (*Builder) Nop

func (f *Builder) Nop()

Nop appends the "nop" instruction to the byte code.

func (*Builder) Not

func (f *Builder) Not()

Not appends the "not" instruction to the byte code.

func (*Builder) Or

func (f *Builder) Or()

Or appends the "or" instruction to the byte code.

func (*Builder) ResolveBool

func (f *Builder) ResolveBool(n string)

ResolveBool appends the "resolve_b" instruction to the byte code.

func (*Builder) ResolveDouble

func (f *Builder) ResolveDouble(n string)

ResolveDouble appends the "resolve_d" instruction to the byte code.

func (*Builder) ResolveInt

func (f *Builder) ResolveInt(n string)

ResolveInt appends the "resolve_i" instruction to the byte code.

func (*Builder) ResolveInterface

func (f *Builder) ResolveInterface(n string)

ResolveInterface appends the "resolve_f" instruction to the byte code.

func (*Builder) ResolveString

func (f *Builder) ResolveString(n string)

ResolveString appends the "resolve_s" instruction to the byte code.

func (*Builder) Ret

func (f *Builder) Ret()

Ret appends the "ret" instruction to the byte code.

func (*Builder) SetLabelPos

func (f *Builder) SetLabelPos(label string)

SetLabelPos puts the label position at the current bytecode point that builder is pointing at. Panics if the label position was already set.

func (*Builder) TLookup

func (f *Builder) TLookup()

TLookup appends the "tlookup" instruction to the byte code.

func (*Builder) TResolveBool

func (f *Builder) TResolveBool(n string)

TResolveBool appends the "tresolve_b" instruction to the byte code.

func (*Builder) TResolveDouble

func (f *Builder) TResolveDouble(n string)

TResolveDouble appends the "tresolve_d" instruction to the byte code.

func (*Builder) TResolveInt

func (f *Builder) TResolveInt(n string)

TResolveInt appends the "tresolve_i" instruction to the byte code.

func (*Builder) TResolveInterface

func (f *Builder) TResolveInterface(n string)

TResolveInterface appends the "tresolve_f" instruction to the byte code.

func (*Builder) TResolveString

func (f *Builder) TResolveString(n string)

TResolveString appends the "tresolve_s" instruction to the byte code.

func (*Builder) Xor

func (f *Builder) Xor()

Xor appends the "xor" instruction to the byte code.

type Function

type Function struct {

	// Parameters is the type of the input parameters to the function.
	Parameters []Type

	// ReturnType is the return type of the function.
	ReturnType Type

	// ID is the id of the function. It is also the id of the name of the function in the strings table.
	ID uint32

	// Address is the address of the first opcode for the function within the bytecode.
	Address uint32

	// Length is the length of the function, in uint32s, within the bytecode.
	Length uint32
}

Function contains metadata about an IL-based function that is implemented in a program.

type FunctionTable

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

FunctionTable contains a set of functions, organized by their ids.

func (*FunctionTable) Get

func (t *FunctionTable) Get(name string) *Function

Get returns the function with the given name if it exists, or nil if not found.

func (*FunctionTable) GetByID

func (t *FunctionTable) GetByID(id uint32) *Function

GetByID returns the function with the given id, or nil if not found.

func (*FunctionTable) IDOf

func (t *FunctionTable) IDOf(name string) uint32

IDOf returns the id of a function with the given name, if it exists. Otherwise it returns 0.

func (*FunctionTable) Names

func (t *FunctionTable) Names() []string

Names returns the names of all the functions in the table.

type Opcode

type Opcode uint32

Opcode is the type for the opcodes in the il.

const (
	// Halt stops the VM with an error.
	Halt Opcode = 0

	// Nop does nothing.
	Nop Opcode = 1

	// Err raises an error.
	Err Opcode = 2

	// Errz pops a boolean value from stack and check its value. if the value is false, then it
	// raises an error.
	Errz Opcode = 3

	// Errnz pops a boolean value from stack and check its value. if the value is true, then it
	// raises an error.
	Errnz Opcode = 4

	// PopS pops a string from the stack.
	PopS Opcode = 10

	// PopB pops a bool from the stack.
	PopB Opcode = 11

	// PopI pops an integer from the stack.
	PopI Opcode = 12

	// PopD pops a double from the stack.
	PopD Opcode = 13

	// DupS pops a string value from the stack and pushes it back into the stack twice.
	DupS Opcode = 14

	// DupB pops a boolean value from the stack and pushes it back into the stack twice.
	DupB Opcode = 15

	// DupI pops an integer value from the stack and pushes it back into the stack twice.
	DupI Opcode = 16

	// DupD pops a double value from the stack and pushes it back into the stack twice.
	DupD Opcode = 17

	// RLoadS pops a string from the stack and stores in the target register.
	RLoadS Opcode = 20

	// RLoadB pops a bool from the stack and stores in the target register.
	RLoadB Opcode = 21

	// RLoadI pops an integer from the stack and stores in the target register.
	RLoadI Opcode = 22

	// RLoadD pops a double from the stack and stores in the target register.
	RLoadD Opcode = 23

	// ALoadS loads its string argument into the target register.
	ALoadS Opcode = 30

	// ALoadB loads its boolean argument into the target register.
	ALoadB Opcode = 31

	// ALoadI loads its integer argument into the target register.
	ALoadI Opcode = 32

	// ALoadD loads its double argument into the target register.
	ALoadD Opcode = 33

	// APushS pushes its string argument to the stack.
	APushS Opcode = 40

	// APushB pushes its boolean argument to the stack.
	APushB Opcode = 41

	// APushI pushes its integer argument to the stack.
	APushI Opcode = 42

	// APushD pushes its double argument to the stack.
	APushD Opcode = 43

	// RPushS reads a string value from the target register and pushes it into stack.
	RPushS Opcode = 50

	// RPushB reads a boolean value from the target register and pushes it into stack.
	RPushB Opcode = 51

	// RPushI reads an integer value from the target register and pushes it into stack.
	RPushI Opcode = 52

	// RPushD reads a double value from the target register and pushes it into stack.
	RPushD Opcode = 53

	// EqS pops two string values from the stack and compare for equality. If the strings are
	// equal then it pushes 1 into the stack, otherwise it pushes 0.
	EqS Opcode = 60

	// EqB pops two bool values from the stack and compare for equality. If equal, then it
	// pushes 1 into the stack, otherwise it pushes 0.
	EqB Opcode = 61

	// EqI pops two integer values from the stack and compare for equality. If equal, then it
	// pushes 1 into the stack, otherwise it pushes 0.
	EqI Opcode = 62

	// EqD pops two double values from the stack and compare for equality. If equal, then it
	// pushes 1 into the stack, otherwise it pushes 0.
	EqD Opcode = 63

	// AEqS pops a string value from the stack and compare it against its argument for equality.
	// If equal, then it pushes 1 into the stack, otherwise it pushes 0.
	AEqS Opcode = 70

	// AEqB pops a bool value from the stack and compare it against its argument for equality.
	// If equal, then it pushes 1 into the stack, otherwise it pushes 0.
	AEqB Opcode = 71

	// AEqI pops an integer value from the stack and compare it against its argument for equality
	// If equal, then it pushes 1 into the stack, otherwise it pushes 0.
	AEqI Opcode = 72

	// AEqD pops a double value from the stack and compare it against its argument for equality
	// If equal, then it pushes 1 into the stack, otherwise it pushes 0.
	AEqD Opcode = 73

	// Xor pops two boolean values from the stack, performs logical exclusive-or, then pushes the
	// result back into stack.
	Xor Opcode = 80

	// And pops two boolean values from the stack, performs logical and, then pushes the
	// result back into stack.
	And Opcode = 81

	// Or pops two boolean values from the stack, performs logical or, then pushes the
	// result back into stack.
	Or Opcode = 82

	// AXor pops a boolean value from the stack and performs logical exclusive-or with its
	// argument, then pushes the result back into stack.
	AXor Opcode = 83

	// AAnd pops a boolean value from the stack and performs logical and with its
	// argument, then pushes the result back into stack.
	AAnd Opcode = 84

	// AOr pops a boolean value from the stack and performs logical or with its
	// argument, then pushes the result back into stack.
	AOr Opcode = 85

	// Not pops a boolean value from the stack and performs logical not,
	// then pushes the result back into stack.
	Not Opcode = 86

	// ResolveS lookups up a string attribute value in the bag, with the given name.
	// If successful, pushes the resolved string into stack, otherwise raises error.
	ResolveS Opcode = 90

	// ResolveB lookups up a bool attribute value in the bag, with the given name.
	// If successful, pushes the resolved bool into stack, otherwise raises error.
	ResolveB Opcode = 91

	// ResolveI lookups up an integer attribute value in the bag, with the given name.
	// If successful, pushes the resolved integer into stack, otherwise raises error.
	ResolveI Opcode = 92

	// ResolveD lookups up a double attribute value in the bag, with the given name.
	// If successful, pushes the resolved double into stack, otherwise raises error.
	ResolveD Opcode = 93

	// ResolveF lookups up a interface{} attribute value in the bag, with the given name.
	// If successful, pushes the resolved interface{} into stack, otherwise raises error.
	ResolveF Opcode = 94

	// TResolveS lookups up a string attribute value in the bag, with the given name.
	// If successful, pushes the resolved string value, then 1 into the stack,
	// otherwise pushes 0.
	TResolveS Opcode = 100

	// TResolveB lookups up a  bool attribute value in the bag, with the given name.
	// If successful, pushes the resolved bool value, then 1 into the stack,
	// otherwise pushes 0.
	TResolveB Opcode = 101

	// TResolveI lookups up an integer attribute value in the bag, with the given name.
	// If successful, pushes the resolved integer value, then 1 into the stack,
	// otherwise pushes 0.
	TResolveI Opcode = 102

	// TResolveD lookups up a double attribute value in the bag, with the given name.
	// If successful, pushes the resolved double value, then 1 into the stack,
	// otherwise pushes 0.
	TResolveD Opcode = 103

	// TResolveF lookups up a interface{} attribute value in the bag, with the given name.
	// If successful, pushes the resolved interface{} value, then 1 into the stack,
	// otherwise pushes 0.
	TResolveF Opcode = 104

	// AddI pops two integer values from the stack, adds their value and pushes the result
	// back into stack. The operation follows Go's integer addition semantics.
	AddI Opcode = 110

	// AddD pops two double values from the stack, adds their value and pushes the result
	// back into stack. The operation follows Go's float addition semantics.
	AddD Opcode = 111

	// SubI pops two integer values from the stack, and subtracts the second popped value
	// from the first one, then pushes the result back into stack.
	// The operation follows Go's integer subtraction semantics.
	SubI Opcode = 112

	// SubD pops two double values from the stack, and subtracts the second popped value
	// from the first one, then pushes the result back into stack.
	// The operation follows Go's float subtraction semantics.
	SubD Opcode = 113

	// AAddI pops an integer value from the stack, adds the popped value and its argument,
	// and pushes the result back into stack. The operation follows Go's integer addition
	// semantics.
	AAddI Opcode = 114

	// AAddD pops a double value from the stack, adds the popped value and its argument,
	// and pushes the result back into stack. The operation follows Go's double addition
	// semantics.
	AAddD Opcode = 115

	// ASubI pops an integer value from the stack, subtracts its argument from the popped value,
	// then pushes the result back into stack.  The operation follows Go's integer subtraction
	// semantics.
	ASubI Opcode = 116

	// ASubD pops a double value from the stack, subtracts its argument from the popped value,
	// then pushes the result back into stack.  The operation follows Go's double subtraction
	// semantics.
	ASubD Opcode = 117

	// Jmp jumps to the given instruction address.
	Jmp Opcode = 200

	// Jz pops a bool value from the stack. If the value is zero, then jumps to the given
	// instruction address.
	Jz Opcode = 201

	// Jnz pops a bool value from the stack. If the value is not 0, then jumps to the given
	// instruction address.
	Jnz Opcode = 202

	// Call invokes the target function.
	Call Opcode = 203

	// Ret returns from the current function.
	Ret Opcode = 204

	// Lookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap
	// using the string as the name. If a value is found, then the value is pushed into the
	// stack.  Otherwise raises an error.
	Lookup Opcode = 210

	// TLookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap
	// using the string as the name. If a value is found, then the value is pushed into the
	// stack, then 1.  Otherwise 0 is pushed to into the stack.
	TLookup Opcode = 211

	// ALookup pops a stringmap from the stack and perform a lookup on the stringmap using the string
	// parameter as the name. If a value is found, then the value is pushed into the stack
	// Otherwise raises an error.
	ALookup Opcode = 212

	// NLookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap
	// using the string as the name. If a value is found, then the value is pushed into the
	// stack.  Otherwise empty string is pushed onto the stack.
	NLookup Opcode = 213

	// ANLookup pops a stringmap from the stack and perform a lookup on the stringmap using the string
	// parameter as the name. If a value is found, then the value is pushed into the stack
	// Otherwise empty string is pushed onto the stack.
	ANLookup Opcode = 214
)

func GetOpcode

func GetOpcode(text string) (Opcode, bool)

GetOpcode finds and returns the opcode that matches the keyword text that is supplied.

func (Opcode) Args

func (o Opcode) Args() []OpcodeArg

Args return the metadata about the arguments to the opcode.

func (Opcode) Keyword

func (o Opcode) Keyword() string

Keyword returns the keyword corresponding to the opcode.

func (Opcode) Size

func (o Opcode) Size() uint32

Size returns the total size the instruction and its arguments occupy, in uint32s.

func (Opcode) String

func (o Opcode) String() string

type OpcodeArg

type OpcodeArg int

OpcodeArg represents the type of the arguments that opcodes have.

const (
	// OpcodeArgRegister represents an argument that references a register.
	OpcodeArgRegister OpcodeArg = 0

	// OpcodeArgString represents an argument that is a string.
	OpcodeArgString OpcodeArg = 1

	// OpcodeArgInt represents an argument that is an integer.
	OpcodeArgInt OpcodeArg = 2

	// OpcodeArgDouble represents an argument that is a double.
	OpcodeArgDouble OpcodeArg = 3

	// OpcodeArgBool represents an argument that is a boolean.
	OpcodeArgBool OpcodeArg = 4

	// OpcodeArgFunction represents an argument that is a function.
	OpcodeArgFunction OpcodeArg = 5

	// OpcodeArgAddress represents an argument that is an address.
	OpcodeArgAddress OpcodeArg = 6
)

func (OpcodeArg) Size

func (o OpcodeArg) Size() uint32

Size returns the number of uint32 byte codes that the argument occupies.

type Program

type Program struct {

	// Functions is the collection of functions that are contained in the program.
	Functions *FunctionTable
	// contains filtered or unexported fields
}

Program is a self-contained IL based set of functions that can be executed by an interpreter.

func NewProgram

func NewProgram() *Program

NewProgram creates and returns a new, empty program.

func (*Program) AddExternDef

func (p *Program) AddExternDef(name string, parameters []Type, returnType Type)

AddExternDef adds a new external/native function to the program. The actual bodies of functions need to be supplied to the interpreter separately.

func (*Program) AddFunction

func (p *Program) AddFunction(name string, parameters []Type, returnType Type, body []uint32) error

AddFunction adds a new IL based function to the program.

func (*Program) ByteCode

func (p *Program) ByteCode() []uint32

ByteCode returns a copy of the byte-code of this program.

func (*Program) Strings

func (p *Program) Strings() *StringTable

Strings returns the strings table of this program.

type StringMap

type StringMap interface {
	Get(key string) (value string, found bool)
}

StringMap defines interface over map[string]string This is used for reference counting.

type StringTable

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

StringTable is a table that maps uint32 ids to strings and allows efficient storage of strings in IL.

func (*StringTable) Add

func (t *StringTable) Add(s string) uint32

Add adds the given string to the table, if it doesn't exit, and returns its id.

func (*StringTable) GetString

func (t *StringTable) GetString(id uint32) string

GetString returns the string with the given id, or empty string.

func (*StringTable) Size

func (t *StringTable) Size() int

Size returns the number of entries in the table.

func (*StringTable) TryGetID

func (t *StringTable) TryGetID(s string) uint32

TryGetID returns the id of the given string if it exists, or returns 0.

type Type

type Type uint32

Type represents a core type in the il system.

const (
	// Unknown represents a type that is unknown.
	Unknown Type = iota

	// Void represents the void type.
	Void

	// String represents the string type.
	String

	// Integer represents a 64-bit signed integer.
	Integer

	// Double represents a 64-bit signed floating point number.
	Double

	// Bool represents a boolean value.
	Bool

	// Duration represents a time.Duration value
	Duration

	// Interface represents a generic interface{} value
	Interface
)

func GetType

func GetType(name string) (Type, bool)

GetType returns the type with the given name, if it exists.

func (Type) String

func (t Type) String() string

Directories

Path Synopsis
Package interpreter implements an interpreter based runtime for the Mixer IL.
Package interpreter implements an interpreter based runtime for the Mixer IL.

Jump to

Keyboard shortcuts

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