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
@ -891,6 +911,7 @@ 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:
@ -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) =