further tests for var T result type; ttables test now fails :-(
This commit is contained in:
parent
72e7a98543
commit
d5dd4669df
4 changed files with 167 additions and 161 deletions
|
|
@ -178,12 +178,11 @@ proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||||
if e.kind == tyVar:
|
if e.kind == tyVar:
|
||||||
if n.sons[0].kind == nkPar:
|
if n.sons[0].kind == nkPar:
|
||||||
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
|
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
|
||||||
elif n.sons[0].kind == nkHiddenSubConv and
|
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
||||||
n.sons[0].sons[1].kind == nkPar:
|
n.sons[0].sons[1].kind == nkPar:
|
||||||
var a = n.sons[0].sons[1]
|
var a = n.sons[0].sons[1]
|
||||||
a.sons[i] = takeImplicitAddr(c, a.sons[i])
|
a.sons[i] = takeImplicitAddr(c, a.sons[i])
|
||||||
else:
|
else:
|
||||||
debug n.sons[0]
|
|
||||||
localError(n.sons[0].info, errXExpected, "tuple constructor")
|
localError(n.sons[0].info, errXExpected, "tuple constructor")
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
|
|
|
||||||
320
doc/manual.txt
320
doc/manual.txt
|
|
@ -1188,45 +1188,45 @@ currency. This can be solved with templates_.
|
||||||
DefineCurrency(TDollar, int)
|
DefineCurrency(TDollar, int)
|
||||||
DefineCurrency(TEuro, int)
|
DefineCurrency(TEuro, int)
|
||||||
|
|
||||||
|
|
||||||
Void type
|
Void type
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
The `void`:idx: type denotes the absense of any type. Parameters of
|
The `void`:idx: type denotes the absense of any type. Parameters of
|
||||||
type ``void`` are treated as non-existent, a result ``void`` type means that
|
type ``void`` are treated as non-existent, a result ``void`` type means that
|
||||||
the procedure does not return a value:
|
the procedure does not return a value:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc nothing(x, y: void): void =
|
proc nothing(x, y: void): void =
|
||||||
echo "ha"
|
echo "ha"
|
||||||
|
|
||||||
nothing() # writes "ha" to stdout
|
nothing() # writes "ha" to stdout
|
||||||
|
|
||||||
The ``void`` type is particularly useful for generic code:
|
The ``void`` type is particularly useful for generic code:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc callProc[T](p: proc (x: T), x: T) =
|
proc callProc[T](p: proc (x: T), x: T) =
|
||||||
when T is void:
|
when T is void:
|
||||||
p()
|
p()
|
||||||
else:
|
else:
|
||||||
p(x)
|
p(x)
|
||||||
|
|
||||||
proc intProc(x: int) = nil
|
proc intProc(x: int) = nil
|
||||||
proc emptyProc() = nil
|
proc emptyProc() = nil
|
||||||
|
|
||||||
callProc[int](intProc, 12)
|
callProc[int](intProc, 12)
|
||||||
callProc[void](emptyProc)
|
callProc[void](emptyProc)
|
||||||
|
|
||||||
However, a ``void`` type cannot be inferred in generic code:
|
However, a ``void`` type cannot be inferred in generic code:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
callProc(emptyProc)
|
callProc(emptyProc)
|
||||||
# Error: type mismatch: got (proc ())
|
# Error: type mismatch: got (proc ())
|
||||||
# but expected one of:
|
# but expected one of:
|
||||||
# callProc(p: proc (T), x: T)
|
# callProc(p: proc (T), x: T)
|
||||||
|
|
||||||
The ``void`` type is only valid for parameters and return types; other symbols
|
The ``void`` type is only valid for parameters and return types; other symbols
|
||||||
cannot have the type ``void``.
|
cannot have the type ``void``.
|
||||||
|
|
||||||
|
|
||||||
Type relations
|
Type relations
|
||||||
|
|
@ -1249,7 +1249,7 @@ algorithm (in pseudo-code) determines type equality:
|
||||||
incl(s, (a,b))
|
incl(s, (a,b))
|
||||||
if a.kind == b.kind:
|
if a.kind == b.kind:
|
||||||
case a.kind
|
case a.kind
|
||||||
of int, intXX, float, floatXX, char, string, cstring, pointer,
|
of int, intXX, float, floatXX, char, string, cstring, pointer,
|
||||||
bool, nil, void:
|
bool, nil, void:
|
||||||
# leaf type: kinds identical; nothing more to check
|
# leaf type: kinds identical; nothing more to check
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -2067,37 +2067,40 @@ One can use `tuple unpacking`:idx: to access the tuple's fields:
|
||||||
var (x, y) = divmod(8, 5) # tuple unpacking
|
var (x, y) = divmod(8, 5) # tuple unpacking
|
||||||
assert x == 1
|
assert x == 1
|
||||||
assert y == 3
|
assert y == 3
|
||||||
|
|
||||||
|
|
||||||
Var return type
|
Var return type
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A proc, converter or iterator may return a ``var`` type which means that the
|
A proc, converter or iterator may return a ``var`` type which means that the
|
||||||
returned value is an l-value and can be modified by the caller:
|
returned value is an l-value and can be modified by the caller:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
var g = 0
|
var g = 0
|
||||||
|
|
||||||
proc WriteAccessToG(): var int =
|
proc WriteAccessToG(): var int =
|
||||||
result = g
|
result = g
|
||||||
|
|
||||||
WriteAccessToG() = 6
|
WriteAccessToG() = 6
|
||||||
assert g == 6
|
assert g == 6
|
||||||
|
|
||||||
It is a compile time error if the implicitely introduced pointer could be
|
It is a compile time error if the implicitely introduced pointer could be
|
||||||
used to access a location beyond its lifetime:
|
used to access a location beyond its lifetime:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc WriteAccessToG(): var int =
|
proc WriteAccessToG(): var int =
|
||||||
var g = 0
|
var g = 0
|
||||||
result = g # Error!
|
result = g # Error!
|
||||||
|
|
||||||
For iterators, a component of a tuple return type can have a ``var`` type too:
|
For iterators, a component of a tuple return type can have a ``var`` type too:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
iterator modPairs(a: var seq[string]): tuple[key: int, val: var string] =
|
iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] =
|
||||||
for i in 0..a.high:
|
for i in 0..a.high:
|
||||||
yield (i, a[i])
|
yield (i, a[i])
|
||||||
|
|
||||||
|
In the standard library every name of a routine that returns a ``var`` type
|
||||||
|
starts with the prefix ``m`` per convention.
|
||||||
|
|
||||||
|
|
||||||
Overloading of the subscript operator
|
Overloading of the subscript operator
|
||||||
|
|
@ -2331,105 +2334,106 @@ Example:
|
||||||
add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and
|
add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and
|
||||||
add(root, newNode("world")) # ``add``
|
add(root, newNode("world")) # ``add``
|
||||||
for str in inorder(root):
|
for str in inorder(root):
|
||||||
|
|
||||||
writeln(stdout, str)
|
writeln(stdout, str)
|
||||||
|
|
||||||
`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types with
|
`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types with
|
||||||
`type parameters`:idx:. Depending on context, the brackets are used either to
|
`type parameters`:idx:. Depending on context, the brackets are used either to
|
||||||
introduce type parameters or to instantiate a generic proc, iterator or type.
|
introduce type parameters or to instantiate a generic proc, iterator or type.
|
||||||
|
|
||||||
|
|
||||||
Is operator
|
Is operator
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
The `is`:idx: operator checks for type equivalence at compile time. It is
|
The `is`:idx: operator checks for type equivalence at compile time. It is
|
||||||
therefore very useful for type specialization within generic code:
|
therefore very useful for type specialization within generic code:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
type
|
type
|
||||||
TTable[TKey, TValue] = object
|
TTable[TKey, TValue] = object
|
||||||
keys: seq[TKey]
|
keys: seq[TKey]
|
||||||
values: seq[TValue]
|
values: seq[TValue]
|
||||||
when not (TKey is string): # nil value for strings used for optimization
|
when not (TKey is string): # nil value for strings used for optimization
|
||||||
deletedKeys: seq[bool]
|
deletedKeys: seq[bool]
|
||||||
|
|
||||||
|
|
||||||
Type operator
|
Type operator
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
The `type`:idx: (in many other languages called `typeof`:idx:) operator can
|
The `type`:idx: (in many other languages called `typeof`:idx:) operator can
|
||||||
be used to get the type of an expression:
|
be used to get the type of an expression:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
var x = 0
|
var x = 0
|
||||||
var y: type(x) # y has type int
|
var y: type(x) # y has type int
|
||||||
|
|
||||||
|
|
||||||
Type constraints
|
Type constraints
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
`Type constraints`:idx: can be used to restrict the instantiation of a generic
|
`Type constraints`:idx: can be used to restrict the instantiation of a generic
|
||||||
type parameter. Only the specified types are valid for instantiation:
|
type parameter. Only the specified types are valid for instantiation:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc onlyIntOrString[T: int|string](x, y: T): T = nil
|
proc onlyIntOrString[T: int|string](x, y: T): T = nil
|
||||||
|
|
||||||
onlyIntOrString(45, 66) # valid
|
onlyIntOrString(45, 66) # valid
|
||||||
onlyIntOrString(56.0, 0.0) # type mismatch
|
onlyIntOrString(56.0, 0.0) # type mismatch
|
||||||
|
|
||||||
|
|
||||||
Apart from ordinary types, type constraints can also be of the
|
Apart from ordinary types, type constraints can also be of the
|
||||||
following *type classes*:
|
following *type classes*:
|
||||||
|
|
||||||
================== ===================================================
|
================== ===================================================
|
||||||
type class matches
|
type class matches
|
||||||
================== ===================================================
|
================== ===================================================
|
||||||
``object`` any object type
|
``object`` any object type
|
||||||
``tuple`` any tuple type
|
``tuple`` any tuple type
|
||||||
``enum`` any enumeration
|
``enum`` any enumeration
|
||||||
``proc`` any proc type
|
``proc`` any proc type
|
||||||
``ref`` any ``ref`` type
|
``ref`` any ``ref`` type
|
||||||
``ptr`` any ``ptr`` type
|
``ptr`` any ``ptr`` type
|
||||||
``var`` any ``var`` type
|
``var`` any ``var`` type
|
||||||
``distinct`` any distinct type
|
``distinct`` any distinct type
|
||||||
``array`` any array type
|
``array`` any array type
|
||||||
``set`` any set type
|
``set`` any set type
|
||||||
``seq`` any seq type
|
``seq`` any seq type
|
||||||
================== ===================================================
|
================== ===================================================
|
||||||
|
|
||||||
The following example is taken directly from the system module:
|
The following example is taken directly from the system module:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc `==`*[T: tuple](x, y: T): bool =
|
proc `==`*[T: tuple](x, y: T): bool =
|
||||||
## generic ``==`` operator for tuples that is lifted from the components
|
## generic ``==`` operator for tuples that is lifted from the components
|
||||||
## of `x` and `y`.
|
## of `x` and `y`.
|
||||||
for a, b in fields(x, y):
|
for a, b in fields(x, y):
|
||||||
if a != b: return false
|
if a != b: return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
Symbol lookup in generics
|
Symbol lookup in generics
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Symbols in generics are looked up in two different contexts: Both the context
|
Symbols in generics are looked up in two different contexts: Both the context
|
||||||
at definition and the context at instantiation are considered for any symbol
|
at definition and the context at instantiation are considered for any symbol
|
||||||
occuring in a generic:
|
occuring in a generic:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
type
|
type
|
||||||
TIndex = distinct int
|
TIndex = distinct int
|
||||||
|
|
||||||
proc `==` (a, b: TIndex): bool {.borrow.}
|
proc `==` (a, b: TIndex): bool {.borrow.}
|
||||||
|
|
||||||
var a = (0, 0.TIndex)
|
var a = (0, 0.TIndex)
|
||||||
var b = (0, 0.TIndex)
|
var b = (0, 0.TIndex)
|
||||||
|
|
||||||
echo a == b # works!
|
echo a == b # works!
|
||||||
|
|
||||||
In the example the generic ``==`` for tuples uses the ``==`` operators of the
|
In the example the generic ``==`` for tuples uses the ``==`` operators of the
|
||||||
tuple's components. However, the ``==`` for the ``TIndex`` type is
|
tuple's components. However, the ``==`` for the ``TIndex`` type is
|
||||||
defined *after* the ``==`` for tuples; yet the example compiles as the
|
defined *after* the ``==`` for tuples; yet the example compiles as the
|
||||||
instantiation takes the currently defined symbols into account too.
|
instantiation takes the currently defined symbols into account too.
|
||||||
|
|
||||||
|
|
||||||
Templates
|
Templates
|
||||||
---------
|
---------
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ block orderedTableTest1:
|
||||||
assert val == data[i][1]
|
assert val == data[i][1]
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
|
for key, val in mpairs(t): val = 99
|
||||||
|
for val in mvalues(t): assert val == 99
|
||||||
|
|
||||||
block countTableTest1:
|
block countTableTest1:
|
||||||
var s = data.toTable
|
var s = data.toTable
|
||||||
var t = initCountTable[string]()
|
var t = initCountTable[string]()
|
||||||
|
|
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -1,7 +1,7 @@
|
||||||
Version 0.8.14
|
Version 0.8.14
|
||||||
==============
|
==============
|
||||||
|
|
||||||
- test ``m*`` for generics; document 'm' convention
|
- test ``m*`` for generics
|
||||||
- optional indentation for 'case' statement
|
- optional indentation for 'case' statement
|
||||||
- make threadvar efficient again on linux after testing
|
- make threadvar efficient again on linux after testing
|
||||||
- test the sort implementation again
|
- test the sort implementation again
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue