test the snippets in tut2.rst

This commit is contained in:
Araq
2017-11-28 01:25:59 +01:00
parent 5d2e86ea1a
commit 58c3e5d2f5

View File

@@ -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:
.. code-block:: nim
:test: "nim c $1"
type
Person = ref object of RootObj
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:
.. code-block:: nim
:test: "nim c $1"
type
Node = ref object # a reference to an object with the following field:
le, ri: Node # left and right subtrees
@@ -144,6 +146,7 @@ variant types are needed.
An example:
.. code-block:: nim
:test: "nim c $1"
# This is an example how an abstract syntax tree could be modelled in Nim
type
@@ -201,9 +204,11 @@ This method call syntax is not restricted to objects, it can be used
for any type:
.. code-block:: nim
:test: "nim c $1"
import strutils
echo "abc".len # is the same as echo len("abc")
echo "abc".toUpper()
echo "abc".toUpperAscii()
echo({'a', 'b', 'c'}.card)
stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
@@ -213,6 +218,7 @@ postfix notation.)
So "pure object oriented" code is easy to write:
.. code-block:: nim
:test: "nim c $1"
import strutils, sequtils
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:
.. code-block:: nim
:test: "nim c $1"
type
Socket* = ref object of RootObj
@@ -252,6 +259,7 @@ The ``[]`` array access operator can be overloaded to provide
`array properties`:idx:\ :
.. code-block:: nim
:test: "nim c $1"
type
Vector* = object
x, y, z: float
@@ -283,23 +291,24 @@ Procedures always use static dispatch. For dynamic dispatch replace the
``proc`` keyword by ``method``:
.. code-block:: nim
:test: "nim c $1"
type
PExpr = ref object of RootObj ## abstract base class for an expression
PLiteral = ref object of PExpr
Expression = ref object of RootObj ## abstract base class for an expression
Literal = ref object of Expression
x: int
PPlusExpr = ref object of PExpr
a, b: PExpr
PlusExpr = ref object of Expression
a, b: Expression
# watch out: 'eval' relies on dynamic binding
method eval(e: PExpr): int =
method eval(e: Expression): int =
# override this base method
quit "to override!"
method eval(e: PLiteral): int = e.x
method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
method eval(e: Literal): int = e.x
method eval(e: PlusExpr): int = eval(e.a) + eval(e.b)
proc newLit(x: int): PLiteral = PLiteral(x: x)
proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
proc newLit(x: int): Literal = Literal(x: x)
proc newPlus(a, b: Expression): PlusExpr = PlusExpr(a: a, b: b)
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:
.. code-block:: nim
:test: "nim c $1"
type
Thing = ref object of RootObj
@@ -365,6 +375,7 @@ Raise statement
Raising an exception is done with the ``raise`` statement:
.. code-block:: nim
:test: "nim c $1"
var
e: ref OSError
new(e)
@@ -385,6 +396,9 @@ Try statement
The ``try`` statement handles exceptions:
.. code-block:: nim
:test: "nim c $1"
from strutils import parseInt
# read the first two lines of a text file that should contain numbers
# and tries to add them
var
@@ -479,6 +493,7 @@ with `type parameters`:idx:. They are most useful for efficient type safe
containers:
.. code-block:: nim
:test: "nim c $1"
type
BinaryTree*[T] = ref object # BinaryTree is a generic type with
# generic param ``T``
@@ -573,6 +588,7 @@ Templates are especially useful for lazy evaluation purposes. Consider a
simple proc for logging:
.. code-block:: nim
:test: "nim c $1"
const
debug = true
@@ -590,6 +606,7 @@ evaluation for procedures is *eager*).
Turning the ``log`` proc into a template solves this problem:
.. code-block:: nim
:test: "nim c $1"
const
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:
.. code-block:: nim
:test: "nim c $1"
template withFile(f: untyped, filename: string, mode: FileMode,
body: untyped): typed =
@@ -665,6 +683,7 @@ The following example implements a powerful ``debug`` command that accepts a
variable number of arguments:
.. code-block:: nim
:test: "nim c $1"
# to work with Nim syntax trees, we need an API that is defined in the
# ``macros`` module:
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:
.. code-block:: nim
:test: "nim c $1"
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:
.. code-block:: nim
const cfgversion= "1.1"
const cfglicenseOwner= "Hyori Lee"
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
const cfgversion = "1.1"
const cfglicenseOwner = "Hyori Lee"
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
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
@@ -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:
.. code-block:: nim
:test: "nim c $1"
import macros
dumpTree:
const cfgversion: string = "1.1"
const cfglicenseOwner= "Hyori Lee"
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
const cfglicenseOwner = "Hyori Lee"
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
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
@@ -996,6 +1017,7 @@ Lifting Procs
+++++++++++++
.. code-block:: nim
:test: "nim c $1"
import math
template liftScalarProc(fname) =