diff options
author | Araq <rumpf_a@web.de> | 2013-05-27 23:20:41 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-05-27 23:20:41 +0200 |
commit | a8ba628bcd2535bc55e3bf67737e93ae99906a63 (patch) | |
tree | 73ba562525b0c97bd2a3a5702c33585b2a810c22 | |
parent | 75c586bbe1cc649b36fc00362ab40ebb1d163d9f (diff) | |
download | Nim-a8ba628bcd2535bc55e3bf67737e93ae99906a63.tar.gz |
Revert "fixes #267"
This reverts commit 7fccdedcb5d1e583039b2ea2ae6564412a0f5104.
-rw-r--r-- | compiler/ast.nim | 15 | ||||
-rw-r--r-- | compiler/semdata.nim | 5 | ||||
-rw-r--r-- | compiler/seminst.nim | 103 | ||||
-rw-r--r-- | compiler/semtypes.nim | 156 | ||||
-rw-r--r-- | compiler/types.nim | 2 |
5 files changed, 97 insertions, 184 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index e35bf25ef..d4d5bce9c 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -365,8 +365,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 - tfUnresolved, # marks unresolved typedesc params: e.g. - # proc foo(T: typedesc, list: seq[T]): var T + 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). tfRetType, # marks return types in proc (used to detect type classes # used as return types for return type inference) tfAll, # type class requires all constraints to be met (default) @@ -1003,8 +1007,8 @@ proc NewType(kind: TTypeKind, owner: PSym): PType = result.size = - 1 result.align = 2 # default alignment result.id = getID() - when debugIds: - RegisterId(result) + when debugIds: + RegisterId(result) #if result.id < 2000 then # MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) @@ -1041,6 +1045,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType = if keepId: result.id = t.id else: + result.id = getID() when debugIds: RegisterId(result) result.sym = t.sym # backend-info should not be copied @@ -1285,7 +1290,7 @@ proc isGenericRoutine*(s: PSym): bool = of skProc, skTemplate, skMacro, skIterator, skMethod, skConverter: result = s.ast != nil and s.ast[genericParamsPos].kind != nkEmpty else: nil - + proc isRoutine*(s: PSym): bool {.inline.} = result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod, skConverter} diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 127842a5a..4c94d0812 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -207,11 +207,6 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType = proc newTypeS(kind: TTypeKind, c: PContext): PType = result = newType(kind, getCurrOwner()) -proc newTypeWithSons*(c: PContext, kind: TTypeKind, - sons: seq[PType]): PType = - result = newType(kind, getCurrOwner()) - result.sons = sons - proc errorType*(c: PContext): PType = ## creates a type representing an error state result = newTypeS(tyError, c) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 35ed00965..9dc99d173 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -38,6 +38,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 @@ -83,28 +84,11 @@ proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) = else: for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap) -proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) - proc instantiateBody(c: PContext, n: PNode, result: PSym) = if n.sons[bodyPos].kind != nkEmpty: # add it here, so that recursive generic procs are possible: addDecl(c, result) pushProcCon(c, result) - # add params to scope - let origFormalParams = result.typ.n - result.typ.n = newNodeI(nkFormalParams, - origFormalParams.info, - origFormalParams.len) - result.typ.n.sons[0] = copyNode(origFormalParams.sons[0]) - for i in 1 .. <result.typ.len: - let origParam = origFormalParams[i].sym - var param = copySym(origParam) - result.typ.n.sons[i] = newSymNode(param) - param.typ = result.typ.sons[i] - param.ast = origParam.ast - param.owner = result - addParamOrResult(c, param, result.kind) - # debug result.typ.n maybeAddResult(c, result, n) var b = n.sons[bodyPos] var symMap: TIdTable @@ -139,71 +123,7 @@ proc sideEffectsCheck(c: PContext, s: PSym) = s.ast.sons[genericParamsPos].kind == nkEmpty: c.threadEntries.add(s) -proc instGenericContainer(c: PContext, info: TLineInfo, header: PType): PType = - var cl: TReplTypeVars - InitIdTable(cl.symMap) - InitIdTable(cl.typeMap) - cl.info = info - cl.c = c - result = ReplaceTypeVarsT(cl, header) - -proc instGenericContainer(c: PContext, n: PNode, header: PType): PType = - result = instGenericContainer(c, n.info, header) - -proc fixupProcTypeR(c: PContext, genericType: PType, - inst: TInstantiation): PType = - result = genericType - if result == nil: return - - case genericType.kind - of tyGenericParam, tyTypeClass: - result = inst.concreteTypes[genericType.sym.position] - of tyTypeDesc: - result = inst.concreteTypes[genericType.sym.position] - if tfUnresolved in genericType.flags: - result = result.sons[0] - of tyExpr: - result = inst.concreteTypes[genericType.sym.position] - of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc, - tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs: - if genericType.sons == nil: return - for i in 0 .. <genericType.sons.len: - let changed = fixupProcTypeR(c, genericType.sons[i], inst) - if changed != genericType.sons[i]: - if result == genericType: - # the first detected change initializes the result - result = copyType(genericType, genericType.owner, true) - if genericType.n != nil: - result.n = copyTree(genericType.n) - result.sons[i] = changed - if result.n != nil: - if result.n.kind == nkRecList: - result.n.sons[i].typ = changed - if result.n.kind == nkFormalParams: - if i == 0: - nil - else: - let origParam = result.n.sons[i].sym - var param = copySym(origParam) - param.typ = changed - param.ast = origParam.ast - result.n.sons[i] = newSymNode(param) - - of tyGenericInvokation: - result = newTypeWithSons(c, tyGenericInvokation, genericType.sons) - for i in 1 .. <genericType.sons.len: - result.sons[i] = fixupProcTypeR(c, result.sons[i], inst) - result = instGenericContainer(c, getInfoContext(-1), result) - else: - nil - -proc fixupProcType(c: PContext, genericType: PType, - inst: TInstantiation): PType = - result = copyType(genericType, genericType.owner, false) - for i in 0 .. <result.sons.len: - result.sons[i] = fixupProcTypeR(c, result.sons[i], inst) - -proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, +proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym = # no need to instantiate generic templates/macros: if fn.kind in {skTemplate, skMacro}: return fn @@ -232,8 +152,16 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, var entry = TInstantiation.new entry.sym = result instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[]) - result.typ = fixupProcType(c, fn.typ, entry[]) n.sons[genericParamsPos] = ast.emptyNode + # semantic checking for the parameters: + if n.sons[paramsPos].kind != nkEmpty: + removeDefaultParamValues(n.sons[ParamsPos]) + semParamList(c, n.sons[ParamsPos], nil, result) + else: + result.typ = newTypeS(tyProc, c) + rawAddSon(result.typ, nil) + result.typ.callConv = fn.typ.callConv + if result.kind == skIterator: result.typ.flags.incl(tfIterator) var oldPrc = GenericCacheGet(fn, entry[]) if oldPrc == nil: fn.procInstCache.safeAdd(entry) @@ -254,5 +182,12 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, c.friendModule = oldFriend dec(c.InstCounter) if result.kind == skMethod: finishMethod(c, result) - + +proc instGenericContainer(c: PContext, n: PNode, header: PType): PType = + var cl: TReplTypeVars + InitIdTable(cl.symMap) + InitIdTable(cl.typeMap) + cl.info = n.info + cl.c = c + result = ReplaceTypeVarsT(cl, header) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index c975abb26..658b3507f 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -216,7 +216,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = else: LocalError(n.info, errXExpectsOneTypeParam, "ordinal") result = newOrPrevType(tyError, prev, c) - + proc semTypeIdent(c: PContext, n: PNode): PSym = if n.kind == nkSym: result = n.sym @@ -235,9 +235,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = if result.typ.sym == nil: LocalError(n.info, errTypeExpected) return errorSym(c, n) - result = result.typ.sym.copySym - result.typ = copyType(result.typ, result.typ.owner, true) - result.typ.flags.incl tfUnresolved + return result.typ.sym if result.kind != skType: # this implements the wanted ``var v: V, x: V`` feature ... var ov: TOverloadIter @@ -575,95 +573,81 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = else: if sfGenSym notin param.flags: addDecl(c, param) -proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, - paramType: PType, paramName: string, - info: TLineInfo, anon = false): PType = - if procKind in {skMacro, skTemplate}: - # generic param types in macros and templates affect overload - # resolution, but don't work as generic params when it comes - # to proc instantiation. We don't need to lift such params here. - return - - proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType = - let finalTypId = if typId != nil: typId - else: getIdent(paramName & ":type") - # 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.id == finalTypId.id: - return genericParams.sons[i].typ - - var s = newSym(skType, finalTypId, getCurrOwner(), info) - if typId == nil: s.flags.incl(sfAnon) - s.linkTo(typeClass) - s.position = genericParams.len - genericParams.addSon(newSymNode(s)) - result = typeClass - - # XXX: There are codegen errors if this is turned into a nested proc - template liftingWalk(typ: PType, anonFlag = false): expr = - liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag) - #proc liftingWalk(paramType: PType, anon = false): PType = - - var paramTypId = if not anon and paramType.sym != nil: paramType.sym.name - else: nil - - template addImplicitGeneric(e: expr): expr = - addImplicitGenericImpl(e, paramTypId) - +proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind): + tuple[typ: PType, id: PIdent] = + # if typ is not-nil, the param should be turned into a generic param + # if id is not nil, the generic param will bind just once (see below) case paramType.kind: of tyExpr: if paramType.sonsLen == 0: # proc(a, b: expr) # no constraints, treat like generic param - result = addImplicitGeneric(newTypeS(tyGenericParam, c)) + result.typ = newTypeS(tyGenericParam, c) else: # proc(a: expr{string}, b: expr{nkLambda}) # overload on compile time values and AST trees - result = addImplicitGeneric(c.newTypeWithSons(tyExpr, paramType.sons)) + result.typ = newTypeS(tyExpr, c) + result.typ.sons = paramType.sons of tyTypeDesc: - if tfUnresolved notin paramType.flags: - result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, paramType.sons)) + if tfInstantiated notin paramType.flags: + result.typ = newTypeS(tyTypeDesc, c) + result.typ.sons = paramType.sons of tyDistinct: - if paramType.sonsLen == 1: - # disable the bindOnce behavior for the type class - result = liftingWalk(paramType.sons[0], true) - of tySequence, tySet, tyArray, tyOpenArray: - # XXX: this is a bit strange, but proc(s: seq) - # produces tySequence(tyGenericParam, null). - # This also seems to be true when creating aliases - # like: type myseq = distinct seq. - # Maybe there is another better place to associate - # the seq type class with the seq identifier. - if paramType.lastSon == nil: - let typ = c.newTypeWithSons(tyTypeClass, @[newTypeS(paramType.kind, c)]) - result = addImplicitGeneric(typ) - else: - for i in 0 .. <paramType.sons.len: - var lifted = liftingWalk(paramType.sons[i]) - if lifted != nil: - paramType.sons[i] = lifted - result = paramType + result = paramTypeClass(c, paramType.lastSon, procKind) + # disable the bindOnce behavior for the type class + result.id = nil + return of tyGenericBody: # type Foo[T] = object # proc x(a: Foo, b: Foo) - var typ = newTypeS(tyTypeClass, c) - typ.addSonSkipIntLit(paramType) - result = addImplicitGeneric(typ) - of tyGenericInst: - for i in 1 .. (paramType.sons.len - 2): - var lifted = liftingWalk(paramType.sons[i]) - if lifted != nil: - paramType.sons[i] = lifted - result = paramType - - if result != nil: - result.kind = tyGenericInvokation - result.sons.setLen(result.sons.len - 1) + result.typ = newTypeS(tyTypeClass, c) + result.typ.addSonSkipIntLit(paramType) of tyTypeClass: - result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false)) + result.typ = copyType(paramType, getCurrOwner(), false) else: nil + # bindOnce by default + if paramType.sym != nil: result.id = paramType.sym.name + +proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, + paramType: PType, paramName: string, + info: TLineInfo): PType = + result = paramType + if procKind in {skMacro, skTemplate}: + # generic param types in macros and templates affect overload + # resolution, but don't work as generic params when it comes + # to proc instantiation. We don't need to lift such params here. + return + ## 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. + 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 + let s = searchInScopes(c, paramTypId) + # tests/run/tinterf triggers this: + if s != nil: result = s.typ + else: + LocalError(info, errCannotInstantiateX, paramName) + result = errorType(c) + 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.id == paramTypId.id: + result = genericParams.sons[i].typ + break addImplicitGeneric - # result = liftingWalk(paramType) + var s = newSym(skType, paramTypId, getCurrOwner(), info) + if isAnon: s.flags.incl(sfAnon) + s.linkTo(typeClass) + s.position = genericParams.len + genericParams.addSon(newSymNode(s)) + result = typeClass proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType = if n.kind == nkCurlyExpr: @@ -702,9 +686,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, length = sonsLen(a) hasType = a.sons[length-2].kind != nkEmpty hasDefault = a.sons[length-1].kind != nkEmpty + if hasType: typ = semParamType(c, a.sons[length-2], constraint) - + if hasDefault: def = semExprWithType(c, a.sons[length-1]) # check type compability between def.typ and typ: @@ -722,9 +707,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue for j in countup(0, length-3): var arg = newSymG(skParam, a.sons[j], c) - let lifted = liftParamType(c, kind, genericParams, typ, - arg.name.s, arg.info) - let finalType = if lifted != nil: lifted else: typ.skipIntLit + var finalType = liftParamType(c, kind, genericParams, typ, + arg.name.s, arg.info).skipIntLit arg.typ = finalType arg.position = counter arg.constraint = constraint @@ -742,13 +726,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # compiler only checks for 'nil': if skipTypes(r, {tyGenericInst}).kind != tyEmpty: if r.sym == nil or sfAnon notin r.sym.flags: - let lifted = liftParamType(c, kind, genericParams, r, "result", - n.sons[0].info) - if lifted != nil: r = lifted + r = liftParamType(c, kind, genericParams, r, "result", n.sons[0].info) r.flags.incl tfRetType result.sons[0] = skipIntLit(r) res.typ = result.sons[0] - + proc semStmtListType(c: PContext, n: PNode, prev: PType): PType = checkMinSonsLen(n, 1) var length = sonsLen(n) @@ -1030,7 +1012,6 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = if n.kind != nkGenericParams: illFormedAst(n) return - var position = 0 for i in countup(0, sonsLen(n)-1): var a = n.sons[i] if a.kind != nkIdentDefs: illFormedAst(n) @@ -1068,7 +1049,6 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = if def.kind != nkEmpty: s.ast = def s.typ.sym = s if father != nil: addSonSkipIntLit(father, s.typ) - s.position = position - inc position + s.position = i addSon(result, newSymNode(s)) if sfGenSym notin s.flags: addDecl(c, s) diff --git a/compiler/types.nim b/compiler/types.nim index 731c1f12a..3096b73c8 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -982,8 +982,6 @@ proc matchTypeClass*(bindings: var TIdTable, typeClass, t: PType): bool = # if the loop finished without returning, either all constraints matched # or none of them matched. result = if tfAny in typeClass.flags: false else: true - if result == true: - IdTablePut(bindings, typeClass, t) proc matchTypeClass*(typeClass, typ: PType): bool = var bindings: TIdTable |