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)
|
1 var x; stmts var x; try stmts finally: `=destroy`(x)
|
||||||
2 x = f() `=sink`(x, f())
|
2 x = f() `=sink`(x, f())
|
||||||
|
@ -127,3 +127,39 @@ it doesn't outlive its origin.
|
||||||
# everything turned into moves:
|
# everything turned into moves:
|
||||||
let t = construct(@[construct(@[]), construct(@[])])
|
let t = construct(@[construct(@[]), construct(@[])])
|
||||||
echo t[0] # accessor does not copy the element!
|
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