language change: change how the experimental dot operators work
This commit is contained in:
parent
416a322efb
commit
33814cf63e
5 changed files with 25 additions and 19 deletions
|
|
@ -111,3 +111,9 @@ This now needs to be written as:
|
||||||
- ``strutils.split`` and ``strutils.rsplit`` with an empty string and a
|
- ``strutils.split`` and ``strutils.rsplit`` with an empty string and a
|
||||||
separator now returns that empty string.
|
separator now returns that empty string.
|
||||||
See issue [#4377](https://github.com/nim-lang/Nim/issues/4377).
|
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.
|
||||||
|
|
|
||||||
|
|
@ -111,3 +111,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimNoArrayToCstringConversion")
|
defineSymbol("nimNoArrayToCstringConversion")
|
||||||
defineSymbol("nimNewRoof")
|
defineSymbol("nimNewRoof")
|
||||||
defineSymbol("nimHasRunnableExamples")
|
defineSymbol("nimHasRunnableExamples")
|
||||||
|
defineSymbol("nimNewDot")
|
||||||
|
|
|
||||||
|
|
@ -235,12 +235,11 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
|
|
||||||
if nfDotField in n.flags:
|
if nfDotField in n.flags:
|
||||||
internalAssert f.kind == nkIdent and n.sonsLen >= 2
|
internalAssert f.kind == nkIdent and n.sonsLen >= 2
|
||||||
let calleeName = newStrNode(nkStrLit, f.ident.s).withInfo(n.info)
|
|
||||||
|
|
||||||
# leave the op head symbol empty,
|
# leave the op head symbol empty,
|
||||||
# we are going to try multiple variants
|
# we are going to try multiple variants
|
||||||
n.sons[0..1] = [nil, n[1], calleeName]
|
n.sons[0..1] = [nil, n[1], f]
|
||||||
orig.sons[0..1] = [nil, orig[1], calleeName]
|
orig.sons[0..1] = [nil, orig[1], f]
|
||||||
|
|
||||||
template tryOp(x) =
|
template tryOp(x) =
|
||||||
let op = newIdentNode(getIdent(x), n.info)
|
let op = newIdentNode(getIdent(x), n.info)
|
||||||
|
|
@ -255,8 +254,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
tryOp "."
|
tryOp "."
|
||||||
|
|
||||||
elif nfDotSetter in n.flags and f.kind == nkIdent and n.len == 3:
|
elif nfDotSetter in n.flags and f.kind == nkIdent and n.len == 3:
|
||||||
let calleeName = newStrNode(nkStrLit,
|
# we need to strip away the trailing '=' here:
|
||||||
f.ident.s[0..f.ident.s.len-2]).withInfo(n.info)
|
let calleeName = newIdentNode(getIdent(f.ident.s[0..f.ident.s.len-2]), n.info)
|
||||||
let callOp = newIdentNode(getIdent".=", n.info)
|
let callOp = newIdentNode(getIdent".=", n.info)
|
||||||
n.sons[0..1] = [callOp, n[1], calleeName]
|
n.sons[0..1] = [callOp, n[1], calleeName]
|
||||||
orig.sons[0..1] = [callOp, orig[1], calleeName]
|
orig.sons[0..1] = [callOp, orig[1], calleeName]
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ or dynamic file formats such as JSON or XML.
|
||||||
When Nim encounters an expression that cannot be resolved by the
|
When Nim encounters an expression that cannot be resolved by the
|
||||||
standard overload resolution rules, the current scope will be searched
|
standard overload resolution rules, the current scope will be searched
|
||||||
for a dot operator that can be matched against a re-written form of
|
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
|
the expression, where the unknown field or proc name is passed to
|
||||||
an additional static string parameter:
|
an ``untyped`` parameter:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
a.b # becomes `.`(a, "b")
|
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:
|
templates and macros), depending on the desired effect:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. 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}")
|
var js = parseJson("{ x: 1, y: 2}")
|
||||||
echo js.x # outputs 1
|
echo js.x # outputs 1
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ proc `==`*(x, y: JsRoot): bool {. importcpp: "(# === #)" .}
|
||||||
## and not strings or numbers, this is a *comparison of references*.
|
## and not strings or numbers, this is a *comparison of references*.
|
||||||
|
|
||||||
{. experimental .}
|
{. experimental .}
|
||||||
macro `.`*(obj: JsObject, field: static[cstring]): JsObject =
|
macro `.`*(obj: JsObject, field: untyped): JsObject =
|
||||||
## Experimental dot accessor (get) for type JsObject.
|
## Experimental dot accessor (get) for type JsObject.
|
||||||
## Returns the value of a property of name `field` from a JsObject `x`.
|
## 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`)
|
helper(`obj`)
|
||||||
else:
|
else:
|
||||||
if not mangledNames.hasKey($field):
|
if not mangledNames.hasKey($field):
|
||||||
mangledNames[$field] = $mangleJsName(field)
|
mangledNames[$field] = $mangleJsName($field)
|
||||||
let importString = "#." & mangledNames[$field]
|
let importString = "#." & mangledNames[$field]
|
||||||
result = quote do:
|
result = quote do:
|
||||||
proc helper(o: JsObject): JsObject
|
proc helper(o: JsObject): JsObject
|
||||||
{. importcpp: `importString`, gensym .}
|
{. importcpp: `importString`, gensym .}
|
||||||
helper(`obj`)
|
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.
|
## Experimental dot accessor (set) for type JsObject.
|
||||||
## Sets the value of a property of name `field` in a JsObject `x` to `value`.
|
## Sets the value of a property of name `field` in a JsObject `x` to `value`.
|
||||||
if validJsName($field):
|
if validJsName($field):
|
||||||
|
|
@ -214,7 +214,7 @@ macro `.=`*(obj: JsObject, field: static[cstring], value: untyped): untyped =
|
||||||
helper(`obj`, `value`)
|
helper(`obj`, `value`)
|
||||||
else:
|
else:
|
||||||
if not mangledNames.hasKey($field):
|
if not mangledNames.hasKey($field):
|
||||||
mangledNames[$field] = $mangleJsName(field)
|
mangledNames[$field] = $mangleJsName($field)
|
||||||
let importString = "#." & mangledNames[$field] & " = #"
|
let importString = "#." & mangledNames[$field] & " = #"
|
||||||
result = quote do:
|
result = quote do:
|
||||||
proc helper(o: JsObject, v: auto)
|
proc helper(o: JsObject, v: auto)
|
||||||
|
|
@ -222,7 +222,7 @@ macro `.=`*(obj: JsObject, field: static[cstring], value: untyped): untyped =
|
||||||
helper(`obj`, `value`)
|
helper(`obj`, `value`)
|
||||||
|
|
||||||
macro `.()`*(obj: JsObject,
|
macro `.()`*(obj: JsObject,
|
||||||
field: static[cstring],
|
field: untyped,
|
||||||
args: varargs[JsObject, jsFromAst]): JsObject =
|
args: varargs[JsObject, jsFromAst]): JsObject =
|
||||||
## Experimental "method call" operator for type JsObject.
|
## Experimental "method call" operator for type JsObject.
|
||||||
## Takes the name of a method of the JavaScript object (`field`) and calls
|
## Takes the name of a method of the JavaScript object (`field`) and calls
|
||||||
|
|
@ -245,7 +245,7 @@ macro `.()`*(obj: JsObject,
|
||||||
importString = "#." & $field & "(@)"
|
importString = "#." & $field & "(@)"
|
||||||
else:
|
else:
|
||||||
if not mangledNames.hasKey($field):
|
if not mangledNames.hasKey($field):
|
||||||
mangledNames[$field] = $mangleJsName(field)
|
mangledNames[$field] = $mangleJsName($field)
|
||||||
importString = "#." & mangledNames[$field] & "(@)"
|
importString = "#." & mangledNames[$field] & "(@)"
|
||||||
result = quote:
|
result = quote:
|
||||||
proc helper(o: JsObject): JsObject
|
proc helper(o: JsObject): JsObject
|
||||||
|
|
@ -257,7 +257,7 @@ macro `.()`*(obj: JsObject,
|
||||||
result[1].add args[idx].copyNimTree
|
result[1].add args[idx].copyNimTree
|
||||||
|
|
||||||
macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
||||||
field: static[cstring]): V =
|
field: untyped): V =
|
||||||
## Experimental dot accessor (get) for type JsAssoc.
|
## Experimental dot accessor (get) for type JsAssoc.
|
||||||
## Returns the value of a property of name `field` from a JsObject `x`.
|
## Returns the value of a property of name `field` from a JsObject `x`.
|
||||||
var importString: string
|
var importString: string
|
||||||
|
|
@ -265,7 +265,7 @@ macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
||||||
importString = "#." & $field
|
importString = "#." & $field
|
||||||
else:
|
else:
|
||||||
if not mangledNames.hasKey($field):
|
if not mangledNames.hasKey($field):
|
||||||
mangledNames[$field] = $mangleJsName(field)
|
mangledNames[$field] = $mangleJsName($field)
|
||||||
importString = "#." & mangledNames[$field]
|
importString = "#." & mangledNames[$field]
|
||||||
result = quote do:
|
result = quote do:
|
||||||
proc helper(o: type(`obj`)): `obj`.V
|
proc helper(o: type(`obj`)): `obj`.V
|
||||||
|
|
@ -273,7 +273,7 @@ macro `.`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
||||||
helper(`obj`)
|
helper(`obj`)
|
||||||
|
|
||||||
macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
||||||
field: static[cstring],
|
field: untyped,
|
||||||
value: V): untyped =
|
value: V): untyped =
|
||||||
## Experimental dot accessor (set) for type JsAssoc.
|
## Experimental dot accessor (set) for type JsAssoc.
|
||||||
## Sets the value of a property of name `field` in a JsObject `x` to `value`.
|
## 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 & " = #"
|
importString = "#." & $field & " = #"
|
||||||
else:
|
else:
|
||||||
if not mangledNames.hasKey($field):
|
if not mangledNames.hasKey($field):
|
||||||
mangledNames[$field] = $mangleJsName(field)
|
mangledNames[$field] = $mangleJsName($field)
|
||||||
importString = "#." & mangledNames[$field] & " = #"
|
importString = "#." & mangledNames[$field] & " = #"
|
||||||
result = quote do:
|
result = quote do:
|
||||||
proc helper(o: type(`obj`), v: `obj`.V)
|
proc helper(o: type(`obj`), v: `obj`.V)
|
||||||
|
|
@ -290,7 +290,7 @@ macro `.=`*[K: string | cstring, V](obj: JsAssoc[K, V],
|
||||||
helper(`obj`, `value`)
|
helper(`obj`, `value`)
|
||||||
|
|
||||||
macro `.()`*[K: string | cstring, V: proc](obj: JsAssoc[K, V],
|
macro `.()`*[K: string | cstring, V: proc](obj: JsAssoc[K, V],
|
||||||
field: static[cstring],
|
field: untyped,
|
||||||
args: varargs[untyped]): auto =
|
args: varargs[untyped]): auto =
|
||||||
## Experimental "method call" operator for type JsAssoc.
|
## Experimental "method call" operator for type JsAssoc.
|
||||||
## Takes the name of a method of the JavaScript object (`field`) and calls
|
## Takes the name of a method of the JavaScript object (`field`) and calls
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue