diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-04-21 02:37:24 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-04-21 03:24:32 +0300 |
commit | 251c44ff04749ed969aab7598b6638e7119e2cd6 (patch) | |
tree | 12f0a881ce1d883a87cbf14fa2e69a11b7bc58ef /compiler | |
parent | 2f4ae65917566c0621ee650dc692ce4edf64d06f (diff) | |
download | Nim-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-x | compiler/semtypes.nim | 82 | ||||
-rwxr-xr-x | compiler/semtypinst.nim | 3 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 31 |
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: |