Merge branch 'upstream' into devel
Conflicts: compiler/ccgutils.nim compiler/msgs.nim compiler/sem.nim compiler/semexprs.nim compiler/seminst.nim compiler/semmagic.nim compiler/semstmts.nim compiler/semtypes.nim compiler/semtypinst.nim compiler/sigmatch.nim compiler/types.nim compiler/vmgen.nim lib/core/macros.nim lib/system.nim tests/reject/tenummix.nim web/news.txt
This commit is contained in:
commit
afddae5aaf
41 changed files with 901 additions and 568 deletions
|
|
@ -18,7 +18,7 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
|
|||
if result.kind == tyForward: result.kind = kind
|
||||
|
||||
proc newConstraint(c: PContext, k: TTypeKind): PType =
|
||||
result = newTypeS(tyTypeClass, c)
|
||||
result = newTypeS(tyBuiltInTypeClass, c)
|
||||
result.addSonSkipIntLit(newTypeS(k, c))
|
||||
|
||||
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
|
|
@ -196,7 +196,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
|||
let e = semExprWithType(c, n.sons[1], {efDetermineType})
|
||||
if e.kind in {nkIntLit..nkUInt64Lit}:
|
||||
indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
|
||||
elif e.kind == nkSym and e.typ.kind == tyExpr:
|
||||
elif e.kind == nkSym and e.typ.kind == tyStatic:
|
||||
if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
|
||||
internalAssert c.inGenericContext > 0
|
||||
if not isOrdinalType(e.typ.lastSon):
|
||||
|
|
@ -206,7 +206,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
|||
indx = e.typ.skipTypes({tyTypeDesc})
|
||||
addSonSkipIntLit(result, indx)
|
||||
if indx.kind == tyGenericInst: indx = lastSon(indx)
|
||||
if indx.kind notin {tyGenericParam, tyExpr}:
|
||||
if indx.kind notin {tyGenericParam, tyStatic}:
|
||||
if not isOrdinalType(indx):
|
||||
localError(n.sons[1].info, errOrdinalTypeExpected)
|
||||
elif enumHasHoles(indx):
|
||||
|
|
@ -579,9 +579,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
pragma(c, s, n.sons[0], typePragmas)
|
||||
if base == nil and tfInheritable notin result.flags:
|
||||
incl(result.flags, tfFinal)
|
||||
|
||||
|
||||
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||
if kind == skMacro and param.typ.kind != tyTypeDesc:
|
||||
if kind == skMacro and param.typ.kind notin {tyTypeDesc, tyStatic}:
|
||||
# within a macro, every param has the type PNimrodNode!
|
||||
# and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
||||
let nn = getSysSym"PNimrodNode"
|
||||
|
|
@ -593,18 +593,21 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
|||
|
||||
let typedescId = getIdent"typedesc"
|
||||
|
||||
template shouldHaveMeta(t) =
|
||||
InternalAssert tfHasMeta in result.lastSon.flags
|
||||
# result.lastSon.flags.incl tfHasMeta
|
||||
|
||||
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")
|
||||
if genericParams == nil:
|
||||
# This happens with anonymous proc types appearing in signatures
|
||||
# XXX: we need to lift these earlier
|
||||
return
|
||||
# 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:
|
||||
|
|
@ -618,7 +621,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
|||
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)
|
||||
|
|
@ -631,25 +634,27 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
|||
addImplicitGenericImpl(e, paramTypId)
|
||||
|
||||
case paramType.kind:
|
||||
of tyExpr:
|
||||
if paramType.sonsLen == 0:
|
||||
# proc(a, b: expr)
|
||||
# no constraints, treat like generic param
|
||||
result = addImplicitGeneric(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))
|
||||
of tyAnything:
|
||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||
|
||||
of tyStatic:
|
||||
# proc(a: expr{string}, b: expr{nkLambda})
|
||||
# overload on compile time values and AST trees
|
||||
result = addImplicitGeneric(c.newTypeWithSons(tyStatic, paramType.sons))
|
||||
result.flags.incl tfHasStatic
|
||||
|
||||
of tyTypeDesc:
|
||||
if tfUnresolved notin paramType.flags:
|
||||
# naked typedescs are not bindOnce types
|
||||
if paramType.sonsLen == 0 and paramTypId != nil and
|
||||
paramTypId.id == typedescId.id: paramTypId = nil
|
||||
result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, 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).
|
||||
|
|
@ -658,7 +663,8 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
|||
# 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)])
|
||||
let typ = c.newTypeWithSons(tyBuiltInTypeClass,
|
||||
@[newTypeS(paramType.kind, c)])
|
||||
result = addImplicitGeneric(typ)
|
||||
else:
|
||||
for i in 0 .. <paramType.sons.len:
|
||||
|
|
@ -666,29 +672,45 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
|||
if lifted != nil:
|
||||
paramType.sons[i] = lifted
|
||||
result = paramType
|
||||
|
||||
of tyGenericBody:
|
||||
# type Foo[T] = object
|
||||
# proc x(a: Foo, b: Foo)
|
||||
var typ = newTypeS(tyTypeClass, c)
|
||||
typ.addSonSkipIntLit(paramType)
|
||||
result = addImplicitGeneric(typ)
|
||||
result = newTypeS(tyGenericInvokation, c)
|
||||
result.rawAddSon(paramType)
|
||||
for i in 0 .. paramType.sonsLen - 2:
|
||||
result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
|
||||
result = instGenericContainer(c, paramType.sym.info, result,
|
||||
allowMetaTypes = true)
|
||||
result.lastSon.shouldHaveMeta
|
||||
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
|
||||
result = addImplicitGeneric(result)
|
||||
|
||||
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
|
||||
result.lastSon.shouldHaveMeta
|
||||
|
||||
if paramType.lastSon.kind == tyTypeClass:
|
||||
result = paramType
|
||||
result.kind = tyParametricTypeClass
|
||||
result = addImplicitGeneric(copyType(result,
|
||||
getCurrOwner(), false))
|
||||
elif result != nil:
|
||||
result.kind = tyGenericInvokation
|
||||
result.sons.setLen(result.sons.len - 1)
|
||||
of tyTypeClass:
|
||||
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false))
|
||||
let liftBody = liftingWalk(paramType.lastSon)
|
||||
if liftBody != nil:
|
||||
result = liftBody
|
||||
result.shouldHaveMeta
|
||||
|
||||
of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
|
||||
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
|
||||
|
||||
of tyExpr:
|
||||
if procKind notin {skMacro, skTemplate}:
|
||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||
|
||||
of tyGenericParam:
|
||||
if tfGenericTypeParam in paramType.flags and false:
|
||||
if paramType.sonsLen > 0:
|
||||
result = liftingWalk(paramType.lastSon)
|
||||
else:
|
||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||
|
||||
else: nil
|
||||
|
||||
# result = liftingWalk(paramType)
|
||||
|
|
@ -745,8 +767,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
|||
if not containsGenericType(typ):
|
||||
def = fitNode(c, typ, def)
|
||||
if not (hasType or hasDefault):
|
||||
typ = newTypeS(tyExpr, c)
|
||||
|
||||
let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything
|
||||
typ = newTypeS(tdef, c)
|
||||
|
||||
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
|
||||
for j in countup(0, length-3):
|
||||
var arg = newSymG(skParam, a.sons[j], c)
|
||||
|
|
@ -842,7 +865,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
|||
else:
|
||||
internalAssert s.typ.kind == tyGenericBody
|
||||
|
||||
var m = newCandidate(s, n)
|
||||
var m = newCandidate(c, s, n)
|
||||
matches(c, n, copyTree(n), m)
|
||||
|
||||
if m.state != csMatch:
|
||||
|
|
@ -867,12 +890,15 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
|||
when oUseLateInstantiation:
|
||||
result = lateInstantiateGeneric(c, result, n.info)
|
||||
else:
|
||||
result = instGenericContainer(c, n, result)
|
||||
result = instGenericContainer(c, n.info, result,
|
||||
allowMetaTypes = not isConcrete)
|
||||
if not isConcrete and result.kind == tyGenericInst:
|
||||
result.lastSon.shouldHaveMeta
|
||||
|
||||
proc semTypeExpr(c: PContext, n: PNode): PType =
|
||||
var n = semExprWithType(c, n, {efDetermineType})
|
||||
if n.kind == nkSym and n.sym.kind == skType:
|
||||
result = n.sym.typ
|
||||
if n.typ.kind == tyTypeDesc:
|
||||
result = n.typ.base
|
||||
else:
|
||||
localError(n.info, errTypeExpected, n.renderTree)
|
||||
|
||||
|
|
@ -921,24 +947,27 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
var
|
||||
t1 = semTypeNode(c, n.sons[1], nil)
|
||||
t2 = semTypeNode(c, n.sons[2], nil)
|
||||
if t1 == nil:
|
||||
if t1 == nil:
|
||||
localError(n.sons[1].info, errTypeExpected)
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
elif t2 == nil:
|
||||
elif t2 == nil:
|
||||
localError(n.sons[2].info, errTypeExpected)
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
else:
|
||||
result = newTypeS(tyTypeClass, c)
|
||||
result.addSonSkipIntLit(t1)
|
||||
result.addSonSkipIntLit(t2)
|
||||
result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny)
|
||||
result.flags.incl(tfHasMeta)
|
||||
result = if op.id == ord(wAnd): makeAndType(c, t1, t2)
|
||||
else: makeOrType(c, t1, t2)
|
||||
elif op.id == ord(wNot):
|
||||
checkSonsLen(n, 3)
|
||||
result = semTypeNode(c, n.sons[1], prev)
|
||||
if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
|
||||
result = freshType(result, prev)
|
||||
result.flags.incl(tfNotNil)
|
||||
case n.len
|
||||
of 3:
|
||||
result = semTypeNode(c, n.sons[1], prev)
|
||||
if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
|
||||
result = freshType(result, prev)
|
||||
result.flags.incl(tfNotNil)
|
||||
else:
|
||||
LocalError(n.info, errGenerated, "invalid type")
|
||||
of 2:
|
||||
let negated = semTypeNode(c, n.sons[1], prev)
|
||||
result = makeNotType(c, negated)
|
||||
else:
|
||||
localError(n.info, errGenerated, "invalid type")
|
||||
else:
|
||||
|
|
@ -1004,6 +1033,11 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
|
||||
of nkVarTy: result = semVarType(c, n, prev)
|
||||
of nkDistinctTy: result = semDistinct(c, n, prev)
|
||||
of nkStaticTy:
|
||||
result = newOrPrevType(tyStatic, prev, c)
|
||||
var base = semTypeNode(c, n.sons[0], nil)
|
||||
result.rawAddSon(base)
|
||||
result.flags.incl tfHasStatic
|
||||
of nkProcTy, nkIteratorTy:
|
||||
if n.sonsLen == 0:
|
||||
result = newConstraint(c, tyProc)
|
||||
|
|
@ -1088,11 +1122,7 @@ proc processMagicType(c: PContext, m: PSym) =
|
|||
else: localError(m.info, errTypeExpected)
|
||||
|
||||
proc semGenericConstraints(c: PContext, x: PType): PType =
|
||||
if x.kind in StructuralEquivTypes and (
|
||||
sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
|
||||
result = newConstraint(c, x.kind)
|
||||
else:
|
||||
result = newTypeWithSons(c, tyGenericParam, @[x])
|
||||
result = newTypeWithSons(c, tyGenericParam, @[x])
|
||||
|
||||
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
result = copyNode(n)
|
||||
|
|
@ -1109,7 +1139,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
|||
|
||||
if constraint.kind != nkEmpty:
|
||||
typ = semTypeNode(c, constraint, nil)
|
||||
if typ.kind != tyExpr or typ.len == 0:
|
||||
if typ.kind != tyStatic or typ.len == 0:
|
||||
if typ.kind == tyTypeDesc:
|
||||
if typ.len == 0:
|
||||
typ = newTypeS(tyTypeDesc, c)
|
||||
|
|
@ -1120,14 +1150,16 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
|||
def = semConstExpr(c, def)
|
||||
if typ == nil:
|
||||
if def.typ.kind != tyTypeDesc:
|
||||
typ = newTypeWithSons(c, tyExpr, @[def.typ])
|
||||
typ = newTypeWithSons(c, tyStatic, @[def.typ])
|
||||
else:
|
||||
if not containsGenericType(def.typ):
|
||||
def = fitNode(c, typ, def)
|
||||
|
||||
if typ == nil:
|
||||
typ = newTypeS(tyGenericParam, c)
|
||||
|
||||
|
||||
typ.flags.incl tfGenericTypeParam
|
||||
|
||||
for j in countup(0, L-3):
|
||||
let finalType = if j == 0: typ
|
||||
else: copyType(typ, typ.owner, false)
|
||||
|
|
@ -1136,7 +1168,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
|||
# of the parameter will be stored in the
|
||||
# attached symbol.
|
||||
var s = case finalType.kind
|
||||
of tyExpr:
|
||||
of tyStatic:
|
||||
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
|
||||
else:
|
||||
newSymG(skType, a.sons[j], c).linkTo(finalType)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue