From edca72c160967f1918b65c91a40de89ecd8badda Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 1 Jun 2022 19:51:40 +0000 Subject: Implement proper object types --- pkg/lang/vm/core.go | 71 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 14 deletions(-) (limited to 'pkg/lang/vm/core.go') 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 { -- cgit 1.4.1