tyTypeDesc and tyRange always have 1 child; this might be tyNone but it is required for skipTypes
This commit is contained in:
parent
c097acedd3
commit
d912d18379
11 changed files with 87 additions and 42 deletions
|
|
@ -1129,7 +1129,7 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
|
||||||
result.align = 2 # default alignment
|
result.align = 2 # default alignment
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
when debugIds:
|
when debugIds:
|
||||||
RegisterId(result)
|
registerId(result)
|
||||||
#if result.id < 2000 then
|
#if result.id < 2000 then
|
||||||
# MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
|
# MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
|
||||||
|
|
||||||
|
|
@ -1166,7 +1166,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
|
||||||
if keepId:
|
if keepId:
|
||||||
result.id = t.id
|
result.id = t.id
|
||||||
else:
|
else:
|
||||||
when debugIds: RegisterId(result)
|
when debugIds: registerId(result)
|
||||||
result.sym = t.sym # backend-info should not be copied
|
result.sym = t.sym # backend-info should not be copied
|
||||||
|
|
||||||
proc copySym(s: PSym, keepId: bool = false): PSym =
|
proc copySym(s: PSym, keepId: bool = false): PSym =
|
||||||
|
|
@ -1177,7 +1177,7 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
|
||||||
result.id = s.id
|
result.id = s.id
|
||||||
else:
|
else:
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
when debugIds: RegisterId(result)
|
when debugIds: registerId(result)
|
||||||
result.flags = s.flags
|
result.flags = s.flags
|
||||||
result.magic = s.magic
|
result.magic = s.magic
|
||||||
if s.kind == skModule:
|
if s.kind == skModule:
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,9 @@ proc commonType*(x, y: PType): PType =
|
||||||
elif a.kind == tyTypeDesc:
|
elif a.kind == tyTypeDesc:
|
||||||
# turn any concrete typedesc into the abstract typedesc type
|
# turn any concrete typedesc into the abstract typedesc type
|
||||||
if a.sons == nil: result = a
|
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
|
elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
|
||||||
a.kind == b.kind:
|
a.kind == b.kind:
|
||||||
# check for seq[empty] vs. seq[int]
|
# check for seq[empty] vs. seq[int]
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
|
||||||
|
|
||||||
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
||||||
let typedesc = makeTypeDesc(c, typ)
|
let typedesc = makeTypeDesc(c, typ)
|
||||||
|
rawAddSon(typedesc, newTypeS(tyNone, c))
|
||||||
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
|
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
|
||||||
return newSymNode(sym, info)
|
return newSymNode(sym, info)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
# 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
|
# so we use tyEmpty instead of nil to not crash for strange conversions
|
||||||
# like: mydata.seq
|
# like: mydata.seq
|
||||||
rawAddSon(s.typ, newTypeS(tyEmpty, c))
|
rawAddSon(s.typ, newTypeS(tyNone, c))
|
||||||
s.ast = a
|
s.ast = a
|
||||||
inc c.inGenericContext
|
inc c.inGenericContext
|
||||||
var body = semTypeNode(c, a.sons[2], nil)
|
var body = semTypeNode(c, a.sons[2], nil)
|
||||||
|
|
|
||||||
|
|
@ -681,12 +681,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
of tySequence, tySet, tyArray, tyOpenArray,
|
of tySequence, tySet, tyArray, tyOpenArray,
|
||||||
tyVar, tyPtr, tyRef, tyProc:
|
tyVar, tyPtr, tyRef, tyProc:
|
||||||
# XXX: this is a bit strange, but proc(s: seq)
|
# 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
|
# This also seems to be true when creating aliases
|
||||||
# like: type myseq = distinct seq.
|
# like: type myseq = distinct seq.
|
||||||
# Maybe there is another better place to associate
|
# Maybe there is another better place to associate
|
||||||
# the seq type class with the seq identifier.
|
# 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,
|
let typ = c.newTypeWithSons(tyBuiltInTypeClass,
|
||||||
@[newTypeS(paramType.kind, c)])
|
@[newTypeS(paramType.kind, c)])
|
||||||
result = addImplicitGeneric(typ)
|
result = addImplicitGeneric(typ)
|
||||||
|
|
@ -1133,15 +1133,26 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||||
of mNil: setMagicType(m, tyNil, ptrSize)
|
of mNil: setMagicType(m, tyNil, ptrSize)
|
||||||
of mExpr: setMagicType(m, tyExpr, 0)
|
of mExpr: setMagicType(m, tyExpr, 0)
|
||||||
of mStmt: setMagicType(m, tyStmt, 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 mVoidType: setMagicType(m, tyEmpty, 0)
|
||||||
of mArray: setMagicType(m, tyArray, 0)
|
of mArray:
|
||||||
of mOpenArray: setMagicType(m, tyOpenArray, 0)
|
setMagicType(m, tyArray, 0)
|
||||||
of mVarargs: setMagicType(m, tyVarargs, 0)
|
of mOpenArray:
|
||||||
of mRange: setMagicType(m, tyRange, 0)
|
setMagicType(m, tyOpenArray, 0)
|
||||||
of mSet: setMagicType(m, tySet, 0)
|
of mVarargs:
|
||||||
of mSeq: setMagicType(m, tySequence, 0)
|
setMagicType(m, tyVarargs, 0)
|
||||||
of mOrdinal: setMagicType(m, tyOrdinal, 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
|
of mPNimrodNode: discard
|
||||||
else: localError(m.info, errTypeExpected)
|
else: localError(m.info, errTypeExpected)
|
||||||
|
|
||||||
|
|
@ -1165,8 +1176,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
typ = semTypeNode(c, constraint, nil)
|
typ = semTypeNode(c, constraint, nil)
|
||||||
if typ.kind != tyStatic or typ.len == 0:
|
if typ.kind != tyStatic or typ.len == 0:
|
||||||
if typ.kind == tyTypeDesc:
|
if typ.kind == tyTypeDesc:
|
||||||
if typ.len == 0:
|
if typ.sons[0].kind == tyNone:
|
||||||
typ = newTypeS(tyTypeDesc, c)
|
typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
|
||||||
else:
|
else:
|
||||||
typ = semGenericConstraints(c, typ)
|
typ = semGenericConstraints(c, typ)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
if lookup != nil:
|
if lookup != nil:
|
||||||
result = lookup
|
result = lookup
|
||||||
if tfUnresolved in t.flags: result = result.base
|
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]))
|
result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
|
||||||
|
|
||||||
of tyUserTypeClass:
|
of tyUserTypeClass:
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
#if result < isGeneric: result = isNone
|
#if result < isGeneric: result = isNone
|
||||||
if result notin {isNone, isGeneric}:
|
if result notin {isNone, isGeneric}:
|
||||||
result = typeRangeRel(f, a)
|
result = typeRangeRel(f, a)
|
||||||
elif skipTypes(f, {tyRange}).kind == a.kind:
|
else:
|
||||||
|
if skipTypes(f, {tyRange}).kind == a.kind:
|
||||||
result = isIntConv
|
result = isIntConv
|
||||||
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
|
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
|
||||||
result = isConvertible # a convertible to f
|
result = isConvertible # a convertible to f
|
||||||
|
|
@ -636,7 +637,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
of tyOrdinal:
|
of tyOrdinal:
|
||||||
if isOrdinalType(a):
|
if isOrdinalType(a):
|
||||||
var x = if a.kind == tyOrdinal: a.sons[0] else: a
|
var x = if a.kind == tyOrdinal: a.sons[0] else: a
|
||||||
if f.sonsLen == 0:
|
if f.sons[0].kind == tyNone:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, f.sons[0], x)
|
result = typeRel(c, f.sons[0], x)
|
||||||
|
|
@ -845,7 +846,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
# by a tyTypeDesc params. Unfortunately, this requires more substantial
|
# by a tyTypeDesc params. Unfortunately, this requires more substantial
|
||||||
# changes in semtypinst and elsewhere.
|
# changes in semtypinst and elsewhere.
|
||||||
if a.kind == tyTypeDesc:
|
if a.kind == tyTypeDesc:
|
||||||
if f.sons == nil or f.sons.len == 0:
|
if f.sonsLen == 0:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
internalAssert a.sons != nil and a.sons.len > 0
|
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:
|
else:
|
||||||
result = isNone
|
result = isNone
|
||||||
else:
|
else:
|
||||||
if f.sonsLen > 0:
|
if f.sonsLen > 0 and f.sons[0].kind != tyNone:
|
||||||
result = typeRel(c, f.lastSon, a)
|
result = typeRel(c, f.lastSon, a)
|
||||||
else:
|
else:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
|
|
@ -883,7 +884,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
var prev = PType(idTableGet(c.bindings, f))
|
var prev = PType(idTableGet(c.bindings, f))
|
||||||
if prev == nil:
|
if prev == nil:
|
||||||
if a.kind == tyTypeDesc:
|
if a.kind == tyTypeDesc:
|
||||||
if f.sonsLen == 0:
|
if f.sons[0].kind == tyNone:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, f.sons[0], a.sons[0])
|
result = typeRel(c, f.sons[0], a.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ proc equalParams*(a, b: PNode): TParamsEquality
|
||||||
# returns whether the parameter lists of the procs a, b are exactly the same
|
# returns whether the parameter lists of the procs a, b are exactly the same
|
||||||
proc isOrdinalType*(t: PType): bool
|
proc isOrdinalType*(t: PType): bool
|
||||||
proc enumHasHoles*(t: PType): bool
|
proc enumHasHoles*(t: PType): bool
|
||||||
# XXX it is WRONG to include tyTypeDesc here as that might not have any child!
|
|
||||||
const
|
const
|
||||||
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
||||||
tyConst, tyMutable, tyTypeDesc}
|
tyConst, tyMutable, tyTypeDesc}
|
||||||
|
|
@ -1258,7 +1258,7 @@ proc containsGenericTypeIter(t: PType, closure: PObject): bool =
|
||||||
return true
|
return true
|
||||||
|
|
||||||
if t.kind == tyTypeDesc:
|
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
|
if containsGenericTypeIter(t.base, closure): return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
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) =
|
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
case le.kind
|
case le.kind
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
|
|
@ -973,8 +981,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
gen(c, ri, tmp)
|
gen(c, ri, tmp)
|
||||||
c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
|
c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
|
||||||
else:
|
else:
|
||||||
|
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
||||||
internalAssert s.position > 0 or (s.position == 0 and
|
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)
|
var dest: TRegister = s.position + ord(s.kind == skParam)
|
||||||
gen(c, ri, dest)
|
gen(c, ri, dest)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1035,8 +1044,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
else:
|
else:
|
||||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||||
else:
|
else:
|
||||||
|
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
||||||
if s.position > 0 or (s.position == 0 and
|
if s.position > 0 or (s.position == 0 and
|
||||||
s.kind in {skParam,skResult,skForVar}):
|
s.kind in {skParam,skResult}):
|
||||||
if dest < 0:
|
if dest < 0:
|
||||||
dest = s.position + ord(s.kind == skParam)
|
dest = s.position + ord(s.kind == skParam)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1045,7 +1055,6 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
else:
|
else:
|
||||||
# see tests/t99bott for an example that triggers it:
|
# see tests/t99bott for an example that triggers it:
|
||||||
cannotEval(n)
|
cannotEval(n)
|
||||||
#InternalError(n.info, s.name.s & " " & $s.position)
|
|
||||||
|
|
||||||
proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
flags: TGenFlags) =
|
flags: TGenFlags) =
|
||||||
|
|
@ -1123,14 +1132,6 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkCurly, info, t)
|
result = newNodeIT(nkCurly, info, t)
|
||||||
else: internalError("getNullValue: " & $t.kind)
|
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) =
|
proc genVarSection(c: PCtx; n: PNode) =
|
||||||
for a in n:
|
for a in n:
|
||||||
if a.kind == nkCommentStmt: continue
|
if a.kind == nkCommentStmt: continue
|
||||||
|
|
|
||||||
29
tests/macros/tdebugstmt.nim
Normal file
29
tests/macros/tdebugstmt.nim
Normal 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)
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -2,7 +2,7 @@ version 0.9.4
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- fix macros\tstringinterp.nim
|
- fix macros\tstringinterp.nim
|
||||||
- test and fix showoff; add debug example to showoff
|
- test and fix showoff
|
||||||
- test and fix stdlib
|
- test and fix stdlib
|
||||||
- test and fix misc
|
- test and fix misc
|
||||||
- fix GC issues
|
- fix GC issues
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue