Description
problem 1: var params
when var params are involved, the wrappers in std/jsbigints are more complicated than they should, and maybe even create overhead:
func inc*(this: var JsBigInt; amount: JsBigInt) {.importjs: "([#][0][0] += #)".} =
problem 2: referring to arguments out of order or multiple times
importjs
doesn't allow referring to arguments by position, creating more complex and potentially less efficient wrappers:
func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs:
"(() => { const i = #, b = #; return BigInt.asUintN(b, i) })()".} =
proposal
- P1 extent the
$1
notation (which maps to the proc name) to allow referring to params (eg:$2
is 1st param)
example:
func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs:
"(() => { const i = #, b = #; return BigInt.asUintN(b, i) })()".} =
=>
func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs: "BigInt.asUintN($3, $2)"
- P2 make the dereferencing for var params implicit:
$2
maps to($2)[0]
in js
example:
func inc*(this: var JsBigInt; amount: JsBigInt) {.importjs: "([#][0][0] += #)".}
=>
func inc*(this: var JsBigInt; amount: JsBigInt) {.importjs: "$2 += $3".}
example with a var param and a param referred to more than once:
func myFun*(a: var int, b: int) {.importjs: "$2 = $2 + $3".}
- P3 make jsgen auto-insert
()
around each param so these don't need to appear in declaration (to prevent
example:
func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "((#) $1 #)".}
=>
func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "$2 $1 $3".}
# instead of
func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "($2) $1 $3".}
note: see nim-lang/Nim#16409 (comment) as to why parens are needed in the first place
- P4 (implicitly assumed in above examples): don't require a
()
wrapping the whole importjs expression, as soon as at least one un-escaped $ is detected; this is not the same as P3.
func `==`*(x, y: JsBigInt): bool {.importjs: "(# == #)".}
=>
func `==`*(x, y: JsBigInt): bool {.importjs: "$2 == $3".}
# instead of:
func `==`*(x, y: JsBigInt): bool {.importjs: "($2 == $3)".}
TODO
figure out what to do with:
func debugger*() {.importjs: "debugger".} # should codegen as `debugger;`, not `debugger();`
refs nim-lang/Nim#17296 (comment)
can this work non-ambiguously?
func debugger*() {.importjs: "debugger".}
func debugger*() {.importjs: "$1".} # or even this
- figure out whether this covers use case mentioned in Use
importjs
Nim#17422 (comment)
Using importjs there gives
importjs
for routines requires a pattern errors, since apparently importjs doesn't behave the same as importc and importcpp. Should I open an issue for this or just add patterns for the imports (in a future PR)?
links
importjs pragma is underdocumented and buggy · Issue #488 · timotheecour/Nim