Merge remote-tracking branch 'origin/devel' into fix-test-failures

This commit is contained in:
Aman Gupta 2015-10-02 13:38:35 -07:00
commit 59d226221b
23 changed files with 110 additions and 30 deletions

View file

@ -784,6 +784,7 @@ type
tab*: TStrTable # interface table for modules tab*: TStrTable # interface table for modules
of skLet, skVar, skField, skForVar: of skLet, skVar, skField, skForVar:
guard*: PSym guard*: PSym
bitsize*: int
else: nil else: nil
magic*: TMagic magic*: TMagic
typ*: PType typ*: PType

View file

@ -441,6 +441,8 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
elif fieldType.kind == tySequence: elif fieldType.kind == tySequence:
# we need to use a weak dependency here for trecursive_table. # we need to use a weak dependency here for trecursive_table.
addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname]) 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: else:
# don't use fieldType here because we need the # don't use fieldType here because we need the
# tyGenericInst for C++ template support # tyGenericInst for C++ template support

View file

@ -14,7 +14,7 @@
import import
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
securehash securehash, streams
type type
TSystemCC* = enum TSystemCC* = enum
@ -672,6 +672,12 @@ proc callCCompiler*(projectfile: string) =
var prettyCmds: TStringSeq = @[] var prettyCmds: TStringSeq = @[]
let prettyCb = proc (idx: int) = let prettyCb = proc (idx: int) =
echo prettyCmds[idx] echo prettyCmds[idx]
let runCb = proc (idx: int, p: Process) =
let exitCode = p.peekExitCode
if exitCode != 0:
rawMessage(errGenerated, "execution of an external compiler program '" &
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
p.outputStream.readAll.strip)
compileCFile(toCompile, script, cmds, prettyCmds, false) compileCFile(toCompile, script, cmds, prettyCmds, false)
compileCFile(externalToCompile, script, cmds, prettyCmds, true) compileCFile(externalToCompile, script, cmds, prettyCmds, true)
if optCompileOnly notin gGlobalOptions: if optCompileOnly notin gGlobalOptions:
@ -682,22 +688,17 @@ proc callCCompiler*(projectfile: string) =
res = execWithEcho(cmds[i]) res = execWithEcho(cmds[i])
if res != 0: rawMessage(errExecutionOfProgramFailed, cmds[i]) if res != 0: rawMessage(errExecutionOfProgramFailed, cmds[i])
elif optListCmd in gGlobalOptions or gVerbosity > 1: elif optListCmd in gGlobalOptions or gVerbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poUsePath, poParentStreams}, res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors, afterRunEvent=runCb)
elif gVerbosity == 1: elif gVerbosity == 1:
res = execProcesses(cmds, {poUsePath, poParentStreams}, res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
gNumberOfProcessors, prettyCb) gNumberOfProcessors, prettyCb, afterRunEvent=runCb)
else: else:
res = execProcesses(cmds, {poUsePath, poParentStreams}, res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors, afterRunEvent=runCb)
if res != 0: if res != 0:
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:
rawMessage(errExecutionOfProgramFailed, cmds.join()) rawMessage(errExecutionOfProgramFailed, cmds.join())
else:
rawMessage(errGenerated,
" execution of an external compiler program failed: " &
cmds.join() & "; " &
"rerun with --parallelBuild:1 to see the error message")
if optNoLinking notin gGlobalOptions: if optNoLinking notin gGlobalOptions:
# call the linker: # call the linker:
var it = PStrEntry(toLink.head) var it = PStrEntry(toLink.head)

View file

