agora: github.com/PuerkitoBio/agora/bytecode Index | Files | Directories

package bytecode

import "github.com/PuerkitoBio/agora/bytecode"

Package bytecode provides types and functions to encode to and decode from the binary bytecode representation of compiled agora code.

The complete reference of the bytecode format can be found in /doc/wiki/bytecode.md.

Index

Package Files

build.go decode.go doc.go encode.go file.go instr.go opcodes.go

Constants

const (
    AGORA_BUILD = "8405c1e"
)

Variables

var (
    // Predefined errors
    ErrVersionMismatch    = errors.New("the specified file version does not match the compiler's")
    ErrUnexpectedKValType = errors.New("unexpected constant value type")
    ErrInvalidKType       = errors.New("invalid constant type tag")
    ErrUnknownOpcode      = errors.New("unknown instruction opcode")
)
var (
    // The lookup table of Flag values to literal flag names
    FlagNames = [...]string{
        FLG__:  "_",
        FLG_K:  "K",
        FLG_V:  "V",
        FLG_F:  "F",
        FLG_A:  "A",
        FLG_N:  "N",
        FLG_T:  "T",
        FLG_An: "An",
        FLG_Jf: "Jf",
        FLG_Jb: "Jb",
        FLG_Sn: "Sn",
        FLG_Fn: "Fn",
    }

    // The lookup table of literal flag names to Flag values
    FlagLookup = map[string]Flag{
        "_":  FLG__,
        "K":  FLG_K,
        "V":  FLG_V,
        "F":  FLG_F,
        "A":  FLG_A,
        "N":  FLG_N,
        "T":  FLG_T,
        "An": FLG_An,
        "Jf": FLG_Jf,
        "Jb": FLG_Jb,
        "Sn": FLG_Sn,
        "Fn": FLG_Fn,
    }
)
var (
    // Lookup table of opcodes to literal name
    OpNames = [...]string{
        OP_RET:  "RET",
        OP_PUSH: "PUSH",
        OP_POP:  "POP",
        OP_ADD:  "ADD",
        OP_SUB:  "SUB",
        OP_MUL:  "MUL",
        OP_DIV:  "DIV",
        OP_MOD:  "MOD",
        OP_NOT:  "NOT",
        OP_UNM:  "UNM",
        OP_EQ:   "EQ",
        OP_NEQ:  "NEQ",
        OP_LT:   "LT",
        OP_LTE:  "LTE",
        OP_GT:   "GT",
        OP_GTE:  "GTE",
        OP_TEST: "TEST",
        OP_JMP:  "JMP",
        OP_NEW:  "NEW",
        OP_SFLD: "SFLD",
        OP_GFLD: "GFLD",
        OP_CFLD: "CFLD",
        OP_CALL: "CALL",
        OP_YLD:  "YLD",
        OP_RNGS: "RNGS",
        OP_RNGP: "RNGP",
        OP_RNGE: "RNGE",
        OP_DUMP: "DUMP",
    }

    // Loopup table of literal opcode names to Opcode value
    OpLookup = map[string]Opcode{
        "RET":  OP_RET,
        "PUSH": OP_PUSH,
        "POP":  OP_POP,
        "ADD":  OP_ADD,
        "SUB":  OP_SUB,
        "MUL":  OP_MUL,
        "DIV":  OP_DIV,
        "MOD":  OP_MOD,
        "NOT":  OP_NOT,
        "UNM":  OP_UNM,
        "EQ":   OP_EQ,
        "NEQ":  OP_NEQ,
        "LT":   OP_LT,
        "LTE":  OP_LTE,
        "GT":   OP_GT,
        "GTE":  OP_GTE,
        "TEST": OP_TEST,
        "JMP":  OP_JMP,
        "NEW":  OP_NEW,
        "SFLD": OP_SFLD,
        "GFLD": OP_GFLD,
        "CFLD": OP_CFLD,
        "CALL": OP_CALL,
        "YLD":  OP_YLD,
        "RNGS": OP_RNGS,
        "RNGP": OP_RNGP,
        "RNGE": OP_RNGE,
        "DUMP": OP_DUMP,
    }
)
var (
    // Predefined errors
    ErrInvalidData = errors.New("input data is not valid bytecode")
)

func IsBytecode Uses

func IsBytecode(rs io.ReadSeeker) bool

IsBytecode checks if the provided reader reads from a bytecode-encoded source. It checks if the agora bytecode signature is present at the start of the data.

func Version Uses

func Version() (int, int)

Version returns the major and minor version of the bytecode format.

type Decoder Uses

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

A Decoder reads a bytecode-encoded source into a structured representation in memory.

func NewDecoder Uses

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a Decoder that reads from the provided reader.

func (*Decoder) Decode Uses

func (dec *Decoder) Decode() (*File, error)

Decode reads the bytecode-encoded source into an in-memory data structure, and returns the File structure containing the translated bytecode, or an error.

type Encoder Uses

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

An encoder takes an in-memory representation of agora code and encodes it into the agora bytecode representation.

func NewEncoder Uses

func NewEncoder(w io.Writer) *Encoder

NewEncoder returns an Encoder that will write to the provided writer.

func (*Encoder) Encode Uses

func (enc *Encoder) Encode(f *File) (err error)

Encode encodes the provided in-memory File structure into the bytecode format, written to the encoder's writer. If an error is encountered, it is returned, otherwise it returns nil.

type File Uses

type File struct {
    Name         string
    MajorVersion int
    MinorVersion int
    Fns          []*Fn
}

A File is an in-memory representation of a bytecode file, as defined in /doc/bytecode.md.

func NewFile Uses

func NewFile(nm string) *File

NewFile returns a File structure initialized with the specified name and the current version.

type Flag Uses

type Flag byte

A Flag indicates the meaning of the index (or value) part of an instruction.

const (
    // The possible values of Flag
    FLG__    Flag = iota // Ignored
    FLG_K                // Constant table index
    FLG_V                // Variable table index
    FLG_F                // Function prototype index
    FLG_A                // Arguments array
    FLG_N                // Nil value
    FLG_T                // `this` keyword
    FLG_An               // Args count in a CALL or CFLD instruction
    FLG_Jf               // Jump forward over n instructions
    FLG_Jb               // Jump back over n instructions
    FLG_Sn               // Dump n frames
    FLG_Fn               // Set n fields
    FLG_INVL Flag = 0xFF // Invalid flag
)

func NewFlag Uses

func NewFlag(nm string) Flag

NewFlag returns the Flag value identified by the provided literal name, or the invalid Flag value if the name is unknown.

func (Flag) String Uses

func (f Flag) String() string

String returns the literal name corresponding to the current Flag value.

type Fn Uses

type Fn struct {
    Header H
    Ks     []*K
    Ls     []int64 // locals, as indexes into the K table
    Is     []Instr
}

A Fn is the representation of a single function in a bytecode file.

type H Uses

type H struct {
    Name       string
    StackSz    int64
    ExpArgs    int64
    ParentFnIx int64 // Lexical scope parent function, as index into the Fn table
    LineStart  int64
    LineEnd    int64
}

An H is the function header representation.

type Instr Uses

type Instr uint64

An Instr is an agora instruction to be executed by the virtual machine at runtime.

A bytecode instruction is a sequence of 64 bits arranged like this (a single letter=a byte): `ofvvvvvv` o: represents the opcode, on a single byte. See /bytecode/opcodes.go for the list of codes. f: indicates what the next value represents (Flag) v: represents the instruction's value (or index), on 6 bytes. Its meaning depends on the flag.

Gives a maximum possible value of 2^48.

func NewInstr Uses

func NewInstr(op Opcode, flg Flag, ix uint64) Instr

NewInstr returns an instruction value constructed from the provided opcode, flag and ix.

func (Instr) Flag Uses

func (i Instr) Flag() Flag

Flag returns the flag part of the instruction (the second most significant byte).

func (Instr) Index Uses

func (i Instr) Index() uint64

Index returns the index (or value) part of the instruction, that is, the 6 least significant bytes.

func (Instr) Opcode Uses

func (i Instr) Opcode() Opcode

Opcode returns the opcode part of the instruction (the most significant byte).

func (Instr) String Uses

func (i Instr) String() string

String returns a literal representation of the instruction.

type K Uses

type K struct {
    Type KType
    Val  interface{}
}

A K is the representation of a single constant value.

type KType Uses

type KType byte

The type tag that defines the constant's type.

const (
    // The possible constant types
    KtInteger KType = 'i'
    KtBoolean KType = 'b'
    KtFloat   KType = 'f'
    KtString  KType = 's'
)

type Opcode Uses

type Opcode byte

The opcode takes one byte, leaving 256 possible codes.

const (
    // The possible opcodes
    OP_RET  Opcode = iota // return
    OP_PUSH               // push a value onto the stack
    OP_POP                // pop a value from the stack
    OP_ADD                // add two values from the stack, push the result
    OP_SUB                // subtract two values from the stack, push the result
    OP_MUL                // multiply two values from the stack, push the result
    OP_DIV                // divide two values from the stack, push the result
    OP_MOD                // compute the modulo of two values from the stack, push the result
    OP_NOT                // boolean negation of one value from the stack, push the result
    OP_UNM                // unary minus of one value from the stack, push the result
    OP_EQ                 // check equality of two values from the stack, push the result
    OP_NEQ                // check non-equality of two values from the stack, push the result
    OP_LT                 // lower than on two values from the stack, push the result
    OP_LTE                // lower than or equal on two values from the stack, push the result
    OP_GT                 // greater than on two values from the stack, push the result
    OP_GTE                // greater than or equal on two values from the stack, push the result
    OP_TEST               // check the boolean value on top of the stack, if false jump n instructions
    OP_JMP                // perform an unconditional jump (forward or backward, depending on the flag)
    OP_NEW                // create and initialize a new object, push the result
    OP_SFLD               // set the value of an object's field, using 3 values from the stack (object variable, key and value)
    OP_GFLD               // get the value of an object's field, push the result, using 2 values from the stack (object variable and key)
    OP_CFLD               // call a method on an object, push the result, using 2 values + n arguments from the stack (object variable and key)
    OP_CALL               // call a function, push the result, using 1 value + n arguments from the stack
    OP_YLD                // yield a value for coroutine cooperative multitasking
    OP_RNGS               // range start
    OP_RNGP               // range push
    OP_RNGE               // range end

    OP_DUMP // print the execution context, if the Ctx is in debug mode

    OP_INVL Opcode = 0xFF // Invalid opcode
)

func NewOpcode Uses

func NewOpcode(nm string) Opcode

NewOpcode returns the opcode value corresponding to the provided name, or the invalid opcode if the name is unknown.

func (Opcode) String Uses

func (o Opcode) String() string

String returns the literal string representation of the opcode value, or the string representation of the opcode number if it is unknown.

Directories

PathSynopsis
testingPackage testing is for internal use only, it groups useful utility functions and variables to help in testing bytecode results.

Package bytecode imports 5 packages (graph) and is imported by 39 packages. Updated 2019-06-17. Refresh now. Tools for package owners.