mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 15:23:27 +00:00
implicit generics types as return types. removed the error message for capturing incorrect uses of `proc`
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user