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

This commit is contained in:
Andreas Rumpf 2016-01-26 12:46:38 +01:00
commit 1fbeedaba2
18 changed files with 325 additions and 222 deletions

View file

@ -50,10 +50,10 @@ proc importcSymbol*(sym: PSym): PNode =
# that contains the address instead: # that contains the address instead:
result = newNodeIT(nkPtrLit, sym.info, sym.typ) result = newNodeIT(nkPtrLit, sym.info, sym.typ)
case name case name
of "stdin": result.intVal = cast[TAddress](system.stdin) of "stdin": result.intVal = cast[ByteAddress](system.stdin)
of "stdout": result.intVal = cast[TAddress](system.stdout) of "stdout": result.intVal = cast[ByteAddress](system.stdout)
of "stderr": result.intVal = cast[TAddress](system.stderr) of "stderr": result.intVal = cast[ByteAddress](system.stderr)
of "vmErrnoWrapper": result.intVal = cast[TAddress](myerrno) of "vmErrnoWrapper": result.intVal = cast[ByteAddress](myerrno)
else: else:
let lib = sym.annex let lib = sym.annex
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}: if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
@ -71,7 +71,7 @@ proc importcSymbol*(sym: PSym): PNode =
else: lib.path.strVal, sym.info) else: lib.path.strVal, sym.info)
theAddr = dllhandle.symAddr(name) theAddr = dllhandle.symAddr(name)
if theAddr.isNil: globalError(sym.info, "cannot import: " & sym.name.s) if theAddr.isNil: globalError(sym.info, "cannot import: " & sym.name.s)
result.intVal = cast[TAddress](theAddr) result.intVal = cast[ByteAddress](theAddr)
proc mapType(t: ast.PType): ptr libffi.TType = proc mapType(t: ast.PType): ptr libffi.TType =
if t == nil: return addr libffi.type_void if t == nil: return addr libffi.type_void
@ -107,7 +107,7 @@ proc mapCallConv(cc: TCallingConvention, info: TLineInfo): TABI =
template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[] template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[]
template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
template `+!`(x, y: expr): expr {.immediate.} = template `+!`(x, y: expr): expr {.immediate.} =
cast[pointer](cast[TAddress](x) + y) cast[pointer](cast[ByteAddress](x) + y)
proc packSize(v: PNode, typ: PType): int = proc packSize(v: PNode, typ: PType): int =
## computes the size of the blob ## computes the size of the blob
@ -363,13 +363,13 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
# in their unboxed representation so nothing it to be unpacked: # in their unboxed representation so nothing it to be unpacked:
result = n result = n
else: else:
awi(nkPtrLit, cast[TAddress](p)) awi(nkPtrLit, cast[ByteAddress](p))
of tyPtr, tyRef, tyVar: of tyPtr, tyRef, tyVar:
let p = rd(pointer, x) let p = rd(pointer, x)
if p.isNil: if p.isNil:
setNil() setNil()
elif n == nil or n.kind == nkPtrLit: elif n == nil or n.kind == nkPtrLit:
awi(nkPtrLit, cast[TAddress](p)) awi(nkPtrLit, cast[ByteAddress](p))
elif n != nil and n.len == 1: elif n != nil and n.len == 1:
internalAssert n.kind == nkRefTy internalAssert n.kind == nkRefTy
n.sons[0] = unpack(p, typ.lastSon, n.sons[0]) n.sons[0] = unpack(p, typ.lastSon, n.sons[0])

View file

@ -163,8 +163,31 @@ proc mangleName(s: PSym): Rope =
add(result, rope(s.id)) add(result, rope(s.id))
s.loc.r = result s.loc.r = result
proc makeJSString(s: string): Rope = proc escapeJSString(s: string): string =
(if s.isNil: "null".rope else: strutils.escape(s).rope) result = newStringOfCap(s.len + s.len shr 2)
result.add("\"")
for c in items(s):
case c
of '\l': result.add("\\n")
of '\r': result.add("\\r")
of '\t': result.add("\\t")
of '\b': result.add("\\b")
of '\a': result.add("\\a")
of '\e': result.add("\\e")
of '\v': result.add("\\v")
of '\\': result.add("\\\\")
of '\'': result.add("\\'")
of '\"': result.add("\\\"")
else: add(result, c)
result.add("\"")
proc makeJSString(s: string, escapeNonAscii = true): Rope =
if s.isNil:
result = "null".rope
elif escapeNonAscii:
result = strutils.escape(s).rope
else:
result = escapeJSString(s).rope
include jstypes include jstypes
@ -264,7 +287,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
["", "", "($1 - $2)", "($1 - $2)"], # SubF64 ["", "", "($1 - $2)", "($1 - $2)"], # SubF64
["", "", "($1 * $2)", "($1 * $2)"], # MulF64 ["", "", "($1 * $2)", "($1 * $2)"], # MulF64
["", "", "($1 / $2)", "($1 / $2)"], # DivF64 ["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI ["", "", "", ""], # ShrI
["", "", "($1 << $2)", "($1 << $2)"], # ShlI ["", "", "($1 << $2)", "($1 << $2)"], # ShlI
["", "", "($1 & $2)", "($1 & $2)"], # BitandI ["", "", "($1 & $2)", "($1 & $2)"], # BitandI
["", "", "($1 | $2)", "($1 | $2)"], # BitorI ["", "", "($1 | $2)", "($1 | $2)"], # BitorI
@ -273,21 +296,21 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64 ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64 ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU ["", "", "", ""], # addU
["subU", "subU", "subU($1, $2)", "subU($1, $2)"], # subU ["", "", "", ""], # subU
["mulU", "mulU", "mulU($1, $2)", "mulU($1, $2)"], # mulU ["", "", "", ""], # mulU
["divU", "divU", "divU($1, $2)", "divU($1, $2)"], # divU ["", "", "", ""], # divU
["modU", "modU", "modU($1, $2)", "modU($1, $2)"], # modU ["", "", "($1 % $2)", "($1 % $2)"], # modU
["", "", "($1 == $2)", "($1 == $2)"], # EqI ["", "", "($1 == $2)", "($1 == $2)"], # EqI
["", "", "($1 <= $2)", "($1 <= $2)"], # LeI ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
["", "", "($1 < $2)", "($1 < $2)"], # LtI ["", "", "($1 < $2)", "($1 < $2)"], # LtI
["", "", "($1 == $2)", "($1 == $2)"], # EqF64 ["", "", "($1 == $2)", "($1 == $2)"], # EqF64
["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64 ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
["", "", "($1 < $2)", "($1 < $2)"], # LtF64 ["", "", "($1 < $2)", "($1 < $2)"], # LtF64
["leU", "leU", "leU($1, $2)", "leU($1, $2)"], # leU ["", "", "($1 <= $2)", "($1 <= $2)"], # leU
["ltU", "ltU", "ltU($1, $2)", "ltU($1, $2)"], # ltU ["", "", "($1 < $2)", "($1 < $2)"], # ltU
["leU64", "leU64", "leU64($1, $2)", "leU64($1, $2)"], # leU64 ["", "", "($1 <= $2)", "($1 <= $2)"], # leU64
["ltU64", "ltU64", "ltU64($1, $2)", "ltU64($1, $2)"], # ltU64 ["", "", "($1 < $2)", "($1 < $2)"], # ltU64
["", "", "($1 == $2)", "($1 == $2)"], # EqEnum ["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum ["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
["", "", "($1 < $2)", "($1 < $2)"], # LtEnum ["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
@ -336,90 +359,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"], ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
["", "", "$1", "$1"]] ["", "", "$1", "$1"]]
luaOps: TMagicOps = [
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI
["modInt", "", "modInt($1, $2)", "Math.floor($1 % $2)"], # ModI
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # Succ
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # Pred
["", "", "($1 + $2)", "($1 + $2)"], # AddF64
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
["", "", "($1 | $2)", "($1 | $2)"], # BitorI
["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU
["subU", "subU", "subU($1, $2)", "subU($1, $2)"], # subU
["mulU", "mulU", "mulU($1, $2)", "mulU($1, $2)"], # mulU
["divU", "divU", "divU($1, $2)", "divU($1, $2)"], # divU
["modU", "modU", "modU($1, $2)", "modU($1, $2)"], # modU
["", "", "($1 == $2)", "($1 == $2)"], # EqI
["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
["", "", "($1 < $2)", "($1 < $2)"], # LtI
["", "", "($1 == $2)", "($1 == $2)"], # EqF64
["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
["", "", "($1 < $2)", "($1 < $2)"], # LtF64
["leU", "leU", "leU($1, $2)", "leU($1, $2)"], # leU
["ltU", "ltU", "ltU($1, $2)", "ltU($1, $2)"], # ltU
["leU64", "leU64", "leU64($1, $2)", "leU64($1, $2)"], # leU64
["ltU64", "ltU64", "ltU64($1, $2)", "ltU64($1, $2)"], # ltU64
["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
["", "", "($1 == $2)", "($1 == $2)"], # EqCh
["", "", "($1 <= $2)", "($1 <= $2)"], # LeCh
["", "", "($1 < $2)", "($1 < $2)"], # LtCh
["", "", "($1 == $2)", "($1 == $2)"], # EqB
["", "", "($1 <= $2)", "($1 <= $2)"], # LeB
["", "", "($1 < $2)", "($1 < $2)"], # LtB
["", "", "($1 == $2)", "($1 == $2)"], # EqRef
["", "", "($1 == $2)", "($1 == $2)"], # EqUntracedRef
["", "", "($1 <= $2)", "($1 <= $2)"], # LePtr
["", "", "($1 < $2)", "($1 < $2)"], # LtPtr
["", "", "($1 == $2)", "($1 == $2)"], # EqCString
["", "", "($1 != $2)", "($1 != $2)"], # Xor
["", "", "($1 == $2)", "($1 == $2)"], # EqProc
["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI
["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64
["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI
["", "", "not ($1)", "not ($1)"], # Not
["", "", "+($1)", "+($1)"], # UnaryPlusI
["", "", "~($1)", "~($1)"], # BitnotI
["", "", "+($1)", "+($1)"], # UnaryPlusF64
["", "", "-($1)", "-($1)"], # UnaryMinusF64
["", "", "Math.abs($1)", "Math.abs($1)"], # AbsF64
["Ze8ToI", "Ze8ToI", "Ze8ToI($1)", "Ze8ToI($1)"], # mZe8ToI
["Ze8ToI64", "Ze8ToI64", "Ze8ToI64($1)", "Ze8ToI64($1)"], # mZe8ToI64
["Ze16ToI", "Ze16ToI", "Ze16ToI($1)", "Ze16ToI($1)"], # mZe16ToI
["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64
["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64
["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64
["toU8", "toU8", "toU8($1)", "toU8($1)"], # toU8
["toU16", "toU16", "toU16($1)", "toU16($1)"], # toU16
["toU32", "toU32", "toU32($1)", "toU32($1)"], # toU32
["", "", "$1", "$1"], # ToFloat
["", "", "$1", "$1"], # ToBiggestFloat
["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt
["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt
["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"],
["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"], [
"cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")",
"cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr",
"cstrToNimstr(($1)+\"\")",
"cstrToNimstr(($1)+\"\")"], ["cstrToNimstr",
"cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
["", "", "$1", "$1"]]
proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) = proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
var x, y: TCompRes var x, y: TCompRes
useMagic(p, magic) useMagic(p, magic)
@ -428,6 +367,23 @@ proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
r.res = frmt % [x.rdLoc, y.rdLoc] r.res = frmt % [x.rdLoc, y.rdLoc]
r.kind = resExpr r.kind = resExpr
proc unsignedTrimmer(size: BiggestInt): Rope =
case size
of 1: rope"& 0xff"
of 2: rope"& 0xffff"
of 4: rope">>> 0"
else: rope""
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string, reassign: bool = false) =
var x, y: TCompRes
gen(p, n.sons[1], x)
gen(p, n.sons[2], y)
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
if reassign:
r.res = "$1 = (($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
else:
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) = proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
var x, y, z: TCompRes var x, y, z: TCompRes
useMagic(p, magic) useMagic(p, magic)
@ -455,10 +411,22 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic, ops: TMagicOps) =
else: else:
gen(p, n.sons[1], r) gen(p, n.sons[1], r)
r.res = ops[op][i + 2] % [r.rdLoc] r.res = ops[op][i + 2] % [r.rdLoc]
r.kind = resExpr
proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
arithAux(p, n, r, op, jsOps | luaOps) case op
of mAddU: binaryUintExpr(p, n, r, "+")
of mSubU: binaryUintExpr(p, n, r, "-")
of mMulU: binaryUintExpr(p, n, r, "*")
of mDivU: binaryUintExpr(p, n, r, "/")
of mShrI:
var x, y: TCompRes
gen(p, n.sons[1], x)
gen(p, n.sons[2], y)
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
r.res = "(($1 $2) >>> $3)" % [x.rdLoc, trimmer, y.rdLoc]
else:
arithAux(p, n, r, op, jsOps)
r.kind = resExpr
proc genLineDir(p: PProc, n: PNode) = proc genLineDir(p: PProc, n: PNode) =
let line = toLinenumber(n.info) let line = toLinenumber(n.info)
@ -632,7 +600,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
if stringSwitch: if stringSwitch:
case e.kind case e.kind
of nkStrLit..nkTripleStrLit: addf(p.body, "case $1: ", of nkStrLit..nkTripleStrLit: addf(p.body, "case $1: ",
[makeJSString(e.strVal)]) [makeJSString(e.strVal, false)])
else: internalError(e.info, "jsgen.genCaseStmt: 2") else: internalError(e.info, "jsgen.genCaseStmt: 2")
else: else:
gen(p, e, cond) gen(p, e, cond)
@ -1388,7 +1356,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)") of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)")
of mLeStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)") of mLeStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)")
of mLtStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) < 0)") of mLtStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) < 0)")
of mIsNil: unaryExpr(p, n, r, "", "$1 == null") of mIsNil: unaryExpr(p, n, r, "", "($1 === null)")
of mEnumToStr: genRepr(p, n, r) of mEnumToStr: genRepr(p, n, r)
of mNew, mNewFinalize: genNew(p, n) of mNew, mNewFinalize: genNew(p, n)
of mSizeOf: r.res = rope(getSize(n.sons[1].typ)) of mSizeOf: r.res = rope(getSize(n.sons[1].typ))
@ -1406,11 +1374,17 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
else: else:
unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)") unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)")
of mInc: of mInc:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2") if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)") binaryUintExpr(p, n, r, "+", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)")
of ast.mDec: of ast.mDec:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2") if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)") binaryUintExpr(p, n, r, "-", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0") of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0")
of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2") of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2")
of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)") of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)")
@ -1627,6 +1601,37 @@ proc genPragma(p: PProc, n: PNode) =
of wEmit: genAsmOrEmitStmt(p, it.sons[1]) of wEmit: genAsmOrEmitStmt(p, it.sons[1])
else: discard else: discard
proc genCast(p: PProc, n: PNode, r: var TCompRes) =
var dest = skipTypes(n.typ, abstractVarRange)
var src = skipTypes(n.sons[1].typ, abstractVarRange)
gen(p, n.sons[1], r)
if dest.kind == src.kind:
# no-op conversion
return
let toInt = (dest.kind in tyInt .. tyInt32)
let toUint = (dest.kind in tyUInt .. tyUInt32)
let fromInt = (src.kind in tyInt .. tyInt32)
let fromUint = (src.kind in tyUInt .. tyUInt32)
if toUint and (fromInt or fromUint):
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
elif toInt:
if fromInt:
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
elif fromUint:
if src.size == 4 and dest.size == 4:
r.res = "($1|0)" % [r.res]
else:
let trimmer = unsignedTrimmer(dest.size)
let minuend = case dest.size
of 1: "0xfe"
of 2: "0xfffe"
of 4: "0xfffffffe"
else: ""
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
proc gen(p: PProc, n: PNode, r: var TCompRes) = proc gen(p: PProc, n: PNode, r: var TCompRes) =
r.typ = etyNone r.typ = etyNone
r.kind = resNone r.kind = resNone
@ -1635,7 +1640,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
case n.kind case n.kind
of nkSym: of nkSym:
genSym(p, n, r) genSym(p, n, r)
of nkCharLit..nkInt64Lit: of nkCharLit..nkUInt32Lit:
if n.typ.kind == tyBool: if n.typ.kind == tyBool:
r.res = if n.intVal == 0: rope"false" else: rope"true" r.res = if n.intVal == 0: rope"false" else: rope"true"
else: else:
@ -1654,10 +1659,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
r.kind = resExpr r.kind = resExpr
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if skipTypes(n.typ, abstractVarRange).kind == tyString: if skipTypes(n.typ, abstractVarRange).kind == tyString:
useMagic(p, "cstrToNimstr") useMagic(p, "makeNimstrLit")
r.res = "cstrToNimstr($1)" % [makeJSString(n.strVal)] r.res = "makeNimstrLit($1)" % [makeJSString(n.strVal)]
else: else:
r.res = makeJSString(n.strVal) r.res = makeJSString(n.strVal, false)
r.kind = resExpr r.kind = resExpr
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
let f = n.floatVal let f = n.floatVal
@ -1688,7 +1693,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkCheckedFieldExpr: genCheckedFieldAccess(p, n, r) of nkCheckedFieldExpr: genCheckedFieldAccess(p, n, r)
of nkObjDownConv: gen(p, n.sons[0], r) of nkObjDownConv: gen(p, n.sons[0], r)
of nkObjUpConv: upConv(p, n, r) of nkObjUpConv: upConv(p, n, r)
of nkCast: gen(p, n.sons[1], r) of nkCast: genCast(p, n, r)
of nkChckRangeF: genRangeChck(p, n, r, "chckRangeF") of nkChckRangeF: genRangeChck(p, n, r, "chckRangeF")
of nkChckRange64: genRangeChck(p, n, r, "chckRange64") of nkChckRange64: genRangeChck(p, n, r, "chckRange64")
of nkChckRange: genRangeChck(p, n, r, "chckRange") of nkChckRange: genRangeChck(p, n, r, "chckRange")

