summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-09-26 02:22:39 +0200
committerAraq <rumpf_a@web.de>2012-09-26 02:22:39 +0200
commit5538727945d634272f9de03b626bc2ff4e6df873 (patch)
tree4c80af41c84ee7026fb846d101796d276c4b7d35 /compiler
parentca447be43ea6fd0537c4c74bb653fb2abbfb0177 (diff)
parentc899b51b52e8afbf940c0869dc3d35b55adf9ceb (diff)
downloadNim-5538727945d634272f9de03b626bc2ff4e6df873.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim6
-rwxr-xr-xcompiler/ccgstmts.nim1
-rwxr-xr-xcompiler/ccgtypes.nim10
-rwxr-xr-xcompiler/evals.nim8
-rwxr-xr-xcompiler/procfind.nim3
-rwxr-xr-xcompiler/semexprs.nim5
-rwxr-xr-xcompiler/seminst.nim39
-rw-r--r--compiler/semmagic.nim8
-rwxr-xr-xcompiler/semtypes.nim24
-rwxr-xr-xcompiler/sigmatch.nim5
-rwxr-xr-xcompiler/types.nim60
11 files changed, 90 insertions, 79 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index e556ac671..814784029 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -344,6 +344,12 @@ type
     tfFromGeneric,    # type is an instantiation of a generic; this is needed
                       # because for instantiations of objects, structural
                       # type equality has to be used
+    tfInstantiated    # XXX: used to mark generic params after instantiation.
+                      # if the concrete type happens to be an implicit generic
+                      # this can lead to invalid proc signatures in the second
+                      # pass of semProcTypeNode performed after instantiation.
+                      # this won't be needed if we don't perform this redundant
+                      # second pass (stay tuned).
     tfAll,            # type class requires all constraints to be met (default)
     tfAny,            # type class requires any constraint to be met
     tfCapturesEnv,    # whether proc really captures some environment
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 9c25a44ec..9cb5d732b 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -163,6 +163,7 @@ proc genConstStmt(p: BProc, t: PNode) =
     if it.kind == nkCommentStmt: continue 
     if it.kind != nkConstDef: InternalError(t.info, "genConstStmt")
     var c = it.sons[0].sym 
+    if c.typ.containsCompileTimeOnly: continue
     if sfFakeConst in c.flags:
       genSingleVar(p, it)
     elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 054e7182e..0ab4ff200 100755
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -140,6 +140,14 @@ proc mangleName(s: PSym): PRope =
 proc isCompileTimeOnly(t: PType): bool =
   result = t.kind in {tyTypedesc, tyExpr}
 
+proc containsCompileTimeOnly(t: PType): bool =
+  if isCompileTimeOnly(t): return true
+  if t.sons != nil:
+    for i in 0 .. <t.sonsLen:
+      if t.sons[i] != nil and isCompileTimeOnly(t.sons[i]):
+        return true
+  return false
+
 var anonTypeName = toRope"TY"
 
 proc typeName(typ: PType): PRope =
@@ -174,7 +182,7 @@ proc mapType(typ: PType): TCTypeKind =
   of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
   of tyObject, tyTuple: result = ctStruct
   of tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal,
-     tyConst, tyMutable, tyIter, tyTypeDesc: 
+     tyConst, tyMutable, tyIter, tyTypeDesc:
     result = mapType(lastSon(typ))
   of tyEnum: 
     if firstOrd(typ) < 0: 
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 3f801e123..9c73a6b78 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -865,11 +865,11 @@ proc evalTypeTrait*(n: PNode, context: PSym): PNode =
   # by the type traits procs' signatures, but until the
   # code is more mature it doesn't hurt to be extra safe
   internalAssert n.sons.len >= 2 and n.sons[1].kind == nkSym
-  
+
   let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc})
   case n.sons[0].sym.name.s.normalize
   of "name":
-    result = newStrNode(nkStrLit, typ.typeToString(preferExported))
+    result = newStrNode(nkStrLit, typ.typeToString(preferName))
     result.typ = newType(tyString, context)
     result.info = n.info
   else:
@@ -965,7 +965,9 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
   of mParseExprToAst: result = evalParseExpr(c, n)
   of mParseStmtToAst: result = evalParseStmt(c, n)
   of mExpandToAst: result = evalExpandToAst(c, n)
-  of mTypeTrait: result = evalTypeTrait(n, c.module)
+  of mTypeTrait:
+    n.sons[1] = evalAux(c, n.sons[1], {})
+    result = evalTypeTrait(n, c.module)
   of mSlurp: result = evalSlurp(evalAux(c, n.sons[1], {}), c.module)
   of mStaticExec:
     let cmd = evalAux(c, n.sons[1], {})
