• 重载解析

    重载解析

    在调用 p(args) 中选择匹配最佳的例程 p 。 如果多个例程同样匹配,则在语义分析期间报告歧义。

    args中的每个arg都需要匹配。参数可以匹配的方式有多种不同的类别。 设 f 是形式参数的类型, a 是参数的类型。

    • 准确匹配: a 和 f 是相同类型。
    • 字面匹配: a is an integer literal of value v and f is a signed or unsigned integer type and v is in f's range. Or: a is a floating point literal of value v and f is a floating point type and v is in f's range.
    • 泛型匹配: f 是泛型类型且 a 匹配, 例如 a 是 int 且 f 是泛型限制 (受限) 形参类型 (像 [T] 或 [T: int|char].
    • 子范围或子类型匹配: a is a range[T] and T matches f exactly. Or: a is a subtype of f.
    • 整数转换匹配: a 可转换为 f 且 f 和 a 是同样的整数或浮点类型。
    • 转换匹配: a 可能通过用户定义的转换器转换为 f 。 这些匹配类别具有优先级:完全匹配优于字面值匹配,并且优于通用匹配等。 在下面的 count(p, m) 计算 m 匹配过程 p 的匹配数。

    A routine p matches better than a routine q if the following algorithm returns true:

    1. for each matching category m in ["exact match", "literal match",
    2. "generic match", "subtype match",
    3. "integral match", "conversion match"]:
    4. if count(p, m) > count(q, m): return true
    5. elif count(p, m) == count(q, m):
    6. discard "continue with next category m"
    7. else:
    8. return false
    9. return "ambiguous"

    一些示例:

    1. proc takesInt(x: int) = echo "int"
    2. proc takesInt[T](x: T) = echo "T"
    3. proc takesInt(x: int16) = echo "int16"
    4.  
    5. takesInt(4) # "int"
    6. var x: int32
    7. takesInt(x) # "T"
    8. var y: int16
    9. takesInt(y) # "int16"
    10. var z: range[0..4] = 0
    11. takesInt(z) # "T"

    如果算法返回 "歧义" 则执行进一步消歧: 如果参数 a 通过子类型关系匹配 p 的参数类型 fqg ,则考虑继承深度:

    1. type
    2. A = object of RootObj
    3. B = object of A
    4. C = object of B
    5.  
    6. proc p(obj: A) =
    7. echo "A"
    8.  
    9. proc p(obj: B) =
    10. echo "B"
    11.  
    12. var c = C()
    13. # not ambiguous, calls 'B', not 'A' since B is a subtype of A
    14. # but not vice versa:
    15. p(c)
    16.  
    17. proc pp(obj: A, obj2: B) = echo "A B"
    18. proc pp(obj: B, obj2: A) = echo "B A"
    19.  
    20. # but this is ambiguous:
    21. pp(c, c)

    同样,对于通用匹配,匹配的结果中首选最特化的泛型类型:

    1. proc gen[T](x: ref ref T) = echo "ref ref T"
    2. proc gen[T](x: ref T) = echo "ref T"
    3. proc gen[T](x: T) = echo "T"
    4.  
    5. var ri: ref int
    6. gen(ri) # "ref T"