summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2017-10-17 12:46:49 +0200
committerAraq <rumpf_a@web.de>2017-10-17 12:46:49 +0200
commit45d74f408151f21f1593bfc04bd29ea7509ddae9 (patch)
tree3fa1400ea556c6295977d25f87b3f25643ce5b12 /compiler
parent7ee825a6e5979a23cb0e0323f8d8069edc3285ba (diff)
downloadNim-45d74f408151f21f1593bfc04bd29ea7509ddae9.tar.gz
destructors: preparations for upcoming changes
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/destroyer.nim3
-rw-r--r--compiler/semasgn.nim12
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/semstmts.nim1
-rw-r--r--compiler/semtypinst.nim6
7 files changed, 20 insertions, 8 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 6519b698a..cdc78be74 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1663,3 +1663,5 @@ when false:
     if n.isNil: return true
     for i in 0 ..< n.safeLen:
       if n[i].containsNil: return true
+
+template hasDestructor*(t: PType): bool = tfHasAsgn in t.flags
diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim
index afa2e5e50..f97c44861 100644
--- a/compiler/destroyer.nim
+++ b/compiler/destroyer.nim
@@ -95,8 +95,6 @@ import
   intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
   strutils, options, dfa, lowerings
 
-template hasDestructor(t: PType): bool = tfHasAsgn in t.flags
-
 const
   InterestingSyms = {skVar, skResult, skLet}
 
@@ -253,6 +251,7 @@ proc p(n: PNode; c: var Con): PNode =
       result = copyNode(n)
       recurse(n, result)
   of nkAsgn, nkFastAsgn:
+    # XXX if special, call special operator
     if n[0].kind == nkSym and interestingSym(n[0].sym):
       result = moveOrCopy(n[0], n[1], c)
     else:
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index caed11341..27626a1d0 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -109,7 +109,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
       styleCheckUse(c.info, op)
       body.add newOpCall(op, x)
       result = true
-  of attachedAsgn:
+  of attachedAsgn, attachedSink:
     if tfHasAsgn in t.flags:
       var op: PSym
       if sameType(t, c.asgnForType):
@@ -285,3 +285,13 @@ proc getAsgnOrLiftBody(c: PContext; typ: PType; info: TLineInfo): PSym =
 proc overloadedAsgn(c: PContext; dest, src: PNode): PNode =
   let a = getAsgnOrLiftBody(c, dest.typ, dest.info)
   result = newAsgnCall(c, a, dest, src)
+
+proc liftTypeBoundOps*(c: PContext; typ: PType) =
+  ## In the semantic pass this is called in strategic places
+  ## to ensure we lift assignment, destructors and moves properly.
+  ## Since this is done in the sem* routines generics already have
+  ## been resolved for us and do not complicate the logic any further.
+  ## We have to ensure that the 'tfHasDesctructor' flags bubbles up
+  ## in the generic instantiations though.
+  ## The later 'destroyer' pass depends on it.
+  if not newDestructors or not hasDestructor(typ): return
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index a3f0f715b..8b5803a7f 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -70,6 +70,7 @@ type
 
   TTypeAttachedOp* = enum
     attachedAsgn,
+    attachedSink,
     attachedDeepCopy,
     attachedDestructor
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 180754168..465b09814 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -670,6 +670,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
     analyseIfAddressTakenInCall(c, result)
     if callee.magic != mNone:
       result = magicsAfterOverloadResolution(c, result, flags)
+    if result.typ != nil: liftTypeBoundOps(c, result.typ)
   if c.matchedConcept == nil:
     result = evalAtCompileTime(c, result)
 
@@ -1390,6 +1391,8 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
       if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
           mode != noOverloadedAsgn:
         return overloadedAsgn(c, lhs, n.sons[1])
+    else:
+      liftTypeBoundOps(c, lhs.typ)
 
     fixAbstractType(c, n)
     asgnToResultVar(c, n, n.sons[0], n.sons[1])
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c6e03cef3..3c26be89e 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -553,6 +553,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
     # this can only happen for errornous var statements:
     if typ == nil: continue
     typeAllowedCheck(a.info, typ, symkind)
+    liftTypeBoundOps(c, typ)
     var tup = skipTypes(typ, {tyGenericInst, tyAlias})
     if a.kind == nkVarTuple:
       if tup.kind != tyTuple:
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 172a557b3..5d0f0177c 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -363,11 +363,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
         # '=' 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)
+    if not newDestructors: typeBound(assignment)
     let methods = skipTypes(bbody, abstractPtrs).methods
     for col, meth in items(methods):
       # we instantiate the known methods belonging to that type, this causes
efault.Background(line.bg).Foreground(line.fg) ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', style) ctx.Printf(0, 0, style, "%s", line.message) } func (status *StatusLine) Set(text string) *StatusMessage { status.fallback = StatusMessage{ bg: tcell.ColorWhite, fg: tcell.ColorBlack, message: text, } status.Invalidate() return &status.fallback } func (status *StatusLine) Push(text string, expiry time.Duration) *StatusMessage { msg := &StatusMessage{ bg: tcell.ColorWhite, fg: tcell.ColorBlack, message: text, } status.stack = append(status.stack, msg) go (func() { time.Sleep(expiry) for i, m := range status.stack { if m == msg { status.stack = append(status.stack[:i], status.stack[i+1:]...) break } } status.Invalidate() })() return msg } func (msg *StatusMessage) Color(bg tcell.Color, fg tcell.Color) { msg.bg = bg msg.fg = fg }