123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230 |
- (*
- The Haxe Compiler
- Copyright (C) 2005-2019 Haxe Foundation
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *)
- open Extlib_leftovers
- open Ast
- open Type
- open Globals
- open Lookup
- open Define
- open NativeLibraries
- open Warning
- type package_rule =
- | Forbidden
- | Remap of string
- type pos = Globals.pos
- let const_type basic const default =
- match const with
- | TString _ -> basic.tstring
- | TInt _ -> basic.tint
- | TFloat _ -> basic.tfloat
- | TBool _ -> basic.tbool
- | _ -> default
- type stats = {
- s_files_parsed : int ref;
- s_classes_built : int ref;
- s_methods_typed : int ref;
- s_macros_called : int ref;
- }
- (**
- The capture policy tells which handling we make of captured locals
- (the locals which are referenced in local functions)
- See details/implementation in Codegen.captured_vars
- *)
- type capture_policy =
- (** do nothing, let the platform handle it *)
- | CPNone
- (** wrap all captured variables into a single-element array to allow modifications *)
- | CPWrapRef
- (** similar to wrap ref, but will only apply to the locals that are declared in loops *)
- | CPLoopVars
- type exceptions_config = {
- (* Base types which may be thrown from Haxe code without wrapping. *)
- ec_native_throws : path list;
- (* Base types which may be caught from Haxe code without wrapping. *)
- ec_native_catches : path list;
- (*
- Hint exceptions filter to avoid wrapping for targets, which can throw/catch any type
- Ignored on targets with a specific native base type for exceptions.
- *)
- ec_avoid_wrapping : bool;
- (* Path of a native class or interface, which can be used for wildcard catches. *)
- ec_wildcard_catch : path;
- (*
- Path of a native base class or interface, which can be thrown.
- This type is used to cast `haxe.Exception.thrown(v)` calls to.
- For example `throw 123` is compiled to `throw (cast Exception.thrown(123):ec_base_throw)`
- *)
- ec_base_throw : path;
- (*
- Checks if throwing this expression is a special case for current target
- and should not be modified.
- *)
- ec_special_throw : texpr -> bool;
- }
- type var_scope =
- | FunctionScope
- | BlockScope
- type var_scoping_flags =
- (**
- Variables are hoisted in their scope
- *)
- | VarHoisting
- (**
- It's not allowed to shadow existing variables in a scope.
- *)
- | NoShadowing
- (**
- It's not allowed to shadow a `catch` variable.
- *)
- | NoCatchVarShadowing
- (**
- Local vars cannot have the same name as the current top-level package or
- (if in the root package) current class name
- *)
- | ReserveCurrentTopLevelSymbol
- (**
- Local vars cannot have a name used for any top-level symbol
- (packages and classes in the root package)
- *)
- | ReserveAllTopLevelSymbols
- (**
- Reserve all type-paths converted to "flat path" with `Path.flat_path`
- *)
- | ReserveAllTypesFlat
- (**
- List of names cannot be taken by local vars
- *)
- | ReserveNames of string list
- (**
- Cases in a `switch` won't have blocks, but will share the same outer scope.
- *)
- | SwitchCasesNoBlocks
- type var_scoping_config = {
- vs_flags : var_scoping_flags list;
- vs_scope : var_scope;
- }
- type platform_config = {
- (** has a static type system, with not-nullable basic types (Int/Float/Bool) *)
- pf_static : bool;
- (** has access to the "sys" package *)
- pf_sys : bool;
- (** captured variables handling (see before) *)
- pf_capture_policy : capture_policy;
- (** when calling a method with optional args, do we replace the missing args with "null" constants *)
- pf_pad_nulls : bool;
- (** add a final return to methods not having one already - prevent some compiler warnings *)
- pf_add_final_return : bool;
- (** does the platform natively support overloaded functions *)
- pf_overload : bool;
- (** can the platform use default values for non-nullable arguments *)
- pf_can_skip_non_nullable_argument : bool;
- (** type paths that are reserved on the platform *)
- pf_reserved_type_paths : path list;
- (** supports function == function **)
- pf_supports_function_equality : bool;
- (** uses utf16 encoding with ucs2 api **)
- pf_uses_utf16 : bool;
- (** target supports accessing `this` before calling `super(...)` **)
- pf_this_before_super : bool;
- (** target supports threads **)
- pf_supports_threads : bool;
- (** target supports Unicode **)
- pf_supports_unicode : bool;
- (** target supports rest arguments **)
- pf_supports_rest_args : bool;
- (** exceptions handling config **)
- pf_exceptions : exceptions_config;
- (** the scoping of local variables *)
- pf_scoping : var_scoping_config;
- (** target supports atomic operations via haxe.Atomic **)
- pf_supports_atomics : bool;
- }
- class compiler_callbacks = object(self)
- val before_typer_create = ref [];
- val after_init_macros = ref [];
- val mutable after_typing = [];
- val before_save = ref [];
- val after_save = ref [];
- val after_filters = ref [];
- val after_generation = ref [];
- val mutable null_safety_report = [];
- method add_before_typer_create (f : unit -> unit) : unit =
- before_typer_create := f :: !before_typer_create
- method add_after_init_macros (f : unit -> unit) : unit =
- after_init_macros := f :: !after_init_macros
- method add_after_typing (f : module_type list -> unit) : unit =
- after_typing <- f :: after_typing
- method add_before_save (f : unit -> unit) : unit =
- before_save := f :: !before_save
- method add_after_save (f : unit -> unit) : unit =
- after_save := f :: !after_save
- method add_after_filters (f : unit -> unit) : unit =
- after_filters := f :: !after_filters
- method add_after_generation (f : unit -> unit) : unit =
- after_generation := f :: !after_generation
- method add_null_safety_report (f : (string*pos) list -> unit) : unit =
- null_safety_report <- f :: null_safety_report
- method run handle_error r =
- match !r with
- | [] ->
- ()
- | l ->
- r := [];
- List.iter (fun f -> try f() with Error.Error err -> handle_error err) (List.rev l);
- self#run handle_error r
- method get_before_typer_create = before_typer_create
- method get_after_init_macros = after_init_macros
- method get_after_typing = after_typing
- method get_before_save = before_save
- method get_after_save = after_save
- method get_after_filters = after_filters
- method get_after_generation = after_generation
- method get_null_safety_report = null_safety_report
- end
- class file_keys = object(self)
- val cache = Hashtbl.create 0
- method get file =
- try
- Hashtbl.find cache file
- with Not_found ->
- let key = Path.UniqueKey.create file in
- Hashtbl.add cache file key;
- key
- end
- type shared_display_information = {
- mutable diagnostics_messages : diagnostic list;
- }
- type display_information = {
- mutable unresolved_identifiers : (string * pos * (string * CompletionItem.t * int) list) list;
- mutable display_module_has_macro_defines : bool;
- mutable module_diagnostics : DisplayTypes.module_diagnostics list;
- }
- (* This information is shared between normal and macro context. *)
- type shared_context = {
- shared_display_information : shared_display_information;
- }
- type json_api = {
- send_result : Json.t -> unit;
- send_error : Json.t list -> unit;
- jsonrpc : Jsonrpc_handler.jsonrpc_handler;
- }
- type compiler_stage =
- | CCreated (* Context was just created *)
- | CInitialized (* Context was initialized (from CLI args and such). *)
- | CInitMacrosStart (* Init macros are about to run. *)
- | CInitMacrosDone (* Init macros did run - at this point the signature is locked. *)
- | CTypingDone (* The typer is done - at this point com.types/modules/main is filled. *)
- | CFilteringStart (* Filtering just started (nothing changed yet). *)
- | CAnalyzerStart (* Some filters did run, the analyzer is about to run. *)
- | CAnalyzerDone (* The analyzer just finished. *)
- | CSaveStart (* The type state is about to be saved. *)
- | CSaveDone (* The type state has been saved - at this point we can destroy things. *)
- | CDceStart (* DCE is about to run - everything is still available. *)
- | CDceDone (* DCE just finished. *)
- | CFilteringDone (* Filtering just finished. *)
- | CGenerationStart (* Generation is about to begin. *)
- | CGenerationDone (* Generation just finished. *)
- let s_compiler_stage = function
- | CCreated -> "CCreated"
- | CInitialized -> "CInitialized"
- | CInitMacrosStart -> "CInitMacrosStart"
- | CInitMacrosDone -> "CInitMacrosDone"
- | CTypingDone -> "CTypingDone"
- | CFilteringStart -> "CFilteringStart"
- | CAnalyzerStart -> "CAnalyzerStart"
- | CAnalyzerDone -> "CAnalyzerDone"
- | CSaveStart -> "CSaveStart"
- | CSaveDone -> "CSaveDone"
- | CDceStart -> "CDceStart"
- | CDceDone -> "CDceDone"
- | CFilteringDone -> "CFilteringDone"
- | CGenerationStart -> "CGenerationStart"
- | CGenerationDone -> "CGenerationDone"
- type report_mode =
- | RMNone
- | RMLegacyDiagnostics of (Path.UniqueKey.t list)
- | RMDiagnostics of (Path.UniqueKey.t list)
- | RMStatistics
- class module_lut = object(self)
- inherit [path,module_def] hashtbl_lookup as super
- val type_lut : (path,path) lookup = new hashtbl_lookup
- method add_module_type (m : module_def) (mt : module_type) =
- let t = t_infos mt in
- try
- let path2 = type_lut#find t.mt_path in
- let p = t.mt_pos in
- if m.m_path <> path2 && String.lowercase_ascii (s_type_path path2) = String.lowercase_ascii (s_type_path m.m_path) then Error.raise_typing_error ("Module " ^ s_type_path path2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p;
- let m2 = self#find path2 in
- let hex1 = Digest.to_hex m.m_extra.m_sign in
- let hex2 = Digest.to_hex m2.m_extra.m_sign in
- let s = if hex1 = hex2 then hex1 else Printf.sprintf "was %s, is %s" hex2 hex1 in
- Error.raise_typing_error (Printf.sprintf "Type name %s is redefined from module %s (%s)" (s_type_path t.mt_path) (s_type_path path2) s) p
- with Not_found ->
- type_lut#add t.mt_path m.m_path
- method! add (path : path) (m : module_def) =
- super#add path m;
- List.iter (fun mt -> self#add_module_type m mt) m.m_types
- method! remove (path : path) =
- try
- List.iter (fun mt -> type_lut#remove (t_path mt)) (self#find path).m_types;
- super#remove path;
- with Not_found ->
- ()
- method find_by_type (path : path) =
- self#find (type_lut#find path)
- method! clear =
- super#clear;
- type_lut#clear
- method get_type_lut = type_lut
- end
- class virtual abstract_hxb_lib = object(self)
- method virtual load : unit
- method virtual get_bytes : string -> path -> bytes option
- method virtual close : unit
- method virtual get_file_path : string
- end
- type context_main = {
- mutable main_class : path option;
- mutable main_expr : texpr option;
- }
- type context = {
- compilation_step : int;
- mutable stage : compiler_stage;
- cs : CompilationCache.t;
- mutable cache : CompilationCache.context_cache option;
- is_macro_context : bool;
- mutable json_out : json_api option;
- (* config *)
- version : int;
- mutable args : string list;
- mutable display : DisplayTypes.DisplayMode.settings;
- mutable debug : bool;
- mutable verbose : bool;
- mutable foptimize : bool;
- mutable platform : platform;
- mutable config : platform_config;
- empty_class_path : ClassPath.class_path;
- class_paths : ClassPaths.class_paths;
- main : context_main;
- mutable package_rules : (string,package_rule) PMap.t;
- mutable report_mode : report_mode;
- (* communication *)
- mutable print : string -> unit;
- mutable error : ?depth:int -> string -> pos -> unit;
- mutable error_ext : Error.error -> unit;
- mutable info : ?depth:int -> ?from_macro:bool -> string -> pos -> unit;
- mutable warning : ?depth:int -> ?from_macro:bool -> warning -> Warning.warning_option list list -> string -> pos -> unit;
- mutable warning_options : Warning.warning_option list list;
- mutable get_messages : unit -> compiler_message list;
- mutable filter_messages : (compiler_message -> bool) -> unit;
- mutable run_command : string -> int;
- mutable run_command_args : string -> string list -> int;
- (* typing setup *)
- mutable load_extern_type : (string * (path -> pos -> Ast.package option)) list; (* allow finding types which are not in sources *)
- callbacks : compiler_callbacks;
- defines : Define.define;
- mutable user_defines : (string, Define.user_define) Hashtbl.t;
- mutable user_metas : (string, Meta.user_meta) Hashtbl.t;
- mutable get_macros : unit -> context option;
- (* typing state *)
- mutable std : tclass;
- mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
- shared : shared_context;
- display_information : display_information;
- file_keys : file_keys;
- mutable file_contents : (Path.UniqueKey.t * string option) list;
- parser_cache : (string,(type_def * pos) list) lookup;
- module_to_file : (path,ClassPaths.resolved_file) lookup;
- cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) lookup;
- stored_typed_exprs : (int, texpr) lookup;
- overload_cache : ((path * string),(Type.t * tclass_field) list) lookup;
- module_lut : module_lut;
- module_nonexistent_lut : (path,bool) lookup;
- fake_modules : (Path.UniqueKey.t,module_def) Hashtbl.t;
- mutable has_error : bool;
- pass_debug_messages : string DynArray.t;
- (* output *)
- mutable file : string;
- mutable features : (string,bool) Hashtbl.t;
- mutable modules : Type.module_def list;
- mutable types : Type.module_type list;
- mutable resources : (string,string) Hashtbl.t;
- functional_interface_lut : (path,(tclass * tclass_field)) lookup;
- (* target-specific *)
- mutable flash_version : float;
- mutable neko_lib_paths : string list;
- mutable include_files : (string * string) list;
- mutable native_libs : native_libraries;
- mutable hxb_libs : abstract_hxb_lib list;
- mutable net_std : string list;
- net_path_map : (path,string list * string list * string) Hashtbl.t;
- mutable js_gen : (unit -> unit) option;
- (* misc *)
- mutable basic : basic_types;
- memory_marker : float array;
- mutable hxb_reader_api : HxbReaderApi.hxb_reader_api option;
- hxb_reader_stats : HxbReader.hxb_reader_stats;
- mutable hxb_writer_config : HxbWriterConfig.t option;
- }
- let enter_stage com stage =
- (* print_endline (Printf.sprintf "Entering stage %s" (s_compiler_stage stage)); *)
- com.stage <- stage
- let ignore_error com =
- let b = com.display.dms_error_policy = EPIgnore in
- if b then com.has_error <- true;
- b
- let module_warning com m w options msg p =
- DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,msg,p));
- com.warning w options msg p
- (* Defines *)
- module Define = Define
- let defined com s =
- Define.defined com.defines s
- let raw_defined com v =
- Define.raw_defined com.defines v
- let defined_value com v =
- Define.defined_value com.defines v
- let defined_value_safe ?default com v =
- match default with
- | Some s -> Define.defined_value_safe ~default:s com.defines v
- | None -> Define.defined_value_safe com.defines v
- let define com v =
- Define.define com.defines v
- let raw_define com v =
- Define.raw_define com.defines v
- let define_value com k v =
- Define.define_value com.defines k v
- let convert_define k =
- String.concat "_" (ExtString.String.nsplit k "-")
- let is_next com = defined com HaxeNext
- let external_defined ctx k =
- Define.raw_defined ctx.defines (convert_define k)
- let external_defined_value ctx k =
- Define.raw_defined_value ctx.defines (convert_define k)
- let reserved_flags = [
- "true";"false";"null";"cross";"js";"lua";"neko";"flash";"php";"cpp";"java";"jvm";"python";"hl";"hlc";
- "swc";"macro";"sys";"static";"utf16";"haxe";"haxe_ver"
- ]
- let reserved_flag_namespaces = ["target"]
- let convert_and_validate k =
- let converted_flag = convert_define k in
- let raise_reserved description =
- raise (Arg.Bad (description ^ " and cannot be defined from the command line"))
- in
- if List.mem converted_flag reserved_flags then
- raise_reserved (Printf.sprintf "`%s` is a reserved compiler flag" k);
- List.iter (fun ns ->
- if ExtString.String.starts_with converted_flag (ns ^ ".") then
- raise_reserved (Printf.sprintf "`%s` uses the reserved compiler flag namespace `%s.*`" k ns)
- ) reserved_flag_namespaces;
- converted_flag
- let external_define_value ctx k v =
- raw_define_value ctx.defines (convert_and_validate k) v
- let external_define ctx k =
- Define.raw_define ctx.defines (convert_and_validate k)
- let external_undefine ctx k =
- Define.raw_undefine ctx.defines (convert_and_validate k)
- let defines_for_external ctx =
- PMap.foldi (fun k v acc ->
- let added_underscore = PMap.add k v acc in
- match ExtString.String.nsplit k "_" with
- | [_] -> added_underscore
- | split -> PMap.add (String.concat "-" split) v added_underscore;
- ) ctx.defines.values PMap.empty
- let get_es_version com =
- try int_of_string (defined_value com Define.JsEs) with _ -> 0
- let short_platform_name = function
- | Cross -> "x"
- | Js -> "js"
- | Lua -> "lua"
- | Neko -> "n"
- | Flash -> "swf"
- | Php -> "php"
- | Cpp -> "cpp"
- | Jvm -> "jvm"
- | Python -> "py"
- | Hl -> "hl"
- | Eval -> "evl"
- | CustomTarget n -> "c_" ^ n
- let stats =
- {
- s_files_parsed = ref 0;
- s_classes_built = ref 0;
- s_methods_typed = ref 0;
- s_macros_called = ref 0;
- }
- let default_config =
- {
- pf_static = true;
- pf_sys = true;
- pf_capture_policy = CPNone;
- pf_pad_nulls = false;
- pf_add_final_return = false;
- pf_overload = false;
- pf_can_skip_non_nullable_argument = true;
- pf_reserved_type_paths = [];
- pf_supports_function_equality = true;
- pf_uses_utf16 = true;
- pf_this_before_super = true;
- pf_supports_threads = false;
- pf_supports_unicode = true;
- pf_supports_rest_args = false;
- pf_exceptions = {
- ec_native_throws = [];
- ec_native_catches = [];
- ec_wildcard_catch = (["StdTypes"],"Dynamic");
- ec_base_throw = (["StdTypes"],"Dynamic");
- ec_avoid_wrapping = true;
- ec_special_throw = fun _ -> false;
- };
- pf_scoping = {
- vs_scope = BlockScope;
- vs_flags = [];
- };
- pf_supports_atomics = false;
- }
- let get_config com =
- let defined f = PMap.mem (Define.get_define_key f) com.defines.values in
- match com.platform with
- | Cross ->
- default_config
- | CustomTarget _ ->
- (* impossible to reach. see update_platform_config *)
- raise Exit
- | Js ->
- let es6 = get_es_version com >= 6 in
- {
- default_config with
- pf_static = false;
- pf_sys = false;
- pf_capture_policy = if es6 then CPNone else CPLoopVars;
- pf_reserved_type_paths = [([],"Object");([],"Error")];
- pf_this_before_super = not es6; (* cannot access `this` before `super()` when generating ES6 classes *)
- pf_supports_rest_args = true;
- pf_exceptions = { default_config.pf_exceptions with
- ec_native_throws = [
- ["js";"lib"],"Error";
- ["haxe"],"Exception";
- ];
- ec_avoid_wrapping = false;
- };
- pf_scoping = {
- vs_scope = if es6 then BlockScope else FunctionScope;
- vs_flags =
- (if defined Define.JsUnflatten then ReserveAllTopLevelSymbols else ReserveAllTypesFlat)
- :: if es6 then [NoShadowing; SwitchCasesNoBlocks;] else [VarHoisting; NoCatchVarShadowing];
- };
- pf_supports_atomics = true;
- }
- | Lua ->
- {
- default_config with
- pf_static = false;
- pf_capture_policy = CPLoopVars;
- pf_uses_utf16 = false;
- pf_supports_rest_args = true;
- pf_exceptions = { default_config.pf_exceptions with
- ec_avoid_wrapping = false;
- }
- }
- | Neko ->
- {
- default_config with
- pf_static = false;
- pf_pad_nulls = true;
- pf_uses_utf16 = false;
- pf_supports_threads = true;
- pf_supports_unicode = false;
- pf_scoping = { default_config.pf_scoping with
- vs_flags = [ReserveAllTopLevelSymbols];
- }
- }
- | Flash ->
- {
- default_config with
- pf_sys = false;
- pf_capture_policy = CPLoopVars;
- pf_can_skip_non_nullable_argument = false;
- pf_reserved_type_paths = [([],"Object");([],"Error")];
- pf_supports_rest_args = true;
- pf_exceptions = { default_config.pf_exceptions with
- ec_native_throws = [
- ["flash";"errors"],"Error";
- ["haxe"],"Exception";
- ];
- ec_native_catches = [
- ["flash";"errors"],"Error";
- ["haxe"],"Exception";
- ];
- ec_avoid_wrapping = false;
- };
- pf_scoping = {
- vs_scope = FunctionScope;
- vs_flags = [VarHoisting];
- };
- }
- | Php ->
- {
- default_config with
- pf_static = false;
- pf_uses_utf16 = false;
- pf_supports_rest_args = true;
- pf_exceptions = { default_config.pf_exceptions with
- ec_native_throws = [
- ["php"],"Throwable";
- ["haxe"],"Exception";
- ];
- ec_native_catches = [
- ["php"],"Throwable";
- ["haxe"],"Exception";
- ];
- ec_wildcard_catch = (["php"],"Throwable");
- ec_base_throw = (["php"],"Throwable");
- };
- pf_scoping = {
- vs_scope = FunctionScope;
- vs_flags = [VarHoisting]
- }
- }
- | Cpp ->
- {
- default_config with
- pf_capture_policy = CPWrapRef;
- pf_pad_nulls = true;
- pf_add_final_return = true;
- pf_supports_threads = true;
- pf_supports_unicode = (defined Define.Cppia) || not (defined Define.DisableUnicodeStrings);
- pf_scoping = { default_config.pf_scoping with
- vs_flags = [NoShadowing];
- vs_scope = FunctionScope;
- };
- pf_supports_atomics = true;
- }
- | Jvm ->
- {
- default_config with
- pf_capture_policy = CPWrapRef;
- pf_pad_nulls = true;
- pf_overload = true;
- pf_supports_threads = true;
- pf_supports_rest_args = true;
- pf_this_before_super = false;
- pf_exceptions = { default_config.pf_exceptions with
- ec_native_throws = [
- ["java";"lang"],"RuntimeException";
- ["haxe"],"Exception";
- ];
- ec_native_catches = [
- ["java";"lang"],"Throwable";
- ["haxe"],"Exception";
- ];
- ec_wildcard_catch = (["java";"lang"],"Throwable");
- ec_base_throw = (["java";"lang"],"RuntimeException");
- };
- pf_supports_atomics = true;
- }
- | Python ->
- {
- default_config with
- pf_static = false;
- pf_capture_policy = CPLoopVars;
- pf_uses_utf16 = false;
- pf_supports_threads = true;
- pf_supports_rest_args = true;
- pf_exceptions = { default_config.pf_exceptions with
- ec_native_throws = [
- ["python";"Exceptions"],"BaseException";
- ];
- ec_native_catches = [
- ["python";"Exceptions"],"BaseException";
- ];
- ec_wildcard_catch = ["python";"Exceptions"],"BaseException";
- ec_base_throw = ["python";"Exceptions"],"BaseException";
- };
- pf_scoping = {
- vs_scope = FunctionScope;
- vs_flags = [VarHoisting]
- };
- }
- | Hl ->
- {
- default_config with
- pf_capture_policy = CPWrapRef;
- pf_pad_nulls = true;
- pf_supports_threads = true;
- pf_supports_atomics = true;
- pf_scoping = {
- vs_scope = BlockScope;
- vs_flags = [NoShadowing]
- };
- }
- | Eval ->
- {
- default_config with
- pf_static = false;
- pf_pad_nulls = true;
- pf_uses_utf16 = false;
- pf_supports_threads = true;
- pf_capture_policy = CPWrapRef;
- }
- let memory_marker = [|Unix.time()|]
- let create compilation_step cs version args display_mode =
- let rec com = {
- compilation_step = compilation_step;
- cs = cs;
- cache = None;
- stage = CCreated;
- version = version;
- args = args;
- shared = {
- shared_display_information = {
- diagnostics_messages = [];
- }
- };
- display_information = {
- unresolved_identifiers = [];
- display_module_has_macro_defines = false;
- module_diagnostics = [];
- };
- debug = false;
- display = display_mode;
- verbose = false;
- foptimize = true;
- features = Hashtbl.create 0;
- platform = Cross;
- config = default_config;
- print = (fun s -> print_string s; flush stdout);
- run_command = Sys.command;
- run_command_args = (fun s args -> com.run_command (Printf.sprintf "%s %s" s (String.concat " " args)));
- empty_class_path = new ClassPath.directory_class_path "" User;
- class_paths = new ClassPaths.class_paths;
- main = {
- main_class = None;
- main_expr = None;
- };
- package_rules = PMap.empty;
- file = "";
- types = [];
- callbacks = new compiler_callbacks;
- global_metadata = [];
- modules = [];
- module_lut = new module_lut;
- module_nonexistent_lut = new hashtbl_lookup;
- fake_modules = Hashtbl.create 0;
- flash_version = 10.;
- resources = Hashtbl.create 0;
- net_std = [];
- native_libs = create_native_libs();
- hxb_libs = [];
- net_path_map = Hashtbl.create 0;
- neko_lib_paths = [];
- include_files = [];
- js_gen = None;
- load_extern_type = [];
- defines = {
- defines_signature = None;
- values = PMap.empty;
- };
- user_defines = Hashtbl.create 0;
- user_metas = Hashtbl.create 0;
- get_macros = (fun() -> None);
- info = (fun ?depth ?from_macro _ _ -> die "" __LOC__);
- warning = (fun ?depth ?from_macro _ _ _ -> die "" __LOC__);
- warning_options = [];
- error = (fun ?depth _ _ -> die "" __LOC__);
- error_ext = (fun _ -> die "" __LOC__);
- get_messages = (fun() -> []);
- filter_messages = (fun _ -> ());
- pass_debug_messages = DynArray.create();
- basic = {
- tvoid = mk_mono();
- tint = mk_mono();
- tfloat = mk_mono();
- tbool = mk_mono();
- tstring = mk_mono();
- tcoro_control = mk_mono();
- tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
- tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
- tcoro = (fun _ -> die "Could not locate abstract Coroutine<T> (was it redefined?)" __LOC__);
- };
- std = null_class;
- file_keys = new file_keys;
- file_contents = [];
- module_to_file = new hashtbl_lookup;
- stored_typed_exprs = new hashtbl_lookup;
- cached_macros = new hashtbl_lookup;
- memory_marker = memory_marker;
- parser_cache = new hashtbl_lookup;
- overload_cache = new hashtbl_lookup;
- json_out = None;
- has_error = false;
- report_mode = RMNone;
- is_macro_context = false;
- functional_interface_lut = new Lookup.hashtbl_lookup;
- hxb_reader_api = None;
- hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
- hxb_writer_config = None;
- } in
- com
- let is_diagnostics com = match com.report_mode with
- | RMLegacyDiagnostics _ | RMDiagnostics _ -> true
- | _ -> false
- let is_compilation com = com.display.dms_kind = DMNone && not (is_diagnostics com)
- let disable_report_mode com =
- let old = com.report_mode in
- com.report_mode <- RMNone;
- (fun () -> com.report_mode <- old)
- let log com str =
- if com.verbose then com.print (str ^ "\n")
- let clone com is_macro_context =
- let t = com.basic in
- { com with
- cache = None;
- basic = { t with
- tvoid = mk_mono();
- tint = mk_mono();
- tfloat = mk_mono();
- tbool = mk_mono();
- tstring = mk_mono();
- tcoro_control = mk_mono();
- };
- main = {
- main_class = None;
- main_expr = None;
- };
- features = Hashtbl.create 0;
- callbacks = new compiler_callbacks;
- display_information = {
- unresolved_identifiers = [];
- display_module_has_macro_defines = false;
- module_diagnostics = [];
- };
- defines = {
- values = com.defines.values;
- defines_signature = com.defines.defines_signature;
- };
- native_libs = create_native_libs();
- is_macro_context = is_macro_context;
- parser_cache = new hashtbl_lookup;
- module_to_file = new hashtbl_lookup;
- overload_cache = new hashtbl_lookup;
- module_lut = new module_lut;
- fake_modules = Hashtbl.create 0;
- hxb_reader_api = None;
- hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
- std = null_class;
- functional_interface_lut = new Lookup.hashtbl_lookup;
- empty_class_path = new ClassPath.directory_class_path "" User;
- class_paths = new ClassPaths.class_paths;
- }
- let file_time file = Extc.filetime file
- let flash_versions = List.map (fun v ->
- let maj = int_of_float v in
- let min = int_of_float (mod_float (v *. 10.) 10.) in
- v, string_of_int maj ^ (if min = 0 then "" else "_" ^ string_of_int min)
- ) [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;11.9;12.0;13.0;14.0;15.0;16.0;17.0;18.0;19.0;20.0;21.0;22.0;23.0;24.0;25.0;26.0;27.0;28.0;29.0;31.0;32.0]
- let flash_version_tag = function
- | 6. -> 6
- | 7. -> 7
- | 8. -> 8
- | 9. -> 9
- | 10. | 10.1 -> 10
- | 10.2 -> 11
- | 10.3 -> 12
- | 11. -> 13
- | 11.1 -> 14
- | 11.2 -> 15
- | 11.3 -> 16
- | 11.4 -> 17
- | 11.5 -> 18
- | 11.6 -> 19
- | 11.7 -> 20
- | 11.8 -> 21
- | 11.9 -> 22
- | v when v >= 12.0 && float_of_int (int_of_float v) = v -> int_of_float v + 11
- | v -> failwith ("Invalid SWF version " ^ string_of_float v)
- let update_platform_config com =
- match com.platform with
- | CustomTarget _ ->
- () (* do nothing, configured with macro api *)
- | _ ->
- com.config <- get_config com
- let init_platform com =
- let name = platform_name com.platform in
- begin match com.platform with
- | Flash when Path.file_extension com.file = "swc" ->
- define com Define.Swc
- | Jvm ->
- raw_define com "java"
- | Hl ->
- if Path.file_extension com.file = "c" then define com Define.Hlc;
- | _ ->
- ()
- end;
- (* Set the source header, unless the user has set one already or the platform sets a custom one *)
- if not (defined com Define.SourceHeader) && (com.platform <> Hl) then
- define_value com Define.SourceHeader ("Generated by Haxe " ^ s_version_full);
- let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
- com.package_rules <- List.fold_left forbid com.package_rules ("java" :: (List.map platform_name platforms));
- update_platform_config com;
- if com.config.pf_static then begin
- raw_define com "target.static";
- define com Define.Static;
- end;
- if com.config.pf_sys then begin
- raw_define com "target.sys";
- define com Define.Sys
- end else
- com.package_rules <- PMap.add "sys" Forbidden com.package_rules;
- if com.config.pf_uses_utf16 then begin
- raw_define com "target.utf16";
- define com Define.Utf16;
- end;
- if com.config.pf_supports_threads then begin
- raw_define com "target.threaded";
- end;
- if com.config.pf_supports_unicode then begin
- raw_define com "target.unicode";
- end;
- raw_define_value com.defines "target.name" name;
- raw_define com (match com.platform with | CustomTarget _ -> "custom_target" | _ -> name);
- if com.config.pf_supports_atomics then begin
- raw_define com "target.atomics"
- end
- let set_platform com pf file =
- if com.platform <> Cross then failwith "Multiple targets";
- com.platform <- pf;
- com.file <- file
- let set_custom_target com name path =
- if List.find_opt (fun pf -> (platform_name pf) = name) platforms <> None then
- raise (Arg.Bad (Printf.sprintf "--custom-target cannot use reserved name %s" name));
- if String.length name > max_custom_target_len then
- raise (Arg.Bad (Printf.sprintf "--custom-target name %s exceeds the maximum of %d characters" name max_custom_target_len));
- let name_regexp = Str.regexp "^[a-zA-Z0-9\\_]+$" in
- if Str.string_match name_regexp name 0 then
- set_platform com (CustomTarget name) path
- else
- raise (Arg.Bad (Printf.sprintf "--custom-target name %s may only contain alphanumeric or underscore characters" name))
- let add_feature com f =
- Hashtbl.replace com.features f true
- let has_dce com =
- (try defined_value com Define.Dce <> "no" with Not_found -> false)
- (*
- TODO: The has_dce check is there because we mark types with @:directlyUsed in the DCE filter,
- which is not run in dce=no and thus we can't know if a type is used directly or not,
- so we just assume that they are.
- If we had dce filter always running (even with dce=no), we would have types marked with @:directlyUsed
- and we wouldn't need to generate unnecessary imports in dce=no, but that's good enough for now.
- *)
- let is_directly_used com meta =
- not (has_dce com) || Meta.has Meta.DirectlyUsed meta
- let rec has_feature com f =
- try
- Hashtbl.find com.features f
- with Not_found ->
- if com.types = [] then not (has_dce com) else
- match List.rev (ExtString.String.nsplit f ".") with
- | [] -> die "" __LOC__
- | [cl] -> has_feature com (cl ^ ".*")
- | field :: cl :: pack ->
- let r = (try
- let path = List.rev pack, cl in
- (match List.find (fun t -> t_path t = path && not (Meta.has Meta.RealPath (t_infos t).mt_meta)) com.types with
- | t when field = "*" ->
- not (has_dce com) ||
- begin match t with
- | TClassDecl c ->
- has_class_flag c CUsed;
- | TAbstractDecl a ->
- Meta.has Meta.ValueUsed a.a_meta
- | _ -> Meta.has Meta.Used (t_infos t).mt_meta
- end;
- | TClassDecl c when (has_class_flag c CExtern) && (com.platform <> Js || cl <> "Array" && cl <> "Math") ->
- not (has_dce com) || has_class_field_flag (try PMap.find field c.cl_statics with Not_found -> PMap.find field c.cl_fields) CfUsed
- | TClassDecl c ->
- PMap.exists field c.cl_statics || PMap.exists field c.cl_fields
- | _ ->
- false)
- with Not_found ->
- false
- ) in
- Hashtbl.add com.features f r;
- r
- let allow_package ctx s =
- try
- if (PMap.find s ctx.package_rules) = Forbidden then ctx.package_rules <- PMap.remove s ctx.package_rules
- with Not_found ->
- ()
- let platform ctx p = ctx.platform = p
- let platform_name_macro com =
- if defined com Define.Macro then "macro"
- else platform_name com.platform
- let find_file ctx f =
- (ctx.class_paths#find_file f).file
- (* let find_file ctx f =
- let timer = Timer.timer ["find_file"] in
- Std.finally timer (find_file ctx) f *)
- let mem_size v =
- Objsize.size_with_headers (Objsize.objsize v [] [])
- let hash f =
- let h = ref 0 in
- for i = 0 to String.length f - 1 do
- h := !h * 223 + int_of_char (String.unsafe_get f i);
- done;
- if Sys.word_size = 64 then Int32.to_int (Int32.shift_right (Int32.shift_left (Int32.of_int !h) 1) 1) else !h
- let url_encode s add_char =
- let hex = "0123456789ABCDEF" in
- for i = 0 to String.length s - 1 do
- let c = String.unsafe_get s i in
- match c with
- | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' ->
- add_char c
- | _ ->
- add_char '%';
- add_char (String.unsafe_get hex (int_of_char c lsr 4));
- add_char (String.unsafe_get hex (int_of_char c land 0xF));
- done
- let url_encode_s s =
- let b = Buffer.create 0 in
- url_encode s (Buffer.add_char b);
- Buffer.contents b
- (* UTF8 *)
- let to_utf8 str p =
- let u8 = try
- UTF8.validate str;
- str;
- with
- UTF8.Malformed_code ->
- (* ISO to utf8 *)
- let b = UTF8.Buf.create 0 in
- String.iter (fun c -> UTF8.Buf.add_char b (UCharExt.of_char c)) str;
- UTF8.Buf.contents b
- in
- let ccount = ref 0 in
- UTF8.iter (fun c ->
- let c = UCharExt.code c in
- if (c >= 0xD800 && c <= 0xDFFF) || c >= 0x110000 then Error.abort "Invalid unicode char" p;
- incr ccount;
- if c > 0x10000 then incr ccount;
- ) u8;
- u8, !ccount
- let utf16_add buf c =
- let add c =
- Buffer.add_char buf (char_of_int (c land 0xFF));
- Buffer.add_char buf (char_of_int (c lsr 8));
- in
- if c >= 0 && c < 0x10000 then begin
- if c >= 0xD800 && c <= 0xDFFF then failwith ("Invalid unicode char " ^ string_of_int c);
- add c;
- end else if c < 0x110000 then begin
- let c = c - 0x10000 in
- add ((c asr 10) + 0xD800);
- add ((c land 1023) + 0xDC00);
- end else
- failwith ("Invalid unicode char " ^ string_of_int c)
- let utf8_to_utf16 str zt =
- let b = Buffer.create (String.length str * 2) in
- (try UTF8.iter (fun c -> utf16_add b (UCharExt.code c)) str with Invalid_argument _ | UCharExt.Out_of_range -> ()); (* if malformed *)
- if zt then utf16_add b 0;
- Buffer.contents b
- let utf16_to_utf8 str =
- let b = Buffer.create 0 in
- let add c = Buffer.add_char b (char_of_int (c land 0xFF)) in
- let get i = int_of_char (String.unsafe_get str i) in
- let rec loop i =
- if i >= String.length str then ()
- else begin
- let c = get i in
- if c < 0x80 then begin
- add c;
- loop (i + 2);
- end else if c < 0x800 then begin
- let c = c lor ((get (i + 1)) lsl 8) in
- add c;
- add (c lsr 8);
- loop (i + 2);
- end else
- die "" __LOC__;
- end
- in
- loop 0;
- Buffer.contents b
- let add_diagnostics_message ?(depth = 0) ?(code = None) com s p kind sev =
- if sev = MessageSeverity.Error then com.has_error <- true;
- let di = com.shared.shared_display_information in
- di.diagnostics_messages <- (make_diagnostic ~depth ~code s p kind sev) :: di.diagnostics_messages
- let display_error_ext com err =
- if is_diagnostics com then begin
- Error.recurse_error (fun depth err ->
- add_diagnostics_message ~depth com (Error.error_msg err.err_message) err.err_pos MessageKind.DKCompilerMessage MessageSeverity.Error;
- ) err;
- end else
- com.error_ext err
- let display_error com ?(depth = 0) msg p =
- display_error_ext com (Error.make_error ~depth (Custom msg) p)
- let dump_path com =
- Define.defined_value_safe ~default:"dump" com.defines Define.DumpPath
- let adapt_defines_to_macro_context defines =
- let to_remove = "java" :: List.map Globals.platform_name Globals.platforms in
- let to_remove = List.fold_left (fun acc d -> Define.get_define_key d :: acc) to_remove [Define.NoTraces] in
- let to_remove = List.fold_left (fun acc (_, d) -> ("flash" ^ d) :: acc) to_remove flash_versions in
- let macro_defines = {
- values = PMap.foldi (fun k v acc ->
- if List.mem k to_remove then acc else PMap.add k v acc) defines.values PMap.empty;
- defines_signature = None
- } in
- Define.define macro_defines Define.Macro;
- Define.raw_define macro_defines (platform_name Eval);
- macro_defines
- let adapt_defines_to_display_context defines =
- let defines = adapt_defines_to_macro_context defines in
- Define.define defines Define.Display;
- defines
- let is_legacy_completion com = match com.json_out with
- | None -> true
- | Some api -> !ServerConfig.legacy_completion
- let get_entry_point com =
- Option.map (fun path ->
- let m = List.find (fun m -> m.m_path = path) com.modules in
- let c =
- match m.m_statics with
- | Some c when (PMap.mem "main" c.cl_statics) -> c
- | _ -> Option.get (ExtList.List.find_map (fun t -> match t with TClassDecl c when c.cl_path = path -> Some c | _ -> None) m.m_types)
- in
- let e = Option.get com.main.main_expr in (* must be present at this point *)
- (snd path, c, e)
- ) com.main.main_class
- let expand_coro_type basic args ret =
- let ret_type = if ExtType.is_void (follow ret) then t_dynamic else ret in
- let tcontinuation = tfun [ret_type; t_dynamic] basic.tvoid in
- let args = args @ [("_hx_continuation",false,tcontinuation)] in
- let ret = tfun [t_dynamic; basic.tcoro_control] basic.tvoid in
- (args,ret)
|