From 5a6d4664e4417763b4a7d9f215e42102fa1b3fd4 Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 28 Jul 2022 22:11:02 +0000 Subject: Compile type declarations correctly --- pkg/lang/vm/exec.go | 44 ++++++++++++++++++++++++++++++++++---------- pkg/lang/vm/value/data.go | 11 +++++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) (limited to 'pkg/lang/vm') diff --git a/pkg/lang/vm/exec.go b/pkg/lang/vm/exec.go index 5a8eb05..353d8ac 100644 --- a/pkg/lang/vm/exec.go +++ b/pkg/lang/vm/exec.go @@ -208,17 +208,11 @@ func (vm *VM) execGetMember(name string) error { if parent.Type() == value.TypeRefType { ref := parent.Data().(value.TypeRefData) - ptr := ref.TypeRef() - - cell, err := vm.getMemCell(ptr, mem.CellKindType, false) + ok, methodData, err := ref.GetMethod(vm.memory, name) if err != nil { return err } - typ := cell.(value.TypeCell).Get() - - methodData, ok := typ.GetMethod(name) - if !methodData.Env().IsNull() { panic("methods with environments not implemented yet") } @@ -831,15 +825,45 @@ func (vm *VM) execCall(argCount uint) error { return err } - if f.Type() != value.FunctionType { + var fn value.FunctionData + // Constructor call + if f.Type() == value.TypeRefType { + t := f.Data().(value.TypeRefData) + ok, initMethod, err := t.GetMethod(vm.memory, "$init") + if err != nil { + return err + } + + if !ok { + panic("constructor not found on type") + } + + // TODO: Very unsure about this, it's duplicated from execGetMember, probably need to refactor. + if f.Outlet().IsNull() { + outletPtr, err := vm.memory.Allocate(mem.CellKindOutlet) + if err != nil { + return err + } + f = f.WithOutlet(outletPtr) + } + + newEnv := value.NewEnv() + newEnv.Add(0, f.Outlet()) + envPtr, err := newEnv.Allocate(vm.memory) + if err != nil { + return err + } + + fn = initMethod.WithEnv(envPtr) + } else if f.Type() == value.FunctionType { + fn = f.Data().(value.FunctionData) + } else { return ErrInvalidOperandType{ Op: code.OpCall, X: f.Type(), } } - fn := f.Data().(value.FunctionData) - if argCount != fn.Args() { return ErrWrongNumberOfArguments{ Got: argCount, diff --git a/pkg/lang/vm/value/data.go b/pkg/lang/vm/value/data.go index 6c3d762..6ec7be9 100644 --- a/pkg/lang/vm/value/data.go +++ b/pkg/lang/vm/value/data.go @@ -180,6 +180,17 @@ func (t TypeRefData) TypeRef() mem.Ptr { return t.typeRef } +func (t TypeRefData) GetMethod(m mem.Mem, name string) (bool, FunctionData, error) { + cell, err := m.Get(t.typeRef) + if err != nil { + return false, FunctionData{}, err + } + + typ := cell.(TypeCell).Get() + method, ok := typ.Methods[name] + return ok, method, nil +} + func (t TypeRefData) AddMethod(m mem.Mem, name string, method FunctionData) error { cell, err := m.Get(t.typeRef) if err != nil { -- cgit 1.4.1