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
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:
result = newNodeIT(nkPtrLit, sym.info, sym.typ)
case name
of "stdin": result.intVal = cast[TAddress](system.stdin)
of "stdout": result.intVal = cast[TAddress](system.stdout)
of "stderr": result.intVal = cast[TAddress](system.stderr)
of "vmErrnoWrapper": result.intVal = cast[TAddress](myerrno)
of "stdin": result.intVal = cast[ByteAddress](system.stdin)
of "stdout": result.intVal = cast[ByteAddress](system.stdout)
of "stderr": result.intVal = cast[ByteAddress](system.stderr)
of "vmErrnoWrapper": result.intVal = cast[ByteAddress](myerrno)
else:
let lib = sym.annex
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)
theAddr = dllhandle.symAddr(name)
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 =
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 wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
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 =
## 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:
result = n
else:
awi(nkPtrLit, cast[TAddress](p))
awi(nkPtrLit, cast[ByteAddress](p))
of tyPtr, tyRef, tyVar:
let p = rd(pointer, x)
if p.isNil:
setNil()
elif n == nil or n.kind == nkPtrLit:
awi(nkPtrLit, cast[TAddress](p))
awi(nkPtrLit, cast[ByteAddress](p))
elif n != nil and n.len == 1:
internalAssert n.kind == nkRefTy
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))
s.loc.r = result
proc makeJSString(s: string): Rope =
(if s.isNil: "null".rope else: strutils.escape(s).rope)
proc escapeJSString(s: string): string =
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
@@ -264,7 +287,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
["", "", "", ""], # ShrI
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
["", "", "($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
["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
["", "", "", ""], # addU
["", "", "", ""], # subU
["", "", "", ""], # mulU
["", "", "", ""], # divU
["", "", "($1 % $2)", "($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)"], # leU
["", "", "($1 < $2)", "($1 < $2)"], # ltU
["", "", "($1 <= $2)", "($1 <= $2)"], # leU64
["", "", "($1 < $2)", "($1 < $2)"], # ltU64
["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
["", "", "($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)"],
["", "", "$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) =
var x, y: TCompRes
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.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) =
var x, y, z: TCompRes
useMagic(p, magic)
@@ -455,10 +411,22 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic, ops: TMagicOps) =
else:
gen(p, n.sons[1], r)
r.res = ops[op][i + 2] % [r.rdLoc]
r.kind = resExpr
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) =
let line = toLinenumber(n.info)
@@ -632,7 +600,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
if stringSwitch:
case e.kind
of nkStrLit..nkTripleStrLit: addf(p.body, "case $1: ",
[makeJSString(e.strVal)])
[makeJSString(e.strVal, false)])
else: internalError(e.info, "jsgen.genCaseStmt: 2")
else:
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 mLeStr: 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 mNew, mNewFinalize: genNew(p, n)
of mSizeOf: r.res = rope(getSize(n.sons[1].typ))
@@ -1406,11 +1374,17 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
else:
unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)")
of mInc:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)")
if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
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:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
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 mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2")
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])
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) =
r.typ = etyNone
r.kind = resNone
@@ -1635,7 +1640,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
case n.kind
of nkSym:
genSym(p, n, r)
of nkCharLit..nkInt64Lit:
of nkCharLit..nkUInt32Lit:
if n.typ.kind == tyBool:
r.res = if n.intVal == 0: rope"false" else: rope"true"
else:
@@ -1654,10 +1659,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
r.kind = resExpr
of nkStrLit..nkTripleStrLit:
if skipTypes(n.typ, abstractVarRange).kind == tyString:
useMagic(p, "cstrToNimstr")
r.res = "cstrToNimstr($1)" % [makeJSString(n.strVal)]
useMagic(p, "makeNimstrLit")
r.res = "makeNimstrLit($1)" % [makeJSString(n.strVal)]
else:
r.res = makeJSString(n.strVal)
r.res = makeJSString(n.strVal, false)
r.kind = resExpr
of nkFloatLit..nkFloat64Lit:
let f = n.floatVal
@@ -1688,7 +1693,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkCheckedFieldExpr: genCheckedFieldAccess(p, n, r)
of nkObjDownConv: gen(p, n.sons[0], 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 nkChckRange64: genRangeChck(p, n, r, "chckRange64")
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.
It is recommended to avoid those if you're not sure how they are translated
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
use ``cstring`` only when it is semantically appropriate. E.g. don't use
``cstring`` as a binary data buffer.

View File

@@ -12,7 +12,7 @@
## report at program exit.
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 ...
{.push profiler: off.}

View File

@@ -886,7 +886,7 @@ elif not defined(useNimRtl):
discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
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
proc startProcessAfterFork(data: ptr StartProcessData) =
@@ -916,17 +916,16 @@ elif not defined(useNimRtl):
discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC)
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.
# On MacOSX we can arrive here only from fork, so this is safe:
environ = data.sysEnv
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:
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) =
## writes the string `x` to the the stream `s`. No length field or
## 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.} =
## **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()) %%
s == 0, "rawDealloc 3")
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")
f.zeroField = 0
f.next = c.freeList

