summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2014-03-16 17:12:30 +0200
committerZahary Karadjov <zahary@gmail.com>2014-03-16 20:42:06 +0200
commitf0953db3ba59f2e23df2fb7932c672f5020db5fb (patch)
tree4d19cedca26380083c6374f8a97f3b0c0eba8892 /compiler
parentda5d88f04ef8adb7e2606fb16c6cbde770d39fe0 (diff)
downloadNim-f0953db3ba59f2e23df2fb7932c672f5020db5fb.tar.gz
handle arbitrary expressions dependent on static input params in proc signatures
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/ccgutils.nim5
-rw-r--r--compiler/semexprs.nim14
-rw-r--r--compiler/semtypes.nim8
-rw-r--r--compiler/semtypinst.nim9
-rw-r--r--compiler/sigmatch.nim8
-rw-r--r--compiler/types.nim11
7 files changed, 42 insertions, 16 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index a48ba9dc5..1dff21503 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -432,8 +432,9 @@ type
     tfFromGeneric,    # type is an instantiation of a generic; this is needed
                       # because for instantiations of objects, structural
                       # type equality has to be used
-    tfUnresolved,     # marks unresolved typedesc params: e.g.
+    tfUnresolved,     # marks unresolved typedesc/static params: e.g.
                       # proc foo(T: typedesc, list: seq[T]): var T
+                      # proc foo(L: static[int]): array[L, int]
     tfRetType,        # marks return types in proc (used to detect type classes 
                       # used as return types for return type inference)
     tfCapturesEnv,    # whether proc really captures some environment
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index da1673ca4..1d8f0158b 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -87,9 +87,10 @@ proc getUniqueType*(key: PType): PType =
       gCanonicalTypes[k] = key
       result = key
   of tyTypeDesc, tyTypeClasses, tyGenericParam,
-     tyFromExpr, tyStatic, tyFieldAccessor:
+     tyFromExpr, tyFieldAccessor:
     internalError("GetUniqueType")
-  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
+  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable,
+     tyConst, tyIter, tyStatic:
     result = getUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
      tyOpenArray, tyArray, tySet, tyRange, tyTuple,
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 5a12156ec..2c7408047 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -612,7 +612,19 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
       if result.isNil: result = n
       else: return result
     result.typ = semfold.getIntervalType(callee.magic, call)
-    
+  
+  block maybeLabelAsStatic:
+    # XXX: temporary work-around needed for tlateboundstatic.
+    # This is certainly not correct, but it will get the job
+    # done until we have a more robust infrastructure for
+    # implicit statics.
+    if n.len > 1:
+      for i in 1 .. <n.len:
+        if n[i].typ.kind != tyStatic or tfUnresolved notin n[i].typ.flags:
+          break maybeLabelAsStatic
+      n.typ = newTypeWithSons(c, tyStatic, @[n.typ])
+      n.typ.flags.incl tfUnresolved
+
   # optimization pass: not necessary for correctness of the semantic pass
   if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
      {sfForward, sfImportc} * callee.flags == {}:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 74378801d..4e97a6744 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -704,11 +704,13 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tyStatic:
     # proc(a: expr{string}, b: expr{nkLambda})
     # overload on compile time values and AST trees
+    if paramType.n != nil: return # this is a concrete type
+    if tfUnresolved in paramType.flags: return # already lifted
     let base = paramType.base.maybeLift
     if base.isMetaType and procKind == skMacro:
       localError(info, errMacroBodyDependsOnGenericTypes, paramName)
     result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
-    result.flags.incl tfHasStatic
+    result.flags.incl({tfHasStatic, tfUnresolved})
   
   of tyTypeDesc:
     if tfUnresolved notin paramType.flags:
@@ -911,7 +913,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
 
   if genericParams != nil:
     for n in genericParams:
-      if tfUnresolved in n.sym.typ.flags:
+      if tfWildcard in n.sym.typ.flags:
         n.sym.kind = skType
         n.sym.typ.flags.excl tfWildcard
 
@@ -981,7 +983,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
       let typ = m.call[i].typ.skipTypes({tyTypeDesc})
       if containsGenericType(typ): isConcrete = false
       addToResult(typ)
-    
+   
     if isConcrete:
       if s.ast == nil:
         localError(n.info, errCannotInstantiateX, s.name.s)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 30810a1d1..4a8a463f5 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -96,8 +96,11 @@ proc replaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
   checkMetaInvariants(cl, result)
 
 proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
+  let t = replaceTypeVarsT(cl, n.typ)
+  if t != nil and t.kind == tyStatic and t.n != nil:
+    return t.n
   result = copyNode(n)
-  result.typ = replaceTypeVarsT(cl, n.typ)
+  result.typ = t
   if result.kind == nkSym: result.sym = replaceTypeVarsS(cl, n.sym)
   let isCall = result.kind in nkCallKinds
   for i in 0 .. <n.safeLen:
@@ -197,10 +200,10 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
     result = copySym(s, false)
     incl(result.flags, sfFromGeneric)
     idTablePut(cl.symMap, s, result)
-    result.typ = replaceTypeVarsT(cl, s.typ)
     result.owner = s.owner
+    result.typ = replaceTypeVarsT(cl, s.typ)
     result.ast = replaceTypeVarsN(cl, s.ast)
-
+    
 proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 4ad7849e5..b87d27cb4 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1053,11 +1053,15 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     # and finally start using tyTypedesc for generic types properly.
     if argType.kind == tyGenericParam and tfWildcard in argType.flags:
       argType.assignType(f)
-      argType.flags.incl tfUnresolved
       # put(m.bindings, f, argType)
       return argSemantized
 
-    if argType.kind != tyStatic:
+    if argType.kind == tyStatic:
+      if m.calleeSym.kind == skType:
+        result = newNodeI(nkType, argOrig.info)
+        result.typ = makeTypeFromExpr(c, arg)
+        return
+    else:
       var evaluated = c.semTryConstExpr(c, arg)
       if evaluated != nil:
         arg.typ = newTypeS(tyStatic, c)
diff --git a/compiler/types.nim b/compiler/types.nim
index 8cf91da8b..89b15c4a8 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1255,15 +1255,18 @@ proc getSize(typ: PType): BiggestInt =
   if result < 0: internalError("getSize: " & $typ.kind)
 
 proc containsGenericTypeIter(t: PType, closure: PObject): bool =
-  if t.kind in GenericTypes + tyTypeClasses + {tyFromExpr}:
-    return true
+  if t.kind == tyStatic:
+    return t.n == nil
 
   if t.kind == tyTypeDesc:
     if t.base.kind == tyNone: return true
     if containsGenericTypeIter(t.base, closure): return true
     return false
-  
-  return t.kind == tyStatic and t.n == nil
+
+  if t.kind in GenericTypes + tyTypeClasses + {tyFromExpr}:
+    return true
+
+  return false
 
 proc containsGenericType*(t: PType): bool = 
   result = iterOverType(t, containsGenericTypeIter, nil)