summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-04-21 02:37:24 +0300
committerZahary Karadjov <zahary@gmail.com>2012-04-21 03:24:32 +0300
commit251c44ff04749ed969aab7598b6638e7119e2cd6 (patch)
tree12f0a881ce1d883a87cbf14fa2e69a11b7bc58ef /compiler
parent2f4ae65917566c0621ee650dc692ce4edf64d06f (diff)
downloadNim-251c44ff04749ed969aab7598b6638e7119e2cd6.tar.gz
implicit generics types as return types. removed the error message for capturing incorrect uses of ``proc``
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/semtypes.nim82
-rwxr-xr-xcompiler/semtypinst.nim3
-rwxr-xr-xcompiler/sigmatch.nim31
3 files changed, 59 insertions, 57 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index a201d1f03..f9420d410 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -190,7 +190,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         # This is a typedesc param. is it already bound?
         # it's not bound when it's also used as return type for example
         if result.typ.sonsLen > 0:
-          return result.typ.sons[0].sym
+          let bound = result.typ.sons[0].sym
+          if bound != nil:
+            return bound
+          else:
+            return result.typ.sym
         else:
           return result.typ.sym
       if result.kind != skType: GlobalError(n.info, errTypeExpected)
@@ -536,6 +540,36 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
     result.typ = copyType(paramType, getCurrOwner(), false)
   else: nil
 
+proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
+                   paramType: PType, paramName: string): PType =
+  ## Params having implicit generic types or pseudo types such as 'expr'
+  ## need to be added to the generic params lists. 
+  ## 'expr' is different from 'expr{string}' so we must first call 
+  ## paramTypeClass to get the actual type we are going to use.
+  result = paramType
+  var (typeClass, paramTypId) = paramTypeClass(c, paramType, procKind)
+  let isAnon = paramTypId == nil
+  if typeClass != nil:
+    if isAnon: paramTypId = getIdent(paramName & ":type")
+    if genericParams == nil:
+      # genericParams is nil when the proc is being instantiated
+      # the resolved type will be in scope then
+      result = SymtabGet(c.tab, paramTypId).AssertNotNil.typ
+    else:
+      block addImplicitGeneric:
+        # is this a bindOnce type class already present in the param list?
+        for i in countup(0, genericParams.len - 1):
+          if genericParams.sons[i].sym.name == paramTypId:
+            result = genericParams.sons[i].typ
+            break addImplicitGeneric
+
+        var s = newSym(skType, paramTypId, getCurrOwner())
+        if isAnon: s.flags.incl(sfAnon)
+        s.linkTo(typeClass)
+        s.position = genericParams.len
+        genericParams.addSon(newSymNode(s))
+        result = typeClass
+
 proc semProcTypeNode(c: PContext, n, genericParams: PNode, 
                      prev: PType, kind: TSymKind): PType = 
   var
@@ -583,37 +617,15 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
     for j in countup(0, length-3): 
       var arg = newSymS(skParam, a.sons[j], c)
-      var endingType = typ
-      var (typeClass, paramTypId) = paramTypeClass(c, typ, kind)
-      if typeClass != nil:
-        if paramTypId == nil: paramTypId = getIdent(arg.name.s & ":type")
-        if genericParams == nil:
-          # genericParams is nil when the proc is being instantiated
-          # the resolved type will be in scope then
-          endingType = SymtabGet(c.tab, paramTypId).AssertNotNil.typ
-        else:
-          block addImplicitGeneric:
-            # is this a bindOnce type class already present in the param list?
-            for i in countup(0, genericParams.len - 1):
-              if genericParams.sons[i].sym.name == paramTypId:
-                endingType = genericParams.sons[i].typ
-                break addImplicitGeneric
-
-            var s = newSym(skType, paramTypId, getCurrOwner())
-            s.flags.incl(sfAnon)
-            s.linkTo(typeClass)
-            s.position = genericParams.len
-            genericParams.addSon(newSymNode(s))
-            endingType = typeClass
-      
-      arg.typ = endingType
+      var finalType = liftParamType(c, kind, genericParams, typ, arg.name.s)
+      arg.typ = finalType
       arg.position = counter
       inc(counter)
       if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def)
       if ContainsOrIncl(check, arg.name.id): 
         LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
       addSon(result.n, newSymNode(arg))
