test the snippets in tut2.rst
This commit is contained in:
parent
5d2e86ea1a
commit
58c3e5d2f5
1 changed files with 37 additions and 15 deletions
52
doc/tut2.rst
52
doc/tut2.rst
|
|
@ -55,6 +55,7 @@ Objects have access to their type at runtime. There is an
|
||||||
``of`` operator that can be used to check the object's type:
|
``of`` operator that can be used to check the object's type:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
type
|
type
|
||||||
Person = ref object of RootObj
|
Person = ref object of RootObj
|
||||||
name*: string # the * means that `name` is accessible from other modules
|
name*: string # the * means that `name` is accessible from other modules
|
||||||
|
|
@ -103,6 +104,7 @@ would require arbitrary symbol lookahead which slows down compilation.)
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
type
|
type
|
||||||
Node = ref object # a reference to an object with the following field:
|
Node = ref object # a reference to an object with the following field:
|
||||||
le, ri: Node # left and right subtrees
|
le, ri: Node # left and right subtrees
|
||||||
|
|
@ -144,6 +146,7 @@ variant types are needed.
|
||||||
An example:
|
An example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
|
||||||
# This is an example how an abstract syntax tree could be modelled in Nim
|
# This is an example how an abstract syntax tree could be modelled in Nim
|
||||||
type
|
type
|
||||||
|
|
@ -201,9 +204,11 @@ This method call syntax is not restricted to objects, it can be used
|
||||||
for any type:
|
for any type:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
import strutils
|
||||||
|
|
||||||
echo "abc".len # is the same as echo len("abc")
|
echo "abc".len # is the same as echo len("abc")
|
||||||
echo "abc".toUpper()
|
echo "abc".toUpperAscii()
|
||||||
echo({'a', 'b', 'c'}.card)
|
echo({'a', 'b', 'c'}.card)
|
||||||
stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
|
stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
|
||||||
|
|
||||||
|
|
@ -213,6 +218,7 @@ postfix notation.)
|
||||||
So "pure object oriented" code is easy to write:
|
So "pure object oriented" code is easy to write:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
import strutils, sequtils
|
import strutils, sequtils
|
||||||
|
|
||||||
stdout.writeLine("Give a list of numbers (separated by spaces): ")
|
stdout.writeLine("Give a list of numbers (separated by spaces): ")
|
||||||
|
|
@ -228,6 +234,7 @@ the same. But setting a value is different; for this a special setter syntax
|
||||||
is needed:
|
is needed:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
|
||||||
type
|
type
|
||||||
Socket* = ref object of RootObj
|
Socket* = ref object of RootObj
|
||||||
|
|
@ -252,6 +259,7 @@ The ``[]`` array access operator can be overloaded to provide
|
||||||
`array properties`:idx:\ :
|
`array properties`:idx:\ :
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
type
|
type
|
||||||
Vector* = object
|
Vector* = object
|
||||||
x, y, z: float
|
x, y, z: float
|
||||||
|
|
@ -283,23 +291,24 @@ Procedures always use static dispatch. For dynamic dispatch replace the
|
||||||
``proc`` keyword by ``method``:
|
``proc`` keyword by ``method``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
type
|
type
|
||||||
PExpr = ref object of RootObj ## abstract base class for an expression
|
Expression = ref object of RootObj ## abstract base class for an expression
|
||||||
PLiteral = ref object of PExpr
|
Literal = ref object of Expression
|
||||||
x: int
|
x: int
|
||||||
PPlusExpr = ref object of PExpr
|
PlusExpr = ref object of Expression
|
||||||
a, b: PExpr
|
a, b: Expression
|
||||||
|
|
||||||
# watch out: 'eval' relies on dynamic binding
|
# watch out: 'eval' relies on dynamic binding
|
||||||
method eval(e: PExpr): int =
|
method eval(e: Expression): int =
|
||||||
# override this base method
|
# override this base method
|
||||||
quit "to override!"
|
quit "to override!"
|
||||||
|
|
||||||
method eval(e: PLiteral): int = e.x
|
method eval(e: Literal): int = e.x
|
||||||
method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
|
method eval(e: PlusExpr): int = eval(e.a) + eval(e.b)
|
||||||
|
|
||||||
proc newLit(x: int): PLiteral = PLiteral(x: x)
|
proc newLit(x: int): Literal = Literal(x: x)
|
||||||
proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
|
proc newPlus(a, b: Expression): PlusExpr = PlusExpr(a: a, b: b)
|
||||||
|
|
||||||
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
||||||
|
|
||||||
|
|
@ -311,6 +320,7 @@ In a multi-method all parameters that have an object type are used for the
|
||||||
dispatching:
|
dispatching:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
|
||||||
type
|
type
|
||||||
Thing = ref object of RootObj
|
Thing = ref object of RootObj
|
||||||
|
|
@ -365,6 +375,7 @@ Raise statement
|
||||||
Raising an exception is done with the ``raise`` statement:
|
Raising an exception is done with the ``raise`` statement:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
var
|
var
|
||||||
e: ref OSError
|
e: ref OSError
|
||||||
new(e)
|
new(e)
|
||||||
|
|
@ -385,6 +396,9 @@ Try statement
|
||||||
The ``try`` statement handles exceptions:
|
The ``try`` statement handles exceptions:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
from strutils import parseInt
|
||||||
|
|
||||||
# read the first two lines of a text file that should contain numbers
|
# read the first two lines of a text file that should contain numbers
|
||||||
# and tries to add them
|
# and tries to add them
|
||||||
var
|
var
|
||||||
|
|
@ -479,6 +493,7 @@ with `type parameters`:idx:. They are most useful for efficient type safe
|
||||||
containers:
|
containers:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
type
|
type
|
||||||
BinaryTree*[T] = ref object # BinaryTree is a generic type with
|
BinaryTree*[T] = ref object # BinaryTree is a generic type with
|
||||||
# generic param ``T``
|
# generic param ``T``
|
||||||
|
|
@ -573,6 +588,7 @@ Templates are especially useful for lazy evaluation purposes. Consider a
|
||||||
simple proc for logging:
|
simple proc for logging:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
const
|
const
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
|
@ -590,6 +606,7 @@ evaluation for procedures is *eager*).
|
||||||
Turning the ``log`` proc into a template solves this problem:
|
Turning the ``log`` proc into a template solves this problem:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
const
|
const
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
|
@ -611,6 +628,7 @@ If the template has no explicit return type,
|
||||||
To pass a block of statements to a template, use 'untyped' for the last parameter:
|
To pass a block of statements to a template, use 'untyped' for the last parameter:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
|
||||||
template withFile(f: untyped, filename: string, mode: FileMode,
|
template withFile(f: untyped, filename: string, mode: FileMode,
|
||||||
body: untyped): typed =
|
body: untyped): typed =
|
||||||
|
|
@ -665,6 +683,7 @@ The following example implements a powerful ``debug`` command that accepts a
|
||||||
variable number of arguments:
|
variable number of arguments:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
# to work with Nim syntax trees, we need an API that is defined in the
|
# to work with Nim syntax trees, we need an API that is defined in the
|
||||||
# ``macros`` module:
|
# ``macros`` module:
|
||||||
import macros
|
import macros
|
||||||
|
|
@ -744,6 +763,7 @@ dynamic code into something that compiles statically. For the exercise we will
|
||||||
use the following snippet of code as the starting point:
|
use the following snippet of code as the starting point:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
|
||||||
import strutils, tables
|
import strutils, tables
|
||||||
|
|
||||||
|
|
@ -863,9 +883,9 @@ variables with ``cfg``. In essence, what the compiler is doing is replacing
|
||||||
the line calling the macro with the following snippet of code:
|
the line calling the macro with the following snippet of code:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
const cfgversion= "1.1"
|
const cfgversion = "1.1"
|
||||||
const cfglicenseOwner= "Hyori Lee"
|
const cfglicenseOwner = "Hyori Lee"
|
||||||
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
|
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
|
||||||
|
|
||||||
You can verify this yourself adding the line ``echo source`` somewhere at the
|
You can verify this yourself adding the line ``echo source`` somewhere at the
|
||||||
end of the macro and compiling the program. Another difference is that instead
|
end of the macro and compiling the program. Another difference is that instead
|
||||||
|
|
@ -891,12 +911,13 @@ an expression macro. Since we know that we want to generate a bunch of
|
||||||
see what the compiler *expects* from us:
|
see what the compiler *expects* from us:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
dumpTree:
|
dumpTree:
|
||||||
const cfgversion: string = "1.1"
|
const cfgversion: string = "1.1"
|
||||||
const cfglicenseOwner= "Hyori Lee"
|
const cfglicenseOwner = "Hyori Lee"
|
||||||
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
|
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
|
||||||
|
|
||||||
During compilation of the source code we should see the following lines in the
|
During compilation of the source code we should see the following lines in the
|
||||||
output (again, since this is a macro, compilation is enough, you don't have to
|
output (again, since this is a macro, compilation is enough, you don't have to
|
||||||
|
|
@ -996,6 +1017,7 @@ Lifting Procs
|
||||||
+++++++++++++
|
+++++++++++++
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
import math
|
import math
|
||||||
|
|
||||||
template liftScalarProc(fname) =
|
template liftScalarProc(fname) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue