summary refs log tree commit diff stats
path: root/compiler/semstmts.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r--compiler/semstmts.nim56
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: