kode4food/ale

View on GitHub
internal/runtime/vm/vm.go

Summary

Maintainability
A
3 hrs
Test Coverage
A
100%
package vm

import (
    "github.com/kode4food/ale/internal/debug"
    "github.com/kode4food/ale/internal/runtime/isa"
    "github.com/kode4food/ale/pkg/data"
)

type (
    state int

    VM struct {
        CODE isa.Instructions
        RES  data.Value
        CL   *Closure
        MEM  data.Vector
        ARGS data.Vector
        ST   state
        PC   int
        LP   int
        SP   int
        INST isa.Instruction
    }
)

// ErrBadInstruction is raised when the VM encounters an Opcode that has not
// been properly mapped
const ErrBadInstruction = "unknown instruction encountered: %s"

const (
    failure state = iota - 1
    running
    success
)

func (vm *VM) initMem() {
    vm.MEM = make(data.Vector, vm.CL.StackSize+vm.CL.LocalCount)
    vm.initCode()
}

func (vm *VM) initCode() {
    vm.CODE = vm.CL.Code
    vm.LP = int(vm.CL.StackSize)
    vm.initState()
}

func (vm *VM) initState() {
    vm.SP = vm.LP - 1
    vm.PC = 0
}

func (vm *VM) Run() data.Value {
    vm.initMem()
    for vm.ST == running {
        vm.INST = vm.CODE[vm.PC]
        switch vm.INST.Opcode() {
        case isa.Add:
            doAdd(vm)
        case isa.Arg:
            doArg(vm)
        case isa.ArgLen:
            doArgLen(vm)
        case isa.Bind:
            doBind(vm)
        case isa.BindRef:
            doBindRef(vm)
        case isa.Call0:
            doCall0(vm)
        case isa.Call1:
            doCall1(vm)
        case isa.Call:
            doCall(vm)
        case isa.CallWith:
            doCallWith(vm)
        case isa.Car:
            doCar(vm)
        case isa.Cdr:
            doCdr(vm)
        case isa.Closure:
            doClosure(vm)
        case isa.CondJump:
            doCondJump(vm)
        case isa.Cons:
            doCons(vm)
        case isa.Const:
            doConst(vm)
        case isa.Declare:
            doDeclare(vm)
        case isa.Deref:
            doDeref(vm)
        case isa.Div:
            doDiv(vm)
        case isa.Dup:
            doDup(vm)
        case isa.Empty:
            doEmpty(vm)
        case isa.Eq:
            doEq(vm)
        case isa.False:
            doFalse(vm)
        case isa.Jump:
            doJump(vm)
        case isa.Load:
            doLoad(vm)
        case isa.Mod:
            doMod(vm)
        case isa.Mul:
            doMul(vm)
        case isa.Neg:
            doNeg(vm)
        case isa.NegInt:
            doNegInt(vm)
        case isa.NewRef:
            doNewRef(vm)
        case isa.NoOp:
            doNoOp(vm)
        case isa.Not:
            doNot(vm)
        case isa.Null:
            doNull(vm)
        case isa.NumEq:
            doNumEq(vm)
        case isa.NumGt:
            doNumGt(vm)
        case isa.NumGte:
            doNumGte(vm)
        case isa.NumLt:
            doNumLt(vm)
        case isa.NumLte:
            doNumLte(vm)
        case isa.Panic:
            doPanic(vm)
        case isa.Pop:
            doPop(vm)
        case isa.PosInt:
            doPosInt(vm)
        case isa.Private:
            doPrivate(vm)
        case isa.Resolve:
            doResolve(vm)
        case isa.RestArg:
            doRestArg(vm)
        case isa.RetFalse:
            doRetFalse(vm)
        case isa.RetNull:
            doRetNull(vm)
        case isa.RetTrue:
            doRetTrue(vm)
        case isa.Return:
            doReturn(vm)
        case isa.SetArgs:
            doSetArgs(vm)
        case isa.Store:
            doStore(vm)
        case isa.Sub:
            doSub(vm)
        case isa.TailCall:
            doTailCall(vm)
        case isa.True:
            doTrue(vm)
        case isa.Vector:
            doVector(vm)
        case isa.Zero:
            doZero(vm)
        default:
            panic(debug.ProgrammerError(ErrBadInstruction, vm.INST))
        }
    }
    return vm.RES
}