From d2f69dccb3643834a79da79be4ece189a7178c9e Mon Sep 17 00:00:00 2001 From: Mel Date: Sun, 29 May 2022 21:42:32 +0000 Subject: Types, Methods and basic Core Lib --- pkg/lang/vm/exec.go | 113 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 18 deletions(-) (limited to 'pkg/lang/vm/exec.go') diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go index 10ac604..79016fa 100644 --- a/pkg/lang/vm/exec.go +++ b/pkg/lang/vm/exec.go @@ -58,6 +58,82 @@ func (vm *VM) execGetLocal(offset int) error { return nil } +func (vm *VM) execGetMember(name string) error { + parent, err := vm.stack.Pop() + if err != nil { + return err + } + + typeCell, err := vm.getMemCell(parent.TypePtr(), mem.CellKindType, false) + if err != nil { + return err + } + + t := typeCell.(value.TypeCell).Get() + + member, ok := t.GetMethod(name) + if !ok { + vm.stack.Push(value.NewNull()) + return nil + } + + if parent.Outlet().IsNull() { + outletPtr, err := vm.memory.Allocate(mem.CellKindOutlet) + if err != nil { + return err + } + parent = parent.WithOutlet(outletPtr) + } + + var envPtr mem.Ptr + if member.Env().IsNull() { + envPtr, err = vm.memory.Allocate(mem.CellKindEnv) + if err != nil { + return err + } + + newEnv := value.NewEnv() + newEnv.Add(0, parent.Outlet()) // stackIndex can be 0, because the parent will be dropped when the function returns. + vm.memory.Set(envPtr, value.EnvCell(newEnv)) + + member = member.WithEnv(envPtr) + } else { + // Clone the environment, with the parent at env 0. + oldEnvCell, err := vm.getMemCell(member.Env(), mem.CellKindEnv, false) + if err != nil { + return err + } + + oldEnv := oldEnvCell.(value.EnvCell).Get() + newEnv := value.NewEnv() + + newEnv.Add(0, parent.Outlet()) + + for i := 0; i < oldEnv.Len(); i++ { + differentOutlet := oldEnv.GetOutlet(i) + if err = vm.memory.Retain(differentOutlet); err != nil { + return err + } + + newEnv.Add(oldEnv.GetStackIndex(i), differentOutlet) + } + + envPtr, err = vm.memory.Allocate(mem.CellKindEnv) + if err != nil { + return err + } + vm.memory.Set(envPtr, value.EnvCell(newEnv)) + member = member.WithEnv(envPtr) + } + + val := value.NewFunction(0).WithData(member) + vm.stack.Push(val) + + parent.Drop(vm.memory) + + return nil +} + func (vm *VM) execGetEnv(envIndex int) error { envCell, err := vm.getMemCell(vm.stack.CurrentCallEnv(), mem.CellKindEnv, false) if err != nil { @@ -136,7 +212,7 @@ func (vm *VM) execAddToEnv(localIndex int) error { return err } - if f.Type().Kind != value.FunctionType { + if f.Type() != value.FunctionType { return ErrInvalidOperandType{ Op: code.OpAddToEnv, X: f.Type(), @@ -206,10 +282,10 @@ func (vm *VM) execAdd() error { var res value.Value - switch x.Type().Kind { + switch x.Type() { case value.IntType: xv := x.Data().(value.IntData).Get() - switch y.Type().Kind { + switch y.Type() { case value.IntType: yv := y.Data().(value.IntData).Get() res = value.NewInt(xv + yv) @@ -225,7 +301,7 @@ func (vm *VM) execAdd() error { } case value.FloatType: xv := x.Data().(value.FloatData).Get() - switch y.Type().Kind { + switch y.Type() { case value.IntType: yv := y.Data().(value.IntData).Get() res = value.NewFloat(xv + float64(yv)) @@ -240,7 +316,7 @@ func (vm *VM) execAdd() error { } } case value.StringType: - switch y.Type().Kind { + switch y.Type() { case value.StringType: panic("not implemented") // res = value.NewString(x.Data().(value.StringData).Get() + y.Data().(value.StringData).Get()) @@ -275,10 +351,10 @@ func (vm *VM) execSub() error { var res value.Value - switch x.Type().Kind { + switch x.Type() { case value.IntType: xv := x.Data().(value.IntData).Get() - switch y.Type().Kind { + switch y.Type() { case value.IntType: yv := y.Data().(value.IntData).Get() res = value.NewInt(xv - yv) @@ -294,7 +370,7 @@ func (vm *VM) execSub() error { } case value.FloatType: xv := x.Data().(value.FloatData).Get() - switch y.Type().Kind { + switch y.Type() { case value.IntType: yv := y.Data().(value.IntData).Get() res = value.NewFloat(xv - float64(yv)) @@ -330,10 +406,10 @@ func (vm *VM) execIndex() error { return err } - switch v.Type().Kind { + switch v.Type() { case value.ArrayType: arr := v.Data().(value.ArrayData) - switch i.Type().Kind { + switch i.Type() { case value.IntType: idx := i.Data().(value.IntData).Get() len, err := arr.Len(vm.memory) @@ -383,10 +459,10 @@ func (vm *VM) execLte() error { var res value.Value - switch x.Type().Kind { + switch x.Type() { case value.IntType: xv := x.Data().(value.IntData).Get() - switch y.Type().Kind { + switch y.Type() { case value.IntType: yv := y.Data().(value.IntData).Get() res = value.NewBool(xv <= yv) @@ -402,7 +478,7 @@ func (vm *VM) execLte() error { } case value.FloatType: xv := x.Data().(value.FloatData).Get() - switch y.Type().Kind { + switch y.Type() { case value.IntType: yv := y.Data().(value.IntData).Get() res = value.NewBool(xv <= float64(yv)) @@ -434,7 +510,7 @@ func (vm *VM) execCall() error { return err } - if f.Type().Kind != value.FunctionType { + if f.Type() != value.FunctionType { return ErrInvalidOperandType{ Op: code.OpCall, X: f.Type(), @@ -471,7 +547,7 @@ func (vm *VM) execJumpIf(pc int, cond bool) error { return err } - switch b.Type().Kind { + switch b.Type() { case value.BoolType: bl := b.Data().(value.BoolData) if bl.Get() == cond { @@ -511,12 +587,12 @@ func (vm *VM) execRet() error { } func (vm *VM) execTempArrLen() error { - a, err := vm.popAndDrop() + a, err := vm.stack.Pop() if err != nil { return err } - switch a.Type().Kind { + switch a.Type() { case value.ArrayType: arr := a.Data().(value.ArrayData) len, err := arr.Len(vm.memory) @@ -525,6 +601,7 @@ func (vm *VM) execTempArrLen() error { } res := value.NewInt(int64(len)) vm.stack.Push(res) + a.Drop(vm.memory) default: return ErrInvalidOperandTypes{ Op: code.OpTempArrLen, @@ -545,7 +622,7 @@ func (vm *VM) execTempArrPush() error { return err } - switch a.Type().Kind { + switch a.Type() { case value.ArrayType: arr := a.Data().(value.ArrayData) arr.Push(vm.memory, e) -- cgit 1.4.1