about summary refs log tree commit diff
path: root/pkg/lang/vm
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm')
-rw-r--r--pkg/lang/vm/exec.go44
-rw-r--r--pkg/lang/vm/value/data.go11
2 files changed, 45 insertions, 10 deletions
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 {