better support for slices as views (#15414)

* moved view tests to tests/views
* refactoring
* more refactorings
* better support for system.toOpenArray for first class view types
This commit is contained in:
Andreas Rumpf 2020-09-27 09:20:10 +02:00 • committed by GitHub
commit 57b7841c18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 44 deletions

View file

@ -148,9 +148,52 @@ proc reifiedOpenArray(n: PNode): bool {.inline.} =
else: else:
result = true result = true
proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope = proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, Rope) =
var a: TLoc var a, b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
initLocExpr(p, q[3], c)
# but first produce the required index checks:
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
let dest = getTypeDesc(p.module, destType)
let lengthExpr = "($1)-($2)+1" % [rdLoc(c), rdLoc(b)]
case ty.kind
of tyArray:
let first = toInt64(firstOrd(p.config, ty))
if first == 0:
result = ("($3*)(($1)+($2))" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
else:
result = ("($4*)($1)+(($2)-($3))" %
[rdLoc(a), rdLoc(b), intLiteral(first), dest],
lengthExpr)
of tyOpenArray, tyVarargs:
if reifiedOpenArray(q[1]):
result = ("($3*)($1.d)+($2)" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
else:
result = ("($3*)($1)+($2)" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
of tyUncheckedArray, tyCString:
result = ("($3*)($1)+($2)" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
of tyString, tySequence:
let atyp = skipTypes(a.t, abstractInst)
if formalType.skipTypes(abstractInst).kind in {tyVar} and atyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind in {tyVar} and not compileToCpp(p.module):
result = ("($4*)(*$1)$3+($2)" % [rdLoc(a), rdLoc(b), dataField(p), dest],
lengthExpr)
else:
result = ("($4*)$1$3+($2)" % [rdLoc(a), rdLoc(b), dataField(p), dest],
lengthExpr)
else:
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
var q = skipConv(n) var q = skipConv(n)
var skipped = false var skipped = false
while q.kind == nkStmtListExpr and q.len > 0: while q.kind == nkStmtListExpr and q.len > 0:
@ -164,42 +207,10 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
for i in 0..<q.len-1: for i in 0..<q.len-1:
genStmts(p, q[i]) genStmts(p, q[i])
q = q.lastSon q = q.lastSon
var b, c: TLoc let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
initLocExpr(p, q[1], a) result = x & ", " & y
initLocExpr(p, q[2], b)
initLocExpr(p, q[3], c)
# but first produce the required index checks:
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
let dest = getTypeDesc(p.module, n.typ[0])
case ty.kind
of tyArray:
let first = toInt64(firstOrd(p.config, ty))
if first == 0:
result = "($4*)(($1)+($2)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
else:
result = "($5*)($1)+(($2)-($4)), ($3)-($2)+1" %
[rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first), dest]
of tyOpenArray, tyVarargs:
if reifiedOpenArray(q[1]):
result = "($4*)($1.d)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
else:
result = "($4*)($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
of tyUncheckedArray, tyCString:
result = "($4*)($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
of tyString, tySequence:
let atyp = skipTypes(a.t, abstractInst)
if formalType.skipTypes(abstractInst).kind in {tyVar} and atyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind in {tyVar} and not compileToCpp(p.module):
result = "($5*)(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
result = "($5*)$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
else: else:
var a: TLoc
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a) initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
case skipTypes(a.t, abstractVar).kind case skipTypes(a.t, abstractVar).kind
of tyOpenArray, tyVarargs: of tyOpenArray, tyVarargs:

View file

@ -2215,6 +2215,14 @@ proc genDispose(p: BProc; n: PNode) =
# destructor, but it uses the runtime type. Afterwards the memory is freed: # destructor, but it uses the runtime type. Afterwards the memory is freed:
lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)]) lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)])
proc genSlice(p: BProc; e: PNode; d: var TLoc) =
let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon)
if d.k == locNone: getTemp(p, e.typ, d)
linefmt(p, cpsStmts, "$1.d = $2; $1.l = $3;$n", [rdLoc(d), x, y])
when false:
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
"'toOpenArray' is only valid within a call expression")
proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) = proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
const ToStringProcSlot = -4 const ToStringProcSlot = -4
let t = e[1].typ.skipTypes(abstractInst+{tyRange}) let t = e[1].typ.skipTypes(abstractInst+{tyRange})
@ -2396,9 +2404,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mMove: genMove(p, e, d) of mMove: genMove(p, e, d)
of mDestroy: genDestroy(p, e) of mDestroy: genDestroy(p, e)
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0") of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
of mSlice: of mSlice: genSlice(p, e, d)
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
"'toOpenArray' is only valid within a call expression")
else: else:
when defined(debugMagics): when defined(debugMagics):
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind

View file

@ -1831,6 +1831,8 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
else: else:
localError(c.config, n[0].info, errXExpected, "tuple constructor") localError(c.config, n[0].info, errXExpected, "tuple constructor")
else: else:
when false:
# XXX investigate what we really need here.
if isViewType(t): if isViewType(t):
n[0] = takeImplicitAddr(c, n[0], false) n[0] = takeImplicitAddr(c, n[0], false)

View file

@ -0,0 +1,37 @@
discard """
output: '''asdf
231
'''
cmd: "nim c --gc:arc -d:useMalloc -g $file"
valgrind: true
"""
{.experimental: "views".}
const
Whitespace = {' ', '\t', '\n', '\r'}
iterator split*(s: string, seps: set[char] = Whitespace,
maxsplit: int = -1): openArray[char] =
var last = 0
var splits = maxsplit
while last <= len(s):
var first = last
while last < len(s) and s[last] notin seps:
inc(last)
if splits == 0: last = len(s)
yield toOpenArray(s, first, last-1)
if splits == 0: break
dec(splits)
inc(last)
proc `$`(x: openArray[char]): string =
result = newString(x.len)
for i in 0..<x.len: result[i] = x[i]
proc main() =
for x in split("asdf 231"):
echo x
main()