Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Dominik Picheta
2016-04-04 12:06:42 +01:00
28 changed files with 463 additions and 102 deletions

View File

@@ -1856,10 +1856,16 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
initLocExpr(p, n.sons[1], b)
if n.sons[0].skipConv.kind == nkClosure:
internalError(n.info, "closure to closure created")
getTemp(p, n.typ, tmp)
linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
tmp.rdLoc, a.rdLoc, b.rdLoc)
putLocIntoDest(p, d, tmp)
# tasyncawait.nim breaks with this optimization:
when false:
if d.k != locNone:
linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
d.rdLoc, a.rdLoc, b.rdLoc)
else:
getTemp(p, n.typ, tmp)
linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
tmp.rdLoc, a.rdLoc, b.rdLoc)
putLocIntoDest(p, d, tmp)
proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
var arr: TLoc

View File

@@ -1059,9 +1059,8 @@ proc genModule(m: BModule, cfile: string): Rope =
result = getFileHeader(cfile)
result.add(genMergeInfo(m))
generateHeaders(m)
generateThreadLocalStorage(m)
generateHeaders(m)
for i in countup(cfsHeaders, cfsProcs):
add(result, genSectionStart(i))
add(result, m.s[i])

View File

@@ -721,6 +721,10 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
let m = newSymNode(n[namePos].sym)
m.typ = n.typ
result = liftCapturedVars(m, owner, d, c)
of nkHiddenStdConv:
if n.len == 2:
n.sons[1] = liftCapturedVars(n[1], owner, d, c)
if n[1].kind == nkClosure: result = n[1]
else:
if owner.isIterator:
if n.kind == nkYieldStmt:

View File

@@ -326,6 +326,7 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode =
getTok(p)
else:
parMessage(p, errIdentifierExpected, p.tok)
break
eat(p, tkAccent)
else:
if allowNil and p.tok.tokType == tkNil:

View File

@@ -256,8 +256,9 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
if (sym == nil) or (sym.kind == skModule):
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
expectDynlibNode(c, n))
let lib = getLib(c, libDynamic, expectDynlibNode(c, n))
if not lib.isOverriden:
POptionEntry(c.optionStack.tail).dynlib = lib
else:
if n.kind == nkExprColonExpr:
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))

View File

@@ -10,7 +10,9 @@
## This file implements the new evaluation engine for Nim code.
## An instruction is 1-3 int32s in memory, it is a register based VM.
const debugEchoCode = false
const
debugEchoCode = false
traceCode = debugEchoCode
import ast except getstr
@@ -121,7 +123,7 @@ template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b)
# XXX fix minor 'shallowCopy' overloading bug in compiler
proc createStrKeepNode(x: var TFullReg; keepNode=true) =
if x.node.isNil:
if x.node.isNil or not keepNode:
x.node = newNode(nkStrLit)
elif x.node.kind == nkNilLit and keepNode:
when defined(useNodeIds):
@@ -404,7 +406,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let instr = c.code[pc]
let ra = instr.regA
#if c.traceActive:
#echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
when traceCode:
echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
# message(c.debug[pc], warnUser, "Trace")
case instr.opcode
@@ -542,7 +545,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
if regs[rb].node.kind == nkRefTy:
regs[ra].node = regs[rb].node.sons[0]
else:
stackTrace(c, tos, pc, errGenerated, "limited VM support for 'ref'")
stackTrace(c, tos, pc, errGenerated, "limited VM support for pointers")
else:
stackTrace(c, tos, pc, errNilAccess)
of opcWrDeref:

View File

@@ -102,6 +102,10 @@ proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
(b.uint32 shl 16'u32) or
(c.uint32 shl 24'u32)).TInstr
when false:
if ctx.code.len == 43:
writeStackTrace()
echo "generating ", opc
ctx.code.add(ins)
ctx.debug.add(n.info)
@@ -122,6 +126,11 @@ proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
# Applies `opc` to `bx` and stores it into register `a`
# `bx` must be signed and in the range [-32768, 32767]
when false:
if c.code.len == 43:
writeStackTrace()
echo "generating ", opc
if bx >= -32768 and bx <= 32767:
let ins = (opc.uint32 or a.uint32 shl 8'u32 or
(bx+wordExcess).uint32 shl 16'u32).TInstr
@@ -704,6 +713,10 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
c.genNarrow(n, dest)
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
if n.typ.kind == arg.typ.kind and arg.typ.kind == tyProc:
# don't do anything for lambda lifting conversions:
gen(c, arg, dest)
return
let tmp = c.genx(arg)
if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opc, dest, tmp)
@@ -1117,7 +1130,10 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
if isAddr and (let m = canElimAddr(n); m != nil):
gen(c, m, dest, flags)
return
let newflags = if isAddr: flags+{gfAddrOf} else: flags
let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfAddrOf, gfFieldAccess}
else: {gfAddrOf}
let newflags = if isAddr: flags+af else: flags
# consider:
# proc foo(f: var ref int) =
# f = new(int)
@@ -1132,7 +1148,7 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
if gfAddrOf notin flags and fitsRegister(n.typ):
c.gABC(n, opcNodeToReg, dest, dest)
elif isAddr and isGlobal(n.sons[0]):
gen(c, n.sons[0], dest, flags+{gfAddrOf})
gen(c, n.sons[0], dest, flags+af)
else:
let tmp = c.genx(n.sons[0], newflags)
if dest < 0: dest = c.getTemp(n.typ)
@@ -1447,12 +1463,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyObject:
result = newNodeIT(nkObjConstr, info, t)
result.add(newNodeIT(nkEmpty, info, t))
getNullValueAux(t.n, result)
# initialize inherited fields:
var base = t.sons[0]
while base != nil:
getNullValueAux(skipTypes(base, skipPtrs).n, result)
base = base.sons[0]
getNullValueAux(t.n, result)
of tyArray, tyArrayConstr:
result = newNodeIT(nkBracket, info, t)
for i in countup(0, int(lengthOrd(t)) - 1):
@@ -1736,9 +1752,9 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
of declarativeDefs:
unused(n, dest)
of nkLambdaKinds:
let s = n.sons[namePos].sym
discard genProc(c, s)
genLit(c, n.sons[namePos], dest)
#let s = n.sons[namePos].sym
#discard genProc(c, s)
genLit(c, newSymNode(n.sons[namePos].sym), dest)
of nkChckRangeF, nkChckRange64, nkChckRange:
let
tmp0 = c.genx(n.sons[0])

View File

@@ -420,7 +420,7 @@ function directly will be able to use it since Nim's garbage collector has
not had a chance to run *yet*. This gives you enough time to make a copy for
the C side of the program, as calling any further Nim procs *might* trigger
garbage collection making the previously returned string garbage. Or maybe you
are `triggering yourself the collection <gc.html>`_.
are `yourself triggering the collection <gc.html>`_.
Custom data types

View File

@@ -77,38 +77,6 @@ Once bound, typedesc params can appear in the rest of the proc signature:
declareVariableWithType int, 42
When used with macros and .compileTime. procs on the other hand, the compiler
does not need to instantiate the code multiple times, because types then can be
manipulated using the unified internal symbol representation. In such context
typedesc acts as any other type. One can create variables, store typedesc
values inside containers and so on. For example, here is how one can create
a type-safe wrapper for the unsafe `printf` function from C:
.. code-block:: nim
macro safePrintF(formatString: string{lit}, args: varargs[expr]): expr =
var i = 0
for c in formatChars(formatString):
var expectedType = case c
of 'c': char
of 'd', 'i', 'x', 'X': int
of 'f', 'e', 'E', 'g', 'G': float
of 's': string
of 'p': pointer
else: EOutOfRange
var actualType = args[i].getType
inc i
if expectedType == EOutOfRange:
error c & " is not a valid format character"
elif expectedType != actualType:
error "type mismatch for argument ", i, ". expected type: ",
expectedType.name, ", actual type: ", actualType.name
# keep the original callsite, but use cprintf instead
result = callsite()
result[0] = newIdentNode(!"cprintf")
Overload resolution can be further influenced by constraining the set of
types that will match the typedesc param:

View File

@@ -9,6 +9,7 @@
## This module contains Nim's support for locks and condition vars.
const insideRLocksModule = false
include "system/syslocks"
type
@@ -63,4 +64,4 @@ template withLock*(a: Lock, body: untyped) =
try:
body
finally:
a.release()
a.release()

View File

@@ -9,6 +9,7 @@
## This module contains Nim's support for reentrant locks.
const insideRLocksModule = true
include "system/syslocks"
type

View File

@@ -35,6 +35,15 @@ const
hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays
hasAioH = defined(linux)
when defined(linux):
# On Linux:
# timer_{create,delete,settime,gettime},
# clock_{getcpuclockid, getres, gettime, nanosleep, settime} lives in librt
{.passL: "-lrt".}
when defined(solaris):
# On Solaris hstrerror lives in libresolv
{.passL: "-lresolv".}
when false:
const
C_IRUSR = 0c000400 ## Read by owner.
@@ -2309,9 +2318,9 @@ proc strftime*(a1: cstring, a2: int, a3: cstring,
a4: var Tm): int {.importc, header: "<time.h>".}
proc strptime*(a1, a2: cstring, a3: var Tm): cstring {.importc, header: "<time.h>".}
proc time*(a1: var Time): Time {.importc, header: "<time.h>".}
proc timer_create*(a1: var ClockId, a2: var SigEvent,
proc timer_create*(a1: ClockId, a2: var SigEvent,
a3: var Timer): cint {.importc, header: "<time.h>".}
proc timer_delete*(a1: var Timer): cint {.importc, header: "<time.h>".}
proc timer_delete*(a1: Timer): cint {.importc, header: "<time.h>".}
proc timer_gettime*(a1: Timer, a2: var Itimerspec): cint {.
importc, header: "<time.h>".}
proc timer_getoverrun*(a1: Timer): cint {.importc, header: "<time.h>".}

View File

@@ -0,0 +1,44 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2016 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Template based implementation of singly and doubly linked lists.
## The involved types should have 'prev' or 'next' fields and the
## list header should have 'head' or 'tail' fields.
template prepend*(header, node) =
when compiles(header.head):
when compiles(node.prev):
if header.head != nil:
header.head.prev = node
node.next = header.head
header.head = node
when compiles(header.tail):
if header.tail == nil:
header.tail = node
template append*(header, node) =
when compiles(header.head):
if header.head == nil:
header.head = node
when compiles(header.tail):
when compiles(node.prev):
node.prev = header.tail
if header.tail != nil:
header.tail.next = node
header.tail = node
template unlink*(header, node) =
if node.next != nil:
node.next.prev = node.prev
if node.prev != nil:
node.prev.next = node.next
if header.head == node:
header.head = node.prev
if header.tail == node:
header.tail = node.next

View File

@@ -5,29 +5,31 @@ type
{.deprecated: [TMersenneTwister: MersenneTwister].}
proc newMersenneTwister*(seed: int): MersenneTwister =
proc newMersenneTwister*(seed: uint32): MersenneTwister =
result.index = 0
result.mt[0]= uint32(seed)
result.mt[0] = seed
for i in 1..623'u32:
result.mt[i]= (0x6c078965'u32 * (result.mt[i-1] xor (result.mt[i-1] shr 30'u32)) + i)
result.mt[i] = (0x6c078965'u32 * (result.mt[i-1] xor (result.mt[i-1] shr 30'u32)) + i)
proc generateNumbers(m: var MersenneTwister) =
for i in 0..623:
var y = (m.mt[i] and 0x80000000'u32) + (m.mt[(i+1) mod 624] and 0x7fffffff'u32)
var y = (m.mt[i] and 0x80000000'u32) +
(m.mt[(i+1) mod 624] and 0x7fffffff'u32)
m.mt[i] = m.mt[(i+397) mod 624] xor uint32(y shr 1'u32)
if (y mod 2'u32) != 0:
m.mt[i] = m.mt[i] xor 0x9908b0df'u32
m.mt[i] = m.mt[i] xor 0x9908b0df'u32
proc getNum*(m: var MersenneTwister): int =
proc getNum*(m: var MersenneTwister): uint32 =
## Returns the next pseudo random number ranging from 0 to high(uint32)
if m.index == 0:
generateNumbers(m)
var y = m.mt[m.index]
y = y xor (y shr 11'u32)
y = y xor ((7'u32 shl y) and 0x9d2c5680'u32)
y = y xor ((15'u32 shl y) and 0xefc60000'u32)
y = y xor (y shr 18'u32)
m.index = (m.index+1) mod 624
return int(y)
result = m.mt[m.index]
m.index = (m.index + 1) mod m.mt.len
result = result xor (result shr 11'u32)
result = result xor ((7'u32 shl result) and 0x9d2c5680'u32)
result = result xor ((15'u32 shl result) and 0xefc60000'u32)
result = result xor (result shr 18'u32)
# Test
when not defined(testing) and isMainModule:

View File

@@ -222,9 +222,9 @@ when defined(ssl):
of protSSLv23:
newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
of protSSLv2:
raiseSslError("SSLv2 is no longer secure and has been deprecated, use protSSLv3")
raiseSslError("SSLv2 is no longer secure and has been deprecated, use protSSLv23")
of protSSLv3:
newCTX = SSL_CTX_new(SSLv3_method())
raiseSslError("SSLv3 is no longer secure and has been deprecated, use protSSLv23")
of protTLSv1:
newCTX = SSL_CTX_new(TLSv1_method())

View File

@@ -234,6 +234,47 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
elif result != 0:
number = int(res)
# overflowChecks doesn't work with uint64
proc rawParseUInt(s: string, b: var uint64, start = 0): int =
var
res = 0'u64
prev = 0'u64
i = start
if s[i] == '+': inc(i) # Allow
if s[i] in {'0'..'9'}:
b = 0
while s[i] in {'0'..'9'}:
prev = res
res = res * 10 + (ord(s[i]) - ord('0')).uint64
if prev > res:
return 0 # overflowChecks emulation
inc(i)
while s[i] == '_': inc(i) # underscores are allowed and ignored
b = res
result = i - start
proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {.
rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
## parses an unsigned integer starting at `start` and stores the value into `number`.
## Result is the number of processed chars or 0 if there is no integer or overflow detected.
var res: uint64
# use 'res' for exception safety (don't write to 'number' in case of an
# overflow exception):
result = rawParseUInt(s, res, start)
number = res
proc parseUInt*(s: string, number: var uint, start = 0): int {.
rtl, extern: "npuParseUInt", noSideEffect.} =
## parses an unsigned integer starting at `start` and stores the value into `number`.
## Result is the number of processed chars or 0 if there is no integer or overflow detected.
var res: uint64
result = parseBiggestUInt(s, res, start)
if (sizeof(uint) <= 4) and
(res > 0xFFFF_FFFF'u64):
raise newException(OverflowError, "overflow")
elif result != 0:
number = uint(res)
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
## parses a float starting at `start` and stores the value into `number`.

View File

@@ -560,6 +560,24 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar,
if L != s.len or L == 0:
raise newException(ValueError, "invalid integer: " & s)
proc parseUInt*(s: string): uint {.noSideEffect, procvar,
rtl, extern: "nsuParseUInt".} =
## Parses a decimal unsigned integer value contained in `s`.
##
## If `s` is not a valid integer, `ValueError` is raised.
var L = parseutils.parseUInt(s, result, 0)
if L != s.len or L == 0:
raise newException(ValueError, "invalid unsigned integer: " & s)
proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
rtl, extern: "nsuParseBiggestUInt".} =
## Parses a decimal unsigned integer value contained in `s`.
##
## If `s` is not a valid integer, `ValueError` is raised.
var L = parseutils.parseBiggestUInt(s, result, 0)
if L != s.len or L == 0:
raise newException(ValueError, "invalid unsigned integer: " & s)
proc parseFloat*(s: string): float {.noSideEffect, procvar,
rtl, extern: "nsuParseFloat".} =
## Parses a decimal floating point value contained in `s`. If `s` is not

View File

@@ -2877,6 +2877,7 @@ when not defined(JS): #and not defined(nimscript):
when declared(initAllocator):
initAllocator()
when hasThreadSupport:
const insideRLocksModule = false
include "system/syslocks"
when hostOS != "standalone": include "system/threads"
elif not defined(nogc) and not defined(nimscript):

View File

@@ -109,9 +109,30 @@ elif defined(windows) or defined(dos):
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
result = getProcAddress(cast[THINSTANCE](lib), name)
if result != nil: return
var decorated: array[250, char]
const decorated_length = 250
var decorated: array[decorated_length, char]
decorated[0] = '_'
var m = 1
while m < (decorated_length - 5):
if name[m - 1] == '\x00': break
decorated[m] = name[m - 1]
inc(m)
decorated[m] = '@'
for i in countup(0, 50):
discard csprintf(decorated, "_%s@%ld", name, i*4)
var k = i * 4
if k div 100 == 0:
if k div 10 == 0:
m = m + 1
else:
m = m + 2
else:
m = m + 3
decorated[m + 1] = '\x00'
while true:
decorated[m] = chr(ord('0') + (k %% 10))
dec(m)
k = k div 10
if k == 0: break
result = getProcAddress(cast[THINSTANCE](lib), decorated)
if result != nil: return
procAddrError(name)

View File

@@ -14,39 +14,41 @@
when defined(Windows):
type
Handle = int
SysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
SysLock {.importc: "CRITICAL_SECTION",
header: "<windows.h>", final, pure.} = object # CRITICAL_SECTION in WinApi
DebugInfo: pointer
LockCount: int32
RecursionCount: int32
OwningThread: int
LockSemaphore: int
Reserved: int32
SpinCount: int
SysCond = Handle
{.deprecated: [THandle: Handle, TSysLock: SysLock, TSysCond: SysCond].}
proc initSysLock(L: var SysLock) {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "InitializeCriticalSection".}
proc initSysLock(L: var SysLock) {.importc: "InitializeCriticalSection",
header: "<windows.h>".}
## Initializes the lock `L`.
proc tryAcquireSysAux(L: var SysLock): int32 {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "TryEnterCriticalSection".}
proc tryAcquireSysAux(L: var SysLock): int32 {.importc: "TryEnterCriticalSection",
header: "<windows.h>".}
## Tries to acquire the lock `L`.
proc tryAcquireSys(L: var SysLock): bool {.inline.} =
result = tryAcquireSysAux(L) != 0'i32
proc acquireSys(L: var SysLock) {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "EnterCriticalSection".}
proc acquireSys(L: var SysLock) {.importc: "EnterCriticalSection",
header: "<windows.h>".}
## Acquires the lock `L`.
proc releaseSys(L: var SysLock) {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "LeaveCriticalSection".}
proc releaseSys(L: var SysLock) {.importc: "LeaveCriticalSection",
header: "<windows.h>".}
## Releases the lock `L`.
proc deinitSys(L: var SysLock) {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "DeleteCriticalSection".}
proc deinitSys(L: var SysLock) {.importc: "DeleteCriticalSection",
header: "<windows.h>".}
proc createEvent(lpEventAttributes: pointer,
bManualReset, bInitialState: int32,
@@ -86,17 +88,16 @@ else:
#include <pthread.h>""".} = object
SysLockType = distinct cint
proc SysLockType_Reentrant: SysLockType =
{.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) {.
importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
proc initSysLockAttr(a: var SysLockAttr) {.
importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
when insideRLocksModule:
proc SysLockType_Reentrant: SysLockType =
{.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
proc initSysLockAttr(a: var SysLockAttr) {.
importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
proc acquireSys(L: var SysLock) {.noSideEffect,
importc: "pthread_mutex_lock", header: "<pthread.h>".}
@@ -111,14 +112,12 @@ else:
proc deinitSys(L: var SysLock) {.noSideEffect,
importc: "pthread_mutex_destroy", header: "<pthread.h>".}
proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
proc signalSysCond(cond: var SysCond) {.
importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
proc deinitSysCond(cond: var SysCond) {.noSideEffect,
importc: "pthread_cond_destroy", header: "<pthread.h>".}
{.pop.}
when not insideRLocksModule:
proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
proc signalSysCond(cond: var SysCond) {.
importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
proc deinitSysCond(cond: var SysCond) {.noSideEffect,
importc: "pthread_cond_destroy", header: "<pthread.h>".}

View File

@@ -0,0 +1,24 @@
# bug #3995
import future
type
RNG* = tuple[]
Rand*[A] = (RNG) -> (A, RNG)
proc nextInt*(r: RNG): (int, RNG) =
(1, ())
proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
(rng: RNG) => (
let (a, rng2) = f(rng);
let g1 = g(a);
g1(rng2)
)
proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
flatMap(s, g)
let f = nextInt.map(i => i - i mod 2)

View File

@@ -0,0 +1,48 @@
discard """
output: '''test 10'''
"""
# bug #1152
import macros, typetraits
proc printfImpl(formatstr: cstring) {.importc: "printf", varargs.}
iterator tokenize(format: string): char =
var i = 0
while true:
case format[i]
of '%':
case format[i+1]
of '\0': break
else: yield format[i+1]
i.inc
of '\0': break
else: discard
i.inc
macro printf(formatString: string{lit}, args: varargs[typed]): untyped =
var i = 0
let err = getType(bindSym"ValueError")
for c in tokenize(formatString.strVal):
var expectedType = case c
of 'c': getType(bindSym"char")
of 'd', 'i', 'x', 'X': getType(bindSym"int")
of 'f', 'e', 'E', 'g', 'G': getType(bindSym"float")
of 's': getType(bindSym"string")
of 'p': getType(bindSym"pointer")
else: err
var actualType = getType(args[i])
inc i
if sameType(expectedType, err):
error c & " is not a valid format character"
elif not sameType(expectedType, actualType):
error "type mismatch for argument " & $i & ". expected type: " &
$expectedType & ", actual type: " & $actualType
# keep the original callsite, but use cprintf instead
result = callsite()
result[0] = bindSym"printfImpl"
printf("test %d\n", 10)

View File

@@ -0,0 +1,11 @@
discard """
action: run
"""
import unittest, strutils
suite "parseutils":
test "uint":
check: parseBiggestUInt("0") == 0'u64
check: parseBiggestUInt("18446744073709551615") == 0xFFFF_FFFF_FFFF_FFFF'u64
expect(ValueError):
discard parseBiggestUInt("18446744073709551616")

52
tests/vm/tanonproc.nim Normal file
View File

@@ -0,0 +1,52 @@
discard """
output: '''`Test`'''
"""
# bug #3561
import macros, future, strutils
type
Option[T] = ref object
case valid: bool
of true:
data: T
else:
discard
proc some[T](v: T): Option[T] = Option[T](valid: true, data: v)
proc none[T](v: T): Option[T] = Option[T](valid: false)
proc none(T: typedesc): Option[T] = Option[T](valid: false)
proc map[T,U](o: Option[T], f: T -> U): Option[U] =
case o.valid
of true:
f(o.data).some
else:
U.none
proc notEmpty(o: Option[string]): Option[string] =
case o.valid
of true:
if o.data.strip == "": string.none else: o.data.strip.some
else:
o
proc getOrElse[T](o: Option[T], def: T): T =
case o.valid
of true:
o.data
else:
def
proc quoteStr(s: string): Option[string] =
s.some.notEmpty.map(v => "`" & v & "`")
macro str(s: string): stmt =
let x = s.strVal
let y = quoteStr(x)
let sn = newStrLitNode(y.getOrElse("NONE"))
result = quote do:
echo `sn`
str"Test"

29
tests/vm/tinheritance.nim Normal file
View File

@@ -0,0 +1,29 @@
discard """
msg: '''Hello fred , managed by sally
Hello sally , managed by bob'''
"""
# bug #3973
type
EmployeeCode = enum
ecCode1,
ecCode2
Person* = object of RootObj
name* : string
last_name*: string
Employee* = object of Person
empl_code* : EmployeeCode
mgr_name* : string
proc test() =
var
empl1 = Employee(name: "fred", last_name: "smith", mgr_name: "sally", empl_code: ecCode1)
empl2 = Employee(name: "sally", last_name: "jones", mgr_name: "bob", empl_code: ecCode2)
echo "Hello ", empl1.name, " , managed by ", empl1.mgr_name
echo "Hello ", empl2.name, " , managed by ", empl2.mgr_name
static:
test()

31
tests/vm/tmitems.nim Normal file
View File

@@ -0,0 +1,31 @@
discard """
msg: '''13'''
output: '''3
3
3'''
"""
# bug #3731
var list {.compileTime.} = newSeq[int]()
macro calc*(): stmt {.immediate.} =
list.add(1)
for c in list.mitems:
c = 13
for c in list:
echo c
calc()
# bug #3859
import macros
macro m: stmt =
var s = newseq[NimNode](3)
# var s: array[3,NimNode] # not working either
for i in 0..<s.len: s[i] = newLit(3) # works
#for x in s.mitems: x = newLit(3)
result = newStmtList()
for i in s:
result.add newCall(bindsym"echo", i)
m()

View File

@@ -0,0 +1,28 @@
discard """
output: '''success'''
"""
# bug #3804
#import sequtils
type AnObj = ref object
field: string
#proc aBug(objs: seq[AnObj]) {.compileTime.} =
# discard objs.mapIt(it.field & " bug")
proc sameBug(objs: seq[AnObj]) {.compileTime.} =
var strSeq = newSeq[string](objs.len)
strSeq[0] = objs[0].field & " bug"
static:
var objs: seq[AnObj] = @[]
objs.add(AnObj(field: "hello"))
sameBug(objs)
# sameBug(objs)
echo objs[0].field
assert(objs[0].field == "hello") # fails, because (objs[0].field == "hello bug") - mutated!
echo "success"

View File

@@ -20,6 +20,9 @@ Changes affecting backwards compatibility
new experimental ``this`` pragma to achieve a similar effect to what the old ``using`` statement tried to achieve.
- Typeless parameters have been removed from the language since it would
clash with ``using``.
- Procedures in ``mersenne.nim`` (Mersenne Twister implementation) no longer
accept and produce ``int`` values which have platform-dependent size -
they use ``uint32`` instead.
Library Additions