metaeducation / rebol-issues

6 stars 1 forks source link

PARSE's INSERT used after a seek puts data at the position before the seek #2269

Open hostilefork opened 7 years ago

hostilefork commented 7 years ago

@giuliolunati noticed that:

>>  s: copy "ab" parse s [p: to end :p insert "x"] s

Gave back "abx" when the expected result was "xab".

hostilefork commented 7 years ago

The source of this problem comes from a general peculiarity of how :p is treated as a "rule".

It doesn't seem to make a lot of sense to say:

>> s: copy "abcd" parse s [x: "ab" thru :s "abcd"]

But you can, and it gives back true. It means the same as if you said:

>> s: copy "abcd" parse s [x: "ab" :s thru "abcd"]

This comes from the generally freeform way in which PARSE runs. It's not a grammar which processes well-formed rules, it's a hand-written loop through the block with a few state flags and variables that are tweaked. When a GET-WORD! is encountered it just changes the parse position without interrupting any of the other state.

One piece of state is "what the parse position was at the beginning of the overall rule".

https://github.com/rebol/rebol/blob/25033f897b2bd466068d7663563cd3ff64740b94/src/core/u-parse.c#L648

Since GET-WORD!s are processed at any position in the rule they don't consider them to affect this; note that begin is not changed, only the "current parse position":

https://github.com/rebol/rebol/blob/25033f897b2bd466068d7663563cd3ff64740b94/src/core/u-parse.c#L806

That causes the observed behavior.

hostilefork commented 7 years ago

A tentative solution for Ren-C disabled the use of SET-WORD! and GET-WORD! in the middle of rules for position marking and seeking. That broke the following tests, which were added for #2130

res: parse ser: [x] [set val pos: word!]
all [res | val = 'x | pos = ser]

res: parse ser: [x] [set val: pos: word!]
all [res | val = 'x | pos = ser]

res: parse
ser: "foo" [copy val pos: skip]
all [not res | val = "f" | pos = ser]

res: parse ser: "foo" [copy val: pos: skip]
all [not res | val = "f" | pos = ser]

A more modest interim patch than ruling out mid-seeks or mid-marks was committed, pending deeper review:

https://github.com/metaeducation/ren-c/commit/c7b68ea0d352f81244f955dc2e64219e160f7e29