重载解析
在调用 p(args) 中选择匹配最佳的例程 p 。 如果多个例程同样匹配,则在语义分析期间报告歧义。
args中的每个arg都需要匹配。参数可以匹配的方式有多种不同的类别。 设 f 是形式参数的类型, a 是参数的类型。
- 准确匹配: a 和 f 是相同类型。
- 字面匹配: a 是值为 v 的整型字面值, f 是有符号或无符号整型 v 在 f 的范围里. 或: a 是值为 v
的浮点字面值,
f 是浮点类型 v 在 f 的范围里。 - 泛型匹配: 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 的匹配数。
如果下列算法返回真,例程 p 比 q 更匹配:
- for each matching category m in ["exact match", "literal match",
- "generic match", "subtype match", "integral match", "conversion match"]:
- if count(p, m) > count(q, m): return true
- elif count(p, m) == count(q, m):
- discard "continue with next category m"
- else:
- return false
return "ambiguous"
一些示例:
- proc takesInt(x: int) = echo "int"
- proc takesInt[T](x: T) = echo "T"
- proc takesInt(x: int16) = echo "int16"
- takesInt(4) # "int"
- var x: int32
- takesInt(x) # "T"
- var y: int16
- takesInt(y) # "int16"
- var z: range[0..4] = 0
- takesInt(z) # "T"
如果算法返回 "歧义" 则执行进一步消歧: 如果参数 a 通过子类型关系匹配 p 的参数类型 f 和 q 的 g ,则考虑继承深度:
- type
- A = object of RootObj
- B = object of A
- C = object of B
- proc p(obj: A) =
- echo "A"
- proc p(obj: B) =
- echo "B"
- var c = C()
- # not ambiguous, calls 'B', not 'A' since B is a subtype of A
- # but not vice versa:
- p(c)
- proc pp(obj: A, obj2: B) = echo "A B"
- proc pp(obj: B, obj2: A) = echo "B A"
- # but this is ambiguous:
- pp(c, c)
同样,对于通用匹配,匹配的结果中首选最特化的泛型类型:
- proc gen[T](x: ref ref T) = echo "ref ref T"
- proc gen[T](x: ref T) = echo "ref T"
- proc gen[T](x: T) = echo "T"
- var ri: ref int
- gen(ri) # "ref T"