bytecode

package
v0.0.0-...-485ca13 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2023 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

The bytecode package contains definitions that are used in the communication between the compiler and the virtual machine.

Index

Constants

View Source
const (
	// MaxConstants is the maximum number of constants we can have on a
	// CompiledStoryworld. This is equal to 2^31, so that it fits on an int even
	// on platforms that use 32-bit integers. And this number should be large
	// enough to ensure we don't run out of space for constants.
	MaxConstants uint32 = 2_147_483_648

	// CSWVersion is the current version of a Romualdo Compiled Storyworld.
	CSWVersion uint32 = 0
)
View Source
const (
	// DebugInfoVersion is the current version of a Romualdo DebugInfo.
	DebugInfoVersion uint32 = 0
)

Variables

View Source
var CSWMagic = []byte{0x52, 0x6D, 0x6C, 0x64, 0x43, 0x53, 0x57, 0x1A}

CSWMagic is the "magic number" identifying a Romualdo Compiled Storyworld. It is comprised of the "RmldCSW" string followed by a SUB character (which in times long gone used to represent a "soft end-of-file").

View Source
var DebugInfoMagic = []byte{0x52, 0x6D, 0x6C, 0x64, 0x44, 0x62, 0x67, 0x1A}

DebugInfoMagic is the "magic number" identifying a Romualdo DebugInfo. It is comprised of the "RmldDbg" string followed by a SUB character (which in times long gone used to represent a "soft end-of-file").

Functions

func DecodeInt32

func DecodeInt32(bytecode []byte) int

Decodes the first four bytes in bytecode into a signed 32-bit integer.

func DecodeUInt31

func DecodeUInt31(bytecode []byte) int

Decodes the first four bytes in bytecode into an unsigned 31-bit integer. Panics if the value read does not fit into 31 bits.

func EncodeInt32

func EncodeInt32(bytecode []byte, v int)

Encodes a signed 32-bit integer into the four first bytes of bytecode.

func EncodeUInt31

func EncodeUInt31(bytecode []byte, v int)

Encodes an unsigned 31-bit integer into the four first bytes of bytecode. Panics if v does not fit into 31 bits.

func ValuesEqual

func ValuesEqual(a, b Value) bool

ValuesEqual checks if a and b are considered equal.

Types

type Chunk

type Chunk struct {
	// The bytecode itself. Includes both OpCodes and immediate arguments needed
	// by the opcodes.
	Code []uint8
}

A Chunk is a chunk of bytecode. We'll have one Chunk for each procedure in a Storyworld.

TODO: In the future, one chunk for each version of each procedure.

TODO: In the future, probably, chunks for implicitly-defined procedures that initialize globals and stuff.

type CompiledStoryworld

type CompiledStoryworld struct {
	// Swid is the Storyworld ID. It is a free string that should uniquely
	// identify the Storyworld.
	Swid string

	// Swov is the Storyworld version. A negative value means that this is a
	// development version. A non-negative value means that this is a release
	// version. For example, if the currently released version of a Storyworld
	// is 3, the development version will be -4. When the development version
	// becomes stable, it will be released as version 4.
	//
	// A version equals to zero is invalid.
	Swov int32

	// The constant values used in all Chunks.
	Constants []Value

	// Chunks is a slice with all Chunks of bytecode containing the compiled
	// data. There is one Chunk for each procedure in the Storyworld.
	//
	// TODO: And in the future, one Chunk for every version of every procedure.
	Chunks []*Chunk

	// InitialChunk indexes the element in Chunks from where the Storyworld
	// execution starts. In other words, it points to the latest version of the
	// "/main" chunk.
	InitialChunk int
}

CompiledStoryworld is a compiled, binary version of a Romualdo Language Storyworld.

TODO: Use a string interner to avoid having duplicate strings in memory. Make some measurements to ensure it's really beneficial.

func (*CompiledStoryworld) AddConstant

func (csw *CompiledStoryworld) AddConstant(value Value) int

AddConstant adds a constant to the CompiledStoryworld and returns the index of the new constant into csw.Constants.

func (*CompiledStoryworld) Deserialize

func (csw *CompiledStoryworld) Deserialize(r io.Reader) error

Deserialize deserializes a CompiledStoryworld from the given io.Reader.

func (*CompiledStoryworld) DisassembleChunk

func (csw *CompiledStoryworld) DisassembleChunk(chunk *Chunk, out io.Writer, debugInfo *DebugInfo, chunkIndex int)

DisassembleChunk disassembles a whole chunk and writes the output to out. debugInfo is optional: if not nil, it will be used for better disassembly.

func (*CompiledStoryworld) DisassembleInstruction

func (csw *CompiledStoryworld) DisassembleInstruction(chunk *Chunk, out io.Writer, offset int, debugInfo *DebugInfo, chunkIndex int) int

DisassembleInstruction disassembles the instruction at a given offset of chunk and returns the offset of the next instruction to disassemble. Output is written to out. chunkIndex is the index of the current chunk. debugInfo is optional: if not nil, it will be used for better disassembly.

func (*CompiledStoryworld) SearchConstant

func (csw *CompiledStoryworld) SearchConstant(value Value) int

SearchConstant searches the constant pool for a constant with the given value. If found, it returns the index of this constant into csw.Constants. If not found, it returns a negative value.

func (*CompiledStoryworld) Serialize

func (csw *CompiledStoryworld) Serialize(w io.Writer) errs.Error

Serialize serializes the CompiledStoryworld to the given io.Writer.

type DebugInfo