@ -56,7 +56,7 @@ const
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe} wBorrow, wGcSafe}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard} wImportCpp, wImportObjC, wError, wGuard, wBitsize}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, 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) if sym == nil: pragmaLockStmt(c, it)
elif sym.typ == nil: invalidPragma(it) elif sym.typ == nil: invalidPragma(it)
else: sym.typ.lockLevel = pragmaLocks(c, 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: of wGuard:
if sym == nil or sym.kind notin {skVar, skLet, skField}: if sym == nil or sym.kind notin {skVar, skLet, skField}:
invalidPragma(it) invalidPragma(it)

View file

@ -82,6 +82,7 @@ type
wStdIn, wStdOut, wStdErr, wStdIn, wStdOut, wStdErr,
wInOut, wByCopy, wByRef, wOneWay, wInOut, wByCopy, wByRef, wOneWay,
wBitsize,
TSpecialWords* = set[TSpecialWord] TSpecialWords* = set[TSpecialWord]
@ -168,6 +169,7 @@ const
"stdin", "stdout", "stderr", "stdin", "stdout", "stderr",
"inout", "bycopy", "byref", "oneway", "inout", "bycopy", "byref", "oneway",
"bitsize",
] ]
proc findStr*(a: openArray[string], s: string): int = proc findStr*(a: openArray[string], s: string): int =

View file

@ -531,6 +531,24 @@ Implementation Specific Pragmas
This section describes additional pragmas that the current Nim implementation This section describes additional pragmas that the current Nim implementation
supports but which should not be seen as part of the language specification. 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 Volatile pragma
--------------- ---------------

View file

@ -1,4 +1,4 @@
#! stdtmpl | standard #? stdtmpl | standard
#proc generateHTMLPage(title, currentTab, content: string, #proc generateHTMLPage(title, currentTab, content: string,
# tabs: openArray[string]): string = # tabs: openArray[string]): string =
# result = "" # result = ""

View file

@ -500,7 +500,7 @@ when defined(nimdoc) and not declared(os):
proc existsFile(x: string): bool = discard proc existsFile(x: string): bool = discard
when declared(getEnv) or defined(nimscript): when declared(getEnv) or defined(nimscript):
proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} = proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect, ReadIOEffect].} =
## Returns the home directory of the current user. ## Returns the home directory of the current user.
## ##
## This proc is wrapped by the expandTilde proc for the convenience of ## This proc is wrapped by the expandTilde proc for the convenience of
@ -508,7 +508,7 @@ when declared(getEnv) or defined(nimscript):
when defined(windows): return string(getEnv("USERPROFILE")) & "\\" when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
else: return string(getEnv("HOME")) & "/" else: return string(getEnv("HOME")) & "/"
proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} = proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect, ReadIOEffect].} =
## Returns the config directory of the current user for applications. ## Returns the config directory of the current user for applications.
when defined(windows): return string(getEnv("APPDATA")) & "\\" when defined(windows): return string(getEnv("APPDATA")) & "\\"
else: return string(getEnv("HOME")) & "/.config/" else: return string(getEnv("HOME")) & "/.config/"
@ -519,7 +519,7 @@ when declared(getEnv) or defined(nimscript):
when defined(windows): return string(getEnv("TEMP")) & "\\" when defined(windows): return string(getEnv("TEMP")) & "\\"
else: return "/tmp/" else: return "/tmp/"
proc expandTilde*(path: string): string {.tags: [ReadEnvEffect].} = proc expandTilde*(path: string): string {.tags: [ReadEnvEffect, ReadIOEffect].} =
## Expands a path starting with ``~/`` to a full path. ## Expands a path starting with ``~/`` to a full path.
## ##
## If `path` starts with the tilde character and is followed by `/` or `\\` ## If `path` starts with the tilde character and is followed by `/` or `\\`
@ -549,7 +549,7 @@ when declared(getEnv) or defined(nimscript):
yield substr(s, first, last-1) yield substr(s, first, last-1)
inc(last) inc(last)
proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect].} = proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
## Searches for `exe` in the current working directory and then ## Searches for `exe` in the current working directory and then
## in directories listed in the ``PATH`` environment variable. ## in directories listed in the ``PATH`` environment variable.
## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe` ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`

View file

