test the snippets in tut2.rst

This commit is contained in:
Araq 2017-11-28 01:25:59 +01:00
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: ``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) =