mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 05:50:30 +00:00
remove old implementation of the roof operator; make tests green again; close #6292
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"{}=")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
@@ -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)?"))
|
||||
|
||||
@@ -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":
|
||||
|
||||
Reference in New Issue
Block a user