Updated Destructors (rest)

This commit is contained in:
Andreas Rumpf 2018-01-04 13:26:33 +01:00
parent d6743cda74
commit 833304ebcf
1 changed files with 37 additions and 1 deletions

View File

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