diff options
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r-- | compiler/semstmts.nim | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 4d06b201e..d394a2ae5 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -22,20 +22,23 @@ proc semDiscard(c: PContext, n: PNode): PNode = proc semBreakOrContinue(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) - if n.sons[0].kind != nkEmpty: - var s: PSym - case n.sons[0].kind - of nkIdent: s = lookUp(c, n.sons[0]) - of nkSym: s = n.sons[0].sym - else: illFormedAst(n) - if s.kind == skLabel and s.owner.id == c.p.owner.id: - var x = newSymNode(s) - x.info = n.info - incl(s.flags, sfUsed) - n.sons[0] = x - suggestSym(x.info, s) + if n.sons[0].kind != nkEmpty: + if n.kind != nkContinueStmt: + var s: PSym + case n.sons[0].kind + of nkIdent: s = lookUp(c, n.sons[0]) + of nkSym: s = n.sons[0].sym + else: illFormedAst(n) + if s.kind == skLabel and s.owner.id == c.p.owner.id: + var x = newSymNode(s) + x.info = n.info + incl(s.flags, sfUsed) + n.sons[0] = x + suggestSym(x.info, s) + else: + localError(n.info, errInvalidControlFlowX, s.name.s) else: - localError(n.info, errInvalidControlFlowX, s.name.s) + localError(n.info, errGenerated, "'continue' cannot have a label") elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0): localError(n.info, errInvalidControlFlowX, renderTree(n, {renderNoComments})) @@ -1009,6 +1012,31 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) = addResult(c, s.typ.sons[0], n.info, s.kind) addResultNode(c, n) +proc semOverride(c: PContext, s: PSym, n: PNode) = + case s.name.s.normalize + of "destroy": doDestructorStuff(c, s, n) + of "deepcopy": + if s.typ.len == 2 and + s.typ.sons[1].skipTypes(abstractInst).kind in {tyRef, tyPtr} and + sameType(s.typ.sons[1], s.typ.sons[0]): + # Note: we store the deepCopy in the base of the pointer to mitigate + # the problem that pointers are structural types: + let t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst) + if t.kind in {tyObject, tyDistinct, tyEnum}: + if t.deepCopy.isNil: t.deepCopy = s + else: + localError(n.info, errGenerated, + "cannot bind another 'deepCopy' to: " & typeToString(t)) + else: + localError(n.info, errGenerated, + "cannot bind 'deepCopy' to: " & typeToString(t)) + else: + localError(n.info, errGenerated, + "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T") + of "=": discard + else: localError(n.info, errGenerated, + "'destroy' or 'deepCopy' expected for 'override'") + type TProcCompilationSteps = enum stepRegisterSymbol, @@ -1125,7 +1153,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, popOwner() pushOwner(s) s.options = gOptions - if sfDestructor in s.flags: doDestructorStuff(c, s, n) + if sfOverriden in s.flags: semOverride(c, s, n) if n.sons[bodyPos].kind != nkEmpty: # for DLL generation it is annoying to check for sfImportc! if sfBorrow in s.flags: |