tyTypeDesc and tyRange always have 1 child; this might be tyNone but it is required for skipTypes

This commit is contained in:
Araq
2014-02-05 23:43:13 +01:00
parent c097acedd3
commit d912d18379
11 changed files with 87 additions and 42 deletions

View File

@@ -1129,7 +1129,7 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
result.align = 2 # default alignment
result.id = getID()
when debugIds:
RegisterId(result)
registerId(result)
#if result.id < 2000 then
# MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
@@ -1166,7 +1166,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
if keepId:
result.id = t.id
else:
when debugIds: RegisterId(result)
when debugIds: registerId(result)
result.sym = t.sym # backend-info should not be copied
proc copySym(s: PSym, keepId: bool = false): PSym =
@@ -1177,7 +1177,7 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
result.id = s.id
else:
result.id = getID()
when debugIds: RegisterId(result)
when debugIds: registerId(result)
result.flags = s.flags
result.magic = s.magic
if s.kind == skModule:

View File

@@ -83,7 +83,9 @@ proc commonType*(x, y: PType): PType =
elif a.kind == tyTypeDesc:
# turn any concrete typedesc into the abstract typedesc type
if a.sons == nil: result = a
else: result = newType(tyTypeDesc, a.owner)
else:
result = newType(tyTypeDesc, a.owner)
rawAddSon(result, newType(tyNone, a.owner))
elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
a.kind == b.kind:
# check for seq[empty] vs. seq[int]

View File

@@ -211,6 +211,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
let typedesc = makeTypeDesc(c, typ)
rawAddSon(typedesc, newTypeS(tyNone, c))
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
return newSymNode(sym, info)

View File

@@ -740,7 +740,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
# we fill it out later. For magic generics like 'seq', it won't be filled
# so we use tyEmpty instead of nil to not crash for strange conversions
# like: mydata.seq
rawAddSon(s.typ, newTypeS(tyEmpty, c))
rawAddSon(s.typ, newTypeS(tyNone, c))
s.ast = a
inc c.inGenericContext
var body = semTypeNode(c, a.sons[2], nil)
@@ -748,7 +748,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
if body != nil:
body.sym = s
body.size = -1 # could not be computed properly
s.typ.sons[sonsLen(s.typ) - 1] = body
s.typ.sons[sonsLen(s.typ) - 1] = body
popOwner()
closeScope(c)
elif a.sons[2].kind != nkEmpty:

View File

@@ -681,12 +681,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tySequence, tySet, tyArray, tyOpenArray,
tyVar, tyPtr, tyRef, tyProc:
# XXX: this is a bit strange, but proc(s: seq)
# produces tySequence(tyGenericParam, null).
# produces tySequence(tyGenericParam, tyNone).
# 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.kind == tySequence and paramType.lastSon == nil:
if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
let typ = c.newTypeWithSons(tyBuiltInTypeClass,
@[newTypeS(paramType.kind, c)])
result = addImplicitGeneric(typ)
@@ -1133,15 +1133,26 @@ proc processMagicType(c: PContext, m: PSym) =
of mNil: setMagicType(m, tyNil, ptrSize)
of mExpr: setMagicType(m, tyExpr, 0)
of mStmt: setMagicType(m, tyStmt, 0)
of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
of mTypeDesc:
setMagicType(m, tyTypeDesc, 0)
rawAddSon(m.typ, newTypeS(tyNone, c))
of mVoidType: setMagicType(m, tyEmpty, 0)
of mArray: setMagicType(m, tyArray, 0)
of mOpenArray: setMagicType(m, tyOpenArray, 0)
of mVarargs: setMagicType(m, tyVarargs, 0)
of mRange: setMagicType(m, tyRange, 0)
of mSet: setMagicType(m, tySet, 0)
of mSeq: setMagicType(m, tySequence, 0)
of mOrdinal: setMagicType(m, tyOrdinal, 0)
of mArray:
setMagicType(m, tyArray, 0)
of mOpenArray:
setMagicType(m, tyOpenArray, 0)
of mVarargs:
setMagicType(m, tyVarargs, 0)
of mRange:
setMagicType(m, tyRange, 0)
rawAddSon(m.typ, newTypeS(tyNone, c))
of mSet:
setMagicType(m, tySet, 0)
of mSeq:
setMagicType(m, tySequence, 0)
of mOrdinal:
setMagicType(m, tyOrdinal, 0)
rawAddSon(m.typ, newTypeS(tyNone, c))
of mPNimrodNode: discard
else: localError(m.info, errTypeExpected)
@@ -1165,8 +1176,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
typ = semTypeNode(c, constraint, nil)
if typ.kind != tyStatic or typ.len == 0:
if typ.kind == tyTypeDesc:
if typ.len == 0:
typ = newTypeS(tyTypeDesc, c)
if typ.sons[0].kind == tyNone:
typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
else:
typ = semGenericConstraints(c, typ)

View File

@@ -358,7 +358,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
if lookup != nil:
result = lookup
if tfUnresolved in t.flags: result = result.base
elif t.sonsLen > 0:
elif t.sons[0].kind != tyNone:
result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
of tyUserTypeClass:

View File

@@ -562,10 +562,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
#if result < isGeneric: result = isNone
if result notin {isNone, isGeneric}:
result = typeRangeRel(f, a)
elif skipTypes(f, {tyRange}).kind == a.kind:
result = isIntConv
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
result = isConvertible # a convertible to f
else:
if skipTypes(f, {tyRange}).kind == a.kind:
result = isIntConv
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
result = isConvertible # a convertible to f
of tyInt: result = handleRange(f, a, tyInt8, tyInt32)
of tyInt8: result = handleRange(f, a, tyInt8, tyInt8)
of tyInt16: result = handleRange(f, a, tyInt8, tyInt16)
@@ -636,7 +637,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyOrdinal:
if isOrdinalType(a):
var x = if a.kind == tyOrdinal: a.sons[0] else: a
if f.sonsLen == 0:
if f.sons[0].kind == tyNone:
result = isGeneric
else:
result = typeRel(c, f.sons[0], x)
@@ -736,7 +737,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyGenericInst:
let roota = a.skipGenericAlias
let rootf = f.skipGenericAlias
if a.kind == tyGenericInst and roota.base == rootf.base :
if a.kind == tyGenericInst and roota.base == rootf.base:
for i in 1 .. rootf.sonsLen-2:
let ff = rootf.sons[i]
let aa = roota.sons[i]
@@ -845,7 +846,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# by a tyTypeDesc params. Unfortunately, this requires more substantial
# changes in semtypinst and elsewhere.
if a.kind == tyTypeDesc:
if f.sons == nil or f.sons.len == 0:
if f.sonsLen == 0:
result = isGeneric
else:
internalAssert a.sons != nil and a.sons.len > 0
@@ -854,7 +855,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else:
result = isNone
else:
if f.sonsLen > 0:
if f.sonsLen > 0 and f.sons[0].kind != tyNone:
result = typeRel(c, f.lastSon, a)
else:
result = isGeneric
@@ -883,7 +884,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
var prev = PType(idTableGet(c.bindings, f))
if prev == nil:
if a.kind == tyTypeDesc:
if f.sonsLen == 0:
if f.sons[0].kind == tyNone:
result = isGeneric
else:
result = typeRel(c, f.sons[0], a.sons[0])

View File

@@ -47,7 +47,7 @@ proc equalParams*(a, b: PNode): TParamsEquality
# returns whether the parameter lists of the procs a, b are exactly the same
proc isOrdinalType*(t: PType): bool
proc enumHasHoles*(t: PType): bool
# XXX it is WRONG to include tyTypeDesc here as that might not have any child!
const
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
tyConst, tyMutable, tyTypeDesc}
@@ -1258,7 +1258,7 @@ proc containsGenericTypeIter(t: PType, closure: PObject): bool =
return true
if t.kind == tyTypeDesc:
if t.sonsLen == 0: return true
if t.sons[0].kind == tyNone: return true
if containsGenericTypeIter(t.base, closure): return true
return false

View File

@@ -946,6 +946,14 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
proc setSlot(c: PCtx; v: PSym) =
# XXX generate type initialization here?
if v.position == 0:
v.position = c.prc.maxSlots
c.prc.slots[v.position] = (inUse: true,
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
inc c.prc.maxSlots
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
case le.kind
of nkBracketExpr:
@@ -973,8 +981,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
gen(c, ri, tmp)
c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
else:
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
internalAssert s.position > 0 or (s.position == 0 and
s.kind in {skParam,skResult,skForVar})
s.kind in {skParam,skResult})
var dest: TRegister = s.position + ord(s.kind == skParam)
gen(c, ri, dest)
else:
@@ -1035,8 +1044,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
else:
c.gABx(n, opcLdGlobal, dest, s.position)
else:
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
if s.position > 0 or (s.position == 0 and
s.kind in {skParam,skResult,skForVar}):
s.kind in {skParam,skResult}):
if dest < 0:
dest = s.position + ord(s.kind == skParam)
else:
@@ -1045,7 +1055,6 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
else:
# see tests/t99bott for an example that triggers it:
cannotEval(n)
#InternalError(n.info, s.name.s & " " & $s.position)
proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
flags: TGenFlags) =
@@ -1123,14 +1132,6 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
result = newNodeIT(nkCurly, info, t)
else: internalError("getNullValue: " & $t.kind)
proc setSlot(c: PCtx; v: PSym) =
# XXX generate type initialization here?
if v.position == 0:
v.position = c.prc.maxSlots
c.prc.slots[v.position] = (inUse: true,
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
inc c.prc.maxSlots
proc genVarSection(c: PCtx; n: PNode) =
for a in n:
if a.kind == nkCommentStmt: continue

View File

@@ -0,0 +1,29 @@
discard """
output: '''a[0]: 42
a[1]: 45
x: some string'''
"""
import macros
macro debug(n: varargs[expr]): stmt =
# `n` is a Nimrod AST that contains the whole macro invocation
# this macro returns a list of statements:
result = newNimNode(nnkStmtList, n)
# iterate over any argument that is passed to this macro:
for i in 0..n.len-1:
# add a call to the statement list that writes the expression;
# `toStrLit` converts an AST to its string representation:
add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
# add a call to the statement list that writes ": "
add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
# add a call to the statement list that writes the expressions value:
add(result, newCall("writeln", newIdentNode("stdout"), n[i]))
var
a: array [0..10, int]
x = "some string"
a[0] = 42
a[1] = 45
debug(a[0], a[1], x)

View File

@@ -2,7 +2,7 @@ version 0.9.4
=============
- fix macros\tstringinterp.nim
- test and fix showoff; add debug example to showoff
- test and fix showoff
- test and fix stdlib
- test and fix misc
- fix GC issues