summaryrefslogtreecommitdiff
path: root/script/vm/getDef.lua
blob: 339053e4418e83d4deca525afe4e4dffeeae7802 (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
---@class vm
local vm       = require 'vm.vm'
local util     = require 'utility'
local compiler = require 'vm.node.compiler'
local guide    = require 'parser.guide'

local simpleMap

local function searchGetLocal(source, node, results)
    local key = guide.getKeyName(source)
    for _, ref in ipairs(node.node.ref) do
        if  ref.type == 'getlocal'
        and guide.isSet(ref.next)
        and guide.getKeyName(ref.next) == key then
            results[#results+1] = ref.next
        end
    end
end

simpleMap = util.switch()
    : case 'local'
    : call(function (source, results)
        results[#results+1] = source
        if source.ref then
            for _, ref in ipairs(source.ref) do
                if ref.type == 'setlocal' then
                    results[#results+1] = ref
                end
            end
        end

        if source.dummy then
            for _, res in ipairs(vm.getDefs(source.method.node)) do
                results[#results+1] = res
            end
        end
    end)
    : case 'getlocal'
    : case 'setlocal'
    : call(function (source, results)
        simpleMap['local'](source.node, results)
    end)
    : case 'field'
    : call(function (source, results)
        local node = source.parent.node
        if node.type == 'getlocal' then
            searchGetLocal(source, node, results)
        end
    end)
    : case 'setfield'
    : case 'getfield'
    : call(function (source, results)
        simpleMap['field'](source.field, results)
    end)
    : case 'getindex'
    : case 'setindex'
    : call(function (source, results)
        local node = source.node
        if node.type == 'getlocal' then
            searchGetLocal(source, node, results)
        end
    end)
    : getMap()

local searchFieldMap = util.switch()
    : case 'table'
    : call(function (node, key, results)
        for _, field in ipairs(node) do
            if field.type == 'tablefield'
            or field.type == 'tableindex' then
                if guide.getKeyName(field) == key then
                    results[#results+1] = field
                end
            end
        end
    end)
    : getMap()

local compiledMap;compiledMap = util.switch()
    : case 'field'
    : call(function (source, results)
        local parent = source.parent
        compiledMap[parent.type](parent, results)
    end)
    : case 'getfield'
    : case 'setfield'
    : call(function (source, results)
        local node = compiler.compileNode(guide.getUri(source.node), source.node)
        if not node then
            return
        end
        if searchFieldMap[node.type] then
            searchFieldMap[node.type](node, guide.getKeyName(source), results)
        end
    end)
    : getMap()

---@param source  parser.object
---@param results parser.object[]
local function searchBySimple(source, results)
    local simple = simpleMap[source.type]
    if simple then
        simple(source, results)
    end
end

---@param source  parser.object
---@param results parser.object[]
local function searchByGlobal(source, results)
    if source.type == 'field' then
        source = source.parent
    end
    local global = source._globalID
    if not global then
        return
    end
    for _, src in ipairs(global:getSets()) do
        results[#results+1] = src
    end
end

---@param source  parser.object
---@param results parser.object[]
local function searchByCompiled(source, results)
    local compiled = compiledMap[source.type]
    if compiled then
        compiled(source, results)
    end
end

---@param source parser.object
---@return       parser.object[]
function vm.getDefs(source)
    local results = {}

    searchBySimple(source, results)
    searchByGlobal(source, results)
    searchByCompiled(source, results)

    return results
end

---@param source parser.object
---@return       parser.object[]
function vm.getAllDefs(source)
    return vm.getDefs(source)
end