diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-11-29 13:31:31 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-11-29 13:31:31 +0100 |
commit | 33814cf63e9cdf3300c2d14df8f611dcb863dfaa (patch) | |
tree | 229c4485e3cac314aa02cdce4c7badea5de969b7 | |
parent | 416a322efb3ce8a90c88f596863cbba89d28bccb (diff) | |
download | Nim-33814cf63e9cdf3300c2d14df8f611dcb863dfaa.tar.gz |
language change: change how the experimental dot operators work
-rw-r--r-- | changelog.md | 6 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/semcall.nim | 9 | ||||
-rw-r--r-- | doc/manual/special_ops.txt | 6 | ||||
-rw-r--r-- | lib/js/jsffi.nim | 22 |
5 files changed, 25 insertions, 19 deletions
diff --git a/changelog.md b/changelog.md index f0deceb15..a37089ef2 100644 --- a/changelog.md +++ b/changelog.md @@ -111,3 +111,9 @@ This now needs to be written as: - ``strutils.split`` and ``strutils.rsplit`` with an empty string and a separator now returns that empty string. See issue [#4377](https://github.com/nim-lang/Nim/issues/4377). +- The experimental overloading of the dot ``.`` operators now take + an ``untyped``` parameter as the field name, it used to be + a ``static[string]``. You can use ``when defined(nimNewDot)`` to make + your code work with both old and new Nim versions. + See [special-operators](https://nim-lang.org/docs/manual.html#special-operators) + for more information. diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 4879ce5c3..a52214e73 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -111,3 +111,4 @@ proc initDefines*() = defineSymbol("nimNoArrayToCstringConversion") defineSymbol("nimNewRoof") defineSymbol("nimHasRunnableExamples") + defineSymbol("nimNewDot") diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 5c0624a77..5ea34ab1a 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -235,12 +235,11 @@ proc resolveOverloads(c: PContext, n, orig: PNode, if nfDotField in n.flags: internalAssert f.kind == nkIdent and n.sonsLen >= 2 - let calleeName = newStrNode(nkStrLit, f.ident.s).withInfo(n.info) # leave the op head symbol empty, # we are going to try multiple variants - n.sons[0..1] = [nil, n[1], calleeName] - orig.sons[0..1] = [nil, orig[1], calleeName] + n.sons[0..1] = [nil, n[1], f] + orig.sons[0..1] = [nil, orig[1], f] template tryOp(x) = let op = newIdentNode(getIdent(x), n.info) @@ -255,8 +254,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode, tryOp "." elif nfDotSetter in n.flags and f.kind == nkIdent and n.len == 3: - let calleeName = newStrNode(nkStrLit, - f.ident.s[0..f.ident.s.len-2]).withInfo(n.info) + # we need to strip away the trailing '=' here: + let calleeName = newIdentNode(getIdent(f.ident.s[0..f.ident.s.len-2]), n.info) let callOp = newIdentNode(getIdent".=", n.info) n.sons[0..1] = [callOp, n[1], calleeName] orig.sons[0..1] = [callOp, orig[1], calleeName] diff --git a/doc/manual/special_ops.txt b/doc/manual/special_ops.txt index 1c7136bec..93977f81b 100644 --- a/doc/manual/special_ops.txt +++ b/doc/manual/special_ops.txt @@ -17,8 +17,8 @@ or dynamic file formats such as JSON or XML. When Nim encounters an expression that cannot be resolved by the standard overload resolution rules, the current scope will be searched for a dot operator that can be matched against a re-written form of -the expression, where the unknown field or proc name is converted to -an additional static string parameter: +the expression, where the unknown field or proc name is passed to +an ``untyped`` parameter: .. code-block:: nim a.b # becomes `.`(a, "b") @@ -28,7 +28,7 @@ The matched dot operators can be symbols of any callable kind (procs, templates and macros), depending on the desired effect: .. code-block:: nim - proc `.` (js: PJsonNode, field: string): JSON = js[field] + template `.` (js: PJsonNode, field: untyped): JSON = js[astToStr(field)] var js = parseJson("{ x: 1, y: 2}") echo js.x # outputs 1 diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim index 13eb1e759..f34efe9a2 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -177,7 +177,7 @@ proc `==`*(x, y: JsRoot): bool {. importcpp: "(# === #)" .} ## and not strings or numbers, this is a *comparison of references*. {. experimental .} -macro `.`*(obj: JsObject, field: static[cstring]): JsObject = +macro `.`*(obj: JsObject, field: untyped): JsObject = ## Experimental dot accessor (get) for type JsObject. ## Returns the value of a property of name `field` from a JsObject `x`. ## @@ -196,14 +196,14 @@ macro `.`*(obj: JsObject, field: static[cstring]): JsObject = helper(`obj`) else: if not mangledNames.hasKey($field): - mangledNames[$field] = $mangleJsName(field) + mangledNames[$field] = $mangleJsName($field) let importString = "#." & mangledNames[$field] result = quote do: proc helper(o: JsObject): JsObject {. importcpp: `importString`, gensym .} helper(`obj`) -macro `.=`*(obj: JsObject, field: static[cstring], value: untyped): untyped = +macro `.=`*(obj: JsObject, field, value: untyped): untyped = ## Experimental dot accessor (set) for type JsObject. ## Sets the value of a property of name `field` in a JsObject `x` to `value`. if validJsName($field): @@ -214,7 +214,7 @@ macro `.=`*(obj: JsObject, field: static[cstring], value: untyped): untyped = helper(`obj`, `value`) else: if not mangledNames.hasKey($field): - mangledNames[$field] = $mangleJsName(field) + mangledNames[$field] = $mangleJsName($field) let importString = "#." & mangledNames[$field] & " = #" result = quote do: proc helper(o: JsObject, v: auto) @@ -222,7 +222,7 @@ macro `.=`*(obj: JsObject, field: static[cstring], value: untyped): untyped = helper(`obj`, `value`) macro `.()`*(obj: JsObject, - field: static[cstring], + field: untyped, args: varargs[JsObject, jsFromAst]): JsObject = ## Experimental "method call" operator for type JsObject. ## Takes the name of a method of the JavaScript object (`field`) and calls @@ -245,7 +245,7 @@ macro `.()`*(obj: JsObject, importString = "#." & $field & "(@)" else: if not mangledNames.hasKey($field): - mangledNames[$field] = $mangleJsName(field) + mangledNames[$field] = $mangleJsName($field) importString = "#." & mangledNames[$field] & "(@)" result = quote: proc helper(o: JsObject): JsObject @@ -257,7 +257,7 @@ macro `.()`*(obj: JsObject, result[1].add args[idx].copyNimTree macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V], - field: static[cstring]): V = + field: untyped): V = ## Experimental dot accessor (get) for type JsAssoc. ## Returns the value of a property of name `field` from a JsObject `x`. var importString: string @@ -265,7 +265,7 @@ macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V], importString = "#." & $field else: if not mangledNames.hasKey($field): - mangledNames[$field] = $mangleJsName(field) + mangledNames[$field] = $mangleJsName($field) importString = "#." & mangledNames[$field] result = quote do: proc helper(o: type(`obj`)): `obj`.V @@ -273,7 +273,7 @@ macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V], helper(`obj`) macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V], - field: static[cstring], + field: untyped, value: V): untyped = ## Experimental dot accessor (set) for type JsAssoc. ## Sets the value of a property of name `field` in a JsObject `x` to `value`. @@ -282,7 +282,7 @@ macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V], importString = "#." & $field & " = #" else: if not mangledNames.hasKey($field): - mangledNames[$field] = $mangleJsName(field) + mangledNames[$field] = $mangleJsName($field) importString = "#." & mangledNames[$field] & " = #" result = quote do: proc helper(o: type(`obj`), v: `obj`.V) @@ -290,7 +290,7 @@ macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V], helper(`obj`, `value`) macro `.()`*[K: string | cstring, V: proc](obj: JsAssoc[K, V], - field: static[cstring], + field: untyped, args: varargs[untyped]): auto = ## Experimental "method call" operator for type JsAssoc. ## Takes the name of a method of the JavaScript object (`field`) and calls |