diff --git a/compiler/procfind.nim b/compiler/procfind.nim
index eefe734b3..fde4d22ea 100755
--- a/compiler/procfind.nim
+++ b/compiler/procfind.nim
@@ -28,7 +28,8 @@ proc equalGenericParams(procA, procB: PNode): bool =
       return
     a = procA.sons[i].sym
     b = procB.sons[i].sym
-    if (a.name.id != b.name.id) or not sameTypeOrNil(a.typ, b.typ): return 
+    if (a.name.id != b.name.id) or 
+        not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return 
     if (a.ast != nil) and (b.ast != nil): 
       if not ExprStructuralEquivalent(a.ast, b.ast): return 
   result = true
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a74907384..5dedc9b82 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -19,7 +19,8 @@ proc restoreOldStyleType(n: PNode) =
   #
   # This is strictly for backward compatibility until 
   # the transition to types as first-class values is complete.
-  n.typ = n.typ.skipTypes({tyTypeDesc})
+  if n.typ.kind == tyTypeDesc and n.typ.sonsLen == 1:
+    n.typ = n.typ.sons[0]
 
 proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = 
   markUsed(n, s)
@@ -376,6 +377,8 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
     
     addSon(result, semExprWithType(c, x))
     var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
+    # turn any concrete typedesc into the absract typedesc type
+    if typ.kind == tyTypeDesc: typ.sons = nil
     for i in countup(1, sonsLen(n) - 1): 
       x = n.sons[i]
       if x.kind == nkExprColonExpr and sonsLen(x) == 2: 
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index ba950422f..61210c0f8 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -33,6 +33,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
       #t = instGenericContainer(c, a, t)
       t = generateTypeInstance(c, pt, a, t)
       #t = ReplaceTypeVarsT(cl, t)
+    t.flags.incl tfInstantiated
     s.typ = t
     addDecl(c, s)
     entry.concreteTypes[i] = t
@@ -41,7 +42,8 @@ proc sameInstantiation(a, b: TInstantiatedSymbol): bool =
   if a.genericSym.id == b.genericSym.id and 
       a.concreteTypes.len == b.concreteTypes.len:
     for i in 0 .. < a.concreteTypes.len:
-      if not sameType(a.concreteTypes[i], b.concreteTypes[i]): return
+      if not compareTypes(a.concreteTypes[i], b.concreteTypes[i],
+                          flags = {TypeDescExactMatch}): return
     result = true
 
 proc GenericCacheGet(c: PContext, entry: var TInstantiatedSymbol): PSym = 
@@ -122,33 +124,6 @@ proc sideEffectsCheck(c: PContext, s: PSym) =
       s.ast.sons[genericParamsPos].kind == nkEmpty:
     c.threadEntries.add(s)
 
-proc applyConcreteTypesToSig(genericProc: PSym, concTypes: seq[PType]): PType =
-  # XXX: This is intended to replace the use of semParamList in generateInstance.
-  # The results of semParamList's analysis are already encoded in the original
-  # proc type and any concrete types may be aplied directly over it.
-  # Besides being more efficient, it will remove the awkward case of
-  # genericParams == nil in semParamList.
-  # Currenly, it fails in some cases such as:
-  # proc inc2*[T](x: var ordinal[T], y = 1) {.magic: "Inc", noSideEffect.}
-  let sig = genericProc.typ
-  result = copyType(sig, getCurrOwner(), false)
-  result.n = sig.n.shallowCopy
-  
-  for i in countup(0, sig.len - 1):
-    let tOrig = sig.sons[i]
-    if tOrig == nil: continue        
-    let oGenParams = genericProc.ast.sons[genericParamsPos]
-    if skipTypes(tOrig, skipPtrs).kind in {tyGenericParam}:
-      var tConcrete = concTypes[tOrig.sym.position]
-      if i > 0:
-        let param = sig.n.sons[i].sym.copySym
-        param.typ = tConcrete
-        result.n.sons[i] = newSymNode(param)
-      result.sons[i] = tConcrete
-    else:
-      result.sons[i] = tOrig
-      if i > 0: result.n.sons[i] = sig.n.sons[i]
-
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, 
                       info: TLineInfo): PSym =
   # no need to instantiate generic templates/macros:
@@ -182,12 +157,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   n.sons[genericParamsPos] = ast.emptyNode
   # semantic checking for the parameters:
   if n.sons[paramsPos].kind != nkEmpty:
