Răsfoiți Sursa

Add additional `Compiler`/`Context` functions for getting compiler configuration and main func/output types (#10871)

* Added `Compiler`/`Context` functions accessing arguments, main function, and other context info

* Added `Compiler.getConfiguration` and `TypeTools.[to/from]ModuleType`

Added `Compiler.getConfiguration` and its required typedefs/enums:
* `haxe.macro.Compiler.CompilerConfiguration`
* `haxe.macro.Compiler.PackageRule`
* `haxe.macro.PlatformConfig`
* `haxe.macro.PlatformConfig.CapturePolicy`
* `haxe.macro.PlatformConfig.VarScopingConfig`
* `haxe.macro.PlatformConfig.VarScope`
* `haxe.macro.PlatformConfig.VarScopingFlags`
* `haxe.macro.PlatformConfig.ExceptionsConfig`

* Renamed `decode_path` -> `decode_ast_path` for consistency

* Use `Globals.platform_name` for `encode_platform`

* Added warning doc comment for `PlatformConfig`

* Added tests for pull #10871

* Fixed var name typos
RoBBoR 2 ani în urmă
părinte
comite
851704fcc8

+ 1 - 0
src/core/globals.ml

@@ -50,6 +50,7 @@ let platforms = [
 	Eval;
 ]
 
+(** Expected to match `haxe.display.Display.Platform`. *)
 let platform_name = function
 	| Cross -> "cross"
 	| Js -> "js"

+ 4 - 0
src/macro/eval/evalEncode.ml

@@ -183,6 +183,10 @@ let encode_enum i pos index pl =
 		| IQuoteStatus -> key_haxe_macro_QuoteStatus
 		| IDisplayKind -> key_haxe_macro_DisplayKind
 		| IDisplayMode -> key_haxe_macro_DisplayMode
+		| ICapturePolicy -> key_haxe_macro_CapturePolicy
+		| IVarScope -> key_haxe_macro_VarScope
+		| IVarScopingFlags -> key_haxe_macro_VarScopingFlags
+		| IPackageRule -> key_haxe_macro_PackageRule
 		| IMessage -> key_haxe_macro_Message
 		| IFunctionKind -> key_haxe_macro_FunctionKind
 		| IStringLiteralKind -> key_haxe_macro_StringLiteralKind

+ 4 - 0
src/macro/eval/evalHash.ml

@@ -116,6 +116,10 @@ let key_haxe_macro_ImportMode = hash "haxe.macro.ImportMode"
 let key_haxe_macro_QuoteStatus = hash "haxe.macro.QuoteStatus"
 let key_haxe_macro_DisplayKind = hash "haxe.macro.DisplayKind"
 let key_haxe_macro_DisplayMode = hash "haxe.macro.DisplayMode"
+let key_haxe_macro_CapturePolicy = hash "haxe.macro.CapturePolicy"
+let key_haxe_macro_VarScope = hash "haxe.macro.VarScope"
+let key_haxe_macro_VarScopingFlags = hash "haxe.macro.VarScopingFlags"
+let key_haxe_macro_PackageRule = hash "haxe.macro.PackageRule"
 let key_haxe_macro_Message = hash "haxe.macro.Message"
 let key_haxe_macro_FunctionKind = hash "haxe.macro.FunctionKind"
 let key_haxe_macro_StringLiteralKind = hash "haxe.macro.StringLiteralKind"

+ 129 - 11
src/macro/macroApi.ml

@@ -4,6 +4,7 @@ open Type
 open Common
 open DefineList
 open MetaList
+open Globals
 
 exception Invalid_expr
 exception Abort
@@ -91,6 +92,10 @@ type enum_type =
 	| IImportMode
 	| IDisplayKind
 	| IDisplayMode
+	| ICapturePolicy
+	| IVarScope
+	| IVarScopingFlags
+	| IPackageRule
 	| IMessage
 	| IFunctionKind
 	| IStringLiteralKind
@@ -271,7 +276,15 @@ let encode_import (path,mode) =
 let encode_placed_name (s,p) =
 	encode_string s
 
-let rec encode_path (t,p) =
+(* Globals.path *)
+let encode_path (p,n) =
+	encode_obj [
+		"pack", encode_array (List.map encode_string p);
+		"name", encode_string n;
+	]
+
+(* Ast.placed_type_path *)
+let rec encode_ast_path (t,p) =
 	let fields = [
 		"pack", encode_array (List.map encode_string t.tpackage);
 		"name", encode_string t.tname;
@@ -331,7 +344,7 @@ and encode_field (f:class_field) =
 and encode_ctype t =
 	let tag, pl = match fst t with
 	| CTPath p ->
-		0, [encode_path (p,Globals.null_pos)]
+		0, [encode_ast_path (p,Globals.null_pos)]
 	| CTFunction (pl,r) ->
 		1, [encode_array (List.map encode_ctype pl);encode_ctype r]
 	| CTAnonymous fl ->
@@ -339,7 +352,7 @@ and encode_ctype t =
 	| CTParent t ->
 		3, [encode_ctype t]
 	| CTExtend (tl,fields) ->
-		4, [encode_array (List.map encode_path tl); encode_array (List.map encode_field fields)]
+		4, [encode_array (List.map encode_ast_path tl); encode_array (List.map encode_field fields)]
 	| CTOptional t ->
 		5, [encode_ctype t]
 	| CTNamed (n,t) ->
@@ -403,6 +416,83 @@ and encode_display_mode dm =
 	in
 	encode_enum ~pos:None IDisplayMode tag pl
 
+(** encoded to haxe.display.Display.Platform, an enum abstract of String *)
+and encode_platform p =
+	encode_string (platform_name p)
+
+and encode_platform_config pc =
+	encode_obj [
+		"staticTypeSystem", vbool pc.pf_static;
+		"sys", vbool pc.pf_sys;
+		"capturePolicy", encode_capture_policy pc.pf_capture_policy;
+		"padNulls", vbool pc.pf_pad_nulls;
+		"addFinalReturn", vbool pc.pf_add_final_return;
+		"overloadFunctions", vbool pc.pf_overload;
+		"canSkipNonNullableArgument", vbool pc.pf_can_skip_non_nullable_argument;
+		"reservedTypePaths", encode_array (List.map encode_path pc.pf_reserved_type_paths);
+		"supportsFunctionEquality", vbool pc.pf_supports_function_equality;
+		"usesUtf16", vbool pc.pf_uses_utf16;
+		"thisBeforeSuper", vbool pc.pf_this_before_super;
+		"supportsThreads", vbool pc.pf_supports_threads;
+		"supportsUnicode", vbool pc.pf_supports_unicode;
+		"supportsRestArgs", vbool pc.pf_supports_rest_args;
+		"exceptions", encode_exceptions_config pc.pf_exceptions;
+		"scoping", encode_var_scoping_config pc.pf_scoping;
+		"supportsAtomics", vbool pc.pf_supports_atomics;
+	]
+
+and encode_capture_policy cp =
+	let tag = match cp with
+		| CPNone -> 0
+		| CPWrapRef -> 1
+		| CPLoopVars -> 2
+	in
+	encode_enum ~pos:None ICapturePolicy tag []
+
+and encode_var_scoping_config vsc =
+	encode_obj [
+		"scope", encode_var_scope vsc.vs_scope;
+		"flags", encode_array (List.map encode_var_scoping_flags vsc.vs_flags);
+	]
+
+and encode_var_scope vs =
+	let tag = match vs with
+		| FunctionScope -> 0
+		| BlockScope -> 1
+	in
+	encode_enum ~pos:None IVarScope tag []
+
+and encode_var_scoping_flags vsf =
+	let tag, pl = match vsf with
+		| VarHoisting -> 0, []
+		| NoShadowing -> 1, []
+		| NoCatchVarShadowing -> 2, []
+		| ReserveCurrentTopLevelSymbol -> 3, []
+		| ReserveAllTopLevelSymbols -> 4, []
+		| ReserveAllTypesFlat -> 5, []
+		| ReserveNames (names) -> 6, [encode_array (List.map encode_string names)]
+		| SwitchCasesNoBlocks -> 7, []
+	in
+	encode_enum ~pos:None IVarScopingFlags tag pl
+
+and encode_exceptions_config ec =
+	encode_obj [
+		"nativeThrows", encode_array (List.map encode_path ec.ec_native_throws);
+		"nativeCatches", encode_array (List.map encode_path ec.ec_native_catches);
+		"avoidWrapping", vbool ec.ec_avoid_wrapping;
+		"wildcardCatch", encode_path ec.ec_wildcard_catch;
+		"baseThrow", encode_path ec.ec_base_throw;
+		(* skipping "specialThrow" since cannot use "decode_texpr" here *)
+	]
+
+and encode_package_rule pr =
+	let tag, pl = match pr with
+		| Forbidden -> 0, []
+		| Directory (path) -> 1, [encode_string path]
+		| Remap (path) -> 2, [encode_string path]
+	in
+	encode_enum ~pos:None IPackageRule tag pl
+
 and encode_message (msg,p,_,sev) =
 	let tag, pl = match sev with
 		| Globals.MessageSeverity.Information -> 0, [(encode_string msg); (encode_pos p)]
@@ -443,7 +533,7 @@ and encode_expr e =
 			| ECall (e,el) ->
 				7, [loop e;encode_array (List.map loop el)]
 			| ENew (p,el) ->
-				8, [encode_path p; encode_array (List.map loop el)]
+				8, [encode_ast_path p; encode_array (List.map loop el)]
 			| EUnop (op,flag,e) ->
 				9, [encode_unop op; vbool (match flag with Prefix -> false | Postfix -> true); loop e]
 			| EVars vl ->
@@ -631,7 +721,8 @@ let decode_placed_name vp v =
 let decode_opt_array f v =
 	if v = vnull then [] else List.map f (decode_array v)
 
-let rec decode_path t =
+(* Ast.placed_type_path *)
+let rec decode_ast_path t =
 	let p = field t "pos" in
 	let pack = List.map decode_string (decode_array (field t "pack"))
 	and name = decode_string (field t "name")
@@ -729,7 +820,7 @@ and decode_ctype t =
 	let (i,args),p = decode_enum_with_pos t in
 	(match i,args with
 	| 0, [p] ->
-		CTPath (fst (decode_path p))
+		CTPath (fst (decode_ast_path p))
 	| 1, [a;r] ->
 		CTFunction (List.map decode_ctype (decode_array a), decode_ctype r)
 	| 2, [fl] ->
@@ -737,7 +828,7 @@ and decode_ctype t =
 	| 3, [t] ->
 		CTParent (decode_ctype t)
 	| 4, [tl;fl] ->
-		CTExtend (List.map decode_path (decode_array tl), List.map decode_field (decode_array fl))
+		CTExtend (List.map decode_ast_path (decode_array tl), List.map decode_field (decode_array fl))
 	| 5, [t] ->
 		CTOptional (decode_ctype t)
 	| 6, [n;t] ->
@@ -801,7 +892,7 @@ and decode_expr v =
 		| 7, [e;el] ->
 			ECall (loop e,List.map loop (decode_array el))
 		| 8, [t;el] ->
-			ENew (decode_path t,List.map loop (decode_array el))
+			ENew (decode_ast_path t,List.map loop (decode_array el))
 		| 9, [op;f;e] ->
 			EUnop (decode_unop op,(if decode_bool f then Postfix else Prefix),loop e)
 		| 10, [vl] ->
@@ -1513,8 +1604,8 @@ let decode_type_def v =
 		let is_interface = decode_opt_bool interf in
 		let is_final = decode_opt_bool final in
 		let is_abstract = decode_opt_bool abstract in
-		let interfaces = (match opt (fun v -> List.map decode_path (decode_array v)) impl with Some l -> l | _ -> [] ) in
-		let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in
+		let interfaces = (match opt (fun v -> List.map decode_ast_path (decode_array v)) impl with Some l -> l | _ -> [] ) in
+		let flags = (match opt decode_ast_path ext with None -> flags | Some t -> HExtends t :: flags) in
 		let flags = if is_interface then begin
 				let flags = HInterface :: flags in
 				List.map (fun t -> HExtends t) interfaces @ flags
@@ -1950,7 +2041,7 @@ let macro_api ccom get_api =
 			encode_type t
 		);
 		"define_module", vfun4 (fun path vl ui ul ->
-			(get_api()).define_module (decode_string path) (decode_array vl) (List.map decode_import (decode_array ui)) (List.map fst (List.map decode_path (decode_array ul)));
+			(get_api()).define_module (decode_string path) (decode_array vl) (List.map decode_import (decode_array ui)) (List.map fst (List.map decode_ast_path (decode_array ul)));
 			vnull
 		);
 		"add_class_path", vfun1 (fun cp ->
@@ -2027,6 +2118,33 @@ let macro_api ccom get_api =
 		"get_display_mode", vfun0 (fun() ->
 			encode_display_mode !Parser.display_mode
 		);
+		"get_configuration", vfun0 (fun() ->
+			let com = ccom() in
+			encode_obj [
+				"version", vint com.version;
+				"args", encode_array (List.map encode_string com.args);
+				"debug", vbool com.debug;
+				"verbose", vbool com.verbose;
+				"foptimize", vbool com.foptimize;
+				"platform", encode_platform com.platform;
+				"platformConfig", encode_platform_config com.config;
+				"stdPath", encode_array (List.map encode_string com.std_path);
+				"mainClass", (match com.main_class with None -> vnull | Some path -> encode_path path);
+				"packageRules", encode_string_map encode_package_rule com.package_rules;
+			]
+		);
+		"get_main_expr", vfun0 (fun() ->
+			match (ccom()).main with None -> vnull | Some e -> encode_texpr e
+		);
+		"get_module_types", vfun0 (fun() ->
+			encode_array (List.map encode_module_type (ccom()).types)
+		);
+		"type_to_module_type", vfun1 (fun(t) ->
+			encode_module_type (module_type_of_type (decode_type t))
+		);
+		"module_type_to_type", vfun1 (fun(t) ->
+			encode_type (type_of_module_type (decode_module_type t))
+		);
 		"apply_params", vfun3 (fun tpl tl t ->
 			let tl = List.map decode_type (decode_array tl) in
 			let tpl = List.map (fun v ->

+ 73 - 0
std/haxe/macro/Compiler.hx

@@ -163,6 +163,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).
 
@@ -661,3 +674,63 @@ typedef DefineDescription = {
 	**/
 	@: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);
+}

+ 23 - 0
std/haxe/macro/Context.hx

@@ -309,6 +309,29 @@ class Context {
 		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.
+	**/
+	public static function getAllModuleTypes():Array<haxe.macro.Type.ModuleType> {
+		return load("get_module_types", 0)();
+	}
+
 	/**
 		Parses `expr` as Haxe code, returning the corresponding AST.
 

+ 206 - 0
std/haxe/macro/PlatformConfig.hx

@@ -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;
+}

+ 22 - 0
std/haxe/macro/TypeTools.hx

@@ -370,6 +370,28 @@ class TypeTools {
 	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
 
 	/**

+ 32 - 0
tests/misc/projects/Issue10871/Compiler/Main.hx

@@ -0,0 +1,32 @@
+package;
+
+#if macro
+import haxe.macro.Compiler;
+import haxe.macro.Compiler.PackageRule;
+#end
+
+function main() {
+}
+
+#if macro
+class MacroClass {
+	public static function start() {
+		final config = Compiler.getConfiguration();
+
+		trace(config.args);
+		trace(config.debug);
+		trace(config.verbose);
+		trace(config.foptimize);
+		trace(config.platform);
+		trace(config.mainClass.pack);
+		trace(config.mainClass.name);
+
+		for(packageName => packageRule in config.packageRules) {
+			switch(packageRule) {
+				case Forbidden: trace(packageName + " is forbidden");
+				case _:
+			}
+		}
+	}
+}
+#end

+ 5 - 0
tests/misc/projects/Issue10871/Compiler/MainFail.hx

@@ -0,0 +1,5 @@
+package;
+
+function main() {
+	haxe.macro.Compiler.getConfiguration();
+}

+ 2 - 0
tests/misc/projects/Issue10871/Compiler/compile-fail.hxml

@@ -0,0 +1,2 @@
+--main MainFail
+--interp

+ 1 - 0
tests/misc/projects/Issue10871/Compiler/compile-fail.hxml.stderr

@@ -0,0 +1 @@
+MainFail.hx:4: characters 22-38 : Class<haxe.macro.Compiler> has no field getConfiguration

+ 3 - 0
tests/misc/projects/Issue10871/Compiler/compile1.hxml

@@ -0,0 +1,3 @@
+--main Main
+--macro Main.MacroClass.start()
+--interp

+ 18 - 0
tests/misc/projects/Issue10871/Compiler/compile1.hxml.stdout

@@ -0,0 +1,18 @@
+Main.hx:16: [--main,Main,--macro,Main.MacroClass.start(),--interp]
+Main.hx:17: false
+Main.hx:18: false
+Main.hx:19: true
+Main.hx:20: eval
+Main.hx:21: []
+Main.hx:22: Main
+Main.hx:26: python is forbidden
+Main.hx:26: php is forbidden
+Main.hx:26: neko is forbidden
+Main.hx:26: lua is forbidden
+Main.hx:26: jvm is forbidden
+Main.hx:26: js is forbidden
+Main.hx:26: java is forbidden
+Main.hx:26: hl is forbidden
+Main.hx:26: flash is forbidden
+Main.hx:26: cs is forbidden
+Main.hx:26: cpp is forbidden

+ 5 - 0
tests/misc/projects/Issue10871/Compiler/compile2.hxml

@@ -0,0 +1,5 @@
+--main Main
+--macro Main.MacroClass.start()
+--js Output.js
+--no-output
+--debug

+ 19 - 0
tests/misc/projects/Issue10871/Compiler/compile2.hxml.stdout

@@ -0,0 +1,19 @@
+Main.hx:16: [--main,Main,--macro,Main.MacroClass.start(),--js,Output.js,--no-output,--debug]
+Main.hx:17: true
+Main.hx:18: false
+Main.hx:19: true
+Main.hx:20: js
+Main.hx:21: []
+Main.hx:22: Main
+Main.hx:26: sys is forbidden
+Main.hx:26: python is forbidden
+Main.hx:26: php is forbidden
+Main.hx:26: neko is forbidden
+Main.hx:26: lua is forbidden
+Main.hx:26: jvm is forbidden
+Main.hx:26: java is forbidden
+Main.hx:26: hl is forbidden
+Main.hx:26: flash is forbidden
+Main.hx:26: eval is forbidden
+Main.hx:26: cs is forbidden
+Main.hx:26: cpp is forbidden

+ 5 - 0
tests/misc/projects/Issue10871/Compiler/compile3.hxml

@@ -0,0 +1,5 @@
+--main Main
+--macro Main.MacroClass.start()
+--cpp bin
+--no-output
+--no-opt

+ 18 - 0
tests/misc/projects/Issue10871/Compiler/compile3.hxml.stdout

@@ -0,0 +1,18 @@
+Main.hx:16: [--main,Main,--macro,Main.MacroClass.start(),--cpp,bin,--no-output,--no-opt]
+Main.hx:17: false
+Main.hx:18: false
+Main.hx:19: false
+Main.hx:20: cpp
+Main.hx:21: []
+Main.hx:22: Main
+Main.hx:26: python is forbidden
+Main.hx:26: php is forbidden
+Main.hx:26: neko is forbidden
+Main.hx:26: lua is forbidden
+Main.hx:26: jvm is forbidden
+Main.hx:26: js is forbidden
+Main.hx:26: java is forbidden
+Main.hx:26: hl is forbidden
+Main.hx:26: flash is forbidden
+Main.hx:26: eval is forbidden
+Main.hx:26: cs is forbidden

+ 43 - 0
tests/misc/projects/Issue10871/Context/Main.hx

@@ -0,0 +1,43 @@
+package;
+
+#if macro
+import haxe.macro.Context;
+import haxe.macro.Type;
+#end
+
+function main() {
+}
+
+#if macro
+class MacroClass {
+	public static function start() {
+		printTypedExpr(Context.getMainExpr());
+
+		Context.onAfterTyping(function(modules: Array<ModuleType>) {
+			printTypedExpr(Context.getMainExpr());
+		});
+
+		Context.onGenerate(function(types: Array<Type>) {
+			printTypedExpr(Context.getMainExpr());
+
+			if(Context.getAllModuleTypes().length == types.length) {
+				trace("Module type list length == types.length");
+			} else {
+				trace("Module types length != types.length");
+			}
+		});
+		
+		Context.onAfterGenerate(function() {
+			printTypedExpr(Context.getMainExpr());
+		});
+	}
+
+	static function printTypedExpr(te: Null<TypedExpr>, ?pos:haxe.PosInfos) {
+		if(te == null) {
+			haxe.Log.trace("null", pos);
+		} else {
+			haxe.Log.trace(haxe.macro.TypedExprTools.toString(te, true), pos);
+		}
+	}
+}
+#end

+ 3 - 0
tests/misc/projects/Issue10871/Context/compile.hxml

@@ -0,0 +1,3 @@
+--main Main
+--macro Main.MacroClass.start()
+--interp

+ 5 - 0
tests/misc/projects/Issue10871/Context/compile.hxml.stdout

@@ -0,0 +1,5 @@
+Main.hx:14: null
+Main.hx:17: null
+Main.hx:21: _Main.Main_Fields_.main()
+Main.hx:24: Module type list length == types.length
+Main.hx:31: _Main.Main_Fields_.main()

+ 118 - 0
tests/misc/projects/Issue10871/TypeTools/Main.hx

@@ -0,0 +1,118 @@
+package;
+
+#if macro
+import haxe.macro.Context;
+import haxe.macro.TypeTools;
+import haxe.macro.Type;
+#end
+
+function main() {
+}
+
+#if macro
+class MacroClass {
+	public static function start() {
+		Context.onGenerate(function(types: Array<Type>) {
+			for(t in types) {
+				testTypeConversion(t);
+			}
+		});
+	}
+
+	static function testTypeConversion(t: Type) {
+		final moduleType = TypeTools.toModuleType(t);
+
+		switch(t) {
+			case TInst(t, params): {
+				switch(moduleType) {
+					case TClassDecl(t2): {
+						if(!compareClassTypes(t.get(), t2.get())) {
+							trace("Class types not equal");
+						}
+					}
+					case _: trace("Module wasn't class type");
+				}
+			}
+			case TEnum(e, params): {
+				switch(moduleType) {
+					case TEnumDecl(e2): {
+						if(!compareEnumTypes(e.get(), e2.get())) {
+							trace("Enum types not equal");
+						}
+					}
+					case _: trace("Module wasn't enum type");
+				}
+			}
+			case TType(d, params): {
+				switch(moduleType) {
+					case TTypeDecl(d2): {
+						if(!compareDefTypes(d.get(), d2.get())) {
+							trace("Def types not equal");
+						}
+					}
+					case _: trace("Module wasn't def type");
+				}
+			}
+			case TAbstract(a, params): {
+				switch(moduleType) {
+					case TAbstract(a2): {
+						if(!compareDefTypes(a.get(), a2.get())) {
+							trace("Abstract types not equal");
+						}
+					}
+					case _: trace("Module wasn't abstract type");
+				}
+			}
+			case _:
+		}
+	}
+
+	static function compareClassTypes(c1: ClassType, c2: ClassType): Bool {
+		return (
+			c1.name == c2.name &&
+			c1.module == c2.module &&
+			c1.pack.toString() == c2.pack.toString() &&
+			Std.string(c1.pos) == Std.string(c2.pos) &&
+			c1.isPrivate == c2.isPrivate &&
+			c1.isInterface == c2.isInterface &&
+			c1.isFinal == c2.isFinal &&
+			c1.isExtern == c2.isExtern &&
+			c1.isAbstract == c2.isAbstract
+		);
+	}
+
+	static function compareEnumTypes(e1: EnumType, e2: EnumType): Bool {
+		return (
+			e1.name == e2.name &&
+			e1.module == e2.module &&
+			e1.pack.toString() == e2.pack.toString() &&
+			e1.names.toString() == e2.names.toString() &&
+			Std.string(e1.pos) == Std.string(e2.pos) &&
+			e1.isPrivate == e2.isPrivate &&
+			e1.isExtern == e2.isExtern
+		);
+	}
+
+	static function compareDefTypes(d1: DefType, d2: DefType): Bool {
+		return (
+			d1.name == d2.name &&
+			d1.module == d2.module &&
+			d1.pack.toString() == d2.pack.toString() &&
+			Std.string(d1.pos) == Std.string(d2.pos) &&
+			d1.isPrivate == d2.isPrivate &&
+			d1.isExtern == d2.isExtern
+		);
+	}
+
+	static function compareAbstractTypes(a1: AbstractType, a2: AbstractType): Bool {
+		return (
+			a1.name == a2.name &&
+			a1.module == a2.module &&
+			a1.pack.toString() == a2.pack.toString() &&
+			Std.string(a1.pos) == Std.string(a2.pos) &&
+			a1.isPrivate == a2.isPrivate &&
+			a1.isExtern == a2.isExtern
+		);
+	}
+}
+#end

+ 3 - 0
tests/misc/projects/Issue10871/TypeTools/compile.hxml

@@ -0,0 +1,3 @@
+--main Main
+--macro Main.MacroClass.start()
+--interp

+ 0 - 0
tests/misc/projects/Issue10871/TypeTools/compile.hxml.stdout