Updated Destructors (rest)
This commit is contained in:
parent
d6743cda74
commit
833304ebcf
|
@ -6,7 +6,7 @@ Rewrite rules (simplified)
|
|||
==========================
|
||||
|
||||
======== ==================== ===========================================================
|
||||
Rule Pattern Meaning
|
||||
Rule Pattern Transformed into
|
||||
======== ==================== ===========================================================
|
||||
1 var x; stmts var x; try stmts finally: `=destroy`(x)
|
||||
2 x = f() `=sink`(x, f())
|
||||
|
@ -127,3 +127,39 @@ it doesn't outlive its origin.
|
|||
# everything turned into moves:
|
||||
let t = construct(@[construct(@[]), construct(@[])])
|
||||
echo t[0] # accessor does not copy the element!
|
||||
|
||||
|
||||
``sink T`` and ``lent T`` introduce further rewrite rules but lead to more efficient code. Even better, these rules optimize away create/copy <-> destroy pairs and so can also make atomic reference counting more efficient by eliminating incref <-> decref pairs.
|
||||
|
||||
|
||||
Rewrite rules (extended)
|
||||
========================
|
||||
|
||||
======== ==================== ===========================================================
|
||||
Rule Pattern Transformed into
|
||||
======== ==================== ===========================================================
|
||||
1.1 var x: T; stmts var x: T; try stmts finally: `=destroy`(x)
|
||||
1.2 var x: sink T; stmts var x: sink T; stmts; ensureEmpty(x)
|
||||
2 x = f() `=sink`(x, f())
|
||||
3 x = lastReadOf z `=sink`(x, z)
|
||||
4.1 sinkParam = y `=sink`(sinkParam, y)
|
||||
4.2 x = y `=`(x, y) # a copy
|
||||
5.1 f_sink(g()) f_sink(g())
|
||||
5.2 f_sink(y) f_sink(y); reset(y)
|
||||
# 'reset(y)' for locals usually optimized away
|
||||
5.3 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp)
|
||||
======== ==================== ===========================================================
|
||||
|
||||
``sink T`` also affects overloading resolution rules; by the time type checking is performed we have no control flow graph yet so the property ``lastReadOf z`` is not available. However, passing a call expression ``f()`` to a ``g`` taking a sink parameter is a syntactic property and so is available for overloading resolution. Thus I propose the following rule:
|
||||
|
||||
.. code-block:: nim
|
||||
proc add(c: var Container; x: T) # version A
|
||||
proc add(c: var Container; x: sink T) # version B
|
||||
|
||||
var c: Container
|
||||
var x: T
|
||||
c.add x # calls version A
|
||||
c.add f() # calls version B
|
||||
# object construction counts as proc call:
|
||||
c.add T() # calls version B
|
||||
|
||||
|
|
Loading…
Reference in New Issue