This commit is contained in:
Dante
2026-05-21 23:40:20 -07:00
parent 3e2915dff7
commit 877a69d844
5737 changed files with 29796 additions and 1589684 deletions

View File

@ -150,6 +150,23 @@ class EntryPoint {
flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, function(_) processEvents());
#elseif (target.threaded && !cppia)
//everything is delegated to sys.thread.EventLoop
#elseif lua
inline function luvRun(mode:String):Bool
return untyped __lua__('_hx_luv.run({0})', mode);
while (true) {
var nextTick = processEvents();
if(untyped __lua__('_hx_luv.loop_alive()')) {
if(nextTick < 0)
luvRun("once")
else
luvRun("nowait");
} else {
if (nextTick < 0)
break;
if (nextTick > 0)
sleepLock.wait(nextTick);
}
}
#elseif sys
while (true) {
var nextTick = processEvents();

View File

@ -40,6 +40,14 @@ abstract EnumFlags<T:EnumValue>(Int) {
this = i;
}
@:from static function from<T:EnumValue>(e:T) : EnumFlags<T> {
return new EnumFlags(1 << e.getIndex());
}
@:op(a|b) function or(f:haxe.EnumFlags<T>) : haxe.EnumFlags<T>;
@:op(a&b) function and(f:haxe.EnumFlags<T>) : haxe.EnumFlags<T>;
@:op(a^b) function xor(f:haxe.EnumFlags<T>) : haxe.EnumFlags<T>;
/**
Checks if the index of enum instance `v` is set.
@ -76,6 +84,22 @@ abstract EnumFlags<T:EnumValue>(Int) {
this &= 0xFFFFFFFF - (1 << Type.enumIndex(v));
}
/**
Depending on the value of `condition` sets (`condition=true`) or unsets (`condition=false`)
the index of enum instance `v`.
This method is optimized if `v` is an enum instance expression such as
`SomeEnum.SomeCtor`.
If `v` is `null`, the result is unspecified.
**/
public inline function setTo(v:T, condition:Bool):Void {
if(condition)
set(v)
else
unset(v);
}
/**
Convert a integer bitflag into a typed one (this is a no-op, it does not
have any impact on speed).

View File

@ -37,7 +37,7 @@ extern class EnumTools {
If `e` is inside a package, the package structure is returned dot-
separated, with another dot separating the enum name:
pack1.pack2.(...).packN.EnumName
If `e` is a sub-type of a Haxe module, that module is not part of the
@ -110,6 +110,11 @@ extern class EnumTools {
static inline function getConstructors<T>(e:Enum<T>):Array<String> {
return Type.getEnumConstructs(e);
}
#if (java && jvm)
@:noCompletion
extern static function values<T>(en:Enum<T>):java.NativeArray<java.lang.Enum<T>>;
#end
}
/**

View File

@ -25,7 +25,7 @@ package haxe;
/**
Cross-platform JSON API: it will automatically use the optimized native API if available.
Use `-D haxeJSON` to force usage of the Haxe implementation even if a native API is found:
This will provide extra encoding features such as enums (replaced by their index) and StringMaps.
This will provide extra encoding (but not decoding) features such as enums (replaced by their index) and StringMaps.
@see https://haxe.org/manual/std-Json.html
**/

View File

@ -60,11 +60,6 @@ class MainEvent {
@:access(haxe.MainEvent)
class MainLoop {
#if (target.threaded && !cppia)
static var eventLoopHandler:Null<EventHandler>;
static var mutex = new sys.thread.Mutex();
static var mainThread = Thread.current();
#end
static var pending:MainEvent;
@ -94,7 +89,7 @@ class MainLoop {
/**
Add a pending event to be run into the main loop.
**/
public static function add(f:Void->Void, priority = 0):MainEvent@:privateAccess {
public static function add(f:Void->Void, priority = 0) : MainEvent {
if (f == null)
throw "Event function is null";
var e = new MainEvent(f, priority);
@ -103,29 +98,9 @@ class MainLoop {
head.prev = e;
e.next = head;
pending = e;
injectIntoEventLoop(0);
return e;
}
static function injectIntoEventLoop(waitMs:Int) {
#if (target.threaded && !cppia)
mutex.acquire();
if(eventLoopHandler != null)
mainThread.events.cancel(eventLoopHandler);
eventLoopHandler = mainThread.events.repeat(
() -> {
mainThread.events.cancel(eventLoopHandler);
var wait = tick();
if(hasEvents()) {
injectIntoEventLoop(Std.int(wait * 1000));
}
},
waitMs
);
mutex.release();
#end
}
static function sortEvents() {
// pending = haxe.ds.ListSort.sort(pending, function(e1, e2) return e1.nextRun > e2.nextRun ? -1 : 1);
// we can't use directly ListSort because it requires prev/next to be public, which we don't want here

View File

@ -7,7 +7,7 @@ private typedef NativeRest<T> = Array<T>;
/**
A special type that represents a "rest" function argument.
The special `...` syntax can be used for convenience and improved readability:
```haxe

View File

@ -45,12 +45,12 @@ class SysTools {
**/
public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String {
// If there is no space, tab, back-slash, or double-quotes, and it is not an empty string.
if (!~/^[^ \t\\"]+$/.match(argument)) {
if (!~/^(\/)?[^ \t\/\\"]+$/.match(argument)) {
// Based on cpython's subprocess.list2cmdline().
// https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620
var result = new StringBuf();
var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == "";
var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == "" || argument.indexOf("/") > 0;
if (needquote)
result.add('"');

View File

@ -40,6 +40,11 @@ import sys.thread.EventLoop;
It is also possible to extend this class and override its `run()` method in
the child class.
Notice for threaded targets:
`Timer` instances require threads they were created in to run with Haxe's event loops.
Main thread of a Haxe program always contains an event loop. For other cases use
`sys.thread.Thread.createWithEventLoop` and `sys.thread.Thread.runWithEventLoop` methods.
**/
class Timer {
#if (flash || js)

View File

@ -0,0 +1,55 @@
package haxe.atomic;
#if !(target.atomics || core_api)
#error "Atomic operations are not supported on this target!"
#end
/**
Atomic boolean.
(js) The Atomics and SharedArrayBuffer objects need to be available. Errors will be thrown if this is not the case.
**/
@:coreApi
abstract AtomicBool(AtomicInt) {
private inline function toInt(v:Bool):Int {
return v ? 1 : 0;
}
private inline function toBool(v:Int):Bool {
return v == 1;
}
public inline function new(value:Bool):Void {
this = new AtomicInt(toInt(value));
}
/**
Atomically compares the value of `a` with `expected` and replaces `a` with `replacement` if they are equal..
Returns the original value of `a`.
**/
public inline function compareExchange(expected:Bool, replacement:Bool):Bool {
return toBool(this.compareExchange(toInt(expected), toInt(replacement)));
}
/**
Atomically exchanges `a` with `value`.
Returns the original value of `a`.
**/
public inline function exchange(value:Bool):Bool {
return toBool(this.exchange(toInt(value)));
}
/**
Atomically fetches the value of `a`.
**/
public inline function load():Bool {
return toBool(this.load());
}
/**
Atomically stores `value` into `a`.
Returns the value that has been stored.
**/
public inline function store(value:Bool):Bool {
return toBool(this.store(toInt(value)));
}
}

View File

@ -0,0 +1,67 @@
package haxe.atomic;
#if !(target.atomics || core_api)
#error "This target does not support atomic operations."
#end
/**
Atomic integer.
(js) The Atomics and SharedArrayBuffer objects need to be available. Errors will be thrown if this is not the case.
**/
@:coreType
abstract AtomicInt {
public function new(value:Int):Void;
/**
Atomically adds `b` to `a`.
Returns the original value of `a`.
**/
public function add(b:Int):Int;
/**
Atomically substracts `b` from `a`.
Returns the original value of `a`.
**/
public function sub(b:Int):Int;
/**
Atomically computes the bitwise and of `a` and `b` and stores it in `a`.
Returns the original value of `a`.
**/
public function and(b:Int):Int;
/**
Atomically computes the bitwise or of `a` and `b` and stores it in `a`.
Returns the original value of `a`.
**/
public function or(b:Int):Int;
/**
Atomically computes the bitwise xor of `a` and `b` and stores it in `a`.
Returns the original value of `a`.
**/
public function xor(b:Int):Int;
/**
Atomically compares the value of `a` with `expected` and replaces `a` with `replacement` if they are equal..
Returns the original value of `a`.
**/
public function compareExchange(expected:Int, replacement:Int):Int;
/**
Atomically exchanges `a` with `value`.
Returns the original value of `a`.
**/
public function exchange(value:Int):Int;
/**
Atomically fetches the value of `a`.
**/
public function load():Int;
/**
Atomically stores `value` into `a`.
Returns the value that has been stored.
**/
public function store(value:Int):Int;
}

View File

@ -0,0 +1,44 @@
package haxe.atomic;
#if !(target.atomics || core_api)
#error "This target does not support atomic operations."
#end
#if (js || hxcpp)
#error "JavaScript and Hxcpp do not support AtomicObject"
#end
/**
Atomic object. Use with care, this does not magically make it thread-safe to mutate objects.
Not supported on JavaScript or C++.
**/
@:coreType
abstract AtomicObject<T:{}> {
public function new(value:T):Void;
/**
Atomically compares the value of `a` with `expected` and replaces `a` with `replacement` if they are equal..
Returns the original value of `a`.
Note that comparison is done by reference, and not by value.
While this is expected for most objects, this might give unexpected behaviour for strings.
**/
public function compareExchange(expected:T, replacement:T):T;
/**
Atomically exchanges `a` with `value`.
Returns the original value of `a`.
**/
public function exchange(value:T):T;
/**
Atomically fetches the value of `a`.
**/
public function load():T;
/**
Atomically stores `value` into `a`.
Returns the value that has been stored.
**/
public function store(value:T):T;
}

View File

@ -0,0 +1,79 @@
// from vshaxe
package haxe.display;
import haxe.display.Position.Location;
import haxe.display.Position.Range;
import haxe.display.JsonModuleTypes;
enum abstract UnresolvedIdentifierSuggestion(Int) {
var UISImport;
var UISTypo;
}
enum abstract MissingFieldCauseKind<T>(String) {
final AbstractParent:MissingFieldCauseKind<{parent:JsonTypePathWithParams}>;
final ImplementedInterface:MissingFieldCauseKind<{parent:JsonTypePathWithParams}>;
final PropertyAccessor:MissingFieldCauseKind<{property:JsonClassField, isGetter:Bool}>;
final FieldAccess:MissingFieldCauseKind<{}>;
final FinalFields:MissingFieldCauseKind<{fields:Array<JsonClassField>}>;
}
typedef MissingFieldCause<T> = {
var kind:MissingFieldCauseKind<T>;
var args:T;
}
typedef MissingField = {
var field:JsonClassField;
var type:JsonType<Dynamic>;
/**
When implementing multiple interfaces, there can be field duplicates among them. This flag is only
true for the first such occurrence of a field, so that the "Implement all" code action doesn't end
up implementing the same field multiple times.
**/
var unique:Bool;
}
typedef MissingFieldDiagnostic = {
var fields:Array<MissingField>;
var cause:MissingFieldCause<Dynamic>;
}
typedef MissingFieldDiagnostics = {
var moduleType:JsonModuleType<Dynamic>;
var moduleFile:String;
var entries:Array<MissingFieldDiagnostic>;
}
enum abstract DiagnosticKind<T>(Int) from Int to Int {
final DKUnusedImport:DiagnosticKind<Void>;
final DKUnresolvedIdentifier:DiagnosticKind<Array<{kind:UnresolvedIdentifierSuggestion, name:String}>>;
final DKCompilerError:DiagnosticKind<String>;
final DKRemovableCode:DiagnosticKind<{description:String, range:Range}>;
final DKParserError:DiagnosticKind<String>;
final DeprecationWarning:DiagnosticKind<String>;
final InactiveBlock:DiagnosticKind<Void>;
final MissingFields:DiagnosticKind<MissingFieldDiagnostics>;
}
enum abstract DiagnosticSeverity(Int) {
var Error = 1;
var Warning;
var Information;
var Hint;
}
typedef Diagnostic<T> = {
var kind:DiagnosticKind<T>;
var range:Range;
var severity:DiagnosticSeverity;
var args:T;
var relatedInformation:Array<DiagnosticRelatedInformation>;
}
typedef DiagnosticRelatedInformation = {
var location:Location;
var message:String;
var depth:Int;
}

View File

@ -25,6 +25,7 @@ package haxe.display;
import haxe.display.JsonModuleTypes;
import haxe.display.Position;
import haxe.display.Protocol;
import haxe.ds.ReadOnlyArray;
/**
Methods of the JSON-RPC-based `--display` protocol in Haxe 4.
@ -32,6 +33,12 @@ import haxe.display.Protocol;
**/
@:publicFields
class DisplayMethods {
/**
The request is sent from the client to Haxe to get diagnostics for a specific file, a list of files or the whole project.
**/
static inline var Diagnostics = new HaxeRequestMethod<DiagnosticsParams, DiagnosticsResult>("display/diagnostics");
/**
The completion request is sent from the client to Haxe to request code completion.
Haxe automatically determines the type of completion to use based on the passed position, see `CompletionResultKind`.
@ -78,11 +85,20 @@ class DisplayMethods {
**/
static inline var SignatureHelp = new HaxeRequestMethod<SignatureHelpParams, SignatureHelpResult>("display/signatureHelp");
/**
The metadata request is sent from the client to Haxe to get a list of all registered metadata and their documentation.
**/
static inline var Metadata = new HaxeRequestMethod<MetadataParams, MetadataResult>("display/metadata");
/**
The defines request is sent from the client to Haxe to get a list of all registered defines and their documentation.
**/
static inline var Defines = new HaxeRequestMethod<DefinesParams, DefinesResult>("display/defines");
/*
TODO:
- finish completion
- diagnostics
- codeLens
- workspaceSymbols ("project/symbol"?)
*/
@ -295,6 +311,7 @@ typedef Metadata = {
var platforms:Array<Platform>;
var targets:Array<MetadataTarget>;
var internal:Bool;
var ?origin:String;
var ?links:Array<String>;
}
@ -305,6 +322,8 @@ typedef Define = {
var parameters:Array<String>;
var platforms:Array<Platform>;
var links:Array<String>;
var ?origin:String;
var ?deprecated:String;
}
typedef Keyword = {
@ -425,6 +444,17 @@ typedef PatternCompletion<T> = ToplevelCompletion<T> & {
var isOutermostPattern:Bool;
}
typedef DiagnosticsParams = {
var ?file:FsPath;
var ?contents:String;
var ?fileContents:Array<{file:FsPath, ?contents:String}>;
}
typedef DiagnosticsResult = Response<ReadOnlyArray<{
var file:FsPath;
var diagnostics:ReadOnlyArray<Diagnostic<Any>>;
}>>
enum abstract CompletionModeKind<T>(Int) {
var Field:CompletionModeKind<FieldCompletionSubject<Dynamic>>;
var StructureField;
@ -542,6 +572,20 @@ typedef SignatureItem = {
typedef SignatureHelpResult = Response<Null<SignatureItem>>;
typedef MetadataParams = {
var compiler:Bool;
var user:Bool;
}
typedef MetadataResult = Response<Array<Metadata>>;
typedef DefinesParams = {
var compiler:Bool;
var user:Bool;
}
typedef DefinesResult = Response<Array<Define>>;
/** General types **/
typedef PositionParams = FileParams & {
/** Unicode character offset in the file. **/

View File

@ -163,6 +163,7 @@ enum abstract JsonBinopKind<T>(String) {
var OpInterval;
var OpArrow;
var OpIn;
var OpNullCoal;
}
typedef JsonBinop<T> = {

View File

@ -41,6 +41,7 @@ class ServerMethods {
static inline var ModuleMemory = new HaxeRequestMethod<ModuleParams, Response<HaxeModuleMemoryResult>>("server/memory/module");
static inline var Modules = new HaxeRequestMethod<ContextParams, Response<Array<String>>>("server/modules");
static inline var Module = new HaxeRequestMethod<ModuleParams, Response<JsonModule>>("server/module");
static inline var Type = new HaxeRequestMethod<TypeParams, Response<JsonModuleType<Any>>>("server/type");
static inline var Files = new HaxeRequestMethod<ContextParams, Response<Array<JsonServerFile>>>("server/files");
static inline var ModuleCreated = new HaxeRequestMethod<FileParams, Response<NoData>>("server/moduleCreated");
}
@ -97,7 +98,9 @@ typedef JsonModule = {
final types:Array<JsonTypePath>;
final file:String;
final sign:String;
final dirty:Null<String>;
final dependencies:Array<ModuleId>;
final dependents:Array<ModuleId>;
}
typedef JsonServerFile = {
@ -108,7 +111,6 @@ typedef JsonServerFile = {
}
/* Memory */
typedef HaxeMemoryResult = {
final contexts:Array<{
final context:HaxeServerContext;
@ -165,3 +167,8 @@ typedef ContextParams = {
typedef ModuleParams = ContextParams & {
final path:String;
}
typedef TypeParams = ContextParams & {
final modulePath:String;
final typeName:String;
}

View File

@ -227,7 +227,7 @@ class BalancedTree<K, V> implements haxe.Constraints.IMap<K, V> {
}
public function toString() {
return root == null ? '{}' : '{${root.toString()}}';
return root == null ? "[]" : '[${root.toString()}]';
}
/**
@ -264,6 +264,6 @@ class TreeNode<K, V> {
return this == null ? 0 : _height;
public function toString() {
return (left == null ? "" : left.toString() + ", ") + '$key=$value' + (right == null ? "" : ", " + right.toString());
return (left == null ? "" : left.toString() + ", ") + '$key => $value' + (right == null ? "" : ", " + right.toString());
}
}

View File

@ -33,11 +33,25 @@ class EnumValueMap<K:EnumValue, V> extends haxe.ds.BalancedTree<K, V> implements
var d = k1.getIndex() - k2.getIndex();
if (d != 0)
return d;
#if hl
var a1 = @:privateAccess Type._enumParameters(k1);
var a2 = @:privateAccess Type._enumParameters(k2);
var ld = a1.length - a2.length;
if (ld != 0)
return ld;
for (i in 0...a1.length) {
var d = compareArg(a1[i], a2[i]);
if (d != 0)
return d;
}
return 0;
#else
var p1 = k1.getParameters();
var p2 = k2.getParameters();
if (p1.length == 0 && p2.length == 0)
return 0;
return compareArgs(p1, p2);
#end
}
function compareArgs(a1:Array<Dynamic>, a2:Array<Dynamic>):Int {

View File

@ -24,9 +24,7 @@ package haxe.ds;
import haxe.ds.StringMap;
import haxe.ds.IntMap;
import haxe.ds.HashMap;
import haxe.ds.ObjectMap;
import haxe.ds.WeakMap;
import haxe.ds.EnumValueMap;
import haxe.Constraints.IMap;

View File

@ -41,7 +41,7 @@ private typedef VectorData<T> =
eval.Vector<T>
#else
Array<T>
#end
#end;
/**
A Vector is a storage of fixed size. It can be faster than Array on some
@ -61,7 +61,7 @@ abstract Vector<T>(VectorData<T>) {
If `length` is less than or equal to 0, the result is unspecified.
**/
public inline function new(length:Int) {
extern overload public inline function new(length:Int) {
#if flash10
this = new flash.Vector<T>(length, true);
#elseif neko
@ -75,7 +75,7 @@ abstract Vector<T>(VectorData<T>) {
#elseif cpp
this = NativeArray.create(length);
#elseif python
this = python.Syntax.code("[{0}]*{1}", null, length);
this = python.Syntax.code("([{0}]*{1})", null, length);
#elseif lua
this = untyped __lua_table__({length: length});
#elseif eval
@ -86,6 +86,43 @@ abstract Vector<T>(VectorData<T>) {
#end
}
/**
Creates a new Vector of length `length` filled with `defaultValue` elements.
Can be faster than `new Vector(length)` for iteration on some targets for non-nullable elements.
If `length` is less than or equal to 0, the result is unspecified.
**/
extern overload public inline function new(length:Int, defaultValue:T):Vector<T> {
#if js
this = [for (_ in 0...length) defaultValue];
#elseif python
this = python.Syntax.code("([{0}]*{1})", defaultValue, length);
#else
#if flash10
this = new flash.Vector<T>(length, true);
#elseif neko
this = untyped __dollar__amake(length);
#elseif cs
this = new cs.NativeArray(length);
#elseif java
this = new java.NativeArray(length);
#elseif cpp
this = NativeArray.create(length);
#elseif lua
this = untyped __lua_table__({length: length});
#elseif eval
this = new eval.Vector(length);
#else
this = [];
untyped this.length = length;
#end
fill(defaultValue);
#end
}
/**
Returns the value at index `index`.
@ -141,6 +178,12 @@ abstract Vector<T>(VectorData<T>) {
#end
}
/**
Sets all `length` elements of `this` Vector to `value`.
**/
public inline function fill(value:T):Void
for (i in 0...length) this[i] = value;
/**
Copies `length` of elements from `src` Vector, beginning at `srcPos` to
`dest` Vector, beginning at `destPos`

View File

@ -128,8 +128,8 @@ class JsonPrinter {
} else
classString(v);
case TEnum(_):
var i:Dynamic = Type.enumIndex(v);
add(i);
var i = Type.enumIndex(v);
add(Std.string(i));
case TBool:
add(#if (php || jvm || hl) (v ? 'true' : 'false') #else v #end);
case TNull:
@ -165,16 +165,15 @@ class JsonPrinter {
function fieldsString(v:Dynamic, fields:Array<String>) {
addChar('{'.code);
var len = fields.length;
var last = len - 1;
var first = true;
var empty = true;
for (i in 0...len) {
var f = fields[i];
var value = Reflect.field(v, f);
if (Reflect.isFunction(value))
continue;
if (first) {
if (empty) {
nind++;
first = false;
empty = false;
} else
addChar(','.code);
newl();
@ -184,11 +183,11 @@ class JsonPrinter {
if (pretty)
addChar(' '.code);
write(f, value);
if (i == last) {
nind--;
newl();
ipad();
}
}
if (!empty) {
nind--;
newl();
ipad();
}
addChar('}'.code);
}

View File

@ -30,6 +30,7 @@ import haxe.io.Bytes;
class HttpJs extends haxe.http.HttpBase {
public var async:Bool;
public var withCredentials:Bool;
public var responseHeaders:Map<String, String>;
var req:js.html.XMLHttpRequest;
@ -53,6 +54,7 @@ class HttpJs extends haxe.http.HttpBase {
public override function request(?post:Bool) {
this.responseAsString = null;
this.responseBytes = null;
this.responseHeaders = null;
var r = req = js.Browser.createXMLHttpRequest();
var onreadystatechange = function(_) {
if (r.readyState != 4)
@ -73,6 +75,21 @@ class HttpJs extends haxe.http.HttpBase {
onStatus(s);
if (s != null && s >= 200 && s < 400) {
req = null;
// split headers and remove the last \r\n\r\n
var headers = r.getAllResponseHeaders().split('\r\n');
headers = headers.filter(h -> h != '');
// store response headers
responseHeaders = new haxe.ds.StringMap();
for (hline in headers) {
var a = hline.split(": ");
var hname = a.shift();
var hval = if (a.length == 1) a[0] else a.join(": ");
hval = StringTools.ltrim(StringTools.rtrim(hval));
responseHeaders.set(hname, hval);
}
success(Bytes.ofData(r.response));
} else if (s == null || (s == 0 && r.response == null)) {
req = null;

View File

@ -27,6 +27,8 @@ import js.node.Buffer;
import haxe.io.Bytes;
class HttpNodeJs extends haxe.http.HttpBase {
public var responseHeaders:Map<String, String>;
var req:js.node.http.ClientRequest;
public function new(url:String) {
@ -47,6 +49,7 @@ class HttpNodeJs extends haxe.http.HttpBase {
public override function request(?post:Bool) {
responseAsString = null;
responseBytes = null;
responseHeaders = null;
var parsedUrl = new js.node.url.URL(url);
var secure = (parsedUrl.protocol == "https:");
var host = parsedUrl.hostname;
@ -97,6 +100,14 @@ class HttpNodeJs extends haxe.http.HttpBase {
var buf = (data.length == 1 ? data[0] : Buffer.concat(data));
responseBytes = Bytes.ofData(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
req = null;
// store response headers
responseHeaders = new haxe.ds.StringMap();
for (field in Reflect.fields(res.headers))
{
responseHeaders.set(field, Reflect.field(res.headers, field));
}
if (s != null && s >= 200 && s < 400) {
success(responseBytes);
} else {

View File

@ -318,4 +318,5 @@ enum abstract Mime(String) from String to String {
var ApplicationXCompress = 'application/x-compress';
var MultipartXZip = 'multipart/x-zip';
var TextXScriptZsh = 'text/x-script.zsh';
var ImageAvif = 'image/avif';
}

View File

@ -27,18 +27,15 @@ class ArrayKeyValueIterator<T> {
var current:Int = 0;
var array:Array<T>;
#if !hl inline #end
public function new(array:Array<T>) {
public inline function new(array:Array<T>) {
this.array = array;
}
#if !hl inline #end
public function hasNext():Bool {
public inline function hasNext():Bool {
return current < array.length;
}
#if !hl inline #end
public function next():{key:Int,value:T} {
public inline function next():{key:Int,value:T} {
return {value:array[current], key:current++};
}
}

View File

@ -52,6 +52,10 @@ enum abstract ModuleCheckPolicy(Int) {
of the current module file.
**/
var NoCheckShadowing = 3;
/**
Retype the module's contents if its file is invalidated. This is currently experimental.
**/
var Retype = 4;
}
enum abstract ContextOptions(Int) {
@ -97,7 +101,9 @@ class CompilationServer {
**/
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);
Context.onAfterInitMacros(() -> {
@:privateAccess Compiler.load("server_add_module_check_policy", 4)(pathFilters, policy, recursive, contextOptions);
});
}
/**

View File

@ -22,6 +22,7 @@
package haxe.macro;
import haxe.display.Display;
import haxe.macro.Expr;
/**
@ -69,13 +70,16 @@ class Compiler {
**/
public static function define(flag:String, ?value:String) {
#if (neko || eval)
Context.assertInitMacro();
load("define", 2)(flag, value);
#end
}
#if (!neko && !eval)
@:deprecated("Will be removed in Haxe 5.0")
private static function typePatch(cl:String, f:String, stat:Bool, t:String) {}
@:deprecated("Will be removed in Haxe 5.0")
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) {}
@ -85,13 +89,18 @@ class Compiler {
Removes a (static) field from a given class by name.
An error is thrown when `className` or `field` is invalid.
**/
@:deprecated("Will be removed in Haxe 5.0")
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)
#if haxe_next
Context.onAfterInitMacros(() -> load("type_patch", 4)(className, field, isStatic == true, null));
#else
load("type_patch", 4)(className, field, isStatic == true, null);
#end
#else
typePatch(className, field, isStatic == true, null);
#end
@ -101,13 +110,18 @@ class Compiler {
Set the type of a (static) field at a given class by name.
An error is thrown when `className` or `field` is invalid.
**/
@:deprecated("Will be removed in Haxe 5.0")
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)
#if haxe_next
Context.onAfterInitMacros(() -> load("type_patch", 4)(className, field, isStatic == true, type));
#else
load("type_patch", 4)(className, field, isStatic == true, type);
#end
#else
typePatch(className, field, isStatic == true, type);
#end
@ -117,13 +131,18 @@ class Compiler {
Add metadata to a (static) field or class by name.
An error is thrown when `className` or `field` is invalid.
**/
@:deprecated
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)
#if haxe_next
Context.onAfterInitMacros(() -> load("meta_patch", 4)(meta, className, field, isStatic == true));
#else
load("meta_patch", 4)(meta, className, field, isStatic == true);
#end
#else
metaPatch(meta, className, field, isStatic == true);
#end
@ -136,6 +155,7 @@ class Compiler {
**/
public static function addClassPath(path:String) {
#if (neko || eval)
Context.assertInitMacro();
load("add_class_path", 1)(path);
#end
}
@ -162,6 +182,19 @@ class Compiler {
#end
}
/**
Returns all the configuration settings applied to the compiler.
Usage of this function outside a macro context returns `null`.
**/
public static function getConfiguration():Null<CompilerConfiguration> {
#if (neko || eval)
return load("get_configuration", 0)();
#else
return null;
#end
}
/**
Adds a native library depending on the platform (e.g. `-swf-lib` for Flash).
@ -169,6 +202,7 @@ class Compiler {
**/
public static function addNativeLib(name:String) {
#if (neko || eval)
Context.assertInitMacro();
load("add_native_lib", 1)(name);
#end
}
@ -192,6 +226,8 @@ class Compiler {
If you want to specify a different set of paths to search for modules, you can use the optional
argument `classPath`.
Usage of this function outside of initialization macros is deprecated and may cause compilation server issues.
@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.
@ -201,69 +237,74 @@ class Compiler {
@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);
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))
var skip = if (ignore == null) {
function(c) return false;
} else {
function(c:String) {
if (Lambda.has(ignoreString, c))
return true;
return false;
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());
}
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());
Context.assertInitMacro();
Context.onAfterInitMacros(() -> include(pack, rec, ignore, classPaths, strict));
}
/**
@ -340,6 +381,7 @@ class Compiler {
/**
Load a type patch file that can modify the field types within declared classes and enums.
**/
@:deprecated("Will be removed in Haxe 5.0")
public static function patchTypes(file:String):Void {
var file = Context.resolvePath(file);
var f = sys.io.File.read(file, true);
@ -450,6 +492,44 @@ class Compiler {
#end
}
/**
Reference a json file describing user-defined metadata
See https://github.com/HaxeFoundation/haxe/blob/development/src-json/meta.json
**/
public static function registerMetadataDescriptionFile(path:String, ?source:String):Void {
var f = sys.io.File.getContent(path);
var content:Array<MetadataDescription> = haxe.Json.parse(f);
for (m in content) registerCustomMetadata(m, source);
}
/**
Reference a json file describing user-defined defines
See https://github.com/HaxeFoundation/haxe/blob/development/src-json/define.json
**/
public static function registerDefinesDescriptionFile(path:String, ?source:String):Void {
var f = sys.io.File.getContent(path);
var content:Array<DefineDescription> = haxe.Json.parse(f);
for (d in content) registerCustomDefine(d, source);
}
/**
Register a custom medatada for documentation and completion purposes
**/
public static function registerCustomMetadata(meta:MetadataDescription, ?source:String):Void {
#if (neko || eval)
load("register_metadata_impl", 2)(meta, source);
#end
}
/**
Register a custom define for documentation purposes
**/
public static function registerCustomDefine(define:DefineDescription, ?source:String):Void {
#if (neko || eval)
load("register_define_impl", 2)(define, source);
#end
}
/**
Change the default JS output by using a custom generator callback
**/
@ -577,3 +657,108 @@ enum abstract NullSafetyMode(String) to String {
**/
var StrictThreaded;
}
typedef MetadataDescription = {
final metadata:String;
final doc:String;
/**
External resources for more information about this metadata.
**/
@:optional final links:Array<String>;
/**
List (small description) of parameters that this metadata accepts.
**/
@:optional final params:Array<String>;
/**
Haxe target(s) for which this metadata is used.
**/
@:optional final platforms:Array<Platform>;
/**
Places where this metadata can be applied.
**/
@:optional final targets:Array<MetadataTarget>;
}
typedef DefineDescription = {
final define:String;
final doc:String;
/**
External resources for more information about this define.
**/
@:optional final links:Array<String>;
/**
List (small description) of parameters that this define accepts.
**/
@:optional final params:Array<String>;
/**
Haxe target(s) for which this define is used.
**/
@:optional final platforms:Array<Platform>;
}
typedef CompilerConfiguration = {
/**
The version integer of the current Haxe compiler build.
**/
final version:Int;
/**
Returns an array of the arguments passed to the compiler from either the `.hxml` file or the command line.
**/
final args:Array<String>;
/**
If `--debug` mode is enabled, this is `true`.
**/
final debug:Bool;
/**
If `--verbose` mode is enabled, this is `true`.
**/
final verbose:Bool;
/**
If `--no-opt` is enabled, this is `false`.
**/
final foptimize:Bool;
/**
The target platform.
**/
final platform:haxe.display.Display.Platform;
/**
The compilation configuration for the target platform.
**/
final platformConfig:PlatformConfig;
/**
A list of paths being used for the standard library.
**/
final stdPath:Array<String>;
/**
The path of the class passed using the `-main` argument.
**/
final mainClass:TypePath;
/**
Special access rules for packages depending on the compiler configuration.
For example, the "java" package is "Forbidden" when the target platform is Python.
**/
final packageRules:Map<String,PackageRule>;
}
enum PackageRule {
Forbidden;
Directory(path:String);
Remap(path:String);
}

View File

@ -39,7 +39,7 @@ class ComplexTypeTools {
static public function toString(c:ComplexType):String
return new Printer().printComplexType(c);
#if (macro || display)
#if macro
/**
Returns a type corresponding to `c`.

View File

@ -47,45 +47,61 @@ class Context {
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);
public static function error(msg:String, pos:Position, ?depth:Int = 0):Dynamic {
return load("error", 2)(msg, pos, depth);
}
/**
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);
public static function fatalError(msg:String, pos:Position, ?depth:Int = 0):Dynamic {
return load("fatal_error", 2)(msg, pos, depth);
}
/**
Displays a compilation error `msg` at the given `Position` `pos`
without aborting the current macro call.
**/
public static function reportError(msg:String, pos:Position, ?depth:Int = 0):Void {
load("report_error", 2)(msg, pos, depth);
}
/**
Displays a compilation warning `msg` at the given `Position` `pos`.
**/
public static function warning(msg:String, pos:Position) {
load("warning", 2)(msg, pos);
public static function warning(msg:String, pos:Position, ?depth:Int = 0) {
load("warning", 2)(msg, pos, depth);
}
/**
Displays a compilation info `msg` at the given `Position` `pos`.
**/
public static function info(msg:String, pos:Position) {
load("info", 2)(msg, pos);
public static function info(msg:String, pos:Position, ?depth:Int = 0) {
load("info", 2)(msg, pos, depth);
}
/**
Gets a list of all current compilation info/warning messages.
**/
public static function getMessages() : Array<Message> {
return load("get_messages",0)();
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);
public static function filterMessages(predicate:Message->Bool) {
load("filter_messages", 1)(predicate);
}
/**
Check if compiler is past initializations macros or not.
When it is, configuration phase is over and parsing/typing can start.
**/
public static function initMacrosDone():Bool {
return load("init_macros_done", 0)();
}
/**
@ -119,6 +135,10 @@ class Context {
return load("contains_display_position", 1)(pos);
}
public static function getDisplayMode():DisplayMode {
return load("get_display_mode", 0)();
}
/**
Returns the position at which the macro was called.
**/
@ -126,6 +146,14 @@ class Context {
return load("current_pos", 0)();
}
/**
Get the call stack (excluding the call to `Context.getMacroStack()`
that led to current macro.
**/
public static function getMacroStack():Array<Position> {
return load("get_macro_stack", 0)();
}
/**
Returns the type which is expected at the place the macro is called.
@ -136,6 +164,7 @@ class Context {
macro is not an expression-macro.
**/
public static function getExpectedType():Null<Type> {
assertInitMacrosDone(false);
return load("get_expected_type", 0)();
}
@ -146,6 +175,7 @@ class Context {
Returns `null` if the current macro is not a `@:genericBuild` macro.
**/
public static function getCallArguments():Null<Array<Expr>> {
assertInitMacrosDone(false);
return load("get_call_arguments", 0)();
}
@ -155,6 +185,7 @@ class Context {
If no such class exists, `null` is returned.
**/
public static function getLocalClass():Null<Type.Ref<Type.ClassType>> {
assertInitMacrosDone(false);
var l:Type = load("get_local_type", 0)();
if (l == null)
return null;
@ -168,6 +199,7 @@ class Context {
Returns the current module path in/on which the macro was called.
**/
public static function getLocalModule():String {
assertInitMacrosDone(false);
return load("get_local_module", 0)();
}
@ -177,6 +209,7 @@ class Context {
If no such type exists, `null` is returned.
**/
public static function getLocalType():Null<Type> {
assertInitMacrosDone(false);
return load("get_local_type", 0)();
}
@ -186,6 +219,7 @@ class Context {
If no such method exists, `null` is returned.
**/
public static function getLocalMethod():Null<String> {
assertInitMacrosDone(false);
return load("get_local_method", 0)();
}
@ -196,6 +230,7 @@ class Context {
Modifying the returned array has no effect on the compiler.
**/
public static function getLocalUsing():Array<Type.Ref<Type.ClassType>> {
assertInitMacrosDone(false);
return load("get_local_using", 0)();
}
@ -205,6 +240,7 @@ class Context {
Modifying the returned array has no effect on the compiler.
**/
public static function getLocalImports():Array<ImportExpr> {
assertInitMacrosDone(false);
return load("get_local_imports", 0)();
}
@ -219,6 +255,7 @@ class Context {
**/
@:deprecated("Use Context.getLocalTVars() instead")
public static function getLocalVars():Map<String, Type> {
assertInitMacrosDone(false);
return load("local_vars", 1)(false);
}
@ -227,6 +264,7 @@ class Context {
of `Type`.
**/
public static function getLocalTVars():Map<String, Type.TVar> {
assertInitMacrosDone(false);
return load("local_vars", 1)(true);
}
@ -279,8 +317,13 @@ class Context {
declared class path has priority.
If no type can be found, an exception of type `String` is thrown.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function getType(name:String):Type {
assertInitMacrosDone();
return load("get_type", 1)(name);
}
@ -292,11 +335,44 @@ class Context {
declared class path has priority.
If no module can be found, an exception of type `String` is thrown.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function getModule(name:String):Array<Type> {
assertInitMacrosDone();
return load("get_module", 1)(name);
}
/**
Returns the typed expression of the call to the main function.
This function will only work in the generation phase. Any calls
made outside a function passed to `haxe.macro.Context.onGenerate`
or `haxe.macro.Context.onAfterGenerate` will return `null`.
**/
public static function getMainExpr():Null<TypedExpr> {
return load("get_main_expr", 0)();
}
/**
Returns an array of module types to be generated in the output.
This list may change depending on the phase of compilation and
should not be treated as conclusive until the generation phase.
Modifying the returned array has no effect on the compilation.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function getAllModuleTypes():Array<haxe.macro.Type.ModuleType> {
assertInitMacrosDone();
return load("get_module_types", 0)();
}
/**
Parses `expr` as Haxe code, returning the corresponding AST.
@ -334,6 +410,7 @@ class Context {
Returns a hashed MD5 signature of value `v`.
**/
public static function signature(v:Dynamic):String {
assertInitMacrosDone(false);
return load("signature", 1)(v);
}
@ -382,6 +459,22 @@ class Context {
load("on_after_typing", 1)(callback);
}
/**
Adds a callback function `callback` which is invoked after the compiler
is done running initialization macros, when typing begins.
`onAfterInitMacros` should be used to delay typer-dependant code from
your initalization macros, to properly separate configuration phase and
actual typing.
**/
public static function onAfterInitMacros(callback:Void->Void):Void {
if (Context.initMacrosDone()) {
callback();
} else {
load("on_after_init_macros", 1)(callback);
}
}
/**
Adds a callback function `callback` which is invoked when a type name
cannot be resolved.
@ -399,8 +492,13 @@ class Context {
Typing the expression may result in a compiler error which can be
caught using `try ... catch`.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function typeof(e:Expr):Type {
assertInitMacrosDone();
return load("typeof", 1)(e);
}
@ -408,9 +506,17 @@ class Context {
Types expression `e` and returns the corresponding `TypedExpr`.
Typing the expression may result in a compiler error which can be
caught using `try ... catch`.
caught using `try ... catch`. Note that not all compiler errors can
be caught this way because the compiler might delay various checks
to a later stage, at which point the exception handler is no longer
active.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function typeExpr(e:Expr):TypedExpr {
assertInitMacrosDone();
return load("type_expr", 1)(e);
}
@ -420,8 +526,13 @@ class Context {
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.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function resolveType(t:ComplexType, p:Position):Type {
assertInitMacrosDone();
return load("resolve_type", 2)(t, p);
}
@ -436,8 +547,13 @@ class Context {
/**
Tries to unify `t1` and `t2` and returns `true` if successful.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function unify(t1:Type, t2:Type):Bool {
assertInitMacrosDone();
return load("unify", 2)(t1, t2);
}
@ -445,8 +561,13 @@ class Context {
Follows a type.
See `haxe.macro.TypeTools.follow` for details.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function follow(t:Type, ?once:Bool):Type {
assertInitMacrosDone();
return load("follow", 2)(t, once);
}
@ -454,8 +575,13 @@ class Context {
Follows a type, including abstracts' underlying implementation
See `haxe.macro.TypeTools.followWithAbstracts` for details.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function followWithAbstracts(t:Type, once:Bool = false):Type {
assertInitMacrosDone();
return load("follow_with_abstracts", 2)(t, once);
}
@ -505,6 +631,7 @@ class Context {
This is only defined for `@:build/@:autoBuild` macros.
**/
public static function getBuildFields():Array<Field> {
assertInitMacrosDone(false);
return load("get_build_fields", 0)();
}
@ -514,11 +641,31 @@ class Context {
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.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function defineType(t:TypeDefinition, ?moduleDependency:String):Void {
assertInitMacrosDone();
load("define_type", 2)(t, moduleDependency);
}
/**
Creates and returns a new instance of monomorph (`TMono`) type.
Returned monomorph can be used with e.g. `Context.unify` to make the compiler
bind the monomorph to an actual type and let macro further process the resulting type.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function makeMonomorph():Type {
assertInitMacrosDone();
return load("make_monomorph", 0)();
}
/**
Defines a new module as `modulePath` with several `TypeDefinition`
`types`. This is analogous to defining a .hx file.
@ -526,12 +673,17 @@ class Context {
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.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function defineModule(modulePath:String, types:Array<TypeDefinition>, ?imports:Array<ImportExpr>, ?usings:Array<TypePath>):Void {
if (imports == null)
imports = [];
if (usings == null)
usings = [];
assertInitMacrosDone();
load("define_module", 4)(modulePath, types, imports, usings);
}
@ -539,8 +691,13 @@ class Context {
Returns a syntax-level expression corresponding to typed expression `t`.
This process may lose some information.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function getTypedExpr(t:Type.TypedExpr):Expr {
assertInitMacrosDone();
return load("get_typed_expr", 1)(t);
}
@ -555,8 +712,13 @@ class Context {
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.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function storeTypedExpr(t:Type.TypedExpr):Expr {
assertInitMacrosDone();
return load("store_typed_expr", 1)(t);
}
@ -574,11 +736,29 @@ class Context {
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.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function storeExpr(e:Expr):Expr {
assertInitMacrosDone();
return load("store_expr", 1)(e);
}
/**
This function works like `storeExpr`, but also returns access to the expression's
type through the `type` field of the return value.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function typeAndStoreExpr(e:Expr):{final type:Type.Ref<Type>; final expr:Expr;} {
assertInitMacrosDone();
return load("type_and_store_expr", 1)(e);
}
/**
Manually adds a dependency between module `modulePath` and an external
file `externFile`.
@ -587,9 +767,13 @@ class Context {
`externFile` has changed.
Has no effect if the compilation cache is not used.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function registerModuleDependency(modulePath:String, externFile:String) {
load("register_module_dependency", 2)(modulePath, externFile);
onAfterInitMacros(() -> load("register_module_dependency", 2)(modulePath, externFile));
}
/**
@ -606,10 +790,47 @@ class Context {
stopTimer();
```
**/
public static function timer(id:String):()->Void {
public static function timer(id:String):() -> Void {
return load("timer", 1)(id);
}
/**
Executes `code` in a context that has `imports` and `usings` added.
This is equivalent to temporarily having `import` and `using` statements in a file. These
are only active during the execution of `code` and do not affect anything afterwards. This
is true even if `code` throws an exception.
If any argument is `null`, the result is unspecified.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function withImports<X>(imports:Array<String>, usings:Array<String>, code:() -> X):X {
assertInitMacrosDone();
return load("with_imports", 3)(imports, usings, code);
}
/**
Executes `code` in a context that has some compiler options set, restore the compiler to its
default behavior afterwards.
`allowInlining`: enable or disable inlining during typing with `typeExpr`.
`allowTransform`: when disabled, the code typed with `typeExpr` will be almost exactly the same
as the input code. This will disable some abstract types transformations.
Usage of this function from initialization macros is deprecated and may
cause compilation server issues. Use `Context.onAfterInitMacros` to
run your code once typer is ready to be used.
**/
public static function withOptions<X>(options:{?allowInlining:Bool,?allowTransform:Bool}, code : () -> X) : X {
assertInitMacrosDone();
return load("with_options", 2)(options, code);
}
@:deprecated
public static function registerModuleReuseCall(modulePath:String, macroCall:String) {
throw "This method is no longer supported. See https://github.com/HaxeFoundation/haxe/issues/5746";
@ -639,7 +860,36 @@ class Context {
}
private static function sExpr(e:TypedExpr, pretty:Bool):String {
return haxe.macro.Context.load("s_expr", 2)(e, pretty);
return load("s_expr", 2)(e, pretty);
}
@:allow(haxe.macro.Compiler)
private static function assertInitMacro():Void {
if (initMacrosDone()) {
var stack = getMacroStack();
warning(
"This API should only be used from initialization macros.",
if (stack.length > 2) stack[2] else currentPos()
);
}
}
@:allow(haxe.macro.Compiler)
private static function assertInitMacrosDone(includeSuggestion = true):Void {
#if haxe_next
if (!initMacrosDone()) {
var stack = getMacroStack();
var suggestion = includeSuggestion
? "\nUse `Context.onAfterInitMacros` to register a callback to run when context is ready."
: "";
warning(
"Cannot use this API from initialization macros." + suggestion,
if (stack.length > 2) stack[2] else currentPos()
);
}
#end
}
#end
}

View File

@ -0,0 +1,15 @@
package haxe.macro;
enum DisplayMode {
None;
Default;
Definition;
TypeDefinition;
Implementation;
Package;
Hover;
References(withDefinition:Bool, findDescendants:Bool, findBase:Bool);
ModuleSymbols;
WorkspaceSymbols(filter:String);
Signature;
}

View File

@ -231,7 +231,13 @@ class ExampleJSGenerator {
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; };");
print(
#if (js_es < 5)
"function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; }"
#else
"function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = m.bind(o); o.hx__closures__[m.__id__] = f; } return f; }"
#end
);
newline();
for (t in api.types)
genType(t);

View File

@ -60,12 +60,12 @@ enum Constant {
/**
Represents an integer literal.
**/
CInt(v:String);
CInt(v:String, ?s:String);
/**
Represents a float literal.
**/
CFloat(f:String);
CFloat(f:String, ?s:String);
/**
Represents a string literal.
@ -214,6 +214,11 @@ enum Binop {
`in`
**/
OpIn;
/**
`??`
**/
OpNullCoal;
}
/**
@ -252,6 +257,11 @@ enum Unop {
OpSpread;
}
enum EFieldKind {
Normal;
Safe;
}
/**
Represents a node in the AST.
@see https://haxe.org/manual/macro-reification-expression.html
@ -306,6 +316,11 @@ typedef Var = {
**/
var name:String;
/**
The position of the variable name.
**/
var ?namePos:Position;
/**
The type-hint of the variable, if available.
**/
@ -321,6 +336,11 @@ typedef Var = {
**/
var ?isFinal:Bool;
/**
Whether or not the variable is static.
**/
var ?isStatic:Bool;
/**
Metadata associatied with the variable, if available.
**/
@ -424,8 +444,10 @@ enum ExprDef {
/**
Field access on `e.field`.
If `kind` is null, it is equal to Normal.
**/
EField(e:Expr, field:String);
EField(e:Expr, field:String, ?kind:EFieldKind);
/**
Parentheses `(e)`.
@ -545,11 +567,6 @@ enum ExprDef {
**/
EDisplay(e:Expr, displayKind:DisplayKind);
/**
Used internally to provide completion.
**/
EDisplayNew(t:TypePath);
/**
A `(econd) ? eif : eelse` expression.
**/
@ -681,6 +698,11 @@ typedef TypeParamDecl = {
**/
var ?constraints:Array<ComplexType>;
/**
The optional default type of the type parameter.
**/
var ?defaultType:Null<ComplexType>;
/**
The optional parameters of the type parameter.
**/
@ -977,7 +999,7 @@ enum TypeDefKind {
/**
Represents an abstract kind.
**/
TDAbstract(tthis:Null<ComplexType>, ?from:Array<ComplexType>, ?to:Array<ComplexType>);
TDAbstract(tthis:Null<ComplexType>, ?flags:Array<AbstractFlag>, ?from:Array<ComplexType>, ?to:Array<ComplexType>);
/**
Represents a module-level field.
@ -985,6 +1007,28 @@ enum TypeDefKind {
TDField(kind:FieldType, ?access:Array<Access>); // ignore TypeDefinition.fields
}
/**
Represents an abstract flag.
**/
enum AbstractFlag {
/**
Indicates that this abstract is an `enum abstract`
**/
AbEnum;
/**
Indicates that this abstract can be assigned from `ct`.
This flag can be added several times to add multiple "from" types.
**/
AbFrom(ct:ComplexType);
/**
Indicates that this abstract can be assigned to `ct`.
This flag can be added several times to add multiple "to" types.
**/
AbTo(ct:ComplexType);
}
/**
This error can be used to handle or produce compilation errors in macros.
**/
@ -994,6 +1038,11 @@ class Error extends Exception {
**/
public var pos:Position;
/**
Child error messages, if any.
**/
private var childErrors:Array<Error>;
/**
Instantiates an error with given message and position.
**/

View File

@ -70,7 +70,7 @@ class ExprTools {
**/
static public function iter(e:Expr, f:Expr->Void):Void {
switch (e.expr) {
case EConst(_), EContinue, EBreak, EDisplayNew(_):
case EConst(_), EContinue, EBreak:
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):
@ -144,7 +144,7 @@ class ExprTools {
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 EField(e, field, kind): EField(f(e), field, kind);
case EParenthesis(e): EParenthesis(f(e));
case EObjectDecl(fields):
var ret = [];
@ -161,6 +161,8 @@ class ExprTools {
var v2:Var = {name: v.name, type: v.type, expr: opt(v.expr, f)};
if (v.isFinal != null)
v2.isFinal = v.isFinal;
if (v.isStatic != null)
v2.isStatic = v.isStatic;
ret.push(v2);
}
EVars(ret);
@ -176,7 +178,7 @@ class ExprTools {
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:
case EContinue, EBreak:
e.expr;
case ETry(e, catches):
var ret = [];

View File

@ -32,7 +32,7 @@ import haxe.macro.Expr;
@:hlNative("macro")
#end
class MacroStringTools {
#if (macro || display)
#if macro
/**
Formats `String` `s` using the usual interpolation rules.

View File

@ -0,0 +1,206 @@
package haxe.macro;
import haxe.macro.Expr;
/**
Represents the internal structure generated with options assigned based on
the target platform.
Warning: `PlatformConfig` and the typedefs unique to its fields correspond to
compiler-internal data structures and might change in minor Haxe releases in
order to adapt to internal changes.
**/
typedef PlatformConfig = {
/**
Has a static type system, with not-nullable basic types (Int/Float/Bool)
**/
final staticTypeSystem:Bool;
/**
Has access to the "sys" package
**/
final sys:Bool;
/**
Captured variables handling (see before)
**/
final capturePolicy:CapturePolicy;
/**
When calling a method with optional args, do we replace the missing args with "null" constants
**/
final padNulls:Bool;
/**
Add a final return to methods not having one already - prevent some compiler warnings
**/
final addFinalReturn:Bool;
/**
Does the platform natively support overloaded functions
**/
final overloadFunctions:Bool;
/**
Can the platform use default values for non-nullable arguments
**/
final canSkipNonNullableArgument:Bool;
/**
Type paths that are reserved on the platform
**/
final reservedTypePaths:Array<TypePath>;
/**
Supports function == function
**/
final supportsFunctionEquality:Bool;
/**
Uses utf16 encoding with ucs2 api
**/
final usesUtf16:Bool;
/**
Target supports accessing `this` before calling `super(...)`
**/
final thisBeforeSuper:Bool;
/**
Target supports threads
**/
final supportsThreads:Bool;
/**
Target supports Unicode
**/
final supportsUnicode:Bool;
/**
Target supports rest arguments
**/
final supportsRestArgs:Bool;
/**
Exceptions handling config
**/
final exceptions:ExceptionsConfig;
/**
The scoping of local variables
**/
final scoping:VarScopingConfig;
/**
Target supports atomic operations via haxe.Atomic
**/
final supportsAtomics:Bool;
}
enum CapturePolicy {
/**
Do nothing, let the platform handle it
**/
None;
/**
Wrap all captured variables into a single-element array to allow modifications
**/
WrapRef;
/**
Similar to wrap ref, but will only apply to the locals that are declared in loops
**/
LoopVars;
}
typedef VarScopingConfig = {
final scope:VarScope;
final flags:Array<VarScopingFlags>;
}
enum VarScope {
FunctionScope;
BlockScope;
}
enum VarScopingFlags {
/**
Variables are hoisted in their scope
**/
VarHoisting;
/**
It's not allowed to shadow existing variables in a scope.
**/
NoShadowing;
/**
It's not allowed to shadow a `catch` variable.
**/
NoCatchVarShadowing;
/**
Local vars cannot have the same name as the current top-level package or
(if in the root package) current class name
**/
ReserveCurrentTopLevelSymbol;
/**
Local vars cannot have a name used for any top-level symbol
(packages and classes in the root package)
**/
ReserveAllTopLevelSymbols;
/**
Reserve all type-paths converted to "flat path" with `Path.flat_path`
**/
ReserveAllTypesFlat;
/**
List of names cannot be taken by local vars
**/
ReserveNames(names:Array<String>);
/**
Cases in a `switch` won't have blocks, but will share the same outer scope.
**/
SwitchCasesNoBlocks;
}
typedef ExceptionsConfig = {
/**
Base types which may be thrown from Haxe code without wrapping.
**/
final nativeThrows:Array<TypePath>;
/**
Base types which may be caught from Haxe code without wrapping.
**/
final nativeCatches:Array<TypePath>;
/**
Hint exceptions filter to avoid wrapping for targets, which can throw/catch any type
Ignored on targets with a specific native base type for exceptions.
**/
final avoidWrapping:Bool;
/**
Path of a native class or interface, which can be used for wildcard catches.
**/
final wildcardCatch:TypePath;
/**
Path of a native base class or interface, which can be thrown.
This type is used to cast `haxe.Exception.thrown(v)` calls to.
For example `throw 123` is compiled to `throw (cast Exception.thrown(123):ec_base_throw)`
**/
final baseThrow:TypePath;
/**
Checks if throwing this expression is a special case for current target
and should not be modified.
**/
// final specialThrow:(TypedExpr)->Bool;
}

View File

@ -60,7 +60,7 @@ class PositionTools {
#end
}
#if (macro || display)
#if macro
/**
Converts a `haxe.macro.Position` to a `haxe.display.Position.Location`.

View File

@ -75,13 +75,15 @@ class Printer {
case OpInterval: "...";
case OpArrow: "=>";
case OpIn: "in";
case OpNullCoal: "??";
case OpAssignOp(op):
printBinop(op) + "=";
}
function escapeString(s:String, delim:String) {
return delim
+ s.replace("\n", "\\n")
+ s.replace('\\', '\\\\')
.replace("\n", "\\n")
.replace("\t", "\\t")
.replace("\r", "\\r")
.replace("'", "\\'")
@ -100,8 +102,10 @@ class Printer {
return switch (c) {
case CString(s, SingleQuotes): printFormatString(s);
case CString(s, _): printString(s);
case CIdent(s), CInt(s), CFloat(s):
case CIdent(s), CInt(s, null), CFloat(s, null):
s;
case CInt(s, suffix), CFloat(s, suffix):
s + suffix;
case CRegexp(s, opt): '~/$s/$opt';
}
@ -192,7 +196,8 @@ class Printer {
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(", ") + ")" : "");
+ (tpd.constraints != null && tpd.constraints.length > 0 ? ":(" + tpd.constraints.map(printComplexType).join(", ") + ")" : "")
+ (tpd.defaultType != null ? "=" + printComplexType(tpd.defaultType) : "");
public function printFunctionArg(arg:FunctionArg)
return (arg.opt ? "?" : "") + arg.name + opt(arg.type, printComplexType, ":") + opt(arg.value, printExpr, " = ");
@ -235,7 +240,7 @@ class Printer {
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 EField(e1, n, kind): kind == Safe ? '${printExpr(e1)}?.$n' : '${printExpr(e1)}.$n';
case EParenthesis(e1): '(${printExpr(e1)})';
case EObjectDecl(fl):
"{ " + fl.map(function(fld) return printObjectField(fld)).join(", ") + " }";
@ -246,7 +251,8 @@ class Printer {
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 EVars([]): "var ";
case EVars(vl): ((vl[0].isStatic) ? "static " : "") + ((vl[0].isFinal) ? "final " : "var ") + vl.map(printVar).join(", ");
case EBlock([]): '{ }';
case EBlock(el):
var old = tabs;
@ -281,7 +287,6 @@ class Printer {
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);
@ -377,13 +382,28 @@ class Printer {
case _: printComplexType(ct);
})
+ ";";
case TDAbstract(tthis, from, to):
"abstract "
case TDAbstract(tthis, tflags, from, to):
var from = from == null ? [] : from.copy();
var to = to == null ? [] : to.copy();
var isEnum = false;
if (tflags != null) {
for (flag in tflags) {
switch (flag) {
case AbEnum: isEnum = true;
case AbFrom(ct): from.push(ct);
case AbTo(ct): to.push(ct);
}
}
}
(isEnum ? "enum " : "")
+ "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(""))
+ [for (f in from) " from " + printComplexType(f)].join("")
+ [for (f in to) " to " + printComplexType(f)].join("")
+ " {\n"
+ [
for (f in t.fields) {
@ -443,8 +463,9 @@ class Printer {
add("EBinop " + printBinop(op));
loopI(e1);
loopI(e2);
case EField(e, field):
add("EField " + field);
case EField(e, field, kind):
if (kind == null) kind = Normal;
add('EField $field (${kind.getName()})');
loopI(e);
case EParenthesis(e):
add("EParenthesis");
@ -543,8 +564,6 @@ class Printer {
case EDisplay(e, displayKind):
add("EDisplay");
loopI(e);
case EDisplayNew(t):
add("EDisplayNew");
case ETernary(econd, eif, eelse):
add("ETernary");
loopI(econd);

View File

@ -180,6 +180,11 @@ typedef TypeParameter = {
`KTypeParameter` kind.
**/
var t:Type;
/**
The default type for this type parameter.
**/
var ?defaultType:Null<Type>;
}
/**
@ -765,6 +770,11 @@ typedef TVar = {
The metadata of the variable.
**/
public var meta(default, never):Null<MetaAccess>;
/**
Whether the variable is a local static variable
**/
public var isStatic(default, never):Bool;
}
/**

View File

@ -85,7 +85,7 @@ class TypeTools {
pos: cf.pos,
meta: cf.meta.get(),
} else {
throw "Invalid TAnonymous";
throw "Invalid TAnonymous";
}
}
@ -162,7 +162,7 @@ class TypeTools {
}
}
#if (macro || display)
#if macro
/**
Follows all typedefs of `t` to reach the actual type.
@ -174,12 +174,17 @@ class TypeTools {
If `t` is null, an internal exception is thrown.
Usage example:
Usage example with monomorphs:
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,[])
Usage example with typedefs:
var t = Context.typeof(macro ("foo" :MyString)); // typedef MyString = String
trace(t); // TType(MyString,[])
trace(t.follow()); //TInst(String,[])
**/
static public inline function follow(t:Type, ?once:Bool):Type
return Context.follow(t, once);
@ -363,6 +368,35 @@ class TypeTools {
return null;
#end
}
/**
Changes the name of the variable in the typed expression.
**/
static public function setVarName(t:TVar, name:String) {
Context.load("set_var_name", 2)(t, name);
}
/**
Converts type `t` to `haxe.macro.Type.ModuleType`.
**/
static public function toModuleType(t:Type):ModuleType {
#if (neko || eval)
return Context.load("type_to_module_type", 1)(t);
#else
return null;
#end
}
/**
Creates a type from the `haxe.macro.Type.ModuleType` argument.
**/
static public function fromModuleType(mt:ModuleType):Type {
#if (neko || eval)
return Context.load("module_type_to_type", 1)(mt);
#else
return null;
#end
}
#end
/**

View File

@ -167,7 +167,7 @@ class TypedExprTools {
}
}
#if (macro || display)
#if macro
static public function toString(t:TypedExpr, ?pretty = false):String {
return @:privateAccess haxe.macro.Context.sExpr(t, pretty);
}