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:
|
||||
result = true
|
||||
|
||||
proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||
var a: TLoc
|
||||
proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, Rope) =
|
||||
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 skipped = false
|
||||
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:
|
||||
genStmts(p, q[i])
|
||||
q = q.lastSon
|
||||
var 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, 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))
|
||||
let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
|
||||
result = x & ", " & y
|
||||
else:
|
||||
var a: TLoc
|
||||
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
|
||||
case skipTypes(a.t, abstractVar).kind
|
||||
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:
|
||||
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) =
|
||||
const ToStringProcSlot = -4
|
||||
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 mDestroy: genDestroy(p, e)
|
||||
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
|
||||
of mSlice:
|
||||
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
|
||||
"'toOpenArray' is only valid within a call expression")
|
||||
of mSlice: genSlice(p, e, d)
|
||||
else:
|
||||
when defined(debugMagics):
|
||||
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
|
||||
|
|
|
|||
|
|
@ -1762,7 +1762,7 @@ proc semReturn(c: PContext, n: PNode): PNode =
|
|||
a.add newSymNode(c.p.resultSym)
|
||||
a.add n[0]
|
||||
n[0] = a
|
||||
else:
|
||||
else:
|
||||
localError(c.config, n.info, errNoReturnTypeDeclared)
|
||||
return
|
||||
result[0] = semAsgn(c, n[0])
|
||||
|
|
@ -1831,8 +1831,10 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
|||
else:
|
||||
localError(c.config, n[0].info, errXExpected, "tuple constructor")
|
||||
else:
|
||||
if isViewType(t):
|
||||
n[0] = takeImplicitAddr(c, n[0], false)
|
||||
when false:
|
||||
# XXX investigate what we really need here.
|
||||
if isViewType(t):
|
||||
n[0] = takeImplicitAddr(c, n[0], false)
|
||||
|
||||
proc semYield(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
|
|
@ -2060,7 +2062,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
|
|||
else:
|
||||
identNodeSym.newSymNode
|
||||
quotes[1] = newTreeI(nkCall, n.info, identNode, newStrNode(nkStrLit, "result"))
|
||||
result = newTreeI(nkCall, n.info,
|
||||
result = newTreeI(nkCall, n.info,
|
||||
createMagic(c.graph, "getAst", mExpandToAst).newSymNode,
|
||||
newTreeI(nkCall, n.info, quotes))
|
||||
result = semExpandToAst(c, result)
|
||||
|
|
|
|||
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