remove old implementation of the roof operator; make tests green again; close #6292

This commit is contained in:
Andreas Rumpf
2017-10-29 20:36:07 +01:00
parent d52a1061b3
commit f1dab39086
13 changed files with 28 additions and 161 deletions

View File

@@ -37,7 +37,6 @@ type
# in standalone ``except`` and ``finally``
next*: PProcCon # used for stacking procedure contexts
wasForwarded*: bool # whether the current proc has a separate header
bracketExpr*: PNode # current bracket expression (for ^ support)
mapping*: TIdTable
TMatchedConcept* = object

View File

@@ -1189,7 +1189,6 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
tyCString:
if n.len != 2: return nil
n.sons[0] = makeDeref(n.sons[0])
c.p.bracketExpr = n.sons[0]
for i in countup(1, sonsLen(n) - 1):
n.sons[i] = semExprWithType(c, n.sons[i],
flags*{efInTypeof, efDetermineType})
@@ -1210,7 +1209,6 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
of tyTuple:
if n.len != 2: return nil
n.sons[0] = makeDeref(n.sons[0])
c.p.bracketExpr = n.sons[0]
# [] operator for tuples requires constant expression:
n.sons[1] = semConstExpr(c, n.sons[1])
if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias}).kind in
@@ -1248,17 +1246,13 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
of skType:
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
else:
c.p.bracketExpr = n.sons[0]
else:
c.p.bracketExpr = n.sons[0]
discard
proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
let oldBracketExpr = c.p.bracketExpr
result = semSubscript(c, n, flags)
if result == nil:
# overloaded [] operator:
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"[]"))
c.p.bracketExpr = oldBracketExpr
proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
var id = considerQuotedIdent(a[1], a)
@@ -1330,7 +1324,6 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
of nkBracketExpr:
# a[i] = x
# --> `[]=`(a, i, x)
let oldBracketExpr = c.p.bracketExpr
a = semSubscript(c, a, {efLValue})
if a == nil:
result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=")
@@ -1340,9 +1333,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
return n
else:
result = semExprNoType(c, result)
c.p.bracketExpr = oldBracketExpr
return result
c.p.bracketExpr = oldBracketExpr
of nkCurlyExpr:
# a{i} = x --> `{}=`(a, i, x)
result = buildOverloadedSubscripts(n.sons[0], getIdent"{}=")

View File

@@ -38,9 +38,7 @@ proc skipAddr(n: PNode): PNode {.inline.} =
proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
result = newNodeI(nkBracketExpr, n.info)
for i in 1..<n.len: result.add(n[i])
let oldBracketExpr = c.p.bracketExpr
result = semSubscript(c, result, flags)
c.p.bracketExpr = oldBracketExpr
if result.isNil:
let x = copyTree(n)
x.sons[0] = newIdentNode(getIdent"[]", n.info)
@@ -274,35 +272,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
of mDotDot:
result = n
of mRoof:
let bracketExpr = if n.len == 3: n.sons[2] else: c.p.bracketExpr
if bracketExpr.isNil:
localError(n.info, "no surrounding array access context for '^'")
result = n.sons[1]
elif bracketExpr.checkForSideEffects != seNoSideEffect:
localError(n.info, "invalid context for '^' as '$#' has side effects" %
renderTree(bracketExpr))
result = n.sons[1]
elif bracketExpr.typ.isStrangeArray:
localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" %
renderTree(bracketExpr))
result = n.sons[1]
else:
# ^x is rewritten to: len(a)-x
let lenExpr = newNodeI(nkCall, n.info)
lenExpr.add newIdentNode(getIdent"len", n.info)
lenExpr.add bracketExpr
let lenExprB = semExprWithType(c, lenExpr)
if lenExprB.typ.isNil or not isOrdinalType(lenExprB.typ):
localError(n.info, "'$#' has to be of an ordinal type for '^'" %
renderTree(lenExpr))
result = n.sons[1]
else:
result = newNodeIT(nkCall, n.info, getSysType(tyInt))
let subi = getSysMagic("-", mSubI)
#echo "got ", typeToString(subi.typ)
result.add newSymNode(subi, n.info)
result.add lenExprB
result.add n.sons[1]
localError(n.info, "builtin roof operator is not supported anymore")
of mPlugin:
let plugin = getPlugin(n[0].sym)
if plugin.isNil:

View File

@@ -113,13 +113,9 @@ type
owner: PSym
cursorInBody: bool # only for nimsuggest
scopeN: int
bracketExpr: PNode
template withBracketExpr(ctx, x, body: untyped) =
let old = ctx.bracketExpr
ctx.bracketExpr = x
body
ctx.bracketExpr = old
proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
case n.kind
@@ -304,18 +300,6 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
for i in 0 ..< n.len:
result.sons[i] = semTemplBody(c, n.sons[i])
proc oprIsRoof(n: PNode): bool =
const roof = "^"
case n.kind
of nkIdent: result = n.ident.s == roof
of nkSym: result = n.sym.name.s == roof
of nkAccQuoted:
if n.len == 1:
result = oprIsRoof(n.sons[0])
of nkOpenSymChoice, nkClosedSymChoice:
result = oprIsRoof(n.sons[0])
else: discard
proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = n
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
@@ -506,8 +490,6 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = semTemplBodySons(c, n)
of nkCallKinds-{nkPostfix}:
result = semTemplBodySons(c, n)
if c.bracketExpr != nil and n.len == 2 and oprIsRoof(n.sons[0]):
result.add c.bracketExpr
of nkDotExpr, nkAccQuoted:
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
# so we use the generic code for nkDotExpr too

View File

@@ -155,7 +155,7 @@ type
## - ``"abc".match(re"(?<letter>\w)").captures["letter"] == "a"``
## - ``"abc".match(re"(\w)\w").captures[-1] == "ab"``
##
## ``captureBounds[]: Option[Slice[int]]``
## ``captureBounds[]: Option[Slice[int, int]]``
## gets the bounds of the given capture according to the same rules as
## the above. If the capture is not filled, then ``None`` is returned.
## The bounds are both inclusive.
@@ -167,7 +167,7 @@ type
## ``match: string``
## the full text of the match.
##
## ``matchBounds: Slice[int]``
## ``matchBounds: Slice[int, int]``
## the bounds of the match, as in ``captureBounds[]``
##
## ``(captureBounds|captures).toTable``
@@ -182,9 +182,9 @@ type
## Not nil.
str*: string ## The string that was matched against.
## Not nil.
pcreMatchBounds: seq[Slice[cint]] ## First item is the bounds of the match
## Other items are the captures
## `a` is inclusive start, `b` is exclusive end
pcreMatchBounds: seq[Slice[cint, cint]] ## First item is the bounds of the match
## Other items are the captures
## `a` is inclusive start, `b` is exclusive end
Captures* = distinct RegexMatch
CaptureBounds* = distinct RegexMatch
@@ -251,13 +251,13 @@ proc captureBounds*(pattern: RegexMatch): CaptureBounds = return CaptureBounds(p
proc captures*(pattern: RegexMatch): Captures = return Captures(pattern)
proc `[]`*(pattern: CaptureBounds, i: int): Option[Slice[int]] =
proc `[]`*(pattern: CaptureBounds, i: int): Option[Slice[int, int]] =
let pattern = RegexMatch(pattern)
if pattern.pcreMatchBounds[i + 1].a != -1:
let bounds = pattern.pcreMatchBounds[i + 1]
return some(int(bounds.a) .. int(bounds.b-1))
else:
return none(Slice[int])
return none(Slice[int, int])
proc `[]`*(pattern: Captures, i: int): string =
let pattern = RegexMatch(pattern)
@@ -272,10 +272,10 @@ proc `[]`*(pattern: Captures, i: int): string =
proc match*(pattern: RegexMatch): string =
return pattern.captures[-1]
proc matchBounds*(pattern: RegexMatch): Slice[int] =
proc matchBounds*(pattern: RegexMatch): Slice[int, int] =
return pattern.captureBounds[-1].get
proc `[]`*(pattern: CaptureBounds, name: string): Option[Slice[int]] =
proc `[]`*(pattern: CaptureBounds, name: string): Option[Slice[int, int]] =
let pattern = RegexMatch(pattern)
return pattern.captureBounds[pattern.pattern.captureNameToId.fget(name)]
@@ -295,13 +295,13 @@ proc toTable*(pattern: Captures, default: string = nil): Table[string, string] =
result = initTable[string, string]()
toTableImpl(nextVal == nil)
proc toTable*(pattern: CaptureBounds, default = none(Slice[int])):
Table[string, Option[Slice[int]]] =
result = initTable[string, Option[Slice[int]]]()
proc toTable*(pattern: CaptureBounds, default = none(Slice[int, int])):
Table[string, Option[Slice[int, int]]] =
result = initTable[string, Option[Slice[int, int]]]()
toTableImpl(nextVal.isNone)
template itemsImpl(cond: untyped) {.dirty.} =
for i in 0 .. <RegexMatch(pattern).pattern.captureCount:
for i in 0 ..< RegexMatch(pattern).pattern.captureCount:
let nextVal = pattern[i]
# done in this roundabout way to avoid multiple yields (potential code
# bloat)
@@ -309,13 +309,13 @@ template itemsImpl(cond: untyped) {.dirty.} =
yield nextYieldVal
iterator items*(pattern: CaptureBounds, default = none(Slice[int])): Option[Slice[int]] =
iterator items*(pattern: CaptureBounds, default = none(Slice[int, int])): Option[Slice[int, int]] =
itemsImpl(nextVal.isNone)
iterator items*(pattern: Captures, default: string = nil): string =
itemsImpl(nextVal == nil)
proc toSeq*(pattern: CaptureBounds, default = none(Slice[int])): seq[Option[Slice[int]]] =
proc toSeq*(pattern: CaptureBounds, default = none(Slice[int, int])): seq[Option[Slice[int, int]]] =
accumulateResult(pattern.items(default))
proc toSeq*(pattern: Captures, default: string = nil): seq[string] =
@@ -396,8 +396,6 @@ proc extractOptions(pattern: string): tuple[pattern: string, flags: int, study:
# }}}
type UncheckedArray {.unchecked.}[T] = array[0 .. 0, T]
proc destroyRegex(pattern: Regex) =
pcre.free_substring(cast[cstring](pattern.pcreObj))
pattern.pcreObj = nil
@@ -412,7 +410,7 @@ proc getNameToNumberTable(pattern: Regex): Table[string, int] =
result = initTable[string, int]()
for i in 0 .. <entryCount:
for i in 0 ..< entryCount:
let pos = i * entrySize
let num = (int(table[pos]) shl 8) or int(table[pos + 1]) - 1
var name = ""
@@ -464,7 +462,7 @@ proc matchImpl(str: string, pattern: Regex, start, endpos: int, flags: int): Opt
# 1x capture count as slack space for PCRE
let vecsize = (pattern.captureCount() + 1) * 3
# div 2 because each element is 2 cints long
myResult.pcreMatchBounds = newSeq[Slice[cint]](ceil(vecsize / 2).int)
myResult.pcreMatchBounds = newSeq[Slice[cint, cint]](ceil(vecsize / 2).int)
myResult.pcreMatchBounds.setLen(vecsize div 3)
let strlen = if endpos == int.high: str.len else: endpos+1

View File

@@ -48,7 +48,7 @@ proc validEmailAddress*(s: string): bool {.noSideEffect,
"aero", "jobs", "museum": return true
else: return false
proc parseInt*(s: string, value: var int, validRange: Slice[int]) {.
proc parseInt*(s: string, value: var int, validRange: Slice[int, int]) {.
noSideEffect, rtl, extern: "nmatchParseInt".} =
## parses `s` into an integer in the range `validRange`. If successful,
## `value` is modified to contain the result. Otherwise no exception is

View File

@@ -323,7 +323,7 @@ proc `..`*[T, U](a: T, b: U): Slice[T, U] {.noSideEffect, inline, magic: "DotDot
result.a = a
result.b = b
proc `..`*[T](b: T): Slice[T, T] {.noSideEffect, inline, magic: "DotDot".} =
proc `..`*[T](b: T): Slice[int, T] {.noSideEffect, inline, magic: "DotDot".} =
## `slice`:idx: operator that constructs an interval ``[default(T), b]``
result.b = b

View File

@@ -1,7 +1,6 @@
discard """
output: '''@[2, 3, 4]321
9.0 4.0
(a: 1.0, b: 2.0, c: 8.0)2.0'''
9.0 4.0'''
"""
proc foo[T](x, y: T): T = x
@@ -10,27 +9,3 @@ var a = @[1, 2, 3, 4]
var b: array[3, array[2, float]] = [[1.0,2], [3.0,4], [8.0,9]]
echo a[1.. ^1], a[^2], a[^3], a[^4]
echo b[^1][^1], " ", (b[^2]).foo(b[^1])[^1]
type
MyArray = object
a, b, c: float
var
ma = MyArray(a: 1.0, b: 2.0, c: 3.0)
proc len(x: MyArray): int = 3
proc `[]=`(x: var MyArray; idx: range[0..2]; val: float) =
case idx
of 0: x.a = val
of 1: x.b = val
of 2: x.c = val
proc `[]`(x: var MyArray; idx: range[0..2]): float =
case idx
of 0: result = x.a
of 1: result = x.b
of 2: result = x.c
ma[^1] = 8.0
echo ma, ma[^2]

View File

@@ -1,10 +0,0 @@
discard """
errormsg: "invalid context for '^' as 'foo()' has side effects"
line: "9"
"""
# XXX This needs to be fixed properly!
proc foo(): seq[int] {.sideEffect.} =
echo "ha"
let f = foo()[^1]

View File

@@ -1,8 +1,7 @@
discard """
errormsg: "invalid context for '^' as len!=high+1 for 'a'"
line: "8"
output: '''c'''
"""
var a: array[1..3, string]
var a: array['a'..'c', string] = ["a", "b", "c"]
echo a[^1]

View File

@@ -1,37 +0,0 @@
discard """
errormsg: "no surrounding array access context for '^'"
line: "37"
"""
proc foo[T](x, y: T): T = x
var a = @[1, 2, 3, 4]
var b: array[3, array[2, float]] = [[1.0,2], [3.0,4], [8.0,9]]
echo a[1.. ^1], a[^2], a[^3], a[^4]
echo b[^1][^1], " ", (b[^2]).foo(b[^1])[^1]
type
MyArray = object
a, b, c: float
var
ma = MyArray(a: 1.0, b: 2.0, c: 3.0)
proc len(x: MyArray): int = 3
proc `[]=`(x: var MyArray; idx: range[0..2]; val: float) =
case idx
of 0: x.a = val
of 1: x.b = val
of 2: x.c = val
proc `[]`(x: var MyArray; idx: range[0..2]): float =
case idx
of 0: result = x.a
of 1: result = x.b
of 2: result = x.c
ma[^1] = 8.0
echo ma, ma[^2]
echo(^1)

View File

@@ -32,7 +32,7 @@ suite "captures":
test "named capture bounds":
let ex1 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
check(ex1.captureBounds["foo"] == some(0..2))
check(ex1.captureBounds["bar"] == none(Slice[int]))
check(ex1.captureBounds["bar"] == none(Slice[int, int]))
test "capture count":
let ex1 = re("(?<foo>foo)(?<bar>bar)?")
@@ -42,7 +42,7 @@ suite "captures":
test "named capture table":
let ex1 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
check(ex1.captures.toTable == {"foo" : "foo", "bar" : nil}.toTable())
check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int])}.toTable())
check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int, int])}.toTable())
check(ex1.captures.toTable("") == {"foo" : "foo", "bar" : ""}.toTable())
let ex2 = "foobar".find(re("(?<foo>foo)(?<bar>bar)?"))
@@ -51,7 +51,7 @@ suite "captures":
test "capture sequence":
let ex1 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
check(ex1.captures.toSeq == @["foo", nil])
check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int])])
check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int, int])])
check(ex1.captures.toSeq("") == @["foo", ""])
let ex2 = "foobar".find(re("(?<foo>foo)(?<bar>bar)?"))

View File

@@ -12,7 +12,7 @@ suite "find":
test "find bounds":
check(toSeq(findIter("1 2 3 4 5 ", re" ")).map(
proc (a: RegexMatch): Slice[int] = a.matchBounds
proc (a: RegexMatch): Slice[int, int] = a.matchBounds
) == @[1..1, 3..3, 5..5, 7..7, 9..9])
test "overlapping find":