summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-10-14 09:32:57 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-10-14 20:37:49 +0200
commit8780d25e038ed6ca6815f3ed4aa6a7a58416714b (patch)
treeffa8aa46e6821e084673f0278a47fac1423566ee /compiler
parent4eaa2bf15d1f59311b2fb7efac39cd652f9b2a42 (diff)
downloadNim-8780d25e038ed6ca6815f3ed4aa6a7a58416714b.tar.gz
minor refactorings for better destructors
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/nversion.nim2
-rw-r--r--compiler/rodread.nim7
-rw-r--r--compiler/rodwrite.nim8
-rw-r--r--compiler/semasgn.nim6
-rw-r--r--compiler/semstmts.nim27
-rw-r--r--compiler/semtypinst.nim16
7 files changed, 51 insertions, 17 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index a6f774790..6519b698a 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1081,7 +1081,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
   result.info = info
   result.options = gOptions
   result.owner = owner
-  result.offset = - 1
+  result.offset = -1
   result.id = getID()
   when debugIds:
     registerId(result)
diff --git a/compiler/nversion.nim b/compiler/nversion.nim
index 4d4fe6c95..85265a7c0 100644
--- a/compiler/nversion.nim
+++ b/compiler/nversion.nim
@@ -13,5 +13,5 @@
 const
   MaxSetElements* = 1 shl 16  # (2^16) to support unicode character sets?
   VersionAsString* = system.NimVersion
-  RodFileVersion* = "1222"       # modify this if the rod-format changes!
+  RodFileVersion* = "1223"       # modify this if the rod-format changes!
 
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index 31b54d760..2546aa77a 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -336,10 +336,13 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
   if r.s[r.pos] == '\17':
     inc(r.pos)
     result.assignment = rrGetSym(r, decodeVInt(r.s, r.pos), info)
-  while r.s[r.pos] == '\18':
+  if r.s[r.pos] == '\18':
+    inc(r.pos)
+    result.sink = rrGetSym(r, decodeVInt(r.s, r.pos), info)
+  while r.s[r.pos] == '\19':
     inc(r.pos)
     let x = decodeVInt(r.s, r.pos)
-    doAssert r.s[r.pos] == '\19'
+    doAssert r.s[r.pos] == '\20'
     inc(r.pos)
     let y = rrGetSym(r, decodeVInt(r.s, r.pos), info)
     result.methods.safeAdd((x, y))
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index fb50c6473..1bc136acf 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -245,10 +245,14 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
     add(result, '\17')
     encodeVInt(t.assignment.id, result)
     pushSym(w, t.assignment)
-  for i, s in items(t.methods):
+  if t.sink != nil:
     add(result, '\18')
-    encodeVInt(i, result)
+    encodeVInt(t.sink.id, result)
+    pushSym(w, t.sink)
+  for i, s in items(t.methods):
     add(result, '\19')
+    encodeVInt(i, result)
+    add(result, '\20')
     encodeVInt(s.id, result)
     pushSym(w, s)
   encodeLoc(w, t.loc, result)
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index dbb2a140b..caed11341 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -92,13 +92,13 @@ proc newAsgnStmt(le, ri: PNode): PNode =
   result.sons[0] = le
   result.sons[1] = ri
 
-proc newDestructorCall(op: PSym; x: PNode): PNode =
+proc newOpCall(op: PSym; x: PNode): PNode =
   result = newNodeIT(nkCall, x.info, op.typ.sons[0])
   result.add(newSymNode(op))
   result.add x
 
 proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
-  result = newAsgnStmt(x, newDestructorCall(op, y))
+  result = newAsgnStmt(x, newOpCall(op, y))
 
 proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
   case c.kind
@@ -107,7 +107,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
     if op != nil:
       markUsed(c.info, op, c.c.graph.usageSym)
       styleCheckUse(c.info, op)
-      body.add newDestructorCall(op, x)
+      body.add newOpCall(op, x)
       result = true
   of attachedAsgn:
     if tfHasAsgn in t.flags:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 3e6e918f1..c6e03cef3 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1277,9 +1277,30 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
 proc semOverride(c: PContext, s: PSym, n: PNode) =
   case s.name.s.normalize
   of "destroy", "=destroy":
-    doDestructorStuff(c, s, n)
-    if not newDestructors and not experimentalMode(c):
-      localError n.info, "use the {.experimental.} pragma to enable destructors"
+    if newDestructors:
+      let t = s.typ
+      var noError = false
+      if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
+        var obj = t.sons[1].sons[0]
+        while true:
+          incl(obj.flags, tfHasAsgn)
+          if obj.kind == tyGenericBody: obj = obj.lastSon
+          elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
+          else: break
+        if obj.kind in {tyObject, tyDistinct}:
+          if obj.destructor.isNil:
+            obj.destructor = s
+          else:
+            localError(n.info, errGenerated,
+              "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
+          noError = true
+      if not noError:
+        localError(n.info, errGenerated,
+          "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
+    else:
+      doDestructorStuff(c, s, n)
+      if not experimentalMode(c):
+        localError n.info, "use the {.experimental.} pragma to enable destructors"
     incl(s.flags, sfUsed)
   of "deepcopy", "=deepcopy":
     if s.typ.len == 2 and
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index a3953d87e..172a557b3 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -357,11 +357,17 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
         assert newbody.kind in {tyRef, tyPtr}
         assert newbody.lastSon.typeInst == nil
         newbody.lastSon.typeInst = result
-    let asgn = newbody.assignment
-    if asgn != nil and sfFromGeneric notin asgn.flags:
-      # '=' needs to be instantiated for generics when the type is constructed:
-      newbody.assignment = cl.c.instTypeBoundOp(cl.c, asgn, result, cl.info,
-                                                attachedAsgn, 1)
+    template typeBound(field) =
+      let opr = newbody.field
+      if opr != nil and sfFromGeneric notin opr.flags:
+        # '=' needs to be instantiated for generics when the type is constructed:
+        newbody.field = cl.c.instTypeBoundOp(cl.c, opr, result, cl.info,
+                                             attachedAsgn, 1)
+    # we need to produce the destructor first here because generated '='
+    # and '=sink' operators can rely on it:
+    if newDestructors: typeBound(destructor)
+    typeBound(assignment)
+    typeBound(sink)
     let methods = skipTypes(bbody, abstractPtrs).methods
     for col, meth in items(methods):
       # we instantiate the known methods belonging to that type, this causes