summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/destroyer.nim40
-rw-r--r--compiler/dfa.nim8
2 files changed, 40 insertions, 8 deletions
diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim
index dd12a7966..a3d1730cd 100644
--- a/compiler/destroyer.nim
+++ b/compiler/destroyer.nim
@@ -98,9 +98,16 @@ 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); wasMoved(z)
+3.2       x = path z; body        ``x = bitwiseCopy(path z);``
+                                  do not emit `=destroy(x)`. Note: body
+                                  must not mutate ``z`` nor ``x``. All
+                                  assignments to ``x`` must be of the form
+                                  ``path z`` but the ``z`` can differ.
+                                  Neither ``z`` nor ``x`` can have the
+                                  flag ``sfAddrTaken`` to ensure no other
+                                  aliasing is going on.
 4.1       y = sinkParam           `=sink`(y, sinkParam)
 4.2       x = y                   `=`(x, y) # a copy
 5.1       f_sink(g())             f_sink(g())
@@ -108,10 +115,33 @@ Rule      Pattern                 Transformed into
 5.3       f_sink(move y)          f_sink(y); wasMoved(y) # explicit moves empties 'y'
 5.4       f_noSink(g())           var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp)
 
-Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
-  not allowed as a local variable.
-
-``move`` builtin needs to be implemented.
+Rule 3.2 describes a "cursor" variable, a variable that is only used as a
+view into some data structure. Rule 3.2 applies to value based
+datatypes like strings and sequences and also ``ref`` cursors. We
+seek to allow most forms of "scan" loops like::
+
+  var x = it
+  # scan loop:
+  while x != nil:
+    x.foo = value
+    x = x.next
+
+The difference is that ``s[i] = y`` needs to be turned into a ``mut(s)``
+for seqs and ``r.field = y`` is NOT turned into ``mut(r)`` as it doesn't
+mutate the ``r`` itself. So the above loop is turned into something like::
+
+    use it
+    def x
+  L1:
+    fork L2
+    use value
+    use x
+    def x
+  L2:
+
+Which means that ``x`` is detected as a "cursor". Rule 3.2 is not yet
+implemented and requires either DFA changes or a different analysis.
+Write-tracking also helps to compute this.
 ]##
 
 import
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index 462cf0fb7..5eef04148 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -12,9 +12,8 @@
 ## make this easier to handle: There are only 2 different branching
 ## instructions: 'goto X' is an unconditional goto, 'fork X'
 ## is a conditional goto (either the next instruction or 'X' can be
-## taken). Exhaustive case statements could be translated
-## so that the last branch is transformed into an 'else' branch, but
-## this is currently not done.
+## taken). Exhaustive case statements are translated
+## so that the last branch is transformed into an 'else' branch.
 ## ``return`` and ``break`` are all covered by 'goto'.
 ##
 ## Control flow through exception handling:
@@ -596,6 +595,9 @@ proc genCall(c: var Con; n: PNode) =
   for i in 1..<n.len:
     gen(c, n[i])
     if t != nil and i < t.len and t.sons[i].kind == tyVar:
+      # XXX This is wrong! Pass by var is a 'might def', not a 'must def'
+      # like the other defs we emit. This is not good enough for a move
+      # optimizer.
       genDef(c, n[i])
   # every call can potentially raise:
   if c.inTryStmt > 0 and canRaise(n[0]):