mercurial/revsetlang.py
changeset 34272 53fb09c73ba8
parent 34131 0fa781320203
child 34273 b0790bebfcf8
equal deleted inserted replaced
34271:a254c669b475 34272:53fb09c73ba8
   351     All pseudo operations should be mapped to real operations or functions
   351     All pseudo operations should be mapped to real operations or functions
   352     defined in methods or symbols table respectively.
   352     defined in methods or symbols table respectively.
   353     """
   353     """
   354     return _analyze(x)
   354     return _analyze(x)
   355 
   355 
   356 def _optimize(x, small):
   356 def _optimize(x):
   357     if x is None:
   357     if x is None:
   358         return 0, x
   358         return 0, x
   359 
   359 
   360     smallbonus = 1
       
   361     if small:
       
   362         smallbonus = .5
       
   363 
       
   364     op = x[0]
   360     op = x[0]
   365     if op in ('string', 'symbol'):
   361     if op in ('string', 'symbol'):
   366         return smallbonus, x # single revisions are small
   362         return 0.5, x # single revisions are small
   367     elif op == 'and':
   363     elif op == 'and':
   368         wa, ta = _optimize(x[1], True)
   364         wa, ta = _optimize(x[1])
   369         wb, tb = _optimize(x[2], True)
   365         wb, tb = _optimize(x[2])
   370         w = min(wa, wb)
   366         w = min(wa, wb)
   371 
   367 
   372         # (draft/secret/_notpublic() & ::x) have a fast path
   368         # (draft/secret/_notpublic() & ::x) have a fast path
   373         m = _match('_() & ancestors(_)', ('and', ta, tb))
   369         m = _match('_() & ancestors(_)', ('and', ta, tb))
   374         if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}:
   370         if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}:
   395             if len(ss) == 1:
   391             if len(ss) == 1:
   396                 w, t = ss[0]
   392                 w, t = ss[0]
   397             else:
   393             else:
   398                 s = '\0'.join(t[1] for w, t in ss)
   394                 s = '\0'.join(t[1] for w, t in ss)
   399                 y = _build('_list(_)', ('string', s))
   395                 y = _build('_list(_)', ('string', s))
   400                 w, t = _optimize(y, False)
   396                 w, t = _optimize(y)
   401             ws.append(w)
   397             ws.append(w)
   402             ts.append(t)
   398             ts.append(t)
   403             del ss[:]
   399             del ss[:]
   404         for y in getlist(x[1]):
   400         for y in getlist(x[1]):
   405             w, t = _optimize(y, False)
   401             w, t = _optimize(y)
   406             if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
   402             if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
   407                 ss.append((w, t))
   403                 ss.append((w, t))
   408                 continue
   404                 continue
   409             flushss()
   405             flushss()
   410             ws.append(w)
   406             ws.append(w)
   414             return ws[0], ts[0] # 'or' operation is fully optimized out
   410             return ws[0], ts[0] # 'or' operation is fully optimized out
   415         return max(ws), (op, ('list',) + tuple(ts))
   411         return max(ws), (op, ('list',) + tuple(ts))
   416     elif op == 'not':
   412     elif op == 'not':
   417         # Optimize not public() to _notpublic() because we have a fast version
   413         # Optimize not public() to _notpublic() because we have a fast version
   418         if _match('public()', x[1]):
   414         if _match('public()', x[1]):
   419             o = _optimize(_build('_notpublic()'), not small)
   415             o = _optimize(_build('_notpublic()'))
   420             return o[0], o[1]
   416             return o[0], o[1]
   421         else:
   417         else:
   422             o = _optimize(x[1], not small)
   418             o = _optimize(x[1])
   423             return o[0], (op, o[1])
   419             return o[0], (op, o[1])
   424     elif op == 'rangeall':
   420     elif op == 'rangeall':
   425         return smallbonus, x
   421         return 1, x
   426     elif op in ('rangepre', 'rangepost', 'parentpost'):
   422     elif op in ('rangepre', 'rangepost', 'parentpost'):
   427         o = _optimize(x[1], small)
   423         o = _optimize(x[1])
   428         return o[0], (op, o[1])
   424         return o[0], (op, o[1])
   429     elif op in ('dagrange', 'range'):
   425     elif op in ('dagrange', 'range'):
   430         wa, ta = _optimize(x[1], small)
   426         wa, ta = _optimize(x[1])
   431         wb, tb = _optimize(x[2], small)
   427         wb, tb = _optimize(x[2])
   432         return wa + wb, (op, ta, tb)
   428         return wa + wb, (op, ta, tb)
   433     elif op in ('parent', 'ancestor', 'relation', 'subscript'):
   429     elif op in ('parent', 'ancestor', 'relation', 'subscript'):
   434         w, t = _optimize(x[1], small)
   430         w, t = _optimize(x[1])
   435         return w, (op, t, x[2])
   431         return w, (op, t, x[2])
   436     elif op == 'relsubscript':
   432     elif op == 'relsubscript':
   437         w, t = _optimize(x[1], small)
   433         w, t = _optimize(x[1])
   438         return w, (op, t, x[2], x[3])
   434         return w, (op, t, x[2], x[3])
   439     elif op == 'list':
   435     elif op == 'list':
   440         ws, ts = zip(*(_optimize(y, small) for y in x[1:]))
   436         ws, ts = zip(*(_optimize(y) for y in x[1:]))
   441         return sum(ws), (op,) + ts
   437         return sum(ws), (op,) + ts
   442     elif op == 'keyvalue':
   438     elif op == 'keyvalue':
   443         w, t = _optimize(x[2], small)
   439         w, t = _optimize(x[2])
   444         return w, (op, x[1], t)
   440         return w, (op, x[1], t)
   445     elif op == 'func':
   441     elif op == 'func':
   446         f = getsymbol(x[1])
   442         f = getsymbol(x[1])
   447         wa, ta = _optimize(x[2], small)
   443         wa, ta = _optimize(x[2])
   448         if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep',
   444         if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep',
   449                  'keyword', 'outgoing', 'user', 'destination'):
   445                  'keyword', 'outgoing', 'user', 'destination'):
   450             w = 10 # slow
   446             w = 10 # slow
   451         elif f in ('modifies', 'adds', 'removes'):
   447         elif f in ('modifies', 'adds', 'removes'):
   452             w = 30 # slower
   448             w = 30 # slower
   453         elif f == "contains":
   449         elif f == "contains":
   454             w = 100 # very slow
   450             w = 100 # very slow
   455         elif f == "ancestor":
   451         elif f == "ancestor":
   456             w = 1 * smallbonus
   452             w = 0.5
   457         elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'):
   453         elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'):
   458             w = 0
   454             w = 0
   459         elif f == "sort":
   455         elif f == "sort":
   460             w = 10 # assume most sorts look at changelog
   456             w = 10 # assume most sorts look at changelog
   461         else:
   457         else:
   466 def optimize(tree):
   462 def optimize(tree):
   467     """Optimize evaluatable tree
   463     """Optimize evaluatable tree
   468 
   464 
   469     All pseudo operations should be transformed beforehand.
   465     All pseudo operations should be transformed beforehand.
   470     """
   466     """
   471     _weight, newtree = _optimize(tree, small=True)
   467     _weight, newtree = _optimize(tree)
   472     return newtree
   468     return newtree
   473 
   469 
   474 # the set of valid characters for the initial letter of symbols in
   470 # the set of valid characters for the initial letter of symbols in
   475 # alias declarations and definitions
   471 # alias declarations and definitions
   476 _aliassyminitletters = _syminitletters | {'$'}
   472 _aliassyminitletters = _syminitletters | {'$'}