[RFC] revision sets
Bill Barry
after.fallout at gmail.com
Tue Apr 20 09:39:01 CDT 2010
Matt Mackall wrote:
> You must be new here. There's nothing we care about being
> backward-compatible with. Mercurial is not a library and explicitly has
> no stable API. We only care about Mercurial's internal API being
> friendly for Mercurial's future development. If you decide to link to
> Mercurial internals, then you have to expect things to break on a
> regular basis because we're not going to stop improving the core any
> time soon.
>
> There are three kinds of backward compatibility in the world:
>
> - the kind offered by Mercurial's command line API where you should
> expect things to work forever or get lots of advanced notice that
> they'll be breaking
>
This was exactly what I was talking about. Keeping this without any
required extra effort is a good thing (for one example it has less
opportunity to introduce bugs). I don't care about the backward
compatibility inside the codebase, just at the CLI level.
>> step 4: eval this statement
>>
>
> eval is banned from use in hg. And regex parsing is insufficient to
> properly handle the quoting and nesting requirements here.
>
It doesn't have to be eval, that was just the easy way out. you could
almost as easily push the method calls onto a stack and use getattr instead.
without regexes (though I think they could have been used just as easily
as the simple tokenizer below) or eval, still not a formal grammer of
any kind (again the usual warnings about untested code and the fact that
python isn't a language I feel strong with):
class revfinder(object):
unquoteddelims = "()\t\n \"'"
def __init__(self, repo, query):
self.repo=repo
"""goal:
turn:
descendant(parent2(1.0)) and ancestor(2.0)
and author(george) and sorted('date') and reversed()
into:
[reversed, [sorted, [andf, [andf, [descendant, parent2, "1.0"],
ancestor, "2.0"], author, "george"], "date"]]
"""
charstack = []
delimiters = unquoteddelims
tokens = []
for char in query:
if delimiters.find(char) != -1:
charstack.append(char)
else
token = chartoken = ''.join(charstack)
if chartoken:
charstack = []
if token=='and' or token=='or':
token = token+'f'
if delimiters == unquoteddelims:
try:
token = getattr(self, token)
except AttributeError:
pass
if isinstance(string, tokens[-1]):
tokens[-1] = ' '.join([tokens[-1], chartoken])
else:
# could use tags on the functions to determine
which case here
# doing so would allow plugins to extend
(examples: xor, except, ...)
if chartoken=='and' or chartoken=='or':
# infix operation
tokens = [token].append(tokens)
elif chartoken=='sorted' or chartoken=='reversed':
# whole-list nonfiltering operations
tokens = [token, tokens[1]]
else:
# other
tokens.append(token)
if char=='"':
if token[-1]=="\\":
charstack = [chartoken, char]
elif delimiters = char:
delimiters = unquoteddelims
else:
delimiters = char
elif char=="'":
if delimiters = char:
delimiters = unquoteddelims
else:
delimiters=char
self.statement = tokens
def evalstmt(self):
tokens = self.statement
return self.run(tokens[0], tokens[1:])
def run(self, func, args):
if isinstance(list, args[-1]):
args[-1] = self.run(args[-1][0], args[-1][1:])
if len(args) > 2:
if isinstance(list, args[1]):
args[1] = self.run(args[1][0], args[1][1:])
while len(args) >= 2 and callable(args[-2]):
# heres hoping lists and strings are not callable
args[-2:-1] = args[-2](args[-1])
return func(*args)
# does self need to be a parameter here somewhere
# or is it implicitly included because of the getattr done?
def andf(self, set1, set2):
pass #not interested in writing these right now
def orf(self, set1, set2):
pass
def reversed(self, changes):
pass
def sorted(self, changes, key):
pass
...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20100420/af1fa8fb/attachment.htm>
More information about the Mercurial-devel
mailing list