implicit generics types as return types. removed the error message for capturing incorrect uses of `proc`

This commit is contained in:
Zahary Karadjov
2012-04-21 02:37:24 +03:00
parent 2f4ae65917
commit 251c44ff04
6 changed files with 67 additions and 60 deletions

View File

@@ -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)

View File

@@ -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")

View File

@@ -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:

View File

@@ -1374,7 +1374,8 @@ proc each*[T](data: var openArray[T], op: proc (x: var T)) =
## `op` to every item in `data`.
for i in 0..data.len-1: op(data[i])
iterator fields*[T: tuple](x: T): expr {.magic: "Fields", noSideEffect.}
iterator fields*[T: tuple](x: T): TObject {.
magic: "Fields", noSideEffect.}
## iterates over every field of `x`. Warning: This really transforms
## the 'for' and unrolls the loop. The current implementation also has a bug
## that affects symbol binding in the loop body.
@@ -1384,7 +1385,8 @@ iterator fields*[S: tuple, T: tuple](x: S, y: T): tuple[a, b: expr] {.
## Warning: This is really transforms the 'for' and unrolls the loop.
## The current implementation also has a bug that affects symbol binding
## in the loop body.
iterator fieldPairs*[T: tuple](x: T): expr {.magic: "FieldPairs", noSideEffect.}
iterator fieldPairs*[T: tuple](x: T): TObject {.
magic: "FieldPairs", noSideEffect.}
## iterates over every field of `x`. Warning: This really transforms
## the 'for' and unrolls the loop. The current implementation also has a bug
## that affects symbol binding in the loop body.

View File

@@ -5,7 +5,7 @@ discard """
type TAlphabet = enum
A, B, C
iterator items(E: typedesc): E =
iterator items(E: typedesc{enum}): E =
for v in low(E)..high(E):
yield v

View File

@@ -52,6 +52,9 @@ Changes affecting backwards compatibility
``PNimrodNode`` which unfortunately breaks the old macro system.
- ``pegs.@`` has been renamed to ``pegs.!*`` and ``pegs.@@`` has been renamed
to ``pegs.!*\`` as ``@`` operators now have different precedence.
- the type ``proc`` (without any params or return type) is now considered a
type class matching all proc types. Use ``proc ()`` to get the old meaning
denoting a proc expecing no arguments and returing no value.
Compiler Additions