summary refs log tree commit diff stats
path: root/rod/semcall.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/semcall.nim')
-rw-r--r--rod/semcall.nim36
1 files changed, 29 insertions, 7 deletions
diff --git a/rod/semcall.nim b/rod/semcall.nim
index 1b31558ca..294c0399b 100644
--- a/rod/semcall.nim
+++ b/rod/semcall.nim
@@ -79,20 +79,42 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
     initialBinding = nil
   result = semDirectCallWithBinding(c, n, f, filter, initialBinding)
 
-proc explictGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
+proc explicitGenericInstError(n: PNode): PNode =
+  LocalError(n.info, errCannotInstantiateX, renderTree(n))
+  result = n
+
+proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
   assert n.kind == nkBracketExpr
   for i in 1..sonsLen(n)-1:
     n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
-  # we cannot check for the proper number of type parameters because in
-  # `f[a,b](x, y)` `f` is not resolved yet properly.
-  # XXX: BUG this should be checked somehow!
-  assert n.sons[0].kind == nkSym
+  var s = s
+  var a = n.sons[0]
+  if a.kind == nkSym:
+    # common case; check the only candidate has the right
+    # number of generic type parameters:
+    if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
+      return explicitGenericInstError(n)
+  elif a.kind == nkSymChoice:
+    # choose the generic proc with the proper number of type parameters.
+    # XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
+    # It's good enough for now.
+    var candidateCount = 0
+    for i in countup(0, len(a)-1): 
+      var candidate = a.sons[i].sym
+      if candidate.kind in {skProc, skMethod, skConverter, skIterator}: 
+        # if suffices that the candidate has the proper number of generic 
+        # type parameters:
+        if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
+          s = candidate
+          inc(candidateCount)
+    if candidateCount != 1: return explicitGenericInstError(n)
+  else:
+    assert false
   
   var x: TCandidate
   initCandidate(x, s, n)
   var newInst = generateInstance(c, s, x.bindings, n.info)
   
   markUsed(n, s)
-  result = newSymNode(newInst)
-  result.info = n.info
+  result = newSymNode(newInst, n.info)