diff options
Diffstat (limited to 'pkg/lang/vm/exec.go')
| -rw-r--r-- | pkg/lang/vm/exec.go | 135 |
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") + } +} |
