diff options
author | Araq <rumpf_a@web.de> | 2018-03-24 20:26:20 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2018-03-24 20:26:34 +0100 |
commit | 1d9343080de8e19835c3f6568630ba759afbb94f (patch) | |
tree | 95649a7fecf7c5aaff39c5d2136aaac8306ba8b0 /compiler | |
parent | 121b9e26fb9d1ae6037c806dbb12a3ae0e26ded6 (diff) | |
download | Nim-1d9343080de8e19835c3f6568630ba759afbb94f.tar.gz |
added toOpenArray builtin for zero-copy slices; syntax sugar yet to come
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgcalls.nim | 36 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 17 | ||||
-rw-r--r-- | compiler/seminst.nim | 4 |
3 files changed, 44 insertions, 13 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 18741732c..5f14b6804 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -83,6 +83,8 @@ proc isInCurrentFrame(p: BProc, n: PNode): bool = result = isInCurrentFrame(p, n.sons[0]) else: discard +proc genIndexCheck(p: BProc; arr, idx: TLoc) + proc openArrayLoc(p: BProc, n: PNode): Rope = var a: TLoc @@ -93,18 +95,28 @@ proc openArrayLoc(p: BProc, n: PNode): Rope = initLocExpr(p, q[1], a) initLocExpr(p, q[2], b) initLocExpr(p, q[3], c) - let fmt = - case skipTypes(a.t, abstractVar+{tyPtr}).kind - of tyOpenArray, tyVarargs, tyArray: - "($1)+($2), ($3)-($2)+1" - of tyString, tySequence: - if skipTypes(n.typ, abstractInst).kind == tyVar and - not compileToCpp(p.module): - "(*$1)->data+($2), ($3)-($2)+1" - else: - "$1->data+($2), ($3)-($2)+1" - else: (internalError("openArrayLoc: " & typeToString(a.t)); "") - result = fmt % [rdLoc(a), rdLoc(b), rdLoc(c)] + # but first produce the required index checks: + if optBoundsCheck in p.options: + genIndexCheck(p, a, b) + genIndexCheck(p, a, c) + let ty = skipTypes(a.t, abstractVar+{tyPtr}) + case ty.kind + of tyArray: + let first = firstOrd(ty) + if first == 0: + result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)] + else: + result = "($1)+(($2)-($4)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first)] + of tyOpenArray, tyVarargs: + result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)] + of tyString, tySequence: + if skipTypes(n.typ, abstractInst).kind == tyVar and + not compileToCpp(p.module): + result = "(*$1)->data+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)] + else: + result = "$1->data+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)] + else: + internalError("openArrayLoc: " & typeToString(a.t)) else: initLocExpr(p, n, a) case skipTypes(a.t, abstractVar).kind diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 6ea56d71d..dc06c8482 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -880,6 +880,23 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = putIntoDest(p, d, n, rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) +proc genIndexCheck(p: BProc; arr, idx: TLoc) = + let ty = skipTypes(arr.t, abstractVarRange) + case ty.kind + of tyOpenArray, tyVarargs: + linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n", + rdLoc(idx), rdLoc(arr)) + of tyArray: + let first = intLiteral(firstOrd(ty)) + if tfUncheckedArray notin ty.flags: + linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n", + rdCharLoc(idx), first, intLiteral(lastOrd(ty))) + of tySequence, tyString: + linefmt(p, cpsStmts, + "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n", + rdLoc(idx), rdLoc(arr), lenField(p)) + else: discard + proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc initLocExpr(p, x, a) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 7fedaca5b..32b385308 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -346,7 +346,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, if c.inGenericContext == 0: instantiateBody(c, n, fn.typ.n, result, fn) sideEffectsCheck(c, result) - paramsTypeCheck(c, result.typ) + if result.magic != mSlice: + # 'toOpenArray' is special and it is allowed to return 'openArray': + paramsTypeCheck(c, result.typ) else: result = oldPrc popProcCon(c) |