View file

@ -1000,7 +1000,9 @@ JavaScript-compatible code you should remember the following:
- ``addr`` and ``ptr`` have slightly different semantic meaning in JavaScript. - ``addr`` and ``ptr`` have slightly different semantic meaning in JavaScript.
It is recommended to avoid those if you're not sure how they are translated It is recommended to avoid those if you're not sure how they are translated
to JavaScript. to JavaScript.
- ``cast[T](x)`` in JavaScript is translated to ``(x)``. - ``cast[T](x)`` in JavaScript is translated to ``(x)``, except for casting
between signed/unsigned ints, in which case it behaves as static cast in
C language.
- ``cstring`` in JavaScript means JavaScript string. It is a good practice to - ``cstring`` in JavaScript means JavaScript string. It is a good practice to
use ``cstring`` only when it is semantically appropriate. E.g. don't use use ``cstring`` only when it is semantically appropriate. E.g. don't use
``cstring`` as a binary data buffer. ``cstring`` as a binary data buffer.

View file

@ -12,7 +12,7 @@
## report at program exit. ## report at program exit.
when not defined(profiler) and not defined(memProfiler): when not defined(profiler) and not defined(memProfiler):
{.warning: "Profiling support is turned off!".} {.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".}
# We don't want to profile the profiling code ... # We don't want to profile the profiling code ...
{.push profiler: off.} {.push profiler: off.}

View file

@ -886,7 +886,7 @@ elif not defined(useNimRtl):
discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error)) discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
exitnow(1) exitnow(1)
when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(android): when not defined(uClibc) and (not defined(linux) or defined(android)):
var environ {.importc.}: cstringArray var environ {.importc.}: cstringArray
proc startProcessAfterFork(data: ptr StartProcessData) = proc startProcessAfterFork(data: ptr StartProcessData) =
@ -916,17 +916,16 @@ elif not defined(useNimRtl):
discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC) discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC)
if data.optionPoUsePath: if data.optionPoUsePath:
when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(android): when defined(uClibc):
# uClibc environment (OpenWrt included) doesn't have the full execvpe
discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
elif defined(linux) and not defined(android):
discard execvpe(data.sysCommand, data.sysArgs, data.sysEnv)
else:
# MacOSX doesn't have execvpe, so we need workaround. # MacOSX doesn't have execvpe, so we need workaround.
# On MacOSX we can arrive here only from fork, so this is safe: # On MacOSX we can arrive here only from fork, so this is safe:
environ = data.sysEnv environ = data.sysEnv
discard execvp(data.sysCommand, data.sysArgs) discard execvp(data.sysCommand, data.sysArgs)
else:
when defined(uClibc):
# uClibc environment (OpenWrt included) doesn't have the full execvpe
discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
else:
discard execvpe(data.sysCommand, data.sysArgs, data.sysEnv)
else: else:
discard execve(data.sysCommand, data.sysArgs, data.sysEnv) discard execve(data.sysCommand, data.sysArgs, data.sysEnv)

View file

@ -148,7 +148,10 @@ proc write*[T](s: Stream, x: T) =
proc write*(s: Stream, x: string) = proc write*(s: Stream, x: string) =
## writes the string `x` to the the stream `s`. No length field or ## writes the string `x` to the the stream `s`. No length field or
## terminating zero is written. ## terminating zero is written.
writeData(s, cstring(x), x.len) when nimvm:
writeData(s, cstring(x), x.len)
else:
if x.len > 0: writeData(s, unsafeAddr x[0], x.len)
proc writeLn*(s: Stream, args: varargs[string, `$`]) {.deprecated.} = proc writeLn*(s: Stream, args: varargs[string, `$`]) {.deprecated.} =
## **Deprecated since version 0.11.4:** Use **writeLine** instead. ## **Deprecated since version 0.11.4:** Use **writeLine** instead.

View file

@ -688,7 +688,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %% sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
s == 0, "rawDealloc 3") s == 0, "rawDealloc 3")
var f = cast[ptr FreeCell](p) var f = cast[ptr FreeCell](p)
#echo("setting to nil: ", $cast[TAddress](addr(f.zeroField))) #echo("setting to nil: ", $cast[ByteAddress](addr(f.zeroField)))
sysAssert(f.zeroField != 0, "rawDealloc 1") sysAssert(f.zeroField != 0, "rawDealloc 1")
f.zeroField = 0 f.zeroField = 0
f.next = c.freeList f.next = c.freeList

View file

@ -659,7 +659,7 @@ when useMarkForDebug or useBackupGc:
proc stackMarkS(gch: var GcHeap, p: pointer) {.inline.} = proc stackMarkS(gch: var GcHeap, p: pointer) {.inline.} =
# the addresses are not as cells on the stack, so turn them to cells: # the addresses are not as cells on the stack, so turn them to cells:
var cell = usrToCell(p) var cell = usrToCell(p)
var c = cast[TAddress](cell) var c = cast[ByteAddress](cell)
if c >% PageSize: if c >% PageSize:
# fast check: does it look like a cell? # fast check: does it look like a cell?
var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell)) var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
@ -805,8 +805,8 @@ proc markThreadStacks(gch: var GcHeap) =
while it != nil: while it != nil:
# mark registers: # mark registers:
for i in 0 .. high(it.registers): gcMark(gch, it.registers[i]) for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
var sp = cast[TAddress](it.stackBottom) var sp = cast[ByteAddress](it.stackBottom)
var max = cast[TAddress](it.stackTop) var max = cast[ByteAddress](it.stackTop)
# XXX stack direction? # XXX stack direction?
# XXX unroll this loop: # XXX unroll this loop:
while sp <=% max: while sp <=% max:

View file

@ -131,9 +131,9 @@ when defined(sparc): # For SPARC architecture.
proc isOnStack(p: pointer): bool = proc isOnStack(p: pointer): bool =
var stackTop {.volatile.}: pointer var stackTop {.volatile.}: pointer
stackTop = addr(stackTop) stackTop = addr(stackTop)
var b = cast[TAddress](gch.stackBottom) var b = cast[ByteAddress](gch.stackBottom)
var a = cast[TAddress](stackTop) var a = cast[ByteAddress](stackTop)
var x = cast[TAddress](p) var x = cast[ByteAddress](p)
result = a <=% x and x <=% b result = a <=% x and x <=% b
template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} = template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
@ -150,7 +150,7 @@ when defined(sparc): # For SPARC architecture.
# Addresses decrease as the stack grows. # Addresses decrease as the stack grows.
while sp <= max: while sp <= max:
gcMark(gch, sp[]) gcMark(gch, sp[])
sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer)) sp = cast[PPointer](cast[ByteAddress](sp) +% sizeof(pointer))
elif defined(ELATE): elif defined(ELATE):
{.error: "stack marking code is to be written for this architecture".} {.error: "stack marking code is to be written for this architecture".}

View file

@ -165,15 +165,46 @@ proc SetConstr() {.varargs, asmNoStackFrame, compilerproc.} =
return result; return result;
""" """
proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} =
{.emit: """
var ln = `c`.length;
var result = new Array(ln + 1);
var i = 0;
for (; i < ln; ++i) {
result[i] = `c`.charCodeAt(i);
}
result[i] = 0; // terminating zero
return result;
""".}
proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} = proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} =
asm """ {.emit: """
var result = []; var ln = `c`.length;
for (var i = 0; i < `c`.length; ++i) { var result = new Array(ln);
result[i] = `c`.charCodeAt(i); var r = 0;
for (var i = 0; i < ln; ++i) {
var ch = `c`.charCodeAt(i);
if (ch < 128) {
result[r] = ch;
} }
result[result.length] = 0; // terminating zero else if((ch > 127) && (ch < 2048)) {
return result; result[r] = (ch >> 6) | 192;
""" ++r;
result[r] = (ch & 63) | 128;
}
else {
result[r] = (ch >> 12) | 224;
++r;
result[r] = ((ch >> 6) & 63) | 128;
++r;
result[r] = (ch & 63) | 128;
}
++r;
}
result[r] = 0; // terminating zero
return result;
""".}
proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} = proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
asm """ asm """
@ -417,42 +448,6 @@ proc absInt(a: int): int {.compilerproc.} =
proc absInt64(a: int64): int64 {.compilerproc.} = proc absInt64(a: int64): int64 {.compilerproc.} =
result = if a < 0: a*(-1) else: a result = if a < 0: a*(-1) else: a
proc leU(a, b: int): bool {.compilerproc.} =
result = abs(a) <= abs(b)
proc ltU(a, b: int): bool {.compilerproc.} =
result = abs(a) < abs(b)
proc leU64(a, b: int64): bool {.compilerproc.} =
result = abs(a) <= abs(b)
proc ltU64(a, b: int64): bool {.compilerproc.} =
result = abs(a) < abs(b)
proc addU(a, b: int): int {.compilerproc.} =
result = abs(a) + abs(b)
proc addU64(a, b: int64): int64 {.compilerproc.} =
result = abs(a) + abs(b)
proc subU(a, b: int): int {.compilerproc.} =
result = abs(a) - abs(b)
proc subU64(a, b: int64): int64 {.compilerproc.} =
result = abs(a) - abs(b)
proc mulU(a, b: int): int {.compilerproc.} =
result = abs(a) * abs(b)
proc mulU64(a, b: int64): int64 {.compilerproc.} =
result = abs(a) * abs(b)
proc divU(a, b: int): int {.compilerproc.} =
result = abs(a) div abs(b)
proc divU64(a, b: int64): int64 {.compilerproc.} =
result = abs(a) div abs(b)
proc modU(a, b: int): int {.compilerproc.} =
result = abs(a) mod abs(b)
proc modU64(a, b: int64): int64 {.compilerproc.} =
result = abs(a) mod abs(b)
proc ze*(a: int): int {.compilerproc.} = proc ze*(a: int): int {.compilerproc.} =
result = a result = a

View file

