summary refs log tree commit diff stats
path: root/compiler/semdestruct.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semdestruct.nim')
-rw-r--r--compiler/semdestruct.nim185
1 files changed, 0 insertions, 185 deletions
diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim
deleted file mode 100644
index b16bf004f..000000000
--- a/compiler/semdestruct.nim
+++ /dev/null
@@ -1,185 +0,0 @@
-#
-#
-#           The Nim Compiler
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements destructors.
-
-# included from sem.nim
-
-# special marker values that indicates that we are
-# 1) AnalyzingDestructor: currently analyzing the type for destructor
-# generation (needed for recursive types)
-# 2) DestructorIsTrivial: completed the analysis before and determined
-# that the type has a trivial destructor
-var analyzingDestructor, destructorIsTrivial: PSym
-new(analyzingDestructor)
-new(destructorIsTrivial)
-
-var
-  destructorName = getIdent"destroy_"
-  destructorParam = getIdent"this_"
-
-proc instantiateDestructor(c: PContext, typ: PType): PType
-
-proc doDestructorStuff(c: PContext, s: PSym, n: PNode) =
-  var t = s.typ.sons[1].skipTypes({tyVar})
-  if t.kind == tyGenericInvocation:
-    for i in 1 ..< t.sonsLen:
-      if t.sons[i].kind != tyGenericParam:
-        localError(n.info, errDestructorNotGenericEnough)
-        return
-    t = t.base
-  elif t.kind == tyCompositeTypeClass:
-    t = t.base
-    if t.kind != tyGenericBody:
-      localError(n.info, errDestructorNotGenericEnough)
-      return
-
-  t.destructor = s
-  # automatically insert calls to base classes' destructors
-  if n.sons[bodyPos].kind != nkEmpty:
-    for i in countup(0, t.sonsLen - 1):
-      # when inheriting directly from object
-      # there will be a single nil son
-      if t.sons[i] == nil: continue
-      let destructableT = instantiateDestructor(c, t.sons[i])
-      if destructableT != nil:
-        n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[
-            useSym(destructableT.destructor, c.graph.usageSym),
-            n.sons[paramsPos][1][0]]))
-
-proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode
-
-proc destroySym(c: PContext, field: PSym, holder: PNode): PNode =
-  let destructableT = instantiateDestructor(c, field.typ)
-  if destructableT != nil:
-    result = newNode(nkCall, field.info, @[
-      useSym(destructableT.destructor, c.graph.usageSym),
-      newNode(nkDotExpr, field.info, @[holder, useSym(field, c.graph.usageSym)])])
-
-proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
-  var nonTrivialFields = 0
-  result = newNode(nkCaseStmt, n.info, @[])
-  # case x.kind
-  result.addSon(newNode(nkDotExpr, n.info, @[holder, n.sons[0]]))
-  for i in countup(1, n.len - 1):
-    # of A, B:
-    let ni = n[i]
-    var caseBranch = newNode(ni.kind, ni.info, ni.sons[0..ni.len-2])
-
-    let stmt = destroyFieldOrFields(c, ni.lastSon, holder)
-    if stmt == nil:
-      caseBranch.addSon(newNode(nkStmtList, ni.info, @[]))
-    else:
-      caseBranch.addSon(stmt)
-      nonTrivialFields += stmt.len
-
-    result.addSon(caseBranch)
-
-  # maybe no fields were destroyed?
-  if nonTrivialFields == 0:
-    result = nil
-
-proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode =
-  template maybeAddLine(e) =
-    let stmt = e
-    if stmt != nil:
-      if result == nil: result = newNode(nkStmtList)
-      result.addSon(stmt)
-
-  case field.kind
-  of nkRecCase:
-    maybeAddLine destroyCase(c, field, holder)
-  of nkSym:
-    maybeAddLine destroySym(c, field.sym, holder)
-  of nkRecList:
-    for son in field:
-      maybeAddLine destroyFieldOrFields(c, son, holder)
-  else:
-    internalAssert false
-
-proc generateDestructor(c: PContext, t: PType): PNode =
-  ## generate a destructor for a user-defined object or tuple type
-  ## returns nil if the destructor turns out to be trivial
-
-  # XXX: This may be true for some C-imported types such as
-  # Tposix_spawnattr
-  if t.n == nil or t.n.sons == nil: return
-  internalAssert t.n.kind == nkRecList
-  let destructedObj = newIdentNode(destructorParam, unknownLineInfo())
-  # call the destructods of all fields
-  result = destroyFieldOrFields(c, t.n, destructedObj)
-  # base classes' destructors will be automatically called by
-  # semProcAux for both auto-generated and user-defined destructors
-
-proc instantiateDestructor(c: PContext, typ: PType): PType =
-  # returns nil if a variable of type `typ` doesn't require a
-  # destructor. Otherwise, returns the type, which holds the
-  # destructor that must be used for the varialbe.
-  # The destructor is either user-defined or automatically
-  # generated by the compiler in a member-wise fashion.
-  var t = typ.skipGenericAlias
-  let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base else: t
-
-  if typeHoldingUserDefinition.destructor != nil:
-    # XXX: This is not entirely correct for recursive types, but we need
-    # it temporarily to hide the "destroy is already defined" problem
-    if typeHoldingUserDefinition.destructor notin
-        [analyzingDestructor, destructorIsTrivial]:
-      return typeHoldingUserDefinition
-    else:
-      return nil
-
-  t = t.skipTypes({tyGenericInst, tyAlias})
-  case t.kind
-  of tySequence, tyArray, tyOpenArray, tyVarargs:
-    t.destructor = analyzingDestructor
-    if instantiateDestructor(c, t.sons[0]) != nil:
-      t.destructor = getCompilerProc"nimDestroyRange"
-      return t
-    else:
-      return nil
-  of tyTuple, tyObject:
-    t.destructor = analyzingDestructor
-    let generated = generateDestructor(c, t)
-    if generated != nil:
-      internalAssert t.sym != nil
-      let info = t.sym.info
-      let fullDef = newNode(nkProcDef, info, @[
-        newIdentNode(destructorName, info),
-        emptyNode,
-        emptyNode,
-        newNode(nkFormalParams, info, @[
-          emptyNode,
-          newNode(nkIdentDefs, info, @[
-            newIdentNode(destructorParam, info),
-            symNodeFromType(c, makeVarType(c, t), t.sym.info),
-            emptyNode]),
-          ]),
-        emptyNode,
-        emptyNode,
-        generated
-        ])
-      let semantizedDef = semProc(c, fullDef)
-      t.destructor = semantizedDef[namePos].sym
-      return t
-    else:
-      t.destructor = destructorIsTrivial
-      return nil
-  else:
-    return nil
-
-proc createDestructorCall(c: PContext, s: PSym): PNode =
-  let varTyp = s.typ
-  if varTyp == nil or sfGlobal in s.flags: return
-  let destructableT = instantiateDestructor(c, varTyp)
-  if destructableT != nil:
-    let call = semStmt(c, newNode(nkCall, s.info, @[
-      useSym(destructableT.destructor, c.graph.usageSym),
-      useSym(s, c.graph.usageSym)]))
-    result = newNode(nkDefer, s.info, @[call])