[英]Some errors with genericbuilding enums
Solved For a first ever macro to write this wasnt the easiest.已解决对于第一个编写此宏的宏来说,这并不是最简单的。 But I learned a lot, much kudo's to Gama11 who pointed me in the right direction, and the coreteam for such a thing of beauty: Haxe.
但是我学到了很多东西,非常感谢 Gama11,他为我指明了正确的方向,以及这样一个美丽事物的核心团队:Haxe。
And I even added some slick doc field strings, so you get nice info during autocompletion.我什至添加了一些漂亮的文档字段字符串,因此您可以在自动完成过程中获得不错的信息。
Main.hx主文件
var e1:Either<String, Int, Bool> = Either3._1('test');
var e2:Either<String, Int, Bool> = Either3._2(1);
var e3:Either<String, Int, Bool> = Either3._3(true);
var error:Either<String, Int, Bool> = Either3._3('Bool expected, but got a String this will give an error');
Either.hx要么.hx
package;
@:genericBuild(EitherMacro.build())
class Either<Rest> {}
/*@:genericbuild only works on classes, but
can still override the class with an enum. Funky. */
EitherMacro.hx要么宏.hx
package;
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
class EitherMacro {
static var eitherTypes = new Map<Int,Bool>();
static function build():ComplexType {
return switch (Context.getLocalType()) {
case TInst(_.get() => {name: "Either"}, params):
buildEitherEnum(params);
default:
throw false;
}
return macro:Dynamic;
}
static function buildEitherEnum(params:Array<Type>):ComplexType {
var numParams = params.length;
var name='Either$numParams';
if (!eitherTypes.exists(numParams)){
Context.defineType(defineType(name, params));
eitherTypes[numParams] = true;
}
return TPath({pack: [], name: name, params: [for (t in params) TPType(t.toComplexType())]});
}
private static inline function defineType(name:String, params:Array<Type>){
var typeParams:Array<TypeParamDecl> = [];
var typeStrings:Array<String>=[];
var numParams = params.length;
var fields:Array<Field>=[];
for (i in 0...numParams) {
var t=i+1;
typeStrings.push(params[i].toString());
}
var constDocStr=typeStrings.join(',');
for (i in 0...numParams) {
var t=i+1;
var typeString:String=typeStrings[i];
typeParams.push({name:'T$t'});
fields.push(
{
name: '_$t',
pos: Context.currentPos(),
doc: 'from $name<$constDocStr> _$t(v: $typeString)',
kind:FFun({
ret: null,
params: [{name:'T$t'}],
expr: null,
args: [
{
name: 'v',
type: TPath(
{
name:'T$t',
params:[],
pack:[]
}
)
}
]
}
)
}
);
}
var docStr:String="Either represents values which are either of type ";
for(k in 0...typeStrings.length){
if(k!=typeStrings.length-1){
docStr+=typeStrings[k]+" or ";
} else {
docStr+=typeStrings[k]+".";
}
}
return {
pack:[],
name:name,
pos:Context.currentPos(),
doc:docStr,
isExtern: false,
meta:null,
kind:TDEnum,
fields:fields,
params:typeParams
}
}
}
#end
usage of -D dump=pretty dumps typed AST in dump subdirectory using prettified mode.使用 -D dump=pretty 转储使用美化模式在转储子目录中键入 AST。 The output from dump=pretty is almost indistuingishable from regular Haxe code.
dump=pretty 的输出与常规 Haxe 代码几乎没有区别。 When errors appear, you find iin the root of the dump directory a file called 'decoding_error.txt'.
当出现错误时,您会在转储目录的根目录中找到一个名为“decoding_error.txt”的文件。 Its contents might look like this:
它的内容可能如下所示:
{
doc: null
fields: null <- expected value
isExtern: null
kind: null <- expected value
meta: null
name: null <- expected value
pack: null <- expected value
params: null
pos: null <- expected value
}
line 3: expected value
line 5: expected value
line 7: expected value
line 8: expected value
line 10: expected value
This made it much easier for me to debug.这使我更容易调试。 But the even better way, is way simple... To debug the easiest way, go to your macrofile (in my case EitherMacro.hx) and do
但更好的方法是简单......要调试最简单的方法,请转到您的宏文件(在我的情况下为EitherMacro.hx)并执行
class EitherMacro{
public static function build(){
var fields=Context.getBuildFields();
var type=Context.getLocalType();
trace(type);
for(f in fields){
trace(f);
}
// your other code
/*
If you use @:build)() instead of @:genericbuild
to debug. Make sure the buildfunction returns
Array<Field> and put at the last line
return Context.getBuildFields();
if you use @:genericbuild you must return
ComplexType, and you can add as the line
return macro:Dynamic; if you have no working return yet.
*/
}
}
the output might look like this:输出可能如下所示:
source/EnumBuilder2.hx:18: TEnum(SomeEnum,[TInst(SomeEnum.T1,[]),TInst(SomeEnum.T2,[]),TInst(SomeEnum.T3,[])])
source/EnumBuilder2.hx:20: {name: _1, doc: null, pos: #pos(source/SomeEnum.hx:4: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:4: characters 5-7)}
source/EnumBuilder2.hx:20: {name: _2, doc: null, pos: #pos(source/SomeEnum.hx:5: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:5: characters 5-7)}
source/EnumBuilder2.hx:20: {name: _3, doc: null, pos: #pos(source/SomeEnum.hx:6: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:6: characters 5-7)}
Another good idea with @:genericbuild(), is to first constructed an enum by hand(or whatever type) and after that trace it using a @:genericbuild, or if you got too much errors using @:build.使用@:genericbuild() 的另一个好主意是首先手动构造一个枚举(或任何类型),然后使用@:genericbuild 跟踪它,或者如果使用@:build 出现太多错误。 Then you can copy those trace outputs and try use that code to craft the AST in the macro.
然后您可以复制这些跟踪输出并尝试使用该代码在宏中制作 AST。 This will seriously speedup your development, especially in case of complicated macro's.
这将大大加快您的开发速度,尤其是在复杂的宏的情况下。 Almost mindlessly ;-)
几乎是无意识的;-)
Your macro has never run.您的宏从未运行过。
Replace your build()
function with the following to verify将您的
build()
函数替换为以下内容以验证
static function build():ComplexType {
trace('build');
return macro:Dynamic;
}
I suppose @:genericBuild
only works for class
我想
@:genericBuild
只适用于class
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.