diff options
author | Zahary Karadjov <zahary@gmail.com> | 2014-03-16 17:12:30 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2014-03-16 20:42:06 +0200 |
commit | f0953db3ba59f2e23df2fb7932c672f5020db5fb (patch) | |
tree | 4d19cedca26380083c6374f8a97f3b0c0eba8892 /compiler | |
parent | da5d88f04ef8adb7e2606fb16c6cbde770d39fe0 (diff) | |
download | Nim-f0953db3ba59f2e23df2fb7932c672f5020db5fb.tar.gz |
handle arbitrary expressions dependent on static input params in proc signatures
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/ccgutils.nim | 5 | ||||
-rw-r--r-- | compiler/semexprs.nim | 14 | ||||
-rw-r--r-- | compiler/semtypes.nim | 8 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 9 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 8 | ||||
-rw-r--r-- | compiler/types.nim | 11 |
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) |