1

给出了以下 Swift 协议


public protocol Symbol {
    associatedtype Meaning
}

public protocol Interpretation : Symbol {}

public protocol Program : Symbol where Meaning == Body.Meaning {
    
    associatedtype Body : Symbol
    var body : Body {get}
    
}

解释只是我需要用于其他代码生成的标记协议。手头的代码生成问题是:使每个实现的类型Program都符合每个符合的协议Body。理想情况下,我还想将这种“符合每个协议”限制为仅继承自Interpretation. 为简单起见,我将自己限制在只包含实例变量和实例方法而没有输入参数的协议。

这是我尝试过的:


{% for type in types.based.Program|public %}

extension {{type.name}} : Interpretation {}

{% for proto in types.protocols|public %}{% if type.Body.based.{{proto.name}} %}
extension {{type.name}} : {{proto.name}} {

{% for variable in proto.variables|instance %}
    @inlinable
    public var {{variable.name}} : {{variable.typeName}} {
        body.{{variable.name}}
    }
{%endfor%}
{% for method in proto.methods|instance %}
        
    @inlinable
    public func {{method.name}} -> {{method.returnTypeName}} {
        body.{{method.name}}
    }
{%endfor%}

}

{% endif %}{% endfor %}{% endfor %}

这是我的测试类型:



public protocol ArrayInterpretable : Interpretation {
    
    var asArray : Array<Meaning> {get}
    
}


public struct Nil<Meaning> : ArrayInterpretable {
    
    public var asArray: [Meaning] {
        []
    }
    
}

public struct Bar<T> : Program {

    public typealias Meaning = T
    public typealias Body = Nil<T>
    
    public let body = Nil<T>()
    
}

这是我得到的:

// Generated using Sourcery 1.6.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT



extension Bar : Interpretation {}


我本来希望通过 codegen自动符合Barto 。ArrayInterpretable如何解决这个问题?

4

1 回答 1

0

我想出了一个似乎有效的技巧,即使它在多个层面上都令人畏缩。

import Free

{% for type in types.based.Program | public %}

extension {{type.name}} : Interpretation {}

{% for v in type.variables %}{%if v.name == "body"%}
{%for proto in types.protocols|public%}
{%if proto.based.Interpretation%}
{%for prt in v.type.basedTypes%}
{%if prt == proto.name %}
extension {{type.name}} : {{proto.name}} {

{% for variable in proto.variables|instance %}
    @inlinable
    public var {{variable.name}} : {{variable.typeName}} {
        body.{{variable.name}}
    }
{%endfor%}
{% for method in proto.methods|instance %}
    @inlinable
    public func {{method.name}} -> {{method.returnTypeName}} {
        body.{{method.name}}
    }
{%endfor%}

}

{%endif%}{%endfor%}{%endif%}{%endfor%}
{%endif%}
{% endfor %}{% endfor %}
于 2021-11-13T21:44:25.483 回答