diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 6 | ||||
-rw-r--r-- | compiler/cgen.nim | 6 | ||||
-rw-r--r-- | compiler/destroyer.nim | 14 | ||||
-rw-r--r-- | compiler/parser.nim | 48 | ||||
-rw-r--r-- | compiler/semasgn.nim | 5 | ||||
-rw-r--r-- | compiler/semstmts.nim | 3 | ||||
-rw-r--r-- | compiler/semtypes.nim | 17 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 37 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 5 |
10 files changed, 89 insertions, 53 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 24891d6d3..fc470b7a8 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1352,7 +1352,6 @@ proc copySym*(s: PSym): PSym = result = newSym(s.kind, s.name, s.owner, s.info, s.options) #result.ast = nil # BUGFIX; was: s.ast which made problems result.typ = s.typ - result.id = getID() when debugIds: registerId(result) result.flags = s.flags result.magic = s.magic diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index ed6255004..5bcbcda1c 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -460,7 +460,7 @@ proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, frmt: string) = if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr") initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) - lineCg(p, cpsStmts, frmt, addrLoc(p.config, a), rdLoc(b)) + lineCg(p, cpsStmts, frmt, byRefLoc(p, a), rdLoc(b)) proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a: TLoc @@ -1028,7 +1028,7 @@ proc gcUsage(conf: ConfigRef; n: PNode) = proc strLoc(p: BProc; d: TLoc): Rope = if p.config.selectedGc == gcDestructors: - result = addrLoc(p.config, d) + result = byRefLoc(p, d) else: result = rdLoc(d) @@ -1110,7 +1110,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = strLoc(p, dest), rdLoc(a))) if p.config.selectedGC == gcDestructors: linefmt(p, cpsStmts, "#prepareAdd($1, $2$3);$n", - addrLoc(p.config, dest), lens, rope(L)) + byRefLoc(p, dest), lens, rope(L)) else: initLoc(call, locCall, e, OnHeap) call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, rope(L)]) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 2d9814621..d020b1bd7 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -264,6 +264,12 @@ proc addrLoc(conf: ConfigRef; a: TLoc): Rope = if lfIndirect notin a.flags and mapType(conf, a.t) != ctArray: result = "(&" & result & ")" +proc byRefLoc(p: BProc; a: TLoc): Rope = + result = a.r + if lfIndirect notin a.flags and mapType(p.config, a.t) != ctArray and not + p.module.compileToCpp: + result = "(&" & result & ")" + proc rdCharLoc(a: TLoc): Rope = # read a location that may need a char-cast: result = rdLoc(a) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index e21d532ea..22ace3634 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -244,7 +244,10 @@ proc patchHead(n: PNode) = proc patchHead(s: PSym) = if sfFromGeneric in s.flags: - patchHead(s.ast[bodyPos]) + # do not patch the builtin type bound operators for seqs: + let dest = s.typ.sons[1].skipTypes(abstractVar) + if dest.kind != tySequence: + patchHead(s.ast[bodyPos]) proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) = var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">" @@ -267,7 +270,8 @@ template genOp(opr, opname, ri) = globalError(c.graph.config, dest.info, "internal error: '" & opname & "' operator not found for type " & typeToString(t)) elif op.ast[genericParamsPos].kind != nkEmpty: - globalError(c.graph.config, dest.info, "internal error: '" & opname & "' operator is generic") + globalError(c.graph.config, dest.info, "internal error: '" & opname & + "' operator is generic") patchHead op if sfError in op.flags: checkForErrorPragma(c, t, ri, opname) let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ)) @@ -275,6 +279,12 @@ template genOp(opr, opname, ri) = result = newTree(nkCall, newSymNode(op), addrExp) proc genSink(c: Con; t: PType; dest, ri: PNode): PNode = + when false: + if t.kind != tyString: + echo "this one ", c.graph.config$dest.info, " for ", typeToString(t, preferDesc) + debug t.sink.typ.sons[2] + echo t.sink.id, " owner ", t.id + quit 1 let t = t.skipTypes({tyGenericInst, tyAlias, tySink}) genOp(if t.sink != nil: t.sink else: t.assignment, "=sink", ri) diff --git a/compiler/parser.nim b/compiler/parser.nim index c9626c527..01a3ce4d0 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -724,6 +724,14 @@ const tkTypeClasses = {tkRef, tkPtr, tkVar, tkStatic, tkType, tkEnum, tkTuple, tkObject, tkProc} +proc commandExpr(p: var TParser; r: PNode; mode: TPrimaryMode): PNode = + result = newNodeP(nkCommand, p) + addSon(result, r) + var isFirstParam = true + # progress NOT guaranteed + p.hasProgress = false + addSon result, commandParam(p, isFirstParam, mode) + proc primarySuffix(p: var TParser, r: PNode, baseIndent: int, mode: TPrimaryMode): PNode = #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks? @@ -734,8 +742,6 @@ proc primarySuffix(p: var TParser, r: PNode, #| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax result = r - template somePar() = - if p.tok.strongSpaceA > 0: break # progress guaranteed while p.tok.indent < 0 or (p.tok.tokType == tkDot and p.tok.indent >= baseIndent): @@ -749,6 +755,8 @@ proc primarySuffix(p: var TParser, r: PNode, result = newNodeP(nkCommand, p) result.addSon r result.addSon primary(p, pmNormal) + else: + result = commandExpr(p, result, mode) break result = namedParams(p, result, nkCall, tkParRi) if result.len > 1 and result.sons[1].kind == nkExprColonExpr: @@ -759,39 +767,27 @@ proc primarySuffix(p: var TParser, r: PNode, result = parseGStrLit(p, result) of tkBracketLe: # progress guaranteed - somePar() + if p.tok.strongSpaceA > 0: + result = commandExpr(p, result, mode) + break result = namedParams(p, result, nkBracketExpr, tkBracketRi) of tkCurlyLe: # progress guaranteed - somePar() + if p.tok.strongSpaceA > 0: + result = commandExpr(p, result, mode) + break result = namedParams(p, result, nkCurlyExpr, tkCurlyRi) of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast, tkOpr, tkDotDot, tkTypeClasses - {tkRef, tkPtr}: - # XXX: In type sections we allow the free application of the - # command syntax, with the exception of expressions such as - # `foo ref` or `foo ptr`. Unfortunately, these two are also - # used as infix operators for the memory regions feature and - # the current parsing rules don't play well here. + # XXX: In type sections we allow the free application of the + # command syntax, with the exception of expressions such as + # `foo ref` or `foo ptr`. Unfortunately, these two are also + # used as infix operators for the memory regions feature and + # the current parsing rules don't play well here. if p.inPragma == 0 and (isUnary(p) or p.tok.tokType notin {tkOpr, tkDotDot}): # actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet # solution, but pragmas.nim can't handle that - let a = result - result = newNodeP(nkCommand, p) - addSon(result, a) - var isFirstParam = true - when true: - # progress NOT guaranteed - p.hasProgress = false - addSon result, commandParam(p, isFirstParam, mode) - if not p.hasProgress: break - else: - while p.tok.tokType != tkEof: - let x = parseExpr(p) - addSon(result, x) - if p.tok.tokType != tkComma: break - getTok(p) - optInd(p, x) - result = postExprBlocks(p, result) + result = commandExpr(p, result, mode) break else: break diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index 9f1ef313b..41b0879e6 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -316,6 +316,11 @@ proc liftBody(g: ModuleGraph; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym = if typ.kind == tyDistinct: return liftBodyDistinctType(g, typ, kind, info) + when false: + var typ = typ + if c.config.selectedGC == gcDestructors and typ.kind == tySequence: + # use the canonical type to access the =sink and =destroy etc. + typ = c.graph.sysTypes[tySequence] var a: TLiftCtx a.info = info diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 5e9d5d9c5..f1778e816 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -168,7 +168,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode = else: illFormedAst(it, c.config) if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or (not hasElse and efInTypeof notin flags): - for it in n: + for it in n: it.sons[^1] = discardCheck(c, it.sons[^1], flags) result.kind = nkIfStmt # propagate any enforced VoidContext: @@ -1563,6 +1563,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, objB): # attach these ops to the canonical tySequence obj = canonType(c, obj) + #echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj) let opr = if s.name.s == "=": addr(obj.assignment) else: addr(obj.sink) if opr[].isNil: opr[] = s diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index fbf363834..744746323 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1159,7 +1159,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # compiler only checks for 'nil': if skipTypes(r, {tyGenericInst, tyAlias, tySink}).kind != tyVoid: if kind notin {skMacro, skTemplate} and r.kind in {tyStmt, tyExpr}: - localError(c.config, n.sons[0].info, "return type '" & typeToString(r) & + localError(c.config, n.sons[0].info, "return type '" & typeToString(r) & "' is only valid for macros and templates") # 'auto' as a return type does not imply a generic: elif r.kind == tyAnything: @@ -1577,11 +1577,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = assert s != nil assert prev == nil result = copyType(s, s.owner, keepId=false) - # XXX figure out why this has children already... + # Remove the 'T' parameter from tySequence: result.sons.setLen 0 result.n = nil result.flags = {tfHasAsgn} semContainerArg(c, n, "seq", result) + if result.len > 0: + var base = result[0] + if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base) + if base.kind != tyGenericParam: + c.typesWithOps.add((result, result)) else: result = semContainer(c, n, tySequence, "seq", prev) if c.config.selectedGc == gcDestructors: @@ -1714,11 +1719,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyError, prev, c) n.typ = result dec c.inTypeContext - if c.inTypeContext == 0: instAllTypeBoundOp(c, n.info) - -when false: - proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = - result = semTypeNodeInner(c, n, prev) + if c.inTypeContext == 0: + #if $n == "var seq[StackTraceEntry]": + # echo "begin ", n instAllTypeBoundOp(c, n.info) proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) = diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 027ffd4aa..ebe822cdf 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -297,12 +297,6 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = #result.destructor = nil result.sink = nil -template typeBound(c, newty, oldty, field, info) = - let opr = newty.field - if opr != nil and sfFromGeneric notin opr.flags: - # '=' needs to be instantiated for generics when the type is constructed: - newty.field = c.instTypeBoundOp(c, opr, oldty, info, attachedAsgn, 1) - proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # tyGenericInvocation[A, tyGenericInvocation[A, B]] # is difficult to handle: @@ -317,7 +311,10 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = else: result = searchInstTypes(t) - if result != nil and eqFlags*result.flags == eqFlags*t.flags: return + if result != nil and eqFlags*result.flags == eqFlags*t.flags: + when defined(reportCacheHits): + echo "Generic instantiation cached ", typeToString(result), " for ", typeToString(t) + return for i in countup(1, sonsLen(t) - 1): var x = t.sons[i] if x.kind in {tyGenericParam}: @@ -332,7 +329,11 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = if header != t: # search again after first pass: result = searchInstTypes(header) - if result != nil and eqFlags*result.flags == eqFlags*t.flags: return + if result != nil and eqFlags*result.flags == eqFlags*t.flags: + when defined(reportCacheHits): + echo "Generic instantiation cached ", typeToString(result), " for ", + typeToString(t), " header ", typeToString(header) + return else: header = instCopyType(cl, t) @@ -384,7 +385,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = rawAddSon(result, newbody) checkPartialConstructedType(cl.c.config, cl.info, newbody) let dc = newbody.deepCopy - if cl.allowMetaTypes == false: + if not cl.allowMetaTypes: if dc != nil and sfFromGeneric notin newbody.deepCopy.flags: # 'deepCopy' needs to be instantiated for # generics *when the type is constructed*: @@ -402,6 +403,11 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = discard else: newbody.lastSon.typeInst = result + # DESTROY: adding object|opt for opt[topttree.Tree] + # sigmatch: Formal opt[=destroy.T] real opt[topttree.Tree] + # adding myseq for myseq[system.int] + # sigmatch: Formal myseq[=destroy.T] real myseq[system.int] + #echo "DESTROY: adding ", typeToString(newbody), " for ", typeToString(result, preferDesc) cl.c.typesWithOps.add((newbody, result)) let mm = skipTypes(bbody, abstractPtrs) if tfFromGeneric notin mm.flags: @@ -432,7 +438,7 @@ proc eraseVoidParams*(t: PType) = inc pos setLen t.sons, pos setLen t.n.sons, pos - return + break proc skipIntLiteralParams*(t: PType) = for i in 0 ..< t.sonsLen: @@ -561,9 +567,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = for i in countup(0, sonsLen(result) - 1): if result.sons[i] != nil: if result.sons[i].kind == tyGenericBody: - localError( - cl.c.config, - t.sym.info, + localError(cl.c.config, t.sym.info, "cannot instantiate '" & typeToString(result.sons[i], preferDesc) & "' inside of type definition: '" & @@ -603,6 +607,13 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result.size = -1 result.n = replaceObjBranches(cl, result.n) +template typeBound(c, newty, oldty, field, info) = + let opr = newty.field + if opr != nil and sfFromGeneric notin opr.flags: + # '=' needs to be instantiated for generics when the type is constructed: + #echo "DESTROY: instantiating ", astToStr(field), " for ", typeToString(oldty) + newty.field = c.instTypeBoundOp(c, opr, oldty, info, attachedAsgn, 1) + proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) = var i = 0 while i < c.typesWithOps.len: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index fa4ab3703..3eaac06e5 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -2505,6 +2505,11 @@ proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo; if f.kind in {tyRef, tyPtr}: f = f.lastSon else: if f.kind == tyVar: f = f.lastSon + #if c.config.selectedGC == gcDestructors and f.kind == tySequence: + # use the canonical type to access the =sink and =destroy etc. + # f = c.graph.sysTypes[tySequence] + #echo "YUP_---------Formal ", typeToString(f, preferDesc), " real ", typeToString(t, preferDesc), " ", f.id, " ", t.id + if typeRel(m, f, t) == isNone: localError(c.config, info, "cannot instantiate: '" & dc.name.s & "'") else: |