about summary refs log tree commit diff
path: root/pkg/lang/vm/core.go
blob: e482211d8b8b62c9ea07af1776cef8777987c036 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package vm

import (
	"jinx/pkg/lang/vm/code"
	"jinx/pkg/lang/vm/value"
)

func (vm *VM) createCoreNullType() value.Type {
	return value.Type{
		Kind: value.NullType,
	}
}

func (vm *VM) createCoreIntType() value.Type {
	return value.Type{
		Kind: value.IntType,
	}
}

func (vm *VM) createCoreFloatType() value.Type {
	return value.Type{
		Kind: value.FloatType,
	}
}

func (vm *VM) createCoreStringType() value.Type {
	return value.Type{
		Kind: value.StringType,
	}
}

func (vm *VM) createCoreBoolType() value.Type {
	return value.Type{
		Kind: value.BoolType,
	}
}

func (vm *VM) createCoreArrayType() value.Type {
	return value.Type{
		Kind: value.ArrayType,
		Methods: map[string]value.FunctionData{
			"length": makeCoreFn(vm.coreArrayLength),
		},
	}
}

func (vm *VM) createCoreFunctionType() value.Type {
	return value.Type{
		Kind: value.FunctionType,
	}
}

func (vm *VM) coreArrayLength(args []value.Value) (value.Value, error) {
	a, err := vm.getThis()
	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(),
		}
	}
}

func makeCoreFn(f value.NativeFunc) value.FunctionData {
	return value.NewNativeFunction(f).Data().(value.FunctionData)
}

func (vm *VM) getThis() (value.Value, error) {
	err := vm.execGetEnv(0)
	if err != nil {
		return value.Value{}, err
	}

	// Take it back!
	this, err := vm.popAndDrop()
	if err != nil {
		return value.Value{}, err
	}

	return this, nil
}