Documentation ¶
Index ¶
Constants ¶
const ( INTEGER_OBJ = "INTEGER" BOOLEAN_OBJ = "BOOLEAN" NULL_OBJ = "NULL" RETURN_VALUE_OBJ = "RETURN_VALUE" ERROR_OBJ = "ERROR" FUNCTION_OBJ = "FUNCTION" STRING_OBJ = "STRING" BUILTIN_OBJ = "BUILTIN" ARRAY_OBJ = "ARRAY" HASH_OBJ = "HASH" COMPILED_FUNCTION_OBJ = "COMPILED_FUNCTION_OBJ" CLOSURE_OBJ = "CLOSURE" )
Variables ¶
var Builtins = []struct { Name string Builtin *Builtin }{ { "len", &Builtin{ Fn: func(args ...Object) Object { if len(args) != 1 { return newError("wrong number of arguments. got=%d, want=1", len(args)) } switch arg := args[0].(type) { case *Array: return &Integer{Value: int64(len(arg.Elements))} case *String: return &Integer{Value: int64(len(arg.Value))} default: return newError("argument to `len` not supported, got=%s", args[0].Type()) } }, }, }, { "puts", &Builtin{ Fn: func(args ...Object) Object { for _, arg := range args { fmt.Println(arg.Inspect()) } return nil }, }, }, { "first", &Builtin{ Fn: func(args ...Object) Object { if len(args) != 1 { return newError("wrong number of arguments. got=%d, want=1", len(args)) } if args[0].Type() != ARRAY_OBJ { return newError("argument to `first` must be ARRAY, got %s", args[0].Type()) } arr := args[0].(*Array) if len(arr.Elements) > 0 { return arr.Elements[0] } return nil }, }, }, { "last", &Builtin{ Fn: func(args ...Object) Object { if len(args) != 1 { return newError("wrong number of arguments. got=%d, want=1", len(args)) } if args[0].Type() != ARRAY_OBJ { return newError("argument to `last` must be ARRAY, got %s", args[0].Type()) } arr := args[0].(*Array) length := len(arr.Elements) if length > 0 { return arr.Elements[length-1] } return nil }, }, }, { "rest", &Builtin{ Fn: func(args ...Object) Object { if len(args) != 1 { return newError("wrong number of arguments. got=%d, want=1", len(args)) } if args[0].Type() != ARRAY_OBJ { return newError("argument to `rest` must be ARRAY, got %s", args[0].Type()) } arr := args[0].(*Array) length := len(arr.Elements) if length > 0 { newElements := make([]Object, length-1, length-1) copy(newElements, arr.Elements[1:length]) return &Array{Elements: newElements} } return nil }, }, }, { "push", &Builtin{ Fn: func(args ...Object) Object { if len(args) != 2 { return newError("wrong number of arguments. got=%d, want=2", len(args)) } if args[0].Type() != ARRAY_OBJ { return newError("argument to `push` must be ARRAY, got %s", args[0].Type()) } arr := args[0].(*Array) length := len(arr.Elements) newElements := make([]Object, length+1, length+1) copy(newElements, arr.Elements) newElements[length] = args[1] return &Array{Elements: newElements} }, }, }, }
Builtins contains a mapping of the supported built-in functions.
Functions ¶
This section is empty.
Types ¶
type Array ¶
type Array struct {
Elements []Object
}
Array is the referenced struct for Array Literals in our object system. The struct holds the evaluated elements of the array literal
func (*Array) Inspect ¶
Inspect will construct the Array as a string by stringifying its elements, and concatenating them into the expected array format.
func (*Array) Type ¶
func (ao *Array) Type() ObjectType
Type returns the ObjectType (ARRAY_OBJ) associated with the referenced Array struct
type Boolean ¶
type Boolean struct {
Value bool // the evaluated value
}
Boolean is the referenced struct for Boolean Literals in our object system. The struct holds the evaluated value of the Boolean Literal.
func (*Boolean) HashKey ¶
HashKey constructs a boolean hash-key for a Hash. The hash-key can be a binary of 1 or 0 depending on the Boolean's Value (true or false). This HashKey struct will be used as a key in the evaluated Hash Literal.
func (*Boolean) Type ¶
func (b *Boolean) Type() ObjectType
Type returns the ObjectType (BOOLEAN_OBJ) associated with the referenced Boolean struct
type Builtin ¶
type Builtin struct {
Fn BuiltinFunction
}
Builtin is the referenced struct for built-in functions in our object system. The struct holds the defined built-in function.
func GetBuiltInByName ¶ added in v0.0.2
GetBuiltInByName simply finds a BuiltIn with a matching name
func (*Builtin) Type ¶
func (b *Builtin) Type() ObjectType
Type returns the ObjectType (BUILTIN_OBJ) associated with the referenced Builtin struct
type BuiltinFunction ¶
BuiltinFunction is used to create built-in functions that can be called in the interpretor. The functions are defined by us and can be called by the user. A built-in function can be constructed with any number of arguments of the type Object, but it must return an Object.
type Closure ¶ added in v0.0.2
type Closure struct { Fn *CompiledFunction Free []Object }
Closure is the referenced struct for closures in the object system. Fn points to the CompiledFunction enclosed by the closure. Free is a slice that keeps track of the free-variables relevant to the closure. A Closure struct will be constructed during run-time (when the VM executes) The Compiler provides an OpClosure instruction and the VM executes it, the will wrap an *object.CompiledFunction from the constants pool in a new Closure and put it on the stack. NOTE: All *object.CompiledFunctions will be wrapped by a Closure.
func (*Closure) Inspect ¶ added in v0.0.2
Inspect will simply return a preformatted string for the Closure with its memory-address.
func (*Closure) Type ¶ added in v0.0.2
func (c *Closure) Type() ObjectType
Type returns the ObjectType (CLOSURE_OBJ) associated with the referenced CLOSURE_OBJ struct
type CompiledFunction ¶ added in v0.0.2
type CompiledFunction struct { Instructions code.Instructions NumLocals int NumParameters int }
CompiledFunction is the referenced struct for compiled functions in our object system. The Instructions field holds the bytecode instructions from compiling a function literal. NumLocals is the number of local bindings in the function. CompiledFunction is intended to be a bytecode constant, it will be loaded on to to the stack and eventually used by the VM when it executes the function as a call expression instruction (OpCall).
func (*CompiledFunction) Inspect ¶ added in v0.0.2
func (cf *CompiledFunction) Inspect() string
Inspect will simply return a preformatted string for the CompiledFunction with its memory-address.
func (*CompiledFunction) Type ¶ added in v0.0.2
func (cf *CompiledFunction) Type() ObjectType
Type returns the ObjectType (COMPILED_FUNCTION_OBJ) associated with the referenced CompiledFunction struct
type Environment ¶
type Environment struct {
// contains filtered or unexported fields
}
Environment employ a hashmap to keep track of evaluated values for expressions. Each value (Object) is associated with a name, typically the same name of the Identifier it was original bound too.
func NewEnclosedEnvironment ¶
func NewEnclosedEnvironment(outer *Environment) *Environment
NewEnclosedEnvironment extends the given Environment (outer). We create a new instance of an Environment with a pointer to the environment it should extend. By doing that, we enclose a fresh and empty environment with an existing one (outer). This allows us to preserve previous bindings while at the same time making new ones available, effectively introducing the concept of variable "scoping" ie: Identifiers of the same name can exist in different environments and hold different values:
// The outer enclosing environment let x = 5 let printNum = fn(x) { // The inner environment puts(x) } printNum(10) ----> 10 puts(x) ----> 5
The inner environment can always Get and reference the store of its outer environment
func NewEnvironment ¶
func NewEnvironment() *Environment
NewEnvironment creates a new instance of an Environment
func (*Environment) Get ¶
func (e *Environment) Get(name string) (Object, bool)
Get uses the given name to find an associated Object in the Environment store. If the name cannot be found in the current environment, and the current environment has an outer environment, then try to Get the Object from the outer environment. This repeats and surfaces up the Environment tree until an associated Object is found or when there are no enclosing Environments left (reached the root environment).
type Error ¶
type Error struct {
Message string
}
Error contains the Message corresponding to an error that was encountered while evaluating the AST
func (*Error) Inspect ¶
Inspect returns the Error struct's Message as a formatted string to print out the error message
func (*Error) Type ¶
func (e *Error) Type() ObjectType
Type returns the ObjectType (ERROR_OBJ) associated with the referenced Error struct
type Function ¶
type Function struct { Parameters []*ast.Identifier Body *ast.BlockStatement Env *Environment }
Function is the referenced struct for Function Literals in our object system. The struct holds the function's parameters and body to be later evaluated when referenced in its respective environment in a function call
func (*Function) Inspect ¶
Inspect will construct the Function as a string by stringifying its components, the parameters and body, and concatenating them into the expected function format.
func (*Function) Type ¶
func (f *Function) Type() ObjectType
Type returns the ObjectType (FUNCTION_OBJ) associated with the referenced Function struct
type Hash ¶
Hash is the referenced strsuct for Hash Literals in our object system The Pairs field holds the evaluated map of the hash literal.
func (*Hash) Inspect ¶
Inspect will construct the Hash as a string by stringifying its key-value pairs, and concatenating them into the expected hash format.
func (*Hash) Type ¶
func (h *Hash) Type() ObjectType
Type returns the ObjectType (HASH_OBJ) associated with the referenced Hash struct
type HashKey ¶
type HashKey struct { Type ObjectType Value uint64 }
HashKey is the referenced struct for a hash-key used in a Hash. It helps us effectively look up keys in the Hash.Pairs. Type refers to the different object types a hash-key can have (string, integer, boolean) before being converted to a uint64. Value refers to the actual literal value of the key, the key in the key-value pair.
type HashPair ¶
HashPair is the referenced struct used as the designated value to HashKeys. It helps us print the values of the map in a more practial manner by containing both the objects that generated the keys and values of the map.
type Hashable ¶
type Hashable interface {
HashKey() HashKey
}
Hashable is the interface used in our evaluator to check if the given object is usable as a hash key when we evaluate hash literals or index expressions for hashes.
type Integer ¶
type Integer struct {
Value int64 // the evaluated value
}
Integer is the referenced struct for Integer Literals in our object system. The struct holds the evaluated value of the Integer Literal.
func (*Integer) HashKey ¶
HashKey constructs an integer hash-key for a Hash. It uses the Integer's Value as the HashKey value. This HashKey struct will be used as a key in the evaluated Hash Literal.
func (*Integer) Type ¶
func (i *Integer) Type() ObjectType
Type returns the ObjectType (INTEGER_OBJ) associated with the referenced Integer struct
type Null ¶
type Null struct{}
Null is the referenced struct for Null Literals in our object system. By nature it has no value, since it represents the absence of any value.
func (*Null) Inspect ¶
Inspect returns a literal "null" string as there is no value to stringify on Null structs
func (*Null) Type ¶
func (n *Null) Type() ObjectType
Type returns the ObjectType (NULL_OBJ) associated with the referenced Null struct
type Object ¶
type Object interface { Type() ObjectType Inspect() string }
Object is the interface that represents every value we encounter when evaluating Monkey source code. Every value will be wrapped inside a stuct, which fulfills this Object interface. Tt is foundation for our object system.
type ObjectType ¶
type ObjectType string
ObjectType is the type that represents an evaluated value as a string
type ReturnValue ¶
type ReturnValue struct {
Value Object
}
ReturnValue wraps the intended return value inside an Object, giving us the ability to keep track of it. Keeping track of it helps us later decide whether to stop evalution or not.
func (*ReturnValue) Inspect ¶
func (rv *ReturnValue) Inspect() string
Inspect returns the ReturnValue struct's Value as a string. Since the Value is of type Object (interface), we can call Inspect() from the underlying struct which implemeneted the Object interface.
func (*ReturnValue) Type ¶
func (rv *ReturnValue) Type() ObjectType
Type returns the ObjectType (RETURN_VALUE_OBJ) associated with the referenced ReturnValue struct
type String ¶
type String struct {
Value string
}
String is the referenced struct for String Literals in our object system. The struct holds the evaluated value of the String Literal.
func (*String) HashKey ¶
HashKey constructs a string hash-key for a Hash. The hash-key uses the String's Value to construct a new 64-bit hash and converts it to a primitive uint64 for the hash-key. This helps resolve the issue where &Object.Strings have the same Value, but have different memory allocations. There is an inequality when comparing the index operation's value, map[&Object.String{Value:"key"}] to a key in the map, {&Object.String{Value:"key"}: "value"}, we are comparing two different pointer addresses. Instead we should compare two structs. By using a HashKey, we convert the &Object.String.Value to a uint64 value and use that as the key. A unique input (string) will always return the same corresponding unique output (uint64). We take the inequal pointers out of the equation and now simply compare the two structs.
func (*String) Type ¶
func (s *String) Type() ObjectType
Type returns the ObjectType (STRING_OBJ) associated with the referenced String struct