cppCppia.ml 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930
  1. open Extlib_leftovers
  2. open Ast
  3. open Type
  4. open Error
  5. open Globals
  6. open CppExprUtils
  7. open CppTypeUtils
  8. open CppAst
  9. open CppAstTools
  10. open CppSourceWriter
  11. open CppContext
  12. let cpp_type_of = CppRetyper.cpp_type_of
  13. let script_type t optional = if optional then begin
  14. match type_string t with
  15. | "::String" -> "String"
  16. | _ -> "Object"
  17. end else match type_string t with
  18. | "bool" -> "Int"
  19. | "int" | "::cpp::Int32" -> "Int"
  20. | "Float" -> "Float"
  21. | "::String" -> "String"
  22. | "Null" -> "Void"
  23. | "Void" -> "Void"
  24. | "float" | "::cpp::Float32" | "::cpp::Float64" -> "Float"
  25. | "::cpp::Int64" | "::cpp::UInt64" -> "Object"
  26. | _ -> "Object"
  27. let script_signature t optional = match script_type t optional with
  28. | "Bool" -> "b"
  29. | "Int" -> "i"
  30. | "Float" -> "f"
  31. | "String" -> "s"
  32. | "Void" -> "v"
  33. | "void" -> "v"
  34. | _ -> "o"
  35. let script_size_type t optional = match script_type t optional with
  36. | "Object" -> "void *"
  37. | "Int" -> "int"
  38. | "Bool" -> "bool"
  39. | x -> x
  40. let rec script_type_string haxe_type =
  41. match haxe_type with
  42. | TAbstract ({ a_path = [], "Null" }, [ t ]) -> (
  43. match follow t with
  44. | TAbstract ({ a_path = [], "Int" }, _)
  45. | TAbstract ({ a_path = [], "Float" }, _)
  46. | TAbstract ({ a_path = [], "Bool" }, _) ->
  47. "Dynamic"
  48. | _ -> script_type_string t)
  49. | TInst ({ cl_path = [], "Null" }, [ t ]) -> (
  50. match follow t with
  51. | TAbstract ({ a_path = [], "Int" }, _)
  52. | TAbstract ({ a_path = [], "Float" }, _)
  53. | TAbstract ({ a_path = [], "Bool" }, _) ->
  54. "Dynamic"
  55. | _ -> script_type_string t)
  56. | _ -> (
  57. match follow haxe_type with
  58. | TType ({ t_path = [], "Array" }, params) -> "Array"
  59. | TInst ({ cl_path = [], "Array" }, params) -> (
  60. match params with
  61. | [ t ] -> (
  62. match type_string_suff "" t false with
  63. | "int" -> "Array.int"
  64. | "Float" -> "Array.Float"
  65. | "bool" -> "Array.bool"
  66. | "::String" -> "Array.String"
  67. | "unsigned char" -> "Array.unsigned char"
  68. | "::cpp::UInt8" -> "Array.unsigned char"
  69. | "Dynamic" -> "Array.Any"
  70. | _ -> "Array.Object")
  71. | _ -> "Array.Object")
  72. | TAbstract (abs, pl) when abs.a_impl <> None ->
  73. script_type_string (Abstract.get_underlying_type abs pl)
  74. | _ -> type_string_suff "" haxe_type false)
  75. let rec script_cpptype_string cppType =
  76. match cppType with
  77. | TCppDynamic | TCppUnchanged | TCppWrapped _ | TCppObject -> "Dynamic"
  78. | TCppObjectPtr -> ".*.hx.Object*"
  79. | TCppReference t -> ".ref." ^ script_cpptype_string t
  80. | TCppStruct t -> ".struct." ^ script_cpptype_string t
  81. | TCppStar (t, _) -> "*." ^ script_cpptype_string t
  82. | TCppVoid -> "void"
  83. | TCppVoidStar -> "*.void"
  84. | TCppRest _ -> "vaarg_list"
  85. | TCppVarArg -> "vararg"
  86. | TCppAutoCast -> ".cpp.AutoCast"
  87. | TCppVariant -> ".cpp.Variant"
  88. | TCppEnum enum -> join_class_path enum.e_path "."
  89. | TCppScalar scalar -> scalar
  90. | TCppString -> "String"
  91. | TCppFastIterator it -> "cpp.FastIterator." ^ script_cpptype_string it
  92. | TCppPointer (_, valueType) ->
  93. "cpp.Pointer." ^ script_cpptype_string valueType
  94. | TCppRawPointer (_, valueType) ->
  95. "cpp.RawPointer." ^ script_cpptype_string valueType
  96. | TCppFunction _ -> "cpp.Function"
  97. | TCppObjCBlock _ -> "cpp.ObjCBlock"
  98. | TCppDynamicArray -> "Array.Any"
  99. | TCppObjectArray _ -> "Array.Object"
  100. | TCppScalarArray value -> "Array." ^ script_cpptype_string value
  101. | TCppObjC _ -> "cpp.ObjC"
  102. | TCppProtocol _ -> "cpp.ObjC.Protocol"
  103. | TCppNativePointer klass ->
  104. "cpp.Pointer." ^ join_class_path klass.cl_path "."
  105. | TCppInterface klass -> join_class_path klass.cl_path "."
  106. | TCppInst (klass, _) -> join_class_path klass.cl_path "."
  107. | TCppClass -> "Class"
  108. | TCppGlobal -> "?global"
  109. | TCppNull -> "null"
  110. | TCppCode _ -> "Dynamic"
  111. type array_of =
  112. | ArrayInterface of int
  113. | ArrayData of string
  114. | ArrayObject
  115. | ArrayAny
  116. | ArrayNone
  117. let is_template_type t = false
  118. type cppia_op =
  119. | IaFunction
  120. | IaVar
  121. | IaToInterface
  122. | IaToDynArray
  123. | IaToDataArray
  124. | IaToInterfaceArray
  125. | IaFun
  126. | IaCast
  127. | IaTCast
  128. | IaBlock
  129. | IaBreak
  130. | IaContinue
  131. | IaIsNull
  132. | IaNotNull
  133. | IaSet
  134. | IaCall
  135. | IaCallGlobal
  136. | IaCallStatic
  137. | IaCallMember
  138. | IaCallSuper
  139. | IaCallThis
  140. | IaCallSuperNew
  141. | IaCreateEnum
  142. | IaADef
  143. | IaIf
  144. | IaIfElse
  145. | IaFStatic
  146. | IaFName
  147. | IaFThisInst
  148. | IaFLink
  149. | IaFThisName
  150. | IaFEnum
  151. | IaThrow
  152. | IaArrayI
  153. | IaPlusPlus
  154. | IaPlusPlusPost
  155. | IaMinusMinus
  156. | IaMinusMinusPost
  157. | IaNeg
  158. | IaBitNot
  159. | IaLogicNot
  160. | IaTVars
  161. | IaVarDecl
  162. | IaVarDeclI
  163. | IaNew
  164. | IaReturn
  165. | IaRetVal
  166. | IaPosInfo
  167. | IaObjDef
  168. | IaClassOf
  169. | IaWhile
  170. | IaFor
  171. | IaEnumI
  172. | IaSwitch
  173. | IaTry
  174. | IaImplDynamic
  175. | IaConstInt
  176. | IaConstFloat
  177. | IaConstString
  178. | IaConstFalse
  179. | IaConstTrue
  180. | IaConstNull
  181. | IaConsThis
  182. | IaConstSuper
  183. | IaCastInt
  184. | IaCastBool
  185. | IaInterface
  186. | IaClass
  187. | IaAccessNormal
  188. | IaAccessNot
  189. | IaAccessResolve
  190. | IaAccessCall
  191. | IaEnum
  192. | IaInline
  193. | IaMain
  194. | IaNoMain
  195. | IaResources
  196. | IaReso
  197. | IaNoCast
  198. | IaAccessCallNative
  199. | IaBinOp of Ast.binop
  200. let cppia_op_info = function
  201. | IaFunction -> ("FUNCTION", 1)
  202. | IaVar -> ("VAR", 2)
  203. | IaToInterface -> ("TOINTERFACE", 3)
  204. | IaToDynArray -> ("TODYNARRAY", 4)
  205. | IaToDataArray -> ("TODATAARRAY", 5)
  206. | IaToInterfaceArray -> ("TOINTERFACEARRAY", 6)
  207. | IaFun -> ("FUN", 7)
  208. | IaCast -> ("CAST", 8)
  209. | IaBlock -> ("BLOCK", 9)
  210. | IaBreak -> ("BREAK", 10)
  211. | IaContinue -> ("CONTINUE", 11)
  212. | IaIsNull -> ("ISNULL", 12)
  213. | IaNotNull -> ("NOTNULL", 13)
  214. | IaSet -> ("SET", 14)
  215. | IaCall -> ("CALL", 15)
  216. | IaCallGlobal -> ("CALLGLOBAL", 16)
  217. | IaCallStatic -> ("CALLSTATIC", 17)
  218. | IaCallMember -> ("CALLMEMBER", 18)
  219. | IaCallSuper -> ("CALLSUPER", 19)
  220. | IaCallThis -> ("CALLTHIS", 20)
  221. | IaCallSuperNew -> ("CALLSUPERNEW", 21)
  222. | IaCreateEnum -> ("CREATEENUM", 22)
  223. | IaADef -> ("ADEF", 23)
  224. | IaIf -> ("IF", 24)
  225. | IaIfElse -> ("IFELSE", 25)
  226. | IaFName -> ("FNAME", 27)
  227. | IaFStatic -> ("FSTATIC", 28)
  228. | IaFThisInst -> ("FTHISINST", 29)
  229. | IaFLink -> ("FLINK", 30)
  230. | IaFThisName -> ("FTHISNAME", 31)
  231. | IaFEnum -> ("FENUM", 32)
  232. | IaThrow -> ("THROW", 33)
  233. | IaArrayI -> ("ARRAYI", 34)
  234. | IaPlusPlus -> ("++", 35)
  235. | IaPlusPlusPost -> ("+++", 36)
  236. | IaMinusMinus -> ("--", 37)
  237. | IaMinusMinusPost -> ("---", 38)
  238. | IaNeg -> ("NEG", 39)
  239. | IaBitNot -> ("~", 40)
  240. | IaLogicNot -> ("!", 41)
  241. | IaTVars -> ("TVARS", 42)
  242. | IaVarDecl -> ("VARDECL", 43)
  243. | IaVarDeclI -> ("VARDECLI", 44)
  244. | IaNew -> ("NEW", 45)
  245. | IaReturn -> ("RETURN", 46)
  246. | IaRetVal -> ("RETVAL", 47)
  247. | IaPosInfo -> ("POSINFO", 48)
  248. | IaObjDef -> ("OBJDEF", 49)
  249. | IaClassOf -> ("CLASSOF", 50)
  250. | IaWhile -> ("WHILE", 51)
  251. | IaFor -> ("FOR", 52)
  252. | IaEnumI -> ("ENUMI", 53)
  253. | IaSwitch -> ("SWITCH", 54)
  254. | IaTry -> ("TRY", 55)
  255. | IaImplDynamic -> ("IMPLDYNAMIC", 56)
  256. | IaConstInt -> ("i", 57)
  257. | IaConstFloat -> ("f", 58)
  258. | IaConstString -> ("s", 59)
  259. | IaConstFalse -> ("false", 60)
  260. | IaConstTrue -> ("true", 61)
  261. | IaConstNull -> ("NULL", 62)
  262. | IaConsThis -> ("THIS", 63)
  263. | IaConstSuper -> ("SUPER", 64)
  264. | IaCastInt -> ("CASTINT", 65)
  265. | IaCastBool -> ("CASTBOOL", 66)
  266. | IaInterface -> ("INTERFACE", 67)
  267. | IaClass -> ("CLASS", 68)
  268. | IaAccessNormal -> ("N", 69)
  269. | IaAccessNot -> ("n", 70)
  270. | IaAccessResolve -> ("R", 71)
  271. | IaAccessCall -> ("C", 72)
  272. | IaEnum -> ("ENUM", 73)
  273. | IaInline -> ("INLINE", 74)
  274. | IaMain -> ("MAIN", 75)
  275. | IaNoMain -> ("NOMAIN", 76)
  276. | IaResources -> ("RESOURCES", 77)
  277. | IaReso -> ("RESO", 78)
  278. | IaNoCast -> ("NOCAST", 79)
  279. | IaAccessCallNative -> ("V", 80)
  280. | IaBinOp OpAdd -> ("+", 101)
  281. | IaBinOp OpMult -> ("*", 102)
  282. | IaBinOp OpDiv -> ("/", 103)
  283. | IaBinOp OpSub -> ("-", 104)
  284. | IaBinOp OpAssign -> ("=", 105)
  285. | IaBinOp OpEq -> ("==", 106)
  286. | IaBinOp OpNotEq -> ("!=", 107)
  287. | IaBinOp OpGte -> (">=", 108)
  288. | IaBinOp OpLte -> ("<=", 109)
  289. | IaBinOp OpGt -> (">", 110)
  290. | IaBinOp OpLt -> ("<", 111)
  291. | IaBinOp OpAnd -> ("&", 112)
  292. | IaBinOp OpOr -> ("|", 113)
  293. | IaBinOp OpXor -> ("^", 114)
  294. | IaBinOp OpBoolAnd -> ("&&", 115)
  295. | IaBinOp OpBoolOr -> ("||", 116)
  296. | IaBinOp OpShr -> (">>", 117)
  297. | IaBinOp OpUShr -> (">>>", 118)
  298. | IaBinOp OpShl -> ("<<", 119)
  299. | IaBinOp OpMod -> ("%", 120)
  300. | IaBinOp OpInterval -> ("...", 121)
  301. | IaBinOp OpArrow -> ("=>", 122)
  302. | IaBinOp OpIn -> (" in ", 123)
  303. | IaBinOp OpNullCoal -> ("??", 124)
  304. | IaBinOp (OpAssignOp OpAdd) -> ("+=", 201)
  305. | IaBinOp (OpAssignOp OpMult) -> ("*=", 202)
  306. | IaBinOp (OpAssignOp OpDiv) -> ("/=", 203)
  307. | IaBinOp (OpAssignOp OpSub) -> ("-=", 204)
  308. | IaBinOp (OpAssignOp OpAnd) -> ("&=", 212)
  309. | IaBinOp (OpAssignOp OpOr) -> ("|=", 213)
  310. | IaBinOp (OpAssignOp OpXor) -> ("^=", 214)
  311. | IaBinOp (OpAssignOp OpBoolAnd) -> ("&&=", 215)
  312. | IaBinOp (OpAssignOp OpBoolOr) -> ("||=", 216)
  313. | IaBinOp (OpAssignOp OpShr) -> (">>=", 217)
  314. | IaBinOp (OpAssignOp OpUShr) -> (">>>=", 218)
  315. | IaBinOp (OpAssignOp OpShl) -> ("<<=", 219)
  316. | IaBinOp (OpAssignOp OpMod) -> ("%=", 220)
  317. | IaBinOp (OpAssignOp OpIn)
  318. | IaBinOp (OpAssignOp OpNullCoal)
  319. | IaBinOp (OpAssignOp OpInterval)
  320. | IaBinOp (OpAssignOp OpAssign)
  321. | IaBinOp (OpAssignOp OpEq)
  322. | IaBinOp (OpAssignOp OpNotEq)
  323. | IaBinOp (OpAssignOp OpGte)
  324. | IaBinOp (OpAssignOp OpLte)
  325. | IaBinOp (OpAssignOp OpGt)
  326. | IaBinOp (OpAssignOp OpLt)
  327. | IaBinOp (OpAssignOp (OpAssignOp _))
  328. | IaBinOp (OpAssignOp OpArrow) ->
  329. die "" __LOC__
  330. | IaTCast -> ("TCAST", 221)
  331. let follow = Abstract.follow_with_abstracts
  332. let is_matching_interface_type t0 t1 =
  333. match (follow t0, follow t1) with
  334. | TInst (k0, _), TInst (k1, _) -> k0 == k1
  335. | _ -> false
  336. let rec is_null expr =
  337. match expr.eexpr with
  338. | TConst TNull -> true
  339. | TParenthesis expr | TMeta (_, expr) -> is_null expr
  340. | TCast (e, None) -> is_null e
  341. | _ -> false
  342. let is_virtual_array expr = type_string expr.etype = "cpp::VirtualArray"
  343. let is_this expression =
  344. match (remove_parens expression).eexpr with
  345. | TConst TThis -> true
  346. | _ -> false
  347. let is_super expression =
  348. match (remove_parens expression).eexpr with
  349. | TConst TSuper -> true
  350. | _ -> false
  351. let is_native_pointer expr =
  352. let t = type_string expr.etype in
  353. let l = String.length t in
  354. l > 1 && String.sub t (l - 1) 1 = "*"
  355. let is_extern_class_instance obj =
  356. match follow obj.etype with
  357. | TInst (klass, params) -> has_class_flag klass CExtern
  358. | _ -> false
  359. let rec is_dynamic_in_cpp ctx expr =
  360. let expr_type =
  361. type_string
  362. (match follow expr.etype with TFun (args, ret) -> ret | _ -> expr.etype)
  363. in
  364. if expr_type = "Dynamic" || expr_type = "cpp::ArrayBase" then true
  365. else
  366. let result =
  367. match expr.eexpr with
  368. | TEnumParameter (obj, _, index) -> true (* TODO? *)
  369. | TField (obj, field) ->
  370. is_dynamic_member_lookup_in_cpp ctx obj field
  371. || is_dynamic_member_return_in_cpp ctx obj field
  372. | TArray (obj, index) -> is_dynamic_in_cpp ctx obj || is_virtual_array obj
  373. | TTypeExpr _ -> false
  374. | TCall (func, args) -> (
  375. let is_IaCall =
  376. match (remove_parens_cast func).eexpr with
  377. | TField ({ eexpr = TIdent "__global__" }, field) -> false
  378. | TField (obj, FStatic (class_def, field))
  379. when is_real_function field ->
  380. false
  381. | TField (obj, FInstance (_, _, field))
  382. when is_this obj && is_real_function field ->
  383. false
  384. | TField (obj, FInstance (_, _, field)) when is_super obj -> false
  385. | TField (obj, FInstance (_, _, field))
  386. when field.cf_name = "_hx_getIndex" ->
  387. false
  388. | TField (obj, FInstance (_, _, field))
  389. when field.cf_name = "__Index"
  390. || (not (is_dynamic_in_cppia ctx obj))
  391. && is_real_function field ->
  392. false
  393. | TField (obj, FDynamic name)
  394. when is_internal_member name
  395. || (type_string obj.etype = "::String" && name = "cca") ->
  396. false
  397. | TConst TSuper -> false
  398. | TField (_, FEnum (enum, field)) -> false
  399. | _ -> true
  400. in
  401. if is_IaCall then true
  402. else
  403. match follow func.etype with
  404. | TFun (args, ret) -> is_dynamic_in_cpp ctx func
  405. | _ -> true)
  406. | TParenthesis expr | TMeta (_, expr) -> is_dynamic_in_cpp ctx expr
  407. | TCast (e, None) -> type_string expr.etype = "Dynamic"
  408. | TIdent "__global__" -> false
  409. | TConst TNull -> true
  410. | _ -> false (* others ? *)
  411. in
  412. result
  413. and is_dynamic_member_lookup_in_cpp (ctx : context) field_object field =
  414. let member = field_name field in
  415. if is_internal_member member then false
  416. else if is_native_pointer field_object then false
  417. else if is_pointer field_object.etype true then false
  418. else if match field_object.eexpr with TTypeExpr _ -> true | _ -> false then
  419. false
  420. else if is_dynamic_in_cpp ctx field_object then true
  421. else if is_array field_object.etype then false
  422. else
  423. let tstr = type_string field_object.etype in
  424. match tstr with
  425. (* Internal classes have no dynamic members *)
  426. | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math"
  427. | "::ArrayAccess" ->
  428. false
  429. | "Dynamic" -> true
  430. | name ->
  431. let full_name = name ^ "." ^ member in
  432. if Hashtbl.mem ctx.ctx_class_member_types full_name then false
  433. else not (is_extern_class_instance field_object)
  434. and is_dynamic_member_return_in_cpp ctx field_object field =
  435. let member = field_name field in
  436. if is_array field_object.etype then false
  437. else if is_pointer field_object.etype true then false
  438. else if is_internal_member member then false
  439. else
  440. match field_object.eexpr with
  441. | TTypeExpr t -> (
  442. let full_name =
  443. "::" ^ join_class_path_remap (t_path t) "::" ^ "." ^ member
  444. in
  445. try
  446. let mem_type = Hashtbl.find ctx.ctx_class_member_types full_name in
  447. mem_type = "Dynamic"
  448. || mem_type = "cpp::ArrayBase"
  449. || mem_type = "cpp::VirtualArray"
  450. with Not_found -> true)
  451. | _ -> (
  452. let tstr = type_string field_object.etype in
  453. match tstr with
  454. (* Internal classes have no dynamic members *)
  455. | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math"
  456. | "::ArrayAccess" ->
  457. false
  458. | "Dynamic" | "cpp::ArrayBase" | "cpp::VirtualArray" -> true
  459. | name -> (
  460. let full_name = name ^ "." ^ member in
  461. try
  462. let mem_type =
  463. Hashtbl.find ctx.ctx_class_member_types full_name
  464. in
  465. mem_type = "Dynamic"
  466. || mem_type = "cpp::ArrayBase"
  467. || mem_type = "cpp::VirtualArray"
  468. with Not_found -> true))
  469. and is_dynamic_in_cppia ctx expr =
  470. match expr.eexpr with
  471. | TCast (_, None) -> true
  472. | _ -> is_dynamic_in_cpp ctx expr
  473. class script_writer ctx filename asciiOut =
  474. object (this)
  475. val debug = asciiOut
  476. val doComment =
  477. asciiOut && Gctx.defined ctx.ctx_common Define.AnnotateSource
  478. val indent_str = if asciiOut then "\t" else ""
  479. val mutable indent = ""
  480. val mutable indents = []
  481. val mutable just_finished_block = false
  482. val mutable classCount = 0
  483. val mutable return_type = TMono (Monomorph.create ())
  484. val buffer = Buffer.create 0
  485. val identTable = Hashtbl.create 0
  486. val fileTable = Hashtbl.create 0
  487. val identBuffer = Buffer.create 0
  488. val cppiaAst = not (Gctx.defined ctx.ctx_common Define.NoCppiaAst)
  489. method stringId name =
  490. try Hashtbl.find identTable name
  491. with Not_found ->
  492. let size = Hashtbl.length identTable in
  493. Hashtbl.add identTable name size;
  494. Buffer.add_string identBuffer
  495. (string_of_int (String.length name) ^ " " ^ name ^ "\n");
  496. size
  497. method incClasses = classCount <- classCount + 1
  498. method stringText name = string_of_int (this#stringId name) ^ " "
  499. val typeTable = Hashtbl.create 0
  500. val typeBuffer = Buffer.create 0
  501. method typeId name =
  502. let name = if name = "::hx::Class" then "::Class" else name in
  503. try Hashtbl.find typeTable name
  504. with Not_found ->
  505. let size = Hashtbl.length typeTable in
  506. Hashtbl.add typeTable name size;
  507. Buffer.add_string typeBuffer
  508. (string_of_int (String.length name) ^ " " ^ name ^ "\n");
  509. size
  510. method write str =
  511. (if asciiOut then Buffer.add_string buffer str
  512. else
  513. let push i = Buffer.add_char buffer (Char.chr i) in
  514. let pushI32 i =
  515. push (Int32.to_int (Int32.logand i (Int32.of_int 255)))
  516. in
  517. List.iter
  518. (fun i ->
  519. if
  520. Int32.compare i Int32.zero >= 0
  521. && Int32.compare i (Int32.of_int 254) < 0
  522. then pushI32 i
  523. else if
  524. Int32.compare i Int32.zero >= 0
  525. && Int32.compare i (Int32.of_int 65536) < 0
  526. then (
  527. push 254;
  528. pushI32 i;
  529. pushI32 (Int32.shift_right i 8))
  530. else (
  531. push 255;
  532. pushI32 i;
  533. pushI32 (Int32.shift_right i 8);
  534. pushI32 (Int32.shift_right i 16);
  535. pushI32 (Int32.shift_right i 24)))
  536. (List.map Int32.of_string (Str.split (Str.regexp "[\n\t ]+") str)));
  537. just_finished_block <- false
  538. method comment text = if doComment then this#write ("# " ^ text ^ "\n")
  539. method commentOf text = if doComment then " # " ^ text else ""
  540. method typeTextString typeName = string_of_int (this#typeId typeName) ^ " "
  541. method typeText typeT =
  542. let tname =
  543. if cppiaAst then script_cpptype_string (cpp_type_of typeT)
  544. else script_type_string typeT
  545. in
  546. string_of_int (this#typeId tname) ^ " "
  547. method astType cppType =
  548. string_of_int (this#typeId (script_cpptype_string cppType)) ^ " "
  549. method writeType typeT = this#write (this#typeText typeT)
  550. method toCppType etype =
  551. string_of_int (this#typeId (script_cpptype_string (cpp_type_of etype)))
  552. ^ " "
  553. method boolText value = if value then "1" else "0"
  554. method writeBool value = this#write (if value then "1 " else "0 ")
  555. method staticText value = if value then "1" else "0"
  556. method writeData str = Buffer.add_string buffer str
  557. method wint ival = this#write (string_of_int ival ^ " ")
  558. method ident name = this#wint (this#stringId name)
  559. method cppInstText clazz =
  560. match clazz.cl_path with
  561. | [], "Array" -> this#typeTextString "Array"
  562. | x -> this#typeTextString (join_class_path x ".")
  563. method instText clazz =
  564. match clazz.cl_path with
  565. | [], "Array" -> string_of_int (this#typeId "Array< ::Dynamic >") ^ " "
  566. | _ -> this#typeText (TInst (clazz, []))
  567. method instName clazz =
  568. this#write
  569. (if cppiaAst then this#cppInstText clazz else this#instText clazz)
  570. method enumText e = this#typeText (TEnum (e, []))
  571. method close =
  572. let out_file = open_out_bin filename in
  573. output_string out_file (if asciiOut then "CPPIA\n" else "CPPIB\n");
  574. let idents = Buffer.contents identBuffer in
  575. output_string out_file (string_of_int (Hashtbl.length identTable) ^ "\n");
  576. output_string out_file idents;
  577. let types = Buffer.contents typeBuffer in
  578. output_string out_file (string_of_int (Hashtbl.length typeTable) ^ "\n");
  579. output_string out_file types;
  580. output_string out_file (string_of_int classCount ^ "\n");
  581. let contents = Buffer.contents buffer in
  582. output_string out_file contents;
  583. close_out out_file
  584. method fileId file =
  585. try Hashtbl.find fileTable file
  586. with Not_found ->
  587. let stripped_file = strip_file ctx.ctx_common file in
  588. let result = this#stringId stripped_file in
  589. Hashtbl.add fileTable file result;
  590. result
  591. method constText c =
  592. match c with
  593. | TInt i -> this#op IaConstInt ^ Printf.sprintf "%ld " i
  594. | TFloat f ->
  595. this#op IaConstFloat ^ this#stringText (Texpr.replace_separators f "")
  596. | TString s -> this#op IaConstString ^ this#stringText s
  597. | TBool true -> this#op IaConstTrue
  598. | TBool false -> this#op IaConstFalse
  599. | TNull -> this#op IaConstNull
  600. | TThis -> this#op IaConsThis
  601. | TSuper -> this#op IaConstSuper
  602. method get_array_type t =
  603. match follow t with
  604. | TInst ({ cl_path = [], "Array" }, [ param ]) -> (
  605. let typeName = type_string_suff "" param false in
  606. match typeName with
  607. | "::String" -> ArrayData "String"
  608. | "int" | "Float" | "bool" | "String" | "unsigned char"
  609. | "::cpp::UInt8" ->
  610. ArrayData typeName
  611. | "cpp::ArrayBase" | "cpp::VirtualArray" | "Dynamic" -> ArrayAny
  612. | _ when is_interface_type param ->
  613. ArrayInterface (this#typeId (script_type_string param))
  614. | _ -> ArrayObject)
  615. | TAbstract (abs, pl) when abs.a_impl <> None ->
  616. this#get_array_type (Abstract.get_underlying_type abs pl)
  617. | _ -> ArrayNone
  618. method pushReturn inType =
  619. let oldReturnType = return_type in
  620. return_type <- inType;
  621. fun () -> return_type <- oldReturnType
  622. method fileText file = string_of_int (this#fileId file)
  623. method indent_one = this#write indent_str
  624. method push_indent =
  625. indents <- indent_str :: indents;
  626. indent <- String.concat "" indents
  627. method pop_indent =
  628. match indents with
  629. | h :: tail ->
  630. indents <- tail;
  631. indent <- String.concat "" indents
  632. | [] -> indent <- "/*?*/"
  633. method write_i x = this#write (indent ^ x)
  634. method get_indent = indent
  635. method begin_expr = this#push_indent
  636. method end_expr =
  637. if not just_finished_block then this#write "\n";
  638. this#pop_indent;
  639. just_finished_block <- true
  640. method op x =
  641. match cppia_op_info x with
  642. | name, index -> (if debug then name else string_of_int index) ^ " "
  643. method writeOp o = this#write (this#op o)
  644. method writeOpLine o = this#write (this#op o ^ "\n")
  645. method voidFunc isStatic isDynamic funcName fieldExpression =
  646. this#comment funcName;
  647. this#write
  648. (this#op IaFunction ^ this#staticText isStatic ^ " "
  649. ^ this#boolText isDynamic ^ " " ^ this#stringText funcName ^ " ");
  650. this#write (this#typeTextString "Void" ^ "0\n");
  651. this#gen_expression fieldExpression
  652. method func isStatic isDynamic funcName ret args isInterface fieldExpression
  653. abstractPos =
  654. this#comment funcName;
  655. this#write
  656. (this#op IaFunction ^ this#staticText isStatic ^ " "
  657. ^ this#boolText isDynamic ^ " " ^ this#stringText funcName ^ " ");
  658. this#write (this#typeText ret ^ string_of_int (List.length args) ^ " ");
  659. List.iter
  660. (fun (name, opt, typ) ->
  661. this#write
  662. (this#stringText name ^ this#boolText opt ^ " " ^ this#typeText typ
  663. ^ " "))
  664. args;
  665. this#write "\n";
  666. if not isInterface then
  667. match fieldExpression with
  668. | Some ({ eexpr = TFunction function_def } as e) ->
  669. if cppiaAst then (
  670. let args = List.map fst function_def.tf_args in
  671. let cppExpr =
  672. CppRetyper.expression ctx TCppVoid args function_def.tf_type
  673. function_def.tf_expr false
  674. in
  675. this#begin_expr;
  676. this#writePos function_def.tf_expr;
  677. this#write
  678. (this#op IaFun
  679. ^ this#typeText function_def.tf_type
  680. ^ string_of_int (List.length args)
  681. ^ "\n");
  682. let close = this#gen_func_args function_def.tf_args in
  683. this#gen_expression_tree cppExpr;
  684. this#end_expr;
  685. close ())
  686. else this#gen_expression e
  687. | _ ->
  688. (* Abstract function - dummp implementation that (should) not get called *)
  689. this#begin_expr;
  690. this#wpos abstractPos;
  691. this#writeOpLine IaReturn;
  692. this#end_expr
  693. method var readAcc writeAcc isExtern isStatic name varType varExpr =
  694. this#write
  695. (this#op IaVar ^ this#staticText isStatic ^ " " ^ this#op readAcc
  696. ^ this#op writeAcc ^ this#boolText isExtern ^ " " ^ this#stringText name
  697. ^ this#typeText varType
  698. ^ (match varExpr with Some _ -> "1" | _ -> "0")
  699. ^ if doComment then " # " ^ name ^ "\n" else "\n");
  700. match varExpr with
  701. | Some expression ->
  702. if cppiaAst then
  703. let varType = cpp_type_of expression.etype in
  704. let cppExpr =
  705. CppRetyper.expression ctx varType [] t_dynamic expression false
  706. in
  707. this#gen_expression_tree cppExpr
  708. else this#gen_expression expression
  709. | _ -> ()
  710. method implDynamic = this#writeOpLine IaImplDynamic
  711. method writeVar v =
  712. this#ident v.v_name;
  713. this#wint v.v_id;
  714. this#writeBool (has_var_flag v VCaptured);
  715. this#writeType v.v_type
  716. method writeList prefix len =
  717. this#write (prefix ^ " " ^ string_of_int len ^ "\n")
  718. method wpos p =
  719. if debug then
  720. this#write
  721. (this#fileText p.pfile ^ "\t"
  722. ^ string_of_int (Lexer.get_error_line p)
  723. ^ indent)
  724. method writePos expr = this#wpos expr.epos
  725. method writeCppPos expr = this#wpos expr.cpppos
  726. method checkCast toType expr forceCast fromGenExpression =
  727. let write_cast text =
  728. if not fromGenExpression then this#writePos expr;
  729. this#write (text ^ "\n");
  730. this#begin_expr;
  731. this#gen_expression expr;
  732. this#end_expr;
  733. true
  734. in
  735. let was_cast =
  736. if is_interface_type toType then
  737. if is_dynamic_in_cppia ctx expr then
  738. write_cast
  739. (this#op IaToInterface ^ this#typeText toType ^ " "
  740. ^ this#typeTextString "Dynamic")
  741. else if not (is_matching_interface_type toType expr.etype) then
  742. write_cast
  743. (this#op IaToInterface ^ this#typeText toType ^ " "
  744. ^ this#typeText expr.etype)
  745. else false
  746. else
  747. let get_array_expr_type expr =
  748. if is_dynamic_in_cppia ctx expr then ArrayNone
  749. else this#get_array_type expr.etype
  750. in
  751. match (this#get_array_type toType, get_array_expr_type expr) with
  752. | ArrayAny, _ -> false
  753. | ArrayObject, ArrayData _ -> write_cast (this#op IaToDynArray)
  754. | ArrayObject, ArrayObject -> false
  755. | ArrayObject, ArrayNone | ArrayObject, ArrayAny ->
  756. write_cast
  757. (this#op IaToDataArray ^ this#typeTextString "Array.Object")
  758. | ArrayData t, ArrayNone
  759. | ArrayData t, ArrayObject
  760. | ArrayData t, ArrayAny ->
  761. write_cast
  762. (this#op IaToDataArray ^ this#typeTextString ("Array." ^ t))
  763. | ArrayInterface t, ArrayNone | ArrayInterface t, ArrayAny ->
  764. write_cast (this#op IaToInterfaceArray ^ string_of_int t)
  765. | _, _ ->
  766. (* a0,a1 ->
  767. let arrayString a =
  768. match a with
  769. | ArrayNone -> "ArrayNone"
  770. | ArrayAny -> "ArrayAny"
  771. | ArrayObject -> "ArrayObject"
  772. | ArrayData _ -> "ArrayData"
  773. | ArrayInterface _ -> "ArrayInterface"
  774. in
  775. this#write ("NOCAST " ^ (arrayString a0) ^ "=" ^ (arrayString a1)); *)
  776. false
  777. in
  778. if not was_cast then (
  779. (if forceCast then
  780. let op =
  781. match type_string expr.etype with
  782. | "int" -> IaCastInt
  783. | "bool" -> IaCastBool
  784. | _ when is_interface_type toType -> IaNoCast
  785. | _ -> IaCast
  786. in
  787. this#writeOpLine op);
  788. this#gen_expression expr)
  789. method gen_func_args args =
  790. let gen_inits = ref [] in
  791. List.iter
  792. (fun (arg, init) ->
  793. this#write (indent ^ indent_str);
  794. this#writeVar arg;
  795. match init with
  796. | Some { eexpr = TConst TNull } -> this#write "0\n"
  797. | Some const ->
  798. let argType = cpp_type_of const.etype in
  799. if is_cpp_scalar argType || argType == TCppString then (
  800. this#write "1 ";
  801. this#gen_expression_only const;
  802. this#write "\n")
  803. else (
  804. gen_inits := (arg, const) :: !gen_inits;
  805. this#write "0\n")
  806. | _ -> this#write "0\n")
  807. args;
  808. if List.length !gen_inits == 0 then fun () -> ()
  809. else (
  810. this#begin_expr;
  811. this#writePos (snd (List.hd !gen_inits));
  812. this#writeList (this#op IaBlock) (List.length !gen_inits + 1);
  813. List.iter
  814. (fun (arg, const) ->
  815. let start_expr () =
  816. this#begin_expr;
  817. this#writePos const
  818. in
  819. let local_var () =
  820. this#begin_expr;
  821. this#writePos const;
  822. this#write
  823. (this#op IaVar ^ string_of_int arg.v_id
  824. ^ this#commentOf arg.v_name);
  825. this#end_expr
  826. in
  827. start_expr ();
  828. this#writeOpLine IaIf;
  829. start_expr ();
  830. this#writeOpLine IaIsNull;
  831. local_var ();
  832. this#end_expr;
  833. start_expr ();
  834. this#writeOpLine IaSet;
  835. local_var ();
  836. this#gen_expression const;
  837. this#end_expr;
  838. this#begin_expr)
  839. !gen_inits;
  840. fun () -> this#end_expr)
  841. method gen_expression expr =
  842. this#begin_expr;
  843. this#writePos expr;
  844. this#gen_expression_only expr;
  845. this#end_expr
  846. method gen_expression_only expr =
  847. (* { *)
  848. let expression = remove_parens expr in
  849. match expression.eexpr with
  850. | TFunction function_def ->
  851. this#write
  852. (this#op IaFun
  853. ^ this#typeText function_def.tf_type
  854. ^ string_of_int (List.length function_def.tf_args)
  855. ^ "\n");
  856. let close = this#gen_func_args function_def.tf_args in
  857. let pop = this#pushReturn function_def.tf_type in
  858. this#gen_expression function_def.tf_expr;
  859. pop ();
  860. close ()
  861. | TBlock expr_list ->
  862. this#writeList (this#op IaBlock) (List.length expr_list);
  863. List.iter this#gen_expression expr_list
  864. | TConst const -> this#write (this#constText const)
  865. | TBreak -> this#writeOp IaBreak
  866. | TContinue -> this#writeOp IaContinue
  867. | TBinop (op, e1, e2) when op = OpAssign ->
  868. this#writeOpLine IaSet;
  869. this#gen_expression e1;
  870. this#checkCast e1.etype e2 false false
  871. | TBinop (OpEq, e1, { eexpr = TConst TNull }) ->
  872. this#writeOpLine IaIsNull;
  873. this#gen_expression e1
  874. | TBinop (OpNotEq, e1, { eexpr = TConst TNull }) ->
  875. this#writeOpLine IaNotNull;
  876. this#gen_expression e1
  877. | TBinop (OpEq, { eexpr = TConst TNull }, e1) ->
  878. this#writeOpLine IaIsNull;
  879. this#gen_expression e1
  880. | TBinop (OpNotEq, { eexpr = TConst TNull }, e1) ->
  881. this#writeOpLine IaNotNull;
  882. this#gen_expression e1
  883. | TBinop (op, e1, e2) ->
  884. this#writeOpLine (IaBinOp op);
  885. this#gen_expression e1;
  886. this#gen_expression e2
  887. | TThrow e ->
  888. this#writeOpLine IaThrow;
  889. this#gen_expression e
  890. | TArrayDecl expr_list ->
  891. this#write
  892. (this#op IaADef
  893. ^ this#typeText expression.etype
  894. ^ " "
  895. ^ string_of_int (List.length expr_list)
  896. ^ "\n");
  897. List.iter this#gen_expression expr_list
  898. | TIf (e, e1, e2) -> (
  899. match e2 with
  900. | None ->
  901. this#writeOpLine IaIf;
  902. this#gen_expression e;
  903. this#gen_expression e1
  904. | Some elze ->
  905. this#writeOpLine IaIfElse;
  906. this#gen_expression e;
  907. this#gen_expression e1;
  908. this#gen_expression elze)
  909. | TCall (func, arg_list) -> (
  910. let argN = string_of_int (List.length arg_list) ^ " " in
  911. let gen_call () =
  912. (match (remove_parens_cast func).eexpr with
  913. | TField ({ eexpr = TIdent "__global__" }, field) ->
  914. this#write
  915. (this#op IaCallGlobal
  916. ^ this#stringText (field_name field)
  917. ^ argN
  918. ^ this#commentOf (field_name field)
  919. ^ "\n")
  920. | TField (obj, FStatic (class_def, field))
  921. when is_real_function field ->
  922. this#write
  923. (this#op IaCallStatic ^ this#instText class_def ^ " "
  924. ^ this#stringText field.cf_name
  925. ^ argN
  926. ^ this#commentOf
  927. (join_class_path class_def.cl_path "."
  928. ^ "." ^ field.cf_name)
  929. ^ "\n")
  930. | TField (obj, FInstance (_, _, field))
  931. when is_this obj && is_real_function field ->
  932. this#write
  933. (this#op IaCallThis ^ this#typeText obj.etype ^ " "
  934. ^ this#stringText field.cf_name
  935. ^ argN
  936. ^ this#commentOf field.cf_name
  937. ^ "\n")
  938. | TField (obj, FInstance (_, _, field)) when is_super obj ->
  939. this#write
  940. (this#op IaCallSuper ^ this#typeText obj.etype ^ " "
  941. ^ this#stringText field.cf_name
  942. ^ argN
  943. ^ this#commentOf field.cf_name
  944. ^ "\n")
  945. (* Cppia does not have a "GetEnumIndex" op code - must use IaCallMember ::hx::EnumBase.__Index *)
  946. | TField (obj, FInstance (_, _, field))
  947. when field.cf_name = "_hx_getIndex"
  948. && script_type_string obj.etype = "::hx::EnumBase" ->
  949. this#write
  950. (this#op IaCallMember
  951. ^ this#typeTextString "::hx::EnumBase"
  952. ^ " " ^ this#stringText "__Index" ^ argN
  953. ^ this#commentOf "Enum index"
  954. ^ "\n");
  955. this#gen_expression obj
  956. | TField (obj, FInstance (_, _, field))
  957. when field.cf_name = "__Index"
  958. || (not (is_dynamic_in_cppia ctx obj))
  959. && is_real_function field ->
  960. this#write
  961. (this#op IaCallMember ^ this#typeText obj.etype ^ " "
  962. ^ this#stringText field.cf_name
  963. ^ argN
  964. ^ this#commentOf field.cf_name
  965. ^ "\n");
  966. this#gen_expression obj
  967. | TField (obj, FDynamic name)
  968. when is_internal_member name
  969. || (type_string obj.etype = "::String" && name = "cca") ->
  970. this#write
  971. (this#op IaCallMember ^ this#typeText obj.etype ^ " "
  972. ^ this#stringText name ^ argN ^ this#commentOf name ^ "\n");
  973. this#gen_expression obj
  974. | TConst TSuper ->
  975. this#write
  976. (this#op IaCallSuperNew ^ this#typeText func.etype ^ " "
  977. ^ argN ^ "\n")
  978. | TField (_, FEnum (enum, field)) ->
  979. this#write
  980. (this#op IaCreateEnum ^ this#enumText enum ^ " "
  981. ^ this#stringText field.ef_name
  982. ^ argN
  983. ^ this#commentOf field.ef_name
  984. ^ "\n")
  985. | _ ->
  986. this#write (this#op IaCall ^ argN ^ "\n");
  987. this#gen_expression func);
  988. let matched_args =
  989. match func.etype with
  990. | TFun (args, _) -> (
  991. try
  992. List.iter2
  993. (fun (_, _, protoT) arg ->
  994. this#checkCast protoT arg false false)
  995. args arg_list;
  996. true
  997. with Invalid_argument _ ->
  998. (*print_endline "Bad count?";*) false)
  999. | _ -> false
  1000. in
  1001. if not matched_args then List.iter this#gen_expression arg_list
  1002. in
  1003. match (remove_parens_cast func).eexpr with
  1004. | TField (obj, field)
  1005. when is_array_or_dyn_array obj.etype && field_name field = "map"
  1006. -> (
  1007. match this#get_array_type expression.etype with
  1008. | ArrayData t ->
  1009. this#write
  1010. (this#op IaToDataArray
  1011. ^ this#typeTextString ("Array." ^ t)
  1012. ^ "\n");
  1013. this#begin_expr;
  1014. this#writePos func;
  1015. gen_call ();
  1016. this#end_expr
  1017. | ArrayInterface t ->
  1018. this#write
  1019. (this#op IaToInterfaceArray ^ string_of_int t ^ "\n");
  1020. this#begin_expr;
  1021. this#writePos func;
  1022. gen_call ();
  1023. this#end_expr
  1024. | _ -> gen_call ())
  1025. | _ -> gen_call ())
  1026. | TField (obj, acc) -> (
  1027. let objType =
  1028. if is_dynamic_in_cppia ctx obj then "Dynamic"
  1029. else script_type_string obj.etype
  1030. in
  1031. let typeText =
  1032. if is_dynamic_in_cppia ctx obj then this#typeTextString "Dynamic"
  1033. else this#typeText obj.etype
  1034. in
  1035. match acc with
  1036. | FDynamic name ->
  1037. this#write
  1038. (this#op IaFName ^ typeText ^ " " ^ this#stringText name
  1039. ^ this#commentOf name ^ "\n");
  1040. this#gen_expression obj
  1041. | FStatic (class_def, field) ->
  1042. this#write
  1043. (this#op IaFStatic ^ this#instText class_def ^ " "
  1044. ^ this#stringText field.cf_name
  1045. ^ this#commentOf field.cf_name)
  1046. | FInstance (_, _, field) when is_this obj ->
  1047. this#write
  1048. (this#op IaFThisInst ^ typeText ^ " "
  1049. ^ this#stringText field.cf_name
  1050. ^ this#commentOf field.cf_name)
  1051. | FInstance (_, _, field) ->
  1052. this#write
  1053. (this#op IaFLink ^ typeText ^ " "
  1054. ^ this#stringText field.cf_name
  1055. ^ this#commentOf (objType ^ "." ^ field.cf_name)
  1056. ^ "\n");
  1057. this#gen_expression obj
  1058. | FClosure (_, field) when is_this obj ->
  1059. this#write
  1060. (this#op IaFThisName ^ typeText ^ " "
  1061. ^ this#stringText field.cf_name
  1062. ^ "\n")
  1063. | FAnon field when is_this obj ->
  1064. this#write
  1065. (this#op IaFThisName ^ typeText ^ " "
  1066. ^ this#stringText field.cf_name
  1067. ^ this#commentOf field.cf_name
  1068. ^ "\n")
  1069. | FClosure (_, field) | FAnon field ->
  1070. this#write
  1071. (this#op IaFName ^ typeText ^ " "
  1072. ^ this#stringText field.cf_name
  1073. ^ this#commentOf field.cf_name
  1074. ^ "\n");
  1075. this#gen_expression obj
  1076. | FEnum (enum, field) ->
  1077. this#write
  1078. (this#op IaFEnum ^ this#enumText enum ^ " "
  1079. ^ this#stringText field.ef_name
  1080. ^ this#commentOf field.ef_name))
  1081. | TArray (e1, e2) ->
  1082. this#write (this#op IaArrayI ^ this#typeText e1.etype ^ "\n");
  1083. this#gen_expression e1;
  1084. this#gen_expression e2
  1085. | TUnop (op, flag, e) ->
  1086. this#writeOpLine
  1087. (match (op, flag) with
  1088. | Increment, Prefix -> IaPlusPlus
  1089. | Increment, _ -> IaPlusPlusPost
  1090. | Decrement, Prefix -> IaMinusMinus
  1091. | Decrement, _ -> IaMinusMinusPost
  1092. | Not, _ -> IaLogicNot
  1093. | Neg, _ -> IaNeg
  1094. | Spread, _ -> die ~p:e.epos "Unexpected spread operator" __LOC__
  1095. | NegBits, _ -> IaBitNot);
  1096. this#gen_expression e
  1097. (* TODO - lval op-assign local/member/array *)
  1098. | TLocal var ->
  1099. this#write
  1100. (this#op IaVar ^ string_of_int var.v_id ^ this#commentOf var.v_name)
  1101. | TVar (tvar, optional_init) -> (
  1102. this#write
  1103. (this#op IaTVars ^ string_of_int 1
  1104. ^ this#commentOf (tvar.v_name ^ ":" ^ script_type_string tvar.v_type)
  1105. ^ "\n");
  1106. this#write ("\t\t" ^ indent);
  1107. match optional_init with
  1108. | None ->
  1109. this#writeOp IaVarDecl;
  1110. this#writeVar tvar
  1111. | Some init ->
  1112. this#writeOp IaVarDeclI;
  1113. let init = remove_parens init in
  1114. this#writeVar tvar;
  1115. this#write (" " ^ this#typeText init.etype);
  1116. this#write "\n";
  1117. this#checkCast tvar.v_type init false false)
  1118. | TNew (clazz, params, arg_list) -> (
  1119. this#write
  1120. (this#op IaNew
  1121. ^ this#typeText (TInst (clazz, params))
  1122. ^ string_of_int (List.length arg_list)
  1123. ^ "\n");
  1124. try
  1125. match
  1126. OverloadResolution.maybe_resolve_constructor_overload clazz params
  1127. arg_list
  1128. with
  1129. | Some (_, { cf_type = TFun (args, _) }, _) ->
  1130. List.iter2
  1131. (fun (_, _, protoT) arg ->
  1132. this#checkCast protoT arg false false)
  1133. args arg_list
  1134. | _ -> raise (Invalid_argument "")
  1135. with Invalid_argument _ -> List.iter this#gen_expression arg_list)
  1136. | TReturn optval -> (
  1137. match optval with
  1138. | None -> this#writeOpLine IaReturn
  1139. | Some value ->
  1140. this#write (this#op IaRetVal ^ this#typeText value.etype ^ "\n");
  1141. this#checkCast return_type value false false)
  1142. | TObjectDecl
  1143. [
  1144. (("fileName", _, _), { eexpr = TConst (TString file) });
  1145. (("lineNumber", _, _), { eexpr = TConst (TInt line) });
  1146. (("className", _, _), { eexpr = TConst (TString class_name) });
  1147. (("methodName", _, _), { eexpr = TConst (TString meth) });
  1148. ] ->
  1149. this#write
  1150. (this#op IaPosInfo ^ this#stringText file
  1151. ^ Printf.sprintf "%ld" line ^ " " ^ this#stringText class_name ^ " "
  1152. ^ this#stringText meth)
  1153. | TObjectDecl values ->
  1154. this#write (this#op IaObjDef ^ string_of_int (List.length values));
  1155. this#write " ";
  1156. List.iter
  1157. (fun ((name, _, _), _) -> this#write (this#stringText name))
  1158. values;
  1159. this#write "\n";
  1160. List.iter (fun (_, e) -> this#gen_expression e) values
  1161. | TTypeExpr type_expr ->
  1162. let klass = "::" ^ join_class_path (t_path type_expr) "::" in
  1163. this#write (this#op IaClassOf ^ string_of_int (this#typeId klass))
  1164. | TWhile (e1, e2, flag) ->
  1165. this#write
  1166. (this#op IaWhile ^ (if flag = NormalWhile then "1" else "0") ^ "\n");
  1167. this#gen_expression e1;
  1168. this#gen_expression e2
  1169. | TFor (tvar, init, loop) ->
  1170. this#writeOp IaFor;
  1171. this#writeVar tvar;
  1172. this#write "\n";
  1173. this#gen_expression init;
  1174. this#gen_expression loop
  1175. | TEnumParameter (expr, ef, i) ->
  1176. let enum =
  1177. match follow ef.ef_type with
  1178. | TEnum (en, _) | TFun (_, TEnum (en, _)) -> en
  1179. | _ -> die "" __LOC__
  1180. in
  1181. this#write
  1182. (this#op IaEnumI
  1183. ^ this#typeText (TEnum (enum, []))
  1184. ^ string_of_int i ^ "\n");
  1185. this#gen_expression expr
  1186. | TEnumIndex expr ->
  1187. this#write
  1188. (this#op IaCallMember
  1189. ^ this#typeTextString "::hx::EnumBase"
  1190. ^ " " ^ this#stringText "__Index" ^ "0"
  1191. ^ this#commentOf "Enum index"
  1192. ^ "\n");
  1193. this#gen_expression expr
  1194. | TSwitch
  1195. {
  1196. switch_subject = condition;
  1197. switch_cases = cases;
  1198. switch_default = optional_default;
  1199. } -> (
  1200. this#write
  1201. (this#op IaSwitch
  1202. ^ string_of_int (List.length cases)
  1203. ^ " "
  1204. ^ (match optional_default with None -> "0" | Some _ -> "1")
  1205. ^ "\n");
  1206. this#gen_expression condition;
  1207. List.iter
  1208. (fun { case_patterns = cases_list; case_expr = expression } ->
  1209. this#writeList ("\t\t\t" ^ indent) (List.length cases_list);
  1210. List.iter (fun value -> this#gen_expression value) cases_list;
  1211. this#gen_expression expression)
  1212. cases;
  1213. match optional_default with
  1214. | None -> ()
  1215. | Some expr -> this#gen_expression expr)
  1216. | TTry (e, catches) ->
  1217. this#writeList (this#op IaTry) (List.length catches);
  1218. this#gen_expression e;
  1219. List.iter
  1220. (fun (tvar, catch_expr) ->
  1221. this#write ("\t\t\t" ^ indent);
  1222. this#writeVar tvar;
  1223. this#write "\n";
  1224. this#gen_expression catch_expr)
  1225. catches
  1226. | TCast (cast, Some (TClassDecl t)) ->
  1227. this#write (this#op IaTCast ^ this#typeText (TInst (t, [])) ^ "\n");
  1228. this#gen_expression cast
  1229. | TCast (cast, _) -> this#checkCast expression.etype cast true true
  1230. | TParenthesis _ -> abort "Unexpected parens" expression.epos
  1231. | TMeta (_, _) -> abort "Unexpected meta" expression.epos
  1232. | TIdent _ -> abort "Unexpected ident" expression.epos
  1233. (* } *)
  1234. method gen_expression_tree expression_tree =
  1235. (* { *)
  1236. let rec gen_expression expression =
  1237. this#begin_expr;
  1238. this#writeCppPos expression;
  1239. let rec match_expr expression =
  1240. match expression.cppexpr with
  1241. | CppBlock (exprs, closures, _) ->
  1242. this#writeList (this#op IaBlock) (List.length exprs);
  1243. List.iter gen_expression exprs
  1244. | CppVarDecl (var, init) -> (
  1245. let name = CppGen.cpp_var_name_of var in
  1246. this#write
  1247. (this#op IaTVars ^ string_of_int 1
  1248. ^ this#commentOf (name ^ ":" ^ script_type_string var.v_type)
  1249. ^ "\n");
  1250. this#write ("\t\t" ^ indent);
  1251. match init with
  1252. | None ->
  1253. this#writeOp IaVarDecl;
  1254. this#writeVar var
  1255. | Some init ->
  1256. this#writeOp IaVarDeclI;
  1257. this#writeVar var;
  1258. this#write (" " ^ this#astType init.cpptype);
  1259. this#write "\n";
  1260. gen_expression init)
  1261. | CppInt i -> this#write (this#op IaConstInt ^ Printf.sprintf "%ld " i)
  1262. | CppFloat float_as_string ->
  1263. this#write (this#op IaConstFloat ^ this#stringText float_as_string)
  1264. | CppString s -> this#write (this#op IaConstString ^ this#stringText s)
  1265. | CppBool false -> this#writeOp IaConstFalse
  1266. | CppBool true -> this#writeOp IaConstTrue
  1267. | CppNull -> this#writeOp IaConstNull
  1268. | CppNil -> abort "Nil not supported in cppia" expression.cpppos
  1269. | CppThis _ -> this#writeOp IaConsThis
  1270. | CppSuper _ -> this#writeOp IaConstSuper
  1271. | CppBreak -> this#writeOp IaBreak
  1272. | CppContinue -> this#writeOp IaContinue
  1273. | CppGoto label ->
  1274. abort "Goto not supported in cppia" expression.cpppos
  1275. | CppReturn None -> this#writeOpLine IaReturn
  1276. | CppReturn (Some value) ->
  1277. this#write (this#op IaRetVal ^ this#astType value.cpptype ^ "\n");
  1278. gen_expression value
  1279. | CppWhile (condition, block, while_flag, _) ->
  1280. this#write
  1281. (this#op IaWhile
  1282. ^ (if while_flag = NormalWhile then "1" else "0")
  1283. ^ "\n");
  1284. gen_expression condition;
  1285. gen_expression block
  1286. | CppIf (condition, block, None) ->
  1287. this#writeOpLine IaIf;
  1288. gen_expression condition;
  1289. gen_expression block
  1290. | CppIf (condition, block, Some elze) ->
  1291. this#writeOpLine IaIfElse;
  1292. gen_expression condition;
  1293. gen_expression block;
  1294. gen_expression elze
  1295. | CppBinop (op, left, right) ->
  1296. this#writeOpLine (IaBinOp op);
  1297. gen_expression left;
  1298. gen_expression right
  1299. | CppVar var -> gen_var_loc var
  1300. | CppExtern (name, _) ->
  1301. abort
  1302. ("Unexpected global '" ^ name ^ "' in cppia")
  1303. expression.cpppos
  1304. | CppSet (lvalue, rvalue) ->
  1305. this#writeOpLine IaSet;
  1306. gen_lvalue lvalue expression.cpppos;
  1307. gen_expression rvalue
  1308. | CppCall (func, args) ->
  1309. let argN = string_of_int (List.length args) ^ " " in
  1310. (match func with
  1311. | FuncThis (field, inst) ->
  1312. let name = field.cf_name in
  1313. this#write
  1314. (this#op IaCallThis ^ this#astType inst ^ " "
  1315. ^ this#stringText name ^ argN ^ this#commentOf name ^ "\n")
  1316. | FuncInstance (expr, _, field) | FuncInterface (expr, _, field)
  1317. ->
  1318. this#write
  1319. (this#op IaCallMember ^ this#astType expr.cpptype ^ " "
  1320. ^ this#stringText field.cf_name
  1321. ^ argN
  1322. ^ this#commentOf field.cf_name
  1323. ^ "\n");
  1324. gen_expression expr
  1325. | FuncStatic (class_def, _, field) ->
  1326. this#write
  1327. (this#op IaCallStatic ^ this#cppInstText class_def ^ " "
  1328. ^ this#stringText field.cf_name
  1329. ^ argN
  1330. ^ this#commentOf
  1331. (join_class_path class_def.cl_path "."
  1332. ^ "." ^ field.cf_name)
  1333. ^ "\n")
  1334. | FuncTemplate _ ->
  1335. abort "Templated function call not supported in cppia"
  1336. expression.cpppos
  1337. | FuncFromStaticFunction ->
  1338. abort "Unexpected FuncFromStaticFunction" expression.cpppos
  1339. | FuncEnumConstruct (enum, field) ->
  1340. this#write
  1341. (this#op IaCreateEnum ^ this#enumText enum ^ " "
  1342. ^ this#stringText field.ef_name
  1343. ^ argN
  1344. ^ this#commentOf field.ef_name
  1345. ^ "\n")
  1346. | FuncSuperConstruct (TCppInst (klass, _))
  1347. when is_native_gen_class klass && is_native_class klass ->
  1348. abort "Unsupported super for native class constructor"
  1349. expression.cpppos
  1350. | FuncSuperConstruct childType ->
  1351. this#write
  1352. (this#op IaCallSuperNew ^ this#astType childType ^ " "
  1353. ^ argN ^ "\n")
  1354. | FuncSuper (_, TCppInst (klass, _), _)
  1355. when is_native_gen_class klass && is_native_class klass ->
  1356. abort "Unsupported super for native class method"
  1357. expression.cpppos
  1358. | FuncSuper (_, objType, field) ->
  1359. this#write
  1360. (this#op IaCallSuper ^ this#astType objType ^ " "
  1361. ^ this#stringText field.cf_name
  1362. ^ argN
  1363. ^ this#commentOf field.cf_name
  1364. ^ "\n")
  1365. | FuncExtern (name, _) ->
  1366. this#write
  1367. (this#op IaCallGlobal ^ this#stringText name ^ argN
  1368. ^ this#commentOf name ^ "\n")
  1369. | FuncNew newType ->
  1370. this#write (this#op IaNew ^ this#astType newType ^ argN ^ "\n")
  1371. | FuncInternal (obj, "cca", ".") when obj.cpptype = TCppString ->
  1372. this#write
  1373. (this#op IaCallMember ^ this#astType obj.cpptype ^ " "
  1374. ^ this#stringText "cca" ^ argN ^ this#commentOf "cca" ^ "\n"
  1375. );
  1376. gen_expression obj
  1377. | FuncInternal (obj, name, join) ->
  1378. (* abort ("Internal function call '" ^ name ^ "' not supported in cppia") expression.cpppos; *)
  1379. this#write
  1380. (this#op IaCallMember ^ this#astType obj.cpptype ^ " "
  1381. ^ this#stringText name ^ argN ^ this#commentOf name ^ "\n");
  1382. gen_expression obj
  1383. | FuncExpression expr ->
  1384. this#write (this#op IaCall ^ argN ^ "\n");
  1385. gen_expression expr);
  1386. List.iter gen_expression args
  1387. | CppFunction (func, _) -> (
  1388. match func with
  1389. | FuncThis (field, inst) ->
  1390. this#write
  1391. (this#op IaFThisName ^ this#astType inst ^ " "
  1392. ^ this#stringText field.cf_name
  1393. ^ this#commentOf
  1394. (script_cpptype_string inst ^ "." ^ field.cf_name))
  1395. | FuncInternal (expr, name, _) ->
  1396. this#write
  1397. (this#op IaFLink ^ this#astType expr.cpptype ^ " "
  1398. ^ this#stringText name
  1399. ^ this#commentOf
  1400. ("Internal "
  1401. ^ script_cpptype_string expr.cpptype
  1402. ^ "." ^ name)
  1403. ^ "\n");
  1404. gen_expression expr
  1405. | FuncInstance (expr, _, field) | FuncInterface (expr, _, field)
  1406. ->
  1407. this#write
  1408. (this#op IaFName ^ this#astType expr.cpptype ^ " "
  1409. ^ this#stringText field.cf_name
  1410. ^ this#commentOf
  1411. (script_cpptype_string expr.cpptype
  1412. ^ "." ^ field.cf_name)
  1413. ^ "\n");
  1414. gen_expression expr
  1415. | FuncStatic (class_def, _, field) ->
  1416. this#write
  1417. (this#op IaFStatic ^ this#cppInstText class_def ^ " "
  1418. ^ this#stringText field.cf_name
  1419. ^ this#commentOf field.cf_name)
  1420. | FuncExpression expr -> match_expr expr
  1421. | FuncExtern (name, _) ->
  1422. abort
  1423. ("Can't create extern " ^ name ^ " closure")
  1424. expression.cpppos
  1425. | FuncSuper _ | FuncSuperConstruct _ ->
  1426. abort "Can't create super closure" expression.cpppos
  1427. | FuncNew _ -> abort "Can't create new closure" expression.cpppos
  1428. | FuncEnumConstruct _ ->
  1429. abort "Enum constructor outside of CppCall" expression.cpppos
  1430. | FuncFromStaticFunction ->
  1431. abort "Can't create cpp.Function.fromStaticFunction closure"
  1432. expression.cpppos
  1433. | FuncTemplate _ ->
  1434. abort "Can't create template function closure"
  1435. expression.cpppos)
  1436. | CppPosition (file, line, class_name, meth) ->
  1437. this#write
  1438. (this#op IaPosInfo ^ this#stringText file
  1439. ^ Printf.sprintf "%ld" line ^ " " ^ this#stringText class_name
  1440. ^ " " ^ this#stringText meth)
  1441. | CppNullCompare ("IsNull", e) ->
  1442. this#writeOpLine IaIsNull;
  1443. gen_expression e
  1444. | CppNullCompare (_, e) ->
  1445. this#writeOpLine IaNotNull;
  1446. gen_expression e
  1447. | CppCompare (_, left, right, op) ->
  1448. this#writeOpLine (IaBinOp op);
  1449. gen_expression left;
  1450. gen_expression right
  1451. | CppArray arrayLoc -> gen_array arrayLoc expression.cpppos
  1452. | CppArrayDecl exprList ->
  1453. this#write
  1454. (this#op IaADef
  1455. ^ this#astType expression.cpptype
  1456. ^ " "
  1457. ^ string_of_int (List.length exprList)
  1458. ^ "\n");
  1459. List.iter gen_expression exprList
  1460. | CppEnumField (enum, field) ->
  1461. this#write
  1462. (this#op IaFEnum ^ this#enumText enum ^ " "
  1463. ^ this#stringText field.ef_name
  1464. ^ this#commentOf field.ef_name)
  1465. | CppEnumIndex obj ->
  1466. (* Cppia does not have a "GetEnumIndex" op code - must use IaCallMember ::hx::EnumBase.__Index *)
  1467. this#write
  1468. (this#op IaCallMember
  1469. ^ this#typeTextString "::hx::EnumBase"
  1470. ^ " " ^ this#stringText "__Index" ^ "0"
  1471. ^ this#commentOf "Enum index"
  1472. ^ "\n");
  1473. gen_expression obj
  1474. | CppDynamicField (obj, name) ->
  1475. this#write
  1476. (this#op IaFName
  1477. ^ this#typeTextString "Dynamic"
  1478. ^ " " ^ this#stringText name ^ this#commentOf name ^ "\n");
  1479. gen_expression obj
  1480. | CppClassOf (path, native) ->
  1481. let klass = join_class_path path "." in
  1482. this#write
  1483. (this#op IaClassOf ^ this#typeTextString klass
  1484. ^ this#commentOf klass)
  1485. | CppEnumParameter (obj, field, index) ->
  1486. this#write
  1487. (this#op IaEnumI
  1488. ^ this#typeTextString "Dynamic"
  1489. ^ string_of_int index ^ "\n");
  1490. gen_expression obj
  1491. | CppClosure closure ->
  1492. this#write
  1493. (this#op IaFun
  1494. ^ this#astType closure.close_type
  1495. ^ string_of_int (List.length closure.close_args)
  1496. ^ "\n");
  1497. let close = this#gen_func_args closure.close_args in
  1498. gen_expression closure.close_expr;
  1499. close ()
  1500. | CppObjectDecl (values, isStruct) ->
  1501. this#write (this#op IaObjDef ^ string_of_int (List.length values));
  1502. this#write " ";
  1503. List.iter
  1504. (fun (name, _) -> this#write (this#stringText name))
  1505. values;
  1506. this#write "\n";
  1507. List.iter (fun (_, e) -> gen_expression e) values
  1508. | CppCrement (incFlag, preFlag, lvalue) ->
  1509. let op =
  1510. match (incFlag, preFlag) with
  1511. | CppIncrement, Prefix -> IaPlusPlus
  1512. | CppIncrement, Postfix -> IaPlusPlusPost
  1513. | CppDecrement, Prefix -> IaMinusMinus
  1514. | CppDecrement, Postfix -> IaMinusMinusPost
  1515. in
  1516. this#writeOpLine op;
  1517. gen_lvalue lvalue expression.cpppos
  1518. | CppModify (op, lvalue, rvalue) ->
  1519. this#writeOpLine (IaBinOp (OpAssignOp op));
  1520. gen_lvalue lvalue expression.cpppos;
  1521. gen_expression rvalue
  1522. | CppUnop (op, expr) ->
  1523. let op =
  1524. match op with
  1525. | CppNot -> IaLogicNot
  1526. | CppNeg -> IaNeg
  1527. | CppNegBits -> IaBitNot
  1528. in
  1529. this#writeOpLine op;
  1530. gen_expression expr
  1531. | CppThrow value ->
  1532. this#writeOpLine IaThrow;
  1533. gen_expression value
  1534. | CppTry (block, catches) ->
  1535. this#writeList (this#op IaTry) (List.length catches);
  1536. gen_expression block;
  1537. List.iter
  1538. (fun (tvar, catch_expr) ->
  1539. this#write ("\t\t\t" ^ indent);
  1540. this#writeVar tvar;
  1541. this#write "\n";
  1542. gen_expression catch_expr)
  1543. catches
  1544. | CppIntSwitch _ ->
  1545. abort "CppIntSwitch not supported in cppia" expression.cpppos
  1546. | CppSwitch (condition, _, cases, optional_default, _) -> (
  1547. this#write
  1548. (this#op IaSwitch
  1549. ^ string_of_int (List.length cases)
  1550. ^ " "
  1551. ^ (match optional_default with None -> "0" | Some _ -> "1")
  1552. ^ "\n");
  1553. gen_expression condition;
  1554. List.iter
  1555. (fun (cases_list, expression) ->
  1556. this#writeList ("\t\t\t" ^ indent) (List.length cases_list);
  1557. List.iter (fun value -> gen_expression value) cases_list;
  1558. gen_expression expression)
  1559. cases;
  1560. match optional_default with
  1561. | None -> ()
  1562. | Some expr -> gen_expression expr)
  1563. | CppTCast (expr, toType) ->
  1564. this#write (this#op IaTCast ^ this#astType toType ^ "\n");
  1565. gen_expression expr
  1566. | CppCast (expr, toType) -> (
  1567. match toType with
  1568. | TCppDynamicArray ->
  1569. this#write (this#op IaToDynArray ^ "\n");
  1570. gen_expression expr
  1571. | TCppObjectArray _ ->
  1572. this#write
  1573. (this#op IaToDataArray
  1574. ^ this#typeTextString "Array.Object"
  1575. ^ "\n");
  1576. gen_expression expr
  1577. | TCppScalarArray t ->
  1578. this#write
  1579. (this#op IaToDataArray
  1580. ^ this#typeTextString ("Array." ^ script_cpptype_string t)
  1581. ^ "\n");
  1582. gen_expression expr
  1583. | _ -> match_expr expr)
  1584. | CppCastScalar (expr, "bool") ->
  1585. this#writeOpLine IaCastBool;
  1586. gen_expression expr
  1587. | CppCastScalar (expr, "int") ->
  1588. this#writeOpLine IaCastInt;
  1589. gen_expression expr
  1590. | CppCastScalar (expr, "Float") ->
  1591. this#write
  1592. (this#op IaTCast ^ this#astType (TCppScalar "Float") ^ "\n");
  1593. gen_expression expr
  1594. | CppCastScalar (expr, _) -> match_expr expr
  1595. | CppCastVariant expr -> match_expr expr
  1596. | CppCastStatic (expr, _) -> match_expr expr
  1597. | CppNullAccess ->
  1598. this#writeOpLine IaThrow;
  1599. this#begin_expr;
  1600. this#writeCppPos expression;
  1601. this#write (this#op IaConstString ^ this#stringText "Null access");
  1602. this#end_expr
  1603. | CppCode _ | CppFunctionAddress _ | CppNewNative _ | CppDereference _
  1604. | CppAddressOf _ | CppFor _ | CppCastObjC _ | CppCastObjCBlock _
  1605. | CppCastProtocol _ | CppCastNative _ ->
  1606. abort
  1607. ("Unsupported operation in cppia :" ^ s_tcpp expression.cppexpr)
  1608. expression.cpppos
  1609. (*| x -> print_endline ("Unknown cppexpr " ^ (s_tcpp x) );*)
  1610. in
  1611. match_expr expression;
  1612. this#end_expr
  1613. and gen_array arrayLoc pos =
  1614. match arrayLoc with
  1615. | ArrayObject (arrayObj, index, _) | ArrayTyped (arrayObj, index, _) ->
  1616. this#write (this#op IaArrayI ^ this#astType arrayObj.cpptype ^ "\n");
  1617. gen_expression arrayObj;
  1618. gen_expression index
  1619. | ArrayPointer (_, _) | ArrayRawPointer (_, _) ->
  1620. abort "Unvalid array access in cppia" pos
  1621. | ArrayVirtual (arrayObj, index)
  1622. | ArrayImplements (_, arrayObj, index)
  1623. | ArrayDynamic (arrayObj, index) ->
  1624. this#write (this#op IaArrayI ^ this#astType arrayObj.cpptype ^ "\n");
  1625. gen_expression arrayObj;
  1626. gen_expression index
  1627. and gen_lvalue lvalue pos =
  1628. this#begin_expr;
  1629. this#wpos pos;
  1630. (match lvalue with
  1631. | CppVarRef varLoc -> gen_var_loc varLoc
  1632. | CppArrayRef arrayLoc -> gen_array arrayLoc pos
  1633. | CppExternRef (name, _) ->
  1634. abort ("Unsupported extern '" ^ name ^ "' in cppia") pos
  1635. | CppDynamicRef (expr, name) ->
  1636. let typeText = this#typeTextString "Dynamic" in
  1637. this#write
  1638. (this#op IaFName ^ typeText ^ " " ^ this#stringText name
  1639. ^ this#commentOf name ^ "\n");
  1640. gen_expression expr);
  1641. this#end_expr
  1642. and gen_var_loc loc =
  1643. match loc with
  1644. | VarClosure var | VarLocal var ->
  1645. this#write
  1646. (this#op IaVar ^ string_of_int var.v_id
  1647. ^ this#commentOf var.v_name)
  1648. | VarStatic (class_def, _, field) ->
  1649. this#write
  1650. (this#op IaFStatic ^ this#cppInstText class_def ^ " "
  1651. ^ this#stringText field.cf_name
  1652. ^ this#commentOf field.cf_name)
  1653. | VarThis (field, thisType) ->
  1654. this#write
  1655. (this#op IaFThisInst ^ this#astType thisType ^ " "
  1656. ^ this#stringText field.cf_name
  1657. ^ this#commentOf field.cf_name)
  1658. | VarInstance (obj, field, _, _) | VarInterface (obj, field) ->
  1659. let objType = script_cpptype_string obj.cpptype in
  1660. this#write
  1661. (this#op IaFLink ^ this#astType obj.cpptype ^ " "
  1662. ^ this#stringText field.cf_name
  1663. ^ this#commentOf (objType ^ "." ^ field.cf_name)
  1664. ^ "\n");
  1665. gen_expression obj
  1666. | VarInternal (obj, _, name) ->
  1667. let objType = script_cpptype_string obj.cpptype in
  1668. this#write
  1669. (this#op IaFLink ^ this#astType obj.cpptype ^ " "
  1670. ^ this#stringText name
  1671. ^ this#commentOf (objType ^ "." ^ name)
  1672. ^ "\n");
  1673. gen_expression obj
  1674. (*
  1675. and get_array_type elem =
  1676. this#stringText (script_cpptype_string elem.cpptype);
  1677. *)
  1678. in
  1679. gen_expression expression_tree
  1680. end
  1681. let generate_script_class common_ctx script class_def =
  1682. script#incClasses;
  1683. let classText = join_class_path class_def.cl_path "." in
  1684. script#comment ("Class " ^ classText);
  1685. script#writeOp
  1686. (if has_class_flag class_def CInterface then IaInterface else IaClass);
  1687. script#instName class_def;
  1688. (match class_def.cl_super with
  1689. | None -> script#ident ""
  1690. | Some (c, _) -> script#instName c);
  1691. script#wint (List.length class_def.cl_implements);
  1692. List.iter (fun (c, _) -> script#instName c) class_def.cl_implements;
  1693. script#write "\n";
  1694. (* Looks like some map impl classes have their bodies discarded - not sure best way to filter *)
  1695. let non_dodgy_function allow_empty field =
  1696. has_class_flag class_def CInterface
  1697. ||
  1698. match (field.cf_kind, field.cf_expr) with
  1699. | Var _, _ -> true
  1700. | Method MethDynamic, _ -> true
  1701. | Method MethNormal, None when allow_empty -> true
  1702. | Method _, Some _ -> true
  1703. | _ -> false
  1704. in
  1705. let ordered_statics =
  1706. List.filter (non_dodgy_function false) class_def.cl_ordered_statics
  1707. in
  1708. let ordered_fields =
  1709. List.filter (non_dodgy_function true) class_def.cl_ordered_fields
  1710. in
  1711. script#write
  1712. (string_of_int
  1713. (List.length ordered_fields
  1714. + List.length ordered_statics
  1715. + (match class_def.cl_constructor with Some _ -> 1 | _ -> 0)
  1716. + match TClass.get_cl_init class_def with Some _ -> 1 | _ -> 0)
  1717. ^ "\n");
  1718. let generate_field isStatic field =
  1719. match (field.cf_kind, follow field.cf_type) with
  1720. | Var { v_read = AccInline; v_write = AccNever }, _ ->
  1721. script#writeOpLine IaInline
  1722. | Var v, _ ->
  1723. let mode_code mode =
  1724. match mode with
  1725. | AccNormal | AccCtor -> IaAccessNormal
  1726. | AccNo -> IaAccessNot
  1727. | AccNever -> IaAccessNot
  1728. | AccCall ->
  1729. if
  1730. Meta.has Meta.NativeProperty class_def.cl_meta
  1731. || Meta.has Meta.NativeProperty field.cf_meta
  1732. || Gctx.defined common_ctx Define.ForceNativeProperty
  1733. then IaAccessCallNative
  1734. else IaAccessCall
  1735. | AccInline -> IaAccessNormal
  1736. | AccRequire (_, _) -> IaAccessNormal
  1737. in
  1738. let isExtern = not (is_physical_field field) in
  1739. script#var (mode_code v.v_read) (mode_code v.v_write) isExtern isStatic
  1740. field.cf_name field.cf_type field.cf_expr
  1741. | Method MethDynamic, TFun (args, ret) ->
  1742. script#func isStatic true field.cf_name ret args
  1743. (has_class_flag class_def CInterface)
  1744. field.cf_expr field.cf_pos
  1745. | Method _, TFun (args, ret) when field.cf_name = "new" ->
  1746. script#func true false "new"
  1747. (TInst (class_def, []))
  1748. args false field.cf_expr field.cf_pos
  1749. | Method _, TFun (args, ret) ->
  1750. script#func isStatic false field.cf_name ret args
  1751. (has_class_flag class_def CInterface)
  1752. field.cf_expr field.cf_pos
  1753. | Method _, _ ->
  1754. print_endline
  1755. ("Unknown method type "
  1756. ^ join_class_path class_def.cl_path "."
  1757. ^ "." ^ field.cf_name)
  1758. in
  1759. (match class_def.cl_constructor with
  1760. | Some field -> generate_field true field
  1761. | _ -> ());
  1762. (match TClass.get_cl_init class_def with
  1763. | Some expression -> script#voidFunc true false "__init__" expression
  1764. | _ -> ());
  1765. List.iter (generate_field false) ordered_fields;
  1766. List.iter (generate_field true) ordered_statics;
  1767. script#write "\n"
  1768. let generate_script_enum script enum_def meta =
  1769. script#incClasses;
  1770. let sorted_items =
  1771. List.sort
  1772. (fun f1 f2 -> f1.ef_index - f2.ef_index)
  1773. (pmap_values enum_def.e_constrs)
  1774. in
  1775. script#writeList
  1776. (script#op IaEnum ^ script#enumText enum_def)
  1777. (List.length sorted_items);
  1778. List.iter
  1779. (fun constructor ->
  1780. let name = script#stringText constructor.ef_name in
  1781. match constructor.ef_type with
  1782. | TFun (args, _) ->
  1783. script#write (name ^ " " ^ string_of_int (List.length args));
  1784. List.iter
  1785. (fun (arg, _, t) ->
  1786. script#write
  1787. (" " ^ script#stringText arg ^ " " ^ script#typeText t))
  1788. args;
  1789. script#write "\n"
  1790. | _ -> script#write (name ^ " 0\n"))
  1791. sorted_items;
  1792. match meta with
  1793. | Some expr ->
  1794. script#write "1\n";
  1795. script#gen_expression expr
  1796. | _ ->
  1797. script#write "0\n";
  1798. script#write "\n"
  1799. let generate_cppia ctx =
  1800. let common_ctx = ctx.ctx_common in
  1801. let debug = ctx.ctx_debug_level in
  1802. Path.mkdir_from_path common_ctx.file;
  1803. let script = new script_writer ctx common_ctx.file common_ctx.debug in
  1804. ignore (script#stringId "");
  1805. ignore (script#typeId "");
  1806. List.iter
  1807. (fun object_def ->
  1808. match object_def with
  1809. | TClassDecl class_def when has_class_flag class_def CExtern ->
  1810. () (*if (gen_externs) then gen_extern_class common_ctx class_def;*)
  1811. | TClassDecl class_def ->
  1812. let is_internal = is_internal_class class_def.cl_path in
  1813. if is_internal || Meta.has Meta.Macro class_def.cl_meta then (
  1814. if debug >= 4 then
  1815. print_endline
  1816. (" internal class " ^ join_class_path class_def.cl_path "."))
  1817. else generate_script_class common_ctx script class_def
  1818. | TEnumDecl enum_def when has_enum_flag enum_def EnExtern -> ()
  1819. | TEnumDecl enum_def ->
  1820. let is_internal = is_internal_class enum_def.e_path in
  1821. if is_internal then (
  1822. if debug >= 4 then
  1823. print_endline
  1824. (" internal enum " ^ join_class_path enum_def.e_path "."))
  1825. else
  1826. let meta = Texpr.build_metadata common_ctx.basic object_def in
  1827. if has_enum_flag enum_def EnExtern then
  1828. if debug >= 4 then
  1829. print_endline
  1830. ("external enum " ^ join_class_path enum_def.e_path ".");
  1831. generate_script_enum script enum_def meta
  1832. | TTypeDecl _ | TAbstractDecl _ -> (* already done *) ())
  1833. common_ctx.types;
  1834. (match common_ctx.main.main_expr with
  1835. | None -> script#writeOpLine IaNoMain
  1836. | Some e ->
  1837. script#writeOpLine IaMain;
  1838. script#gen_expression e);
  1839. script#write
  1840. (script#op IaResources
  1841. ^ string_of_int (Hashtbl.length common_ctx.resources)
  1842. ^ "\n");
  1843. Hashtbl.iter
  1844. (fun name data ->
  1845. script#write
  1846. (script#op IaReso ^ script#stringText name
  1847. ^ string_of_int (String.length data)
  1848. ^ "\n"))
  1849. common_ctx.resources;
  1850. Hashtbl.iter (fun _ data -> script#writeData data) common_ctx.resources;
  1851. script#close