如何使用表达式宏返回类实例?

问题描述 投票:0回答:2

驱动程序代码

//---------------- Main.hx ------------------------------------------------------------------
import core.reflection.ReflectionTools;
import core.SomeClass;
class Main{
   public static function main(){
      var s = new SomeClass();
      ReflectionTools.info(s);
   }
}

//---------------- ReflectionTools.hx -----------------------------------------------------
class RelectionTools {
    public static macro function info(obj:Expr):Expr{
        var pos = Context.currentPos();
        var block = [];
        var result:Dynamic;
        var type:Type=Context.typeof(obj);        
        result=(switch(type){
            case TInst(t, params):new RelectionClass(t, params);
            case TEnum(t, params):new ReflectionEnum(t, params);
            case TDynamic(t):new ReflectionDynamic(t);
            case TFun(args, ret):new ReflectionFunction(args, ret);
            case TMono(t):new ReflectionMonomorph(t);
            case TLazy(f):new ReflectionLazy(f);
            case TAbstract(t, params):new ReflectionAbstract(t, params);
            case TType(t, params):new ReflectionTypeDefinition(t, params);
            case TAnonymous(a):new ReflectionAnonymousStructure(a);
        });
        return $v{result};
    }
}

Haxe编译器:

期望的Expr,但是得到了core.reflection.RelectionClass(有关详细信息,请参见dump / decoding_error.txt)

haxe
2个回答
1
投票

宏是编译时功能,不是运行时功能,您不能返回类实例。相反,您必须返回创建新实例的表达式(我没有您的课程,所以我在这里使用我的课程)

        var type=Context.typeof(obj); 
        return (switch(type){
            case TInst(t, params):macro new MyClass();//RelectionClass(t, params);
            case TEnum(t, params):macro new MyClass();//ReflectionEnum(t, params);
            case TDynamic(t):macro new MyClass();//ReflectionDynamic(t);
            case TFun(args, ret):macro new MyClass();//ReflectionFunction(args, ret);
            case TMono(t):macro new MyClass();//ReflectionMonomorph(t);
            case TLazy(f):macro new MyClass();//ReflectionLazy(f);
            case TAbstract(t, params):macro new MyClass();//ReflectionAbstract(t, params);
            case TType(t, params):macro new MyClass();//ReflectionTypeDefinition(t, params);
            case TAnonymous(a):macro new MyClass();//ReflectionAnonymousStructure(a);
        });
        return macro null;

0
投票

它不是构建宏(它允许返回类实例),但是它是一个表达式宏。模仿类功能的最佳方法是使用摘要。

/* Solution Description
1. a custom Json abstract with underlying type {} and with implicit   
    casts to underlying type. See Json.hx
2. abstracts which reflect possible Type enums with underlying custom 
   Json abstract and forwards. See example ReflectionPrimitive.hx
   and mimic inheritance by underlying types as superclass 
   see example ReflectionFunction.hx 
3. uses same instantiation code as original class instantiation 
   but now they are abstracts (see PROBLEM(The macro). Solved! */

步骤1.具有基本类型{}且具有隐式强制转换为的自定义Json抽象基础类型。

// ---------------- Json.hx ----------------------------------------------
package core.ds.json;
import haxe.Serializer;
import haxe.Unserializer;
import haxe.Json as J;

abstract Json({}) from ({}) to ({}) {
    public inline function new(?data:{}){
        this=data;
        if(this==null){
            this={};
        }
    }
    @:arrayAccess 
    public inline function get(key:String):Dynamic{
        if(exists(key)){
            return Reflect.field(this,key);
        } 
        return null;
    }
    @:arrayAccess 
    public inline function set(key:String, value:Dynamic):Dynamic{
        Reflect.setField(this, key, value);
        return value;
    }   

    public inline function isEmpty(key:String):Bool{
        return !isSet(key) || (exists(key) && (  get(key)=="" || get(key)==''|| get(key)==null || get(key)==0  ));
    }

    public inline function isSet(key:String):Bool{
        return exists(key) && get(key)!=null;
    }

    public inline function exists(key:String):Bool {
        return Reflect.hasField(this, key);
    } 
    @:to
    public inline function toMap():Map<String, Dynamic>{
        var result:Map<String, Dynamic>=new Map<String, Dynamic>();
        var fields:Array<String>=Reflect.fields(this);
        for (f in fields){
            result.set(f, Reflect.field(this, f));
        }
        return result;
    }
    @:to
    public inline function toJsonString():String{
        return J.stringify(this,null," ");
    }

    public inline function values():Array<Dynamic>{
        var result:Array<Dynamic>=[];
        var keys:Array<String>=keys();
        for(k in keys){
            result.push(Reflect.field(this,k));
        }
        return result;
    }

    public inline function keys():Array<String>{
        return Reflect.fields(this);
    }

    public inline function clone():Json{
        return Unserializer.run(Serializer.run(this));
    }

    public var length(get,never):Int;


    private inline function get_length():Int{
        return keys().length;
    }

    public inline function keyValueIterator():KeyValueIterator<String, Dynamic>{
        return toMap().keyValueIterator();
    }


    @:from 
    public static function fromJsonString(json:String):Json{
        return J.parse(json);
    }
    @:from 
    public static function fromMap(map:Map<String, Dynamic>):Json{
        var result={};
        for (k=>v in map){
            Reflect.setField(result, k, v);
        }
        return result;
    }

}

步骤2.摘要,这些摘要反映了带有基础自定义Json摘要并转发的可能的Type枚举。参见示例ReflectionPrimitive.hx,并通过基础类型模仿继承作为超类,参见示例ReflectionFunction.hx

//---------------- ReflectionPrimitive.hx ----------------------------------------------

@:forward()
abstract ReflectionPrimitive(core.ds.json.Json) from core.ds.json.Json to core.ds.json.Json{
    public inline function new(nameType:String){
        this=new core.ds.json.Json({data:new core.ds.json.Json(), info:new core.ds.json.Json({nameType:nameType})});
    }
    public var data(get, set):core.ds.json.Json;
    public var info(get, set):core.ds.json.Json;
    private function get_data():core.ds.json.Json {
        return this["data"];
    }
    private function set_data(value:core.ds.json.Json):core.ds.json.Json {
        this["data"]=value;
        return this;
    }
    private function get_info():core.ds.json.Json {
        return this["info"];
    }
    private function set_info(value:core.ds.json.Json):core.ds.json.Json {
        this["info"]=value;
        return this;
    }
 }

模仿模仿

//---------------- ReflectionFunction.hx ----------------------------------------------
@:forward(data, info, get, isEmpty, isSet, exists, toMap, toJsonString, values, keys, clone, length, keyValueIterator, fromJsonString, fromMap)
abstract ReflectionFunction(ReflectionPrimitive) from ReflectionPrimitive to ReflectionPrimitive{
    public inline function new(args:Array<{t:Type, opt:Bool, name:String}>, ret:Type){
        this=new ReflectionPrimitive(NameType.FUNCTION);
        var newArgs=new Array<core.ds.json.Json>();
        for(a in args){
           newArgs.push(new core.ds.json.Json(a));
        }
        this.data=this.data.set("args",newArgs).set("ret", ret);
    }
    public var args(get, never):Array<core.ds.json.Json>;
    public var ret(get,never):Type;

    private function get_args():Array<core.ds.json.Json>{
        return this.data.get("args");
    }
    private function get_ret():Type{
        return this.data.get("ret");
    }

}

保持宏不变,它将立即可用。

© www.soinside.com 2019 - 2024. All rights reserved.