diff options
-rw-r--r-- | compiler/evalffi.nim | 16 | ||||
-rw-r--r-- | compiler/jsgen.nim | 223 | ||||
-rw-r--r-- | doc/tut2.txt | 4 | ||||
-rw-r--r-- | lib/pure/nimprof.nim | 2 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 15 | ||||
-rw-r--r-- | lib/pure/streams.nim | 5 | ||||
-rw-r--r-- | lib/system/alloc.nim | 2 | ||||
-rw-r--r-- | lib/system/gc.nim | 6 | ||||
-rw-r--r-- | lib/system/gc_common.nim | 8 | ||||
-rw-r--r-- | lib/system/jssys.nim | 81 | ||||
-rw-r--r-- | lib/wrappers/openssl.nim | 11 | ||||
-rw-r--r-- | readme.md | 4 | ||||
-rw-r--r-- | tests/js/tstringitems.nim | 84 | ||||
-rw-r--r-- | tests/misc/tints.nim | 39 | ||||
-rw-r--r-- | tests/misc/tunsignedinc.nim | 34 | ||||
-rw-r--r-- | tests/testament/categories.nim | 2 | ||||
-rw-r--r-- | web/community.txt | 7 | ||||
-rw-r--r-- | web/news.txt | 4 |
18 files changed, 325 insertions, 222 deletions
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim index b1a23802d..75394c2f3 100644 --- a/compiler/evalffi.nim +++ b/compiler/evalffi.nim @@ -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]) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 14cdf0174..9424a9fc5 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -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") diff --git a/doc/tut2.txt b/doc/tut2.txt index 563344570..f60818da6 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -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. diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index e2397b91c..5a7deaab0 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -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.} diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 8560c3ee4..34fb81520 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -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) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index 38e91fee4..bb6175a12 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -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. diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index b4462ed83..6de8e19e7 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -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 diff --git a/lib/system/gc.nim b/lib/system/gc.nim index c25cf4606..727b039d7 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -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: diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index 47e8b4b1f..fdedcaf18 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -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".} diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 5bac54772..6eadae17a 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -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 diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index a227ac98c..05843e2d3 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -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 diff --git a/readme.md b/readme.md index 32dbad9f1..27b2273f0 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/tests/js/tstringitems.nim b/tests/js/tstringitems.nim index f4ea02fec..20aed6e8b 100644 --- a/tests/js/tstringitems.nim +++ b/tests/js/tstringitems.nim @@ -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) diff --git a/tests/misc/tints.nim b/tests/misc/tints.nim index ded24fb5c..5bfb8a17c 100644 --- a/tests/misc/tints.nim +++ b/tests/misc/tints.nim @@ -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 diff --git a/tests/misc/tunsignedinc.nim b/tests/misc/tunsignedinc.nim index 95622156f..60c0559b0 100644 --- a/tests/misc/tunsignedinc.nim +++ b/tests/misc/tunsignedinc.nim @@ -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) diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 73d72289c..ff83379b8 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -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"]: diff --git a/web/community.txt b/web/community.txt index fba59f946..f63ad5c25 100644 --- a/web/community.txt +++ b/web/community.txt @@ -88,6 +88,13 @@ Nim's Community .. 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 ------ diff --git a/web/news.txt b/web/news.txt index 62c3cef24..61a74127f 100644 --- a/web/news.txt +++ b/web/news.txt @@ -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." |