mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-22 23:35:22 +00:00
tyTypeDesc and tyRange always have 1 child; this might be tyNone but it is required for skipTypes
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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)
|
||||
Reference in New Issue
Block a user