type DebugInfo struct {
	// Swid is the Storyworld ID. It must match the corresponding field in
	// CompiledStoryworld.
	Swid string

	// Swov is the Storyworld version. It must match the corresponding field in
	// CompiledStoryworld.
	Swov int32

	// ChunksNames contains the names of the procedures on a CompiledStoryworld.
	// There is one entry for each entry in the corresponding
	// CompiledStoryworld.Chunks.
	ChunksNames []string

	// ChunksSourceFiles contains the source files every Chunk was compiled
	// from. The indices here match those in CompiledStoryworld.Chunks. The file
	// names here contain the path from the root of the Storyworld.
	ChunksSourceFiles []string

	// ChunksLines contains the source code line that generated each instruction
	// of each Chunk. This must be interpreted like this:
	// ChunksLines[chunkIndex][codeIndex] contains the line that generated the
	// bytecode at CompiledStoryworld.Chunks[chunkIndex].Code[codeIndex].
	//
	// Notice that we have one entry for each entry in Code. Very
	// space-inefficient, but very simple.
	//
	// TODO: Use run-length encoding (RLE) or something like that to spare some
	// memory and storage.
	ChunksLines [][]int
}

DebugInfo contains debug information matching a CompiledStoryworld. All information that is not strictly necessary to run a Storyworld but is useful for debugging, producing better error reporting, etc, belongs here.

func (*DebugInfo) Deserialize

func (di *DebugInfo) Deserialize(r io.Reader) errs.Error

func (*DebugInfo) Serialize

func (di *DebugInfo) Serialize(w io.Writer) errs.Error

romutil.Serializer and romutil.Deserializer interfaces

Serialize serializes the DebugInfo to the given io.Writer.

type Lecture

type Lecture struct {
	// Text is the text of the Lecture.
	Text string
}

Lecture is the runtime representation of a Lecture. Lectures are just strings, but we wrap them in a struct so that we can differentiate between strings and Lectures.

type OpCode

type OpCode uint8

OpCode is an opcode in the Romualdo Virtual Machine.

const (
	OpNop OpCode = iota
	OpConstant
	OpSay
	OpListen
	OpPop
	OpTrue
	OpFalse
	OpJumpIfFalse
	OpJump
	OpEqual
	OpNotEqual
	OpToString
	OpToLecture
)

type Procedure

type Procedure struct {
	// ChunkIndex points to the Chunk that contains this function's bytecode.
	// It's an index into the CompiledStoryworld slice of Chunks.
	ChunkIndex int
}

Procedure is the runtime representation of a Procedure (i.e., a Passage or a Function). We don't include any sort of information about return and parameter types because type-checking is all done statically at compile-time.

type Value

type Value struct {
	Value interface{}
}

Value is a Romualdo language value.

func DeserializeValue

func DeserializeValue(r io.Reader) (Value, errs.Error)

DeserializeValue deserializes a Value from the given io.Reader.

func NewValueBool

func NewValueBool(value bool) Value

NewValueBool creates a new Value of type bool, representing a Boolean with the given value.

func NewValueLecture

func NewValueLecture(text string) Value

NewValueLecture creates a new Value of type Lecture, representing a Lecture with the given text.

func NewValueProcedure

func NewValueProcedure(index int) Value

NewValueProcedure creates a new Value of type Procedure, representing a Procedure that will run the code at the given Chunk index.

func NewValueString

func NewValueString(text string) Value

NewValueString creates a new Value of type string, representing a string with the given text.

func (Value) AsBool

func (v Value) AsBool() bool

AsBool returns this Value's value, assuming it is a Boolean value.

func (Value) AsLecture

func (v Value) AsLecture() Lecture

AsLecture returns this Value's value, assuming it is a Lecture value.

func (Value) AsProcedure

func (v Value) AsProcedure() Procedure

AsProcedure returns this Value's value, assuming it is a Procedure value.

func (Value) AsString

func (v Value) AsString() string

AsString returns this Value's value, assuming it is a string value.

func (Value) DebugString

func (v Value) DebugString(debugInfo *DebugInfo) string

DebugString converts the value to a string usable in debug contexts. debugInfo can be nil (but this will result in less information in the resulting strings).

func (Value) IsBool

func (v Value) IsBool() bool

IsBool checks if the value contains a Boolean value.

func (Value) IsLecture

func (v Value) IsLecture() bool

IsLecture checks if the value contains a Lecture value.

func (Value) IsProcedure

func (v Value) IsProcedure() bool

IsProcedure checks if the value contains a Procedure value.

func (Value) IsString

func (v Value) IsString() bool

IsString checks if the value contains a string value.

func (Value) Serialize

func (v Value) Serialize(w io.Writer) errs.Error

Serialize serializes the Value to the given io.Writer.

func (Value) String

func (v Value) String() string

String converts the value to a string. This is also used by the VM to convert values to strings, so the output must be user-friendly.

type ValueKind

type ValueKind int

A ValueKind represents one of the types a value in the Romualdo Virtual Machine can have. This is the type from the perspective of the VM (in the sense that user-defined types are obviously not directly represented here). We use "kind" in the name because "type" is a keyword in Go.

const (
	// ValueBool identifies a Boolean value.
	ValueBool ValueKind = iota

	// ValueString identifies a string value.
	ValueString

	// ValueLecture identifies a Lecture value.
	ValueLecture

	// ValueProcedure identifies a procedure value (either a Passage or a
	// Function).
	ValueProcedure
)

Jump to

Keyboard shortcuts

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