View File

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

View File

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

View File

@@ -165,15 +165,46 @@ proc SetConstr() {.varargs, asmNoStackFrame, compilerproc.} =
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.} =
asm """
var result = [];
for (var i = 0; i < `c`.length; ++i) {
result[i] = `c`.charCodeAt(i);
{.emit: """
var ln = `c`.length;
var result = new Array(ln);
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
return result;
"""
else if((ch > 127) && (ch < 2048)) {
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.} =
asm """
@@ -417,42 +448,6 @@ proc absInt(a: int): int {.compilerproc.} =
proc absInt64(a: int64): int64 {.compilerproc.} =
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.} =
result = a

View File

@@ -496,13 +496,12 @@ type
data: array[MD5_LBLOCK, MD5_LONG]
num: cuint
{.pragma: ic, importc: "$1".}
{.push callconv:cdecl, dynlib:DLLUtilName.}
proc md5_Init*(c: var MD5_CTX): cint{.ic.}
proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.ic.}
proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.ic.}
proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.ic.}
proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.ic.}
proc md5_Init*(c: var MD5_CTX): cint{.importc: "MD5_Init".}
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{.importc: "MD5_Final".}
proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.importc: "MD5".}
proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.importc: "MD5_Transform".}
{.pop.}
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:
```
$ git clone git://github.com/nim-lang/Nim.git
$ git clone https://github.com/nim-lang/Nim.git
$ 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 ..
$ bin/nim c koch

View File

@@ -3,22 +3,76 @@ discard """
Hello'''
"""
# bug #2581
block: # bug #2581
const someVars = [ "Hello" ]
var someVars2 = [ "Hello" ]
const someVars = [ "Hello" ]
var someVars2 = [ "Hello" ]
proc getSomeVar: string =
for i in someVars:
if i == "Hello":
result = i
break
proc getSomeVar: string =
for i in someVars:
if i == "Hello":
result = i
break
proc getSomeVar2: string =
for i in someVars2:
if i == "Hello":
result = i
break
proc getSomeVar2: string =
for i in someVars2:
if i == "Hello":
result = i
break
echo getSomeVar()
echo getSomeVar2()
echo getSomeVar()
echo getSomeVar2()
block: # Test compile-time binary data generation, invalid unicode
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(`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(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'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`, 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(`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`, 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)
# bug #916
@@ -50,5 +55,27 @@ proc unc(a: float): float =
echo int(unc(0.5)), " ", int(unc(-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
dec x # OverflowError
x -= 1 # OverflowError
x = x - 1 # No error
block:
var x = 130'u8
x += 130'u8
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",
"method/tmultim3", "method/tmultim4",
"varres/tvarres0", "varres/tvarres3", "varres/tvarres4",
"varres/tvartup"]:
"varres/tvartup", "misc/tints", "misc/tunsignedinc"]:
test "tests/" & testfile & ".nim"
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.
.. 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
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.}] = @[]
for i in 0 ..< 30:
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:
@@ -133,8 +133,6 @@ via a commit, for a full list see
(`#3498 <https://github.com/nim-lang/Nim/issues/3498>`_)
- Fixed "multimethods: Error: internal error: cgmeth.genConv"
(`#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"
(`#3546 <https://github.com/nim-lang/Nim/issues/3546>`_)
- Fixed "Bool literals in macros do not work."