diff options
-rw-r--r-- | compiler/ast.nim | 6 | ||||
-rw-r--r-- | compiler/sem.nim | 4 | ||||
-rw-r--r-- | compiler/semdata.nim | 1 | ||||
-rw-r--r-- | compiler/semstmts.nim | 4 | ||||
-rw-r--r-- | compiler/semtypes.nim | 35 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 19 | ||||
-rw-r--r-- | compiler/types.nim | 4 | ||||
-rw-r--r-- | compiler/vmgen.nim | 23 | ||||
-rw-r--r-- | tests/macros/tdebugstmt.nim | 29 | ||||
-rw-r--r-- | todo.txt | 2 |
11 files changed, 87 insertions, 42 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 7138b5f52..cd002eef1 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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: diff --git a/compiler/sem.nim b/compiler/sem.nim index e89e32f4e..00ac79716 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -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] diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 8b97f3685..c9d95e1bf 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -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) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index d3cc1a12e..0871b7fb7 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 408b1b62e..6f2d9ece9 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 1158335a8..a07d91241 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -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: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index d269e9e69..f9200ea0c 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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]) diff --git a/compiler/types.nim b/compiler/types.nim index 812cd4e93..db75cd3c0 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -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 diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index be32f990f..313c43dc4 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -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 diff --git a/tests/macros/tdebugstmt.nim b/tests/macros/tdebugstmt.nim new file mode 100644 index 000000000..865dc436a --- /dev/null +++ b/tests/macros/tdebugstmt.nim @@ -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) diff --git a/todo.txt b/todo.txt index 6f8726199..fef073f90 100644 --- a/todo.txt +++ b/todo.txt @@ -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 |