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:
parent
e6616115e6
commit
57b7841c18
6 changed files with 100 additions and 44 deletions
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
37
tests/views/tsplit_into_openarray.nim
Normal file
37
tests/views/tsplit_into_openarray.nim
Normal 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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue