gpt4 book ai didi

macros - 通用建筑枚举的一些错误

转载 作者:行者123 更新时间:2023-12-01 09:22:14 26 4
gpt4 key购买 nike

已解决对于有史以来第一个编写宏的人来说,这并不是最简单的。但我学到了很多东西,对 Gama11 给予了我很多荣誉,他为我指明了正确的方向,还有这样一个美丽事物的核心团队:Haxe。

我什至添加了一些灵活的文档字段字符串,因此您可以在自动完成期间获得很好的信息。 enter image description here enter image description here enter image description here

主.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');

要么.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

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

调试宏的简单方法

使用 -D dump=pretty 使用美化模式在转储子目录中转储键入 AST。 dump=pretty 的输出与常规的 Haxe 代码几乎没有区别。当出现错误时,您会在转储目录的根目录中找到一个名为“decoding_error.txt”的文件。它的内容可能如下所示:

{
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

这让我更容易调试。但更好的方法很简单...要调试最简单的方法,请转到您的宏文件(在我的例子中是 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.
*/


}
}

输出可能是这样的:

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)}

使用@:genericbuild() 的另一个好主意是首先手动构造一个枚举(或任何类型),然后使用@:genericbuild 跟踪它,或者如果使用@:build 时出现太多错误。然后您可以复制这些跟踪输出并尝试使用该代码在宏中制作 AST。这将大大加快您的开发速度,尤其是在复杂宏的情况下。几乎是无意识的;-)

最佳答案

您的宏从未运行过。

用下面的代码替换你的build()函数来验证

    static function build():ComplexType {
trace('build');
return macro:Dynamic;
}

我想 @:genericBuild 只适用于 class

关于macros - 通用建筑枚举的一些错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57481810/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com