From e1515b53d1992aa8443a3317759cf5bab7fa9139 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Thu, 2 May 2019 08:07:09 +0200 Subject: [PATCH] introduce temporary for 'owned' to get this compile with 0.19 (#11145) * introduce temporary for 'owned' to get this compile with 0.19 * make newTable[string, owned Node]() compile (but it crashes) * make sink/owned parameters consistent * make actiontable test compile again * VM: support sytem.move; makes tests green --- compiler/injectdestructors.nim | 14 ++++++----- compiler/sempass2.nim | 2 +- compiler/trees.nim | 2 +- compiler/vmgen.nim | 41 +++++++++++++++++++++------------ lib/pure/collections/lists.nim | 18 +++++++++------ lib/pure/collections/tables.nim | 16 ++++++------- lib/pure/parsecfg.nim | 10 ++++---- lib/pure/unittest.nim | 6 ++--- lib/system.nim | 6 +++++ 9 files changed, 69 insertions(+), 46 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 90ea0356b..0e414c975 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -426,11 +426,13 @@ proc sinkParamIsLastReadCheck(c: var Con, s: PNode) = proc isSinkTypeForParam(t: PType): bool = # a parameter like 'seq[owned T]' must not be used only once, but its # elements must, so we detect this case here: - if isSinkType(t): - if t.skipTypes({tyGenericInst, tyAlias}).kind in {tyArray, tyVarargs, tyOpenArray, tySequence}: - result = false - else: - result = true + result = t.skipTypes({tyGenericInst, tyAlias}).kind in {tySink, tyOwned} + when false: + if isSinkType(t): + if t.skipTypes({tyGenericInst, tyAlias}).kind in {tyArray, tyVarargs, tyOpenArray, tySequence}: + result = false + else: + result = true proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) @@ -817,7 +819,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = let params = owner.typ.n for i in 1 ..< params.len: let param = params[i].sym - if isSinkParam(param) and hasDestructor(param.typ.skipTypes({tySink})): + if isSinkTypeForParam(param.typ) and hasDestructor(param.typ.skipTypes({tySink})): c.addDestroy genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i]) #if optNimV2 in c.graph.config.globalOptions: diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 7fd2bd5b6..c835ce8e3 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -527,7 +527,7 @@ proc isNoEffectList(n: PNode): bool {.inline.} = n.len == 0 or (n[tagEffects] == nil and n[exceptionEffects] == nil) proc isTrival(caller: PNode): bool {.inline.} = - result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil} + result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil, mMove, mWasMoved} proc trackOperand(tracked: PEffects, n: PNode, paramType: PType; caller: PNode) = let a = skipConvAndClosure(n) diff --git a/compiler/trees.nim b/compiler/trees.nim index 55a3c619e..a06e6152c 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -101,7 +101,7 @@ proc isDeepConstExpr*(n: PNode): bool = if not isDeepConstExpr(n.sons[i]): return false if n.typ.isNil: result = true else: - let t = n.typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink}) + let t = n.typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink, tyOwned}) if t.kind in {tyRef, tyPtr}: return false if t.kind != tyObject or not isCaseObj(t.n): result = true diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 3a46af08a..9c6f8a970 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -931,6 +931,21 @@ proc ldNullOpcode(t: PType): TOpcode = assert t != nil if fitsRegister(t): opcLdNullReg else: opcLdNull +proc whichAsgnOpc(n: PNode): TOpcode = + case n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc}).kind + of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64: + opcAsgnInt + of tyString, tyCString: + opcAsgnStr + of tyFloat..tyFloat128: + opcAsgnFloat + of tyRef, tyNil, tyVar, tyLent, tyPtr: + opcAsgnRef + else: + opcAsgnComplex + +proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc + proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = case m of mAnd: c.genAndOr(n, opcFJmp, dest) @@ -1330,6 +1345,17 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = of mRunnableExamples: discard "just ignore any call to runnableExamples" of mDestroy: discard "ignore calls to the default destructor" + of mMove: + let arg = n[1] + let a = c.genx(arg) + assert dest >= 0 + if dest < 0: dest = c.getTemp(arg.typ) + gABC(c, arg, whichAsgnOpc(arg), dest, a, 1) + # XXX use ldNullOpcode() here? + c.gABx(n, opcLdNull, a, c.genType(arg.typ)) + c.gABx(n, opcNodeToReg, a, a) + c.genAsgnPatch(arg, a) + c.freeTemp(a) else: # mGCref, mGCunref, globalError(c.config, n.info, "cannot generate code for: " & $m) @@ -1423,21 +1449,6 @@ proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ): c.gABC(n, opcNodeToReg, dest, dest) -proc whichAsgnOpc(n: PNode): TOpcode = - case n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc}).kind - of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64: - opcAsgnInt - of tyString, tyCString: - opcAsgnStr - of tyFloat..tyFloat128: - opcAsgnFloat - of tyRef, tyNil, tyVar, tyLent, tyPtr: - opcAsgnRef - else: - opcAsgnComplex - -proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc - proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) = let tmp = c.genx(ri) assert dest >= 0 diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index 1fd32c9fa..2278be218 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -80,14 +80,15 @@ type DoublyLinkedNodeObj*[T] = object ## A node a doubly linked list consists of. ## ## It consists of a `value` field, and pointers to `next` and `prev`. - next*, prev*: ref DoublyLinkedNodeObj[T] + next*: (ref DoublyLinkedNodeObj[T]) + prev*: ref DoublyLinkedNodeObj[T] value*: T DoublyLinkedNode*[T] = ref DoublyLinkedNodeObj[T] SinglyLinkedNodeObj*[T] = object ## A node a singly linked list consists of. ## ## It consists of a `value` field, and a pointer to `next`. - next*: ref SinglyLinkedNodeObj[T] + next*: (ref SinglyLinkedNodeObj[T]) value*: T SinglyLinkedNode*[T] = ref SinglyLinkedNodeObj[T] @@ -95,19 +96,22 @@ type ## ## Use `initSinglyLinkedList proc <#initSinglyLinkedList>`_ to create ## a new empty list. - head*, tail*: SinglyLinkedNode[T] + head*: (SinglyLinkedNode[T]) + tail*: SinglyLinkedNode[T] DoublyLinkedList*[T] = object ## A doubly linked list. ## ## Use `initDoublyLinkedList proc <#initDoublyLinkedList>`_ to create ## a new empty list. - head*, tail*: DoublyLinkedNode[T] + head*: (DoublyLinkedNode[T]) + tail*: DoublyLinkedNode[T] SinglyLinkedRing*[T] = object ## A singly linked ring. ## ## Use `initSinglyLinkedRing proc <#initSinglyLinkedRing>`_ to create ## a new empty ring. - head*, tail*: SinglyLinkedNode[T] + head*: (SinglyLinkedNode[T]) + tail*: SinglyLinkedNode[T] DoublyLinkedRing*[T] = object ## A doubly linked ring. ## @@ -147,7 +151,7 @@ proc initDoublyLinkedRing*[T](): DoublyLinkedRing[T] = var a = initDoublyLinkedRing[int]() discard -proc newDoublyLinkedNode*[T](value: T): DoublyLinkedNode[T] = +proc newDoublyLinkedNode*[T](value: T): (DoublyLinkedNode[T]) = ## Creates a new doubly linked node with the given `value`. runnableExamples: var n = newDoublyLinkedNode[int](5) @@ -156,7 +160,7 @@ proc newDoublyLinkedNode*[T](value: T): DoublyLinkedNode[T] = new(result) result.value = value -proc newSinglyLinkedNode*[T](value: T): SinglyLinkedNode[T] = +proc newSinglyLinkedNode*[T](value: T): (SinglyLinkedNode[T]) = ## Creates a new singly linked node with the given `value`. runnableExamples: var n = newSinglyLinkedNode[int](5) diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 7acd71f38..98ece4779 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -274,7 +274,7 @@ proc enlarge[A, B](t: var Table[A, B]) = var j: Hash = eh and maxHash(t) while isFilled(t.data[j].hcode): j = nextTry(j, maxHash(t)) - rawInsert(t, t.data, n[i].key, n[i].val, eh, j) + rawInsert(t, t.data, move n[i].key, move n[i].val, eh, j) @@ -768,7 +768,7 @@ iterator allValues*[A, B](t: Table[A, B]; key: A): B = # ------------------------------------------------------------------- -proc newTable*[A, B](initialsize = defaultInitialSize): TableRef[A, B] = +proc newTable*[A, B](initialsize = defaultInitialSize): TableRef[A, B] = ## Creates a new ref hash table that is empty. ## ## ``initialSize`` must be a power of two (default: 64). @@ -789,7 +789,7 @@ proc newTable*[A, B](initialsize = defaultInitialSize): TableRef[A, B] = new(result) result[] = initTable[A, B](initialSize) -proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] = +proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] = ## Creates a new ref hash table that contains the given ``pairs``. ## ## ``pairs`` is a container consisting of ``(key, value)`` tuples. @@ -805,7 +805,7 @@ proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] = new(result) result[] = toTable[A, B](pairs) -proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] = +proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] = ## Index the collection with the proc provided. # TODO: As soon as supported, change collection: A to collection: A[B] result = newTable[C, B]() @@ -1690,7 +1690,7 @@ iterator mvalues*[A, B](t: var OrderedTable[A, B]): var B = # --------------------------- OrderedTableRef ------------------------------- # --------------------------------------------------------------------------- -proc newOrderedTable*[A, B](initialsize = defaultInitialSize): OrderedTableRef[A, B] = +proc newOrderedTable*[A, B](initialsize = defaultInitialSize): OrderedTableRef[A, B] = ## Creates a new ordered ref hash table that is empty. ## ## ``initialSize`` must be a power of two (default: 64). @@ -1711,7 +1711,7 @@ proc newOrderedTable*[A, B](initialsize = defaultInitialSize): OrderedTableRef[A new(result) result[] = initOrderedTable[A, B](initialSize) -proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] = +proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] = ## Creates a new ordered ref hash table that contains the given ``pairs``. ## ## ``pairs`` is a container consisting of ``(key, value)`` tuples. @@ -2412,7 +2412,7 @@ iterator mvalues*[A](t: var CountTable[A]): var int = proc inc*[A](t: CountTableRef[A], key: A, val = 1) -proc newCountTable*[A](initialsize = defaultInitialSize): CountTableRef[A] = +proc newCountTable*[A](initialsize = defaultInitialSize): CountTableRef[A] = ## Creates a new ref count table that is empty. ## ## ``initialSize`` must be a power of two (default: 64). @@ -2429,7 +2429,7 @@ proc newCountTable*[A](initialsize = defaultInitialSize): CountTableRef[A] = new(result) result[] = initCountTable[A](initialSize) -proc newCountTable*[A](keys: openArray[A]): CountTableRef[A] = +proc newCountTable*[A](keys: openArray[A]): CountTableRef[A] = ## Creates a new ref count table with every member of a container ``keys`` ## having a count of how many times it occurs in that container. result = newCountTable[A](rightSize(keys.len)) diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index b6fd820ff..d85359953 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -441,17 +441,17 @@ proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} = # ---------------- Configuration file related operations ---------------- type - Config* = OrderedTableRef[string, OrderedTableRef[string, string]] + Config* = OrderedTableRef[string, OrderedTableRef[string, string]] proc newConfig*(): Config = ## Create a new configuration table. ## Useful when wanting to create a configuration file. - result = newOrderedTable[string, OrderedTableRef[string, string]]() + result = newOrderedTable[string, OrderedTableRef[string, string]]() -proc loadConfig*(stream: Stream, filename: string = "[stream]"): Config = +proc loadConfig*(stream: Stream, filename: string = "[stream]"): Config = ## Load the specified configuration from stream into a new Config instance. ## `filename` parameter is only used for nicer error messages. - var dict = newOrderedTable[string, OrderedTableRef[string, string]]() + var dict = newOrderedTable[string, OrderedTableRef[string, string]]() var curSection = "" ## Current section, ## the default value of the current section is "", ## which means that the current section is a common @@ -481,7 +481,7 @@ proc loadConfig*(stream: Stream, filename: string = "[stream]"): Config = close(p) result = dict -proc loadConfig*(filename: string): Config = +proc loadConfig*(filename: string): Config = ## Load the specified configuration file into a new Config instance. let file = open(filename, fmRead) let fileStream = newFileStream(file) diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index 446ead86c..60b20c5b8 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -177,13 +177,13 @@ proc addOutputFormatter*(formatter: OutputFormatter) = formatters.add(formatter) proc newConsoleOutputFormatter*(outputLevel: OutputLevel = PRINT_ALL, - colorOutput = true): ConsoleOutputFormatter = + colorOutput = true): ConsoleOutputFormatter = ConsoleOutputFormatter( outputLevel: outputLevel, colorOutput: colorOutput ) -proc defaultConsoleFormatter*(): ConsoleOutputFormatter = +proc defaultConsoleFormatter*(): ConsoleOutputFormatter = when declared(stdout): # Reading settings # On a terminal this branch is executed @@ -263,7 +263,7 @@ proc xmlEscape(s: string): string = else: result.add(c) -proc newJUnitOutputFormatter*(stream: Stream): JUnitOutputFormatter = +proc newJUnitOutputFormatter*(stream: Stream): JUnitOutputFormatter = ## Creates a formatter that writes report to the specified stream in ## JUnit format. ## The ``stream`` is NOT closed automatically when the test are finished, diff --git a/lib/system.nim b/lib/system.nim index 23868db0f..bf2e156b4 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1641,6 +1641,9 @@ when defined(nimV2) and not defined(nimscript): proc unown*[T](x: T): T {.magic: "Unown", noSideEffect.} ## Use the expression ``x`` ignoring its ownership attribute. + # This is only required to make 0.20 compile with the 0.19 line. + template ``*(t: untyped): untyped = owned(t) + else: template owned*(t: typeDesc): typedesc = t template unown*(x: typed): typed = x @@ -1662,6 +1665,9 @@ else: new(r) return r + # This is only required to make 0.20 compile with the 0.19 line. + template ``*(t: untyped): untyped = t + template disarm*(x: typed) = ## Useful for ``disarming`` dangling pointers explicitly for the ## --newruntime. Regardless of whether --newruntime is used or not