forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
110
Kha/Tools/macos/std/haxe/macro/CompilationServer.hx
Normal file
110
Kha/Tools/macos/std/haxe/macro/CompilationServer.hx
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.Compiler;
|
||||
|
||||
enum abstract ModuleCheckPolicy(Int) {
|
||||
/**
|
||||
Disables file modification checks, avoiding some filesystem operations.
|
||||
**/
|
||||
var NoCheckFileTimeModification = 0;
|
||||
|
||||
/**
|
||||
If a file is modified, also checks if its content changed. This check
|
||||
is not free, but useful when .hx files are auto-generated.
|
||||
**/
|
||||
var CheckFileContentModification = 1;
|
||||
|
||||
/**
|
||||
Disables dependency checks of the module.
|
||||
|
||||
This should only be used for modules that don't depend on any module that
|
||||
might change. It is effectively a promise to the compiler that the module
|
||||
is unaffected by changes made to other modules. If that promise is broken,
|
||||
the compiler is sad and things probably stop working.
|
||||
**/
|
||||
var NoCheckDependencies = 2;
|
||||
|
||||
/**
|
||||
Disables file shadowing checks. Shadowing can occur when a new file
|
||||
is added to a class-path that has higher priority than the class-path
|
||||
of the current module file.
|
||||
**/
|
||||
var NoCheckShadowing = 3;
|
||||
}
|
||||
|
||||
enum abstract ContextOptions(Int) {
|
||||
/**
|
||||
Affects only the normal context.
|
||||
**/
|
||||
var NormalContext = 0;
|
||||
|
||||
/**
|
||||
Affects only the macro context.
|
||||
**/
|
||||
var MacroContext = 1;
|
||||
|
||||
/**
|
||||
Affects the normal and macro contexts.
|
||||
**/
|
||||
var NormalAndMacroContext = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
This class provides some methods which can be invoked from command line using
|
||||
`--macro server.field(args)`.
|
||||
**/
|
||||
class CompilationServer {
|
||||
#if (macro || display)
|
||||
/**
|
||||
Sets the `ModuleCheckPolicy` of all files whose dot-path matches an
|
||||
element of `pathFilters`.
|
||||
|
||||
If `recursive` is true, a dot-path is considered matched if it starts
|
||||
with the path filter. This automatically applies to path filters of
|
||||
packages. Otherwise an exact match is required.
|
||||
|
||||
If an element in `pathFilters` is the empty String `""` it matches
|
||||
everything (if `recursive = true`) or only top-level types (if
|
||||
`recursive = false`).
|
||||
|
||||
The argument `contextOptions` determines which context (normal, macro
|
||||
or both) this affects.
|
||||
|
||||
If a call to this function is added to the compilation parameters, the
|
||||
compilation server should be restarted to ensure it takes effect.
|
||||
**/
|
||||
static public function setModuleCheckPolicy(pathFilters:Array<String>, policy:Array<ModuleCheckPolicy>, ?recursive = true,
|
||||
?contextOptions:ContextOptions = NormalContext) {
|
||||
@:privateAccess Compiler.load("server_add_module_check_policy", 4)(pathFilters, policy, recursive, contextOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
Invalidates all files given in `filePaths`, removing them from the cache.
|
||||
**/
|
||||
static public function invalidateFiles(filePaths:Array<String>) {
|
||||
@:privateAccess Compiler.load("server_invalidate_files", 1)(filePaths);
|
||||
}
|
||||
#end
|
||||
}
|
579
Kha/Tools/macos/std/haxe/macro/Compiler.hx
Normal file
579
Kha/Tools/macos/std/haxe/macro/Compiler.hx
Normal file
@ -0,0 +1,579 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
51
Kha/Tools/macos/std/haxe/macro/ComplexTypeTools.hx
Normal file
51
Kha/Tools/macos/std/haxe/macro/ComplexTypeTools.hx
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to work with AST-level types. It is
|
||||
best used through `using haxe.macro.ComplexTypeTools` syntax and then provides
|
||||
additional methods on `haxe.macro.ComplexType` instances.
|
||||
**/
|
||||
class ComplexTypeTools {
|
||||
/**
|
||||
Converts type `c` to a human-readable `String` representation.
|
||||
|
||||
The result is guaranteed to be valid Haxe code, but there may be
|
||||
differences from the original lexical syntax.
|
||||
**/
|
||||
static public function toString(c:ComplexType):String
|
||||
return new Printer().printComplexType(c);
|
||||
|
||||
#if (macro || display)
|
||||
/**
|
||||
Returns a type corresponding to `c`.
|
||||
|
||||
If `c` is null, the result is null.
|
||||
**/
|
||||
static public function toType(c:ComplexType):Null<Type>
|
||||
return c == null ? null : Context.resolveType(c, Context.currentPos());
|
||||
#end
|
||||
}
|
645
Kha/Tools/macos/std/haxe/macro/Context.hx
Normal file
645
Kha/Tools/macos/std/haxe/macro/Context.hx
Normal file
@ -0,0 +1,645 @@
|
||||
/*
|
||||
* 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;
|
||||
import haxe.macro.Type.TypedExpr;
|
||||
|
||||
enum Message {
|
||||
Info(msg:String, pos:Position);
|
||||
Warning(msg:String, pos:Position);
|
||||
}
|
||||
|
||||
/**
|
||||
Context provides an API for macro programming.
|
||||
|
||||
It contains common functions that interact with the macro interpreter to
|
||||
query or set information. Other API functions are available in the tools
|
||||
classes:
|
||||
|
||||
- `haxe.macro.ComplexTypeTools`
|
||||
- `haxe.macro.ExprTools`
|
||||
- `haxe.macro.TypeTools`
|
||||
**/
|
||||
class Context {
|
||||
#if (neko || eval || display)
|
||||
/**
|
||||
Displays a compilation error `msg` at the given `Position` `pos`
|
||||
and aborts the current macro call.
|
||||
**/
|
||||
public static function error(msg:String, pos:Position):Dynamic {
|
||||
return load("error", 2)(msg, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Displays a compilation error `msg` at the given `Position` `pos`
|
||||
and aborts the compilation.
|
||||
**/
|
||||
public static function fatalError(msg:String, pos:Position):Dynamic {
|
||||
return load("fatal_error", 2)(msg, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Displays a compilation warning `msg` at the given `Position` `pos`.
|
||||
**/
|
||||
public static function warning(msg:String, pos:Position) {
|
||||
load("warning", 2)(msg, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Displays a compilation info `msg` at the given `Position` `pos`.
|
||||
**/
|
||||
public static function info(msg:String, pos:Position) {
|
||||
load("info", 2)(msg, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Gets a list of all current compilation info/warning messages.
|
||||
**/
|
||||
public static function getMessages() : Array<Message> {
|
||||
return load("get_messages",0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Filters all current info/warning messages. Filtered out messages will
|
||||
not be displayed by the compiler.
|
||||
**/
|
||||
public static function filterMessages( predicate : Message -> Bool ) {
|
||||
load("filter_messages",1)(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
Resolves a file name `file` based on the current class paths.
|
||||
|
||||
The resolution follows the usual class path rules where the last
|
||||
declared class path has priority.
|
||||
|
||||
If a class path was declared relative, this method returns the relative
|
||||
file path. Otherwise it returns the absolute file path.
|
||||
**/
|
||||
public static function resolvePath(file:String):String {
|
||||
return load("resolve_path", 1)(file);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an `Array` of current class paths in the order of their
|
||||
declaration.
|
||||
|
||||
Modifying the returned array has no effect on the compiler. Class paths
|
||||
can be added using `haxe.macro.Compiler.addClassPath`.
|
||||
**/
|
||||
public static function getClassPath():Array<String> {
|
||||
return load("class_path", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Check if current display position is within `pos`.
|
||||
**/
|
||||
public static function containsDisplayPosition(pos:Position):Bool {
|
||||
return load("contains_display_position", 1)(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the position at which the macro was called.
|
||||
**/
|
||||
public static function currentPos():Position {
|
||||
return load("current_pos", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the type which is expected at the place the macro is called.
|
||||
|
||||
This affects usages such as `var x:Int = macroCall()`, where the
|
||||
expected type will be reported as `Int`.
|
||||
|
||||
Might return `null` if no specific type is expected or if the calling
|
||||
macro is not an expression-macro.
|
||||
**/
|
||||
public static function getExpectedType():Null<Type> {
|
||||
return load("get_expected_type", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the call arguments that lead to the invocation of the current
|
||||
`@:genericBuild` macro, if available.
|
||||
|
||||
Returns `null` if the current macro is not a `@:genericBuild` macro.
|
||||
**/
|
||||
public static function getCallArguments():Null<Array<Expr>> {
|
||||
return load("get_call_arguments", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current class in which the macro was called.
|
||||
|
||||
If no such class exists, `null` is returned.
|
||||
**/
|
||||
public static function getLocalClass():Null<Type.Ref<Type.ClassType>> {
|
||||
var l:Type = load("get_local_type", 0)();
|
||||
if (l == null)
|
||||
return null;
|
||||
return switch (l) {
|
||||
case TInst(c, _): c;
|
||||
default: null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current module path in/on which the macro was called.
|
||||
**/
|
||||
public static function getLocalModule():String {
|
||||
return load("get_local_module", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current type in/on which the macro was called.
|
||||
|
||||
If no such type exists, `null` is returned.
|
||||
**/
|
||||
public static function getLocalType():Null<Type> {
|
||||
return load("get_local_type", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the name of the method from which the macro was called.
|
||||
|
||||
If no such method exists, `null` is returned.
|
||||
**/
|
||||
public static function getLocalMethod():Null<String> {
|
||||
return load("get_local_method", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an `Array` of classes which are available for `using` usage in
|
||||
the context the macro was called.
|
||||
|
||||
Modifying the returned array has no effect on the compiler.
|
||||
**/
|
||||
public static function getLocalUsing():Array<Type.Ref<Type.ClassType>> {
|
||||
return load("get_local_using", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an `Array` of all imports in the context the macro was called.
|
||||
|
||||
Modifying the returned array has no effect on the compiler.
|
||||
**/
|
||||
public static function getLocalImports():Array<ImportExpr> {
|
||||
return load("get_local_imports", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a map of local variables accessible in the context the macro was
|
||||
called.
|
||||
|
||||
The keys of the returned map are the variable names, the values are
|
||||
their types.
|
||||
|
||||
Modifying the returned map has no effect on the compiler.
|
||||
**/
|
||||
@:deprecated("Use Context.getLocalTVars() instead")
|
||||
public static function getLocalVars():Map<String, Type> {
|
||||
return load("local_vars", 1)(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Similar to `getLocalVars`, but returns elements of type `TVar` instead
|
||||
of `Type`.
|
||||
**/
|
||||
public static function getLocalTVars():Map<String, Type.TVar> {
|
||||
return load("local_vars", 1)(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Tells if the conditional compilation flag `s` has been set.
|
||||
|
||||
Compiler flags are set using the `-D` command line parameter, or
|
||||
by calling `haxe.macro.Compiler.define`.
|
||||
|
||||
@see https://haxe.org/manual/lf-condition-compilation.html
|
||||
**/
|
||||
public static function defined(s:String):Bool {
|
||||
return load("defined", 1)(s);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value defined for the conditional compilation flag `key`.
|
||||
|
||||
If no value is defined for `key`, `null` is returned.
|
||||
|
||||
Compiler flags values are set using the `-D key=value` command line
|
||||
parameter, or by calling `haxe.macro.Compiler.define`.
|
||||
|
||||
The default value is `"1"`.
|
||||
|
||||
@see https://haxe.org/manual/lf-condition-compilation.html
|
||||
**/
|
||||
public static function definedValue(key:String):String {
|
||||
return load("defined_value", 1)(key);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a map of all conditional compilation flags that have been set.
|
||||
|
||||
Compiler flags are set using the `-D` command line parameter, or
|
||||
by calling `haxe.macro.Compiler.define`.
|
||||
|
||||
Modifying the returned map has no effect on the compiler.
|
||||
|
||||
@see https://haxe.org/manual/lf-condition-compilation.html
|
||||
**/
|
||||
public static function getDefines():Map<String, String> {
|
||||
return load("get_defines", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Resolves a type identified by `name`.
|
||||
|
||||
The resolution follows the usual class path rules where the last
|
||||
declared class path has priority.
|
||||
|
||||
If no type can be found, an exception of type `String` is thrown.
|
||||
**/
|
||||
public static function getType(name:String):Type {
|
||||
return load("get_type", 1)(name);
|
||||
}
|
||||
|
||||
/**
|
||||
Resolves a module identified by `name` and returns an `Array` of all
|
||||
its contained types.
|
||||
|
||||
The resolution follows the usual class path rules where the last
|
||||
declared class path has priority.
|
||||
|
||||
If no module can be found, an exception of type `String` is thrown.
|
||||
**/
|
||||
public static function getModule(name:String):Array<Type> {
|
||||
return load("get_module", 1)(name);
|
||||
}
|
||||
|
||||
/**
|
||||
Parses `expr` as Haxe code, returning the corresponding AST.
|
||||
|
||||
String interpolation of single quote strings within `expr` is not
|
||||
supported.
|
||||
|
||||
The provided `Position` `pos` is used for all generated inner AST nodes.
|
||||
**/
|
||||
public static function parse(expr:String, pos:Position):Expr {
|
||||
return load("do_parse", 3)(expr, pos, false);
|
||||
}
|
||||
|
||||
/**
|
||||
Similar to `parse`, but error positions are reported within the provided
|
||||
String `expr`.
|
||||
**/
|
||||
public static function parseInlineString(expr:String, pos:Position):Expr {
|
||||
return load("do_parse", 3)(expr, pos, true);
|
||||
}
|
||||
|
||||
/**
|
||||
Builds an expression from `v`.
|
||||
|
||||
This method generates AST nodes depending on the macro-runtime value of
|
||||
`v`. As such, only basic types and enums are supported and the behavior
|
||||
for other types is undefined.
|
||||
|
||||
The provided `Position` `pos` is used for all generated inner AST nodes.
|
||||
**/
|
||||
public static function makeExpr(v:Dynamic, pos:Position):Expr {
|
||||
return load("make_expr", 2)(v, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a hashed MD5 signature of value `v`.
|
||||
**/
|
||||
public static function signature(v:Dynamic):String {
|
||||
return load("signature", 1)(v);
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a callback function `callback` which is invoked after the
|
||||
compiler's typing phase, just before its generation phase.
|
||||
|
||||
The callback receives an `Array` containing all types which are about
|
||||
to be generated. Modifications are limited to metadata, it is mainly
|
||||
intended to obtain information.
|
||||
|
||||
By default, the callback is made before types are stored in the compilation
|
||||
server, if active. This means that any effect persists for the next compilation.
|
||||
If `persistent` is set to `false`, changes to types made by the callback only
|
||||
affect the current compilation. If no compilation server is used, this flag has
|
||||
no effect.
|
||||
|
||||
*Note*: the callback is still invoked when generation is disabled with `--no-output`.
|
||||
**/
|
||||
public static function onGenerate(callback:Array<Type>->Void, persistent:Bool = true) {
|
||||
load("on_generate", 2)(callback, persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a callback function `callback` which is invoked after the compiler
|
||||
generation phase.
|
||||
|
||||
Compilation has completed at this point and cannot be influenced
|
||||
anymore. However, contextual information is still available.
|
||||
|
||||
*Note*: the callback is still invoked when generation is disabled with `--no-output`.
|
||||
**/
|
||||
public static function onAfterGenerate(callback:Void->Void) {
|
||||
load("on_after_generate", 1)(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a callback function `callback` which is invoked after the compiler
|
||||
is done typing, but before optimization. The callback receives the types
|
||||
which have been typed.
|
||||
|
||||
It is possible to define new types in the callback, in which case it
|
||||
will be called again with the new types as argument.
|
||||
**/
|
||||
public static function onAfterTyping(callback:Array<haxe.macro.Type.ModuleType>->Void) {
|
||||
load("on_after_typing", 1)(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a callback function `callback` which is invoked when a type name
|
||||
cannot be resolved.
|
||||
|
||||
The callback may return a type definition, which is then used for the
|
||||
expected type. If it returns `null`, the type is considered to still not
|
||||
exist.
|
||||
**/
|
||||
public static function onTypeNotFound(callback:String->TypeDefinition) {
|
||||
load("on_type_not_found", 1)(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
Types expression `e` and returns its type.
|
||||
|
||||
Typing the expression may result in a compiler error which can be
|
||||
caught using `try ... catch`.
|
||||
**/
|
||||
public static function typeof(e:Expr):Type {
|
||||
return load("typeof", 1)(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Types expression `e` and returns the corresponding `TypedExpr`.
|
||||
|
||||
Typing the expression may result in a compiler error which can be
|
||||
caught using `try ... catch`.
|
||||
**/
|
||||
public static function typeExpr(e:Expr):TypedExpr {
|
||||
return load("type_expr", 1)(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Resolve type `t` and returns the corresponding `Type`.
|
||||
|
||||
Resolving the type may result in a compiler error which can be
|
||||
caught using `try ... catch`.
|
||||
Resolution is performed based on the current context in which the macro is called.
|
||||
**/
|
||||
public static function resolveType(t:ComplexType, p:Position):Type {
|
||||
return load("resolve_type", 2)(t, p);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the `ComplexType` corresponding to the given `Type` `t`.
|
||||
|
||||
See `haxe.macro.TypeTools.toComplexType` for details.
|
||||
**/
|
||||
public static function toComplexType(t:Type):Null<ComplexType> {
|
||||
return load("to_complex_type", 1)(t);
|
||||
}
|
||||
|
||||
/**
|
||||
Tries to unify `t1` and `t2` and returns `true` if successful.
|
||||
**/
|
||||
public static function unify(t1:Type, t2:Type):Bool {
|
||||
return load("unify", 2)(t1, t2);
|
||||
}
|
||||
|
||||
/**
|
||||
Follows a type.
|
||||
|
||||
See `haxe.macro.TypeTools.follow` for details.
|
||||
**/
|
||||
public static function follow(t:Type, ?once:Bool):Type {
|
||||
return load("follow", 2)(t, once);
|
||||
}
|
||||
|
||||
/**
|
||||
Follows a type, including abstracts' underlying implementation
|
||||
|
||||
See `haxe.macro.TypeTools.followWithAbstracts` for details.
|
||||
**/
|
||||
public static function followWithAbstracts(t:Type, once:Bool = false):Type {
|
||||
return load("follow_with_abstracts", 2)(t, once);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the information stored in `Position` `p`.
|
||||
**/
|
||||
public static function getPosInfos(p:Position):{min:Int, max:Int, file:String} {
|
||||
return load("get_pos_infos", 1)(p);
|
||||
}
|
||||
|
||||
/**
|
||||
Builds a `Position` from `inf`.
|
||||
**/
|
||||
public static function makePosition(inf:{min:Int, max:Int, file:String}):Position {
|
||||
return load("make_position", 3)(inf.min, inf.max, inf.file);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a map of all registered resources for this compilation unit.
|
||||
|
||||
Modifying the returned map has no effect on the compilation, use
|
||||
`haxe.macro.Context.addResource` to add new resources to the compilation unit.
|
||||
**/
|
||||
public static function getResources():Map<String, haxe.io.Bytes> {
|
||||
return load("get_resources", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Makes resource `data` available as `name`.
|
||||
|
||||
The resource is then available using the `haxe.macro.Resource` API.
|
||||
|
||||
If a previous resource was bound to `name`, it is overwritten.
|
||||
|
||||
Compilation server : when using the compilation server, the resource is bound
|
||||
to the Haxe module which calls the macro, so it will be included again if
|
||||
that module is reused. If this resource concerns several modules, prefix its
|
||||
name with a `$` sign, this will bind it to the macro module instead.
|
||||
**/
|
||||
public static function addResource(name:String, data:haxe.io.Bytes) {
|
||||
load("add_resource", 2)(name, data);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an `Array` of fields of the class which is to be built.
|
||||
|
||||
This is only defined for `@:build/@:autoBuild` macros.
|
||||
**/
|
||||
public static function getBuildFields():Array<Field> {
|
||||
return load("get_build_fields", 0)();
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a new type from `TypeDefinition` `t`.
|
||||
|
||||
If `moduleDependency` is given and is not `null`, it should contain
|
||||
a module path that will be used as a dependency for the newly defined module
|
||||
instead of the current module.
|
||||
**/
|
||||
public static function defineType(t:TypeDefinition, ?moduleDependency:String):Void {
|
||||
load("define_type", 2)(t, moduleDependency);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a new module as `modulePath` with several `TypeDefinition`
|
||||
`types`. This is analogous to defining a .hx file.
|
||||
|
||||
The individual `types` can reference each other and any identifier
|
||||
respects the `imports` and `usings` as usual, expect that imports are
|
||||
not allowed to have `.*` wildcards or `as s` shorthands.
|
||||
**/
|
||||
public static function defineModule(modulePath:String, types:Array<TypeDefinition>, ?imports:Array<ImportExpr>, ?usings:Array<TypePath>):Void {
|
||||
if (imports == null)
|
||||
imports = [];
|
||||
if (usings == null)
|
||||
usings = [];
|
||||
load("define_module", 4)(modulePath, types, imports, usings);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a syntax-level expression corresponding to typed expression `t`.
|
||||
|
||||
This process may lose some information.
|
||||
**/
|
||||
public static function getTypedExpr(t:Type.TypedExpr):Expr {
|
||||
return load("get_typed_expr", 1)(t);
|
||||
}
|
||||
|
||||
/**
|
||||
Store typed expression `t` internally and give a syntax-level expression
|
||||
that can be returned from a macro and will be replaced by the stored
|
||||
typed expression.
|
||||
|
||||
If `t` is `null` or invalid, an exception is thrown.
|
||||
|
||||
NOTE: the returned value references an internally stored typed expression
|
||||
that is reset between compilations, so care should be taken when storing
|
||||
the expression returned by this method in a static variable and using the
|
||||
compilation server.
|
||||
**/
|
||||
public static function storeTypedExpr(t:Type.TypedExpr):Expr {
|
||||
return load("store_typed_expr", 1)(t);
|
||||
}
|
||||
|
||||
/**
|
||||
Types expression `e`, stores the resulting typed expression internally and
|
||||
returns a syntax-level expression that can be returned from a macro and
|
||||
will be replaced by the stored typed expression.
|
||||
|
||||
If `e` is `null` or invalid, an exception is thrown.
|
||||
|
||||
A call to `storeExpr(e)` is equivalent to `storeTypedExpr(typeExpr(e))` without
|
||||
the overhead of encoding and decoding between regular and macro runtime.
|
||||
|
||||
NOTE: the returned value references an internally stored typed expression
|
||||
that is reset between compilations, so care should be taken when storing
|
||||
the expression returned by this method in a static variable and using the
|
||||
compilation server.
|
||||
**/
|
||||
public static function storeExpr(e:Expr):Expr {
|
||||
return load("store_expr", 1)(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Manually adds a dependency between module `modulePath` and an external
|
||||
file `externFile`.
|
||||
|
||||
This affects the compilation cache, causing the module to be typed if
|
||||
`externFile` has changed.
|
||||
|
||||
Has no effect if the compilation cache is not used.
|
||||
**/
|
||||
public static function registerModuleDependency(modulePath:String, externFile:String) {
|
||||
load("register_module_dependency", 2)(modulePath, externFile);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a timer which will be printed in the compilation report
|
||||
if `--times` compilation argument is set.
|
||||
|
||||
Note that a timer may be omitted from the report if the amount of time
|
||||
measured is too small.
|
||||
|
||||
This method immediately starts a timer and returns a function to stop it:
|
||||
```
|
||||
var stopTimer = haxe.macro.Context.timer("my heavy task");
|
||||
runTask();
|
||||
stopTimer();
|
||||
```
|
||||
**/
|
||||
public static function timer(id:String):()->Void {
|
||||
return load("timer", 1)(id);
|
||||
}
|
||||
|
||||
@:deprecated
|
||||
public static function registerModuleReuseCall(modulePath:String, macroCall:String) {
|
||||
throw "This method is no longer supported. See https://github.com/HaxeFoundation/haxe/issues/5746";
|
||||
}
|
||||
|
||||
@:deprecated
|
||||
public static function onMacroContextReused(callb:Void->Bool) {
|
||||
throw "This method is no longer supported. See https://github.com/HaxeFoundation/haxe/issues/5746";
|
||||
}
|
||||
|
||||
@:allow(haxe.macro.TypeTools)
|
||||
@:allow(haxe.macro.MacroStringTools)
|
||||
@:allow(haxe.macro.TypedExprTools)
|
||||
@:allow(haxe.macro.PositionTools)
|
||||
static function load(f:String, nargs:Int):Dynamic {
|
||||
#if neko
|
||||
return neko.Lib.load("macro", f, nargs);
|
||||
#elseif eval
|
||||
return eval.vm.Context.callMacroApi(f);
|
||||
#else
|
||||
return Reflect.makeVarArgs(function(_) return throw "Can't be called outside of macro");
|
||||
#end
|
||||
}
|
||||
|
||||
private static function includeFile(file:String, position:String) {
|
||||
load("include_file", 2)(file, position);
|
||||
}
|
||||
|
||||
private static function sExpr(e:TypedExpr, pretty:Bool):String {
|
||||
return haxe.macro.Context.load("s_expr", 2)(e, pretty);
|
||||
}
|
||||
#end
|
||||
}
|
258
Kha/Tools/macos/std/haxe/macro/ExampleJSGenerator.hx
Normal file
258
Kha/Tools/macos/std/haxe/macro/ExampleJSGenerator.hx
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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.Type;
|
||||
import haxe.macro.Expr;
|
||||
|
||||
using Lambda;
|
||||
|
||||
class ExampleJSGenerator {
|
||||
var api:JSGenApi;
|
||||
var buf:StringBuf;
|
||||
var inits:List<TypedExpr>;
|
||||
var statics:List<{c:ClassType, f:ClassField}>;
|
||||
var packages:haxe.ds.StringMap<Bool>;
|
||||
var forbidden:haxe.ds.StringMap<Bool>;
|
||||
|
||||
public function new(api) {
|
||||
this.api = api;
|
||||
buf = new StringBuf();
|
||||
inits = new List();
|
||||
statics = new List();
|
||||
packages = new haxe.ds.StringMap();
|
||||
forbidden = new haxe.ds.StringMap();
|
||||
for (x in ["prototype", "__proto__", "constructor"])
|
||||
forbidden.set(x, true);
|
||||
api.setTypeAccessor(getType);
|
||||
}
|
||||
|
||||
function getType(t:Type) {
|
||||
return switch (t) {
|
||||
case TInst(c, _): getPath(c.get());
|
||||
case TEnum(e, _): getPath(e.get());
|
||||
case TAbstract(a, _): getPath(a.get());
|
||||
default: throw "assert";
|
||||
};
|
||||
}
|
||||
|
||||
inline function print(str:String) {
|
||||
buf.add(str);
|
||||
}
|
||||
|
||||
inline function newline() {
|
||||
buf.add(";\n");
|
||||
}
|
||||
|
||||
inline function genExpr(e) {
|
||||
print(api.generateValue(e));
|
||||
}
|
||||
|
||||
function field(p) {
|
||||
return api.isKeyword(p) ? '["' + p + '"]' : "." + p;
|
||||
}
|
||||
|
||||
function genPackage(p:Array<String>) {
|
||||
var full = null;
|
||||
for (x in p) {
|
||||
var prev = full;
|
||||
if (full == null)
|
||||
full = x
|
||||
else
|
||||
full += "." + x;
|
||||
if (packages.exists(full))
|
||||
continue;
|
||||
packages.set(full, true);
|
||||
if (prev == null)
|
||||
print('if(typeof $x==\'undefined\') $x = {}');
|
||||
else {
|
||||
var p = prev + field(x);
|
||||
print('if(!$p) $p = {}');
|
||||
}
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
function getPath(t:BaseType) {
|
||||
return (t.pack.length == 0) ? t.name : t.pack.join(".") + "." + t.name;
|
||||
}
|
||||
|
||||
function checkFieldName(c:ClassType, f:ClassField) {
|
||||
if (forbidden.exists(f.name))
|
||||
Context.error("The field " + f.name + " is not allowed in JS", c.pos);
|
||||
}
|
||||
|
||||
function genClassField(c:ClassType, p:String, f:ClassField) {
|
||||
checkFieldName(c, f);
|
||||
var field = field(f.name);
|
||||
print('$p.prototype$field = ');
|
||||
var e = f.expr();
|
||||
if (e == null)
|
||||
print("null");
|
||||
else {
|
||||
genExpr(e);
|
||||
}
|
||||
newline();
|
||||
}
|
||||
|
||||
function genStaticField(c:ClassType, p:String, f:ClassField) {
|
||||
checkFieldName(c, f);
|
||||
var field = field(f.name);
|
||||
var e = f.expr();
|
||||
if (e == null) {
|
||||
print('$p$field = null');
|
||||
newline();
|
||||
} else
|
||||
switch (f.kind) {
|
||||
case FMethod(_):
|
||||
print('$p$field = ');
|
||||
genExpr(e);
|
||||
newline();
|
||||
default:
|
||||
statics.add({c: c, f: f});
|
||||
}
|
||||
}
|
||||
|
||||
function genClass(c:ClassType) {
|
||||
genPackage(c.pack);
|
||||
api.setCurrentClass(c);
|
||||
var p = getPath(c);
|
||||
print('$p = $$hxClasses[\'$p\'] = ');
|
||||
if (c.constructor != null)
|
||||
genExpr(c.constructor.get().expr());
|
||||
else
|
||||
print("function() { }");
|
||||
newline();
|
||||
print('$p.__name__ = "$p"');
|
||||
newline();
|
||||
if (c.superClass != null) {
|
||||
var psup = getPath(c.superClass.t.get());
|
||||
print('$p.__super__ = $psup');
|
||||
newline();
|
||||
print('for(var k in $psup.prototype ) $p.prototype[k] = $psup.prototype[k]');
|
||||
newline();
|
||||
}
|
||||
for (f in c.statics.get())
|
||||
genStaticField(c, p, f);
|
||||
for (f in c.fields.get()) {
|
||||
switch (f.kind) {
|
||||
case FVar(r, _):
|
||||
if (r == AccResolve)
|
||||
continue;
|
||||
default:
|
||||
}
|
||||
genClassField(c, p, f);
|
||||
}
|
||||
print('$p.prototype.__class__ = $p');
|
||||
newline();
|
||||
if (c.interfaces.length > 0) {
|
||||
var me = this;
|
||||
var inter = c.interfaces.map(function(i) return me.getPath(i.t.get())).join(",");
|
||||
print('$p.__interfaces__ = [$inter]');
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
function genEnum(e:EnumType) {
|
||||
genPackage(e.pack);
|
||||
var p = getPath(e);
|
||||
var constructs = e.names.map(api.quoteString).join(",");
|
||||
print('$p = $$hxClasses[\'$p\'] = { __ename__ : \'$p\', __constructs__ : [$constructs] }');
|
||||
newline();
|
||||
for (c in e.constructs.keys()) {
|
||||
var c = e.constructs.get(c);
|
||||
var f = field(c.name);
|
||||
print('$p$f = ');
|
||||
switch (c.type) {
|
||||
case TFun(args, _):
|
||||
var sargs = args.map(function(a) return a.name).join(",");
|
||||
print('function($sargs) { var $$x = ["${c.name}",${c.index},$sargs]; $$x.__enum__ = $p; $$x.toString = $$estr; return $$x; }');
|
||||
default:
|
||||
print("[" + api.quoteString(c.name) + "," + c.index + "]");
|
||||
newline();
|
||||
print('$p$f.toString = $$estr');
|
||||
newline();
|
||||
print('$p$f.__enum__ = $p');
|
||||
}
|
||||
newline();
|
||||
}
|
||||
var meta = api.buildMetaData(e);
|
||||
if (meta != null) {
|
||||
print('$p.__meta__ = ');
|
||||
genExpr(meta);
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
function genStaticValue(c:ClassType, cf:ClassField) {
|
||||
var p = getPath(c);
|
||||
var f = field(cf.name);
|
||||
print('$p$f = ');
|
||||
genExpr(cf.expr());
|
||||
newline();
|
||||
}
|
||||
|
||||
function genType(t:Type) {
|
||||
switch (t) {
|
||||
case TInst(c, _):
|
||||
var c = c.get();
|
||||
if (c.init != null)
|
||||
inits.add(c.init);
|
||||
if (!c.isExtern)
|
||||
genClass(c);
|
||||
case TEnum(r, _):
|
||||
var e = r.get();
|
||||
if (!e.isExtern)
|
||||
genEnum(e);
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
public function generate() {
|
||||
print("var $_, $hxClasses = $hxClasses || {}, $estr = function() { return js.Boot.__string_rec(this,''); }");
|
||||
newline();
|
||||
print("function $bind(o,m) { var f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; return f; };");
|
||||
newline();
|
||||
for (t in api.types)
|
||||
genType(t);
|
||||
for (e in inits) {
|
||||
print(api.generateStatement(e));
|
||||
newline();
|
||||
}
|
||||
for (s in statics) {
|
||||
genStaticValue(s.c, s.f);
|
||||
newline();
|
||||
}
|
||||
if (api.main != null) {
|
||||
genExpr(api.main);
|
||||
newline();
|
||||
}
|
||||
sys.io.File.saveContent(api.outputFile, buf.toString());
|
||||
}
|
||||
|
||||
#if (macro || display)
|
||||
public static function use() {
|
||||
Compiler.setCustomJSGenerator(function(api) new ExampleJSGenerator(api).generate());
|
||||
}
|
||||
#end
|
||||
}
|
1040
Kha/Tools/macos/std/haxe/macro/Expr.hx
Normal file
1040
Kha/Tools/macos/std/haxe/macro/Expr.hx
Normal file
File diff suppressed because it is too large
Load Diff
314
Kha/Tools/macos/std/haxe/macro/ExprTools.hx
Normal file
314
Kha/Tools/macos/std/haxe/macro/ExprTools.hx
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
using Lambda;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to work with expressions. It is
|
||||
best used through 'using haxe.macro.ExprTools' syntax and then provides
|
||||
additional methods on haxe.macro.Expr instances.
|
||||
|
||||
While mainly intended to be used in macros, it works in non-macro code as
|
||||
well.
|
||||
**/
|
||||
class ExprTools {
|
||||
/**
|
||||
Converts expression `e` to a human-readable String representation.
|
||||
|
||||
The result is guaranteed to be valid Haxe code, but there may be
|
||||
differences from the original lexical syntax.
|
||||
**/
|
||||
static public function toString(e:Expr):String
|
||||
return new Printer().printExpr(e);
|
||||
|
||||
/**
|
||||
Calls function `f` on each sub-expression of `e`.
|
||||
|
||||
If `e` has no sub-expressions, this operation has no effect.
|
||||
|
||||
Otherwise `f` is called once per sub-expression of `e`, with the
|
||||
sub-expression as argument. These calls are done in order of the
|
||||
sub-expression declarations.
|
||||
|
||||
This method does not call itself recursively. It should instead be used
|
||||
in a recursive function which handles the expression nodes of interest.
|
||||
|
||||
Usage example:
|
||||
```haxe
|
||||
function findStrings(e:Expr) {
|
||||
switch(e.expr) {
|
||||
case EConst(CString(s)):
|
||||
// handle s
|
||||
case _:
|
||||
ExprTools.iter(e, findStrings);
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
static public function iter(e:Expr, f:Expr->Void):Void {
|
||||
switch (e.expr) {
|
||||
case EConst(_), EContinue, EBreak, EDisplayNew(_):
|
||||
case EField(e, _), EParenthesis(e), EUntyped(e), EThrow(e), EDisplay(e, _), ECheckType(e, _), EUnop(_, _, e), ECast(e, _), EIs(e, _) | EMeta(_, e):
|
||||
f(e);
|
||||
case EArray(e1, e2), EWhile(e1, e2, _), EBinop(_, e1, e2), EFor(e1, e2):
|
||||
f(e1);
|
||||
f(e2);
|
||||
case EVars(vl):
|
||||
for (v in vl)
|
||||
opt2(v.expr, f);
|
||||
case ETry(e, cl):
|
||||
f(e);
|
||||
for (c in cl)
|
||||
f(c.expr);
|
||||
case ETernary(e1, e2, e3) | EIf(e1, e2, e3):
|
||||
f(e1);
|
||||
f(e2);
|
||||
opt2(e3, f);
|
||||
case EArrayDecl(el), ENew(_, el), EBlock(el):
|
||||
ExprArrayTools.iter(el, f);
|
||||
case EObjectDecl(fl):
|
||||
for (fd in fl)
|
||||
f(fd.expr);
|
||||
case ECall(e, el):
|
||||
f(e);
|
||||
ExprArrayTools.iter(el, f);
|
||||
case EReturn(e):
|
||||
opt2(e, f);
|
||||
case EFunction(_, func):
|
||||
for (arg in func.args)
|
||||
opt2(arg.value, f);
|
||||
opt2(func.expr, f);
|
||||
case ESwitch(e, cl, edef):
|
||||
f(e);
|
||||
for (c in cl) {
|
||||
ExprArrayTools.iter(c.values, f);
|
||||
opt2(c.guard, f);
|
||||
opt2(c.expr, f);
|
||||
}
|
||||
if (edef != null && edef.expr != null)
|
||||
f(edef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the sub-expressions of `e` by calling `f` on each of them.
|
||||
|
||||
If `e` has no sub-expressions, this operation returns `e` unchanged.
|
||||
|
||||
Otherwise `f` is called once per sub-expression of `e`, with the
|
||||
sub-expression as argument. These calls are done in order of the
|
||||
sub-expression declarations.
|
||||
|
||||
This method does not call itself recursively. It should instead be used
|
||||
in a recursive function which handles the expression nodes of interest.
|
||||
|
||||
Usage example:
|
||||
```haxe
|
||||
function capitalizeStrings(e:Expr) {
|
||||
return switch(e.expr) {
|
||||
case EConst(CString(s)):
|
||||
{ expr: EConst(CString(s.toUpperCase())), pos: e.pos };
|
||||
case _:
|
||||
ExprTools.map(e, capitalizeStrings);
|
||||
}
|
||||
}
|
||||
```
|
||||
**/
|
||||
static public function map(e:Expr, f:Expr->Expr):Expr {
|
||||
return {
|
||||
pos: e.pos,
|
||||
expr: switch (e.expr) {
|
||||
case EConst(_): e.expr;
|
||||
case EArray(e1, e2): EArray(f(e1), f(e2));
|
||||
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
|
||||
case EField(e, field): EField(f(e), field);
|
||||
case EParenthesis(e): EParenthesis(f(e));
|
||||
case EObjectDecl(fields):
|
||||
var ret = [];
|
||||
for (field in fields)
|
||||
ret.push({field: field.field, expr: f(field.expr), quotes: field.quotes});
|
||||
EObjectDecl(ret);
|
||||
case EArrayDecl(el): EArrayDecl(ExprArrayTools.map(el, f));
|
||||
case ECall(e, params): ECall(f(e), ExprArrayTools.map(params, f));
|
||||
case ENew(tp, params): ENew(tp, ExprArrayTools.map(params, f));
|
||||
case EUnop(op, postFix, e): EUnop(op, postFix, f(e));
|
||||
case EVars(vars):
|
||||
var ret = [];
|
||||
for (v in vars) {
|
||||
var v2:Var = {name: v.name, type: v.type, expr: opt(v.expr, f)};
|
||||
if (v.isFinal != null)
|
||||
v2.isFinal = v.isFinal;
|
||||
ret.push(v2);
|
||||
}
|
||||
EVars(ret);
|
||||
case EBlock(el): EBlock(ExprArrayTools.map(el, f));
|
||||
case EFor(it, expr): EFor(f(it), f(expr));
|
||||
case EIf(econd, eif, eelse): EIf(f(econd), f(eif), opt(eelse, f));
|
||||
case EWhile(econd, e, normalWhile): EWhile(f(econd), f(e), normalWhile);
|
||||
case EReturn(e): EReturn(opt(e, f));
|
||||
case EUntyped(e): EUntyped(f(e));
|
||||
case EThrow(e): EThrow(f(e));
|
||||
case ECast(e, t): ECast(f(e), t);
|
||||
case EIs(e, t): EIs(f(e), t);
|
||||
case EDisplay(e, dk): EDisplay(f(e), dk);
|
||||
case ETernary(econd, eif, eelse): ETernary(f(econd), f(eif), f(eelse));
|
||||
case ECheckType(e, t): ECheckType(f(e), t);
|
||||
case EDisplayNew(_), EContinue, EBreak:
|
||||
e.expr;
|
||||
case ETry(e, catches):
|
||||
var ret = [];
|
||||
for (c in catches)
|
||||
ret.push({name: c.name, type: c.type, expr: f(c.expr)});
|
||||
ETry(f(e), ret);
|
||||
case ESwitch(e, cases, edef):
|
||||
var ret = [];
|
||||
for (c in cases)
|
||||
ret.push({expr: opt(c.expr, f), guard: opt(c.guard, f), values: ExprArrayTools.map(c.values, f)});
|
||||
ESwitch(f(e), ret, edef == null || edef.expr == null ? edef : f(edef));
|
||||
case EFunction(kind, func):
|
||||
var ret = [];
|
||||
for (arg in func.args)
|
||||
ret.push({
|
||||
name: arg.name,
|
||||
opt: arg.opt,
|
||||
type: arg.type,
|
||||
value: opt(arg.value, f)
|
||||
});
|
||||
EFunction(kind, {
|
||||
args: ret,
|
||||
ret: func.ret,
|
||||
params: func.params,
|
||||
expr: f(func.expr)
|
||||
});
|
||||
case EMeta(m, e): EMeta(m, f(e));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value `e` represents.
|
||||
|
||||
Supported expressions are:
|
||||
|
||||
- `Int`, `Float` and `String` literals
|
||||
- identifiers `true`, `false` and `null`
|
||||
- structure declarations if all their fields are values
|
||||
- array declarations if all their elements are values
|
||||
- unary operators `-`, `!` and `~` if the operand is a value
|
||||
- binary operators except `=>`, `...` and assignments
|
||||
|
||||
Parentheses, metadata and the `untyped` keyword are ignored.
|
||||
|
||||
If any non-value is encountered, an exception of type `String` is
|
||||
thrown.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
static public function getValue(e:Expr):Dynamic {
|
||||
return switch (e.expr) {
|
||||
case EConst(CInt(v)): Std.parseInt(v);
|
||||
case EConst(CFloat(v)): Std.parseFloat(v);
|
||||
case EConst(CString(s)): s;
|
||||
case EConst(CIdent("true")): true;
|
||||
case EConst(CIdent("false")): false;
|
||||
case EConst(CIdent("null")): null;
|
||||
case EParenthesis(e1) | EUntyped(e1) | EMeta(_, e1): getValue(e1);
|
||||
case EObjectDecl(fields):
|
||||
var obj = {};
|
||||
for (field in fields) {
|
||||
Reflect.setField(obj, field.field, getValue(field.expr));
|
||||
}
|
||||
obj;
|
||||
case EArrayDecl(el): el.map(getValue);
|
||||
case EIf(econd, eif, eelse) | ETernary(econd, eif, eelse):
|
||||
if (eelse == null) {
|
||||
throw "If statements only have a value if the else clause is defined";
|
||||
} else {
|
||||
var econd:Dynamic = getValue(econd);
|
||||
econd ? getValue(eif) : getValue(eelse);
|
||||
}
|
||||
case EUnop(op, false, e1):
|
||||
var e1:Dynamic = getValue(e1);
|
||||
switch (op) {
|
||||
case OpNot: !e1;
|
||||
case OpNeg: -e1;
|
||||
case OpNegBits: ~e1;
|
||||
case _: throw 'Unsupported expression: $e';
|
||||
}
|
||||
case EBinop(op, e1, e2):
|
||||
var e1:Dynamic = getValue(e1);
|
||||
var e2:Dynamic = getValue(e2);
|
||||
switch (op) {
|
||||
case OpAdd: e1 + e2;
|
||||
case OpSub: e1 - e2;
|
||||
case OpMult: e1 * e2;
|
||||
case OpDiv: e1 / e2;
|
||||
case OpMod: e1 % e2;
|
||||
case OpEq: e1 == e2;
|
||||
case OpNotEq: e1 != e2;
|
||||
case OpLt: e1 < e2;
|
||||
case OpLte: e1 <= e2;
|
||||
case OpGt: e1 > e2;
|
||||
case OpGte: e1 >= e2;
|
||||
case OpOr: e1 | e2;
|
||||
case OpAnd: e1 & e2;
|
||||
case OpXor: e1 ^ e2;
|
||||
case OpBoolAnd: e1 && e2;
|
||||
case OpBoolOr: e1 || e2;
|
||||
case OpShl: e1 << e2;
|
||||
case OpShr: e1 >> e2;
|
||||
case OpUShr: e1 >>> e2;
|
||||
case _: throw 'Unsupported expression: $e';
|
||||
}
|
||||
case _: throw 'Unsupported expression: $e';
|
||||
}
|
||||
}
|
||||
|
||||
static inline function opt(e:Null<Expr>, f:Expr->Expr):Expr
|
||||
return e == null ? null : f(e);
|
||||
|
||||
static inline function opt2(e:Null<Expr>, f:Expr->Void):Void
|
||||
if (e != null)
|
||||
f(e);
|
||||
}
|
||||
|
||||
/**
|
||||
This class provides functions on expression arrays for convenience. For a
|
||||
detailed reference on each method, see the documentation of ExprTools.
|
||||
**/
|
||||
class ExprArrayTools {
|
||||
static public function map(el:Array<Expr>, f:Expr->Expr):Array<Expr> {
|
||||
var ret = [];
|
||||
for (e in el)
|
||||
ret.push(f(e));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static public function iter(el:Array<Expr>, f:Expr->Void):Void {
|
||||
for (e in el)
|
||||
f(e);
|
||||
}
|
||||
}
|
119
Kha/Tools/macos/std/haxe/macro/Format.hx
Normal file
119
Kha/Tools/macos/std/haxe/macro/Format.hx
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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;
|
||||
import haxe.macro.Context;
|
||||
|
||||
/**
|
||||
The actual macro implemented for Std.format
|
||||
**/
|
||||
class Format {
|
||||
#if (macro || display)
|
||||
public static function format(estr:Expr) {
|
||||
var str = switch (estr.expr) {
|
||||
case EConst(c): switch (c) {
|
||||
case CString(s): s;
|
||||
default: null;
|
||||
}
|
||||
default: null;
|
||||
};
|
||||
if (str == null)
|
||||
Context.error("Constant string required", estr.pos);
|
||||
var pos = Context.getPosInfos(estr.pos);
|
||||
var min = pos.min;
|
||||
pos.min++;
|
||||
var expr = null;
|
||||
function make(size) {
|
||||
pos.max = pos.min + size;
|
||||
var p = Context.makePosition(pos);
|
||||
pos.min += size;
|
||||
return p;
|
||||
}
|
||||
function add(e) {
|
||||
if (expr == null)
|
||||
expr = e;
|
||||
else
|
||||
expr = {expr: EBinop(OpAdd, expr, e), pos: Context.makePosition({min: min, max: pos.min, file: pos.file})};
|
||||
}
|
||||
var i = 0, start = 0;
|
||||
var max = str.length;
|
||||
while (i < max) {
|
||||
if (StringTools.fastCodeAt(str, i++) != '$'.code)
|
||||
continue;
|
||||
var len = i - start - 1;
|
||||
if (len > 0 || expr == null)
|
||||
add({expr: EConst(CString(str.substr(start, len))), pos: make(len)});
|
||||
pos.min++;
|
||||
start = i;
|
||||
var c = StringTools.fastCodeAt(str, i);
|
||||
if (c == '{'.code) {
|
||||
var count = 1;
|
||||
i++;
|
||||
while (i < max) {
|
||||
var c = StringTools.fastCodeAt(str, i++);
|
||||
if (c == "}".code) {
|
||||
if (--count == 0)
|
||||
break;
|
||||
} else if (c == "{".code)
|
||||
count++;
|
||||
}
|
||||
if (count > 0)
|
||||
Context.error("Closing brace not found", make(1));
|
||||
pos.min++;
|
||||
start++;
|
||||
var len = i - start - 1;
|
||||
var expr = str.substr(start, len);
|
||||
add(Context.parseInlineString(expr, make(len)));
|
||||
pos.min++;
|
||||
start++;
|
||||
} else if ((c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || c == '_'.code) {
|
||||
i++;
|
||||
while (true) {
|
||||
var c = StringTools.fastCodeAt(str, i);
|
||||
if ((c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || (c >= '0'.code && c <= '9'.code) || c == '_'.code)
|
||||
i++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
var len = i - start;
|
||||
var ident = str.substr(start, len);
|
||||
add({expr: EConst(CIdent(ident)), pos: make(len)});
|
||||
} else if (c == '$'.code) {
|
||||
start = i++;
|
||||
continue;
|
||||
} else {
|
||||
start = i - 1;
|
||||
continue;
|
||||
}
|
||||
start = i;
|
||||
}
|
||||
var len = i - start;
|
||||
if (len > 0)
|
||||
add({expr: EConst(CString(str.substr(start, len))), pos: make(len)});
|
||||
if (expr == null)
|
||||
expr = {expr: EConst(CString("")), pos: make(0)};
|
||||
return {expr: ECheckType(expr, TPath({pack: [], name: "String", params: []})), pos: expr.pos};
|
||||
}
|
||||
#end
|
||||
}
|
66
Kha/Tools/macos/std/haxe/macro/JSGenApi.hx
Normal file
66
Kha/Tools/macos/std/haxe/macro/JSGenApi.hx
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.Type;
|
||||
|
||||
/**
|
||||
This is the api that is passed to the custom JS generator.
|
||||
**/
|
||||
typedef JSGenApi = {
|
||||
/** the file in which the JS code can be generated **/
|
||||
var outputFile:String;
|
||||
|
||||
/** all the types that were compiled by Haxe **/
|
||||
var types:Array<Type>;
|
||||
|
||||
/** the main call expression, if a -main class is defined **/
|
||||
var main:Null<TypedExpr>;
|
||||
|
||||
/** generate the JS code for any given typed expression **/
|
||||
function generateStatement(e:TypedExpr):String;
|
||||
|
||||
/** generate the JS code for a given typed expression-value **/
|
||||
function generateValue(e:TypedExpr):String;
|
||||
|
||||
/** define the JS code that gets generated when a class or enum is accessed in a typed expression **/
|
||||
function setTypeAccessor(callb:Type->String):Void;
|
||||
|
||||
/** tells if the given identifier is a JS keyword **/
|
||||
function isKeyword(ident:String):Bool;
|
||||
|
||||
/** add a feature **/
|
||||
function addFeature(f:String):Bool;
|
||||
|
||||
/** check if a feature is used **/
|
||||
function hasFeature(f:String):Bool;
|
||||
|
||||
/** quote and escape the given string constant **/
|
||||
function quoteString(s:String):String;
|
||||
|
||||
/** create the metadata expression for the given type **/
|
||||
function buildMetaData(t:BaseType):Null<TypedExpr>;
|
||||
|
||||
/** select the current classe **/
|
||||
function setCurrentClass(c:ClassType):Void;
|
||||
}
|
99
Kha/Tools/macos/std/haxe/macro/MacroStringTools.hx
Normal file
99
Kha/Tools/macos/std/haxe/macro/MacroStringTools.hx
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to work with strings in macro
|
||||
context.
|
||||
**/
|
||||
#if hl
|
||||
@:hlNative("macro")
|
||||
#end
|
||||
class MacroStringTools {
|
||||
#if (macro || display)
|
||||
/**
|
||||
Formats `String` `s` using the usual interpolation rules.
|
||||
|
||||
The returned expression is a concatenation of string parts and escaped
|
||||
elements.
|
||||
**/
|
||||
static public function formatString(s:String, pos:Position):Expr {
|
||||
#if (neko || eval)
|
||||
return Context.load("format_string", 2)(s, pos);
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
Tells if `e` is a format string, i.e. uses single quotes `'` as
|
||||
delimiters.
|
||||
**/
|
||||
static public function isFormatExpr(e:ExprOf<String>):Bool {
|
||||
return e.expr.match(EConst(CString(_, SingleQuotes)));
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
Converts an array of Strings `sl` to a field expression.
|
||||
|
||||
If `sl` has no elements, the result is null.
|
||||
|
||||
If `sl` has one element, the result is `EConst(CIdent(sl[0])`.
|
||||
|
||||
Otherwise the result is a chain of `EField` nodes.
|
||||
|
||||
If `sl` is null, the result is unspecified.
|
||||
**/
|
||||
static public function toFieldExpr(sl:Array<String>, ?pos):Expr {
|
||||
if (pos == null)
|
||||
return Lambda.fold(sl, function(s, e) return e == null ? (macro $i{s}) : (macro $e.$s), null);
|
||||
var e = null;
|
||||
for (v in sl)
|
||||
if (e == null)
|
||||
e = {expr: EConst(CIdent(v)), pos: pos};
|
||||
else
|
||||
e = {expr: EField(e, v), pos: pos};
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
Converts a path given by package `pack` and name `name` to a `String`
|
||||
separated by dots.
|
||||
|
||||
If `pack` has no elements, the result is `name`.
|
||||
|
||||
If `pack` is null, the result is unspecified.
|
||||
|
||||
Otherwise the elements of `pack` are joined with a separating dot, with
|
||||
an appended dot separating the result from `name`.
|
||||
**/
|
||||
static public function toDotPath(pack:Array<String>, name:String):String {
|
||||
return if (pack.length == 0) name else pack.join(".") + "." + name;
|
||||
}
|
||||
|
||||
static public function toComplex(path:String):ComplexType {
|
||||
var pack = path.split(".");
|
||||
return TPath({pack: pack, name: pack.pop(), params: []});
|
||||
}
|
||||
}
|
29
Kha/Tools/macos/std/haxe/macro/MacroType.hx
Normal file
29
Kha/Tools/macos/std/haxe/macro/MacroType.hx
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
This type is meant to be used to generate custom types using a macro.
|
||||
For instance by doing MacroType<[my.Class.myMacro(55)]>
|
||||
**/
|
||||
extern class MacroType<Const> {}
|
74
Kha/Tools/macos/std/haxe/macro/PositionTools.hx
Normal file
74
Kha/Tools/macos/std/haxe/macro/PositionTools.hx
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.display.Position.Location;
|
||||
import haxe.macro.Expr;
|
||||
|
||||
class PositionTools {
|
||||
/**
|
||||
Returns the `Position` where the caller of `here` is.
|
||||
**/
|
||||
macro public static function here():ExprOf<Position> {
|
||||
var positionExpr = Context.makeExpr(Context.getPosInfos(Context.currentPos()), Context.currentPos());
|
||||
if (Context.defined("macro")) {
|
||||
return macro haxe.macro.Context.makePosition($positionExpr);
|
||||
} else {
|
||||
return positionExpr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Like `Context.getPosInfos`, except this method is available on all platforms.
|
||||
**/
|
||||
public static function getInfos(p:Position):{min:Int, max:Int, file:String} {
|
||||
#if macro
|
||||
return Context.getPosInfos(p);
|
||||
#else
|
||||
return p;
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
Like `Context.makePosition`, except this method is available on all platforms.
|
||||
**/
|
||||
public static function make(inf:{min:Int, max:Int, file:String}):Position {
|
||||
#if macro
|
||||
return Context.makePosition(inf);
|
||||
#else
|
||||
return inf;
|
||||
#end
|
||||
}
|
||||
|
||||
#if (macro || display)
|
||||
/**
|
||||
Converts a `haxe.macro.Position` to a `haxe.display.Position.Location`.
|
||||
|
||||
This operation requires the source file the be known to the Haxe lexer in order
|
||||
to determine line breaks. It is thus only available in macro context.
|
||||
**/
|
||||
public static function toLocation(p:Position):Location {
|
||||
return Context.load("position_to_range", 1)(p);
|
||||
}
|
||||
#end
|
||||
}
|
564
Kha/Tools/macos/std/haxe/macro/Printer.hx
Normal file
564
Kha/Tools/macos/std/haxe/macro/Printer.hx
Normal file
@ -0,0 +1,564 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
using Lambda;
|
||||
using StringTools;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to convert elements from the
|
||||
macro context to a human-readable String representation.
|
||||
*/
|
||||
class Printer {
|
||||
var tabs:String;
|
||||
var tabString:String;
|
||||
|
||||
public function new(?tabString = "\t") {
|
||||
tabs = "";
|
||||
this.tabString = tabString;
|
||||
}
|
||||
|
||||
public function printUnop(op:Unop)
|
||||
return switch (op) {
|
||||
case OpIncrement: "++";
|
||||
case OpDecrement: "--";
|
||||
case OpNot: "!";
|
||||
case OpNeg: "-";
|
||||
case OpNegBits: "~";
|
||||
case OpSpread: "...";
|
||||
}
|
||||
|
||||
public function printBinop(op:Binop)
|
||||
return switch (op) {
|
||||
case OpAdd: "+";
|
||||
case OpMult: "*";
|
||||
case OpDiv: "/";
|
||||
case OpSub: "-";
|
||||
case OpAssign: "=";
|
||||
case OpEq: "==";
|
||||
case OpNotEq: "!=";
|
||||
case OpGt: ">";
|
||||
case OpGte: ">=";
|
||||
case OpLt: "<";
|
||||
case OpLte: "<=";
|
||||
case OpAnd: "&";
|
||||
case OpOr: "|";
|
||||
case OpXor: "^";
|
||||
case OpBoolAnd: "&&";
|
||||
case OpBoolOr: "||";
|
||||
case OpShl: "<<";
|
||||
case OpShr: ">>";
|
||||
case OpUShr: ">>>";
|
||||
case OpMod: "%";
|
||||
case OpInterval: "...";
|
||||
case OpArrow: "=>";
|
||||
case OpIn: "in";
|
||||
case OpAssignOp(op):
|
||||
printBinop(op) + "=";
|
||||
}
|
||||
|
||||
function escapeString(s:String, delim:String) {
|
||||
return delim
|
||||
+ s.replace("\n", "\\n")
|
||||
.replace("\t", "\\t")
|
||||
.replace("\r", "\\r")
|
||||
.replace("'", "\\'")
|
||||
.replace('"', "\\\"") #if sys .replace("\x00", "\\x00") #end + delim;
|
||||
}
|
||||
|
||||
public function printFormatString(s:String) {
|
||||
return escapeString(s, "'");
|
||||
}
|
||||
|
||||
public function printString(s:String) {
|
||||
return escapeString(s, '"');
|
||||
}
|
||||
|
||||
public function printConstant(c:Constant)
|
||||
return switch (c) {
|
||||
case CString(s, SingleQuotes): printFormatString(s);
|
||||
case CString(s, _): printString(s);
|
||||
case CIdent(s), CInt(s), CFloat(s):
|
||||
s;
|
||||
case CRegexp(s, opt): '~/$s/$opt';
|
||||
}
|
||||
|
||||
public function printTypeParam(param:TypeParam)
|
||||
return switch (param) {
|
||||
case TPType(ct): printComplexType(ct);
|
||||
case TPExpr(e): printExpr(e);
|
||||
}
|
||||
|
||||
public function printTypePath(tp:TypePath)
|
||||
return (tp.pack.length > 0 ? tp.pack.join(".") + "." : "")
|
||||
+ tp.name
|
||||
+ (tp.sub != null ? '.${tp.sub}' : "")
|
||||
+ (tp.params == null ? "" : tp.params.length > 0 ? "<" + tp.params.map(printTypeParam).join(", ") + ">" : "");
|
||||
|
||||
// TODO: check if this can cause loops
|
||||
public function printComplexType(ct:ComplexType)
|
||||
return switch (ct) {
|
||||
case TPath(tp): printTypePath(tp);
|
||||
case TFunction(args, ret):
|
||||
var wrapArgumentsInParentheses = switch args {
|
||||
// type `:(a:X) -> Y` has args as [TParent(TNamed(...))], i.e `a:X` gets wrapped in `TParent()`. We don't add parentheses to avoid printing `:((a:X)) -> Y`
|
||||
case [TParent(t)]: false;
|
||||
// this case catches a single argument that's a type-path, so that `X -> Y` prints `X -> Y` not `(X) -> Y`
|
||||
case [TPath(_) | TOptional(TPath(_))]: false;
|
||||
default: true;
|
||||
}
|
||||
var argStr = args.map(printComplexType).join(", ");
|
||||
(wrapArgumentsInParentheses ? '($argStr)' : argStr) + " -> " + (switch ret {
|
||||
// wrap return type in parentheses if it's also a function
|
||||
case TFunction(_): '(${printComplexType(ret)})';
|
||||
default: (printComplexType(ret): String);
|
||||
});
|
||||
case TAnonymous(fields): "{ " + [for (f in fields) printField(f) + "; "].join("") + "}";
|
||||
case TParent(ct): "(" + printComplexType(ct) + ")";
|
||||
case TOptional(ct): "?" + printComplexType(ct);
|
||||
case TNamed(n, ct): n + ":" + printComplexType(ct);
|
||||
case TExtend(tpl, fields):
|
||||
var types = [for (t in tpl) "> " + printTypePath(t) + ", "].join("");
|
||||
var fields = [for (f in fields) printField(f) + "; "].join("");
|
||||
'{${types}${fields}}';
|
||||
case TIntersection(tl): tl.map(printComplexType).join(" & ");
|
||||
}
|
||||
|
||||
public function printMetadata(meta:MetadataEntry)
|
||||
return '@${meta.name}' + ((meta.params != null && meta.params.length > 0) ? '(${printExprs(meta.params, ", ")})' : "");
|
||||
|
||||
public function printAccess(access:Access)
|
||||
return switch (access) {
|
||||
case AStatic: "static";
|
||||
case APublic: "public";
|
||||
case APrivate: "private";
|
||||
case AOverride: "override";
|
||||
case AInline: "inline";
|
||||
case ADynamic: "dynamic";
|
||||
case AMacro: "macro";
|
||||
case AFinal: "final";
|
||||
case AExtern: "extern";
|
||||
case AAbstract: "abstract";
|
||||
case AOverload: "overload";
|
||||
}
|
||||
|
||||
public function printField(field:Field) {
|
||||
inline function orderAccess(access: Array<Access>) {
|
||||
// final should always be printed last
|
||||
// (does not modify input array)
|
||||
return access.has(AFinal) ? access.filter(a -> !a.match(AFinal)).concat([AFinal]) : access;
|
||||
}
|
||||
return (field.doc != null
|
||||
&& field.doc != "" ? "/**\n"
|
||||
+ tabs
|
||||
+ tabString
|
||||
+ StringTools.replace(field.doc, "\n", "\n" + tabs + tabString)
|
||||
+ "\n"
|
||||
+ tabs
|
||||
+ "**/\n"
|
||||
+ tabs : "")
|
||||
+ (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join('\n$tabs') + '\n$tabs' : "")
|
||||
+ (field.access != null && field.access.length > 0 ? orderAccess(field.access).map(printAccess).join(" ") + " " : "")
|
||||
+ switch (field.kind) {
|
||||
case FVar(t, eo): ((field.access != null && field.access.has(AFinal)) ? '' : 'var ') + '${field.name}' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = ");
|
||||
case FProp(get, set, t, eo): 'var ${field.name}($get, $set)' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = ");
|
||||
case FFun(func): 'function ${field.name}' + printFunction(func);
|
||||
}
|
||||
}
|
||||
|
||||
public function printTypeParamDecl(tpd:TypeParamDecl)
|
||||
return (tpd.meta != null && tpd.meta.length > 0 ? tpd.meta.map(printMetadata).join(" ") + " " : "")
|
||||
+ tpd.name
|
||||
+ (tpd.params != null && tpd.params.length > 0 ? "<" + tpd.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ (tpd.constraints != null && tpd.constraints.length > 0 ? ":(" + tpd.constraints.map(printComplexType).join(", ") + ")" : "");
|
||||
|
||||
public function printFunctionArg(arg:FunctionArg)
|
||||
return (arg.opt ? "?" : "") + arg.name + opt(arg.type, printComplexType, ":") + opt(arg.value, printExpr, " = ");
|
||||
|
||||
public function printFunction(func:Function, ?kind:FunctionKind) {
|
||||
var skipParentheses = switch func.args {
|
||||
case [{ type:null }]: kind == FArrow;
|
||||
case _: false;
|
||||
}
|
||||
return (func.params == null ? "" : func.params.length > 0 ? "<" + func.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ (skipParentheses ? "" : "(")
|
||||
+ func.args.map(printFunctionArg).join(", ")
|
||||
+ (skipParentheses ? "" : ")")
|
||||
+ (kind == FArrow ? " ->" : "")
|
||||
+ opt(func.ret, printComplexType, ":")
|
||||
+ opt(func.expr, printExpr, " ");
|
||||
}
|
||||
|
||||
public function printVar(v:Var) {
|
||||
var s = v.name + opt(v.type, printComplexType, ":") + opt(v.expr, printExpr, " = ");
|
||||
return switch v.meta {
|
||||
case null|[]: s;
|
||||
case meta: meta.map(printMetadata).join(" ") + " " + s;
|
||||
}
|
||||
}
|
||||
|
||||
public function printObjectFieldKey(of:ObjectField) {
|
||||
return switch (of.quotes) {
|
||||
case null | Unquoted: of.field;
|
||||
case Quoted: '"${of.field}"'; // TODO: Have to escape that?
|
||||
}
|
||||
}
|
||||
|
||||
public function printObjectField(of:ObjectField) {
|
||||
return '${printObjectFieldKey(of)} : ${printExpr(of.expr)}';
|
||||
}
|
||||
|
||||
public function printExpr(e:Expr)
|
||||
return e == null ? "#NULL" : switch (e.expr) {
|
||||
case EConst(c): printConstant(c);
|
||||
case EArray(e1, e2): '${printExpr(e1)}[${printExpr(e2)}]';
|
||||
case EBinop(op, e1, e2): '${printExpr(e1)} ${printBinop(op)} ${printExpr(e2)}';
|
||||
case EField(e1, n): '${printExpr(e1)}.$n';
|
||||
case EParenthesis(e1): '(${printExpr(e1)})';
|
||||
case EObjectDecl(fl):
|
||||
"{ " + fl.map(function(fld) return printObjectField(fld)).join(", ") + " }";
|
||||
case EArrayDecl(el): '[${printExprs(el, ", ")}]';
|
||||
case ECall(e1, el): '${printExpr(e1)}(${printExprs(el, ", ")})';
|
||||
case ENew(tp, el): 'new ${printTypePath(tp)}(${printExprs(el, ", ")})';
|
||||
case EUnop(op, true, e1): printExpr(e1) + printUnop(op);
|
||||
case EUnop(op, false, e1): printUnop(op) + printExpr(e1);
|
||||
case EFunction(FNamed(no,inlined), func): (inlined ? 'inline ' : '') + 'function $no' + printFunction(func);
|
||||
case EFunction(kind, func): (kind != FArrow ? "function" : "") + printFunction(func, kind);
|
||||
case EVars(vl): "var " + vl.map(printVar).join(", ");
|
||||
case EBlock([]): '{ }';
|
||||
case EBlock(el):
|
||||
var old = tabs;
|
||||
tabs += tabString;
|
||||
var s = '{\n$tabs' + printExprs(el, ';\n$tabs');
|
||||
tabs = old;
|
||||
s + ';\n$tabs}';
|
||||
case EFor(e1, e2): 'for (${printExpr(e1)}) ${printExpr(e2)}';
|
||||
case EIf(econd, eif, null): 'if (${printExpr(econd)}) ${printExpr(eif)}';
|
||||
case EIf(econd, eif, eelse): 'if (${printExpr(econd)}) ${printExpr(eif)} else ${printExpr(eelse)}';
|
||||
case EWhile(econd, e1, true): 'while (${printExpr(econd)}) ${printExpr(e1)}';
|
||||
case EWhile(econd, e1, false): 'do ${printExpr(e1)} while (${printExpr(econd)})';
|
||||
case ESwitch(e1, cl, edef):
|
||||
var old = tabs;
|
||||
tabs += tabString;
|
||||
var s = 'switch ${printExpr(e1)} {\n$tabs'
|
||||
+ cl.map(function(c) return 'case ${printExprs(c.values, ", ")}' + (c.guard != null ? ' if (${printExpr(c.guard)}):' : ":")
|
||||
+ (c.expr != null ? (opt(c.expr, printExpr)) + ";" : ""))
|
||||
.join('\n$tabs');
|
||||
if (edef != null)
|
||||
s += '\n${tabs}default:' + (edef.expr == null ? "" : printExpr(edef) + ";");
|
||||
tabs = old;
|
||||
s + '\n$tabs}';
|
||||
case ETry(e1, cl):
|
||||
'try ${printExpr(e1)}' + cl.map(function(c) return ' catch(${c.name}${c.type == null ? '' : (':' + printComplexType(c.type))}) ${printExpr(c.expr)}').join("");
|
||||
case EReturn(eo): "return" + opt(eo, printExpr, " ");
|
||||
case EBreak: "break";
|
||||
case EContinue: "continue";
|
||||
case EUntyped(e1): "untyped " + printExpr(e1);
|
||||
case EThrow(e1): "throw " + printExpr(e1);
|
||||
case ECast(e1, cto) if (cto != null): 'cast(${printExpr(e1)}, ${printComplexType(cto)})';
|
||||
case ECast(e1, _): "cast " + printExpr(e1);
|
||||
case EIs(e1, ct): '${printExpr(e1)} is ${printComplexType(ct)}';
|
||||
case EDisplay(e1, _): '#DISPLAY(${printExpr(e1)})';
|
||||
case EDisplayNew(tp): '#DISPLAY(${printTypePath(tp)})';
|
||||
case ETernary(econd, eif, eelse): '${printExpr(econd)} ? ${printExpr(eif)} : ${printExpr(eelse)}';
|
||||
case ECheckType(e1, ct): '(${printExpr(e1)} : ${printComplexType(ct)})';
|
||||
case EMeta({ name:":implicitReturn" }, { expr:EReturn(e1) }): printExpr(e1);
|
||||
case EMeta(meta, e1): printMetadata(meta) + " " + printExpr(e1);
|
||||
}
|
||||
|
||||
public function printExprs(el:Array<Expr>, sep:String) {
|
||||
return el.map(printExpr).join(sep);
|
||||
}
|
||||
|
||||
function printExtension(tpl:Array<TypePath>, fields:Array<Field>) {
|
||||
return '{\n$tabs>'
|
||||
+ tpl.map(printTypePath).join(',\n$tabs>')
|
||||
+ ","
|
||||
+ (fields.length > 0 ? ('\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}") : ("\n}"));
|
||||
}
|
||||
|
||||
function printStructure(fields:Array<Field>) {
|
||||
return fields.length == 0 ? "{ }" : '{\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}";
|
||||
}
|
||||
|
||||
public function printTypeDefinition(t:TypeDefinition, printPackage = true):String {
|
||||
var old = tabs;
|
||||
tabs = tabString;
|
||||
|
||||
var str = t == null ? "#NULL" : (printPackage && t.pack.length > 0 && t.pack[0] != "" ? "package " + t.pack.join(".") + ";\n" : "")
|
||||
+ (t.doc != null && t.doc != "" ? "/**\n" + tabString + StringTools.replace(t.doc, "\n", "\n" + tabString) + "\n**/\n" : "")
|
||||
+ (t.meta != null && t.meta.length > 0 ? t.meta.map(printMetadata).join(" ") + " " : "")
|
||||
+ (t.isExtern ? "extern " : "")
|
||||
+ switch (t.kind) {
|
||||
case TDEnum:
|
||||
"enum "
|
||||
+ t.name
|
||||
+ ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ " {\n"
|
||||
+ [
|
||||
for (field in t.fields)
|
||||
tabs
|
||||
+ (field.doc != null
|
||||
&& field.doc != "" ? "/**\n"
|
||||
+ tabs
|
||||
+ tabString
|
||||
+ StringTools.replace(field.doc, "\n", "\n" + tabs + tabString)
|
||||
+ "\n"
|
||||
+ tabs
|
||||
+ "**/\n"
|
||||
+ tabs : "")
|
||||
+ (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join(" ") + " " : "")
|
||||
+ (switch (field.kind) {
|
||||
case FVar(t, _): field.name + opt(t, printComplexType, ":");
|
||||
case FProp(_, _, _, _): throw "FProp is invalid for TDEnum.";
|
||||
case FFun(func): field.name + printFunction(func);
|
||||
})
|
||||
+ ";"].join("\n")
|
||||
+ "\n}";
|
||||
case TDStructure:
|
||||
"typedef "
|
||||
+ t.name
|
||||
+ ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ " = {\n"
|
||||
+ [
|
||||
for (f in t.fields) {
|
||||
tabs + printField(f) + ";";
|
||||
}
|
||||
].join("\n")
|
||||
+ "\n}";
|
||||
case TDClass(superClass, interfaces, isInterface, isFinal, isAbstract):
|
||||
(isFinal ? "final " : "")
|
||||
+ (isAbstract ? "abstract " : "")
|
||||
+ (isInterface ? "interface " : "class ")
|
||||
+ t.name
|
||||
+ (t.params != null && t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ (superClass != null ? " extends " + printTypePath(superClass) : "")
|
||||
+ (interfaces != null ? (isInterface ? [for (tp in interfaces) " extends " + printTypePath(tp)] : [
|
||||
for (tp in interfaces)
|
||||
" implements " + printTypePath(tp)
|
||||
]).join("") : "")
|
||||
+ " {\n"
|
||||
+ [
|
||||
for (f in t.fields) {
|
||||
tabs + printFieldWithDelimiter(f);
|
||||
}
|
||||
].join("\n")
|
||||
+ "\n}";
|
||||
case TDAlias(ct):
|
||||
"typedef "
|
||||
+ t.name
|
||||
+ ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ " = "
|
||||
+ (switch (ct) {
|
||||
case TExtend(tpl, fields): printExtension(tpl, fields);
|
||||
case TAnonymous(fields): printStructure(fields);
|
||||
case _: printComplexType(ct);
|
||||
})
|
||||
+ ";";
|
||||
case TDAbstract(tthis, from, to):
|
||||
"abstract "
|
||||
+ t.name
|
||||
+ ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "")
|
||||
+ (tthis == null ? "" : "(" + printComplexType(tthis) + ")")
|
||||
+ (from == null ? "" : [for (f in from) " from " + printComplexType(f)].join(""))
|
||||
+ (to == null ? "" : [for (t in to) " to " + printComplexType(t)].join(""))
|
||||
+ " {\n"
|
||||
+ [
|
||||
for (f in t.fields) {
|
||||
tabs + printFieldWithDelimiter(f);
|
||||
}
|
||||
].join("\n")
|
||||
+ "\n}";
|
||||
case TDField(kind, access):
|
||||
tabs = old;
|
||||
(access != null && access.length > 0 ? access.map(printAccess).join(" ") + " " : "")
|
||||
+ switch (kind) {
|
||||
case FVar(type, eo): ((access != null && access.has(AFinal)) ? '' : 'var ') + '${t.name}' + opt(type, printComplexType, " : ") + opt(eo, printExpr, " = ") + ";";
|
||||
case FProp(get, set, type, eo): 'var ${t.name}($get, $set)' + opt(type, printComplexType, " : ") + opt(eo, printExpr, " = ") + ";";
|
||||
case FFun(func): 'function ${t.name}' + printFunction(func) + switch func.expr { case {expr: EBlock(_)}: ""; case _: ";"; };
|
||||
}
|
||||
} tabs = old;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function printFieldWithDelimiter(f:Field):String {
|
||||
return printField(f) + switch (f.kind) {
|
||||
case FVar(_, _), FProp(_, _, _, _): ";";
|
||||
case FFun({expr: null}): ";";
|
||||
case FFun({expr: {expr: EBlock(_)}}): "";
|
||||
case FFun(_): ";";
|
||||
case _: "";
|
||||
};
|
||||
}
|
||||
|
||||
function opt<T>(v:T, f:T->String, prefix = "")
|
||||
return v == null ? "" : (prefix + f(v));
|
||||
|
||||
public function printExprWithPositions(e:Expr) {
|
||||
var buffer = new StringBuf();
|
||||
function format4(i:Int) {
|
||||
return StringTools.lpad(Std.string(i), " ", 4);
|
||||
}
|
||||
function loop(tabs:String, e:Expr) {
|
||||
function add(s:String, ?p = null) {
|
||||
if (p == null) {
|
||||
p = e.pos;
|
||||
}
|
||||
var p = #if macro haxe.macro.Context.getPosInfos(p) #else e.pos #end;
|
||||
buffer.add('${format4(p.min)}-${format4(p.max)} $tabs$s\n');
|
||||
}
|
||||
function loopI(e:Expr)
|
||||
loop(tabs + tabString, e);
|
||||
switch (e.expr) {
|
||||
case EConst(c):
|
||||
add(printConstant(c));
|
||||
case EArray(e1, e2):
|
||||
add("EArray");
|
||||
loopI(e1);
|
||||
loopI(e2);
|
||||
case EBinop(op, e1, e2):
|
||||
add("EBinop " + printBinop(op));
|
||||
loopI(e1);
|
||||
loopI(e2);
|
||||
case EField(e, field):
|
||||
add("EField " + field);
|
||||
loopI(e);
|
||||
case EParenthesis(e):
|
||||
add("EParenthesis");
|
||||
loopI(e);
|
||||
case EObjectDecl(fields):
|
||||
add("EObjectDecl");
|
||||
for (field in fields) {
|
||||
add(field.field); // TODO: we don't have the field pos?
|
||||
loopI(field.expr);
|
||||
}
|
||||
case EArrayDecl(values):
|
||||
add("EArrayDecl");
|
||||
values.iter(loopI);
|
||||
case ECall(e, params):
|
||||
add("ECall");
|
||||
loopI(e);
|
||||
params.iter(loopI);
|
||||
case ENew(tp, params):
|
||||
add("ENew " + printTypePath(tp));
|
||||
params.iter(loopI);
|
||||
case EUnop(op, postFix, e):
|
||||
add("EUnop " + printUnop(op));
|
||||
loopI(e);
|
||||
case EVars(vars):
|
||||
add("EVars");
|
||||
for (v in vars) {
|
||||
if (v.expr != null) {
|
||||
add(v.name);
|
||||
loopI(v.expr);
|
||||
}
|
||||
}
|
||||
case EFunction(_, f):
|
||||
add("EFunction");
|
||||
if (f.expr != null) {
|
||||
loopI(f.expr);
|
||||
}
|
||||
case EBlock(exprs):
|
||||
add("EBlock");
|
||||
exprs.iter(loopI);
|
||||
case EFor(it, expr):
|
||||
add("EFor");
|
||||
loopI(it);
|
||||
loopI(expr);
|
||||
case EIf(econd, eif, eelse):
|
||||
add("EIf");
|
||||
loopI(econd);
|
||||
loopI(eif);
|
||||
if (eelse != null) {
|
||||
loopI(eelse);
|
||||
}
|
||||
case EWhile(econd, e, normalWhile):
|
||||
add("EWhile");
|
||||
loopI(econd);
|
||||
loopI(e);
|
||||
case ESwitch(e, cases, edef):
|
||||
add("ESwitch");
|
||||
loopI(e);
|
||||
for (c in cases) {
|
||||
for (pat in c.values) {
|
||||
loop(tabs + tabString + tabString, pat);
|
||||
}
|
||||
if (c.expr != null) {
|
||||
loop(tabs + tabString + tabString + tabString, c.expr);
|
||||
}
|
||||
}
|
||||
if (edef != null) {
|
||||
loop(tabs + tabString + tabString + tabString, edef);
|
||||
}
|
||||
case ETry(e, catches):
|
||||
add("ETry");
|
||||
loopI(e);
|
||||
for (c in catches) {
|
||||
loop(tabs + tabString + tabString, c.expr);
|
||||
}
|
||||
case EReturn(e):
|
||||
add("EReturn");
|
||||
if (e != null) {
|
||||
loopI(e);
|
||||
}
|
||||
case EBreak:
|
||||
add("EBreak");
|
||||
case EContinue:
|
||||
add("EContinue");
|
||||
case EUntyped(e):
|
||||
add("EUntyped");
|
||||
loopI(e);
|
||||
case EThrow(e):
|
||||
add("EThrow");
|
||||
loopI(e);
|
||||
case ECast(e, t):
|
||||
add("ECast");
|
||||
loopI(e);
|
||||
case EIs(e, t):
|
||||
add("EIs");
|
||||
loopI(e);
|
||||
case EDisplay(e, displayKind):
|
||||
add("EDisplay");
|
||||
loopI(e);
|
||||
case EDisplayNew(t):
|
||||
add("EDisplayNew");
|
||||
case ETernary(econd, eif, eelse):
|
||||
add("ETernary");
|
||||
loopI(econd);
|
||||
loopI(eif);
|
||||
loopI(eelse);
|
||||
case ECheckType(e, t):
|
||||
add("ECheckType");
|
||||
loopI(e);
|
||||
case EMeta(s, e):
|
||||
add("EMeta " + printMetadata(s));
|
||||
loopI(e);
|
||||
}
|
||||
}
|
||||
loop("", e);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
54
Kha/Tools/macos/std/haxe/macro/Tools.hx
Normal file
54
Kha/Tools/macos/std/haxe/macro/Tools.hx
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
This class can be added via `using haxe.macro.Tools` in order to enable
|
||||
`using` functionality on these macro tool classes:
|
||||
|
||||
- `haxe.macro.ExprTools`
|
||||
- `haxe.macro.ComplexTypeTools`
|
||||
- `haxe.macro.TypeTools`
|
||||
- `haxe.macro.MacroStringTools`
|
||||
- `haxe.macro.TypedExprTools`
|
||||
- `haxe.macro.PositionTools`
|
||||
|
||||
@see <https://haxe.org/manual/lf-static-extension.html>
|
||||
**/
|
||||
@:dox(hide)
|
||||
typedef TExprTools = ExprTools;
|
||||
|
||||
@:dox(hide)
|
||||
typedef TComplexTypeTools = ComplexTypeTools;
|
||||
|
||||
@:dox(hide)
|
||||
typedef TTypeTools = TypeTools;
|
||||
|
||||
@:dox(hide)
|
||||
typedef TMacroStringTools = MacroStringTools;
|
||||
|
||||
@:dox(hide)
|
||||
typedef TTypedExprTools = TypedExprTools;
|
||||
|
||||
@:dox(hide)
|
||||
typedef TPositionTools = PositionTools;
|
1033
Kha/Tools/macos/std/haxe/macro/Type.hx
Normal file
1033
Kha/Tools/macos/std/haxe/macro/Type.hx
Normal file
File diff suppressed because it is too large
Load Diff
384
Kha/Tools/macos/std/haxe/macro/TypeTools.hx
Normal file
384
Kha/Tools/macos/std/haxe/macro/TypeTools.hx
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* 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.Context;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Type;
|
||||
|
||||
using Lambda;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to work with types. It is
|
||||
best used through 'using haxe.macro.TypeTools' syntax and then provides
|
||||
additional methods on haxe.macro.Type instances.
|
||||
**/
|
||||
#if hl
|
||||
@:hlNative("macro")
|
||||
#end
|
||||
class TypeTools {
|
||||
static function nullable(complexType:ComplexType):ComplexType
|
||||
return macro:Null<$complexType>;
|
||||
|
||||
static function toField(cf:ClassField):Field
|
||||
return {
|
||||
function varAccessToString(va:VarAccess, getOrSet:String):String
|
||||
return {
|
||||
switch (va) {
|
||||
case AccNormal | AccCtor: "default";
|
||||
case AccNo: "null";
|
||||
case AccNever: "never";
|
||||
case AccResolve: throw "Invalid TAnonymous";
|
||||
case AccCall: getOrSet;
|
||||
case AccInline: "default";
|
||||
case AccRequire(_, _): "default";
|
||||
}
|
||||
}
|
||||
var access = cf.isPublic ? [APublic] : [APrivate];
|
||||
if (cf.meta.has(":final")) {
|
||||
access.push(AFinal);
|
||||
}
|
||||
if (cf.params.length == 0)
|
||||
{
|
||||
name: cf.name,
|
||||
doc: cf.doc,
|
||||
access: access,
|
||||
kind: switch ([cf.kind, cf.type]) {
|
||||
case [FVar(read, write), ret]:
|
||||
FProp(varAccessToString(read, "get"), varAccessToString(write, "set"), toComplexType(ret), null);
|
||||
case [FMethod(_), TFun(args, ret)]:
|
||||
FFun({
|
||||
args: [
|
||||
for (a in args)
|
||||
{
|
||||
name: a.name,
|
||||
opt: a.opt,
|
||||
type: toComplexType(a.t),
|
||||
}
|
||||
],
|
||||
ret: toComplexType(ret),
|
||||
expr: null,
|
||||
});
|
||||
default:
|
||||
throw "Invalid TAnonymous";
|
||||
},
|
||||
pos: cf.pos,
|
||||
meta: cf.meta.get(),
|
||||
} else {
|
||||
throw "Invalid TAnonymous";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a syntax-level type corresponding to Type `t`.
|
||||
|
||||
This function is mostly inverse to `ComplexTypeTools.toType`, but may
|
||||
lose some information on types that do not have a corresponding syntax
|
||||
version, such as monomorphs. In these cases, the result is null.
|
||||
|
||||
If `t` is null, an internal exception is thrown.
|
||||
**/
|
||||
public static function toComplexType(type:Null<Type>):Null<ComplexType>
|
||||
return {
|
||||
#if macro
|
||||
Context.toComplexType(type);
|
||||
#else
|
||||
switch (type) {
|
||||
case null:
|
||||
null;
|
||||
case TMono(_.get() => t):
|
||||
t == null ? null : toComplexType(t);
|
||||
case TEnum(_.get() => baseType, params):
|
||||
TPath(toTypePath(baseType, params));
|
||||
case TInst(_.get() => classType, params):
|
||||
switch (classType.kind) {
|
||||
case KTypeParameter(_):
|
||||
TPath({
|
||||
name: classType.name,
|
||||
pack: [],
|
||||
});
|
||||
default:
|
||||
TPath(toTypePath(classType, params));
|
||||
}
|
||||
case TType(_.get() => baseType, params):
|
||||
TPath(toTypePath(baseType, params));
|
||||
case TFun(args, ret):
|
||||
TFunction([for (a in args) a.opt ? nullable(toComplexType(a.t)) : toComplexType(a.t)], toComplexType(ret));
|
||||
case TAnonymous(_.get() => {fields: fields}):
|
||||
TAnonymous([for (cf in fields) toField(cf)]);
|
||||
case TDynamic(t):
|
||||
if (t == null) {
|
||||
macro:Dynamic;
|
||||
} else {
|
||||
var ct = toComplexType(t);
|
||||
macro:Dynamic<$ct>;
|
||||
}
|
||||
case TLazy(f):
|
||||
toComplexType(f());
|
||||
case TAbstract(_.get() => baseType, params):
|
||||
TPath(toTypePath(baseType, params));
|
||||
default:
|
||||
throw "Invalid type";
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
static function toTypeParam(type:Type):TypeParam
|
||||
return {
|
||||
switch (type) {
|
||||
case TInst(_.get() => {kind: KExpr(e)}, _): TPExpr(e);
|
||||
case _: TPType(toComplexType(type));
|
||||
}
|
||||
}
|
||||
|
||||
static function toTypePath(baseType:BaseType, params:Array<Type>):TypePath
|
||||
return {
|
||||
var module = baseType.module;
|
||||
{
|
||||
pack: baseType.pack,
|
||||
name: module.substring(module.lastIndexOf(".") + 1),
|
||||
sub: baseType.name,
|
||||
params: [for (t in params) toTypeParam(t)],
|
||||
}
|
||||
}
|
||||
|
||||
#if (macro || display)
|
||||
/**
|
||||
Follows all typedefs of `t` to reach the actual type.
|
||||
|
||||
If `once` is true, this function does not call itself recursively,
|
||||
otherwise it does. This can be useful in cases where intermediate
|
||||
typedefs might be of interest.
|
||||
|
||||
Affected types are monomorphs `TMono` and typedefs `TType(t,pl)`.
|
||||
|
||||
If `t` is null, an internal exception is thrown.
|
||||
|
||||
Usage example:
|
||||
var t = Context.typeof(macro null); // TMono(<mono>)
|
||||
var ts = Context.typeof(macro "foo"); //TInst(String,[])
|
||||
Context.unify(t, ts);
|
||||
trace(t); // TMono(<mono>)
|
||||
trace(t.follow()); //TInst(String,[])
|
||||
**/
|
||||
static public inline function follow(t:Type, ?once:Bool):Type
|
||||
return Context.follow(t, once);
|
||||
|
||||
/**
|
||||
Like `follow`, follows all typedefs of `t` to reach the actual type.
|
||||
|
||||
Will however follow also abstracts to their underlying implementation,
|
||||
if they are not a @:coreType abstract
|
||||
|
||||
If `t` is null, an internal exception is thrown.
|
||||
|
||||
Usage example:
|
||||
var t = Context.typeof(macro new Map<String, String>());
|
||||
trace(t); // TAbstract(Map,[TInst(String,[]),TInst(String,[])])
|
||||
trace(t.followWithAbstracts()); // TInst(haxe.ds.StringMap, [TInst(String,[])])
|
||||
**/
|
||||
static public inline function followWithAbstracts(t:Type, once:Bool = false):Type
|
||||
return Context.followWithAbstracts(t, once);
|
||||
|
||||
/**
|
||||
Returns true if `t1` and `t2` unify, false otherwise.
|
||||
**/
|
||||
static public inline function unify(t1:Type, t2:Type):Bool
|
||||
return Context.unify(t1, t2);
|
||||
|
||||
/**
|
||||
Tries to extract the class instance stored inside `t`.
|
||||
|
||||
If `t` is a class instance `TInst(c,pl)`, c is returned.
|
||||
|
||||
If `t` is of a different type, an exception of type String is thrown.
|
||||
|
||||
If `t` is null, the result is null.
|
||||
**/
|
||||
static public function getClass(t:Type)
|
||||
return t == null ? null : switch (follow(t)) {
|
||||
case TInst(c, _): c.get();
|
||||
case _: throw "Class instance expected";
|
||||
}
|
||||
|
||||
/**
|
||||
Tries to extract the enum instance stored inside `t`.
|
||||
|
||||
If `t` is an enum instance `TEnum(e,pl)`, e is returned.
|
||||
|
||||
If `t` is of a different type, an exception of type String is thrown.
|
||||
|
||||
If `t` is null, the result is null.
|
||||
**/
|
||||
static public function getEnum(t:Type)
|
||||
return t == null ? null : switch (follow(t)) {
|
||||
case TEnum(e, _): e.get();
|
||||
case _: throw "Enum instance expected";
|
||||
}
|
||||
|
||||
/**
|
||||
Applies the type parameters `typeParameters` to type `t` with the given
|
||||
types `concreteTypes`.
|
||||
|
||||
This function replaces occurrences of type parameters in `t` if they are
|
||||
part of `typeParameters`. The array index of such a type parameter is
|
||||
then used to lookup the concrete type in `concreteTypes`.
|
||||
|
||||
If `typeParameters.length` is not equal to `concreteTypes.length`, an
|
||||
exception of type `String` is thrown.
|
||||
|
||||
If `typeParameters.length` is 0, `t` is returned unchanged.
|
||||
|
||||
If either argument is `null`, the result is unspecified.
|
||||
**/
|
||||
static public function applyTypeParameters(t:Type, typeParameters:Array<TypeParameter>, concreteTypes:Array<Type>):Type {
|
||||
if (typeParameters.length != concreteTypes.length)
|
||||
throw 'Incompatible arguments: ${typeParameters.length} type parameters and ${concreteTypes.length} concrete types';
|
||||
else if (typeParameters.length == 0)
|
||||
return t;
|
||||
#if (neko || eval)
|
||||
return Context.load("apply_params", 3)(typeParameters, concreteTypes, t);
|
||||
#else
|
||||
return applyParams(typeParameters, concreteTypes, t);
|
||||
#end
|
||||
}
|
||||
|
||||
#if !neko
|
||||
private static function applyParams(typeParameters:Array<TypeParameter>, concreteTypes:Array<Type>, t:Type):Type {
|
||||
return null;
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
Transforms `t` by calling `f` on each of its subtypes.
|
||||
|
||||
If `t` is a compound type, `f` is called on each of its components.
|
||||
|
||||
Otherwise `t` is returned unchanged.
|
||||
|
||||
The following types are considered compound:
|
||||
- TInst, TEnum, TType and TAbstract with type parameters
|
||||
- TFun
|
||||
- TAnonymous
|
||||
|
||||
If `t` or `f` are null, the result is unspecified.
|
||||
**/
|
||||
static public function map(t:Type, f:Type->Type):Type {
|
||||
return switch (t) {
|
||||
case TMono(tm):
|
||||
switch (tm.get()) {
|
||||
case null: t;
|
||||
case var t: f(t);
|
||||
}
|
||||
case TEnum(_, []) | TInst(_, []) | TType(_, []):
|
||||
t;
|
||||
case TEnum(en, tl):
|
||||
TEnum(en, tl.map(f));
|
||||
case TInst(cl, tl):
|
||||
TInst(cl, tl.map(f));
|
||||
case TType(t2, tl):
|
||||
TType(t2, tl.map(f));
|
||||
case TAbstract(a, tl):
|
||||
TAbstract(a, tl.map(f));
|
||||
case TFun(args, ret):
|
||||
TFun(args.map(function(arg) return {
|
||||
name: arg.name,
|
||||
opt: arg.opt,
|
||||
t: f(arg.t)
|
||||
}), f(ret));
|
||||
case TAnonymous(an):
|
||||
TAnonymous(Context.load("map_anon_ref", 2)(an, f));
|
||||
case TDynamic(t2):
|
||||
t == t2 ? t : TDynamic(f(t2));
|
||||
case TLazy(ft):
|
||||
var ft = ft();
|
||||
var ft2 = f(ft);
|
||||
ft == ft2 ? t : ft2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Calls function `f` on each component of type `t`.
|
||||
|
||||
If `t` is not a compound type, this operation has no effect.
|
||||
|
||||
The following types are considered compound:
|
||||
- TInst, TEnum, TType and TAbstract with type parameters
|
||||
- TFun
|
||||
- TAnonymous
|
||||
|
||||
If `t` or `f` are null, the result is unspecified.
|
||||
**/
|
||||
static public function iter(t:Type, f:Type->Void):Void {
|
||||
switch (t) {
|
||||
case TMono(tm):
|
||||
var t = tm.get();
|
||||
if (t != null)
|
||||
f(t);
|
||||
case TEnum(_, tl) | TInst(_, tl) | TType(_, tl) | TAbstract(_, tl):
|
||||
for (t in tl)
|
||||
f(t);
|
||||
case TDynamic(t2):
|
||||
if (t != t2)
|
||||
f(t2);
|
||||
case TLazy(ft):
|
||||
f(ft());
|
||||
case TAnonymous(an):
|
||||
for (field in an.get().fields)
|
||||
f(field.type);
|
||||
case TFun(args, ret):
|
||||
for (arg in args)
|
||||
f(arg.t);
|
||||
f(ret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Converts type `t` to a human-readable String representation.
|
||||
**/
|
||||
static public function toString(t:Type):String {
|
||||
#if (neko || eval)
|
||||
return Context.load("s_type", 1)(t);
|
||||
#else
|
||||
return null;
|
||||
#end
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
Resolves the field named `name` on class `c`.
|
||||
|
||||
If `isStatic` is true, the classes' static fields are checked. Otherwise
|
||||
the classes' member fields are checked.
|
||||
|
||||
If the field is found, it is returned. Otherwise if `c` has a super
|
||||
class, `findField` recursively checks that super class. Otherwise null
|
||||
is returned.
|
||||
|
||||
If any argument is null, the result is unspecified.
|
||||
**/
|
||||
static public function findField(c:ClassType, name:String, isStatic:Bool = false):Null<ClassField> {
|
||||
var field = (isStatic ? c.statics : c.fields).get().find(function(field) return field.name == name);
|
||||
return if (field != null) field; else if (c.superClass != null) findField(c.superClass.t.get(), name, isStatic); else null;
|
||||
}
|
||||
}
|
175
Kha/Tools/macos/std/haxe/macro/TypedExprTools.hx
Normal file
175
Kha/Tools/macos/std/haxe/macro/TypedExprTools.hx
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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.Type;
|
||||
|
||||
/**
|
||||
This class provides some utility methods to work with typed expressions.
|
||||
It is best used through 'using haxe.macro.TypedExprTools' syntax and then
|
||||
provides additional methods on `haxe.macro.TypedExpr` instances.
|
||||
**/
|
||||
class TypedExprTools {
|
||||
static function with(e:TypedExpr, ?edef:TypedExprDef, ?t:Type) {
|
||||
return {
|
||||
expr: edef == null ? e.expr : edef,
|
||||
pos: e.pos,
|
||||
t: t == null ? e.t : t
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the sub-expressions of `e` by calling `f` on each of them.
|
||||
|
||||
See `haxe.macro.ExprTools.map` for details on expression mapping in
|
||||
general. This function works the same way, but with a different data
|
||||
structure.
|
||||
**/
|
||||
static public function map(e:TypedExpr, f:TypedExpr->TypedExpr):TypedExpr {
|
||||
return switch (e.expr) {
|
||||
case TConst(_) | TLocal(_) | TBreak | TContinue | TTypeExpr(_) | TIdent(_): e;
|
||||
case TArray(e1, e2): with(e, TArray(f(e1), f(e2)));
|
||||
case TBinop(op, e1, e2): with(e, TBinop(op, f(e1), f(e2)));
|
||||
case TFor(v, e1, e2): with(e, TFor(v, f(e1), f(e2)));
|
||||
case TWhile(e1, e2, flag): with(e, TWhile(f(e1), f(e2), flag));
|
||||
case TThrow(e1): with(e, TThrow(f(e1)));
|
||||
case TEnumParameter(e1, ef, i): with(e, TEnumParameter(f(e1), ef, i));
|
||||
case TEnumIndex(e1): with(e, TEnumIndex(f(e1)));
|
||||
case TField(e1, fa): with(e, TField(f(e1), fa));
|
||||
case TParenthesis(e1): with(e, TParenthesis(f(e1)));
|
||||
case TUnop(op, pre, e1): with(e, TUnop(op, pre, f(e1)));
|
||||
case TArrayDecl(el): with(e, TArrayDecl(el.map(f)));
|
||||
case TNew(t, pl, el): with(e, TNew(t, pl, el.map(f)));
|
||||
case TBlock(el): with(e, TBlock(el.map(f)));
|
||||
case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return {name: field.name, expr: f(field.expr)})));
|
||||
case TCall(e1, el): with(e, TCall(f(e1), el.map(f)));
|
||||
case TVar(v, eo): with(e, TVar(v, eo == null ? null : f(eo)));
|
||||
case TFunction(fu): with(e, TFunction({t: fu.t, args: fu.args, expr: f(fu.expr)}));
|
||||
case TIf(e1, e2, e3): with(e, TIf(f(e1), f(e2), e3 == null ? null : f(e3)));
|
||||
case TSwitch(e1, cases,
|
||||
e2): with(e, TSwitch(f(e1), cases.map(function(c) return {values: c.values.map(f), expr: f(c.expr)}), e2 == null ? null : f(e2)));
|
||||
case TTry(e1, catches): with(e, TTry(f(e1), catches.map(function(c) return {v: c.v, expr: f(c.expr)})));
|
||||
case TReturn(e1): with(e, TReturn(e1 == null ? null : f(e1)));
|
||||
case TCast(e1, mt): with(e, TCast(f(e1), mt));
|
||||
case TMeta(m, e1): with(e, TMeta(m, f(e1)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Calls function `f` on each sub-expression of `e`.
|
||||
|
||||
See `haxe.macro.ExprTools.iter` for details on iterating expressions in
|
||||
general. This function works the same way, but with a different data
|
||||
structure.
|
||||
**/
|
||||
static public function iter(e:TypedExpr, f:TypedExpr->Void):Void {
|
||||
switch (e.expr) {
|
||||
case TConst(_) | TLocal(_) | TBreak | TContinue | TTypeExpr(_) | TIdent(_):
|
||||
case TArray(e1, e2) | TBinop(_, e1, e2) | TFor(_, e1, e2) | TWhile(e1, e2, _):
|
||||
f(e1);
|
||||
f(e2);
|
||||
case TThrow(e1) | TEnumParameter(e1, _, _) | TEnumIndex(e1) | TField(e1, _) | TParenthesis(e1) | TUnop(_, _, e1) | TCast(e1, _) | TMeta(_, e1):
|
||||
f(e1);
|
||||
case TArrayDecl(el) | TNew(_, _, el) | TBlock(el):
|
||||
for (e in el)
|
||||
f(e);
|
||||
case TObjectDecl(fl):
|
||||
for (field in fl)
|
||||
f(field.expr);
|
||||
case TCall(e1, el):
|
||||
f(e1);
|
||||
for (e in el)
|
||||
f(e);
|
||||
case TVar(_, e1) | TReturn(e1):
|
||||
if (e1 != null)
|
||||
f(e1);
|
||||
case TFunction(fu):
|
||||
f(fu.expr);
|
||||
case TIf(e1, e2, e3):
|
||||
f(e1);
|
||||
f(e2);
|
||||
if (e3 != null)
|
||||
f(e3);
|
||||
case TSwitch(e1, cases, e2):
|
||||
f(e1);
|
||||
for (c in cases) {
|
||||
for (v in c.values)
|
||||
f(v);
|
||||
f(c.expr);
|
||||
}
|
||||
if (e2 != null)
|
||||
f(e2);
|
||||
case TTry(e1, catches):
|
||||
f(e1);
|
||||
for (c in catches)
|
||||
f(c.expr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the sub-expressions of `e` by calling `f` on each of them.
|
||||
Additionally, types are mapped using `ft` and variables are mapped using
|
||||
`fv`.
|
||||
|
||||
See `haxe.macro.ExprTools.map` for details on expression mapping in
|
||||
general. This function works the same way, but with a different data
|
||||
structure.
|
||||
**/
|
||||
static public function mapWithType(e:TypedExpr, f:TypedExpr->TypedExpr, ft:Type->Type, fv:TVar->TVar):TypedExpr {
|
||||
return switch (e.expr) {
|
||||
case TConst(_) | TBreak | TContinue | TTypeExpr(_) | TIdent(_): with(e, ft(e.t));
|
||||
case TLocal(v): with(e, TLocal(fv(v)), ft(e.t));
|
||||
case TArray(e1, e2): with(e, TArray(f(e1), f(e2)), ft(e.t));
|
||||
case TBinop(op, e1, e2): with(e, TBinop(op, f(e1), f(e2)), ft(e.t));
|
||||
case TFor(v, e1, e2): with(e, TFor(fv(v), f(e1), f(e2)), ft(e.t));
|
||||
case TWhile(e1, e2, flag): with(e, TWhile(f(e1), f(e2), flag), ft(e.t));
|
||||
case TThrow(e1): with(e, TThrow(f(e1)), ft(e.t));
|
||||
case TEnumParameter(e1, ef, i): with(e, TEnumParameter(f(e1), ef, i), ft(e.t));
|
||||
case TEnumIndex(e1): with(e, TEnumIndex(f(e1)), ft(e.t));
|
||||
case TField(e1, fa): with(e, TField(f(e1), fa), ft(e.t));
|
||||
case TParenthesis(e1): with(e, TParenthesis(e1), ft(e.t));
|
||||
case TUnop(op, pre, e1): with(e, TUnop(op, pre, f(e1)), ft(e.t));
|
||||
case TArrayDecl(el): with(e, TArrayDecl(el.map(f)), ft(e.t));
|
||||
case TNew(t, pl, el): with(e, TNew(t, pl, el.map(f)), ft(e.t));
|
||||
case TBlock(el): with(e, TBlock(el.map(f)), ft(e.t));
|
||||
case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return {name: field.name, expr: f(field.expr)})), ft(e.t));
|
||||
case TCall(e1, el): with(e, TCall(f(e1), el.map(f)), ft(e.t));
|
||||
case TVar(v, eo): with(e, TVar(fv(v), eo == null ? null : f(eo)), ft(e.t));
|
||||
case TFunction(fu): with(e, TFunction({t: ft(fu.t), args: fu.args.map(function(arg) return {v: fv(arg.v), value: arg.value}), expr: f(fu.expr)}),
|
||||
ft(e.t));
|
||||
case TIf(e1, e2, e3): with(e, TIf(f(e1), f(e2), e3 == null ? null : f(e3)), ft(e.t));
|
||||
case TSwitch(e1, cases,
|
||||
e2): with(e, TSwitch(f(e1), cases.map(function(c) return {values: c.values.map(f), expr: f(c.expr)}), e2 == null ? null : f(e2)), ft(e.t));
|
||||
case TTry(e1, catches): with(e, TTry(f(e1), catches.map(function(c) return {v: fv(c.v), expr: f(c.expr)})), ft(e.t));
|
||||
case TReturn(e1): with(e, TReturn(e1 == null ? null : f(e1)), ft(e.t));
|
||||
case TCast(e1, mt): with(e, TCast(f(e1), mt), ft(e.t));
|
||||
case TMeta(m, e1): with(e, TMeta(m, f(e1)), ft(e.t));
|
||||
}
|
||||
}
|
||||
|
||||
#if (macro || display)
|
||||
static public function toString(t:TypedExpr, ?pretty = false):String {
|
||||
return @:privateAccess haxe.macro.Context.sExpr(t, pretty);
|
||||
}
|
||||
#end
|
||||
}
|
Reference in New Issue
Block a user