diff options
author | Alexander Ivanov <alehander42@gmail.com> | 2018-11-23 16:05:15 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-11-23 15:05:15 +0100 |
commit | 88d707cb88b3c0c93aed5e261beffa3a2e6d2c66 (patch) | |
tree | 2102c36fd34281244ec50715ab997387e5983378 /lib/js | |
parent | 562d185cb73fa31d901685a15e92b8904f9b077b (diff) | |
download | Nim-88d707cb88b3c0c93aed5e261beffa3a2e6d2c66.tar.gz |
Support only some types as JsAssoc types (#8627)
Diffstat (limited to 'lib/js')
-rw-r--r-- | lib/js/jsffi.nim | 67 |
1 files changed, 34 insertions, 33 deletions
diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim index 307fe2382..e1c59803d 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -69,10 +69,25 @@ template mangleJsName(name: cstring): cstring = inc nameCounter "mangledName" & $nameCounter +# only values that can be mapped 1 to 1 with cstring should be keys: they have an injective function with cstring + +proc toJsKey*[T: SomeInteger](text: cstring, t: type T): T {.importcpp: "parseInt(#)".} + +proc toJsKey*[T: enum](text: cstring, t: type T): T = + T(text.toJsKey(int)) + +proc toJsKey*(text: cstring, t: type cstring): cstring = + text + +proc toJsKey*[T: SomeFloat](text: cstring, t: type T): T {.importcpp: "parseFloat(#)".} + type + JsKey* = concept a, type T + cstring.toJsKey(T) is type(a) + JsObject* = ref object of JsRoot ## Dynamically typed wrapper around a JavaScript object. - JsAssoc*[K, V] = ref object of JsRoot + JsAssoc*[K: JsKey, V] = ref object of JsRoot ## Statically typed wrapper around a JavaScript object. js* = JsObject @@ -104,7 +119,7 @@ type proc newJsObject*: JsObject {. importcpp: "{@}" .} ## Creates a new empty JsObject -proc newJsAssoc*[K, V]: JsAssoc[K, V] {. importcpp: "{@}" .} +proc newJsAssoc*[K: JsKey, V]: JsAssoc[K, V] {. importcpp: "{@}" .} ## Creates a new empty JsAssoc with key type `K` and value type `V`. # Checks @@ -176,21 +191,19 @@ proc `[]=`*[T](obj: JsObject, field: cstring, val: T) {. importcpp: setImpl .} proc `[]=`*[T](obj: JsObject, field: int, val: T) {. importcpp: setImpl .} ## Set the value of a property of name `field` in a JsObject `obj` to `v`. -proc `[]`*[K: not string, V](obj: JsAssoc[K, V], field: K): V - {. importcpp: getImpl .} - ## Return the value of a property of name `field` from a JsAssoc `obj`. - -proc `[]`*[V](obj: JsAssoc[string, V], field: cstring): V +proc `[]`*[K: JsKey, V](obj: JsAssoc[K, V], field: K): V {. importcpp: getImpl .} ## Return the value of a property of name `field` from a JsAssoc `obj`. -proc `[]=`*[K: not string, V](obj: JsAssoc[K, V], field: K, val: V) +proc `[]=`*[K: JsKey, V](obj: JsAssoc[K, V], field: K, val: V) {. importcpp: setImpl .} ## Set the value of a property of name `field` in a JsAssoc `obj` to `v`. -proc `[]=`*[V](obj: JsAssoc[string, V], field: cstring, val: V) - {. importcpp: setImpl .} - ## Set the value of a property of name `field` in a JsAssoc `obj` to `v`. +proc `[]`*[V](obj: JsAssoc[cstring, V], field: string): V = + obj[cstring(field)] + +proc `[]=`*[V](obj: JsAssoc[cstring, V], field: string, val: V) = + obj[cstring(field)] = val proc `==`*(x, y: JsRoot): bool {. importcpp: "(# === #)" .} ## Compare two JsObjects or JsAssocs. Be careful though, as this is comparison @@ -277,7 +290,7 @@ macro `.()`*(obj: JsObject, result[0][3].add newIdentDefs(paramName, newIdentNode(!"JsObject")) result[1].add args[idx].copyNimTree -macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V], +macro `.`*[K: cstring, V](obj: JsAssoc[K, V], field: untyped): V = ## Experimental dot accessor (get) for type JsAssoc. ## Returns the value of a property of name `field` from a JsObject `x`. @@ -293,7 +306,7 @@ macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V], {. importcpp: `importString`, gensym .} helper(`obj`) -macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V], +macro `.=`*[K: cstring, V](obj: JsAssoc[K, V], field: untyped, value: V): untyped = ## Experimental dot accessor (set) for type JsAssoc. @@ -310,7 +323,7 @@ macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V], {. importcpp: `importString`, gensym .} helper(`obj`, `value`) -macro `.()`*[K: string | cstring, V: proc](obj: JsAssoc[K, V], +macro `.()`*[K: cstring, V: proc](obj: JsAssoc[K, V], field: untyped, args: varargs[untyped]): auto = ## Experimental "method call" operator for type JsAssoc. @@ -354,24 +367,18 @@ iterator keys*(obj: JsObject): cstring = yield k {.emit: "}".} -iterator pairs*[K, V](assoc: JsAssoc[K, V]): (K,V) = +iterator pairs*[K: JsKey, V](assoc: JsAssoc[K, V]): (K,V) = ## Yields tuples of type ``(K, V)``, with the first entry ## being a `key` in the JsAssoc and the second being its corresponding value. - when K is string: - var k: cstring - else: - var k: K + var k: cstring var v: V {.emit: "for (var `k` in `assoc`) {".} {.emit: " if (!`assoc`.hasOwnProperty(`k`)) continue;".} {.emit: " `v`=`assoc`[`k`];".} - when K is string: - yield ($k, v) - else: - yield (k, v) + yield (k.toJsKey(K), v) {.emit: "}".} -iterator items*[K,V](assoc: JSAssoc[K,V]): V = +iterator items*[K, V](assoc: JSAssoc[K, V]): V = ## Yields the `values` in a JsAssoc. var v: V {.emit: "for (var k in `assoc`) {".} @@ -380,18 +387,12 @@ iterator items*[K,V](assoc: JSAssoc[K,V]): V = yield v {.emit: "}".} -iterator keys*[K,V](assoc: JSAssoc[K,V]): K = +iterator keys*[K: JsKey, V](assoc: JSAssoc[K, V]): K = ## Yields the `keys` in a JsAssoc. - when K is string: - var k: cstring - else: - var k: K + var k: cstring {.emit: "for (var `k` in `assoc`) {".} {.emit: " if (!`assoc`.hasOwnProperty(`k`)) continue;".} - when K is string: - yield $k - else: - yield k + yield k.toJsKey(K) {.emit: "}".} # Literal generation |