expr and stmt are now deprecated
This commit is contained in:
parent
86d4090cd8
commit
8876ed23f1
14 changed files with 51 additions and 51 deletions
|
|
@ -293,7 +293,7 @@ definition):
|
|||
var
|
||||
lastId = 0
|
||||
|
||||
template genId*: expr =
|
||||
template genId*: untyped =
|
||||
bind lastId
|
||||
inc(lastId)
|
||||
lastId
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ semantics and should not be used directly! It should only be used in templates
|
|||
that also implement some form of locking at runtime:
|
||||
|
||||
.. code-block:: nim
|
||||
template lock(a: TLock; body: stmt) =
|
||||
template lock(a: TLock; body: untyped) =
|
||||
pthread_mutex_lock(a)
|
||||
{.locks: [a].}:
|
||||
try:
|
||||
|
|
@ -64,7 +64,7 @@ model low level lockfree mechanisms:
|
|||
var dummyLock {.compileTime.}: int
|
||||
var atomicCounter {.guard: dummyLock.}: int
|
||||
|
||||
template atomicRead(x): expr =
|
||||
template atomicRead(x): untyped =
|
||||
{.locks: [dummyLock].}:
|
||||
memoryReadBarrier()
|
||||
x
|
||||
|
|
@ -167,7 +167,7 @@ the runtime check is required to ensure a global ordering for two locks ``a``
|
|||
and ``b`` of the same lock level:
|
||||
|
||||
.. code-block:: nim
|
||||
template multilock(a, b: ptr TLock; body: stmt) =
|
||||
template multilock(a, b: ptr TLock; body: untyped) =
|
||||
if cast[ByteAddress](a) < cast[ByteAddress](b):
|
||||
pthread_mutex_lock(a)
|
||||
pthread_mutex_lock(b)
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ statement as seen in stack backtraces:
|
|||
|
||||
.. code-block:: nim
|
||||
|
||||
template myassert*(cond: expr, msg = "") =
|
||||
template myassert*(cond: untyped, msg = "") =
|
||||
if not cond:
|
||||
# change run-time line information of the 'raise' statement:
|
||||
{.line: InstantiationInfo().}:
|
||||
|
|
|
|||
|
|
@ -57,8 +57,7 @@ A template where every parameter is ``untyped`` is called an `immediate`:idx:
|
|||
template. For historical reasons templates can be explicitly annotated with
|
||||
an ``immediate`` pragma and then these templates do not take part in
|
||||
overloading resolution and the parameters' types are *ignored* by the
|
||||
compiler. Explicit immediate templates are about to be deprecated in later
|
||||
versions of the compiler.
|
||||
compiler. Explicit immediate templates are now deprecated.
|
||||
|
||||
**Note**: For historical reasons ``stmt`` is an alias for ``typed`` and
|
||||
``expr`` an alias for ``untyped``, but new code should use the newer,
|
||||
|
|
@ -159,7 +158,7 @@ bound from the definition scope of the template:
|
|||
var
|
||||
lastId = 0
|
||||
|
||||
template genId*: expr =
|
||||
template genId*: untyped =
|
||||
inc(lastId)
|
||||
lastId
|
||||
|
||||
|
|
@ -181,7 +180,7 @@ In templates identifiers can be constructed with the backticks notation:
|
|||
|
||||
.. code-block:: nim
|
||||
|
||||
template typedef(name: expr, typ: typedesc) {.immediate.} =
|
||||
template typedef(name: untyped, typ: typedesc) =
|
||||
type
|
||||
`T name`* {.inject.} = typ
|
||||
`P name`* {.inject.} = ref `T name`
|
||||
|
|
@ -242,7 +241,7 @@ template cannot be accessed in the instantiation context:
|
|||
|
||||
.. code-block:: nim
|
||||
|
||||
template newException*(exceptn: typedesc, message: string): expr =
|
||||
template newException*(exceptn: typedesc, message: string): untyped =
|
||||
var
|
||||
e: ref exceptn # e is implicitly gensym'ed here
|
||||
new(e)
|
||||
|
|
@ -264,7 +263,7 @@ is ``gensym`` and for ``proc``, ``iterator``, ``converter``, ``template``,
|
|||
template parameter, it is an inject'ed symbol:
|
||||
|
||||
.. code-block:: nim
|
||||
template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} =
|
||||
template withFile(f, fn, mode: untyped, actions: untyped): untyped =
|
||||
block:
|
||||
var f: File # since 'f' is a template param, it's injected implicitly
|
||||
...
|
||||
|
|
@ -298,7 +297,7 @@ rewritten to ``f(x)``. Therefore the dot syntax has some limiations when it
|
|||
is used to invoke templates/macros:
|
||||
|
||||
.. code-block:: nim
|
||||
template declareVar(name: expr): stmt =
|
||||
template declareVar(name: untyped) =
|
||||
const name {.inject.} = 45
|
||||
|
||||
# Doesn't compile:
|
||||
|
|
@ -325,8 +324,7 @@ Macros
|
|||
======
|
||||
|
||||
A macro is a special kind of low level template. Macros can be used
|
||||
to implement `domain specific languages`:idx:. Like templates, macros come in
|
||||
the 2 flavors *immediate* and *ordinary*.
|
||||
to implement `domain specific languages`:idx:.
|
||||
|
||||
While macros enable advanced compile-time code transformations, they
|
||||
cannot change Nim's syntax. However, this is no real restriction because
|
||||
|
|
@ -351,7 +349,7 @@ variable number of arguments:
|
|||
# ``macros`` module:
|
||||
import macros
|
||||
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
macro debug(n: varargs[untyped]): untyped =
|
||||
# `n` is a Nim AST that contains the whole macro invocation
|
||||
# this macro returns a list of statements:
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
|
|
@ -406,7 +404,7 @@ builtin can be used for that:
|
|||
.. code-block:: nim
|
||||
import macros
|
||||
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
macro debug(n: varargs[typed]): untyped =
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
for i in 0..n.len-1:
|
||||
# we can bind symbols in scope via 'bindSym':
|
||||
|
|
@ -454,7 +452,7 @@ regular expressions:
|
|||
.. code-block:: nim
|
||||
import macros
|
||||
|
||||
macro case_token(n: stmt): stmt =
|
||||
macro case_token(n: untyped): untyped =
|
||||
# creates a lexical analyzer from regular expressions
|
||||
# ... (implementation is an exercise for the reader :-)
|
||||
discard
|
||||
|
|
@ -486,14 +484,14 @@ Whole routines (procs, iterators etc.) can also be passed to a template or
|
|||
a macro via the pragma notation:
|
||||
|
||||
.. code-block:: nim
|
||||
template m(s: stmt) = discard
|
||||
template m(s: untyped) = discard
|
||||
|
||||
proc p() {.m.} = discard
|
||||
|
||||
This is a simple syntactic transformation into:
|
||||
|
||||
.. code-block:: nim
|
||||
template m(s: stmt) = discard
|
||||
template m(s: untyped) = discard
|
||||
|
||||
m:
|
||||
proc p() = discard
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ The ``|`` operator
|
|||
The ``|`` operator if used as infix operator creates an ordered choice:
|
||||
|
||||
.. code-block:: nim
|
||||
template t{0|1}(): expr = 3
|
||||
template t{0|1}(): untyped = 3
|
||||
let a = 1
|
||||
# outputs 3:
|
||||
echo a
|
||||
|
|
@ -144,7 +144,7 @@ The matching is performed after the compiler performed some optimizations like
|
|||
constant folding, so the following does not work:
|
||||
|
||||
.. code-block:: nim
|
||||
template t{0|1}(): expr = 3
|
||||
template t{0|1}(): untyped = 3
|
||||
# outputs 1:
|
||||
echo 1
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ A pattern expression can be bound to a pattern parameter via the ``expr{param}``
|
|||
notation:
|
||||
|
||||
.. code-block:: nim
|
||||
template t{(0|1|2){x}}(x: expr): expr = x+1
|
||||
template t{(0|1|2){x}}(x: untyped): untyped = x+1
|
||||
let a = 1
|
||||
# outputs 2:
|
||||
echo a
|
||||
|
|
@ -173,7 +173,7 @@ The ``~`` operator
|
|||
The ``~`` operator is the **not** operator in patterns:
|
||||
|
||||
.. code-block:: nim
|
||||
template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt =
|
||||
template t{x = (~x){y} and (~x){z}}(x, y, z: bool) =
|
||||
x = y
|
||||
if x: x = z
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ to ``&(a, b, c)``:
|
|||
for i in 1..len(s)-1: result.add s[i]
|
||||
inc calls
|
||||
|
||||
template optConc{ `&&` * a }(a: string): expr = &&a
|
||||
template optConc{ `&&` * a }(a: string): untyped = &&a
|
||||
|
||||
let space = " "
|
||||
echo "my" && (space & "awe" && "some " ) && "concat"
|
||||
|
|
@ -239,7 +239,7 @@ all the arguments, but also the matched operators in reverse polish notation:
|
|||
proc mat21(): Matrix =
|
||||
result.dummy = 21
|
||||
|
||||
macro optM{ (`+`|`-`|`*`) ** a }(a: Matrix): expr =
|
||||
macro optM{ (`+`|`-`|`*`) ** a }(a: Matrix): untyped =
|
||||
echo treeRepr(a)
|
||||
result = newCall(bindSym"mat21")
|
||||
|
||||
|
|
@ -273,7 +273,7 @@ parameter is of the type ``varargs`` it is treated specially and it can match
|
|||
template optWrite{
|
||||
write(f, x)
|
||||
((write|writeLine){w})(f, y)
|
||||
}(x, y: varargs[expr], f: File, w: expr) =
|
||||
}(x, y: varargs[untyped], f: File, w: untyped) =
|
||||
w(f, x, y)
|
||||
|
||||
|
||||
|
|
@ -288,8 +288,8 @@ implemented with term rewriting:
|
|||
proc p(x, y: int; cond: bool): int =
|
||||
result = if cond: x + y else: x - y
|
||||
|
||||
template optP1{p(x, y, true)}(x, y: expr): expr = x + y
|
||||
template optP2{p(x, y, false)}(x, y: expr): expr = x - y
|
||||
template optP1{p(x, y, true)}(x, y: untyped): untyped = x + y
|
||||
template optP2{p(x, y, false)}(x, y: untyped): untyped = x - y
|
||||
|
||||
|
||||
Example: Hoisting
|
||||
|
|
|
|||
|
|
@ -539,12 +539,12 @@ not wrapped in another implicit array construction:
|
|||
takeV([123, 2, 1]) # takeV's T is "int", not "array of int"
|
||||
|
||||
|
||||
``varargs[expr]`` is treated specially: It matches a variable list of arguments
|
||||
``varargs[typed]`` is treated specially: It matches a variable list of arguments
|
||||
of arbitrary type but *always* constructs an implicit array. This is required
|
||||
so that the builtin ``echo`` proc does what is expected:
|
||||
|
||||
.. code-block:: nim
|
||||
proc echo*(x: varargs[expr, `$`]) {...}
|
||||
proc echo*(x: varargs[typed, `$`]) {...}
|
||||
|
||||
echo @[1, 2, 3]
|
||||
# prints "@[1, 2, 3]" and not "123"
|
||||
|
|
@ -1082,7 +1082,7 @@ But it seems all this boilerplate code needs to be repeated for the ``Euro``
|
|||
currency. This can be solved with templates_.
|
||||
|
||||
.. code-block:: nim
|
||||
template additive(typ: typedesc): stmt =
|
||||
template additive(typ: typedesc) =
|
||||
proc `+` *(x, y: typ): typ {.borrow.}
|
||||
proc `-` *(x, y: typ): typ {.borrow.}
|
||||
|
||||
|
|
@ -1090,18 +1090,18 @@ currency. This can be solved with templates_.
|
|||
proc `+` *(x: typ): typ {.borrow.}
|
||||
proc `-` *(x: typ): typ {.borrow.}
|
||||
|
||||
template multiplicative(typ, base: typedesc): stmt =
|
||||
template multiplicative(typ, base: typedesc) =
|
||||
proc `*` *(x: typ, y: base): typ {.borrow.}
|
||||
proc `*` *(x: base, y: typ): typ {.borrow.}
|
||||
proc `div` *(x: typ, y: base): typ {.borrow.}
|
||||
proc `mod` *(x: typ, y: base): typ {.borrow.}
|
||||
|
||||
template comparable(typ: typedesc): stmt =
|
||||
template comparable(typ: typedesc) =
|
||||
proc `<` * (x, y: typ): bool {.borrow.}
|
||||
proc `<=` * (x, y: typ): bool {.borrow.}
|
||||
proc `==` * (x, y: typ): bool {.borrow.}
|
||||
|
||||
template defineCurrency(typ, base: expr): stmt =
|
||||
template defineCurrency(typ, base: untyped) =
|
||||
type
|
||||
typ* = distinct base
|
||||
additive(typ)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue