about summary refs log tree commit diff
path: root/pkg/lang/vm/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/exec.go')
-rw-r--r--pkg/lang/vm/exec.go135
1 files changed, 135 insertions, 0 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go
new file mode 100644
index 0000000..241e5f8
--- /dev/null
+++ b/pkg/lang/vm/exec.go
@@ -0,0 +1,135 @@
+package vm
+
+import "jinx/pkg/lang/vm/value"
+
+func (vm *VM) execPushInt(x int64) {
+	vm.stack.Top().Push(value.NewInt(x))
+}
+
+func (vm *VM) execPushFloat(x float64) {
+	vm.stack.Top().Push(value.NewFloat(x))
+}
+
+func (vm *VM) execPushString(str string) {
+	vm.stack.Top().Push(value.NewString(str))
+}
+
+func (vm *VM) execPushBool(b bool) {
+	vm.stack.Top().Push(value.NewBool(b))
+}
+
+func (vm *VM) execPushNull() {
+	vm.stack.Top().Push(value.NewNull())
+}
+
+func (vm *VM) execPushArray() {
+	vm.stack.Top().Push(value.NewArray([]value.Value{}))
+}
+
+func (vm *VM) execGetLocal(offset int) {
+	top := vm.stack.Top()
+	top.Push(top.At(int(offset)))
+}
+
+func (vm *VM) execGetArg() {
+	vm.stack.Top().Push(vm.stack.Prev().Pop())
+}
+
+func (vm *VM) execAdd() {
+	top := vm.stack.Top()
+
+	x := top.Pop()
+	y := top.Pop()
+
+	var res value.Value
+
+	switch x.Type().Kind {
+	case value.IntType:
+		xv := x.Data().(int64)
+		switch y.Type().Kind {
+		case value.IntType:
+			res = value.NewInt(xv + y.Data().(int64))
+		case value.FloatType:
+			res = value.NewFloat(float64(xv) + y.Data().(float64))
+		default:
+			panic("invalid operand types")
+		}
+	case value.FloatType:
+		xv := x.Data().(float64)
+		switch y.Type().Kind {
+		case value.IntType:
+			res = value.NewFloat(xv + float64(y.Data().(int64)))
+		case value.FloatType:
+			res = value.NewFloat(xv + y.Data().(float64))
+		default:
+			panic("invalid operand types")
+		}
+	case value.StringType:
+		switch y.Type().Kind {
+		case value.StringType:
+			res = value.NewString(x.Data().(string) + y.Data().(string))
+		default:
+			panic("invalid operand types")
+		}
+	default:
+		panic("invalid operand types")
+	}
+
+	top.Push(res)
+}
+
+func (vm *VM) execSub() {
+	top := vm.stack.Top()
+
+	x := top.Pop()
+	y := top.Pop()
+
+	var res value.Value
+
+	switch x.Type().Kind {
+	case value.IntType:
+		xv := x.Data().(int64)
+		switch y.Type().Kind {
+		case value.IntType:
+			res = value.NewInt(xv - y.Data().(int64))
+		case value.FloatType:
+			res = value.NewFloat(float64(xv) - y.Data().(float64))
+		default:
+			panic("invalid operand types")
+		}
+	case value.FloatType:
+		xv := x.Data().(float64)
+		switch y.Type().Kind {
+		case value.IntType:
+			res = value.NewFloat(xv - float64(y.Data().(int64)))
+		case value.FloatType:
+			res = value.NewFloat(xv - y.Data().(float64))
+		default:
+			panic("invalid operand types")
+		}
+	default:
+		panic("invalid operand types")
+	}
+
+	top.Push(res)
+}
+
+func (vm *VM) execIndex() {
+	top := vm.stack.Top()
+
+	v := top.Pop()
+	i := top.Pop()
+
+	switch v.Type().Kind {
+	case value.ArrayType:
+		arr := v.Data().([]value.Value)
+		idx := i.Data().(int64)
+		if idx < 0 || idx >= int64(len(arr)) {
+			panic("index out of bounds")
+		}
+
+		top.Push(arr[idx])
+	default:
+		panic("invalid operand types")
+	}
+}