-    if false and nimdbg:
-      result.typ = applyConcreteTypesToSig(fn, entry.concreteTypes)
-      addParams(c, result.typ.n, fn.kind)
-    else:
-      removeDefaultParamValues(n.sons[ParamsPos])
-      semParamList(c, n.sons[ParamsPos], nil, result)
+    removeDefaultParamValues(n.sons[ParamsPos])
+    semParamList(c, n.sons[ParamsPos], nil, result)
   else:
     result.typ = newTypeS(tyProc, c)
     rawAddSon(result.typ, nil)
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index da179f0a7..119e1ef19 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -34,10 +34,14 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
 proc semTypeTraits(c: PContext, n: PNode): PNode =
   checkMinSonsLen(n, 2)
   internalAssert n.sons[1].kind == nkSym
-  if n.sons[1].sym.kind == skType:
+  let typArg = n.sons[1].sym
+  if typArg.kind == skType or
+    (typArg.kind == skParam and typArg.typ.sonsLen > 0):
+    # This is either a type known to sem or a typedesc
+    # param to a regular proc (again, known at instantiation)
     result = evalTypeTrait(n, GetCurrOwner())
   else:
-    # pass unmodified to evals
+    # a typedesc variable, pass unmodified to evals
     result = n
 
 proc semOrd(c: PContext, n: PNode): PNode =
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 36b6a449d..5362d6d4a 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -552,7 +552,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
     incl(result.flags, tfFinal)
   
 proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
-  if kind == skMacro:
+  if kind == skMacro and param.typ.kind != tyTypeDesc:
     # within a macro, every param has the type PNimrodNode!
     # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
     let nn = getSysSym"PNimrodNode"
@@ -579,7 +579,8 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
         result.typ = newTypeS(tyExpr, c)
         result.typ.sons = paramType.sons
   of tyTypeDesc:
-    if procKind notin {skTemplate, skMacro}:
+    if procKind notin {skTemplate, skMacro} and 
+       tfInstantiated notin paramType.flags:
       result.typ = newTypeS(tyTypeDesc, c)
       result.typ.sons = paramType.sons
   of tyDistinct:
@@ -777,19 +778,12 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     else:
       result = instGenericContainer(c, n, result)
 
-proc semTypeFromMacro(c: PContext, n: PNode): PType =
-  # Expands a macro or template until a type is returned
-  # results in an error type if the macro expands to something different
-  var sym = expectMacroOrTemplateCall(c, n)
-  markUsed(n, sym)
-  case sym.kind
-  of skMacro:
-    result = semTypeNode(c, semMacroExpr(c, n, n, sym), nil)
-  of skTemplate:
-    result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
+proc semTypeExpr(c: PContext, n: PNode): PType =
+  var n = semExprWithType(c, n)
+  if n.kind == nkSym and n.sym.kind == skType:
+    result = n.sym.typ
   else:
-    LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
-    result = errorType(c)
+    LocalError(n.info, errTypeExpected, n.renderTree)
 
 proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   result = nil
@@ -823,7 +817,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         result.addSonSkipIntLit(t2)
         result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny)
     else:
-      result = semTypeFromMacro(c, n)
+      result = semTypeExpr(c, n)
   of nkCurlyExpr:
     result = semTypeNode(c, n.sons[0], nil)
     if result != nil:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 1d7b47bde..7e482b3d2 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -271,7 +271,7 @@ proc matchTypeClass(c: var TCandidate, typeClass, t: PType): TTypeRelation =
       of tyTypeClass:
         match = matchTypeClass(c, req, t) == isGeneric
       else: nil
-    elif t.kind in {tyTypeDesc, tyObject}:
+    elif t.kind in {tyObject}:
       match = sameType(t, req)
 
     if tfAny in typeClass.flags:
@@ -659,7 +659,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
   of isGeneric:
     inc(m.genericMatches)
     if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
-      result = argOrig
+      if f.kind == tyTypeDesc: result = arg
+      else: result = argOrig
     else:
       result = copyTree(arg)
       result.typ = getInstantiatedType(c, arg, m, f) 
diff --git a/compiler/types.nim b/compiler/types.nim
index 5958914ba..d8879f1b4 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -585,10 +585,17 @@ type
                            ## or a == (distinct b)
     dcEqOrDistinctOf       ## a equals b or a is distinct of b
 
+  TTypeCmpFlag* = enum
+    IgnoreTupleFields,
+    TypeDescExactMatch,
+    AllowCommonBase
+
+  TTypeCmpFlags* = set[TTypeCmpFlag]
+
   TSameTypeClosure = object {.pure.}
     cmp: TDistinctCompare
