simpler vm
Some checks failed
Test / build (push) Waiting to run
Build / build (push) Successful in 11m8s
Publish Image / publish (push) Has been cancelled

This commit is contained in:
2024-04-01 17:21:55 -04:00
parent f9e6e164b0
commit 803f330e82
6 changed files with 246 additions and 317 deletions

View File

@@ -14,8 +14,14 @@ func Len(args ...object.Object) object.Object {
return newError(err.Error()) return newError(err.Error())
} }
if size, ok := args[0].(object.Sizeable); ok { switch obj := args[0].(type) {
return object.Integer{Value: int64(size.Len())} case object.String:
} return object.Integer{Value: int64(obj.Len())}
case *object.Array:
return object.Integer{Value: int64(obj.Len())}
case *object.Hash:
return object.Integer{Value: int64(obj.Len())}
default:
return newError("TypeError: object of type '%s' has no len()", args[0].Type()) return newError("TypeError: object of type '%s' has no len()", args[0].Type())
}
} }

View File

@@ -70,31 +70,33 @@ func (ao *Array) Less(i, j int) bool {
return false return false
} }
func (ao *Array) Add(other Object) (Object, error) { func (a *Array) Add(other Object) (Object, error) {
if other.Type() != ao.Type() { switch obj := other.(type) {
return nil, NewBinaryOpError(ao, other, "+") case *Array:
}
var elements []Object var elements []Object
elements = append(elements, ao.Elements...) elements = append(elements, a.Elements...)
elements = append(elements, other.(*Array).Elements...) elements = append(elements, obj.Elements...)
return &Array{Elements: elements}, nil return &Array{Elements: elements}, nil
default:
return nil, NewBinaryOpError(a, other, "+")
}
} }
func (ao *Array) Mul(other Object) (Object, error) { func (a *Array) Mul(other Object) (Object, error) {
if other.Type() != IntegerType { switch obj := other.(type) {
return nil, NewBinaryOpError(ao, other, "*") case Integer:
}
var elements []Object var elements []Object
N := int(other.(Integer).Value) N := int(obj.Value)
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
elements = append(elements, ao.Elements...) elements = append(elements, a.Elements...)
} }
return &Array{Elements: elements}, nil return &Array{Elements: elements}, nil
default:
return nil, NewBinaryOpError(a, other, "*")
}
} }
func (ao *Array) Get(index Object) (Object, error) { func (ao *Array) Get(index Object) (Object, error) {

View File

@@ -45,51 +45,61 @@ func (i Integer) Sub(other Object) (Object, error) {
} }
func (i Integer) Mul(other Object) (Object, error) { func (i Integer) Mul(other Object) (Object, error) {
switch other.Type() { switch obj := other.(type) {
case IntegerType: case Integer:
return Integer{i.Value * other.(Integer).Value}, nil return Integer{i.Value * obj.Value}, nil
case StringType: case String:
return other.(Mul).Mul(i) return obj.Mul(i)
case ArrayType: case *Array:
return other.(Mul).Mul(i) return obj.Mul(i)
default: default:
return nil, NewBinaryOpError(i, other, "*") return nil, NewBinaryOpError(i, other, "*")
} }
} }
func (i Integer) Div(other Object) (Object, error) { func (i Integer) Div(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value / obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, "/") return nil, NewBinaryOpError(i, other, "/")
} }
return Integer{i.Value / other.(Integer).Value}, nil
} }
func (i Integer) Mod(other Object) (Object, error) { func (i Integer) Mod(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value % obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, "%") return nil, NewBinaryOpError(i, other, "%")
} }
return Integer{i.Value % other.(Integer).Value}, nil
} }
func (i Integer) BitwiseOr(other Object) (Object, error) { func (i Integer) BitwiseOr(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value | obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, "|") return nil, NewBinaryOpError(i, other, "|")
} }
return Integer{i.Value | other.(Integer).Value}, nil
} }
func (i Integer) BitwiseXor(other Object) (Object, error) { func (i Integer) BitwiseXor(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value ^ obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, "^") return nil, NewBinaryOpError(i, other, "^")
} }
return Integer{i.Value ^ other.(Integer).Value}, nil
} }
func (i Integer) BitwiseAnd(other Object) (Object, error) { func (i Integer) BitwiseAnd(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value & obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, "") return nil, NewBinaryOpError(i, other, "")
} }
return Integer{i.Value & other.(Integer).Value}, nil
} }
func (i Integer) BitwiseNot() Object { func (i Integer) BitwiseNot() Object {
@@ -97,17 +107,21 @@ func (i Integer) BitwiseNot() Object {
} }
func (i Integer) LeftShift(other Object) (Object, error) { func (i Integer) LeftShift(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value << obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, "<<") return nil, NewBinaryOpError(i, other, "<<")
} }
return Integer{i.Value << other.(Integer).Value}, nil
} }
func (i Integer) RightShift(other Object) (Object, error) { func (i Integer) RightShift(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return Integer{i.Value >> obj.Value}, nil
default:
return nil, NewBinaryOpError(i, other, ">>") return nil, NewBinaryOpError(i, other, ">>")
} }
return Integer{i.Value >> other.(Integer).Value}, nil
} }
func (i Integer) LogicalNot() Object { func (i Integer) LogicalNot() Object {

View File

@@ -54,91 +54,6 @@ func (t Type) String() string {
} }
} }
// Add is the interface for binary addition
type Add interface {
Add(other Object) (Object, error)
}
// Sub is the interface for binary subtraction
type Sub interface {
Sub(other Object) (Object, error)
}
// Mul is the interface for binary multiplication
type Mul interface {
Mul(other Object) (Object, error)
}
// Div is the interface for binary division
type Div interface {
Div(other Object) (Object, error)
}
// Mod is the interface for binary modulo
type Mod interface {
Mod(other Object) (Object, error)
}
// LogicalOr is the interface for logical or
type LogicalOr interface {
LogicalOr(other Object) (Object, error)
}
// LogicalAnd is the interface for logical and
type LogicalAnd interface {
LogicalAnd(other Object) (Object, error)
}
// BitwiseOr is the interface for bitwise or
type BitwiseOr interface {
BitwiseOr(other Object) (Object, error)
}
// BitwiseAnd is the interface for bitwise and
type BitwiseAnd interface {
BitwiseAnd(other Object) (Object, error)
}
// BitwiseXor is the interface for bitwise xor
type BitwiseXor interface {
BitwiseXor(other Object) (Object, error)
}
// BitwiseNot is the interface for bitwise not
type BitwiseNot interface {
BitwiseNot() Object
}
// LeftShift is the interface for bitwise left shift
type LeftShift interface {
LeftShift(other Object) (Object, error)
}
// RightShift is the interface for bitwise right shift
type RightShift interface {
RightShift(other Object) (Object, error)
}
// LogicalNot is the interface for logical not
type LogicalNot interface {
LogicalNot() Object
}
// Negate is the interface for unary negation
type Negate interface {
Negate() Object
}
// Setter is the interface for assigning a value to an index
type Setter interface {
Set(index, value Object) error
}
// Getter is the interface for getting a value from an index
type Getter interface {
Get(index Object) (Object, error)
}
// Comparable is the interface for comparing two Object and their underlying // Comparable is the interface for comparing two Object and their underlying
// values. It is the responsibility of the caller (left) to check for types. // values. It is the responsibility of the caller (left) to check for types.
// Returns `true` iif the types and values are identical, `false` otherwise. // Returns `true` iif the types and values are identical, `false` otherwise.
@@ -146,13 +61,6 @@ type Comparable interface {
Compare(other Object) int Compare(other Object) int
} }
// Sizeable is the interface for returning the size of an Object.
// Object(s) that have a valid size must implement this interface and the
// Len() method.
type Sizeable interface {
Len() int
}
// Immutable is the interface for all immutable objects which must implement // Immutable is the interface for all immutable objects which must implement
// the Clone() method used by binding names to values. // the Clone() method used by binding names to values.
type Immutable interface { type Immutable interface {

View File

@@ -35,17 +35,21 @@ func (s String) String() string {
} }
func (s String) Add(other Object) (Object, error) { func (s String) Add(other Object) (Object, error) {
if !AssertTypes(other, StringType) { switch obj := other.(type) {
case String:
return String{s.Value + obj.Value}, nil
default:
return nil, NewBinaryOpError(s, other, "+") return nil, NewBinaryOpError(s, other, "+")
} }
return String{s.Value + other.(String).Value}, nil
} }
func (s String) Mul(other Object) (Object, error) { func (s String) Mul(other Object) (Object, error) {
if !AssertTypes(other, IntegerType) { switch obj := other.(type) {
case Integer:
return String{strings.Repeat(s.Value, int(obj.Value))}, nil
default:
return nil, NewBinaryOpError(s, other, "*") return nil, NewBinaryOpError(s, other, "*")
} }
return String{strings.Repeat(s.Value, int(other.(Integer).Value))}, nil
} }
func (s String) Get(index Object) (Object, error) { func (s String) Get(index Object) (Object, error) {

View File

@@ -206,29 +206,6 @@ func (vm *VM) pop() object.Object {
return o return o
} }
func (vm *VM) executeLoadBuiltin() error {
builtinIndex := vm.currentFrame().ReadUint8()
builtin := builtins.BuiltinsIndex[builtinIndex]
return vm.push(builtin)
}
func (vm *VM) executeConstant() error {
constIndex := vm.currentFrame().ReadUint16()
return vm.push(vm.state.Constants[constIndex])
}
func (vm *VM) executeAssignGlobal() error {
globalIndex := vm.currentFrame().ReadUint16()
vm.state.Globals[globalIndex] = vm.pop()
return vm.push(object.NULL)
}
func (vm *VM) executeAssignLocal() error {
localIndex := vm.currentFrame().ReadUint8()
vm.stack[vm.currentFrame().basePointer+int(localIndex)] = vm.pop()
return vm.push(object.NULL)
}
func (vm *VM) executeSetGlobal() error { func (vm *VM) executeSetGlobal() error {
globalIndex := vm.currentFrame().ReadUint16() globalIndex := vm.currentFrame().ReadUint16()
@@ -242,11 +219,6 @@ func (vm *VM) executeSetGlobal() error {
return vm.push(object.NULL) return vm.push(object.NULL)
} }
func (vm *VM) executeGetGlobal() error {
globalIndex := vm.currentFrame().ReadUint16()
return vm.push(vm.state.Globals[globalIndex])
}
func (vm *VM) executeSetLocal() error { func (vm *VM) executeSetLocal() error {
localIndex := vm.currentFrame().ReadUint8() localIndex := vm.currentFrame().ReadUint8()
@@ -260,38 +232,6 @@ func (vm *VM) executeSetLocal() error {
return vm.push(object.NULL) return vm.push(object.NULL)
} }
func (vm *VM) executeGetLocal() error {
localIndex := vm.currentFrame().ReadUint8()
return vm.push(vm.stack[vm.currentFrame().basePointer+int(localIndex)])
}
func (vm *VM) executeGetFree() error {
freeIndex := vm.currentFrame().ReadUint8()
return vm.push(vm.currentFrame().GetFree(freeIndex))
}
func (vm *VM) executeLoadModule() error {
name := vm.pop()
return vm.loadModule(name)
}
func (vm *VM) executeCurrentClosure() error {
currentClosure := vm.currentFrame().cl
return vm.push(currentClosure)
}
func (vm *VM) executeTrue() error {
return vm.push(object.TRUE)
}
func (vm *VM) executeFalse() error {
return vm.push(object.FALSE)
}
func (vm *VM) executeNull() error {
return vm.push(object.NULL)
}
func (vm *VM) buildHash(startIndex, endIndex int) (object.Object, error) { func (vm *VM) buildHash(startIndex, endIndex int) (object.Object, error) {
hashedPairs := make(map[object.HashKey]object.HashPair) hashedPairs := make(map[object.HashKey]object.HashPair)
@@ -342,200 +282,238 @@ func (vm *VM) executeMakeArray() error {
return vm.push(hash) return vm.push(hash)
} }
func (vm *VM) executeClosure() error {
constIndex := vm.currentFrame().ReadUint16()
numFree := vm.currentFrame().ReadUint8()
return vm.pushClosure(int(constIndex), int(numFree))
}
func (vm *VM) executeAdd() error { func (vm *VM) executeAdd() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Add); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.Add(right) val, err := obj.Add(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
case object.String:
val, err := obj.Add(right)
if err != nil {
return err
} }
return vm.push(val)
case *object.Array:
val, err := obj.Add(right)
if err != nil {
return err
}
return vm.push(val)
case *object.Hash:
val, err := obj.Add(right)
if err != nil {
return err
}
return vm.push(val)
default:
return object.NewBinaryOpError(left, right, "+") return object.NewBinaryOpError(left, right, "+")
}
} }
func (vm *VM) executeSub() error { func (vm *VM) executeSub() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Sub); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.Sub(right) val, err := obj.Sub(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
default:
return fmt.Errorf("unsupported types for unary operation: -%s", left.Type())
} }
return object.NewBinaryOpError(left, right, "+")
} }
func (vm *VM) executeMul() error { func (vm *VM) executeMul() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Mul); ok { switch obj := left.(type) {
case *object.Array:
val, err := obj.Mul(right) val, err := obj.Mul(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
case object.Integer:
val, err := obj.Mul(right)
if err != nil {
return err
} }
return vm.push(val)
case object.String:
val, err := obj.Mul(right)
if err != nil {
return err
}
return vm.push(val)
default:
return object.NewBinaryOpError(left, right, "*") return object.NewBinaryOpError(left, right, "*")
}
} }
func (vm *VM) executeDiv() error { func (vm *VM) executeDiv() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Div); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.Div(right) val, err := obj.Div(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
default:
return object.NewBinaryOpError(left, right, "/")
} }
return object.NewBinaryOpError(left, right, "+")
} }
func (vm *VM) executeMod() error { func (vm *VM) executeMod() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Mod); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.Mod(right) val, err := obj.Mod(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "%") return object.NewBinaryOpError(left, right, "%")
}
} }
func (vm *VM) executeOr() error { func (vm *VM) executeOr() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.LogicalOr); ok { switch obj := left.(type) {
case object.Boolean:
val, err := obj.LogicalOr(right) val, err := obj.LogicalOr(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "||") return object.NewBinaryOpError(left, right, "||")
}
} }
func (vm *VM) executeAnd() error { func (vm *VM) executeAnd() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.LogicalAnd); ok { switch obj := left.(type) {
case object.Boolean:
val, err := obj.LogicalAnd(right) val, err := obj.LogicalAnd(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "&&") return object.NewBinaryOpError(left, right, "&&")
}
} }
func (vm *VM) executeBitwiseOr() error { func (vm *VM) executeBitwiseOr() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.BitwiseOr); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.BitwiseOr(right) val, err := obj.BitwiseOr(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "|") return object.NewBinaryOpError(left, right, "|")
}
} }
func (vm *VM) executeBitwiseXor() error { func (vm *VM) executeBitwiseXor() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.BitwiseXor); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.BitwiseXor(right) val, err := obj.BitwiseXor(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "^") return object.NewBinaryOpError(left, right, "^")
}
} }
func (vm *VM) executeBitwiseAnd() error { func (vm *VM) executeBitwiseAnd() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.BitwiseAnd); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.BitwiseAnd(right) val, err := obj.BitwiseAnd(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "&") return object.NewBinaryOpError(left, right, "&")
}
} }
func (vm *VM) executeBitwiseNot() error { func (vm *VM) executeBitwiseNot() error {
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.BitwiseNot); ok { switch obj := left.(type) {
case object.Integer:
return vm.push(obj.BitwiseNot()) return vm.push(obj.BitwiseNot())
} default:
return fmt.Errorf("unsupported types for unary operation: ~%s", left.Type()) return fmt.Errorf("unsupported types for unary operation: ~%s", left.Type())
}
} }
func (vm *VM) executeLeftShift() error { func (vm *VM) executeLeftShift() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.LeftShift); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.LeftShift(right) val, err := obj.LeftShift(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, "<<") return object.NewBinaryOpError(left, right, "<<")
}
} }
func (vm *VM) executeRightShift() error { func (vm *VM) executeRightShift() error {
right := vm.pop() right := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.RightShift); ok { switch obj := left.(type) {
case object.Integer:
val, err := obj.RightShift(right) val, err := obj.RightShift(right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
} default:
return object.NewBinaryOpError(left, right, ">>") return object.NewBinaryOpError(left, right, ">>")
}
} }
func (vm *VM) executeEqual() error { func (vm *VM) executeEqual() error {
@@ -601,21 +579,27 @@ func (vm *VM) executeGreaterThanOrEqual() error {
func (vm *VM) executeNot() error { func (vm *VM) executeNot() error {
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.LogicalNot); ok { switch obj := left.(type) {
case object.Boolean:
return vm.push(obj.LogicalNot()) return vm.push(obj.LogicalNot())
} case object.Integer:
return vm.push(obj.LogicalNot())
case object.Null:
return vm.push(obj.LogicalNot())
default:
return fmt.Errorf("unsupported types for unary operation: !%s", left.Type()) return fmt.Errorf("unsupported types for unary operation: !%s", left.Type())
}
} }
func (vm *VM) executeMinus() error { func (vm *VM) executeMinus() error {
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Negate); ok { switch obj := left.(type) {
case object.Integer:
return vm.push(obj.Negate()) return vm.push(obj.Negate())
} default:
return fmt.Errorf("unsupported types for unary operation: -%s", left.Type()) return fmt.Errorf("unsupported types for unary operation: -%s", left.Type())
}
} }
func (vm *VM) executeSetItem() error { func (vm *VM) executeSetItem() error {
@@ -623,36 +607,62 @@ func (vm *VM) executeSetItem() error {
index := vm.pop() index := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Setter); ok { switch obj := left.(type) {
case *object.Array:
err := obj.Set(index, right) err := obj.Set(index, right)
if err != nil { if err != nil {
return err return err
} }
return vm.push(object.NULL) return vm.push(object.NULL)
case *object.Hash:
err := obj.Set(index, right)
if err != nil {
return err
} }
return vm.push(object.NULL)
default:
return fmt.Errorf( return fmt.Errorf(
"set item operation not supported: left=%s index=%s", "set item operation not supported: left=%s index=%s",
left.Type(), index.Type(), left.Type(), index.Type(),
) )
}
} }
func (vm *VM) executeGetItem() error { func (vm *VM) executeGetItem() error {
index := vm.pop() index := vm.pop()
left := vm.pop() left := vm.pop()
if obj, ok := left.(object.Getter); ok { switch obj := left.(type) {
case object.String:
val, err := obj.Get(index) val, err := obj.Get(index)
if err != nil { if err != nil {
return err return err
} }
return vm.push(val) return vm.push(val)
case *object.Array:
val, err := obj.Get(index)
if err != nil {
return err
} }
return vm.push(val)
case *object.Hash:
val, err := obj.Get(index)
if err != nil {
return err
}
return vm.push(val)
case object.Module:
val, err := obj.Get(index)
if err != nil {
return err
}
return vm.push(val)
default:
return fmt.Errorf( return fmt.Errorf(
"index operator not supported: left=%s index=%s", "get item operation not supported: left=%s index=%s",
left.Type(), index.Type(), left.Type(), index.Type(),
) )
}
} }
func (vm *VM) executeCall() error { func (vm *VM) executeCall() error {
@@ -672,34 +682,6 @@ func (vm *VM) executeCall() error {
} }
} }
func (vm *VM) executeReturn() error {
returnValue := vm.pop()
frame := vm.popFrame()
vm.sp = frame.basePointer - 1
return vm.push(returnValue)
}
func (vm *VM) executeJumpIfFalse() error {
pos := int(vm.currentFrame().ReadUint16())
if !isTruthy(vm.pop()) {
vm.currentFrame().SetIP(pos)
}
return nil
}
func (vm *VM) executeJump() error {
pos := int(vm.currentFrame().ReadUint16())
vm.currentFrame().SetIP(pos)
return nil
}
func (vm *VM) executePop() error {
vm.pop()
return nil
}
func (vm *VM) callClosure(cl *object.Closure, numArgs int) error { func (vm *VM) callClosure(cl *object.Closure, numArgs int) error {
if numArgs != cl.Fn.NumParameters { if numArgs != cl.Fn.NumParameters {
return fmt.Errorf("wrong number of arguments: want=%d, got=%d", cl.Fn.NumParameters, numArgs) return fmt.Errorf("wrong number of arguments: want=%d, got=%d", cl.Fn.NumParameters, numArgs)
@@ -732,18 +714,10 @@ func (vm *VM) callBuiltin(builtin object.Builtin, numArgs int) error {
vm.sp = vm.sp - numArgs - 1 vm.sp = vm.sp - numArgs - 1
if result != nil { if result != nil {
err := vm.push(result) return vm.push(result)
if err != nil {
return err
}
} else {
err := vm.push(object.NULL)
if err != nil {
return err
}
} }
return nil return vm.push(object.NULL)
} }
func (vm *VM) pushClosure(constIndex, numFree int) error { func (vm *VM) pushClosure(constIndex, numFree int) error {
@@ -830,37 +804,47 @@ func (vm *VM) Run() (err error) {
switch op { switch op {
case code.OpConstant: case code.OpConstant:
err = vm.executeConstant() constIndex := vm.currentFrame().ReadUint16()
err = vm.push(vm.state.Constants[constIndex])
case code.OpPop: case code.OpPop:
err = vm.executePop() vm.pop()
case code.OpTrue: case code.OpTrue:
err = vm.executeTrue() err = vm.push(object.TRUE)
case code.OpFalse: case code.OpFalse:
err = vm.executeFalse() err = vm.push(object.FALSE)
case code.OpJump: case code.OpJump:
err = vm.executeJump() pos := int(vm.currentFrame().ReadUint16())
vm.currentFrame().SetIP(pos)
case code.OpJumpNotTruthy: case code.OpJumpNotTruthy:
err = vm.executeJumpIfFalse() pos := int(vm.currentFrame().ReadUint16())
if !isTruthy(vm.pop()) {
vm.currentFrame().SetIP(pos)
}
case code.OpNull: case code.OpNull:
err = vm.executeNull() err = vm.push(object.NULL)
case code.OpSetGlobal: case code.OpSetGlobal:
err = vm.executeSetGlobal() err = vm.executeSetGlobal()
case code.OpAssignGlobal: case code.OpAssignGlobal:
err = vm.executeAssignGlobal() globalIndex := vm.currentFrame().ReadUint16()
vm.state.Globals[globalIndex] = vm.pop()
err = vm.push(object.NULL)
case code.OpAssignLocal: case code.OpAssignLocal:
err = vm.executeAssignLocal() localIndex := vm.currentFrame().ReadUint8()
vm.stack[vm.currentFrame().basePointer+int(localIndex)] = vm.pop()
err = vm.push(object.NULL)
case code.OpGetGlobal: case code.OpGetGlobal:
err = vm.executeGetGlobal() globalIndex := vm.currentFrame().ReadUint16()
err = vm.push(vm.state.Globals[globalIndex])
case code.OpArray: case code.OpArray:
err = vm.executeMakeArray() err = vm.executeMakeArray()
@@ -878,28 +862,39 @@ func (vm *VM) Run() (err error) {
err = vm.executeCall() err = vm.executeCall()
case code.OpReturn: case code.OpReturn:
err = vm.executeReturn() returnValue := vm.pop()
frame := vm.popFrame()
vm.sp = frame.basePointer - 1
err = vm.push(returnValue)
case code.OpSetLocal: case code.OpSetLocal:
err = vm.executeSetLocal() err = vm.executeSetLocal()
case code.OpGetLocal: case code.OpGetLocal:
err = vm.executeGetLocal() localIndex := vm.currentFrame().ReadUint8()
err = vm.push(vm.stack[vm.currentFrame().basePointer+int(localIndex)])
case code.OpGetBuiltin: case code.OpGetBuiltin:
err = vm.executeLoadBuiltin() builtinIndex := vm.currentFrame().ReadUint8()
builtin := builtins.BuiltinsIndex[builtinIndex]
err = vm.push(builtin)
case code.OpClosure: case code.OpClosure:
err = vm.executeClosure() constIndex := vm.currentFrame().ReadUint16()
numFree := vm.currentFrame().ReadUint8()
err = vm.pushClosure(int(constIndex), int(numFree))
case code.OpGetFree: case code.OpGetFree:
err = vm.executeGetFree() freeIndex := vm.currentFrame().ReadUint8()
err = vm.push(vm.currentFrame().GetFree(freeIndex))
case code.OpCurrentClosure: case code.OpCurrentClosure:
err = vm.executeCurrentClosure() currentClosure := vm.currentFrame().cl
err = vm.push(currentClosure)
case code.OpLoadModule: case code.OpLoadModule:
err = vm.executeLoadModule() name := vm.pop()
err = vm.loadModule(name)
case code.OpAdd: case code.OpAdd:
err = vm.executeAdd() err = vm.executeAdd()