about summary refs log tree commit diff
path: root/pkg/lang/vm
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-07-28 22:11:02 +0000
committerMel <einebeere@gmail.com>2022-07-28 22:11:02 +0000
commit5a6d4664e4417763b4a7d9f215e42102fa1b3fd4 (patch)
tree525f8151bd1bb604ce015425126c5f3dfc84a32c /pkg/lang/vm
parent95c742ef729a657198be43dc2f295f249860332f (diff)
downloadjinx-5a6d4664e4417763b4a7d9f215e42102fa1b3fd4.tar.zst
jinx-5a6d4664e4417763b4a7d9f215e42102fa1b3fd4.zip
Compile type declarations correctly
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 {