Skip to content
6 changes: 6 additions & 0 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,12 @@ proc goodLineInfo(arg: PNode): TLineInfo =
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
checkSonsLen(n, 2, c.config)
var a = n[0]
if n[1].renderTree == "@[]": # HACK D20200203T184833:here
var n2 = newNodeI(nkCall, n.info)
n2.add newIdentNode(getIdent(c.cache, "reset"), n.info)
n2.add a
return semExpr(c, n2)

case a.kind
of nkDotExpr:
# r.f = x
Expand Down
6 changes: 3 additions & 3 deletions lib/pure/strutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ proc rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string]
## * `splitLines proc<#splitLines,string>`_
## * `splitWhitespace proc<#splitWhitespace,string,int>`_
accResult(rsplit(s, sep, maxsplit))
result.reverse()
# result.reverse() # TODO

proc rsplit*(s: string, seps: set[char] = Whitespace,
maxsplit: int = -1): seq[string]
Expand Down Expand Up @@ -810,7 +810,7 @@ proc rsplit*(s: string, seps: set[char] = Whitespace,
## * `splitLines proc<#splitLines,string>`_
## * `splitWhitespace proc<#splitWhitespace,string,int>`_
accResult(rsplit(s, seps, maxsplit))
result.reverse()
# result.reverse() # TODO

proc rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string]
{.noSideEffect, rtl, extern: "nsuRSplitString".} =
Expand Down Expand Up @@ -846,7 +846,7 @@ proc rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string]
doAssert "a largely spaced sentence".rsplit(" ") == @["a", "",
"largely", "", "", "", "spaced", "sentence"]
accResult(rsplit(s, sep, maxsplit))
result.reverse()
# result.reverse() # TODO

proc splitLines*(s: string, keepEol = false): seq[string] {.noSideEffect,
rtl, extern: "nsuSplitLines".} =
Expand Down
169 changes: 119 additions & 50 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ type

include "system/basic_types"

type
ByteAddress* = int
## is the signed integer type that should be used for converting
## pointers to integer addresses for readability.

{.push warning[GcMem]: off, warning[Uninit]: off.}
{.push hints: off.}

Expand Down Expand Up @@ -234,7 +239,6 @@ type
## pointer to the array data and a
## length field.
varargs*[T]{.magic: "Varargs".} ## Generic type to construct a varargs type.
seq*[T]{.magic: "Seq".} ## Generic type to construct sequences.
set*[T]{.magic: "Set".} ## Generic type to construct bit sets.

when defined(nimUncheckedArrayTyp):
Expand Down Expand Up @@ -518,8 +522,6 @@ type
RootRef* = ref RootObj ## Reference to `RootObj`.


include "system/exceptions"

when defined(js) or defined(nimdoc):
type
JsRoot* = ref object of RootObj
Expand Down Expand Up @@ -574,24 +576,47 @@ when defined(nimtypedescfixed):
proc sizeof*(x: typedesc): int {.magic: "SizeOf", noSideEffect.}


proc newSeq*[T](s: var seq[T], len: Natural) {.magic: "NewSeq", noSideEffect.}
## Creates a new sequence of type ``seq[T]`` with length ``len``.
##
## This is equivalent to ``s = @[]; setlen(s, len)``, but more
## efficient since no reallocation is needed.
##
## Note that the sequence will be filled with zeroed entries.
## After the creation of the sequence you should assign entries to
## the sequence instead of adding them. Example:
##
## .. code-block:: Nim
## var inputStrings : seq[string]
## newSeq(inputStrings, 3)
## assert len(inputStrings) == 3
## inputStrings[0] = "The fourth"
## inputStrings[1] = "assignment"
## inputStrings[2] = "would crash"
## #inputStrings[3] = "out of bounds"
type seq*[T] = object
capacity: int
size: int
elems: ptr T

template `+`[T](p: ptr T, off: int): ptr T =
cast[ptr T](cast[ByteAddress](p) +% off * sizeof(T))

when false:
converter toOpenArray3*[T](a: seq[T]): openArray[T] = toOpenArray(a, 0, len(a)-1)
converter toOpenArray2*[T](a: var seq[T]): var openArray[T] = toOpenArray(a, 0, len(a)-1)

proc checkAux(cond: bool)

proc `[]`*[T](a: seq[T], index: int): var T =
# TODO: instead RangeCheck
checkAux(index >= 0)
checkAux(index < a.size)
(a.elems + index)[]

proc `[]=`*[T](a: seq[T], index: int, val: T) =
checkAux(index >= 0)
checkAux(index < a.size)
(a.elems + index)[] = val

proc `==`*[T](x, y: seq[T]): bool {.noSideEffect.} =
## Generic equals operator for sequences: relies on a equals operator for
## the element type `T`.
if x.len != y.len:
return false

for i in 0..x.len-1:
if x[i] != y[i]:
return false

return true

include "system/exceptions"

proc newSeq*[T](s: var seq[T], len: Natural) {.noSideEffect.}
proc newSeqOfCap*[T](cap: Natural): seq[T] {.noSideEffect.}

proc newSeq*[T](len = 0.Natural): seq[T] =
## Creates a new sequence of type ``seq[T]`` with length ``len``.
Expand All @@ -613,18 +638,6 @@ proc newSeq*[T](len = 0.Natural): seq[T] =
## #inputStrings[3] = "out of bounds"
newSeq(result, len)

proc newSeqOfCap*[T](cap: Natural): seq[T] {.
magic: "NewSeqOfCap", noSideEffect.} =
## Creates a new sequence of type ``seq[T]`` with length zero and capacity
## ``cap``.
##
## .. code-block:: Nim
## var x = newSeqOfCap[int](5)
## assert len(x) == 0
## x.add(10)
## assert len(x) == 1
discard

when not defined(js):
proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] =
## Creates a new sequence of type ``seq[T]`` with length ``len``.
Expand Down Expand Up @@ -676,12 +689,13 @@ proc len*(x: (type array)|array): int {.magic: "LengthArray", noSideEffect.}
## echo len(arr) # => 5
## echo len(array[3..8, int]) # => 6

proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
proc len*[T](x: seq[T]): int {.noSideEffect.} =
## Returns the length of a sequence.
##
## .. code-block:: Nim
## var s = @[1, 1, 1, 1, 1]
## echo len(s) # => 5
x.size


proc ord*[T: Ordinal|enum](x: T): int {.magic: "Ord", noSideEffect.}
Expand Down Expand Up @@ -866,8 +880,7 @@ proc cmp*(x, y: string): int {.noSideEffect, procvar.}
## can differ between operating systems!

when defined(nimHasDefault):
proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.
magic: "ArrToSeq", noSideEffect.}
proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.noSideEffect.} =
## Turns an array into a sequence.
##
## This most often useful for constructing
Expand All @@ -881,6 +894,14 @@ when defined(nimHasDefault):
##
## echo @a # => @[1, 3, 5]
## echo @b # => @['f', 'o', 'o']
{.noSideEffect.}: # IMPROVE" should move this to the relevant proc
const n = len(a)
var i=0
let first = low(a) # IMPROVE SPEED when...
result = newSeq[T](n)
while i<n:
result[i] = a[first + i]
i.inc

proc default*(T: typedesc): T {.magic: "Default", noSideEffect.}
## returns the default value of the type ``T``.
Expand All @@ -897,8 +918,13 @@ else:
else:
proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.}

proc setLen*[T](s: var seq[T], newlen: Natural) {.
magic: "SetLengthSeq", noSideEffect.}
when false:
# attempt at fixing this:
# `var a = @[1,2]; a = @[]`; gives: type mismatch: got <seq[empty]> but expected 'seq[system.int]'
# this workaround didn't work, instead see HACK D20200203T184833
proc `=`*[T](a: var T, b: type(@[])) = a.setLen 0

proc setLen*[T](s: var seq[T], newlen: Natural) {.noSideEffect.} =
## Sets the length of seq `s` to `newlen`. ``T`` may be any sequence type.
##
## If the current length is greater than the new length,
Expand All @@ -911,6 +937,7 @@ proc setLen*[T](s: var seq[T], newlen: Natural) {.
## assert x == @[10, 20, 0, 0, 50]
## x.setLen(1)
## assert x == @[10]
newSeq[T](s, newlen) # CHECKME

proc setLen*(s: var string, newlen: Natural) {.
magic: "SetLengthStr", noSideEffect.}
Expand Down Expand Up @@ -1169,14 +1196,18 @@ when notJSnotNims and hostOS != "standalone" and hostOS != "any":
when notJSnotNims and hasAlloc and not defined(nimSeqsV2):
proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.}

when defined(nimscript) or not defined(nimSeqsV2):
proc add*[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
## Generic proc for adding a data item `y` to a container `x`.
##
## For containers that have an order, `add` means *append*. New generic
## containers should also call their adding proc `add` for consistency.
## Generic code becomes much easier to write if the Nim naming scheme is
## respected.
proc add*[T](x: var seq[T], y: T) {.noSideEffect.} =
## Generic proc for adding a data item `y` to a container `x`.
##
## For containers that have an order, `add` means *append*. New generic
## containers should also call their adding proc `add` for consistency.
## Generic code becomes much easier to write if the Nim naming scheme is
## respected.
# CHECKME: SPEED: use doubling
let length = x.len
newSeq[T](x, length + 1)
x[length] = y


proc add*[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
## Generic proc for adding a container `y` to a container `x`.
Expand Down Expand Up @@ -1279,10 +1310,6 @@ when not defined(nimV2):
## echo repr(i) # => 0x1055ed050[1, 2, 3, 4, 5]

type
ByteAddress* = int
## is the signed integer type that should be used for converting
## pointers to integer addresses for readability.

BiggestFloat* = float64
## is an alias for the biggest floating point type the Nim
## compiler supports. Currently this is ``float64``, but it is
Expand Down Expand Up @@ -1446,6 +1473,45 @@ const

include "system/memalloc"

proc c_printf(frmt: cstring): cint {.importc: "printf", header: "<stdio.h>", varargs, discardable.}

proc newSeq[T](s: var seq[T], len: Natural) {.noSideEffect.} =
let oldLen = s.len
if len > s.capacity:
{.noSideEffect.}:
# CHECKME: shared or not?
when declared(resizeShared):
# BUG: this doesn't zero elements: s.elems = resizeShared(s.elems, len)
s.elems = cast[ptr T](reallocShared0(s.elems, T.sizeof * s.capacity, T.sizeof * len))
s.capacity = len
s.size = len
# TODO: destroy/release other elems?

proc newSeqOfCap[T](cap: Natural): seq[T] {.noSideEffect.} =
## Creates a new sequence of type ``seq[T]`` with length zero and capacity
## ``cap``.
##
## .. code-block:: Nim
## var x = newSeqOfCap[int](5)
## assert len(x) == 0
## x.add(10)
## assert len(x) == 1
when declared(createShared): # PRTEMP
result.elems = createShared(T, cap)
nimGCrefImpl(result.elems)
result.capacity = cap


proc `=destroy`*[T](x: var seq[T]) =
# echo "in destroy"
var i=0
while i < len(x):
reset(x[i])
i.inc
when declared(freeShared):
if x.elems != nil:
freeShared(x.elems)
x.elems = nil

proc `|`*(a, b: typedesc): typedesc = discard

Expand Down Expand Up @@ -1680,6 +1746,9 @@ when defined(nimV2):
import system/assertions
export assertions

proc checkAux(cond: bool) =
assert(cond)

import system/iterators
export iterators

Expand Down
38 changes: 0 additions & 38 deletions lib/system/comparisons.nim
Original file line number Diff line number Diff line change
Expand Up @@ -271,41 +271,3 @@ proc `==`*[T](x, y: openArray[T]): bool =
return false
result = true


proc `==`*[T](x, y: seq[T]): bool {.noSideEffect.} =
## Generic equals operator for sequences: relies on a equals operator for
## the element type `T`.
when nimvm:
when not defined(nimNoNil):
if x.isNil and y.isNil:
return true
else:
if x.len == 0 and y.len == 0:
return true
else:
when not defined(js):
proc seqToPtr[T](x: seq[T]): pointer {.inline, noSideEffect.} =
when defined(nimSeqsV2):
result = cast[NimSeqV2[T]](x).p
else:
result = cast[pointer](x)

if seqToPtr(x) == seqToPtr(y):
return true
else:
var sameObject = false
asm """`sameObject` = `x` === `y`"""
if sameObject: return true

when not defined(nimNoNil):
if x.isNil or y.isNil:
return false

if x.len != y.len:
return false

for i in 0..x.len-1:
if x[i] != y[i]:
return false

return true
4 changes: 2 additions & 2 deletions lib/system/nimscript.nim
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ when not defined(nimble):
backend*: string ## Nimble support: The package's backend.

skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*,
installExt*, bin*: seq[string] = @[] ## Nimble metadata.
requiresData*: seq[string] = @[] ## Exposes the list of requirements for read
installExt*, bin*: seq[string] ## Nimble metadata.
requiresData*: seq[string] ## Exposes the list of requirements for read
## and write accesses.

proc requires*(deps: varargs[string]) =
Expand Down
23 changes: 23 additions & 0 deletions tests/seq/tseq2.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
proc main() =
var a = @[10,11]
a.add 12
doAssert $a == "@[10, 11, 12]"
doAssert type(a) is seq[int]
doAssert type(a) is seq
var a2 = default(type(a))
for ai in a:
a2.add ai*10
doAssert a2 == @[100, 110, 120]
var a3 = newSeq[int](1)
doAssert a3 == @[0]
a3.add 17
a3.newSeq(4)
doAssert a3 == @[0, 17, 0, 0]
var a4 = @["foo"] & @["bar"]
a4[0] = "FOO"
a4[1].add "t"
doAssert a4 == @["FOO", "bart"]
a4 = @[]
doAssert a4.len == 0

main()