diff options
-rw-r--r-- | compiler/ccgexprs.nim | 34 | ||||
-rw-r--r-- | compiler/cgen.nim | 3 | ||||
-rw-r--r-- | compiler/cgendata.nim | 10 | ||||
-rw-r--r-- | compiler/pragmas.nim | 8 | ||||
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/semtempl.nim | 10 | ||||
-rw-r--r-- | compiler/trees.nim | 19 | ||||
-rw-r--r-- | compiler/vmdeps.nim | 22 | ||||
-rw-r--r-- | compiler/vmgen.nim | 3 | ||||
-rw-r--r-- | lib/pure/math.nim | 4 | ||||
-rw-r--r-- | lib/pure/memfiles.nim | 34 | ||||
-rw-r--r-- | tests/ccgbugs/tescaping_temps.nim | 20 | ||||
-rw-r--r-- | tests/ccgbugs/tinefficient_const_table.nim | 27 | ||||
-rw-r--r-- | tests/lookups/tprefer_proc.nim | 4 |
14 files changed, 148 insertions, 54 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 75a7cb3bb..a86409e50 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1151,7 +1151,25 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) = genTypeInfo(p.module, seqtype), a.rdLoc])) gcUsage(e) +proc genConstExpr(p: BProc, n: PNode): Rope +proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = + if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr: + var t = getUniqueType(n.typ) + discard getTypeDesc(p.module, t) # so that any fields are initialized + let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels) + fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic) + if id == p.module.labels: + # expression not found in the cache: + inc(p.module.labels) + addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", + [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)]) + result = true + else: + result = false + proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = + if handleConstExpr(p, e, d): return + #echo rendertree e, " ", e.isDeepConstExpr var tmp: TLoc var t = e.typ.skipTypes(abstractInst) getTemp(p, t, tmp) @@ -1769,22 +1787,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mDotDot, mEqCString: genCall(p, e, d) else: internalError(e.info, "genMagicExpr: " & $op) -proc genConstExpr(p: BProc, n: PNode): Rope -proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = - if nfAllConst in n.flags and d.k == locNone and n.len > 0 and n.isDeepConstExpr: - var t = getUniqueType(n.typ) - discard getTypeDesc(p.module, t) # so that any fields are initialized - let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels) - fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic) - if id == p.module.labels: - # expression not found in the cache: - inc(p.module.labels) - addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)]) - result = true - else: - result = false - proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = # example: { a..b, c, d, e, f..g } # we have to emit an expression of the form: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 4dbe8572e..9851ab0e2 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -328,7 +328,8 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) result.r = "LOC" & rope(p.labels) - linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) + addf(p.blocks[0].sections[cpsLocals], + "$1 $2;$n", [getTypeDesc(p.module, t), result.r]) result.k = locTemp #result.a = - 1 result.t = t diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index c027bb451..a94950029 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -15,7 +15,7 @@ import from msgs import TLineInfo type - TLabel* = Rope # for the C generator a label is just a rope + TLabel* = Rope # for the C generator a label is just a rope TCFileSection* = enum # the sections a generated C file consists of cfsMergeInfo, # section containing merge information cfsHeaders, # section for C include file headers @@ -89,7 +89,7 @@ type # requires 'T x = T()' to become 'T x; x = T()' # (yes, C++ is weird like that) gcFrameId*: Natural # for the GC stack marking - gcFrameType*: Rope # the struct {} we put the GC markers into + gcFrameType*: Rope # the struct {} we put the GC markers into TTypeSeq* = seq[PType] @@ -111,10 +111,10 @@ type tmpBase*: Rope # base for temp identifier generation typeCache*: TIdTable # cache the generated types forwTypeCache*: TIdTable # cache for forward declarations of types - declaredThings*: IntSet # things we have declared in this .c file - declaredProtos*: IntSet # prototypes we have declared in this .c file + declaredThings*: IntSet # things we have declared in this .c file + declaredProtos*: IntSet # prototypes we have declared in this .c file headerFiles*: TLinkedList # needed headers to include - typeInfoMarker*: IntSet # needed for generating type information + typeInfoMarker*: IntSet # needed for generating type information initProc*: BProc # code for init procedure postInitProc*: BProc # code to be executed after the init proc preInitProc*: BProc # code executed before the init proc diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 781aab687..354e5bdc6 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -400,8 +400,12 @@ proc relativeFile(c: PContext; n: PNode; ext=""): string = s = addFileExt(s, ext) result = parentDir(n.info.toFullPath) / s if not fileExists(result): - if isAbsolute(s): result = s - else: result = findFile(s) + if isAbsolute(s): + result = s + else: + result = findFile(s) + if result.len == 0: + result = s proc processCompile(c: PContext, n: PNode) = let found = relativeFile(c, n) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index fd18dc3d7..fc31829ba 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2216,7 +2216,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if nfSem in n.flags: return case n.kind of nkIdent, nkAccQuoted: - var s = lookUp(c, n) + let checks = if efNoEvaluateGeneric in flags: {checkUndeclared} + else: {checkUndeclared, checkModule, checkAmbiguity} + var s = qualifiedLookUp(c, n, checks) if c.inTypeClass == 0: semCaptureSym(s, c.p.owner) result = semSym(c, n, s, flags) if s.kind in {skProc, skMethod, skConverter, skIterator}: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 4d3b6d038..20b5071ac 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -51,9 +51,10 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode = var i = 0 a = initOverloadIter(o, c, n) while a != nil: + if a.kind != skModule: + inc(i) + if i > 1: break a = nextOverloadIter(o, c, n) - inc(i) - if i > 1: break if i <= 1 and r != scForceOpen: # XXX this makes more sense but breaks bootstrapping for now: # (s.kind notin routineKinds or s.magic != mNone): @@ -68,8 +69,9 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode = result = newNodeIT(kind, n.info, newTypeS(tyNone, c)) a = initOverloadIter(o, c, n) while a != nil: - incl(a.flags, sfUsed) - addSon(result, newSymNode(a, n.info)) + if a.kind != skModule: + incl(a.flags, sfUsed) + addSon(result, newSymNode(a, n.info)) a = nextOverloadIter(o, c, n) proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode = diff --git a/compiler/trees.nim b/compiler/trees.nim index 659df334b..fdd88c348 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -103,14 +103,16 @@ proc getMagic*(op: PNode): TMagic = else: result = mNone else: result = mNone -proc treeToSym*(t: PNode): PSym = - result = t.sym - proc isConstExpr*(n: PNode): bool = result = (n.kind in {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags) +proc isCaseObj*(n: PNode): bool = + if n.kind == nkRecCase: return true + for i in 0..<safeLen(n): + if n[i].isCaseObj: return true + proc isDeepConstExpr*(n: PNode): bool = case n.kind of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, @@ -119,11 +121,14 @@ proc isDeepConstExpr*(n: PNode): bool = of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: result = isDeepConstExpr(n.sons[1]) of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure: - for i in 0 .. <n.len: + for i in ord(n.kind == nkObjConstr) .. <n.len: if not isDeepConstExpr(n.sons[i]): return false - # XXX once constant objects are supported by the codegen this needs to be - # weakened: - result = n.typ.isNil or n.typ.skipTypes({tyGenericInst, tyDistinct}).kind != tyObject + if n.typ.isNil: result = true + else: + let t = n.typ.skipTypes({tyGenericInst, tyDistinct}) + if t.kind in {tyRef, tyPtr}: return false + if t.kind != tyObject or not isCaseObj(t.n): + result = true else: discard proc flattenTreeAux(d, a: PNode, op: TMagic) = diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 18c5ae832..7dbf6f801 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -85,6 +85,17 @@ proc mapTypeToBracketX(name: string; m: TMagic; t: PType; info: TLineInfo; else: result.add mapTypeToAstX(t.sons[i], info, inst) +proc objectNode(n: PNode): PNode = + if n.kind == nkSym: + result = newNodeI(nkIdentDefs, n.info) + result.add n # name + result.add mapTypeToAstX(n.sym.typ, n.info, true, false) # type + result.add ast.emptyNode # no assigned value + else: + result = copyNode(n) + for i in 0 ..< n.safeLen: + result.add objectNode(n[i]) + proc mapTypeToAstX(t: PType; info: TLineInfo; inst=false; allowRecursionX=false): PNode = var allowRecursion = allowRecursionX @@ -167,7 +178,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; result = newNodeX(nkDistinctTy) result.add mapTypeToAst(t.sons[0], info) else: - if allowRecursion or t.sym==nil: + if allowRecursion or t.sym == nil: result = mapTypeToBracket("distinct", mDistinct, t, info) else: result = atomicType(t.sym.name.s, t.sym.magic) @@ -177,16 +188,13 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; if inst: result = newNodeX(nkObjectTy) result.add ast.emptyNode # pragmas not reconstructed yet - if t.sons[0]==nil: result.add ast.emptyNode # handle parent object + if t.sons[0] == nil: result.add ast.emptyNode # handle parent object else: var nn = newNodeX(nkOfInherit) nn.add mapTypeToAst(t.sons[0], info) result.add nn - if t.n.sons.len>0: - var rl = copyNode(t.n) # handle nkRecList - for s in t.n.sons: - rl.add newIdentDefs(s) - result.add rl + if t.n.len > 0: + result.add objectNode(t.n) else: result.add ast.emptyNode else: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 366662258..61ab65360 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -664,8 +664,7 @@ proc genNarrowU(c: PCtx; n: PNode; dest: TDest) = let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) # uint is uint64 in the VM, we we only need to mask the result for # other unsigned types: - if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or - (t.kind == tyInt and t.size == 4): + if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}: c.gABC(n, opcNarrowU, dest, TRegister(t.size*8)) proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = diff --git a/lib/pure/math.nim b/lib/pure/math.nim index c088e3d7d..58d9879b2 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -219,7 +219,7 @@ when not defined(JS): ## ## .. code-block:: nim ## echo ceil(-2.1) ## -2.0 - + when defined(windows) and defined(vcc): proc round0[T: float32|float64](x: T): T = ## Windows compilers prior to MSVC 2012 do not implement 'round', @@ -360,7 +360,7 @@ proc `mod`*[T: float32|float64](x, y: T): T = proc `^`*[T](x, y: T): T = ## Computes ``x`` to the power ``y`. ``x`` must be non-negative, use ## `pow <#pow,float,float>` for negative exponents. - assert y >= 0 + assert y >= T(0) var (x, y) = (x, y) result = 1 diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index ff3e74d59..aa32778c5 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -42,6 +42,10 @@ type proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = + ## returns a pointer to a mapped portion of MemFile `m` + ## + ## ``mappedSize`` of ``-1`` maps to the whole file, and + ## ``offset`` must be multiples of the PAGE SIZE of your OS var readonly = mode == fmRead when defined(windows): result = mapViewOfFileEx( @@ -68,7 +72,9 @@ proc mapMem*(m: var MemFile, mode: FileMode = fmRead, proc unmapMem*(f: var MemFile, p: pointer, size: int) = ## unmaps the memory region ``(p, <p+size)`` of the mapped file `f`. ## All changes are written back to the file system, if `f` was opened - ## with write access. ``size`` must be of exactly the size that was requested + ## with write access. + ## + ## ``size`` must be of exactly the size that was requested ## via ``mapMem``. when defined(windows): if unmapViewOfFile(p) == 0: raiseOSError(osLastError()) @@ -79,9 +85,17 @@ proc unmapMem*(f: var MemFile, p: pointer, size: int) = proc open*(filename: string, mode: FileMode = fmRead, mappedSize = -1, offset = 0, newFileSize = -1): MemFile = ## opens a memory mapped file. If this fails, ``EOS`` is raised. - ## `newFileSize` can only be set if the file does not exist and is opened - ## with write access (e.g., with fmReadWrite). `mappedSize` and `offset` - ## can be used to map only a slice of the file. Example: + ## + ## ``newFileSize`` can only be set if the file does not exist and is opened + ## with write access (e.g., with fmReadWrite). + ## + ##``mappedSize`` and ``offset`` + ## can be used to map only a slice of the file. + ## + ## ``offset`` must be multiples of the PAGE SIZE of your OS + ## (usually 4K or 8K but is unique to your OS) + ## + ## Example: ## ## .. code-block:: nim ## var @@ -285,7 +299,9 @@ iterator memSlices*(mfile: MemFile, delim='\l', eat='\r'): MemSlice {.inline.} = ## iterate over line-like records in a file. However, returned (data,size) ## objects are not Nim strings, bounds checked Nim arrays, or even terminated ## C strings. So, care is required to access the data (e.g., think C mem* - ## functions, not str* functions). Example: + ## functions, not str* functions). + ## + ## Example: ## ## .. code-block:: nim ## var count = 0 @@ -318,7 +334,9 @@ iterator lines*(mfile: MemFile, buf: var TaintedString, delim='\l', eat='\r'): T ## Replace contents of passed buffer with each new line, like ## `readLine(File) <system.html#readLine,File,TaintedString>`_. ## `delim`, `eat`, and delimiting logic is exactly as for - ## `memSlices <#memSlices>`_, but Nim strings are returned. Example: + ## `memSlices <#memSlices>`_, but Nim strings are returned. + ## + ## Example: ## ## .. code-block:: nim ## var buffer: TaintedString = "" @@ -335,7 +353,9 @@ iterator lines*(mfile: MemFile, delim='\l', eat='\r'): TaintedString {.inline.} ## Return each line in a file as a Nim string, like ## `lines(File) <system.html#lines.i,File>`_. ## `delim`, `eat`, and delimiting logic is exactly as for - ## `memSlices <#memSlices>`_, but Nim strings are returned. Example: + ## `memSlices <#memSlices>`_, but Nim strings are returned. + ## + ## Example: ## ## .. code-block:: nim ## for line in lines(memfiles.open("foo")): diff --git a/tests/ccgbugs/tescaping_temps.nim b/tests/ccgbugs/tescaping_temps.nim new file mode 100644 index 000000000..ef078913b --- /dev/null +++ b/tests/ccgbugs/tescaping_temps.nim @@ -0,0 +1,20 @@ + +# bug #4505 + +proc f(t: tuple[]) = discard +f((block: ())) + +# bug #4230 +# If we make `test` function return nothing - the bug disappears +proc test(dothejob: proc()): int {.discardable.} = + dothejob() + +test proc() = + let f = 15 + if f > 10: + test proc() = discard + # If we remove elif branch of the condition - the bug disappears + elif f < 3: + test proc() = discard + else: + test proc() = discard diff --git a/tests/ccgbugs/tinefficient_const_table.nim b/tests/ccgbugs/tinefficient_const_table.nim new file mode 100644 index 000000000..149b8bcff --- /dev/null +++ b/tests/ccgbugs/tinefficient_const_table.nim @@ -0,0 +1,27 @@ +discard """ + output: '''a +long +list +of +words''' + cmd: r"nim c --hints:on $options -d:release $file" + ccodecheck: "! @'genericSeqAssign'" +""" + + +# bug #4354 +import tables +import sets +import strutils + +#const FRUITS = ["banana", "apple", "grapes"] +#let FRUITS = ["banana", "apple", "grapes"].toSet +const FRUITS = {"banana":0, "apple":0, "grapes":0}.toTable + +proc main() = + let L = "a long list of words".split() + for word in L: + if word notin FRUITS: + echo(word) + +main() diff --git a/tests/lookups/tprefer_proc.nim b/tests/lookups/tprefer_proc.nim new file mode 100644 index 000000000..57ee8e539 --- /dev/null +++ b/tests/lookups/tprefer_proc.nim @@ -0,0 +1,4 @@ + +# bug #4353 +import random +echo random[int](low(int) .. high(int)) |