summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/ccgexprs.nim11
-rw-r--r--compiler/jsgen.nim1
-rw-r--r--compiler/vmgen.nim16
-rw-r--r--lib/system.nim6
-rw-r--r--lib/system/mmdisp.nim14
-rw-r--r--todo.txt1
7 files changed, 47 insertions, 4 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 5d587f35a..792dd0ea8 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -545,7 +545,7 @@ type
     mEcho, mShallowCopy, mSlurp, mStaticExec,
     mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
     mUnaryLt, mInc, mDec, mOrd,
-    mNew, mNewFinalize, mNewSeq,
+    mNew, mNewFinalize, mNewSeq, mNewSeqOfCap,
     mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
     mXLenStr, mXLenSeq,
     mIncl, mExcl, mCard, mChr,
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 5f927ba78..c47478b9c 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1141,6 +1141,16 @@ proc genNewSeq(p: BProc, e: PNode) =
   genNewSeqAux(p, a, b.rdLoc)
   gcUsage(e)
 
+proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
+  let seqtype = skipTypes(e.typ, abstractVarRange)
+  var a: TLoc
+  initLocExpr(p, e.sons[1], a)
+  putIntoDest(p, d, e.typ, ropecg(p.module,
+              "($1)#nimNewSeqOfCap($2, $3)", [
+              getTypeDesc(p.module, seqtype),
+              genTypeInfo(p.module, seqtype), a.rdLoc]))
+  gcUsage(e)
+
 proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   var tmp: TLoc
   var t = e.typ.skipTypes(abstractInst)
@@ -1712,6 +1722,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mNew: genNew(p, e)
   of mNewFinalize: genNewFinalize(p, e)
   of mNewSeq: genNewSeq(p, e)
+  of mNewSeqOfCap: genNewSeqOfCap(p, e, d)
   of mSizeOf:
     let t = e.sons[1].typ.skipTypes({tyTypeDesc})
     putIntoDest(p, d, e.typ, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index fe0f6df53..3f21014e3 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1755,6 +1755,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
       else:
         binaryExpr(p, n, r, "", "isset($1[$2])")
   of mNewSeq: genNewSeq(p, n)
+  of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]" | "array()")
   of mOf: genOf(p, n, r)
   of mReset: genReset(p, n)
   of mEcho: genEcho(p, n, r)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index f0434617b..1c1d03a4f 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -597,16 +597,27 @@ proc genNew(c: PCtx; n: PNode) =
   c.freeTemp(dest)
 
 proc genNewSeq(c: PCtx; n: PNode) =
-  let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
+  let t = n.sons[1].typ
+  let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(t)
              else: c.genx(n.sons[1])
   let tmp = c.genx(n.sons[2])
-  c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(
+  c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
                                                   abstractVar-{tyTypeDesc})))
   c.gABx(n, opcNewSeq, tmp, 0)
   c.freeTemp(tmp)
   c.genAsgnPatch(n.sons[1], dest)
   c.freeTemp(dest)
 
+proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
+  let t = n.typ
+  let tmp = c.getTemp(n.sons[1].typ)
+  c.gABx(n, opcLdNull, dest, c.genType(t))
+  c.gABx(n, opcLdImmInt, tmp, 0)
+  c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
+                                                  abstractVar-{tyTypeDesc})))
+  c.gABx(n, opcNewSeq, tmp, 0)
+  c.freeTemp(tmp)
+
 proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   let tmp = c.genx(n.sons[1])
   if dest < 0: dest = c.getTemp(n.typ)
@@ -782,6 +793,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mNewSeq:
     unused(n, dest)
     c.genNewSeq(n)
+  of mNewSeqOfCap: c.genNewSeqOfCap(n, dest)
   of mNewString:
     genUnaryABC(c, n, dest, opcNewStr)
     # XXX buggy
diff --git a/lib/system.nim b/lib/system.nim
index 40607bdb3..00eae7337 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -669,6 +669,12 @@ 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 0 and capacity
+  ## ``cap``.
+  discard
+
 proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.
   magic: "LengthOpenArray", noSideEffect.}
 proc len*(x: string): int {.magic: "LengthStr", noSideEffect.}
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 7ef26a7c1..186349152 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -354,6 +354,12 @@ elif defined(gogc):
     cast[PGenericSeq](result).reserved = len
     cast[PGenericSeq](result).elemSize = typ.base.size
 
+  proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
+    result = newObj(typ, cap * typ.base.size + GenericSeqSize)
+    cast[PGenericSeq](result).len = 0
+    cast[PGenericSeq](result).reserved = cap
+    cast[PGenericSeq](result).elemSize = typ.base.size
+
   proc growObj(old: pointer, newsize: int): pointer =
     # the Go GC doesn't have a realloc
     var
@@ -447,6 +453,7 @@ elif defined(nogc) and defined(useMalloc):
     result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
     cast[PGenericSeq](result).len = len
     cast[PGenericSeq](result).reserved = len
+
   proc newObjNoInit(typ: PNimType, size: int): pointer =
     result = alloc(size)
 
@@ -506,6 +513,7 @@ elif defined(nogc):
     result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
     cast[PGenericSeq](result).len = len
     cast[PGenericSeq](result).reserved = len
+
   proc growObj(old: pointer, newsize: int): pointer =
     result = realloc(old, newsize)
 
@@ -545,4 +553,10 @@ else:
   else:
     include "system/gc"
 
+when not declared(nimNewSeqOfCap):
+  proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
+    result = newObj(typ, addInt(mulInt(cap, typ.base.size), GenericSeqSize))
+    cast[PGenericSeq](result).len = 0
+    cast[PGenericSeq](result).reserved = cap
+
 {.pop.}
diff --git a/todo.txt b/todo.txt
index 748ffc2dd..38f8ac298 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,6 @@
 version 1.0 battle plan
 =======================
 
-- introduce newSeqOfCap(10)
 - overloading of `()` and ``.`` needs to be in .experimental
 - implement ``.delegate`` for .experimental
 - find a solution for the  x.f[T](y)  gotcha