summaryrefslogtreecommitdiff
path: root/script/src/vm/special.lua
blob: e93c444558e656b5dd9fced56a32d3608344275c (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
local mt             = require 'vm.manager'
local multi          = require 'vm.multi'
local library        = require 'core.library'
local libraryBuilder = require 'vm.library'
local plugin         = require 'plugin'

---@param func emmyFunction
---@param values table
function mt:callEmmySpecial(func, values, source)
    local emmyParams = func:getEmmyParams()
    for index, param in ipairs(emmyParams) do
        local option = param:getOption()
        if option and type(option.special) == 'string' then
            self:checkEmmyParam(func, values, index, option.special, source)
        end
    end
end

---@param func emmyFunction
---@param values table
---@param index integer
---@param special string
function mt:checkEmmyParam(func, values, index, special, source)
    if special == 'dofile:1' then
        self:callEmmyDoFile(func, values, index)
    elseif special == 'loadfile:1' then
        self:callEmmyLoadFile(func, values, index)
    elseif special == 'pcall:1' then
        self:callEmmyPCall(func, values, index, source)
    elseif special == 'require:1' then
        self:callEmmyRequire(func, values, index)
    end
end

---@param func emmyFunction
---@param values table
---@param index integer
function mt:callEmmyDoFile(func, values, index)
    if not values[index] then
        values[index] = self:createValue('any', self:getDefaultSource())
    end
    local str = values[index]:getLiteral()
    if type(str) ~= 'string' then
        return
    end
    local requireValue = self:tryRequireOne(str, values[index], 'dofile')
    if not requireValue then
        requireValue = self:createValue('any', self:getDefaultSource())
        requireValue.isRequire = true
    end
    func:setReturn(1, requireValue)
end

---@param func emmyFunction
---@param values table
---@param index integer
function mt:callEmmyLoadFile(func, values, index)
    if not values[index] then
        values[index] = self:createValue('any', self:getDefaultSource())
    end
    local str = values[index]:getLiteral()
    if type(str) ~= 'string' then
        return
    end
    local requireValue = self:tryRequireOne(str, values[index], 'loadfile')
    if not requireValue then
        requireValue = self:createValue('any', self:getDefaultSource())
        requireValue:set('cross file', true)
    end
    func:setReturn(1, requireValue)
end

---@param func emmyFunction
---@param values table
---@param index integer
---@param source source
function mt:callEmmyPCall(func, values, index, source)
    local funcValue = values[index]
    if not funcValue then
        return
    end
    local realFunc = funcValue:getFunction()
    if not realFunc then
        return
    end
    local argList = multi()
    values:eachValue(function (i, v)
        if i > index then
            argList:push(v)
        end
    end)
    self:call(funcValue, argList, source)
    if realFunc ~= func then
        func:setReturn(1, self:createValue('boolean', source))
        realFunc:getReturn():eachValue(function (i, v)
            func:setReturn(i + 1, v)
        end)
    end
end

---@param func emmyFunction
---@param values table
---@param index integer
function mt:callEmmyRequire(func, values, index)
    if not values[index] then
        values[index] = self:createValue('any', self:getDefaultSource())
    end
    local strValue = values[index]
    local strSource = strValue:getSource()
    if not strSource then
        return nil
    end
    local str = strValue:getLiteral()
    local raw = self.text:sub(strSource.start, strSource.finish)
    str = plugin.call('OnRequirePath', str, raw) or str
    local lib = library.library[str]
    if lib then
        local value = libraryBuilder.value(lib)
        value:markGlobal()
        func:setReturn(1, value)
        return
    else
        local requireValue = self:tryRequireOne(str, strValue, 'require')
        if not requireValue then
            requireValue = self:createValue('any', self:getDefaultSource())
            requireValue:set('cross file', true)
        end
        func:setReturn(1, requireValue)
    end
end