summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/commands.nim22
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/injectdestructors.nim18
-rw-r--r--compiler/liftdestructors.nim30
-rw-r--r--compiler/pragmas.nim7
-rw-r--r--compiler/renderer.nim2
-rw-r--r--compiler/wordrecg.nim4
8 files changed, 58 insertions, 29 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 27db97f0c..06041eaa7 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -228,7 +228,7 @@ type
   TNodeKinds* = set[TNodeKind]
 
 type
-  TSymFlag* = enum    # already 38 flags!
+  TSymFlag* = enum    # 39 flags!
     sfUsed,           # read access of sym (for warnings) or simply used
     sfExported,       # symbol is exported from module
     sfFromGeneric,    # symbol is instantiation of a generic; this is needed
@@ -284,6 +284,7 @@ type
                       # variable is generated closure environment; requires early
                       # destruction for --newruntime.
     sfTemplateParam   # symbol is a template parameter
+    sfCursor          # variable/field is a cursor, see RFC 177 for details
 
 
   TSymFlags* = set[TSymFlag]
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 12526e6c7..b0adaae83 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -224,15 +224,15 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
   case switch.normalize
   of "gc":
     case arg.normalize
-    of "boehm":        result = conf.selectedGC == gcBoehm
-    of "refc":         result = conf.selectedGC == gcRefc
-    of "v2":           result = false
+    of "boehm": result = conf.selectedGC == gcBoehm
+    of "refc": result = conf.selectedGC == gcRefc
+    of "v2": result = false
     of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
     of "generational": result = false
-    of "destructors":  result = conf.selectedGC == gcDestructors
-    of "hooks":        result = conf.selectedGC == gcHooks
-    of "go":           result = conf.selectedGC == gcGo
-    of "none":         result = conf.selectedGC == gcNone
+    of "destructors", "arc": result = conf.selectedGC == gcDestructors
+    of "hooks": result = conf.selectedGC == gcHooks
+    of "go": result = conf.selectedGC == gcGo
+    of "none": result = conf.selectedGC == gcNone
     of "stack", "regions": result = conf.selectedGC == gcRegions
     else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
   of "opt":
@@ -244,9 +244,9 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
   of "verbosity": result = $conf.verbosity == arg
   of "app":
     case arg.normalize
-    of "gui":       result = contains(conf.globalOptions, optGenGuiApp)
-    of "console":   result = not contains(conf.globalOptions, optGenGuiApp)
-    of "lib":       result = contains(conf.globalOptions, optGenDynLib) and
+    of "gui": result = contains(conf.globalOptions, optGenGuiApp)
+    of "console": result = not contains(conf.globalOptions, optGenGuiApp)
+    of "lib": result = contains(conf.globalOptions, optGenDynLib) and
                       not contains(conf.globalOptions, optGenGuiApp)
     of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
                       not contains(conf.globalOptions, optGenGuiApp)
@@ -453,7 +453,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
       of "markandsweep":
         conf.selectedGC = gcMarkAndSweep
         defineSymbol(conf.symbols, "gcmarkandsweep")
-      of "destructors":
+      of "destructors", "arc":
         conf.selectedGC = gcDestructors
         defineSymbol(conf.symbols, "gcdestructors")
         incl conf.globalOptions, optSeqDestructors
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 9e2dc2532..ae23fec3f 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -101,3 +101,4 @@ proc initDefines*(symbols: StringTableRef) =
   defineSymbol("nimFixedForwardGeneric")
   defineSymbol("nimnomagic64")
   defineSymbol("nimNewShiftOps")
+  defineSymbol("nimHasCursor")
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index b6dbf797c..96b4e5240 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -418,6 +418,17 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
   else:
     result = p(arg, c)
 
+proc isCursor(n: PNode): bool =
+  case n.kind
+  of nkSym:
+    result = sfCursor in n.sym.flags
+  of nkDotExpr:
+    result = sfCursor in n[1].sym.flags
+  of nkCheckedFieldExpr:
+    result = isCursor(n[0])
+  else:
+    result = false
+
 proc p(n: PNode; c: var Con): PNode =
   case n.kind
   of nkCallKinds:
@@ -459,7 +470,7 @@ proc p(n: PNode; c: var Con): PNode =
       if it.kind == nkVarTuple and hasDestructor(ri.typ):
         let x = lowerTupleUnpacking(c.graph, it, c.owner)
         result.add p(x, c)
-      elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
+      elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isCursor(it[0]):
         for j in 0..<it.len-2:
           let v = it[j]
           if v.kind == nkSym:
@@ -483,7 +494,8 @@ proc p(n: PNode; c: var Con): PNode =
         v.add itCopy
         result.add v
   of nkAsgn, nkFastAsgn:
-    if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda}:
+    if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda} and
+        not isCursor(n[0]):
       # rule (self-assignment-removal):
       if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
         result = newNodeI(nkEmpty, n.info)
@@ -515,7 +527,7 @@ proc p(n: PNode; c: var Con): PNode =
   of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
       nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef,
       nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt, nkExportStmt,
-      nkPragma, nkCommentStmt, nkBreakStmt:
+      nkPragma, nkCommentStmt, nkBreakStmt, nkBreakState:
     result = n
   of nkWhileStmt:
     result = copyNode(n)
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index 94cad9bad..3787fe6a7 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -52,11 +52,24 @@ proc dotField(x: PNode, f: PSym): PNode =
   result.sons[1] = newSymNode(f, x.info)
   result.typ = f.typ
 
+proc newAsgnStmt(le, ri: PNode): PNode =
+  result = newNodeI(nkAsgn, le.info, 2)
+  result.sons[0] = le
+  result.sons[1] = ri
+
+proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
+  if c.kind != attachedDestructor:
+    body.add newAsgnStmt(x, y)
+
 proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
   case n.kind
   of nkSym:
     let f = n.sym
-    fillBody(c, f.typ, body, x.dotField(f), y.dotField(f))
+    if sfCursor in f.flags and f.typ.skipTypes(abstractInst).kind in {tyRef, tyProc} and
+        c.g.config.selectedGC == gcDestructors:
+      defaultOp(c, f.typ, body, x.dotField(f), y.dotField(f))
+    else:
+      fillBody(c, f.typ, body, x.dotField(f), y.dotField(f))
   of nkNilLit: discard
   of nkRecCase:
     if c.kind in {attachedSink, attachedAsgn, attachedDeepCopy}:
@@ -113,11 +126,6 @@ proc newAsgnCall(g: ModuleGraph; op: PSym; x, y: PNode): PNode =
   result.add genAddr(g, x)
   result.add y
 
-proc newAsgnStmt(le, ri: PNode): PNode =
-  result = newNodeI(nkAsgn, le.info, 2)
-  result.sons[0] = le
-  result.sons[1] = ri
-
 proc newOpCall(op: PSym; x: PNode): PNode =
   result = newNodeIT(nkCall, x.info, op.typ.sons[0])
   result.add(newSymNode(op))
@@ -236,10 +244,6 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
       body.add newDeepCopyCall(op, x, y)
       result = true
 
-proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
-  if c.kind != attachedDestructor:
-    body.add newAsgnStmt(x, y)
-
 proc addVar(father, v, value: PNode) =
   var vpart = newNodeI(nkIdentDefs, v.info, 3)
   vpart.sons[0] = v
@@ -393,6 +397,9 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
     body.add genIf(c, cond, actions)
     body.add newAsgnStmt(x, y)
   of attachedDestructor:
+    when false:
+      # XXX investigate if this is necessary:
+      actions.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
     body.add genIf(c, cond, actions)
   of attachedDeepCopy: assert(false, "cannot happen")
 
@@ -419,6 +426,9 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
     body.add genIf(c, cond, actions)
     body.add newAsgnStmt(x, y)
   of attachedDestructor:
+    when false:
+      # XXX investigate if this is necessary:
+      actions.add newAsgnStmt(xenv, newNodeIT(nkNilLit, body.info, xenv.typ))
     body.add genIf(c, cond, actions)
   of attachedDeepCopy: assert(false, "cannot happen")
 
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index b1eecc50e..205ed4309 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -62,11 +62,11 @@ const
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
     wBorrow, wGcSafe, wPartial, wExplain, wPackage}
   fieldPragmas* = declPragmas + {
-    wGuard, wBitsize} - {wExportNims, wNodecl} # why exclude these?
+    wGuard, wBitsize, wCursor} - {wExportNims, wNodecl} # why exclude these?
   varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
     wMagic, wHeader, wCompilerProc, wCore, wDynlib,
     wNoInit, wCompileTime, wGlobal,
-    wGensym, wInject, wCodegenDecl, wGuard, wGoto}
+    wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor}
   constPragmas* = declPragmas + {wHeader, wMagic,
     wGensym, wInject,
     wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
@@ -833,6 +833,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
       of wVolatile:
         noVal(c, it)
         incl(sym.flags, sfVolatile)
+      of wCursor:
+        noVal(c, it)
+        incl(sym.flags, sfCursor)
       of wRegister:
         noVal(c, it)
         incl(sym.flags, sfRegister)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 2fbe01ce2..dc6ff93c0 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1526,6 +1526,8 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
 
   of nkBreakState:
     put(g, tkTuple, "breakstate")
+    if renderIds in g.flags:
+      gsons(g, n, c, 0)
   of nkTypeClassTy:
     gTypeClassTy(g, n)
   else:
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 4650f22ec..fa18d4f7f 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -35,7 +35,7 @@ type
     wColon, wColonColon, wEquals, wDot, wDotDot,
     wStar, wMinus,
     wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
-    wIntDefine, wStrDefine, wBoolDefine
+    wIntDefine, wStrDefine, wBoolDefine, wCursor,
 
     wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
     wImportCpp, wImportObjC,
@@ -121,7 +121,7 @@ const
     ":", "::", "=", ".", "..",
     "*", "-",
     "magic", "thread", "final", "profiler", "memtracker", "objchecks",
-    "intdefine", "strdefine", "booldefine",
+    "intdefine", "strdefine", "booldefine", "cursor",
 
     "immediate", "constructor", "destructor", "delegator", "override",
     "importcpp", "importobjc",