about summary refs log tree commit diff
path: root/pkg/lang/vm/exec.go
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-05-20 21:04:37 +0200
committerMel <einebeere@gmail.com>2022-05-20 21:04:37 +0200
commit3f4efe745a0404953266476ec52db54b182de2f8 (patch)
tree107542d587c97b99f749c537870e84d196058210 /pkg/lang/vm/exec.go
parent25eb5ca1b0a8b9b35f36deedec4901bca02bf43e (diff)
downloadjinx-3f4efe745a0404953266476ec52db54b182de2f8.tar.zst
jinx-3f4efe745a0404953266476ec52db54b182de2f8.zip
Call and return from functions
Diffstat (limited to 'pkg/lang/vm/exec.go')
-rw-r--r--pkg/lang/vm/exec.go44
1 files changed, 44 insertions, 0 deletions
diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go
index 4f37ad3..655f7f1 100644
--- a/pkg/lang/vm/exec.go
+++ b/pkg/lang/vm/exec.go
@@ -29,6 +29,10 @@ func (vm *VM) execPushArray() {
 	vm.stack.Push(value.NewArray([]value.Value{}))
 }
 
+func (vm *VM) execPushFunction(pc int) {
+	vm.stack.Push(value.NewFunction(pc))
+}
+
 func (vm *VM) execGetLocal(offset int) error {
 	local, err := vm.stack.Local(int(offset))
 	if err != nil {
@@ -262,6 +266,30 @@ func (vm *VM) execLte() error {
 	return nil
 }
 
+func (vm *VM) execCall() error {
+	f, err := vm.stack.Pop()
+	if err != nil {
+		return err
+	}
+
+	if f.Type().Kind != value.FunctionType {
+		return ErrInvalidOperandType{
+			Op: code.OpCall,
+			X:  f.Type(),
+		}
+	}
+
+	fn := f.Data().(value.FunctionData)
+
+	if err = vm.stack.PushCall(fn.Pc(), vm.pc); err != nil {
+		return err
+	}
+
+	vm.pc = fn.Pc()
+
+	return nil
+}
+
 func (vm *VM) execJumpIf(pc int, cond bool) error {
 	b, err := vm.stack.Pop()
 	if err != nil {
@@ -291,6 +319,22 @@ func (vm *VM) execJumpIf(pc int, cond bool) error {
 	return nil
 }
 
+func (vm *VM) execRet() error {
+	returned, err := vm.stack.Pop()
+	if err != nil {
+		return err
+	}
+
+	pc, err := vm.stack.PopCall()
+	if err != nil {
+		return err
+	}
+
+	vm.stack.Push(returned)
+	vm.pc = pc
+	return nil
+}
+
 func (vm *VM) execTempArrLen() error {
 	a, err := vm.stack.Pop()
 	if err != nil {