simpler vm
This commit is contained in:
@@ -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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user