-    ignoreTupleFields: bool
     recCheck: int
+    flags: TTypeCmpFlags
     s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
                             # (few elements expected)
 
@@ -610,13 +617,14 @@ proc SameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
     if a == nil or b == nil: result = false
     else: result = SameTypeAux(a, b, c)
 
-proc SameTypeOrNil*(a, b: PType): bool =
+proc SameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
   if a == b:
     result = true
   else: 
     if a == nil or b == nil: result = false
     else:
       var c = initSameTypeClosure()
+      c.flags = flags
       result = SameTypeAux(a, b, c)
   
 proc equalParam(a, b: PSym): TParamsEquality = 
@@ -655,7 +663,7 @@ proc equalParams(a, b: PNode): TParamsEquality =
         return paramsNotEqual # paramsIncompatible;
       # continue traversal! If not equal, we can return immediately; else
       # it stays incompatible
-    if not SameTypeOrNil(a.sons[0].typ, b.sons[0].typ): 
+    if not SameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {TypeDescExactMatch}):
       if (a.sons[0].typ == nil) or (b.sons[0].typ == nil): 
         result = paramsNotEqual # one proc has a result, the other not is OK
       else: 
@@ -683,13 +691,13 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
     for i in countup(0, sonsLen(a) - 1): 
       var x = a.sons[i]
       var y = b.sons[i]
-      if c.ignoreTupleFields:
+      if IgnoreTupleFields in c.flags:
         x = skipTypes(x, {tyRange})
         y = skipTypes(y, {tyRange})
       
       result = SameTypeAux(x, y, c)
       if not result: return 
-    if a.n != nil and b.n != nil and not c.ignoreTupleFields: 
+    if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
       for i in countup(0, sonsLen(a.n) - 1): 
         # check field names: 
         if a.n.sons[i].kind == nkSym and b.n.sons[i].kind == nkSym:
@@ -760,7 +768,14 @@ proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool =
   if not SameObjectTree(a.n, b.n, c): return
   result = true
 
-proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = 
+proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
+  if sonsLen(a) != sonsLen(b): return false
+  result = true
+  for i in countup(0, sonsLen(a) - 1):
+    result = SameTypeOrNilAux(a.sons[i], b.sons[i], c)
+    if not result: return 
+
+proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
   template CycleCheck() =
     # believe it or not, the direct check for ``containsOrIncl(c, a, b)``
     # increases bootstrapping time from 2.4s to 3.3s on my laptop! So we cheat
@@ -808,38 +823,43 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     CycleCheck()
     result = sameTuple(a, b, c)
   of tyGenericInst: result = sameTypeAux(lastSon(a), lastSon(b), c)
+  of tyTypeDesc:
+    if TypeDescExactMatch in c.flags:
+      CycleCheck()
+      result = sameChildrenAux(x, y, c)
+    else:
+      result = true
   of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence,
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
      tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
-     tyOrdinal, tyTypeDesc, tyTypeClass:
-    if sonsLen(a) == sonsLen(b):
-      CycleCheck()
-      result = true
-      for i in countup(0, sonsLen(a) - 1):
-        result = SameTypeOrNilAux(a.sons[i], b.sons[i], c)
-        if not result: return 
-      if result and (a.kind == tyProc): 
-        result = a.callConv == b.callConv
+     tyOrdinal, tyTypeClass:
+    CycleCheck()
+    result = sameChildrenAux(a, b, c)
+    if result and (a.kind == tyProc):
+      result = a.callConv == b.callConv
   of tyRange:
-    CycleCheck()    
+    CycleCheck()
     result = SameTypeOrNilAux(a.sons[0], b.sons[0], c) and
         SameValue(a.n.sons[0], b.n.sons[0]) and
         SameValue(a.n.sons[1], b.n.sons[1])
   of tyNone: result = false
 
-proc SameType*(x, y: PType): bool =
+proc sameType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   result = sameTypeAux(x, y, c)
-  
+
 proc sameBackendType*(x, y: PType): bool =
   var c = initSameTypeClosure()
-  c.ignoreTupleFields = true
+  c.flags.incl IgnoreTupleFields
   result = sameTypeAux(x, y, c)
   
-proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool =
+proc compareTypes*(x, y: PType,
+                   cmp: TDistinctCompare = dcEq,
+                   flags: TTypeCmpFlags = {}): bool =
   ## compares two type for equality (modulo type distinction)
   var c = initSameTypeClosure()
   c.cmp = cmp
+  c.flags = flags
   result = sameTypeAux(x, y, c)
   
 proc inheritanceDiff*(a, b: PType): int =