about summary refs log tree commit diff
path: root/pkg/lang/vm/vm.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/vm.go')
-rw-r--r--pkg/lang/vm/vm.go108
1 files changed, 108 insertions, 0 deletions
diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go
new file mode 100644
index 0000000..434eae3
--- /dev/null
+++ b/pkg/lang/vm/vm.go
@@ -0,0 +1,108 @@
+package vm
+
+import (
+	"fmt"
+	"jinx/pkg/lang/vm/code"
+)
+
+type VM struct {
+	code  *code.Code
+	pc    int
+	stack CallStack
+}
+
+func New(code *code.Code) *VM {
+	return &VM{
+		code: code,
+		pc:   0,
+	}
+}
+
+func (vm *VM) Run() {
+	for vm.pc < vm.code.Len() {
+		op, advance := vm.code.GetOp(vm.pc)
+		vm.pc += advance
+		vm.step(op)
+	}
+}
+
+type stepDecision int
+
+const (
+	stepDecisionContinue stepDecision = iota
+	stepDecisionHalt
+)
+
+func (vm *VM) step(op code.Op) stepDecision {
+	switch op {
+	case code.OpNop:
+		// do nothing
+	case code.OpHalt:
+		return stepDecisionHalt
+
+	case code.OpPushInt:
+		x, advance := vm.code.GetInt(vm.pc)
+		vm.pc += advance
+
+		vm.execPushInt(x)
+	case code.OpPushFloat:
+		x, advance := vm.code.GetFloat(vm.pc)
+		vm.pc += advance
+
+		vm.execPushFloat(x)
+	case code.OpPushString:
+		str, advance := vm.code.GetString(vm.pc)
+		vm.pc += advance
+
+		vm.execPushString(str)
+	case code.OpPushNull:
+		vm.execPushNull()
+	case code.OpPushTrue:
+		vm.execPushBool(true)
+	case code.OpPushFalse:
+		vm.execPushBool(false)
+	case code.OpPushArray:
+		vm.execPushArray()
+	case code.OpPushFunction:
+		panic("not implemented")
+	case code.OpPushObject:
+		panic("not implemented")
+
+	case code.OpGetGlobal:
+		panic("not implemented")
+	case code.OpGetLocal:
+		offset, advance := vm.code.GetInt(vm.pc)
+		vm.pc += advance
+
+		vm.execGetLocal(int(offset))
+	case code.OpGetMember:
+		panic("not implemented")
+	case code.OpGetArg:
+		vm.execGetArg()
+	case code.OpGetEnv:
+		panic("not implemented")
+
+	case code.OpAdd:
+		vm.execAdd()
+	case code.OpSub:
+		vm.execSub()
+	case code.OpIndex:
+		vm.execIndex()
+	case code.OpCall:
+		panic("not implemented")
+
+	case code.OpJmp:
+		pc, _ := vm.code.GetUint(vm.pc)
+		vm.pc = int(pc)
+	case code.OpJez:
+		panic("not implemented")
+
+	case code.OpRet:
+		panic("not implemented")
+
+	default:
+		panic(fmt.Errorf("unimplemented op: %v", op))
+	}
+
+	return stepDecisionContinue
+}