array literals uses typed arrays; fix a jsgen bug (#16850)
* array litterals uses typed arrays * Update compiler/jsgen.nim Co-authored-by: Timothee Cour <timothee.cour2@gmail.com> Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
parent
c8d9963150
commit
240879bf3d
6 changed files with 81 additions and 31 deletions
|
|
@ -194,6 +194,8 @@ provided by the operating system.
|
||||||
- TLS: OSX now uses native TLS (`--tlsEmulation:off`), TLS now works with importcpp non-POD types,
|
- TLS: OSX now uses native TLS (`--tlsEmulation:off`), TLS now works with importcpp non-POD types,
|
||||||
such types must use `.cppNonPod` and `--tlsEmulation:off`should be used.
|
such types must use `.cppNonPod` and `--tlsEmulation:off`should be used.
|
||||||
|
|
||||||
|
- Now array literals(JS backend) uses JS typed arrays when the corresponding js typed array exists, for example `[byte(1), 2, 3]` generates `new Uint8Array([1, 2, 3])`.
|
||||||
|
|
||||||
- docgen: rst files can now use single backticks instead of double backticks and correctly render
|
- docgen: rst files can now use single backticks instead of double backticks and correctly render
|
||||||
in both rst2html (as before) as well as common tools rendering rst directly (e.g. github), by
|
in both rst2html (as before) as well as common tools rendering rst directly (e.g. github), by
|
||||||
adding: `default-role:: code` directive inside the rst file, which is now handled by rst2html.
|
adding: `default-role:: code` directive inside the rst file, which is now handled by rst2html.
|
||||||
|
|
|
||||||
|
|
@ -1991,6 +1991,23 @@ proc genMove(p: PProc; n: PNode; r: var TCompRes) =
|
||||||
genReset(p, n)
|
genReset(p, n)
|
||||||
#lineF(p, "$1 = $2;$n", [dest.rdLoc, src.rdLoc])
|
#lineF(p, "$1 = $2;$n", [dest.rdLoc, src.rdLoc])
|
||||||
|
|
||||||
|
proc genJSArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
|
var a: TCompRes
|
||||||
|
r.res = rope("[")
|
||||||
|
r.kind = resExpr
|
||||||
|
for i in 0 ..< n.len:
|
||||||
|
if i > 0: r.res.add(", ")
|
||||||
|
gen(p, n[i], a)
|
||||||
|
if a.typ == etyBaseIndex:
|
||||||
|
r.res.addf("[$1, $2]", [a.address, a.res])
|
||||||
|
else:
|
||||||
|
if not needsNoCopy(p, n[i]):
|
||||||
|
let typ = n[i].typ.skipTypes(abstractInst)
|
||||||
|
useMagic(p, "nimCopy")
|
||||||
|
a.res = "nimCopy(null, $1, $2)" % [a.rdLoc, genTypeInfo(p, typ)]
|
||||||
|
r.res.add(a.res)
|
||||||
|
r.res.add("]")
|
||||||
|
|
||||||
proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var
|
var
|
||||||
a: TCompRes
|
a: TCompRes
|
||||||
|
|
@ -2054,8 +2071,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
of mNew, mNewFinalize: genNew(p, n)
|
of mNew, mNewFinalize: genNew(p, n)
|
||||||
of mChr: gen(p, n[1], r)
|
of mChr: gen(p, n[1], r)
|
||||||
of mArrToSeq:
|
of mArrToSeq:
|
||||||
if needsNoCopy(p, n[1]):
|
# only array literals doesn't need copy
|
||||||
gen(p, n[1], r)
|
if n[1].kind == nkBracket:
|
||||||
|
genJSArrayConstr(p, n[1], r)
|
||||||
else:
|
else:
|
||||||
var x: TCompRes
|
var x: TCompRes
|
||||||
gen(p, n[1], x)
|
gen(p, n[1], x)
|
||||||
|
|
@ -2172,21 +2190,26 @@ proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.res = tmp
|
r.res = tmp
|
||||||
|
|
||||||
proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
|
proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
|
## Constructs array or sequence.
|
||||||
|
## Nim array of uint8..uint32, int8..int32 maps to JS typed arrays.
|
||||||
|
## Nim sequence maps to JS array.
|
||||||
|
var t = skipTypes(n.typ, abstractInst)
|
||||||
|
let e = elemType(t)
|
||||||
|
let jsTyp = arrayTypeForElemType(e)
|
||||||
|
if skipTypes(n.typ, abstractVarRange).kind != tySequence and jsTyp.len > 0:
|
||||||
|
# generate typed array
|
||||||
|
# for example Nim generates `new Uint8Array([1, 2, 3])` for `[byte(1), 2, 3]`
|
||||||
|
# TODO use `set` or loop to initialize typed array which improves performances in some situations
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
r.res = rope("[")
|
r.res = "new $1([" % [rope(jsTyp)]
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
for i in 0..<n.len:
|
for i in 0 ..< n.len:
|
||||||
if i > 0: r.res.add(", ")
|
if i > 0: r.res.add(", ")
|
||||||
gen(p, n[i], a)
|
gen(p, n[i], a)
|
||||||
if a.typ == etyBaseIndex:
|
|
||||||
r.res.addf("[$1, $2]", [a.address, a.res])
|
|
||||||
else:
|
|
||||||
if not needsNoCopy(p, n[i]):
|
|
||||||
let typ = n[i].typ.skipTypes(abstractInst)
|
|
||||||
useMagic(p, "nimCopy")
|
|
||||||
a.res = "nimCopy(null, $1, $2)" % [a.rdLoc, genTypeInfo(p, typ)]
|
|
||||||
r.res.add(a.res)
|
r.res.add(a.res)
|
||||||
r.res.add("]")
|
r.res.add("])")
|
||||||
|
else:
|
||||||
|
genJSArrayConstr(p, n, r)
|
||||||
|
|
||||||
proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) =
|
proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,16 @@ when defined(js):
|
||||||
func `[]=`*(arr: Float64Array, i: int, v: float) {.importjs: "#[#] = #".}
|
func `[]=`*(arr: Float64Array, i: int, v: float) {.importjs: "#[#] = #".}
|
||||||
|
|
||||||
|
|
||||||
|
proc jsTypeOf*[T](x: T): cstring {.importjs: "typeof(#)".}
|
||||||
|
## Returns the name of the JsObject's JavaScript type as a cstring.
|
||||||
|
# xxx replace jsffi.jsTypeOf with this definition and add tests
|
||||||
|
|
||||||
|
proc jsConstructorName*[T](a: T): cstring =
|
||||||
|
asm """`result` = `a`.constructor.name"""
|
||||||
|
|
||||||
proc hasJsBigInt*(): bool =
|
proc hasJsBigInt*(): bool =
|
||||||
asm """`result` = typeof BigInt != 'undefined'"""
|
asm """`result` = typeof BigInt != 'undefined'"""
|
||||||
|
|
||||||
proc hasBigUint64Array*(): bool =
|
proc hasBigUint64Array*(): bool =
|
||||||
asm """`result` = typeof BigUint64Array != 'undefined'"""
|
asm """`result` = typeof BigUint64Array != 'undefined'"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
proc jsTypeOf*[T](x: T): cstring {.importjs: "typeof(#)".}
|
import std/private/jsutils
|
||||||
## Returns the name of the JsObject's JavaScript type as a cstring.
|
|
||||||
# xxx replace jsffi.jsTypeOf with this definition and add tests
|
|
||||||
|
|
||||||
type JsBigIntImpl {.importc: "bigint".} = int
|
type JsBigIntImpl {.importc: "bigint".} = int
|
||||||
type JsBigInt = distinct JsBigIntImpl
|
type JsBigInt = distinct JsBigIntImpl
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
discard """
|
|
||||||
output: '''(x: 0, y: 0)
|
|
||||||
(x: 5, y: 0)
|
|
||||||
@[(x: "2", y: 4), (x: "4", y: 5), (x: "4", y: 5)]
|
|
||||||
@[(a: "3", b: 3), (a: "1", b: 1), (a: "2", b: 2)]
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #4139
|
# bug #4139
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -17,8 +9,8 @@ proc onLoad() =
|
||||||
var foo = TestO(x: 0, y: 0)
|
var foo = TestO(x: 0, y: 0)
|
||||||
test.add(foo)
|
test.add(foo)
|
||||||
foo.x = 5
|
foo.x = 5
|
||||||
echo(test[0])
|
doAssert $test[0] == "(x: 0, y: 0)"
|
||||||
echo foo
|
doAssert $foo == "(x: 5, y: 0)"
|
||||||
|
|
||||||
onLoad()
|
onLoad()
|
||||||
|
|
||||||
|
|
@ -34,7 +26,7 @@ proc foo(x: var seq[MyObj]) =
|
||||||
|
|
||||||
var s = @[MyObj(x: "2", y: 4), MyObj(x: "4", y: 5)]
|
var s = @[MyObj(x: "2", y: 4), MyObj(x: "4", y: 5)]
|
||||||
foo(s)
|
foo(s)
|
||||||
echo s
|
doAssert $s == """@[(x: "2", y: 4), (x: "4", y: 5), (x: "4", y: 5)]"""
|
||||||
|
|
||||||
# bug #5933
|
# bug #5933
|
||||||
import sequtils
|
import sequtils
|
||||||
|
|
@ -48,4 +40,9 @@ var test = @[Test(a: "1", b: 1), Test(a: "2", b: 2)]
|
||||||
|
|
||||||
test.insert(@[Test(a: "3", b: 3)], 0)
|
test.insert(@[Test(a: "3", b: 3)], 0)
|
||||||
|
|
||||||
echo test
|
doAssert $test == """@[(a: "3", b: 3), (a: "1", b: 1), (a: "2", b: 2)]"""
|
||||||
|
|
||||||
|
proc hello(): array[5, int] = discard
|
||||||
|
var x = @(hello())
|
||||||
|
x.add(2)
|
||||||
|
doAssert x == @[0, 0, 0, 0, 0, 2]
|
||||||
|
|
|
||||||
21
tests/js/ttypedarray.nim
Normal file
21
tests/js/ttypedarray.nim
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import std/private/jsutils
|
||||||
|
|
||||||
|
proc main()=
|
||||||
|
template fn(a): untyped = jsConstructorName(a)
|
||||||
|
doAssert fn(array[2, int8].default) == "Int8Array"
|
||||||
|
doAssert fn(array[2, uint8].default) == "Uint8Array"
|
||||||
|
doAssert fn(array[2, byte].default) == "Uint8Array"
|
||||||
|
# doAssert fn(array[2, char].default) == "Uint8Array" # xxx fails; bug?
|
||||||
|
doAssert fn(array[2, uint64].default) == "Array"
|
||||||
|
# pending https://github.com/nim-lang/RFCs/issues/187 maybe use `BigUint64Array`
|
||||||
|
doAssert fn([1'u8]) == "Uint8Array"
|
||||||
|
doAssert fn([1'u16]) == "Uint16Array"
|
||||||
|
doAssert fn([byte(1)]) == "Uint8Array"
|
||||||
|
doAssert fn([1.0'f32]) == "Float32Array"
|
||||||
|
doAssert fn(array[2, float32].default) == "Float32Array"
|
||||||
|
doAssert fn(array[2, float].default) == "Float64Array"
|
||||||
|
doAssert fn(array[2, float64].default) == "Float64Array"
|
||||||
|
doAssert fn([1.0]) == "Float64Array"
|
||||||
|
doAssert fn([1.0'f64]) == "Float64Array"
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue