local p = {}
local sollib = require("Module:Complex_Number/Solver")
local calclib = require("Module:Complex_Number/Calculate")
local noop_func = function()end
--mw.log(require("Module:Complex_Number/Calculate").calc("call(object(mw,logObject),string(abc))",p.script.init(),p.script.init().constructor,true,true,function(msg)mw.log("錯誤! "..msg)end))
p.script={
new = function(obj)
if type(obj) == type({}) and obj.isObject then return mw.clone(obj) end
local value = obj
local newObj = {
isObject = true,
value = value
}
newObj.numberType = "object"
setmetatable(newObj,p.script.ObjectMeta)
return newObj
end,['new/doc'] = {name="新物件",title="",othername={},
example="new(string(text))",description="", count = 1},
['string'] = function(str,...)
local result = ''..tostring(str)
local str_list = {...}
for i = 1,#str_list do
result = result .. tostring(str_list[i])
end
return p.script.new(result)
end,['string/doc'] = {name="字串物件",title="",othername={},
example="string(text)",description="", count = 1},
number = function(num)
return p.script.new(tonumber(tostring(num)))
end,['number/doc'] = {name="數字物件",title="",othername={},
example="number(10)",description="", count = 1},
array = function(...)
return p.script.toObject({...})
end,['array/doc'] = {name="陣列物件",title="",othername={},
example="array(1,2,3)",description="", count = "不定"},
newScope = function()
return p.script.toObject({})
end,['newScope/doc'] = {name="新的變數儲存域",title="",othername={},
example="newScope(nil)",description="", count = 1},
object = function(obj,...)
local input_obj = obj
if type(obj) == type({}) and obj.isObject then
input_obj = obj.value
else
if type(obj) == type("string") then input_obj = _G[obj] end
end
if type(input_obj) == type(0) then return p.script.toObject(obj) end
if type(input_obj) == type(noop_func) then return p.script.toObject(obj) end
if input_obj == nil then return p.script.toObject(nil) end
local members = {...}
if #members > 0 then
local it_obj = input_obj
for i = 1,#members do
if type(it_obj) ~= type({}) then return nil end
it_obj = (it_obj or {})[p.script.toObject(members[i]).value]
if it_obj == nil then return nil end
end
return p.script.toObject(it_obj)
end
return p.script.toObject(input_obj)
end,['object/doc'] = {name="物件",title="",othername={},
example="object(mw,site,namespaces,0,displayName)",description="", count = "不定"},
assignMember = function(obj, member, value)
local input_obj = p.script.toObject(obj).value
if type(input_obj) == type("string") then input_obj = _G[input_obj] end
if type(input_obj) == type(0) then error("無法傳值給數字", 2) end
if type(input_obj) == type(noop_func) then error("無法傳值給函數", 2) end
if input_obj == nil then error("無法傳值給空值", 2) end
input_obj[p.script.toObject(member).value] = value
return value
end,['assignMember/doc'] = {name="賦值",title="",othername={},
example="",description="", count = "3"},
call = function(obj, ...)
local func = p.script.toObject(obj).value
if type(func) == type(noop_func) then return func(...)end
return func
end,['call/doc'] = {},
typeof=function(input_obj)
local obj = input_obj
if type(obj) == type({}) and obj.isObject then obj = obj.value end
if type(obj) == type({}) then
if obj.numberType then return p.script.toObject(type(0)) end
local is_array = true
for index, data in pairs(obj) do
if not tonumber(index) and index ~= 'metatable' then
is_array = false
break
end
end
if is_array then return p.script.toObject('array') end
end
return p.script.toObject(type(obj))
end,['typeof/doc'] = {},
equals = function(op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return (obj1 == obj2) and 1 or 0
end,['equals/doc'] = {},
isTrue = function(op)
local obj = p.script.toObject(op)
local val_check = tonumber(tostring(obj.value))
if val_check then
return (math.abs(val_check) > 1e-14) and 1 or 0
end
return obj.value and 1 or 0
end,['isTrue/doc'] = {},
isFalse = function(op)
local obj = p.script.toObject(op)
local val_check = tonumber(tostring(obj.value))
if val_check then
return (math.abs(val_check) > 1e-14) and 0 or 1
end
return obj.value and 0 or 1
end,['isFalse/doc'] = {},
abs = function(op)
local obj = p.script.toObject(op)
if type(obj.value) == type(0) then
return math.abs(tonumber(tostring(obj.value)))
end
return obj.value and 1 or 0
end,
floor=function(op)
local obj = p.script.toObject(op)
return math.floor(obj.value)
end,
ceil=function(op)
local obj = p.script.toObject(op)
return math.ceil(obj.value)
end,
round=function(op1,op2,op3)
local number = p.script.toObject(op1).value
local digs = p.script.toObject(op2).value
local base = p.script.toObject(op3).value
local round_rad = math.pow(base,digs)
local check_number = number * round_rad
check_number = check_number + 0.5
return math.floor( check_number ) / round_rad
end,
div=function(op1,op2)
local obj1 = p.script.toObject(op1)
local obj2 = p.script.toObject(op2)
return obj1.value / obj2.value
end,
re=function(z) return tonumber(tostring(z)) or z end,
im=function(z) return 0 end,
nonRealPart=function(z) return 0 end,
conjugate=function(z) return z end,
inverse=function(op)
local obj = p.script.toObject(op)
return 1 / obj.value
end,
tovector=function(z)
return {z}
end,
trunc=function(op, digs)
local obj = p.script.toObject(op)
local n = tonumber(tostring(digs))
return sollib._trunc(obj.value, n)
end,
digits=function(op)
local obj = p.script.toObject(op)
if type(obj.value) == type("string") then return mw.ustring.len(obj.value) end
local value = math.floor(math.abs(obj.value))
return tostring(value):len()
end,
sqrt=function(op)
local obj = p.script.toObject(op)
return math.sqrt(obj.value)
end,
sin=function(op)
local obj = p.script.toObject(op)
return math.sin(obj.value)
end,
cos=function(op)
local obj = p.script.toObject(op)
return math.cos(obj.value)
end,
tan=function(op)
local obj = p.script.toObject(op)
return math.tan(obj.value)
end,
cot=function(op)
local obj = p.script.toObject(op)
return 1 / math.tan(obj.value)
end,
asin=function(op)
local obj = p.script.toObject(op)
return math.asin(obj.value)
end,
acos=function(op)
local obj = p.script.toObject(op)
return math.acos(obj.value)
end,
atan=function(op)
local obj = p.script.toObject(op)
return math.atan(obj.value)
end,
atan2=function(op1,op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return math.atan2(obj1.value, obj2.value)
end,
acot=function(op)
local obj = p.script.toObject(op)
return math.atan(1/obj.value)
end,
sinh=function(op)
local obj = p.script.toObject(op)
return math.sinh(obj.value)
end,
cosh=function(op)
local obj = p.script.toObject(op)
return math.cosh(obj.value)
end,
tanh=function(op)
local obj = p.script.toObject(op)
return math.tanh(obj.value)
end,
coth=function(op)
local obj = p.script.toObject(op)
return math.cosh(obj.value) / math.sinh(obj.value)
end,
asinh=function(op)
local obj = p.script.toObject(op)
return math.log( obj.value + math.sqrt( obj.value * obj.value + 1 ) )
end,
acosh=function(op)
local obj = p.script.toObject(op)
return math.log( obj.value + math.sqrt( obj.value * obj.value - 1 ) )
end,
atanh=function(op)
local obj = p.script.toObject(op)
return 0.5 * math.log((1+obj.value)/(1-obj.value))
end,
atanh2=function(op1,op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return p.script.atanh(obj1.value / obj2.value)
end,
acoth=function(op)
local obj = p.script.toObject(op)
return 0.5 * math.log((obj.value+1)/(obj.value-1))
end,
exp=function(op)
local obj = p.script.toObject(op)
return math.exp(obj.value)
end,
elog=function(op)
local obj = p.script.toObject(op)
return math.log(obj.value)
end,
log=function(op,basez)
local obj = p.script.toObject(op)
if basez~=nil then return p.script.elog(basez) * p.script.inverse(p.script.elog(op)) end
return math.log(obj.value)
end,
pow=function(op1,op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return math.pow(obj1.value, obj2.value)
end,
random=function(op1,op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
if obj1.value ==nil and obj2.value == nil then return math.random() end
if obj1.value ==nil then return math.random(obj2.value) end
if obj2.value == nil then return math.random(obj1.value) end
return math.random(obj1.value, obj2.value)
end,
isReal=function(z) return not not tonumber(tostring(z)) end,
toObject = function(obj)
if type(obj) == type({}) and obj.isObject then return obj end
return p.script.new(obj)
end,
loadObject = function(obj)
if type(obj) == type({}) and obj.isObject then return obj end
return tonumber(obj)
end,
ObjectMeta = {
__add = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
if type(obj1.value) == type("string") or type(obj2.value) == type("string") then
return p.script.new(tostring(op1.value) .. tostring(obj2.value))
elseif type(obj1.value) == type(0) and type(obj2.value) == type(0) then
return p.script.new(obj1.value + obj2.value)
elseif type(obj1.value) == type({}) and type(obj2.value) == type({}) then
local result = {}
for k,v in pairs(obj1.value) do result[k] = v end
for k,v in pairs(obj2.value) do result[k] = result[k] or v end
return p.script.new(result)
end
return p.script.new(obj1.value + obj2.value)
end,
__sub = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
if type(obj1.value) == type("string") or type(obj2.value) == type("string") then
local str1, str2 = tostring(obj1.value), tostring(obj2.value)
if obj1.value == obj2.value then return 0 end
local keys = {str1, str2}
table.sort(keys)
return (keys[1] == str1) and -1 or 1
elseif type(obj1.value) == type(true) or type(obj2.value) == type(true) then
local bool1, bool2 = (not obj1.value) and 0 or 1, (not obj2.value) and 0 or 1
return math.max(bool1 - bool2, 0)
elseif type(obj1.value) == type(nil) or type(obj2.value) == type(nil) then
if obj1.value == obj2.value then return 0 end
return (obj1.value == nil) and -1 or 1
end
if obj1.value == obj2.value then return 0 end
return p.script.new(obj1.value - obj2.value)
end,
__mul = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return p.script.new(obj1.value * obj2.value)
end,
__div = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return p.script.new(obj1.value / obj2.value)
end,
__mod = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return p.script.new(obj1.value % obj2.value)
end,
__tostring = function (obj)
local this = p.script.toObject(obj)
local typeof = p.script.typeof(this)
if typeof == 'array' then
local result = ''
for i=1,#(this.value) do
if result ~= '' then result = result .. ', ' end
result = result .. tostring(this.value[i] or 'nil')
end
return '{' .. result .. '}'
end
return tostring(this.value or 'nil')
end,
__unm = function (obj)
local this = p.script.new(obj)
this.value = -this.value
return this
end,
__eq = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return obj1.value == obj2.value
end,
__lt = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return obj1.value < obj2.value
end,
__le = function (op1, op2)
local obj1, obj2 = p.script.toObject(op1), p.script.toObject(op2)
return obj1.value <= obj2.value
end,
},
init = function()
p.script['true'] = 1;p.script['true/doc']={}
p.script['false'] = 0;p.script['false/doc']={}
p.script['nil'] = p.script.toObject()
p.script.emptyString = p.script.new("");p.script['emptyString/doc']={}
p.script.numberType = sollib._numberType
p.script.constructor = p.script.loadObject
return p.script
end
}
function p.run(script)
local code = script
if type(script) == type({}) then code = (script.args or script)[1]
elseif type(script) ~= type("string") then tostring(code) end
local scriptlib = p.script.init()
return calclib.calc(code, scriptlib, scriptlib.constructor)
end
function p.runScope(script)
local code = script
if type(script) == type({}) then code = (script.args or script)[1]
elseif type(script) ~= type("string") then tostring(code) end
local scriptlib = p.script.init()
return calclib.calc("scope←newScope(nil);mainFunction:scope↦"..((mw.text.trim(code)=='') and 'nil' or code)..";(scope)", scriptlib, scriptlib.constructor)
end
return p