##// END OF EJS Templates
revsetlang: build optimized tree by helper function...
Yuya Nishihara -
r34046:b862e6fc default
parent child Browse files
Show More
@@ -239,6 +239,25 b' def getargsdict(x, funcname, keys):'
239 239 return parser.buildargsdict(getlist(x), funcname, parser.splitargspec(keys),
240 240 keyvaluenode='keyvalue', keynode='symbol')
241 241
242 # cache of {spec: raw parsed tree} built internally
243 _treecache = {}
244
245 def _cachedtree(spec):
246 # thread safe because parse() is reentrant and dict.__setitem__() is atomic
247 tree = _treecache.get(spec)
248 if tree is None:
249 _treecache[spec] = tree = parse(spec)
250 return tree
251
252 def _build(tmplspec, *repls):
253 """Create raw parsed tree from a template revset statement
254
255 >>> _build('f(_) and _', ('string', '1'), ('symbol', '2'))
256 ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
257 """
258 template = _cachedtree(tmplspec)
259 return parser.buildtree(template, ('symbol', '_'), *repls)
260
242 261 def _isnamedfunc(x, funcname):
243 262 """Check if given tree matches named function"""
244 263 return x and x[0] == 'func' and getsymbol(x[1]) == funcname
@@ -302,16 +321,15 b' def _analyze(x):'
302 321
303 322 op = x[0]
304 323 if op == 'minus':
305 return _analyze(('and', x[1], ('not', x[2])))
324 return _analyze(_build('_ and not _', *x[1:]))
306 325 elif op == 'only':
307 t = ('func', ('symbol', 'only'), ('list', x[1], x[2]))
308 return _analyze(t)
326 return _analyze(_build('only(_, _)', *x[1:]))
309 327 elif op == 'onlypost':
310 return _analyze(('func', ('symbol', 'only'), x[1]))
328 return _analyze(_build('only(_)', x[1]))
311 329 elif op == 'dagrangepre':
312 return _analyze(('func', ('symbol', 'ancestors'), x[1]))
330 return _analyze(_build('ancestors(_)', x[1]))
313 331 elif op == 'dagrangepost':
314 return _analyze(('func', ('symbol', 'descendants'), x[1]))
332 return _analyze(_build('descendants(_)', x[1]))
315 333 elif op == 'negate':
316 334 s = getstring(x[1], _("can't negate that"))
317 335 return _analyze(('string', '-' + s))
@@ -367,9 +385,9 b' def _optimize(x, small):'
367 385 w = min(wa, wb)
368 386
369 387 # (::x and not ::y)/(not ::y and ::x) have a fast path
370 tm = _matchonly(ta, tb) or _matchonly(tb, ta)
371 if tm:
372 return w, ('func', ('symbol', 'only'), tm)
388 m = _matchonly(ta, tb) or _matchonly(tb, ta)
389 if m:
390 return w, _build('only(_, _)', *m[1:])
373 391
374 392 if tb is not None and tb[0] == 'not':
375 393 return wa, ('difference', ta, tb[1])
@@ -387,7 +405,7 b' def _optimize(x, small):'
387 405 w, t = ss[0]
388 406 else:
389 407 s = '\0'.join(t[1] for w, t in ss)
390 y = ('func', ('symbol', '_list'), ('string', s))
408 y = _build('_list(_)', ('string', s))
391 409 w, t = _optimize(y, False)
392 410 ws.append(w)
393 411 ts.append(t)
@@ -407,8 +425,7 b' def _optimize(x, small):'
407 425 elif op == 'not':
408 426 # Optimize not public() to _notpublic() because we have a fast version
409 427 if x[1][:3] == ('func', ('symbol', 'public'), None):
410 newsym = ('func', ('symbol', '_notpublic'), None)
411 o = _optimize(newsym, not small)
428 o = _optimize(_build('_notpublic()'), not small)
412 429 return o[0], o[1]
413 430 else:
414 431 o = _optimize(x[1], not small)
General Comments 0
You need to be logged in to leave comments. Login now