TemplateCommon.lua.txt 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. -- Tencent is pleased to support the open source community by making xLua available.
  2. -- Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  3. -- Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
  4. -- http://opensource.org/licenses/MIT
  5. -- Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  6. local friendlyNameMap = {
  7. ["System.Object"] = "object",
  8. ["System.String"] = "string",
  9. ["System.Boolean"] = "bool",
  10. ["System.Byte"] = "byte",
  11. ["System.Char"] = "char",
  12. ["System.Decimal"] = "decimal",
  13. ["System.Double"] = "double",
  14. ["System.Int16"] = "short",
  15. ["System.Int32"] = "int",
  16. ["System.Int64"] = "long",
  17. ["System.SByte"] = "sbyte",
  18. ["System.Single"] = "float",
  19. ["System.UInt16"] = "ushort",
  20. ["System.UInt32"] = "uint",
  21. ["System.UInt64"] = "ulong",
  22. ["System.Void"] = "void",
  23. }
  24. local csKeywords = {
  25. "abstract", "as", "base", "bool",
  26. "break", "byte", "case", "catch",
  27. "char", "checked", "class", "const",
  28. "continue", "decimal", "default", "delegate",
  29. "do", "double", "else", "enum",
  30. "event", "explicit", "extern", "false",
  31. "finally", "fixed", "float", "for",
  32. "foreach", "goto", "if", "implicit",
  33. "in", "int", "interface",
  34. "internal", "is", "lock", "long",
  35. "namespace", "new", "null", "object",
  36. "operator", "out", "override",
  37. "params", "private", "protected", "public",
  38. "readonly", "ref", "return", "sbyte",
  39. "sealed", "short", "sizeof", "stackalloc",
  40. "static", "string", "struct", "switch",
  41. "this", "throw", "true", "try",
  42. "typeof", "uint", "ulong", "unchecked",
  43. "unsafe", "ushort", "using", "virtual",
  44. "void", "volatile", "while"
  45. }
  46. for _, kw in ipairs(csKeywords) do
  47. csKeywords[kw] = '@'..kw
  48. end
  49. for i = 1, #csKeywords do
  50. csKeywords[i] = nil
  51. end
  52. function UnK(symbol)
  53. return csKeywords[symbol] or symbol
  54. end
  55. local fixChecker = {
  56. --["System.String"] = "LuaAPI.lua_isstring",
  57. ["System.Boolean"] = "LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type",
  58. ["System.Byte"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  59. ["System.Char"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  60. --["System.Decimal"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  61. ["System.Double"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  62. ["System.Int16"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  63. ["System.Int32"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  64. --["System.Int64"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  65. ["System.SByte"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  66. ["System.Single"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  67. ["System.UInt16"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  68. ["System.UInt32"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  69. --["System.UInt64"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
  70. ["System.IntPtr"] = "LuaTypes.LUA_TLIGHTUSERDATA == LuaAPI.lua_type",
  71. }
  72. local typedCaster = {
  73. ["System.Byte"] = "LuaAPI.xlua_tointeger",
  74. ["System.Char"] = "LuaAPI.xlua_tointeger",
  75. ["System.Int16"] = "LuaAPI.xlua_tointeger",
  76. ["System.SByte"] = "LuaAPI.xlua_tointeger",
  77. ["System.Single"] = "LuaAPI.lua_tonumber",
  78. ["System.UInt16"] = "LuaAPI.xlua_tointeger",
  79. }
  80. local fixCaster = {
  81. ["System.Double"] = "LuaAPI.lua_tonumber",
  82. ["System.String"] = "LuaAPI.lua_tostring",
  83. ["System.Boolean"] = "LuaAPI.lua_toboolean",
  84. ["System.Byte[]"] = "LuaAPI.lua_tobytes",
  85. ["System.IntPtr"] = "LuaAPI.lua_touserdata",
  86. ["System.UInt32"] = "LuaAPI.xlua_touint",
  87. ["System.UInt64"] = "LuaAPI.lua_touint64",
  88. ["System.Int32"] = "LuaAPI.xlua_tointeger",
  89. ["System.Int64"] = "LuaAPI.lua_toint64",
  90. }
  91. local fixPush = {
  92. ["System.Byte"] = "LuaAPI.xlua_pushinteger",
  93. ["System.Char"] = "LuaAPI.xlua_pushinteger",
  94. ["System.Int16"] = "LuaAPI.xlua_pushinteger",
  95. ["System.Int32"] = "LuaAPI.xlua_pushinteger",
  96. ["System.Int64"] = "LuaAPI.lua_pushint64",
  97. ["System.SByte"] = "LuaAPI.xlua_pushinteger",
  98. ["System.Single"] = "LuaAPI.lua_pushnumber",
  99. ["System.UInt16"] = "LuaAPI.xlua_pushinteger",
  100. ["System.UInt32"] = "LuaAPI.xlua_pushuint",
  101. ["System.UInt64"] = "LuaAPI.lua_pushuint64",
  102. ["System.Double"] = "LuaAPI.lua_pushnumber",
  103. ["System.String"] = "LuaAPI.lua_pushstring",
  104. ["System.Byte[]"] = "LuaAPI.lua_pushstring",
  105. ["System.Boolean"] = "LuaAPI.lua_pushboolean",
  106. ["System.IntPtr"] = "LuaAPI.lua_pushlightuserdata",
  107. ["System.Decimal"] = "translator.PushDecimal",
  108. ["System.Object"] = "translator.PushAny",
  109. }
  110. local notranslator = {
  111. ["System.Byte"] = true,
  112. ["System.Char"] = true,
  113. ["System.Int16"] = true,
  114. ["System.Int32"] = true,
  115. ["System.Int64"] = true,
  116. ["System.SByte"] = true,
  117. ["System.Single"] = true,
  118. ["System.UInt16"] = true,
  119. ["System.UInt32"] = true,
  120. ["System.UInt64"] = true,
  121. ["System.Double"] = true,
  122. ["System.String"] = true,
  123. ["System.Boolean"] = true,
  124. ["System.Void"] = true,
  125. ["System.IntPtr"] = true,
  126. ["System.Byte[]"] = true,
  127. }
  128. function ForEachCsList(...)
  129. local list_count = select('#', ...) - 1
  130. local callback = select(list_count + 1, ...)
  131. for i = 1, list_count do
  132. local list = select(i, ...)
  133. for i = 0, (list.Count or list.Length) - 1 do
  134. callback(list[i], i)
  135. end
  136. end
  137. end
  138. function CalcCsList(list, predicate)
  139. local count = 0
  140. for i = 0, (list.Count or list.Length) - 1 do
  141. if predicate(list[i], i) then count = count + 1 end
  142. end
  143. return count
  144. end
  145. function IfAny(list, predicate)
  146. for i = 0, (list.Count or list.Length) - 1 do
  147. if predicate(list[i], i) then return true end
  148. end
  149. return false
  150. end
  151. local genPushAndUpdateTypes
  152. function SetGenPushAndUpdateTypes(list)
  153. genPushAndUpdateTypes = {}
  154. ForEachCsList(list, function(t)
  155. genPushAndUpdateTypes[t] = true
  156. end)
  157. end
  158. local xLuaClasses
  159. function SetXLuaClasses(list)
  160. xLuaClasses = {}
  161. ForEachCsList(list, function(t)
  162. xLuaClasses[t.Name] = true
  163. end)
  164. end
  165. local objType = typeof(CS.System.Object)
  166. local valueType = typeof(CS.System.ValueType)
  167. local function _CsFullTypeName(t)
  168. if t.IsArray then
  169. local element_name, element_is_array = _CsFullTypeName(t:GetElementType())
  170. if element_is_array then
  171. local bracket_pos = element_name:find('%[')
  172. return element_name:sub(1, bracket_pos - 1) .. '[' .. string.rep(',', t:GetArrayRank() - 1) .. ']' .. element_name:sub(bracket_pos, -1), true
  173. else
  174. return element_name .. '[' .. string.rep(',', t:GetArrayRank() - 1) .. ']', true
  175. end
  176. elseif t.IsByRef then
  177. return _CsFullTypeName(t:GetElementType())
  178. elseif t.IsGenericParameter then
  179. return (t.BaseType == objType or t.BaseType == valueType) and t.Name or _CsFullTypeName(t.BaseType) --TODO:应该判断是否类型约束
  180. end
  181. local name = t.FullName:gsub("&", ""):gsub("%+", ".")
  182. if not t.IsGenericType then
  183. return friendlyNameMap[name] or name
  184. end
  185. local genericParameter = ""
  186. ForEachCsList(t:GetGenericArguments(), function(at, ati)
  187. if ati ~= 0 then genericParameter = genericParameter .. ', ' end
  188. genericParameter = genericParameter .. _CsFullTypeName(at)
  189. end)
  190. return name:gsub("`%d+", '<' .. genericParameter .. '>'):gsub("%[[^,%]].*", ""), false
  191. end
  192. function CsFullTypeName(t)
  193. if t.DeclaringType then
  194. local name = _CsFullTypeName(t)
  195. local declaringTypeName = _CsFullTypeName(t.DeclaringType);
  196. return xLuaClasses[declaringTypeName] and ("global::" .. name) or name
  197. else
  198. local name = _CsFullTypeName(t)
  199. return xLuaClasses[name] and ("global::" .. name) or name
  200. end
  201. end
  202. function CSVariableName(t)
  203. if t.IsArray then
  204. return CSVariableName(t:GetElementType()) .. '_'.. t:GetArrayRank() ..'_'
  205. end
  206. return t:ToString():gsub("&", ""):gsub("%+", ""):gsub("`", "_"):gsub("%.", ""):gsub("%[", "_"):gsub("%]", "_"):gsub(",", "")
  207. end
  208. local function getSafeFullName(t)
  209. if t == nil then
  210. return ""
  211. end
  212. if t.IsGenericParameter then
  213. return t.BaseType == objType and t.Name or getSafeFullName(t.BaseType)
  214. end
  215. if not t.FullName then return "" end
  216. return t.FullName:gsub("&", "")
  217. end
  218. function GetCheckStatement(t, idx, is_v_params)
  219. local cond_start = is_v_params and "(LuaTypes.LUA_TNONE == LuaAPI.lua_type(L, ".. idx ..") || " or ""
  220. local cond_end = is_v_params and ")" or ""
  221. local testname = getSafeFullName(t)
  222. if testname == "System.String" or testname == "System.Byte[]" then
  223. return cond_start .. "(LuaAPI.lua_isnil(L, " .. idx .. ") || LuaAPI.lua_type(L, ".. idx ..") == LuaTypes.LUA_TSTRING)" .. cond_end
  224. elseif testname == "System.Int64" then
  225. return cond_start .. "(LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, ".. idx ..") || LuaAPI.lua_isint64(L, ".. idx .."))" .. cond_end
  226. elseif testname == "System.UInt64" then
  227. return cond_start .. "(LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, ".. idx ..") || LuaAPI.lua_isuint64(L, ".. idx .."))" .. cond_end
  228. elseif testname == "System.Decimal" then
  229. return cond_start .. "(LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, ".. idx ..") || translator.IsDecimal(L, ".. idx .."))" .. cond_end
  230. elseif testname == "XLua.LuaTable" then
  231. return cond_start .. "(LuaAPI.lua_isnil(L, " .. idx .. ") || LuaAPI.lua_type(L, ".. idx ..") == LuaTypes.LUA_TTABLE)" .. cond_end
  232. elseif testname == "XLua.LuaFunction" then
  233. return cond_start .. "(LuaAPI.lua_isnil(L, " .. idx .. ") || LuaAPI.lua_type(L, ".. idx ..") == LuaTypes.LUA_TFUNCTION)" .. cond_end
  234. end
  235. return cond_start .. (fixChecker[testname] or ("translator.Assignable<" .. CsFullTypeName(t).. ">")) .. "(L, ".. idx ..")" .. cond_end
  236. end
  237. local delegateType = typeof(CS.System.Delegate)
  238. local ExtensionAttribute = typeof(CS.System.Runtime.CompilerServices.ExtensionAttribute)
  239. function IsExtensionMethod(method)
  240. return method:IsDefined(ExtensionAttribute, false)
  241. end
  242. function IsDelegate(t)
  243. return delegateType:IsAssignableFrom(t)
  244. end
  245. function MethodParameters(method)
  246. if not IsExtensionMethod(method) then
  247. return method:GetParameters()
  248. else
  249. local parameters = method:GetParameters()
  250. if parameters[0].ParameterType.IsInterface then
  251. return parameters
  252. end
  253. local ret = {}
  254. for i = 1, parameters.Length - 1 do
  255. ret[i - 1] = parameters[i]
  256. end
  257. ret.Length = parameters.Length - 1
  258. return ret
  259. end
  260. end
  261. function IsStruct(t)
  262. if t.IsByRef then t = t:GetElementType() end
  263. return t.IsValueType and not t.IsPrimitive
  264. end
  265. function NeedUpdate(t)
  266. if t.IsByRef then t = t:GetElementType() end
  267. return t.IsValueType and not t.IsPrimitive and not t.IsEnum and t ~= typeof(CS.System.Decimal)
  268. end
  269. function GetCasterStatement(t, idx, var_name, need_declare, is_v_params)
  270. local testname = getSafeFullName(t)
  271. local statement = ""
  272. local is_struct = IsStruct(t)
  273. if need_declare then
  274. statement = CsFullTypeName(t) .. " " .. var_name
  275. if is_struct and not typedCaster[testname] and not fixCaster[testname] then
  276. statement = statement .. ";"
  277. else
  278. statement = statement .. " = "
  279. end
  280. elseif not is_struct then
  281. statement = var_name .. " = "
  282. end
  283. if is_v_params then
  284. return statement .. "translator.GetParams<" .. CsFullTypeName(t:GetElementType()).. ">" .. "(L, ".. idx ..")"
  285. elseif typedCaster[testname] then
  286. return statement .. "(" .. CsFullTypeName(t) .. ")" ..typedCaster[testname] .. "(L, ".. idx ..")"
  287. elseif IsDelegate(t) then
  288. return statement .. "translator.GetDelegate<" .. CsFullTypeName(t).. ">" .. "(L, ".. idx ..")"
  289. elseif fixCaster[testname] then
  290. return statement .. fixCaster[testname] .. "(L, ".. idx ..")"
  291. elseif testname == "System.Object" then
  292. return statement .. "translator.GetObject(L, ".. idx ..", typeof(" .. CsFullTypeName(t) .."))"
  293. elseif is_struct then
  294. return statement .. "translator.Get(L, ".. idx ..", out " .. var_name .. ")"
  295. elseif t.IsGenericParameter and not t.DeclaringMethod then
  296. return statement .. "translator.GetByType<"..t.Name..">(L, ".. idx ..")"
  297. else
  298. return statement .. "("..CsFullTypeName(t)..")translator.GetObject(L, ".. idx ..", typeof(" .. CsFullTypeName(t) .."))"
  299. end
  300. end
  301. local paramsAttriType = typeof(CS.System.ParamArrayAttribute)
  302. function IsParams(pi)
  303. if (not pi.IsDefined) then
  304. return pi.IsParamArray
  305. end
  306. return pi:IsDefined(paramsAttriType, false)
  307. end
  308. local obsoluteAttriType = typeof(CS.System.ObsoleteAttribute)
  309. function IsObsolute(f)
  310. return f:IsDefined(obsoluteAttriType, false)
  311. end
  312. local objectType = typeof(CS.System.Object)
  313. function GetSelfStatement(t)
  314. local fulltypename = CsFullTypeName(t)
  315. local is_struct = IsStruct(t)
  316. if is_struct then
  317. return fulltypename .. " gen_to_be_invoked;translator.Get(L, 1, out gen_to_be_invoked)"
  318. else
  319. if t == objectType then
  320. return "object gen_to_be_invoked = translator.FastGetCSObj(L, 1)"
  321. else
  322. return fulltypename .. " gen_to_be_invoked = (" .. fulltypename .. ")translator.FastGetCSObj(L, 1)"
  323. end
  324. end
  325. end
  326. local GetNullableUnderlyingType = CS.System.Nullable.GetUnderlyingType
  327. function GetPushStatement(t, variable, is_v_params)
  328. if is_v_params then
  329. local item_push = GetPushStatement(t:GetElementType(), variable..'[__gen_i]')
  330. return 'if ('.. variable ..' != null) { for (int __gen_i = 0; __gen_i < ' .. variable .. '.Length; ++__gen_i) ' .. item_push .. '; }'
  331. end
  332. if t.IsByRef then t = t:GetElementType() end
  333. local testname = getSafeFullName(t)
  334. if fixPush[testname] then
  335. return fixPush[testname] .. "(L, ".. variable ..")"
  336. elseif genPushAndUpdateTypes[t] then
  337. return "translator.Push".. CSVariableName(t) .."(L, "..variable..")"
  338. elseif t.IsGenericParameter and not t.DeclaringMethod then
  339. return "translator.PushByType(L, "..variable..")"
  340. elseif t.IsInterface or GetNullableUnderlyingType(t) then
  341. return "translator.PushAny(L, "..variable..")"
  342. else
  343. return "translator.Push(L, "..variable..")"
  344. end
  345. end
  346. function GetUpdateStatement(t, idx, variable)
  347. if t.IsByRef then t = t:GetElementType() end
  348. if typeof(CS.System.Decimal) == t then error('Decimal not update!') end
  349. if genPushAndUpdateTypes[t] then
  350. return "translator.Update".. CSVariableName(t) .."(L, ".. idx ..", "..variable..")"
  351. else
  352. return "translator.Update(L, ".. idx ..", "..variable..")"
  353. end
  354. end
  355. function JustLuaType(t)
  356. return notranslator[getSafeFullName(t)]
  357. end
  358. function CallNeedTranslator(overload, isdelegate)
  359. if not overload.IsStatic and not isdelegate then return true end
  360. local ret_type_name = getSafeFullName(overload.ReturnType)
  361. if not notranslator[ret_type_name] then return true end
  362. local parameters = overload:GetParameters()
  363. return IfAny(overload:GetParameters(), function(parameter)
  364. return IsParams(parameter) or (not notranslator[getSafeFullName(parameter.ParameterType)])
  365. end)
  366. end
  367. function MethodCallNeedTranslator(method)
  368. return IfAny(method.Overloads, function(overload) return CallNeedTranslator(overload) end)
  369. end
  370. function AccessorNeedTranslator(accessor)
  371. return not accessor.IsStatic or not JustLuaType(accessor.Type)
  372. end
  373. function PushObjectNeedTranslator(type_info)
  374. return IfAny(type_info.FieldInfos, function(field_info) return not JustLuaType(field_info.Type) end)
  375. end
  376. local GenericParameterAttributes = CS.System.Reflection.GenericParameterAttributes
  377. local enum_and_op = debug.getmetatable(CS.System.Reflection.BindingFlags.Public).__band
  378. local has_generic_flag = function(f1, f2)
  379. return (f1 ~= GenericParameterAttributes.None) and (enum_and_op(f1, f2) == f2)
  380. end
  381. function GenericArgumentList(type)
  382. local generic_arg_list = ""
  383. local type_constraints = ""
  384. if type.IsGenericTypeDefinition then
  385. generic_arg_list = "<"
  386. local constraints = {}
  387. ForEachCsList(type:GetGenericArguments(), function(generic_arg, gai)
  388. local constraint = {}
  389. if gai ~= 0 then generic_arg_list = generic_arg_list .. ", " end
  390. generic_arg_list = generic_arg_list .. generic_arg.Name
  391. if has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.ReferenceTypeConstraint) then
  392. table.insert(constraint, 'class')
  393. end
  394. if has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint) then
  395. table.insert(constraint, 'struct')
  396. end
  397. ForEachCsList(generic_arg:GetGenericParameterConstraints(), function(gpc)
  398. if gpc ~= typeof(CS.System.ValueType) or not has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint) then
  399. table.insert(constraint, CsFullTypeName(gpc))
  400. end
  401. end)
  402. if not has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint) and has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.DefaultConstructorConstraint) then
  403. table.insert(constraint, 'new()')
  404. end
  405. if #constraint > 0 then
  406. table.insert(constraints, 'where ' .. generic_arg.Name .. ' : ' .. table.concat(constraint, ','))
  407. end
  408. end)
  409. generic_arg_list = generic_arg_list .. ">"
  410. if #constraints > 0 then
  411. type_constraints = table.concat(constraints, ',')
  412. end
  413. end
  414. return generic_arg_list, type_constraints
  415. end
  416. function LocalName(name)
  417. return "_" .. name
  418. end