diff options
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 2 | ||||
-rw-r--r-- | compiler/pragmas.nim | 7 | ||||
-rw-r--r-- | compiler/vm.nim | 2 | ||||
-rw-r--r-- | compiler/vmgen.nim | 15 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 2 | ||||
-rw-r--r-- | doc/manual/pragmas.txt | 18 | ||||
-rw-r--r-- | examples/curlex.nim | 10 | ||||
-rw-r--r-- | examples/iupex1.nim | 37 | ||||
-rw-r--r-- | lib/pure/streams.nim | 11 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | lib/system/alloc.nim | 11 | ||||
-rw-r--r-- | tests/pragmas/tbitsize.nim | 22 | ||||
-rw-r--r-- | tests/stdlib/tmemfiles2.nim | 2 | ||||
-rw-r--r-- | tests/testament/categories.nim | 4 | ||||
-rw-r--r-- | tests/testament/tester.nim | 6 | ||||
-rw-r--r-- | tests/vm/tsimpleglobals.nim | 16 | ||||
-rw-r--r-- | tests/vm/twrongconst.nim | 2 | ||||
-rw-r--r-- | web/news.txt | 2 |
19 files changed, 104 insertions, 68 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 4001e896e..25958f580 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -784,6 +784,7 @@ type tab*: TStrTable # interface table for modules of skLet, skVar, skField, skForVar: guard*: PSym + bitsize*: int else: nil magic*: TMagic typ*: PType diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 84d02d1da..1ed9ce113 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -441,6 +441,8 @@ proc genRecordFieldsAux(m: BModule, n: PNode, elif fieldType.kind == tySequence: # we need to use a weak dependency here for trecursive_table. addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname]) + elif field.bitsize != 0: + addf(result, "$1 $2:$3;$n", [getTypeDescAux(m, field.loc.t, check), sname, rope($field.bitsize)]) else: # don't use fieldType here because we need the # tyGenericInst for C++ template support diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1c51251fe..ba05b2792 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -56,7 +56,7 @@ const wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wBorrow, wGcSafe} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, - wImportCpp, wImportObjC, wError, wGuard} + wImportCpp, wImportObjC, wError, wGuard, wBitsize} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, @@ -844,6 +844,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if sym == nil: pragmaLockStmt(c, it) elif sym.typ == nil: invalidPragma(it) else: sym.typ.lockLevel = pragmaLocks(c, it) + of wBitsize: + if sym == nil or sym.kind != skField or it.kind != nkExprColonExpr: + invalidPragma(it) + else: + sym.bitsize = expectIntLit(c, it) of wGuard: if sym == nil or sym.kind notin {skVar, skLet, skField}: invalidPragma(it) diff --git a/compiler/vm.nim b/compiler/vm.nim index 4dd3b5232..ad4aa1017 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -311,7 +311,7 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool = if f.position == x: dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal return - internalError("opConv for enum") + dest.node.strVal = styp.sym.name.s & " " & $x of tyInt..tyInt64: dest.node.strVal = $src.intVal of tyUInt..tyUInt64: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 0559acc88..92db0d513 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -37,7 +37,7 @@ when hasFFI: import evalffi type - TGenFlag = enum gfNone, gfAddrOf + TGenFlag = enum gfAddrOf, gfFieldAccess TGenFlags = set[TGenFlag] proc debugInfo(info: TLineInfo): string = @@ -535,7 +535,7 @@ proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister = proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = case le.kind of nkBracketExpr: - let dest = c.genx(le.sons[0], {gfAddrOf}) + let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess}) let idx = c.genIndex(le.sons[1], le.sons[0].typ) c.gABC(le, opcWrArr, dest, idx, value) c.freeTemp(dest) @@ -543,7 +543,7 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = of nkDotExpr, nkCheckedFieldExpr: # XXX field checks here let left = if le.kind == nkDotExpr: le else: le.sons[0] - let dest = c.genx(left.sons[0], {gfAddrOf}) + let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess}) let idx = genField(left.sons[1]) c.gABC(left, opcWrObj, dest, idx, value) c.freeTemp(dest) @@ -1216,7 +1216,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode; proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = case le.kind of nkBracketExpr: - let dest = c.genx(le.sons[0], {gfAddrOf}) + let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess}) let idx = c.genIndex(le.sons[1], le.sons[0].typ) let tmp = c.genx(ri) if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in { @@ -1228,7 +1228,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = of nkDotExpr, nkCheckedFieldExpr: # XXX field checks here let left = if le.kind == nkDotExpr: le else: le.sons[0] - let dest = c.genx(left.sons[0], {gfAddrOf}) + let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess}) let idx = genField(left.sons[1]) let tmp = c.genx(ri) c.preventFalseAlias(left, opcWrObj, dest, idx, tmp) @@ -1321,7 +1321,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = c.gABx(n, opcLdGlobal, cc, s.position) c.gABC(n, opcNodeToReg, dest, cc) c.freeTemp(cc) - elif gfAddrOf in flags: + elif {gfAddrOf, gfFieldAccess} * flags == {gfAddrOf}: c.gABx(n, opcLdGlobalAddr, dest, s.position) else: c.gABx(n, opcLdGlobal, dest, s.position) @@ -1773,6 +1773,9 @@ proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int = d = 0 c.gABC(n, opcEof, d) + #echo renderTree(n) + #c.echoCode(result) + proc genParams(c: PCtx; params: PNode) = # res.sym.position is already 0 c.prc.slots[0] = (inUse: true, kind: slotFixedVar) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 23f012ea5..d1e5438f3 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -82,6 +82,7 @@ type wStdIn, wStdOut, wStdErr, wInOut, wByCopy, wByRef, wOneWay, + wBitsize, TSpecialWords* = set[TSpecialWord] @@ -168,6 +169,7 @@ const "stdin", "stdout", "stderr", "inout", "bycopy", "byref", "oneway", + "bitsize", ] proc findStr*(a: openArray[string], s: string): int = diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt index 68a88f865..f89194c9a 100644 --- a/doc/manual/pragmas.txt +++ b/doc/manual/pragmas.txt @@ -531,6 +531,24 @@ Implementation Specific Pragmas This section describes additional pragmas that the current Nim implementation supports but which should not be seen as part of the language specification. +Bitsize pragma +-------------- + +The ``bitsize`` pragma is for object field members. It declares the field as +a bitfield in C/C++. + +.. code-block:: Nim + type + mybitfield = object + flag {.bitsize:1.}: cuint + +generates: + +.. code-block:: C + struct mybitfield { + unsigned int flag:1; + }; + Volatile pragma --------------- diff --git a/examples/curlex.nim b/examples/curlex.nim deleted file mode 100644 index 21786a6ee..000000000 --- a/examples/curlex.nim +++ /dev/null @@ -1,10 +0,0 @@ -import - libcurl - -var hCurl = easy_init() -if hCurl != nil: - discard easy_setopt(hCurl, OPT_VERBOSE, true) - discard easy_setopt(hCurl, OPT_URL, "http://nim-lang.org/") - discard easy_perform(hCurl) - easy_cleanup(hCurl) - diff --git a/examples/iupex1.nim b/examples/iupex1.nim deleted file mode 100644 index f768fb23f..000000000 --- a/examples/iupex1.nim +++ /dev/null @@ -1,37 +0,0 @@ -# Example IUP program - -# iupTabs: Creates a iupTabs control. - -import iup - -discard iup.open(nil, nil) - -var vbox1 = iup.vbox(iup.label("Inside Tab A"), iup.button("Button A", ""), nil) -var vbox2 = iup.vbox(iup.label("Inside Tab B"), iup.button("Button B", ""), nil) - -iup.setAttribute(vbox1, "TABTITLE", "Tab A") -iup.setAttribute(vbox2, "TABTITLE", "Tab B") - -var tabs1 = iup.tabs(vbox1, vbox2, nil) - -vbox1 = iup.vbox(iup.label("Inside Tab C"), iup.button("Button C", ""), nil) -vbox2 = iup.vbox(iup.label("Inside Tab D"), iup.button("Button D", ""), nil) - -iup.setAttribute(vbox1, "TABTITLE", "Tab C") -iup.setAttribute(vbox2, "TABTITLE", "Tab D") - -var tabs2 = iup.tabs(vbox1, vbox2, nil) -iup.setAttribute(tabs2, "TABTYPE", "LEFT") - -var box = iup.hbox(tabs1, tabs2, nil) -iup.setAttribute(box, "MARGIN", "10x10") -iup.setAttribute(box, "GAP", "10") - -var dlg = iup.dialog(box) -iup.setAttribute(dlg, "TITLE", "iupTabs") -iup.setAttribute(dlg, "SIZE", "200x100") - -discard showXY(dlg, IUP_CENTER, IUP_CENTER) -discard mainLoop() -close() - diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index 68f31e9fe..38e91fee4 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -103,15 +103,16 @@ proc readData*(s: Stream, buffer: pointer, bufLen: int): int = proc readAll*(s: Stream): string = ## Reads all available data. - result = newString(1000) + const bufferSize = 1000 + result = newString(bufferSize) var r = 0 while true: - let readBytes = readData(s, addr(result[r]), 1000) - if readBytes < 1000: + let readBytes = readData(s, addr(result[r]), bufferSize) + if readBytes < bufferSize: setLen(result, r+readBytes) break - inc r, 1000 - setLen(result, r+1000) + inc r, bufferSize + setLen(result, r+bufferSize) proc readData*(s, unused: Stream, buffer: pointer, bufLen: int): int {.deprecated.} = diff --git a/lib/system.nim b/lib/system.nim index 59d0d04b7..1d2ca6a9a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1256,7 +1256,7 @@ proc compileOption*(option, arg: string): bool {. ## echo "compiled with optimization for size and uses Boehm's GC" const - hasThreadSupport = compileOption("threads") + hasThreadSupport = compileOption("threads") and not defined(nimscript) hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own taintMode = compileOption("taintmode") diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 13a10e46f..3a1d7b666 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -27,8 +27,11 @@ sysAssert(roundup(65, 8) == 72, "roundup broken 2") # some platforms have really weird unmap behaviour: unmap(blockStart, PageSize) # really frees the whole block. Happens for Linux/PowerPC for example. Amd64 # and x86 are safe though; Windows is special because MEM_RELEASE can only be -# used with a size of 0: -const weirdUnmap = not (defined(amd64) or defined(i386)) or defined(windows) +# used with a size of 0. We also allow unmapping to be turned off with +# -d:nimAllocNoUnmap: +const doNotUnmap = not (defined(amd64) or defined(i386)) or + defined(windows) or defined(nimAllocNoUnmap) + when defined(posix): const @@ -478,7 +481,7 @@ proc freeBigChunk(a: var MemRegion, c: PBigChunk) = excl(a.chunkStarts, pageIndex(c)) c = cast[PBigChunk](le) - if c.size < ChunkOsReturn or weirdUnmap: + if c.size < ChunkOsReturn or doNotUnmap: incl(a, a.chunkStarts, pageIndex(c)) updatePrevSize(a, c, c.size) listAdd(a.freeChunksList, c) @@ -762,7 +765,7 @@ proc deallocOsPages(a: var MemRegion) = # we free every 'ordinarily' allocated page by iterating over the page bits: for p in elements(a.chunkStarts): var page = cast[PChunk](p shl PageShift) - when not weirdUnmap: + when not doNotUnmap: var size = if page.size < PageSize: PageSize else: page.size osDeallocPages(page, size) else: diff --git a/tests/pragmas/tbitsize.nim b/tests/pragmas/tbitsize.nim new file mode 100644 index 000000000..7a44944d2 --- /dev/null +++ b/tests/pragmas/tbitsize.nim @@ -0,0 +1,22 @@ +discard """ +ccodeCheck: "\\i @'unsigned int flag:1;' .*" +""" + +type + bits* = object + flag* {.bitsize: 1.}: cuint + opts* {.bitsize: 4.}: cint + +var + b: bits + +assert b.flag == 0 +b.flag = 1 +assert b.flag == 1 +b.flag = 2 +assert b.flag == 0 + +b.opts = 7 +assert b.opts == 7 +b.opts = 9 +assert b.opts == -7 diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim index 28af3296a..026443e93 100644 --- a/tests/stdlib/tmemfiles2.nim +++ b/tests/stdlib/tmemfiles2.nim @@ -1,8 +1,10 @@ discard """ file: "tmemfiles2.nim" + disabled: true output: '''Full read size: 20 Half read size: 10 Data: Hello''' """ +# doesn't work on windows. fmReadWrite doesn't create a file. import memfiles, os var mm, mm_full, mm_half: MemFile diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 4de1edeee..afc4a616f 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -339,7 +339,7 @@ proc `&?.`(a, b: string): string = # candidate for the stdlib? result = if a.endswith(b): a else: a & b -proc processCategory(r: var TResults, cat: Category, options: string) = +proc processCategory(r: var TResults, cat: Category, options: string, fileGlob: string = "t*.nim") = case cat.string.normalize of "rodfiles": discard # Disabled for now @@ -376,5 +376,5 @@ proc processCategory(r: var TResults, cat: Category, options: string) = of "nimble-all": testNimblePackages(r, cat, pfAll) else: - for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"): + for name in os.walkFiles("tests" & DirSep &.? cat.string / fileGlob): testSpec r, makeTest(name, options, cat) diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index b138c9909..3961f15c4 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -23,6 +23,7 @@ const Command: all run all tests c|category <category> run all the tests of a certain category + r|run <test> run single test file html [commit] generate $1 from the database; uses the latest commit or a specific one (use -1 for the commit before latest etc) @@ -376,6 +377,11 @@ proc main() = var cat = Category(p.key) p.next processCategory(r, cat, p.cmdLineRest.string) + of "r", "run": + let (dir, file) = splitPath(p.key.string) + let (_, subdir) = splitPath(dir) + var cat = Category(subdir) + processCategory(r, cat, p.cmdLineRest.string, file) of "html": var commit = 0 discard parseInt(p.cmdLineRest.string, commit) diff --git a/tests/vm/tsimpleglobals.nim b/tests/vm/tsimpleglobals.nim new file mode 100644 index 000000000..27bfdce50 --- /dev/null +++ b/tests/vm/tsimpleglobals.nim @@ -0,0 +1,16 @@ +discard """ + msg: "abc xyz bb" +""" + +# bug #2473 +type + Test = tuple[a,b: string] + +static: + var s:seq[Test] = @[(a:"a", b:"b")] + s[0] = (a:"aa", b:"bb") + + var x: Test + x.a = "abc" + x.b = "xyz" + echo x.a, " ", x.b, " ", s[0].b diff --git a/tests/vm/twrongconst.nim b/tests/vm/twrongconst.nim index 68ab2757c..424ed080e 100644 --- a/tests/vm/twrongconst.nim +++ b/tests/vm/twrongconst.nim @@ -1,6 +1,6 @@ discard """ errormsg: "cannot evaluate at compile time: x" - line: 9 + line: 7 """ var x: array[100, char] diff --git a/web/news.txt b/web/news.txt index cfa40c65c..33ceac49e 100644 --- a/web/news.txt +++ b/web/news.txt @@ -108,6 +108,8 @@ News - The compiler finally considers symbol binding rules in templates and generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators (issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_). + - The compiler now supports a `bitsize pragma <docs/manual.html#pragmas-bitsize-pragma>`_ + for constructing bitfields. Language Additions |