further tests for var T result type; ttables test now fails :-(

This commit is contained in:
Araq 2011-08-10 01:16:32 +02:00
commit d5dd4669df
4 changed files with 167 additions and 161 deletions

View file

@ -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

View file

@ -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
--------- ---------

View file

@ -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]()

View file

@ -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