forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			580 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			580 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C)2005-2019 Haxe Foundation
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice shall be included in
 | 
						|
 * all copies or substantial portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
 * DEALINGS IN THE SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
package haxe.macro;
 | 
						|
 | 
						|
import haxe.macro.Expr;
 | 
						|
 | 
						|
/**
 | 
						|
	All these methods can be called for compiler configuration macros.
 | 
						|
**/
 | 
						|
#if hl
 | 
						|
@:hlNative("macro")
 | 
						|
#end
 | 
						|
class Compiler {
 | 
						|
	/**
 | 
						|
		A conditional compilation flag can be set on the command line using
 | 
						|
		`-D key=value`.
 | 
						|
 | 
						|
		Returns the value of a compiler flag.
 | 
						|
 | 
						|
		If the compiler flag is defined but no value is set,
 | 
						|
		`Compiler.getDefine` returns `"1"` (e.g. `-D key`).
 | 
						|
 | 
						|
		If the compiler flag is not defined, `Compiler.getDefine` returns
 | 
						|
		`null`.
 | 
						|
 | 
						|
		Note: This is a macro and cannot be called from within other macros. Refer
 | 
						|
		to `haxe.macro.Context.definedValue` to obtain defined values in macro context.
 | 
						|
 | 
						|
		@see https://haxe.org/manual/lf-condition-compilation.html
 | 
						|
	**/
 | 
						|
	macro /* <-- ! */ static public function getDefine(key:String) {
 | 
						|
		return macro $v{haxe.macro.Context.definedValue(key)};
 | 
						|
	}
 | 
						|
 | 
						|
	#if (neko || (macro && hl) || (macro && eval))
 | 
						|
	static var ident = ~/^[A-Za-z_][A-Za-z0-9_]*$/;
 | 
						|
	static var path = ~/^[A-Za-z_][A-Za-z0-9_.]*$/;
 | 
						|
 | 
						|
	public static function allowPackage(v:String) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("allow_package", 1)(v);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Set a conditional compiler flag.
 | 
						|
 | 
						|
		Usage of this function outside of initialization macros is deprecated and may cause compilation server issues.
 | 
						|
	**/
 | 
						|
	public static function define(flag:String, ?value:String) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("define", 2)(flag, value);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	#if (!neko && !eval)
 | 
						|
	private static function typePatch(cl:String, f:String, stat:Bool, t:String) {}
 | 
						|
 | 
						|
	private static function metaPatch(meta:String, cl:String, f:String, stat:Bool) {}
 | 
						|
 | 
						|
	private static function addGlobalMetadataImpl(pathFilter:String, meta:String, recursive:Bool, toTypes:Bool, toFields:Bool) {}
 | 
						|
	#end
 | 
						|
 | 
						|
	/**
 | 
						|
		Removes a (static) field from a given class by name.
 | 
						|
		An error is thrown when `className` or `field` is invalid.
 | 
						|
	**/
 | 
						|
	public static function removeField(className:String, field:String, ?isStatic:Bool) {
 | 
						|
		if (!path.match(className))
 | 
						|
			throw "Invalid " + className;
 | 
						|
		if (!ident.match(field))
 | 
						|
			throw "Invalid " + field;
 | 
						|
		#if (neko || eval)
 | 
						|
		load("type_patch", 4)(className, field, isStatic == true, null);
 | 
						|
		#else
 | 
						|
		typePatch(className, field, isStatic == true, null);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Set the type of a (static) field at a given class by name.
 | 
						|
		An error is thrown when `className` or `field` is invalid.
 | 
						|
	**/
 | 
						|
	public static function setFieldType(className:String, field:String, type:String, ?isStatic:Bool) {
 | 
						|
		if (!path.match(className))
 | 
						|
			throw "Invalid " + className;
 | 
						|
		if (!ident.match((field.charAt(0) == "$") ? field.substr(1) : field))
 | 
						|
			throw "Invalid " + field;
 | 
						|
		#if (neko || eval)
 | 
						|
		load("type_patch", 4)(className, field, isStatic == true, type);
 | 
						|
		#else
 | 
						|
		typePatch(className, field, isStatic == true, type);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Add metadata to a (static) field or class by name.
 | 
						|
		An error is thrown when `className` or `field` is invalid.
 | 
						|
	**/
 | 
						|
	public static function addMetadata(meta:String, className:String, ?field:String, ?isStatic:Bool) {
 | 
						|
		if (!path.match(className))
 | 
						|
			throw "Invalid " + className;
 | 
						|
		if (field != null && !ident.match(field))
 | 
						|
			throw "Invalid " + field;
 | 
						|
		#if (neko || eval)
 | 
						|
		load("meta_patch", 4)(meta, className, field, isStatic == true);
 | 
						|
		#else
 | 
						|
		metaPatch(meta, className, field, isStatic == true);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Add a class path where ".hx" source files or packages (sub-directories) can be found.
 | 
						|
 | 
						|
		Usage of this function outside of initialization macros is deprecated and may cause compilation server issues.
 | 
						|
	**/
 | 
						|
	public static function addClassPath(path:String) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("add_class_path", 1)(path);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getOutput():String {
 | 
						|
		#if (neko || eval)
 | 
						|
		return load("get_output", 0)();
 | 
						|
		#else
 | 
						|
		return null;
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	public static function setOutput(fileOrDir:String) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("set_output", 1)(fileOrDir);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getDisplayPos():Null<{file:String, pos:Int}> {
 | 
						|
		#if (neko || eval)
 | 
						|
		return load("get_display_pos", 0)();
 | 
						|
		#else
 | 
						|
		return null;
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Adds a native library depending on the platform (e.g. `-swf-lib` for Flash).
 | 
						|
 | 
						|
		Usage of this function outside of initialization macros is deprecated and may cause compilation server issues.
 | 
						|
	**/
 | 
						|
	public static function addNativeLib(name:String) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("add_native_lib", 1)(name);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Adds an argument to be passed to the native compiler (e.g. `-javac-arg` for Java).
 | 
						|
	**/
 | 
						|
	public static function addNativeArg(argument:String) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("add_native_arg", 1)(argument);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Includes all modules in package `pack` in the compilation.
 | 
						|
 | 
						|
		In order to include single modules, their paths can be listed directly
 | 
						|
		on command line: `haxe ... ModuleName pack.ModuleName`.
 | 
						|
 | 
						|
		By default `Compiler.include` will search for modules in the directories defined with `-cp`.
 | 
						|
		If you want to specify a different set of paths to search for modules, you can use the optional
 | 
						|
		argument `classPath`.
 | 
						|
 | 
						|
		@param pack The package dot-path as String. Use `''` to include the root package.
 | 
						|
		@param rec If true, recursively adds all sub-packages.
 | 
						|
		@param ignore Array of module names to ignore for inclusion.
 | 
						|
			   You can use `module*` with a * at the end for Wildcard matching
 | 
						|
		@param classPaths An alternative array of paths (directory names) to use to search for modules to include.
 | 
						|
			   Note that if you pass this argument, only the specified paths will be used for inclusion.
 | 
						|
		@param strict If true and given package wasn't found in any of class paths, fail with an error.
 | 
						|
	**/
 | 
						|
	public static function include(pack:String, ?rec = true, ?ignore:Array<String>, ?classPaths:Array<String>, strict = false) {
 | 
						|
		var ignoreWildcard:Array<String> = [];
 | 
						|
		var ignoreString:Array<String> = [];
 | 
						|
		if (ignore != null) {
 | 
						|
			for (ignoreRule in ignore) {
 | 
						|
				if (StringTools.endsWith(ignoreRule, "*")) {
 | 
						|
					ignoreWildcard.push(ignoreRule.substr(0, ignoreRule.length - 1));
 | 
						|
				} else {
 | 
						|
					ignoreString.push(ignoreRule);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		var skip = if (ignore == null) {
 | 
						|
			function(c) return false;
 | 
						|
		} else {
 | 
						|
			function(c:String) {
 | 
						|
				if (Lambda.has(ignoreString, c))
 | 
						|
					return true;
 | 
						|
				for (ignoreRule in ignoreWildcard)
 | 
						|
					if (StringTools.startsWith(c, ignoreRule))
 | 
						|
						return true;
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		var displayValue = Context.definedValue("display");
 | 
						|
		if (classPaths == null) {
 | 
						|
			classPaths = Context.getClassPath();
 | 
						|
			// do not force inclusion when using completion
 | 
						|
			switch (displayValue) {
 | 
						|
				case null:
 | 
						|
				case "usage":
 | 
						|
				case _:
 | 
						|
					return;
 | 
						|
			}
 | 
						|
			// normalize class path
 | 
						|
			for (i in 0...classPaths.length) {
 | 
						|
				var cp = StringTools.replace(classPaths[i], "\\", "/");
 | 
						|
				if (StringTools.endsWith(cp, "/"))
 | 
						|
					cp = cp.substr(0, -1);
 | 
						|
				if (cp == "")
 | 
						|
					cp = ".";
 | 
						|
				classPaths[i] = cp;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		var prefix = pack == '' ? '' : pack + '.';
 | 
						|
		var found = false;
 | 
						|
		for (cp in classPaths) {
 | 
						|
			var path = pack == '' ? cp : cp + "/" + pack.split(".").join("/");
 | 
						|
			if (!sys.FileSystem.exists(path) || !sys.FileSystem.isDirectory(path))
 | 
						|
				continue;
 | 
						|
			found = true;
 | 
						|
			for (file in sys.FileSystem.readDirectory(path)) {
 | 
						|
				if (StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0) {
 | 
						|
					if( file == "import.hx" ) continue;
 | 
						|
					var cl = prefix + file.substr(0, file.length - 3);
 | 
						|
					if (skip(cl))
 | 
						|
						continue;
 | 
						|
					Context.getModule(cl);
 | 
						|
				} else if (rec && sys.FileSystem.isDirectory(path + "/" + file) && !skip(prefix + file))
 | 
						|
					include(prefix + file, true, ignore, classPaths);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (strict && !found)
 | 
						|
			Context.error('Package "$pack" was not found in any of class paths', Context.currentPos());
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Exclude a class or an enum without changing it to `@:nativeGen`.
 | 
						|
	**/
 | 
						|
	static function excludeBaseType(baseType:Type.BaseType):Void {
 | 
						|
		if (!baseType.isExtern) {
 | 
						|
			var meta = baseType.meta;
 | 
						|
			if (!meta.has(":nativeGen")) {
 | 
						|
				meta.add(":hxGen", [], baseType.pos);
 | 
						|
			}
 | 
						|
			baseType.exclude();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Exclude a specific class, enum, or all classes and enums in a
 | 
						|
		package from being generated. Excluded types become `extern`.
 | 
						|
 | 
						|
		@param pack The package dot-path as String. Use `''` to exclude the root package.
 | 
						|
		@param rec If true, recursively excludes all sub-packages.
 | 
						|
	**/
 | 
						|
	public static function exclude(pack:String, ?rec = true) {
 | 
						|
		Context.onGenerate(function(types) {
 | 
						|
			for (t in types) {
 | 
						|
				var b:Type.BaseType, name;
 | 
						|
				switch (t) {
 | 
						|
					case TInst(c, _):
 | 
						|
						name = c.toString();
 | 
						|
						b = c.get();
 | 
						|
					case TEnum(e, _):
 | 
						|
						name = e.toString();
 | 
						|
						b = e.get();
 | 
						|
					default:
 | 
						|
						continue;
 | 
						|
				}
 | 
						|
				var p = b.pack.join(".");
 | 
						|
				if ((p == pack || name == pack) || (rec && StringTools.startsWith(p, pack + ".")))
 | 
						|
					excludeBaseType(b);
 | 
						|
			}
 | 
						|
		}, false);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Exclude classes and enums listed in an extern file (one per line) from being generated.
 | 
						|
	**/
 | 
						|
	public static function excludeFile(fileName:String) {
 | 
						|
		fileName = Context.resolvePath(fileName);
 | 
						|
		var f = sys.io.File.read(fileName, true);
 | 
						|
		var classes = new haxe.ds.StringMap();
 | 
						|
		try {
 | 
						|
			while (true) {
 | 
						|
				var l = StringTools.trim(f.readLine());
 | 
						|
				if (l == "" || !~/[A-Za-z0-9._]/.match(l))
 | 
						|
					continue;
 | 
						|
				classes.set(l, true);
 | 
						|
			}
 | 
						|
		} catch (e:haxe.io.Eof) {}
 | 
						|
		Context.onGenerate(function(types) {
 | 
						|
			for (t in types) {
 | 
						|
				switch (t) {
 | 
						|
					case TInst(c, _):
 | 
						|
						if (classes.exists(c.toString()))
 | 
						|
							excludeBaseType(c.get());
 | 
						|
					case TEnum(e, _):
 | 
						|
						if (classes.exists(e.toString()))
 | 
						|
							excludeBaseType(e.get());
 | 
						|
					default:
 | 
						|
				}
 | 
						|
			}
 | 
						|
		});
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Load a type patch file that can modify the field types within declared classes and enums.
 | 
						|
	**/
 | 
						|
	public static function patchTypes(file:String):Void {
 | 
						|
		var file = Context.resolvePath(file);
 | 
						|
		var f = sys.io.File.read(file, true);
 | 
						|
		try {
 | 
						|
			while (true) {
 | 
						|
				var r = StringTools.trim(f.readLine());
 | 
						|
				if (r == "" || r.substr(0, 2) == "//")
 | 
						|
					continue;
 | 
						|
				if (StringTools.endsWith(r, ";"))
 | 
						|
					r = r.substr(0, -1);
 | 
						|
				if (r.charAt(0) == "-") {
 | 
						|
					r = r.substr(1);
 | 
						|
					var isStatic = StringTools.startsWith(r, "static ");
 | 
						|
					if (isStatic)
 | 
						|
						r = r.substr(7);
 | 
						|
					var p = r.split(".");
 | 
						|
					var field = p.pop();
 | 
						|
					removeField(p.join("."), field, isStatic);
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				if (r.charAt(0) == "@") {
 | 
						|
					var rp = r.split(" ");
 | 
						|
					var type = rp.pop();
 | 
						|
					var isStatic = rp[rp.length - 1] == "static";
 | 
						|
					if (isStatic)
 | 
						|
						rp.pop();
 | 
						|
					var meta = rp.join(" ");
 | 
						|
					var p = type.split(".");
 | 
						|
					var field = if (p.length > 1 && p[p.length - 2].charAt(0) >= "a") null else p.pop();
 | 
						|
					addMetadata(meta, p.join("."), field, isStatic);
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				if (StringTools.startsWith(r, "enum ")) {
 | 
						|
					define("enumAbstract:" + r.substr(5));
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				var rp = r.split(" : ");
 | 
						|
				if (rp.length > 1) {
 | 
						|
					r = rp.shift();
 | 
						|
					var isStatic = StringTools.startsWith(r, "static ");
 | 
						|
					if (isStatic)
 | 
						|
						r = r.substr(7);
 | 
						|
					var p = r.split(".");
 | 
						|
					var field = p.pop();
 | 
						|
					setFieldType(p.join("."), field, rp.join(" : "), isStatic);
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				throw "Invalid type patch " + r;
 | 
						|
			}
 | 
						|
		} catch (e:haxe.io.Eof) {}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Marks types or packages to be kept by DCE.
 | 
						|
 | 
						|
		This also extends to the sub-types of resolved modules.
 | 
						|
 | 
						|
		In order to include module sub-types directly, their full dot path
 | 
						|
		including the containing module has to be used
 | 
						|
		(e.g. `msignal.Signal.Signal0`).
 | 
						|
 | 
						|
		This operation has no effect if the type has already been loaded, e.g.
 | 
						|
		through `Context.getType`.
 | 
						|
 | 
						|
		@param path A package, module or sub-type dot path to keep.
 | 
						|
		@param paths An Array of package, module or sub-type dot paths to keep.
 | 
						|
		@param recursive If true, recurses into sub-packages for package paths.
 | 
						|
	**/
 | 
						|
	public static function keep(?path:String, ?paths:Array<String>, ?recursive:Bool = true) {
 | 
						|
		if (null == paths)
 | 
						|
			paths = [];
 | 
						|
		if (null != path)
 | 
						|
			paths.push(path);
 | 
						|
		for (path in paths) {
 | 
						|
			addGlobalMetadata(path, "@:keep", recursive, true, true);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Enables null safety for a type or a package.
 | 
						|
 | 
						|
		@param path A package, module or sub-type dot path to enable null safety for.
 | 
						|
		@param recursive If true, recurses into sub-packages for package paths.
 | 
						|
	**/
 | 
						|
	public static function nullSafety(path:String, mode:NullSafetyMode = Loose, recursive:Bool = true) {
 | 
						|
		addGlobalMetadata(path, '@:nullSafety($mode)', recursive);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Adds metadata `meta` to all types (if `toTypes = true`) or fields (if
 | 
						|
		`toFields = true`) whose dot-path matches `pathFilter`.
 | 
						|
 | 
						|
		If `recursive` is true a dot-path is considered matched if it starts
 | 
						|
		with `pathFilter`. This automatically applies to path filters of
 | 
						|
		packages. Otherwise an exact match is required.
 | 
						|
 | 
						|
		If `pathFilter` is the empty String `""` it matches everything (if
 | 
						|
		`recursive = true`) or only top-level types (if `recursive = false`).
 | 
						|
 | 
						|
		This operation has no effect if the type has already been loaded, e.g.
 | 
						|
		through `Context.getType`.
 | 
						|
	**/
 | 
						|
	public static function addGlobalMetadata(pathFilter:String, meta:String, ?recursive:Bool = true, ?toTypes:Bool = true, ?toFields:Bool = false) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("add_global_metadata_impl", 5)(pathFilter, meta, recursive, toTypes, toFields);
 | 
						|
		#else
 | 
						|
		addGlobalMetadataImpl(pathFilter, meta, recursive, toTypes, toFields);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
		Change the default JS output by using a custom generator callback
 | 
						|
	**/
 | 
						|
	public static function setCustomJSGenerator(callb:JSGenApi->Void) {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("set_custom_js_generator", 1)(callb);
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	#if (neko || eval)
 | 
						|
	static inline function load(f, nargs):Dynamic {
 | 
						|
		return @:privateAccess Context.load(f, nargs);
 | 
						|
	}
 | 
						|
	#end
 | 
						|
 | 
						|
	/**
 | 
						|
		Clears cached results of file lookups
 | 
						|
	**/
 | 
						|
	public static function flushDiskCache() {
 | 
						|
		#if (neko || eval)
 | 
						|
		load("flush_disk_cache", 0)();
 | 
						|
		#end
 | 
						|
	}
 | 
						|
 | 
						|
	#end
 | 
						|
 | 
						|
	#if (js || lua || macro)
 | 
						|
	/**
 | 
						|
		Embed a JavaScript or Lua file at compile time (can be called by `--macro` or within an `__init__` method).
 | 
						|
	**/
 | 
						|
	public static #if !macro macro #end function includeFile(file:String, position:IncludePosition = Top) {
 | 
						|
		return switch ((position : String).toLowerCase()) {
 | 
						|
			case Inline:
 | 
						|
				if (Context.getLocalModule() == "")
 | 
						|
					Context.error("Cannot use inline mode when includeFile is called by `--macro`", Context.currentPos());
 | 
						|
 | 
						|
				var f = try sys.io.File.getContent(Context.resolvePath(file)) catch (e:Dynamic) Context.error(Std.string(e), Context.currentPos());
 | 
						|
				var p = Context.currentPos();
 | 
						|
				if(Context.defined("js")) {
 | 
						|
					macro @:pos(p) js.Syntax.plainCode($v{f});
 | 
						|
				} else {
 | 
						|
					macro @:pos(p) untyped __lua__($v{f});
 | 
						|
				}
 | 
						|
			case Top | Closure:
 | 
						|
				@:privateAccess Context.includeFile(file, position);
 | 
						|
				macro {};
 | 
						|
			case _:
 | 
						|
				Context.error("unknown includeFile position: " + position, Context.currentPos());
 | 
						|
		}
 | 
						|
	}
 | 
						|
	#end
 | 
						|
}
 | 
						|
 | 
						|
enum abstract IncludePosition(String) from String to String {
 | 
						|
	/**
 | 
						|
		Prepend the file content to the output file.
 | 
						|
	**/
 | 
						|
	var Top = "top";
 | 
						|
 | 
						|
	/**
 | 
						|
		Prepend the file content to the body of the top-level closure.
 | 
						|
 | 
						|
		Since the closure is in strict-mode, there may be run-time error if the input is not strict-mode-compatible.
 | 
						|
	**/
 | 
						|
	var Closure = "closure";
 | 
						|
 | 
						|
	/**
 | 
						|
		Directly inject the file content at the call site.
 | 
						|
	**/
 | 
						|
	var Inline = "inline";
 | 
						|
}
 | 
						|
 | 
						|
enum abstract NullSafetyMode(String) to String {
 | 
						|
	/**
 | 
						|
		Disable null safety.
 | 
						|
	**/
 | 
						|
	var Off;
 | 
						|
 | 
						|
	/**
 | 
						|
		Loose safety.
 | 
						|
		If an expression is checked `!= null`, then it's considered safe even if it could be modified after the check.
 | 
						|
		E.g.
 | 
						|
		```haxe
 | 
						|
		function example(o:{field:Null<String>}) {
 | 
						|
			if(o.field != null) {
 | 
						|
				mutate(o);
 | 
						|
				var notNullable:String = o.field; //no error
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		function mutate(o:{field:Null<String>}) {
 | 
						|
			o.field = null;
 | 
						|
		}
 | 
						|
		```
 | 
						|
	**/
 | 
						|
	var Loose;
 | 
						|
 | 
						|
	/**
 | 
						|
		Full scale null safety.
 | 
						|
		If a field is checked `!= null` it stays safe until a call is made or any field of any object is reassigned,
 | 
						|
		because that could potentially alter an object of the checked field.
 | 
						|
		E.g.
 | 
						|
		```haxe
 | 
						|
		function example(o:{field:Null<String>}, b:{o:{field:Null<String>}}) {
 | 
						|
			if(o.field != null) {
 | 
						|
				var notNullable:String = o.field; //no error
 | 
						|
				someCall();
 | 
						|
				var notNullable:String = o.field; // Error!
 | 
						|
			}
 | 
						|
			if(o.field != null) {
 | 
						|
				var notNullable:String = o.field; //no error
 | 
						|
				b.o = {field:null};
 | 
						|
				var notNullable:String = o.field; // Error!
 | 
						|
			}
 | 
						|
		}
 | 
						|
		```
 | 
						|
	**/
 | 
						|
	var Strict;
 | 
						|
 | 
						|
	/**
 | 
						|
		Full scale null safety for a multi-threaded environment.
 | 
						|
		With this mode checking a field `!= null` does not make it safe, because it could be changed from another thread
 | 
						|
		at the same time or immediately after the check.
 | 
						|
		The only nullable thing could be safe are local variables.
 | 
						|
	**/
 | 
						|
	var StrictThreaded;
 | 
						|
}
 |