-      addSon(result, endingType)
+      addSon(result, finalType)
       addParamOrResult(c, arg, kind)
 
   if n.sons[0].kind != nkEmpty:
@@ -621,6 +633,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     # turn explicit 'void' return type into 'nil' because the rest of the 
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
+      if r.sym == nil or sfAnon notin r.sym.flags:
+        r = liftParamType(c, kind, genericParams, r, "result")
       result.sons[0] = r
       res.typ = result.sons[0]
 
@@ -778,6 +792,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkVarTy: result = semVarType(c, n, prev)
   of nkDistinctTy: result = semDistinct(c, n, prev)
   of nkProcTy: 
+    if n.sonsLen == 0: return newConstraint(c, tyProc)
     checkSonsLen(n, 2)
     openScope(c.tab)
     result = semProcTypeNode(c, n.sons[0], nil, prev, skProc)
@@ -785,7 +800,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
     s.typ = result
     pragma(c, s, n.sons[1], procTypePragmas)
-    closeScope(c.tab)    
+    closeScope(c.tab)
   of nkEnumTy: result = semEnum(c, n, prev)
   of nkType: result = n.typ
   of nkStmtListType: result = semStmtListType(c, n, prev)
@@ -836,14 +851,11 @@ proc processMagicType(c: PContext, m: PSym) =
   else: GlobalError(m.info, errTypeExpected)
   
 proc semGenericConstraints(c: PContext, n: PNode, result: PType) = 
-  case n.kind
-  of nkProcTy: result.addSon(newConstraint(c, tyProc))
-  else:
-    var x = semTypeNode(c, n, nil)
-    if x.kind in StructuralEquivTypes and (
-        sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
-      x = newConstraint(c, x.kind)
-    result.addSon(x)
+  var x = semTypeNode(c, n, nil)
+  if x.kind in StructuralEquivTypes and (
+      sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
+    x = newConstraint(c, x.kind)
+  result.addSon(x)
 
 proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = 
   result = copyNode(n)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 4a576c00d..bfd706bea 100755
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -17,7 +17,8 @@ proc checkPartialConstructedType(info: TLineInfo, t: PType) =
   elif t.kind == tyVar and t.sons[0].kind == tyVar:
     LocalError(info, errVarVarTypeNotAllowed)
 
-proc checkConstructedType*(info: TLineInfo, t: PType) = 
+proc checkConstructedType*(info: TLineInfo, typ: PType) = 
+  var t = typ.skipTypes({tyDistinct})
   if t.kind in {tyTypeClass}: nil
   elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: 
     LocalError(info, errInvalidPragmaX, "acyclic")
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index da804c2cb..9881e84a3 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -459,33 +459,22 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
           if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
             InternalError("wrong instantiated type!")
           put(mapping, f.sons[i], x)
-  of tyGenericParam: 
+  of tyGenericParam, tyTypeClass:
     var x = PType(idTableGet(mapping, f))
-    if x == nil: 
-      if sonsLen(f) == 0: 
-        # no constraints
+    if x == nil:
+      result = matchTypeClass(mapping, f, a)
+      if result == isGeneric:
         var concrete = concreteType(mapping, a)
-        if concrete != nil:
+        if concrete == nil:
+          result = isNone
+        else:
           put(mapping, f, concrete)
-          result = isGeneric
-      else: 
-        # check constraints:
-        for i in countup(0, sonsLen(f) - 1): 
-          if typeRel(mapping, f.sons[i], a) >= isSubtype: 
-            var concrete = concreteType(mapping, a)
-            if concrete != nil: 
-              put(mapping, f, concrete)
-              result = isGeneric
-            break 
-    elif a.kind == tyEmpty: 
+    elif a.kind == tyEmpty:
       result = isGeneric
-    elif x.kind == tyGenericParam: 
+    elif x.kind == tyGenericParam:
       result = isGeneric
-    else: 
+    else:
       result = typeRel(mapping, x, a) # check if it fits
-  of tyTypeClass:
-    result = matchTypeClass(mapping, f, a)
-    if result == isGeneric: put(mapping, f, a)
   of tyTypeDesc:
     if a.kind == tyTypeDesc:
       if f.sonsLen == 0: