about summary refs log tree commit diff
path: root/pkg/lang/vm/core.go
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-06-01 19:51:40 +0000
committerGitHub <noreply@github.com>2022-06-01 19:51:40 +0000
commitedca72c160967f1918b65c91a40de89ecd8badda (patch)
treeb79feabc0889a3f6cfddf09906a486d09e5c60a1 /pkg/lang/vm/core.go
parent33671436680e7922001df9921ee582c486c7c3f4 (diff)
downloadjinx-edca72c160967f1918b65c91a40de89ecd8badda.tar.zst
jinx-edca72c160967f1918b65c91a40de89ecd8badda.zip
Implement proper object types
Diffstat (limited to 'pkg/lang/vm/core.go')
-rw-r--r--pkg/lang/vm/core.go71
1 files changed, 57 insertions, 14 deletions
diff --git a/pkg/lang/vm/core.go b/pkg/lang/vm/core.go
index 9796a11..59dcaed 100644
--- a/pkg/lang/vm/core.go
+++ b/pkg/lang/vm/core.go
@@ -50,27 +50,70 @@ func (vm *VM) createCoreFunctionType() value.Type {
 	}
 }
 
+func (vm *VM) createCoreTypeRefType() value.Type {
+	return value.Type{
+		Kind: value.TypeRefType,
+		Methods: map[string]value.FunctionData{
+			"$add_method": makeCoreFn(vm.coreTypeRefIntrAddMethod, 2),
+		},
+	}
+}
+
 func (vm *VM) coreArrayLength(args []value.Value) (value.Value, error) {
-	a, err := vm.getThis()
+	a, err := ensureTypeThis[value.ArrayData](vm, value.ArrayType)
 	if err != nil {
 		return value.Value{}, err
 	}
 
-	switch a.Type() {
-	case value.ArrayType:
-		arr := a.Data().(value.ArrayData)
-		len, err := arr.Len(vm.memory)
-		if err != nil {
-			return value.Value{}, err
-		}
-		res := value.NewInt(int64(len))
-		return res, nil
-	default:
-		return value.Value{}, ErrInvalidOperandType{
-			Op: code.OpTempArrLen,
-			X:  a.Type(),
+	len, err := a.Len(vm.memory)
+	if err != nil {
+		return value.Value{}, err
+	}
+	res := value.NewInt(int64(len))
+	return res, nil
+}
+
+func (vm *VM) coreTypeRefIntrAddMethod(args []value.Value) (value.Value, error) {
+	ref, err := ensureTypeThis[value.TypeRefData](vm, value.TypeRefType)
+	if err != nil {
+		return value.Value{}, err
+	}
+
+	nameData, err := ensureType[value.StringData](args[0], value.StringType)
+	if err != nil {
+		return value.Value{}, err
+	}
+	name, err := nameData.RawString(vm.memory)
+	if err != nil {
+		return value.Value{}, err
+	}
+
+	fn, err := ensureType[value.FunctionData](args[1], value.FunctionType)
+	if err != nil {
+		return value.Value{}, err
+	}
+
+	return value.Value{}, ref.AddMethod(vm.memory, name, fn)
+}
+
+func ensureTypeThis[D value.Data](vm *VM, t value.TypeKind) (D, error) {
+	this, err := vm.getThis()
+	if err != nil {
+		return *new(D), err
+	}
+
+	return ensureType[D](this, t)
+}
+
+func ensureType[D value.Data](val value.Value, t value.TypeKind) (D, error) {
+	if val.Type() != t {
+		return *new(D), ErrInvalidOperandType{
+			Op: code.OpNop, // TODO: Add error not dependent on op.
+			X:  val.Type(),
 		}
 	}
+
+	return val.Data().(D), nil
 }
 
 func makeCoreFn(f value.NativeFunc, argCount uint) value.FunctionData {