@ -248,7 +248,8 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
proc execProcesses*(cmds: openArray[string], proc execProcesses*(cmds: openArray[string],
options = {poStdErrToStdOut, poParentStreams}, options = {poStdErrToStdOut, poParentStreams},
n = countProcessors(), n = countProcessors(),
beforeRunEvent: proc(idx: int) = nil): int beforeRunEvent: proc(idx: int) = nil,
afterRunEvent: proc(idx: int, p: Process) = nil): int
{.rtl, extern: "nosp$1", {.rtl, extern: "nosp$1",
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} = tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} =
## executes the commands `cmds` in parallel. Creates `n` processes ## executes the commands `cmds` in parallel. Creates `n` processes
@ -278,6 +279,7 @@ proc execProcesses*(cmds: openArray[string],
err.add("\n") err.add("\n")
echo(err) echo(err)
result = max(waitForExit(q[r]), result) result = max(waitForExit(q[r]), result)
if afterRunEvent != nil: afterRunEvent(r, q[r])
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
@ -291,6 +293,7 @@ proc execProcesses*(cmds: openArray[string],
if not running(q[r]): if not running(q[r]):
#echo(outputStream(q[r]).readLine()) #echo(outputStream(q[r]).readLine())
result = max(waitForExit(q[r]), result) result = max(waitForExit(q[r]), result)
if afterRunEvent != nil: afterRunEvent(r, q[r])
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil: if beforeRunEvent != nil:
beforeRunEvent(i) beforeRunEvent(i)
@ -299,6 +302,7 @@ proc execProcesses*(cmds: openArray[string],
if i > high(cmds): break if i > high(cmds): break
for j in 0..m-1: for j in 0..m-1:
result = max(waitForExit(q[j]), result) result = max(waitForExit(q[j]), result)
if afterRunEvent != nil: afterRunEvent(j, q[j])
if q[j] != nil: close(q[j]) if q[j] != nil: close(q[j])
else: else:
for i in 0..high(cmds): for i in 0..high(cmds):
@ -306,6 +310,7 @@ proc execProcesses*(cmds: openArray[string],
beforeRunEvent(i) beforeRunEvent(i)
var p = startProcess(cmds[i], options=options + {poEvalCommand}) var p = startProcess(cmds[i], options=options + {poEvalCommand})
result = max(waitForExit(p), result) result = max(waitForExit(p), result)
if afterRunEvent != nil: afterRunEvent(i, p)
close(p) close(p)
proc select*(readfds: var seq[Process], timeout = 500): int {.benign.} proc select*(readfds: var seq[Process], timeout = 500): int {.benign.}

View file

@ -18,8 +18,9 @@ type Rational*[T] = object
## a rational number, consisting of a numerator and denominator ## a rational number, consisting of a numerator and denominator
num*, den*: T num*, den*: T
proc initRational*[T](num, den: T): Rational[T] = proc initRational*[T:SomeInteger](num, den: T): Rational[T] =
## Create a new rational number. ## Create a new rational number.
assert(den != 0, "a denominator of zero value is invalid")
result.num = num result.num = num
result.den = den result.den = den
@ -33,7 +34,7 @@ proc `$`*[T](x: Rational[T]): string =
## Turn a rational number into a string. ## Turn a rational number into a string.
result = $x.num & "/" & $x.den result = $x.num & "/" & $x.den
proc toRational*[T](x: T): Rational[T] = proc toRational*[T:SomeInteger](x: T): Rational[T] =
## Convert some integer `x` to a rational number. ## Convert some integer `x` to a rational number.
result.num = x result.num = x
result.den = 1 result.den = 1
@ -47,7 +48,7 @@ proc toInt*[T](x: Rational[T]): int =
## `x` does not contain an integer value. ## `x` does not contain an integer value.
x.num div x.den x.num div x.den
proc reduce*[T](x: var Rational[T]) = proc reduce*[T:SomeInteger](x: var Rational[T]) =
## Reduce rational `x`. ## Reduce rational `x`.
let common = gcd(x.num, x.den) let common = gcd(x.num, x.den)
if x.den > 0: if x.den > 0:

View file

@ -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

View file

@ -0,0 +1,9 @@
discard """
file: "trat_float.nim"
line: "9,19"
errormsg: '''type mismatch: got'''
"""
import rationals
var
# this fails - no floats as num or den
r = initRational(1.0'f, 1.0'f)

View file

@ -0,0 +1,10 @@
discard """
file: "trat_init.nim"
exitcode: "1"
"""
import rationals
var
z = Rational[int](num: 0, den: 1)
o = initRational(num=1, den=1)
a = initRational(1, 2)
r = initRational(1, 0) # this fails - no zero denominator

View file

@ -1,4 +1,4 @@
#! stdtmpl #? stdtmpl
#proc sunsetTemplate*(current, ticker, content: string, #proc sunsetTemplate*(current, ticker, content: string,
# tabs: openarray[array[0..1, string]]): string = # tabs: openarray[array[0..1, string]]): string =
# result = "" # result = ""

View file

@ -213,6 +213,8 @@ proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
expectedmsg = expected.nimout expectedmsg = expected.nimout
givenmsg = given.nimout.strip givenmsg = given.nimout.strip
nimoutCheck(test, expectedmsg, given) nimoutCheck(test, expectedmsg, given)
else:
givenmsg = given.nimout.strip
if given.err == reSuccess: inc(r.passed) if given.err == reSuccess: inc(r.passed)
r.addResult(test, expectedmsg, givenmsg, given.err) r.addResult(test, expectedmsg, givenmsg, given.err)

View file

@ -1,4 +1,4 @@
#! stdtmpl(subsChar='?') | standard #? stdtmpl(subsChar='?') | standard
#proc generateBuildBatchScript(c: ConfigData, winIndex, cpuIndex: int): string = #proc generateBuildBatchScript(c: ConfigData, winIndex, cpuIndex: int): string =
# result = "@echo off\nREM Generated by niminst\n" # result = "@echo off\nREM Generated by niminst\n"
SET CC=gcc SET CC=gcc

View file

@ -1,4 +1,4 @@
#! stdtmpl(subsChar='?') | standard #? stdtmpl(subsChar='?') | standard
#proc generateBuildShellScript(c: ConfigData): string = #proc generateBuildShellScript(c: ConfigData): string =
# result = "#! /bin/sh\n# Generated from niminst\n" & # result = "#! /bin/sh\n# Generated from niminst\n" &
# "# Template is in tools/niminst/buildsh.tmpl\n" & # "# Template is in tools/niminst/buildsh.tmpl\n" &

View file

@ -1,4 +1,4 @@
#! stdtmpl(subsChar='?') | standard #? stdtmpl(subsChar='?') | standard
#proc generateDeinstallScript(c: ConfigData): string = #proc generateDeinstallScript(c: ConfigData): string =
# result = "#! /bin/sh\n# Generated by niminst\n" # result = "#! /bin/sh\n# Generated by niminst\n"
# var proj = c.name.toLower # var proj = c.name.toLower

View file

@ -1,4 +1,4 @@
#! stdtmpl | standard #? stdtmpl | standard
#proc generateInnoSetup(c: ConfigData): string = #proc generateInnoSetup(c: ConfigData): string =
# result = "" # result = ""
; Default Template for NimInst ; Default Template for NimInst

View file

@ -1,4 +1,4 @@
#! stdtmpl(subsChar = '?') | standard #? stdtmpl(subsChar = '?') | standard
#proc generateInstallScript(c: ConfigData): string = #proc generateInstallScript(c: ConfigData): string =
# result = "#! /bin/sh\n# Generated by niminst\n" # result = "#! /bin/sh\n# Generated by niminst\n"
# var proj = c.name.toLower # var proj = c.name.toLower

View file

@ -1,4 +1,4 @@
#! stdtmpl(subsChar='?') | standard #? stdtmpl(subsChar='?') | standard
#proc generateMakefile(c: ConfigData): string = #proc generateMakefile(c: ConfigData): string =
# result = "# Generated from niminst\n" & # result = "# Generated from niminst\n" &
# "# Template is in tools/niminst/makefile.tmpl\n" & # "# Template is in tools/niminst/makefile.tmpl\n" &

View file

@ -1,4 +1,4 @@
#! stdtmpl(subsChar='?') | standard #? stdtmpl(subsChar='?') | standard
#proc generateNsisSetup(c: ConfigData): string = #proc generateNsisSetup(c: ConfigData): string =
# result = "; NSIS script generated by niminst\n" & # result = "; NSIS script generated by niminst\n" &
# "; To regenerate run ``niminst nsis`` or ``koch nsis``\n" # "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"

View file

@ -108,6 +108,8 @@ News
- The compiler finally considers symbol binding rules in templates and - The compiler finally considers symbol binding rules in templates and
generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators
(issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_). (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 Language Additions