Merge branch 'devel' into bigbreak

Conflicts:
	lib/impure/db_postgres.nim
	lib/pure/json.nim
	lib/pure/math.nim
	lib/system/atomics.nim
This commit is contained in:
Araq
2014-11-03 11:42:36 +01:00
10 changed files with 229 additions and 84 deletions

View File

@@ -125,7 +125,7 @@ Files: "start.bat"
BinPath: r"bin;dist\mingw\bin;dist"
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip"
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|doc\overview.html"
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe"
; for now only NSIS supports optional downloads

View File

@@ -620,6 +620,8 @@ proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
someProc[high(someProc)] = val
else:
badNodeKind someProc.kind, "body="
proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.}
proc `$`*(node: PNimrodNode): string {.compileTime.} =
@@ -627,6 +629,8 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
case node.kind
of nnkIdent:
result = $node.ident
of nnkPostfix:
result = $node.basename.ident & "*"
of nnkStrLit..nnkTripleStrLit:
result = node.strVal
else:
@@ -669,7 +673,7 @@ proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
a[i + 1] = a[i]
a[pos] = b
proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} =
proc basename*(a: PNimrodNode): PNimrodNode =
## Pull an identifier from prefix/postfix expressions
case a.kind
of nnkIdent: return a

View File

@@ -57,7 +57,8 @@ when false:
binding: seq[MYSQL_BIND]
discard mysql_stmt_close(stmt)
proc dbQuote(s: string): string =
proc dbQuote*(s: string): string =
## DB quotes the string.
result = "'"
for c in items(s):
if c == '\'': add(result, "''")
@@ -69,7 +70,10 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
var a = 0
for c in items(string(formatstr)):
if c == '?':
add(result, dbQuote(args[a]))
if args[a] == nil:
add(result, "NULL")
else:
add(result, dbQuote(args[a]))
inc(a)
else:
add(result, c)
@@ -115,7 +119,10 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
if row == nil: break
for i in 0..L-1:
setLen(result[i], 0)
add(result[i], row[i])
if row[i] == nil:
result[i] = nil
else:
add(result[i], row[i])
yield result
properFreeResult(sqlres, row)
@@ -132,7 +139,10 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
if row != nil:
for i in 0..L-1:
setLen(result[i], 0)
add(result[i], row[i])
if row[i] == nil:
result[i] = nil
else:
add(result[i], row[i])
properFreeResult(sqlres, row)
proc getAllRows*(db: TDbConn, query: TSqlQuery,
@@ -150,7 +160,11 @@ proc getAllRows*(db: TDbConn, query: TSqlQuery,
if row == nil: break
setLen(result, j+1)
newSeq(result[j], L)
for i in 0..L-1: result[j][i] = $row[i]
for i in 0..L-1:
if row[i] == nil:
result[j][i] = nil
else:
result[j][i] = $row[i]
inc(j)
mysql.freeResult(sqlres)

View File

@@ -48,7 +48,8 @@ proc dbError*(msg: string) {.noreturn.} =
e.msg = msg
raise e
proc dbQuote(s: string): string =
proc dbQuote*(s: string): string =
## DB quotes the string.
result = "'"
for c in items(s):
if c == '\'': add(result, "''")
@@ -60,7 +61,10 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
var a = 0
for c in items(string(formatstr)):
if c == '?':
add(result, dbQuote(args[a]))
if args[a] == nil:
add(result, "NULL")
else:
add(result, dbQuote(args[a]))
inc(a)
else:
add(result, c)
@@ -123,8 +127,11 @@ proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery;
proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
for col in 0..cols-1:
setLen(r[col], 0)
var x = pqgetvalue(res, line, col)
add(r[col], x)
let x = pqgetvalue(res, line, col)
if x.isNil:
r[col] = nil
else:
add(r[col], x)
iterator fastRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =

103
lib/impure/fenv.nim Normal file
View File

@@ -0,0 +1,103 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2014 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Floating-point environment. Handling of floating-point rounding and
## exceptions (overflow, zero-devide, etc.).
{.deadCodeElim:on.}
when defined(Posix) and not defined(haiku):
{.passl: "-lm".}
var
FE_DIVBYZERO* {.importc, header: "<fenv.h>".}: cint
## division by zero
FE_INEXACT* {.importc, header: "<fenv.h>".}: cint
## inexact result
FE_INVALID* {.importc, header: "<fenv.h>".}: cint
## invalid operation
FE_OVERFLOW* {.importc, header: "<fenv.h>".}: cint
## result not representable due to overflow
FE_UNDERFLOW* {.importc, header: "<fenv.h>".}: cint
## result not representable due to underflow
FE_ALL_EXCEPT* {.importc, header: "<fenv.h>".}: cint
## bitwise OR of all supported exceptions
FE_DOWNWARD* {.importc, header: "<fenv.h>".}: cint
## round toward -Inf
FE_TONEAREST* {.importc, header: "<fenv.h>".}: cint
## round to nearest
FE_TOWARDZERO* {.importc, header: "<fenv.h>".}: cint
## round toward 0
FE_UPWARD* {.importc, header: "<fenv.h>".}: cint
## round toward +Inf
FE_DFL_ENV* {.importc, header: "<fenv.h>".}: cint
## macro of type pointer to fenv_t to be used as the argument
## to functions taking an argument of type fenv_t; in this
## case the default environment will be used
type
Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} =
object ## Represents the entire floating-point environment. The
## floating-point environment refers collectively to any
## floating-point status flags and control modes supported
## by the implementation.
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} =
object ## Represents the floating-point status flags collectively,
## including any status the implementation associates with the
## flags. A floating-point status flag is a system variable
## whose value is set (but never cleared) when a floating-point
## exception is raised, which occurs as a side effect of
## exceptional floating-point arithmetic to provide auxiliary
## information. A floating-point control mode is a system variable
## whose value may be set by the user to affect the subsequent
## behavior of floating-point arithmetic.
proc feclearexcept*(excepts: cint): cint {.importc, header: "<fenv.h>".}
## Clear the supported exceptions represented by `excepts`.
proc fegetexceptflag*(flagp: ptr Tfexcept, excepts: cint): cint {.
importc, header: "<fenv.h>".}
## Store implementation-defined representation of the exception flags
## indicated by `excepts` in the object pointed to by `flagp`.
proc feraiseexcept*(excepts: cint): cint {.importc, header: "<fenv.h>".}
## Raise the supported exceptions represented by `excepts`.
proc fesetexceptflag*(flagp: ptr Tfexcept, excepts: cint): cint {.
importc, header: "<fenv.h>".}
## Set complete status for exceptions indicated by `excepts` according to
## the representation in the object pointed to by `flagp`.
proc fetestexcept*(excepts: cint): cint {.importc, header: "<fenv.h>".}
## Determine which of subset of the exceptions specified by `excepts` are
## currently set.
proc fegetround*(): cint {.importc, header: "<fenv.h>".}
## Get current rounding direction.
proc fesetround*(roundingDirection: cint): cint {.importc, header: "<fenv.h>".}
## Establish the rounding direction represented by `roundingDirection`.
proc fegetenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
## Store the current floating-point environment in the object pointed
## to by `envp`.
proc feholdexcept*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
## Save the current environment in the object pointed to by `envp`, clear
## exception flags and install a non-stop mode (if available) for all
## exceptions.
proc fesetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
## Establish the floating-point environment represented by the object
## pointed to by `envp`.
proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
## Save current exceptions in temporary storage, install environment
## represented by object pointed to by `envp` and raise exceptions
## according to saved exceptions.

View File

@@ -102,22 +102,6 @@ type
l_pid*: TPid ## Process ID of the process holding the lock;
## returned with F_GETLK.
Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} =
object ## Represents the entire floating-point environment. The
## floating-point environment refers collectively to any
## floating-point status flags and control modes supported
## by the implementation.
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} =
object ## Represents the floating-point status flags collectively,
## including any status the implementation associates with the
## flags. A floating-point status flag is a system variable
## whose value is set (but never cleared) when a floating-point
## exception is raised, which occurs as a side effect of
## exceptional floating-point arithmetic to provide auxiliary
## information. A floating-point control mode is a system variable
## whose value may be set by the user to affect the subsequent
## behavior of floating-point arithmetic.
TFTW* {.importc: "struct FTW", header: "<ftw.h>", final, pure.} = object
base*: cint
level*: cint
@@ -842,18 +826,6 @@ var
## The application expects to access the specified data once and
## then not reuse it thereafter.
FE_DIVBYZERO* {.importc, header: "<fenv.h>".}: cint
FE_INEXACT* {.importc, header: "<fenv.h>".}: cint
FE_INVALID* {.importc, header: "<fenv.h>".}: cint
FE_OVERFLOW* {.importc, header: "<fenv.h>".}: cint
FE_UNDERFLOW* {.importc, header: "<fenv.h>".}: cint
FE_ALL_EXCEPT* {.importc, header: "<fenv.h>".}: cint
FE_DOWNWARD* {.importc, header: "<fenv.h>".}: cint
FE_TONEAREST* {.importc, header: "<fenv.h>".}: cint
FE_TOWARDZERO* {.importc, header: "<fenv.h>".}: cint
FE_UPWARD* {.importc, header: "<fenv.h>".}: cint
FE_DFL_ENV* {.importc, header: "<fenv.h>".}: cint
when not defined(haiku) and not defined(OpenBSD):
var
MM_HARD* {.importc, header: "<fmtmsg.h>".}: cint
@@ -1829,20 +1801,6 @@ proc posix_fadvise*(a1: cint, a2, a3: TOff, a4: cint): cint {.
proc posix_fallocate*(a1: cint, a2, a3: TOff): cint {.
importc, header: "<fcntl.h>".}
proc feclearexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
proc fegetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.
importc, header: "<fenv.h>".}
proc feraiseexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
proc fesetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.
importc, header: "<fenv.h>".}
proc fetestexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
proc fegetround*(): cint {.importc, header: "<fenv.h>".}
proc fesetround*(a1: cint): cint {.importc, header: "<fenv.h>".}
proc fegetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
proc feholdexcept*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
proc fesetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
proc feupdateenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
when not defined(haiku) and not defined(OpenBSD):
proc fmtmsg*(a1: int, a2: cstring, a3: cint,
a4, a5, a6: cstring): cint {.importc, header: "<fmtmsg.h>".}

View File

@@ -115,3 +115,60 @@ macro `->`*(p, b: expr): expr {.immediate.} =
## f(2, 2)
result = createProcType(p, b)
type ListComprehension = object
var lc*: ListComprehension
macro `[]`*(lc: ListComprehension, comp, typ: expr): expr =
## List comprehension, returns a sequence. `comp` is the actual list
## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is
## the type that will be stored inside the result seq.
##
## .. code-block:: nimrod
##
## echo lc[x | (x <- 1..10, x mod 2 == 0), int]
##
## const n = 20
## echo lc[(x,y,z) | (x <- 1..n, y <- x..n, z <- y..n, x*x + y*y == z*z),
## tuple[a,b,c: int]]
expectLen(comp, 3)
expectKind(comp, nnkInfix)
expectKind(comp[0], nnkIdent)
assert($comp[0].ident == "|")
result = newCall(
newDotExpr(
newIdentNode("result"),
newIdentNode("add")),
comp[1])
for i in countdown(comp[2].len-1, 0):
let x = comp[2][i]
expectKind(x, nnkInfix)
expectMinLen(x, 1)
if x[0].kind == nnkIdent and $x[0].ident == "<-":
expectLen(x, 3)
result = newNimNode(nnkForStmt).add(x[1], x[2], result)
else:
result = newIfStmt((x, result))
result = newNimNode(nnkCall).add(
newNimNode(nnkPar).add(
newNimNode(nnkLambda).add(
newEmptyNode(),
newEmptyNode(),
newEmptyNode(),
newNimNode(nnkFormalParams).add(
newNimNode(nnkBracketExpr).add(
newIdentNode("seq"),
typ)),
newEmptyNode(),
newEmptyNode(),
newStmtList(
newAssignment(
newIdentNode("result"),
newNimNode(nnkPrefix).add(
newIdentNode("@"),
newNimNode(nnkBracket))),
result))))

View File

@@ -14,7 +14,6 @@
## <backends.html#the-javascript-target>`_.
include "system/inclrtl"
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!

View File

@@ -13,25 +13,31 @@
const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
when someGcc and hasThreadSupport:
type
AtomMemModel* = enum
ATOMIC_RELAXED, ## No barriers or synchronization.
ATOMIC_CONSUME, ## Data dependency only for both barrier and
## synchronization with another thread.
ATOMIC_ACQUIRE, ## Barrier to hoisting of code and synchronizes with
## release (or stronger)
## semantic stores from another thread.
ATOMIC_RELEASE, ## Barrier to sinking of code and synchronizes with
## acquire (or stronger)
## semantic loads from another thread.
ATOMIC_ACQ_REL, ## Full barrier in both directions and synchronizes
## with acquire loads
## and release stores in another thread.
ATOMIC_SEQ_CST ## Full barrier in both directions and synchronizes
## with acquire loads
## and release stores in all threads.
type AtomMemModel* = distinct cint
var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel
## No barriers or synchronization.
var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel
## Data dependency only for both barrier and
## synchronization with another thread.
var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
## Barrier to hoisting of code and synchronizes with
## release (or stronger)
## semantic stores from another thread.
var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel
## Barrier to sinking of code and synchronizes with
## acquire (or stronger)
## semantic loads from another thread.
var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel
## Full barrier in both directions and synchronizes
## with acquire loads
## and release stores in another thread.
var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel
## Full barrier in both directions and synchronizes
## with acquire loads
## and release stores in all threads.
TAtomType* = SomeNumber|pointer|ptr|char
type
TAtomType* = TNumber|pointer|ptr|char
## Type Class representing valid types for use with atomic procs
proc atomicLoadN*[T: TAtomType](p: ptr T, mem: AtomMemModel): T {.
@@ -167,14 +173,14 @@ else:
result = p[]
proc atomicInc*(memLoc: var int, x: int = 1): int =
when defined(gcc) and hasThreadSupport:
when someGcc and hasThreadSupport:
result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
else:
inc(memLoc, x)
result = memLoc
proc atomicDec*(memLoc: var int, x: int = 1): int =
when defined(gcc) and hasThreadSupport:
when someGcc and hasThreadSupport:
when declared(atomic_sub_fetch):
result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
else:
@@ -197,7 +203,7 @@ else:
# XXX is this valid for 'int'?
when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)):
when (defined(x86) or defined(amd64)) and someGcc:
proc cpuRelax {.inline.} =
{.emit: """asm volatile("pause" ::: "memory");""".}
elif (defined(x86) or defined(amd64)) and defined(vcc):

View File

@@ -149,11 +149,6 @@
CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
#end if
; Add shortcuts for the documentation
#for f in items(c.cat[fcDocStart]):
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}"
#end for
; Write the shortcut to the uninstaller
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe"
!insertmacro MUI_STARTMENU_WRITE_END
@@ -162,6 +157,7 @@
; Section for adding tools to the PATH variable
Section "Setup Path Environment" PathSection
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw"
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw\bin"
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\bin"
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\babel"
SectionEnd
@@ -203,15 +199,15 @@
abort
${EndIf}
; Shortcuts
# if d.len >= 6:
# let startMenuEntry = d[5]
# let e = splitFile(startMenuEntry).name.capitalize
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
# end if
; Shortcuts
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
!insertmacro MUI_STARTMENU_WRITE_END
# end if
ignore:
SectionEnd
#end
@@ -248,6 +244,7 @@
; Remove entries from the PATH environment variable
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw"
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw\bin"
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\bin"
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\babel"
SectionEnd