Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
436b003173
28 changed files with 463 additions and 102 deletions
|
|
@ -1856,6 +1856,12 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, n.sons[1], b)
|
initLocExpr(p, n.sons[1], b)
|
||||||
if n.sons[0].skipConv.kind == nkClosure:
|
if n.sons[0].skipConv.kind == nkClosure:
|
||||||
internalError(n.info, "closure to closure created")
|
internalError(n.info, "closure to closure created")
|
||||||
|
# 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)
|
getTemp(p, n.typ, tmp)
|
||||||
linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
|
linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
|
||||||
tmp.rdLoc, a.rdLoc, b.rdLoc)
|
tmp.rdLoc, a.rdLoc, b.rdLoc)
|
||||||
|
|
|
||||||
|
|
@ -1059,9 +1059,8 @@ proc genModule(m: BModule, cfile: string): Rope =
|
||||||
result = getFileHeader(cfile)
|
result = getFileHeader(cfile)
|
||||||
result.add(genMergeInfo(m))
|
result.add(genMergeInfo(m))
|
||||||
|
|
||||||
generateHeaders(m)
|
|
||||||
|
|
||||||
generateThreadLocalStorage(m)
|
generateThreadLocalStorage(m)
|
||||||
|
generateHeaders(m)
|
||||||
for i in countup(cfsHeaders, cfsProcs):
|
for i in countup(cfsHeaders, cfsProcs):
|
||||||
add(result, genSectionStart(i))
|
add(result, genSectionStart(i))
|
||||||
add(result, m.s[i])
|
add(result, m.s[i])
|
||||||
|
|
|
||||||
|
|
@ -721,6 +721,10 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
|
||||||
let m = newSymNode(n[namePos].sym)
|
let m = newSymNode(n[namePos].sym)
|
||||||
m.typ = n.typ
|
m.typ = n.typ
|
||||||
result = liftCapturedVars(m, owner, d, c)
|
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:
|
else:
|
||||||
if owner.isIterator:
|
if owner.isIterator:
|
||||||
if n.kind == nkYieldStmt:
|
if n.kind == nkYieldStmt:
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,7 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, p.tok)
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
|
break
|
||||||
eat(p, tkAccent)
|
eat(p, tkAccent)
|
||||||
else:
|
else:
|
||||||
if allowNil and p.tok.tokType == tkNil:
|
if allowNil and p.tok.tokType == tkNil:
|
||||||
|
|
|
||||||
|
|
@ -256,8 +256,9 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||||
if (sym == nil) or (sym.kind == skModule):
|
if (sym == nil) or (sym.kind == skModule):
|
||||||
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
|
let lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
||||||
expectDynlibNode(c, n))
|
if not lib.isOverriden:
|
||||||
|
POptionEntry(c.optionStack.tail).dynlib = lib
|
||||||
else:
|
else:
|
||||||
if n.kind == nkExprColonExpr:
|
if n.kind == nkExprColonExpr:
|
||||||
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
## This file implements the new evaluation engine for Nim code.
|
## This file implements the new evaluation engine for Nim code.
|
||||||
## An instruction is 1-3 int32s in memory, it is a register based VM.
|
## 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
|
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
|
# XXX fix minor 'shallowCopy' overloading bug in compiler
|
||||||
|
|
||||||
proc createStrKeepNode(x: var TFullReg; keepNode=true) =
|
proc createStrKeepNode(x: var TFullReg; keepNode=true) =
|
||||||
if x.node.isNil:
|
if x.node.isNil or not keepNode:
|
||||||
x.node = newNode(nkStrLit)
|
x.node = newNode(nkStrLit)
|
||||||
elif x.node.kind == nkNilLit and keepNode:
|
elif x.node.kind == nkNilLit and keepNode:
|
||||||
when defined(useNodeIds):
|
when defined(useNodeIds):
|
||||||
|
|
@ -404,7 +406,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
let instr = c.code[pc]
|
let instr = c.code[pc]
|
||||||
let ra = instr.regA
|
let ra = instr.regA
|
||||||
#if c.traceActive:
|
#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")
|
# message(c.debug[pc], warnUser, "Trace")
|
||||||
|
|
||||||
case instr.opcode
|
case instr.opcode
|
||||||
|
|
@ -542,7 +545,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
if regs[rb].node.kind == nkRefTy:
|
if regs[rb].node.kind == nkRefTy:
|
||||||
regs[ra].node = regs[rb].node.sons[0]
|
regs[ra].node = regs[rb].node.sons[0]
|
||||||
else:
|
else:
|
||||||
stackTrace(c, tos, pc, errGenerated, "limited VM support for 'ref'")
|
stackTrace(c, tos, pc, errGenerated, "limited VM support for pointers")
|
||||||
else:
|
else:
|
||||||
stackTrace(c, tos, pc, errNilAccess)
|
stackTrace(c, tos, pc, errNilAccess)
|
||||||
of opcWrDeref:
|
of opcWrDeref:
|
||||||
|
|
|
||||||
|
|
@ -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
|
let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
|
||||||
(b.uint32 shl 16'u32) or
|
(b.uint32 shl 16'u32) or
|
||||||
(c.uint32 shl 24'u32)).TInstr
|
(c.uint32 shl 24'u32)).TInstr
|
||||||
|
when false:
|
||||||
|
if ctx.code.len == 43:
|
||||||
|
writeStackTrace()
|
||||||
|
echo "generating ", opc
|
||||||
ctx.code.add(ins)
|
ctx.code.add(ins)
|
||||||
ctx.debug.add(n.info)
|
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) =
|
proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
|
||||||
# Applies `opc` to `bx` and stores it into register `a`
|
# Applies `opc` to `bx` and stores it into register `a`
|
||||||
# `bx` must be signed and in the range [-32768, 32767]
|
# `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:
|
if bx >= -32768 and bx <= 32767:
|
||||||
let ins = (opc.uint32 or a.uint32 shl 8'u32 or
|
let ins = (opc.uint32 or a.uint32 shl 8'u32 or
|
||||||
(bx+wordExcess).uint32 shl 16'u32).TInstr
|
(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)
|
c.genNarrow(n, dest)
|
||||||
|
|
||||||
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
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)
|
let tmp = c.genx(arg)
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, opc, dest, tmp)
|
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):
|
if isAddr and (let m = canElimAddr(n); m != nil):
|
||||||
gen(c, m, dest, flags)
|
gen(c, m, dest, flags)
|
||||||
return
|
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:
|
# consider:
|
||||||
# proc foo(f: var ref int) =
|
# proc foo(f: var ref int) =
|
||||||
# f = new(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):
|
if gfAddrOf notin flags and fitsRegister(n.typ):
|
||||||
c.gABC(n, opcNodeToReg, dest, dest)
|
c.gABC(n, opcNodeToReg, dest, dest)
|
||||||
elif isAddr and isGlobal(n.sons[0]):
|
elif isAddr and isGlobal(n.sons[0]):
|
||||||
gen(c, n.sons[0], dest, flags+{gfAddrOf})
|
gen(c, n.sons[0], dest, flags+af)
|
||||||
else:
|
else:
|
||||||
let tmp = c.genx(n.sons[0], newflags)
|
let tmp = c.genx(n.sons[0], newflags)
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
|
|
@ -1447,12 +1463,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = newNodeIT(nkObjConstr, info, t)
|
result = newNodeIT(nkObjConstr, info, t)
|
||||||
result.add(newNodeIT(nkEmpty, info, t))
|
result.add(newNodeIT(nkEmpty, info, t))
|
||||||
getNullValueAux(t.n, result)
|
|
||||||
# initialize inherited fields:
|
# initialize inherited fields:
|
||||||
var base = t.sons[0]
|
var base = t.sons[0]
|
||||||
while base != nil:
|
while base != nil:
|
||||||
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
||||||
base = base.sons[0]
|
base = base.sons[0]
|
||||||
|
getNullValueAux(t.n, result)
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
result = newNodeIT(nkBracket, info, t)
|
result = newNodeIT(nkBracket, info, t)
|
||||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
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:
|
of declarativeDefs:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
of nkLambdaKinds:
|
of nkLambdaKinds:
|
||||||
let s = n.sons[namePos].sym
|
#let s = n.sons[namePos].sym
|
||||||
discard genProc(c, s)
|
#discard genProc(c, s)
|
||||||
genLit(c, n.sons[namePos], dest)
|
genLit(c, newSymNode(n.sons[namePos].sym), dest)
|
||||||
of nkChckRangeF, nkChckRange64, nkChckRange:
|
of nkChckRangeF, nkChckRange64, nkChckRange:
|
||||||
let
|
let
|
||||||
tmp0 = c.genx(n.sons[0])
|
tmp0 = c.genx(n.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -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
|
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
|
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
|
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
|
Custom data types
|
||||||
|
|
|
||||||
|
|
@ -77,38 +77,6 @@ Once bound, typedesc params can appear in the rest of the proc signature:
|
||||||
|
|
||||||
declareVariableWithType int, 42
|
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
|
Overload resolution can be further influenced by constraining the set of
|
||||||
types that will match the typedesc param:
|
types that will match the typedesc param:
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
## This module contains Nim's support for locks and condition vars.
|
## This module contains Nim's support for locks and condition vars.
|
||||||
|
|
||||||
|
const insideRLocksModule = false
|
||||||
include "system/syslocks"
|
include "system/syslocks"
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
## This module contains Nim's support for reentrant locks.
|
## This module contains Nim's support for reentrant locks.
|
||||||
|
|
||||||
|
const insideRLocksModule = true
|
||||||
include "system/syslocks"
|
include "system/syslocks"
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,15 @@ const
|
||||||
hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays
|
hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays
|
||||||
hasAioH = defined(linux)
|
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:
|
when false:
|
||||||
const
|
const
|
||||||
C_IRUSR = 0c000400 ## Read by owner.
|
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>".}
|
a4: var Tm): int {.importc, header: "<time.h>".}
|
||||||
proc strptime*(a1, a2: cstring, a3: var Tm): cstring {.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 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>".}
|
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 {.
|
proc timer_gettime*(a1: Timer, a2: var Itimerspec): cint {.
|
||||||
importc, header: "<time.h>".}
|
importc, header: "<time.h>".}
|
||||||
proc timer_getoverrun*(a1: Timer): cint {.importc, header: "<time.h>".}
|
proc timer_getoverrun*(a1: Timer): cint {.importc, header: "<time.h>".}
|
||||||
|
|
|
||||||
44
lib/pure/collections/chains.nim
Normal file
44
lib/pure/collections/chains.nim
Normal 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
|
||||||
|
|
@ -5,29 +5,31 @@ type
|
||||||
|
|
||||||
{.deprecated: [TMersenneTwister: MersenneTwister].}
|
{.deprecated: [TMersenneTwister: MersenneTwister].}
|
||||||
|
|
||||||
proc newMersenneTwister*(seed: int): MersenneTwister =
|
proc newMersenneTwister*(seed: uint32): MersenneTwister =
|
||||||
result.index = 0
|
result.index = 0
|
||||||
result.mt[0]= uint32(seed)
|
result.mt[0] = seed
|
||||||
for i in 1..623'u32:
|
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) =
|
proc generateNumbers(m: var MersenneTwister) =
|
||||||
for i in 0..623:
|
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)
|
m.mt[i] = m.mt[(i+397) mod 624] xor uint32(y shr 1'u32)
|
||||||
if (y mod 2'u32) != 0:
|
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:
|
if m.index == 0:
|
||||||
generateNumbers(m)
|
generateNumbers(m)
|
||||||
var y = m.mt[m.index]
|
result = m.mt[m.index]
|
||||||
y = y xor (y shr 11'u32)
|
m.index = (m.index + 1) mod m.mt.len
|
||||||
y = y xor ((7'u32 shl y) and 0x9d2c5680'u32)
|
|
||||||
y = y xor ((15'u32 shl y) and 0xefc60000'u32)
|
result = result xor (result shr 11'u32)
|
||||||
y = y xor (y shr 18'u32)
|
result = result xor ((7'u32 shl result) and 0x9d2c5680'u32)
|
||||||
m.index = (m.index+1) mod 624
|
result = result xor ((15'u32 shl result) and 0xefc60000'u32)
|
||||||
return int(y)
|
result = result xor (result shr 18'u32)
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
when not defined(testing) and isMainModule:
|
when not defined(testing) and isMainModule:
|
||||||
|
|
|
||||||
|
|
@ -222,9 +222,9 @@ when defined(ssl):
|
||||||
of protSSLv23:
|
of protSSLv23:
|
||||||
newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
|
newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
|
||||||
of protSSLv2:
|
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:
|
of protSSLv3:
|
||||||
newCTX = SSL_CTX_new(SSLv3_method())
|
raiseSslError("SSLv3 is no longer secure and has been deprecated, use protSSLv23")
|
||||||
of protTLSv1:
|
of protTLSv1:
|
||||||
newCTX = SSL_CTX_new(TLSv1_method())
|
newCTX = SSL_CTX_new(TLSv1_method())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,47 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
||||||
elif result != 0:
|
elif result != 0:
|
||||||
number = int(res)
|
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 {.
|
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
||||||
magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
|
magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
|
||||||
## parses a float starting at `start` and stores the value into `number`.
|
## parses a float starting at `start` and stores the value into `number`.
|
||||||
|
|
|
||||||
|
|
@ -560,6 +560,24 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar,
|
||||||
if L != s.len or L == 0:
|
if L != s.len or L == 0:
|
||||||
raise newException(ValueError, "invalid integer: " & s)
|
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,
|
proc parseFloat*(s: string): float {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuParseFloat".} =
|
rtl, extern: "nsuParseFloat".} =
|
||||||
## Parses a decimal floating point value contained in `s`. If `s` is not
|
## Parses a decimal floating point value contained in `s`. If `s` is not
|
||||||
|
|
|
||||||
|
|
@ -2877,6 +2877,7 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
when declared(initAllocator):
|
when declared(initAllocator):
|
||||||
initAllocator()
|
initAllocator()
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
|
const insideRLocksModule = false
|
||||||
include "system/syslocks"
|
include "system/syslocks"
|
||||||
when hostOS != "standalone": include "system/threads"
|
when hostOS != "standalone": include "system/threads"
|
||||||
elif not defined(nogc) and not defined(nimscript):
|
elif not defined(nogc) and not defined(nimscript):
|
||||||
|
|
|
||||||
|
|
@ -109,9 +109,30 @@ elif defined(windows) or defined(dos):
|
||||||
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
|
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
|
||||||
result = getProcAddress(cast[THINSTANCE](lib), name)
|
result = getProcAddress(cast[THINSTANCE](lib), name)
|
||||||
if result != nil: return
|
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):
|
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)
|
result = getProcAddress(cast[THINSTANCE](lib), decorated)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
procAddrError(name)
|
procAddrError(name)
|
||||||
|
|
|
||||||
|
|
@ -14,39 +14,41 @@
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
type
|
type
|
||||||
Handle = int
|
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
|
DebugInfo: pointer
|
||||||
LockCount: int32
|
LockCount: int32
|
||||||
RecursionCount: int32
|
RecursionCount: int32
|
||||||
OwningThread: int
|
OwningThread: int
|
||||||
LockSemaphore: int
|
LockSemaphore: int
|
||||||
Reserved: int32
|
SpinCount: int
|
||||||
|
|
||||||
SysCond = Handle
|
SysCond = Handle
|
||||||
|
|
||||||
{.deprecated: [THandle: Handle, TSysLock: SysLock, TSysCond: SysCond].}
|
{.deprecated: [THandle: Handle, TSysLock: SysLock, TSysCond: SysCond].}
|
||||||
|
|
||||||
proc initSysLock(L: var SysLock) {.stdcall, noSideEffect,
|
proc initSysLock(L: var SysLock) {.importc: "InitializeCriticalSection",
|
||||||
dynlib: "kernel32", importc: "InitializeCriticalSection".}
|
header: "<windows.h>".}
|
||||||
## Initializes the lock `L`.
|
## Initializes the lock `L`.
|
||||||
|
|
||||||
proc tryAcquireSysAux(L: var SysLock): int32 {.stdcall, noSideEffect,
|
proc tryAcquireSysAux(L: var SysLock): int32 {.importc: "TryEnterCriticalSection",
|
||||||
dynlib: "kernel32", importc: "TryEnterCriticalSection".}
|
header: "<windows.h>".}
|
||||||
## Tries to acquire the lock `L`.
|
## Tries to acquire the lock `L`.
|
||||||
|
|
||||||
proc tryAcquireSys(L: var SysLock): bool {.inline.} =
|
proc tryAcquireSys(L: var SysLock): bool {.inline.} =
|
||||||
result = tryAcquireSysAux(L) != 0'i32
|
result = tryAcquireSysAux(L) != 0'i32
|
||||||
|
|
||||||
proc acquireSys(L: var SysLock) {.stdcall, noSideEffect,
|
proc acquireSys(L: var SysLock) {.importc: "EnterCriticalSection",
|
||||||
dynlib: "kernel32", importc: "EnterCriticalSection".}
|
header: "<windows.h>".}
|
||||||
## Acquires the lock `L`.
|
## Acquires the lock `L`.
|
||||||
|
|
||||||
proc releaseSys(L: var SysLock) {.stdcall, noSideEffect,
|
proc releaseSys(L: var SysLock) {.importc: "LeaveCriticalSection",
|
||||||
dynlib: "kernel32", importc: "LeaveCriticalSection".}
|
header: "<windows.h>".}
|
||||||
## Releases the lock `L`.
|
## Releases the lock `L`.
|
||||||
|
|
||||||
proc deinitSys(L: var SysLock) {.stdcall, noSideEffect,
|
proc deinitSys(L: var SysLock) {.importc: "DeleteCriticalSection",
|
||||||
dynlib: "kernel32", importc: "DeleteCriticalSection".}
|
header: "<windows.h>".}
|
||||||
|
|
||||||
proc createEvent(lpEventAttributes: pointer,
|
proc createEvent(lpEventAttributes: pointer,
|
||||||
bManualReset, bInitialState: int32,
|
bManualReset, bInitialState: int32,
|
||||||
|
|
@ -86,15 +88,14 @@ else:
|
||||||
#include <pthread.h>""".} = object
|
#include <pthread.h>""".} = object
|
||||||
SysLockType = distinct cint
|
SysLockType = distinct cint
|
||||||
|
|
||||||
proc SysLockType_Reentrant: SysLockType =
|
|
||||||
{.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
|
|
||||||
|
|
||||||
proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) {.
|
proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) {.
|
||||||
importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
|
importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
|
||||||
|
|
||||||
|
when insideRLocksModule:
|
||||||
|
proc SysLockType_Reentrant: SysLockType =
|
||||||
|
{.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
|
||||||
proc initSysLockAttr(a: var SysLockAttr) {.
|
proc initSysLockAttr(a: var SysLockAttr) {.
|
||||||
importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
|
importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
|
||||||
|
|
||||||
proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
|
proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
|
||||||
importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
|
importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
|
||||||
|
|
||||||
|
|
@ -111,14 +112,12 @@ else:
|
||||||
proc deinitSys(L: var SysLock) {.noSideEffect,
|
proc deinitSys(L: var SysLock) {.noSideEffect,
|
||||||
importc: "pthread_mutex_destroy", header: "<pthread.h>".}
|
importc: "pthread_mutex_destroy", header: "<pthread.h>".}
|
||||||
|
|
||||||
|
when not insideRLocksModule:
|
||||||
proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
|
proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
|
||||||
importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
|
importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
|
||||||
proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
|
proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
|
||||||
importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
|
importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
|
||||||
proc signalSysCond(cond: var SysCond) {.
|
proc signalSysCond(cond: var SysCond) {.
|
||||||
importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
|
importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
|
||||||
|
|
||||||
proc deinitSysCond(cond: var SysCond) {.noSideEffect,
|
proc deinitSysCond(cond: var SysCond) {.noSideEffect,
|
||||||
importc: "pthread_cond_destroy", header: "<pthread.h>".}
|
importc: "pthread_cond_destroy", header: "<pthread.h>".}
|
||||||
|
|
||||||
{.pop.}
|
|
||||||
|
|
|
||||||
24
tests/closure/tflatmap.nim
Normal file
24
tests/closure/tflatmap.nim
Normal 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)
|
||||||
48
tests/macros/typesafeprintf.nim
Normal file
48
tests/macros/typesafeprintf.nim
Normal 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)
|
||||||
11
tests/stdlib/tparseuints.nim
Normal file
11
tests/stdlib/tparseuints.nim
Normal 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
52
tests/vm/tanonproc.nim
Normal 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
29
tests/vm/tinheritance.nim
Normal 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
31
tests/vm/tmitems.nim
Normal 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()
|
||||||
28
tests/vm/twrong_concat.nim
Normal file
28
tests/vm/twrong_concat.nim
Normal 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"
|
||||||
|
|
@ -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.
|
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
|
- Typeless parameters have been removed from the language since it would
|
||||||
clash with ``using``.
|
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
|
Library Additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue