diff options
Diffstat (limited to 'compiler/semdestruct.nim')
-rw-r--r-- | compiler/semdestruct.nim | 185 |
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]) |