common.ml 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. (*
  2. * Copyright (C)2005-2013 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. *)
  22. open Ast
  23. open Type
  24. type package_rule =
  25. | Forbidden
  26. | Directory of string
  27. | Remap of string
  28. type pos = Ast.pos
  29. type basic_types = {
  30. mutable tvoid : t;
  31. mutable tint : t;
  32. mutable tfloat : t;
  33. mutable tbool : t;
  34. mutable tnull : t -> t;
  35. mutable tstring : t;
  36. mutable tarray : t -> t;
  37. }
  38. type stats = {
  39. s_files_parsed : int ref;
  40. s_classes_built : int ref;
  41. s_methods_typed : int ref;
  42. s_macros_called : int ref;
  43. }
  44. type platform =
  45. | Cross
  46. | Flash8
  47. | Js
  48. | Neko
  49. | Flash
  50. | Php
  51. | Cpp
  52. | Cs
  53. | Java
  54. (**
  55. The capture policy tells which handling we make of captured locals
  56. (the locals which are referenced in local functions)
  57. See details/implementation in Codegen.captured_vars
  58. *)
  59. type capture_policy =
  60. (** do nothing, let the platform handle it *)
  61. | CPNone
  62. (** wrap all captured variables into a single-element array to allow modifications *)
  63. | CPWrapRef
  64. (** similar to wrap ref, but will only apply to the locals that are declared in loops *)
  65. | CPLoopVars
  66. type platform_config = {
  67. (** has a static type system, with not-nullable basic types (Int/Float/Bool) *)
  68. pf_static : bool;
  69. (** has access to the "sys" package *)
  70. pf_sys : bool;
  71. (** local variables are block-scoped *)
  72. pf_locals_scope : bool;
  73. (** captured local variables are scoped *)
  74. pf_captured_scope : bool;
  75. (** generated locals must be absolutely unique wrt the current function *)
  76. pf_unique_locals : bool;
  77. (** which expressions can be generated to initialize member variables (or will be moved into the constructor *)
  78. pf_can_init_member : tclass_field -> bool;
  79. (** captured variables handling (see before) *)
  80. pf_capture_policy : capture_policy;
  81. (** when calling a method with optional args, do we replace the missing args with "null" constants *)
  82. pf_pad_nulls : bool;
  83. (** add a final return to methods not having one already - prevent some compiler warnings *)
  84. pf_add_final_return : bool;
  85. (** does the platform natively support overloaded functions *)
  86. pf_overload : bool;
  87. }
  88. type context = {
  89. (* config *)
  90. version : int;
  91. args : string list;
  92. mutable sys_args : string list;
  93. mutable display : bool;
  94. mutable debug : bool;
  95. mutable verbose : bool;
  96. mutable foptimize : bool;
  97. mutable platform : platform;
  98. mutable config : platform_config;
  99. mutable std_path : string list;
  100. mutable class_path : string list;
  101. mutable main_class : Type.path option;
  102. mutable defines : (string,string) PMap.t;
  103. mutable package_rules : (string,package_rule) PMap.t;
  104. mutable error : string -> pos -> unit;
  105. mutable warning : string -> pos -> unit;
  106. mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *)
  107. mutable filters : (unit -> unit) list;
  108. mutable defines_signature : string option;
  109. mutable print : string -> unit;
  110. mutable get_macros : unit -> context option;
  111. mutable run_command : string -> int;
  112. (* output *)
  113. mutable file : string;
  114. mutable flash_version : float;
  115. mutable features : (string,bool) Hashtbl.t;
  116. mutable modules : Type.module_def list;
  117. mutable main : Type.texpr option;
  118. mutable types : Type.module_type list;
  119. mutable resources : (string,string) Hashtbl.t;
  120. mutable neko_libs : string list;
  121. mutable php_front : string option;
  122. mutable php_lib : string option;
  123. mutable php_prefix : string option;
  124. mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list;
  125. mutable java_libs : (string * bool * (unit -> unit) * (unit -> ((string list * string) list)) * ((string list * string) -> ((JData.jclass * string * string) option))) list;
  126. mutable js_gen : (unit -> unit) option;
  127. (* typing *)
  128. mutable basic : basic_types;
  129. }
  130. exception Abort of string * Ast.pos
  131. let display_default = ref false
  132. module Define = struct
  133. type strict_defined =
  134. | AbsolutePath
  135. | AdvancedTelemetry
  136. | As3
  137. | CheckXmlProxy
  138. | CoreApi
  139. | Dce
  140. | DceDebug
  141. | Debug
  142. | Display
  143. | DisplayMode
  144. | DllExport
  145. | DllImport
  146. | DocGen
  147. | Dump
  148. | DumpDependencies
  149. | Fdb
  150. | FlashStrict
  151. | FlashUseStage
  152. | FormatWarning
  153. | GencommonDebug
  154. | HaxeBoot
  155. | HaxeVer
  156. | Interp
  157. | JavaVer
  158. | JsClassic
  159. | Macro
  160. | MacroTimes
  161. | NekoSource
  162. | NekoV1
  163. | NetworkSandbox
  164. | NoCompilation
  165. | NoCOpt
  166. | NoInline
  167. | NoOpt
  168. | NoPatternMatching
  169. | NoRoot
  170. | NoSwfCompress
  171. | NoTraces
  172. | PhpPrefix
  173. | RealPosition
  174. | ReplaceFiles
  175. | Scriptable
  176. | Swc
  177. | SwfCompressLevel
  178. | SwfDebugPassword
  179. | SwfDirectBlit
  180. | SwfGpu
  181. | SwfMark
  182. | SwfMetadata
  183. | SwfPreloaderFrame
  184. | SwfProtected
  185. | SwfScriptTimeout
  186. | Sys
  187. | UseNekoc
  188. | UseRttiDoc
  189. | Vcproj
  190. | NoMacroCache
  191. | Last (* must be last *)
  192. let infos = function
  193. | AbsolutePath -> ("absolute_path","Print absoluate file path in trace output")
  194. | AdvancedTelemetry -> ("advanced-telemetry","Allow the SWF to be measured with Monocle tool")
  195. | As3 -> ("as3","Defined when outputing flash9 as3 source code")
  196. | CheckXmlProxy -> ("check_xml_proxy","Check the used fields of the xml proxy")
  197. | CoreApi -> ("core_api","Defined in the core api context")
  198. | Dce -> ("dce","The current DCE mode")
  199. | DceDebug -> ("dce_debug","Show DCE log")
  200. | Debug -> ("debug","Activated when compiling with -debug")
  201. | Display -> ("display","Activated during completion")
  202. | DisplayMode -> ("display_mode", "The display mode to use (default, position, metadata, usage)")
  203. | DllExport -> ("dll_export", "GenCPP experimental linking")
  204. | DllImport -> ("dll_import", "GenCPP experimental linking")
  205. | DocGen -> ("doc_gen","Do not perform any removal/change in order to correctly generate documentation")
  206. | Dump -> ("dump","Dump the complete typed AST for internal debugging")
  207. | DumpDependencies -> ("dump_dependencies","Dump the classes dependencies")
  208. | Fdb -> ("fdb","Enable full flash debug infos for FDB interactive debugging")
  209. | FlashStrict -> ("flash_strict","More strict typing for flash target")
  210. | FlashUseStage -> ("flash_use_stage","Keep the SWF library initial stage")
  211. | FormatWarning -> ("format_warning","Print a warning for each formated string, for 2.x compatibility")
  212. | GencommonDebug -> ("gencommon_debug","GenCommon internal")
  213. | HaxeBoot -> ("haxe_boot","Given the name 'haxe' to the flash boot class instead of a generated name")
  214. | HaxeVer -> ("haxe_ver","The current Haxe version value")
  215. | Interp -> ("interp","The code is compiled to be run with --interp")
  216. | JavaVer -> ("java_ver", "<version:5-7> Sets the Java version to be targeted")
  217. | JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output")
  218. | Macro -> ("macro","Defined when we compile code in the macro context")
  219. | MacroTimes -> ("macro_times","Display per-macro timing when used with --times")
  220. | NekoSource -> ("neko_source","Output neko source instead of bytecode")
  221. | NekoV1 -> ("neko_v1","Keep Neko 1.x compatibility")
  222. | NetworkSandbox -> ("network-sandbox","Use local network sandbox instead of local file access one")
  223. | NoCompilation -> ("no-compilation","Disable CPP final compilation")
  224. | NoCOpt -> ("no_copt","Disable completion optimization (for debug purposes)")
  225. | NoOpt -> ("no_opt","Disable optimizations")
  226. | NoPatternMatching -> ("no_pattern_matching","Disable pattern matching")
  227. | NoInline -> ("no_inline","Disable inlining")
  228. | NoRoot -> ("no_root","GenCS internal")
  229. | NoMacroCache -> ("no_macro_cache","Disable macro context caching")
  230. | NoSwfCompress -> ("no_swf_compress","Disable SWF output compression")
  231. | NoTraces -> ("no_traces","Disable all trace calls")
  232. | PhpPrefix -> ("php_prefix","Compiled with --php-prefix")
  233. | RealPosition -> ("real_position","Disables haxe source mapping when targetting C#")
  234. | ReplaceFiles -> ("replace_files","GenCommon internal")
  235. | Scriptable -> ("scriptable","GenCPP internal")
  236. | Swc -> ("swc","Output a SWC instead of a SWF")
  237. | SwfCompressLevel -> ("swf_compress_level","<level:1-9> Set the amount of compression for the SWF output")
  238. | SwfDebugPassword -> ("swf_debug_password", "Set a password for debugging.")
  239. | SwfDirectBlit -> ("swf_direct_blit", "Use hardware acceleration to blit graphics")
  240. | SwfGpu -> ("swf_gpu", "Use GPU compositing features when drawing graphics")
  241. | SwfMark -> ("swf_mark","GenSWF8 internal")
  242. | SwfMetadata -> ("swf_metadata", "=<file> Include contents of <file> as metadata in the swf.")
  243. | SwfPreloaderFrame -> ("swf_preloader_frame", "Insert empty first frame in swf")
  244. | SwfProtected -> ("swf_protected","Compile Haxe private as protected in the SWF instead of public")
  245. | SwfScriptTimeout -> ("swf_script_timeout", "Maximum ActionScript processing time before script stuck dialog box displays (in seconds)")
  246. | Sys -> ("sys","Defined for all system platforms")
  247. | UseNekoc -> ("use_nekoc","Use nekoc compiler instead of internal one")
  248. | UseRttiDoc -> ("use_rtti_doc","Allows access to documentation during compilation")
  249. | Vcproj -> ("vcproj","GenCPP internal")
  250. | Last -> assert false
  251. end
  252. module MetaInfo = struct
  253. open Meta
  254. type meta_usage =
  255. | TClass
  256. | TClassField
  257. | TAbstract
  258. | TAbstractField
  259. | TEnum
  260. | TTypedef
  261. | TAnyField
  262. type meta_parameter =
  263. | HasParam of string
  264. | Platform of platform
  265. | Platforms of platform list
  266. | UsedOn of meta_usage
  267. | UsedOnEither of meta_usage list
  268. | Internal
  269. let to_string = function
  270. | Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]])
  271. | Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]])
  272. | Allow -> ":allow",("Allows private access from package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]])
  273. | Annotation -> ":annotation",("Annotation (@interface) definitions on -java-lib imports will be annotated with this metadata. Has no effect on types compiled by Haxe",[Platform Java; UsedOn TClass])
  274. | ArrayAccess -> ":arrayAccess",("Allows [] access on an abstract",[UsedOnEither [TAbstract;TAbstractField]])
  275. | AutoBuild -> ":autoBuild",("Extends @:build metadata to all extending and implementing classes",[HasParam "Build macro call";UsedOn TClass])
  276. | Bind -> ":bind",("Override Swf class declaration",[Platform Flash;UsedOn TClass])
  277. | Bitmap -> ":bitmap",("Embeds given bitmap data into the class (must extend flash.display.BitmapData)",[HasParam "Bitmap file path";UsedOn TClass;Platform Flash])
  278. | Build -> ":build",("Builds a class or enum from a macro",[HasParam "Build macro call";UsedOnEither [TClass;TEnum]])
  279. | BuildXml -> ":buildXml",("",[Platform Cpp])
  280. | Class -> ":class",("Used internally to annotate an enum that will be generated as a class",[Platforms [Java;Cs]; UsedOn TEnum; Internal])
  281. | ClassCode -> ":classCode",("Used to inject platform-native code into a class",[Platforms [Java;Cs]; UsedOn TClass])
  282. | Commutative -> ":commutative",("Declares an abstract operator as commutative",[UsedOn TAbstractField])
  283. | CompilerGenerated -> ":compilerGenerated",("Marks a field as generated by the compiler. Shouldn't be used by the end user",[Platforms [Java;Cs]])
  284. | CoreApi -> ":coreApi",("Identifies this class as a core api class (forces Api check)",[UsedOnEither [TClass;TEnum;TTypedef;TAbstract]])
  285. | CoreType -> ":coreType",("Identifies an abstract as core type so that it requires no implementation",[UsedOn TAbstract])
  286. | CppFileCode -> ":cppFileCode",("",[Platform Cpp])
  287. | CppNamespaceCode -> ":cppNamespaceCode",("",[Platform Cpp])
  288. | Debug -> ":debug",("Forces debug information to be generated into the Swf even without -debug",[UsedOnEither [TClass;TClassField]; Platform Flash])
  289. | Decl -> ":decl",("",[Platform Cpp])
  290. | DefParam -> ":defParam",("?",[])
  291. | Depend -> ":depend",("",[Platform Cpp])
  292. | Deprecated -> ":deprecated",("Automatically added by -java-lib on class fields annotated with @Deprecated annotation. Has no effect on types compiled by Haxe.",[Platform Java; UsedOnEither [TClass;TEnum;TClassField]])
  293. | DynamicObject -> ":dynamicObject",("Used internally to identify the Dynamic Object implementation",[Platforms [Java;Cs]; UsedOn TClass; Internal])
  294. | Enum -> ":enum",("Used internally to annotate a class that was generated from an enum",[Platforms [Java;Cs]; UsedOn TClass; Internal])
  295. | EnumConstructorParam -> ":enumConstructorParam",("Used internally to annotate GADT type parameters",[UsedOn TClass; Internal])
  296. | Expose -> ":expose",("Makes the class available on the window object",[HasParam "?Name=Class path";UsedOn TClass;Platform Js])
  297. | Extern -> ":extern",("Marks the field as extern so it is not generated",[UsedOn TClassField])
  298. | FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum])
  299. | File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash])
  300. | Final -> ":final",("Prevents a class from being extended",[UsedOn TClass])
  301. | Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass])
  302. | From -> ":from",("Specifies that the field of the abstract is a cast operation from the type identified in the function",[UsedOn TAbstractField])
  303. | FunctionCode -> ":functionCode",("",[Platform Cpp])
  304. | FunctionTailCode -> ":functionTailCode",("",[Platform Cpp])
  305. | Generic -> ":generic",("Marks a class or class field as generic so each type parameter combination generates its own type/field",[UsedOnEither [TClass;TClassField]])
  306. | Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
  307. | Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass])
  308. | HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
  309. | HeaderClassCode -> ":headerClassCode",("",[Platform Cpp])
  310. | HeaderCode -> ":headerCode",("",[Platform Cpp])
  311. | HeaderNamespaceCode -> ":headerNamespaceCode",("",[Platform Cpp])
  312. | HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]])
  313. | IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField])
  314. | Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; Internal])
  315. | Include -> ":include",("",[Platform Cpp])
  316. | InitPackage -> ":initPackage",("?",[])
  317. | Meta.Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]])
  318. | IsVar -> ":isVar",("Forces a physical field to be generated for properties that otherwise would not require one",[UsedOn TClassField])
  319. | JavaNative -> ":javaNative",("Automatically added by -java-lib on classes generated from JAR/class files",[Platform Java; UsedOnEither[TClass;TEnum]; Internal])
  320. | Keep -> ":keep",("Causes a field or type to be kept by DCE",[])
  321. | KeepInit -> ":keepInit",("Causes a class to be kept by DCE even if all its field are removed",[UsedOn TClass])
  322. | KeepSub -> ":keepSub",("Extends @:keep metadata to all implementing and extending classes",[UsedOn TClass])
  323. | Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[])
  324. | Macro -> ":macro",("(deprecated)",[])
  325. | MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[Internal])
  326. | MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract])
  327. | Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]])
  328. | NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum]])
  329. | NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
  330. | NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField])
  331. | NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash])
  332. | NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[])
  333. | NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField])
  334. | NoPackageRestrict -> ":noPackageRestrict",("?",[])
  335. | NoStack -> ":noStack",("",[Platform Cpp])
  336. | NotNull -> ":notNull",("Declares an abstract type as not accepting null values",[UsedOn TAbstract])
  337. | NoUsing -> ":noUsing",("Prevents a field from being used with 'using'",[UsedOn TClassField])
  338. | Ns -> ":ns",("Internally used by the Swf generator to handle namespaces",[Platform Flash])
  339. | Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField])
  340. | Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField])
  341. | Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField])
  342. | Public -> ":public",("Marks a class field as being public",[UsedOn TClassField])
  343. | PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass])
  344. | PrivateAccess -> ":privateAccess",("Internally used by the typer to allow context-sensitive private access",[Internal])
  345. | Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField])
  346. | ReadOnly -> ":readOnly",("Generates a field with the 'readonly' native keyword",[Platform Cs; UsedOn TClassField])
  347. | RealPath -> ":realPath",("Internally used on @:native types to retain original path information",[Internal])
  348. | Remove -> ":remove",("Causes an interface to be removed from all implementing classes before generation",[UsedOn TClass])
  349. | Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField])
  350. | ReplaceReflection -> ":replaceReflection",("Used internally to specify a function that should replace its internal __hx_functionName counterpart",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum]; Internal])
  351. | Rtti -> ":rtti",("Adds runtime type informations",[UsedOn TClass])
  352. | Runtime -> ":runtime",("?",[])
  353. | RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract])
  354. | Setter -> ":setter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
  355. | SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; Internal])
  356. | SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; Internal])
  357. | Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash])
  358. | Struct -> ":struct",("Marks a class definition as a struct.",[Platform Cs; UsedOn TClass])
  359. | SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass])
  360. | Throws -> ":throws",("Adds a 'throws' declaration to the generated function.",[HasParam "Type as String"; Platform Java; UsedOn TClassField])
  361. | To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField])
  362. | ToString -> ":toString",("Internally used",[Internal])
  363. | Transient -> ":transient",("Adds the 'transient' flag to the class field",[Platform Java; UsedOn TClassField])
  364. | ValueUsed -> ":valueUsed",("Internally used by DCE to mark an abstract value as used",[Internal])
  365. | Volatile -> ":volatile",("",[Platforms [Java;Cs]])
  366. | UnifyMinDynamic -> ":unifyMinDynamic",("Allows a collection of types to unify to Dynamic",[UsedOn TClassField])
  367. | Unreflective -> ":unreflective",("",[Platform Cpp])
  368. | Unsafe -> ":unsafe",("Declares a class, or a method with the C#'s 'unsafe' flag",[Platform Cs; UsedOnEither [TClass;TClassField]])
  369. | Usage -> ":usage",("?",[])
  370. | Used -> ":used",("Internally used by DCE to mark a class or field as used",[Internal])
  371. | Last -> assert false
  372. (* do not put any custom metadata after Last *)
  373. | Dollar s -> "$" ^ s,("",[])
  374. | Custom s -> s,("",[])
  375. let hmeta =
  376. let h = Hashtbl.create 0 in
  377. let rec loop i =
  378. let m = Obj.magic i in
  379. if m <> Last then begin
  380. Hashtbl.add h (fst (to_string m)) m;
  381. loop (i + 1);
  382. end;
  383. in
  384. loop 0;
  385. h
  386. let parse s = try Hashtbl.find hmeta (":" ^ s) with Not_found -> Custom (":" ^ s)
  387. let from_string s =
  388. if s = "" then Custom "" else match s.[0] with
  389. | ':' -> (try Hashtbl.find hmeta s with Not_found -> Custom s)
  390. | '$' -> Dollar (String.sub s 1 (String.length s - 1))
  391. | _ -> Custom s
  392. end
  393. let stats =
  394. {
  395. s_files_parsed = ref 0;
  396. s_classes_built = ref 0;
  397. s_methods_typed = ref 0;
  398. s_macros_called = ref 0;
  399. }
  400. let default_config =
  401. {
  402. pf_static = true;
  403. pf_sys = true;
  404. pf_locals_scope = true;
  405. pf_captured_scope = true;
  406. pf_unique_locals = false;
  407. pf_can_init_member = (fun _ -> true);
  408. pf_capture_policy = CPNone;
  409. pf_pad_nulls = false;
  410. pf_add_final_return = false;
  411. pf_overload = false;
  412. }
  413. let get_config com =
  414. let defined f = PMap.mem (fst (Define.infos f)) com.defines in
  415. match com.platform with
  416. | Cross ->
  417. default_config
  418. | Flash8 ->
  419. {
  420. pf_static = false;
  421. pf_sys = false;
  422. pf_locals_scope = com.flash_version > 6.;
  423. pf_captured_scope = false;
  424. pf_unique_locals = false;
  425. pf_can_init_member = (fun _ -> true);
  426. pf_capture_policy = CPLoopVars;
  427. pf_pad_nulls = false;
  428. pf_add_final_return = false;
  429. pf_overload = false;
  430. }
  431. | Js ->
  432. {
  433. pf_static = false;
  434. pf_sys = false;
  435. pf_locals_scope = false;
  436. pf_captured_scope = false;
  437. pf_unique_locals = false;
  438. pf_can_init_member = (fun _ -> false);
  439. pf_capture_policy = CPLoopVars;
  440. pf_pad_nulls = false;
  441. pf_add_final_return = false;
  442. pf_overload = false;
  443. }
  444. | Neko ->
  445. {
  446. pf_static = false;
  447. pf_sys = true;
  448. pf_locals_scope = true;
  449. pf_captured_scope = true;
  450. pf_unique_locals = false;
  451. pf_can_init_member = (fun _ -> false);
  452. pf_capture_policy = CPNone;
  453. pf_pad_nulls = true;
  454. pf_add_final_return = false;
  455. pf_overload = false;
  456. }
  457. | Flash when defined Define.As3 ->
  458. {
  459. pf_static = true;
  460. pf_sys = false;
  461. pf_locals_scope = false;
  462. pf_captured_scope = true;
  463. pf_unique_locals = true;
  464. pf_can_init_member = (fun _ -> true);
  465. pf_capture_policy = CPLoopVars;
  466. pf_pad_nulls = false;
  467. pf_add_final_return = true;
  468. pf_overload = false;
  469. }
  470. | Flash ->
  471. {
  472. pf_static = true;
  473. pf_sys = false;
  474. pf_locals_scope = true;
  475. pf_captured_scope = true; (* handled by genSwf9 *)
  476. pf_unique_locals = false;
  477. pf_can_init_member = (fun _ -> false);
  478. pf_capture_policy = CPLoopVars;
  479. pf_pad_nulls = false;
  480. pf_add_final_return = false;
  481. pf_overload = false;
  482. }
  483. | Php ->
  484. {
  485. pf_static = false;
  486. pf_sys = true;
  487. pf_locals_scope = false; (* some duplicate work is done in genPhp *)
  488. pf_captured_scope = false;
  489. pf_unique_locals = false;
  490. pf_can_init_member = (fun cf ->
  491. match cf.cf_kind, cf.cf_expr with
  492. | Var { v_write = AccCall }, _ -> false
  493. | _, Some { eexpr = TTypeExpr _ } -> false
  494. | _ -> true
  495. );
  496. pf_capture_policy = CPNone;
  497. pf_pad_nulls = true;
  498. pf_add_final_return = false;
  499. pf_overload = false;
  500. }
  501. | Cpp ->
  502. {
  503. pf_static = true;
  504. pf_sys = true;
  505. pf_locals_scope = true;
  506. pf_captured_scope = true;
  507. pf_unique_locals = false;
  508. pf_can_init_member = (fun _ -> false);
  509. pf_capture_policy = CPWrapRef;
  510. pf_pad_nulls = true;
  511. pf_add_final_return = true;
  512. pf_overload = false;
  513. }
  514. | Cs ->
  515. {
  516. pf_static = true;
  517. pf_sys = true;
  518. pf_locals_scope = false;
  519. pf_captured_scope = true;
  520. pf_unique_locals = true;
  521. pf_can_init_member = (fun _ -> false);
  522. pf_capture_policy = CPWrapRef;
  523. pf_pad_nulls = true;
  524. pf_add_final_return = false;
  525. pf_overload = true;
  526. }
  527. | Java ->
  528. {
  529. pf_static = true;
  530. pf_sys = true;
  531. pf_locals_scope = false;
  532. pf_captured_scope = true;
  533. pf_unique_locals = false;
  534. pf_can_init_member = (fun _ -> false);
  535. pf_capture_policy = CPWrapRef;
  536. pf_pad_nulls = true;
  537. pf_add_final_return = false;
  538. pf_overload = true;
  539. }
  540. let create v args =
  541. let m = Type.mk_mono() in
  542. {
  543. version = v;
  544. args = args;
  545. sys_args = args;
  546. debug = false;
  547. display = !display_default;
  548. verbose = false;
  549. foptimize = true;
  550. features = Hashtbl.create 0;
  551. platform = Cross;
  552. config = default_config;
  553. print = (fun s -> print_string s; flush stdout);
  554. run_command = Sys.command;
  555. std_path = [];
  556. class_path = [];
  557. main_class = None;
  558. defines = PMap.add "true" "1" (if !display_default then PMap.add "display" "1" PMap.empty else PMap.empty);
  559. package_rules = PMap.empty;
  560. file = "";
  561. types = [];
  562. filters = [];
  563. modules = [];
  564. main = None;
  565. flash_version = 10.;
  566. resources = Hashtbl.create 0;
  567. php_front = None;
  568. php_lib = None;
  569. swf_libs = [];
  570. java_libs = [];
  571. neko_libs = [];
  572. php_prefix = None;
  573. js_gen = None;
  574. load_extern_type = [];
  575. defines_signature = None;
  576. get_macros = (fun() -> None);
  577. warning = (fun _ _ -> assert false);
  578. error = (fun _ _ -> assert false);
  579. basic = {
  580. tvoid = m;
  581. tint = m;
  582. tfloat = m;
  583. tbool = m;
  584. tnull = (fun _ -> assert false);
  585. tstring = m;
  586. tarray = (fun _ -> assert false);
  587. };
  588. }
  589. let log com str =
  590. if com.verbose then com.print (str ^ "\n")
  591. let clone com =
  592. let t = com.basic in
  593. { com with basic = { t with tvoid = t.tvoid }; main_class = None; features = Hashtbl.create 0; }
  594. let file_time file =
  595. try (Unix.stat file).Unix.st_mtime with _ -> 0.
  596. let get_signature com =
  597. match com.defines_signature with
  598. | Some s -> s
  599. | None ->
  600. let str = String.concat "@" (PMap.foldi (fun k v acc ->
  601. (* don't make much difference between these special compilation flags *)
  602. match k with
  603. | "display" | "use_rtti_doc" | "macrotimes" -> acc
  604. | _ -> k :: v :: acc
  605. ) com.defines []) in
  606. let s = Digest.string str in
  607. com.defines_signature <- Some s;
  608. s
  609. let file_extension file =
  610. match List.rev (ExtString.String.nsplit file ".") with
  611. | e :: _ -> String.lowercase e
  612. | [] -> ""
  613. let platforms = [
  614. Flash8;
  615. Js;
  616. Neko;
  617. Flash;
  618. Php;
  619. Cpp;
  620. Cs;
  621. Java;
  622. ]
  623. let platform_name = function
  624. | Cross -> "cross"
  625. | Flash8 -> "flash8"
  626. | Js -> "js"
  627. | Neko -> "neko"
  628. | Flash -> "flash"
  629. | Php -> "php"
  630. | Cpp -> "cpp"
  631. | Cs -> "cs"
  632. | Java -> "java"
  633. let flash_versions = List.map (fun v ->
  634. let maj = int_of_float v in
  635. let min = int_of_float (mod_float (v *. 10.) 10.) in
  636. v, string_of_int maj ^ (if min = 0 then "" else "_" ^ string_of_int min)
  637. ) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8]
  638. let raw_defined ctx v =
  639. PMap.mem v ctx.defines
  640. let defined ctx v =
  641. raw_defined ctx (fst (Define.infos v))
  642. let raw_defined_value ctx k =
  643. PMap.find k ctx.defines
  644. let defined_value ctx v =
  645. raw_defined_value ctx (fst (Define.infos v))
  646. let defined_value_safe ctx v =
  647. try defined_value ctx v
  648. with Not_found -> ""
  649. let raw_define ctx v =
  650. let k,v = try ExtString.String.split v "=" with _ -> v,"1" in
  651. ctx.defines <- PMap.add k v ctx.defines;
  652. let k = String.concat "_" (ExtString.String.nsplit k "-") in
  653. ctx.defines <- PMap.add k v ctx.defines;
  654. ctx.defines_signature <- None
  655. let define_value ctx k v =
  656. raw_define ctx (fst (Define.infos k) ^ "=" ^ v)
  657. let define ctx v =
  658. raw_define ctx (fst (Define.infos v))
  659. let init_platform com pf =
  660. com.platform <- pf;
  661. let name = platform_name pf in
  662. let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
  663. com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms);
  664. com.config <- get_config com;
  665. (* if com.config.pf_static then define com "static"; *)
  666. if com.config.pf_sys then define com Define.Sys else com.package_rules <- PMap.add "sys" Forbidden com.package_rules;
  667. raw_define com name
  668. let add_feature com f =
  669. Hashtbl.replace com.features f true
  670. let has_dce com =
  671. (try defined_value com Define.Dce <> "no" with Not_found -> false)
  672. let rec has_feature com f =
  673. try
  674. Hashtbl.find com.features f
  675. with Not_found ->
  676. if com.types = [] then not (has_dce com) else
  677. match List.rev (ExtString.String.nsplit f ".") with
  678. | [] -> assert false
  679. | [cl] -> has_feature com (cl ^ ".*")
  680. | meth :: cl :: pack ->
  681. let r = (try
  682. let path = List.rev pack, cl in
  683. (match List.find (fun t -> t_path t = path && not (Ast.Meta.has Ast.Meta.RealPath (t_infos t).mt_meta)) com.types with
  684. | t when meth = "*" -> (match t with TAbstractDecl a -> Ast.Meta.has Ast.Meta.ValueUsed a.a_meta | _ -> Ast.Meta.has Ast.Meta.Used (t_infos t).mt_meta)
  685. | TClassDecl ({cl_extern = true} as c) -> Meta.has Meta.Used (try PMap.find meth c.cl_statics with Not_found -> PMap.find meth c.cl_fields).cf_meta
  686. | TClassDecl c -> PMap.exists meth c.cl_statics || PMap.exists meth c.cl_fields
  687. | _ -> false)
  688. with Not_found ->
  689. false
  690. ) in
  691. let r = r || not (has_dce com) in
  692. Hashtbl.add com.features f r;
  693. r
  694. let allow_package ctx s =
  695. try
  696. if (PMap.find s ctx.package_rules) = Forbidden then ctx.package_rules <- PMap.remove s ctx.package_rules
  697. with Not_found ->
  698. ()
  699. let error msg p = raise (Abort (msg,p))
  700. let platform ctx p = ctx.platform = p
  701. let add_filter ctx f =
  702. ctx.filters <- f :: ctx.filters
  703. let find_file ctx f =
  704. let rec loop = function
  705. | [] -> raise Not_found
  706. | p :: l ->
  707. let file = p ^ f in
  708. if Sys.file_exists file then
  709. file
  710. else
  711. loop l
  712. in
  713. loop ctx.class_path
  714. let get_full_path f = try Extc.get_full_path f with _ -> f
  715. let unique_full_path = if Sys.os_type = "Win32" || Sys.os_type = "Cygwin" then (fun f -> String.lowercase (get_full_path f)) else get_full_path
  716. let normalize_path p =
  717. let l = String.length p in
  718. if l = 0 then
  719. "./"
  720. else match p.[l-1] with
  721. | '\\' | '/' -> p
  722. | _ -> p ^ "/"
  723. (* ------------------------- TIMERS ----------------------------- *)
  724. type timer_infos = {
  725. name : string;
  726. mutable start : float list;
  727. mutable total : float;
  728. }
  729. let get_time = Extc.time
  730. let htimers = Hashtbl.create 0
  731. let new_timer name =
  732. try
  733. let t = Hashtbl.find htimers name in
  734. t.start <- get_time() :: t.start;
  735. t
  736. with Not_found ->
  737. let t = { name = name; start = [get_time()]; total = 0.; } in
  738. Hashtbl.add htimers name t;
  739. t
  740. let curtime = ref []
  741. let close t =
  742. let start = (match t.start with
  743. | [] -> assert false
  744. | s :: l -> t.start <- l; s
  745. ) in
  746. let now = get_time() in
  747. let dt = now -. start in
  748. t.total <- t.total +. dt;
  749. let rec loop() =
  750. match !curtime with
  751. | [] -> failwith ("Timer " ^ t.name ^ " closed while not active")
  752. | tt :: l -> curtime := l; if t != tt then loop()
  753. in
  754. loop();
  755. (* because of rounding errors while adding small times, we need to make sure that we don't have start > now *)
  756. List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime
  757. let timer name =
  758. let t = new_timer name in
  759. curtime := t :: !curtime;
  760. (function() -> close t)
  761. let rec close_times() =
  762. match !curtime with
  763. | [] -> ()
  764. | t :: _ -> close t; close_times()