documentation for 'var T' as return type

This commit is contained in:
Araq 2011-08-01 00:21:16 +02:00
commit dd99fe61c0
5 changed files with 52 additions and 23 deletions

View file

@ -217,9 +217,6 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
addSon(result, typ) addSon(result, typ)
proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
var
elem: PType
isConcrete: bool
if s.typ == nil or s.typ.kind != tyGenericBody: if s.typ == nil or s.typ.kind != tyGenericBody:
GlobalError(n.info, errCannotInstantiateX, s.name.s) GlobalError(n.info, errCannotInstantiateX, s.name.s)
result = newOrPrevType(tyGenericInvokation, prev, c) result = newOrPrevType(tyGenericInvokation, prev, c)
@ -227,9 +224,9 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
if sonsLen(n) != sonsLen(s.typ): if sonsLen(n) != sonsLen(s.typ):
GlobalError(n.info, errWrongNumberOfArguments) GlobalError(n.info, errWrongNumberOfArguments)
addSon(result, s.typ) addSon(result, s.typ)
isConcrete = true # iterate over arguments: var isConcrete = true # iterate over arguments:
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
elem = semTypeNode(c, n.sons[i], nil) var elem = semTypeNode(c, n.sons[i], nil)
if elem.kind == tyGenericParam: isConcrete = false if elem.kind == tyGenericParam: isConcrete = false
addSon(result, elem) addSon(result, elem)
if isConcrete: if isConcrete:
@ -542,26 +539,26 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
result = newOrPrevType(tyProc, prev, c) result = newOrPrevType(tyProc, prev, c)
result.callConv = lastOptionEntry(c).defaultCC result.callConv = lastOptionEntry(c).defaultCC
result.n = newNodeI(nkFormalParams, n.info) result.n = newNodeI(nkFormalParams, n.info)
if (genericParams != nil) and (sonsLen(genericParams) == 0): if genericParams != nil and sonsLen(genericParams) == 0:
cl = initIntSet() cl = initIntSet()
addSon(result, nil) # return type addSon(result, nil) # return type
res = newNodeI(nkType, n.info) res = newNodeI(nkType, n.info)
addSon(result.n, res) addSon(result.n, res)
var check = initIntSet() var check = initIntSet()
var counter = 0 var counter = 0
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if a.kind != nkIdentDefs: IllFormedAst(a) if a.kind != nkIdentDefs: IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
var length = sonsLen(a) var length = sonsLen(a)
if a.sons[length - 2].kind != nkEmpty: if a.sons[length-2].kind != nkEmpty:
typ = paramType(c, a.sons[length - 2], genericParams, cl) typ = paramType(c, a.sons[length-2], genericParams, cl)
else: else:
typ = nil typ = nil
if a.sons[length - 1].kind != nkEmpty: if a.sons[length-1].kind != nkEmpty:
def = semExprWithType(c, a.sons[length - 1]) def = semExprWithType(c, a.sons[length-1])
# check type compability between def.typ and typ: # check type compability between def.typ and typ:
if typ == nil: if typ == nil:
typ = def.typ typ = def.typ
elif def != nil: elif def != nil:
# and def.typ != nil and def.typ.kind != tyNone: # and def.typ != nil and def.typ.kind != tyNone:
@ -571,7 +568,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
else: else:
def = ast.emptyNode def = ast.emptyNode
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
for j in countup(0, length - 3): for j in countup(0, length-3):
var arg = newSymS(skParam, a.sons[j], c) var arg = newSymS(skParam, a.sons[j], c)
arg.typ = typ arg.typ = typ
arg.position = counter arg.position = counter
@ -647,7 +644,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
prev.id = s.typ.id prev.id = s.typ.id
result = prev result = prev
of nkSym: of nkSym:
if (n.sym.kind == skType) and (n.sym.typ != nil): if n.sym.kind == skType and n.sym.typ != nil:
var t = n.sym.typ var t = n.sym.typ
if prev == nil: if prev == nil:
result = t result = t

View file

@ -2067,6 +2067,37 @@ 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
~~~~~~~~~~~~~~~
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:
.. code-block:: nimrod
var g = 0
proc WriteAccessToG(): var int =
result = g
WriteAccessToG() = 6
assert g == 6
It is a compile time error if the implicitely introduced pointer could be
used to access a location beyond its lifetime:
.. code-block:: nimrod
proc WriteAccessToG(): var int =
var g = 0
result = g # Error!
For iterators, a component of a tuple return type can have a ``var`` type too:
.. code-block:: nimrod
iterator modPairs(a: var seq[string]): tuple[key: int, val: var string] =
for i in 0..a.high:
yield (i, a[i])
Overloading of the subscript operator Overloading of the subscript operator
@ -2340,7 +2371,7 @@ Type constraints
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 = ... 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

View file

@ -5,16 +5,18 @@ type
type type
TEventEmitter = object of TObject TEventEmitter = object of TObject
events*: TTable[string, TDoublyLinkedList[proc(e: TEventArgs)]] events*: TTable[string, TDoublyLinkedList[proc(e: TEventArgs)]]
proc emit*(emitter: TEventEmitter, event: string, args: TEventArgs) =
for func in nodes(emitter.events[event]):
func.value(args) #call function with args.
proc on*(emitter: var TEventEmitter, event: string, func: proc(e: TEventArgs)) = proc on*(emitter: var TEventEmitter, event: string, func: proc(e: TEventArgs)) =
if not hasKey(emitter.events, event): if not hasKey(emitter.events, event):
var list: TDoublyLinkedList[proc(e: TEventArgs)] var list: TDoublyLinkedList[proc(e: TEventArgs)]
add(emitter.events,event,list) #if not, add it. add(emitter.events,event,list) #if not, add it.
#append(emitter.events[event], func) #append(emitter.events[event], func)
#adds the function to the event's list. I get a error here too. #adds the function to the event's list. I get a error here too.
proc emit*(emitter: TEventEmitter, event: string, args: TEventArgs) =
for func in nodes(emitter.events[event]):
func.value(args) #call function with args.
proc initEmitter(emitter: TEventEmitter) = proc initEmitter(emitter: TEventEmitter) =
emitter.events = initTable[string, TDoublyLinkedList[proc(e: TEventArgs)]]() emitter.events = initTable[string, TDoublyLinkedList[proc(e: TEventArgs)]]()

View file

@ -2,9 +2,7 @@ Version 0.8.14
============== ==============
- fix serious bug that keeps teventemitter from compiling - fix serious bug that keeps teventemitter from compiling
- ``var T`` as a return type: - ``var T`` as a return type: add ``modGet`` for generics
* add ``modGet`` for generics
* documentation
- 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
@ -73,7 +71,7 @@ Library
Low priority Low priority
------------ ------------
- ``when validCode(proc())`` for generic code - ``with proc `+`(x, y: T): T`` for generic code
- find a way for easy constructors and destructors; (destructors are much more - find a way for easy constructors and destructors; (destructors are much more
important than constructors) important than constructors)
- code generated for type information is wasteful - code generated for type information is wasteful

View file

@ -41,6 +41,7 @@ Language Additions
- Added new ``is`` and ``of`` operators. - Added new ``is`` and ``of`` operators.
- The built-in type ``void`` can be used to denote the absense of any type. - The built-in type ``void`` can be used to denote the absense of any type.
This is only needed in generic contexts. This is only needed in generic contexts.
- Return types may be of the type ``var T`` to return an l-value.
Compiler Additions Compiler Additions