@ -496,13 +496,12 @@ type
data: array[MD5_LBLOCK, MD5_LONG] data: array[MD5_LBLOCK, MD5_LONG]
num: cuint num: cuint
{.pragma: ic, importc: "$1".}
{.push callconv:cdecl, dynlib:DLLUtilName.} {.push callconv:cdecl, dynlib:DLLUtilName.}
proc md5_Init*(c: var MD5_CTX): cint{.ic.} proc md5_Init*(c: var MD5_CTX): cint{.importc: "MD5_Init".}
proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.ic.} proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.importc: "MD5_Update".}
proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.ic.} proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.importc: "MD5_Final".}
proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.ic.} proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.importc: "MD5".}
proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.ic.} proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.importc: "MD5_Transform".}
{.pop.} {.pop.}
from strutils import toHex,toLower from strutils import toHex,toLower

View file

@ -39,9 +39,9 @@ To build from source you will need:
If you are on a fairly modern *nix system, the following steps should work: If you are on a fairly modern *nix system, the following steps should work:
``` ```
$ git clone git://github.com/nim-lang/Nim.git $ git clone https://github.com/nim-lang/Nim.git
$ cd Nim $ cd Nim
$ git clone --depth 1 git://github.com/nim-lang/csources $ git clone --depth 1 https://github.com/nim-lang/csources
$ cd csources && sh build.sh $ cd csources && sh build.sh
$ cd .. $ cd ..
$ bin/nim c koch $ bin/nim c koch

View file

@ -3,22 +3,76 @@ discard """
Hello''' Hello'''
""" """
# bug #2581 block: # bug #2581
const someVars = [ "Hello" ]
var someVars2 = [ "Hello" ]
const someVars = [ "Hello" ] proc getSomeVar: string =
var someVars2 = [ "Hello" ] for i in someVars:
if i == "Hello":
result = i
break
proc getSomeVar: string = proc getSomeVar2: string =
for i in someVars: for i in someVars2:
if i == "Hello": if i == "Hello":
result = i result = i
break break
proc getSomeVar2: string = echo getSomeVar()
for i in someVars2: echo getSomeVar2()
if i == "Hello":
result = i
break
echo getSomeVar() block: # Test compile-time binary data generation, invalid unicode
echo getSomeVar2() proc signatureMaker(): string {. compiletime .} =
const signatureBytes = [137, 80, 78, 71, 13, 10, 26, 10]
result = ""
for c in signatureBytes: result.add chr(c)
const cSig = signatureMaker()
var rSig = newString(8)
rSig[0] = chr(137)
rSig[1] = chr(80)
rSig[2] = chr(78)
rSig[3] = chr(71)
rSig[4] = chr(13)
rSig[5] = chr(10)
rSig[6] = chr(26)
rSig[7] = chr(10)
doAssert(rSig == cSig)
block: # Test unicode strings
const constStr = "Привет!"
var jsStr : cstring
{.emit: """`jsStr`[0] = "Привет!";""".}
doAssert($jsStr == constStr)
var runtimeStr = "При"
runtimeStr &= "вет!"
doAssert(runtimeStr == constStr)
block: # Conversions from/to cstring
proc stringSaysHelloInRussian(s: cstring): bool =
{.emit: """`result` = (`s` === "Привет!");""".}
doAssert(stringSaysHelloInRussian("Привет!"))
const constStr = "Привет!"
doAssert(stringSaysHelloInRussian(constStr))
var rtStr = "Привет!"
doAssert(stringSaysHelloInRussian(rtStr))
block: # String case of
const constStr = "Привет!"
var s = "Привет!"
case s
of constStr: discard
else: doAssert(false)
case s
of "Привет!": discard
else: doAssert(false)

View file

@ -23,24 +23,29 @@ template test(opr, a, b, c: expr): stmt {.immediate.} =
test(`+`, 12'i8, -13'i16, -1'i16) test(`+`, 12'i8, -13'i16, -1'i16)
test(`shl`, 0b11, 0b100, 0b110000) test(`shl`, 0b11, 0b100, 0b110000)
test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64) when not defined(js):
test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64)
test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32) test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32)
test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16) test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16) test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64) when not defined(js):
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64)
test(`shr`, 0xffff'i16, 0x4'i16, 0x0fff'i16) test(`shr`, 0xffff'i16, 0x4'i16, 0x0fff'i16)
test(`shr`, 0xff'i8, 0x4'i8, 0x0f'i8) test(`shr`, 0xff'i8, 0x4'i8, 0x0f'i8)
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64) when not defined(js):
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
test(`shr`, 0xffffffff'i32, 0x4'i32, 0x0fffffff'i32) test(`shr`, 0xffffffff'i32, 0x4'i32, 0x0fffffff'i32)
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64) when not defined(js):
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16) test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16)
test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8) test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8)
test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64) when not defined(js):
test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32) test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32)
# bug #916 # bug #916
@ -50,5 +55,27 @@ proc unc(a: float): float =
echo int(unc(0.5)), " ", int(unc(-0.5)) echo int(unc(0.5)), " ", int(unc(-0.5))
echo int(0.5), " ", int(-0.5) echo int(0.5), " ", int(-0.5)
echo("Success") #OUT Success block: # Casts to uint
template testCast(fromValue: typed, toType: typed, expectedResult: typed) =
let src = fromValue
let dst = cast[toType](src)
if dst != expectedResult:
echo "Casting ", astToStr(fromValue), " to ", astToStr(toType), " = ", dst.int, " instead of ", astToStr(expectedResult)
doAssert(dst == expectedResult)
testCast(-1'i16, uint16, 0xffff'u16)
testCast(0xffff'u16, int16, -1'i16)
testCast(0xff'u16, uint8, 0xff'u8)
testCast(0xffff'u16, uint8, 0xff'u8)
testCast(-1'i16, uint32, 0xffffffff'u32)
testCast(0xffffffff'u32, int32, -1)
testCast(0xfffffffe'u32, int32, -2'i32)
testCast(0xffffff'u32, int16, -1'i32)
testCast(-5'i32, uint8, 251'u8)
echo("Success") #OUT Success

View file

@ -1,14 +1,28 @@
discard """
output: '''253'''
"""
# bug #2427 block: # bug #2427
var x = 0'u8
dec x # OverflowError
x -= 1 # OverflowError
x = x - 1 # No error
import unsigned doAssert(x == 253'u8)
var x = 0'u8 block:
dec x # OverflowError var x = 130'u8
x -= 1 # OverflowError x += 130'u8
x = x - 1 # No error doAssert(x == 4'u8)
echo x block:
var x = 40000'u16
x = x + 40000'u16
doAssert(x == 14464'u16)
block:
var x = 4000000000'u32
x = x + 4000000000'u32
doAssert(x == 3705032704'u32)
block:
var x = 123'u16
x -= 125
doAssert(x == 65534'u16)

View file

@ -220,7 +220,7 @@ proc jsTests(r: var TResults, cat: Category, options: string) =
"actiontable/tactiontable", "method/tmultim1", "actiontable/tactiontable", "method/tmultim1",
"method/tmultim3", "method/tmultim4", "method/tmultim3", "method/tmultim4",
"varres/tvarres0", "varres/tvarres3", "varres/tvarres4", "varres/tvarres0", "varres/tvarres3", "varres/tvarres4",
"varres/tvartup"]: "varres/tvartup", "misc/tints", "misc/tunsignedinc"]:
test "tests/" & testfile & ".nim" test "tests/" & testfile & ".nim"
for testfile in ["pure/strutils"]: for testfile in ["pure/strutils"]:

View file

@ -86,6 +86,13 @@ Nim's Community
The `G+ Nim community <https://plus.google.com/u/0/communities/106921341535068810587>`_ is another place where discussions related to the language happen. Read and follow various articles, posts and interesting links about Nim. The `G+ Nim community <https://plus.google.com/u/0/communities/106921341535068810587>`_ is another place where discussions related to the language happen. Read and follow various articles, posts and interesting links about Nim.
.. container:: standout
Gitter
------
The `Gitter Chatroom for Nim <https://gitter.im/nim-lang/Nim>`_ is the persistent logged "natural" chatroom for GitHub repositories and very easy to access for GitHub users. This does not need additional software and can send notifications about messages by email.
.. container:: standout .. container:: standout
Meetup Meetup

View file

@ -101,7 +101,7 @@ The following used to work as the environment creation used to be attached to th
var s: seq[proc(): int {.closure.}] = @[] var s: seq[proc(): int {.closure.}] = @[]
for i in 0 ..< 30: for i in 0 ..< 30:
let ii = i let ii = i
s.add(proc(): int = return ii*ii)) s.add(proc(): int = return ii*ii)
This behaviour has changed in 0.13.0 and now needs to be written as: This behaviour has changed in 0.13.0 and now needs to be written as:
@ -133,8 +133,6 @@ via a commit, for a full list see
(`#3498 <https://github.com/nim-lang/Nim/issues/3498>`_) (`#3498 <https://github.com/nim-lang/Nim/issues/3498>`_)
- Fixed "multimethods: Error: internal error: cgmeth.genConv" - Fixed "multimethods: Error: internal error: cgmeth.genConv"
(`#3550 <https://github.com/nim-lang/Nim/issues/3550>`_) (`#3550 <https://github.com/nim-lang/Nim/issues/3550>`_)
- Fixed "multimethods: Error: internal error: cgmeth.genConv"
(`#3550 <https://github.com/nim-lang/Nim/issues/3550>`_)
- Fixed "nimscript - SIGSEGV in except block" - Fixed "nimscript - SIGSEGV in except block"
(`#3546 <https://github.com/nim-lang/Nim/issues/3546>`_) (`#3546 <https://github.com/nim-lang/Nim/issues/3546>`_)
- Fixed "Bool literals in macros do not work." - Fixed "Bool literals in macros do not work."