mercurial/filesetlang.py
author Augie Fackler <augie@google.com>
Sun, 06 Oct 2019 09:45:02 -0400
changeset 43076 2372284d9457
parent 38879 e79a69af1593
child 43077 687b865b95ad
permissions -rw-r--r--
formatting: blacken the codebase This is using my patch to black (https://github.com/psf/black/pull/826) so we don't un-wrap collection literals. Done with: hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S # skip-blame mass-reformatting only # no-check-commit reformats foo_bar functions Differential Revision: https://phab.mercurial-scm.org/D6971
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38805
b9162ea1b815 fileset: extract language processing part to new module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38804
diff changeset
     1
# filesetlang.py - parser, tokenizer and utility for file set language
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2010 Matt Mackall <mpm@selenic.com>
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
25938
e194ada8d45f fileset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
     8
from __future__ import absolute_import
e194ada8d45f fileset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
     9
e194ada8d45f fileset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    10
from .i18n import _
e194ada8d45f fileset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    11
from . import (
e194ada8d45f fileset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    12
    error,
e194ada8d45f fileset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    13
    parser,
32523
1fb0a85fb20e py3: use pycompat.bytestr so that we don't get ascii values
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32291
diff changeset
    14
    pycompat,
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36505
diff changeset
    15
)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
38863
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    17
# common weight constants for static optimization
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    18
# (see registrar.filesetpredicate for details)
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    19
WEIGHT_CHECK_FILENAME = 0.5
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    20
WEIGHT_READ_CONTENTS = 30
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    21
WEIGHT_STATUS = 10
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    22
WEIGHT_STATUS_THOROUGH = 50
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
    23
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
elements = {
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    25
    # token-type: binding-strength, primary, prefix, infix, suffix
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    26
    "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None),
35741
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
    27
    ":": (15, None, None, ("kindpat", 15), None),
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    28
    "-": (5, None, ("negate", 19), ("minus", 5), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    29
    "not": (10, None, ("not", 10), None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    30
    "!": (10, None, ("not", 10), None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    31
    "and": (5, None, None, ("and", 5), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    32
    "&": (5, None, None, ("and", 5), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    33
    "or": (4, None, None, ("or", 4), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    34
    "|": (4, None, None, ("or", 4), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    35
    "+": (4, None, None, ("or", 4), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    36
    ",": (2, None, None, ("list", 2), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    37
    ")": (0, None, None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    38
    "symbol": (0, "symbol", None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    39
    "string": (0, "string", None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    40
    "end": (0, None, None, None, None),
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
}
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32134
diff changeset
    43
keywords = {'and', 'or', 'not'}
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
38805
b9162ea1b815 fileset: extract language processing part to new module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38804
diff changeset
    45
symbols = {}
b9162ea1b815 fileset: extract language processing part to new module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38804
diff changeset
    46
19470
19ac0d8ee9a2 fileset: handle underbar in symbols
Matt Mackall <mpm@selenic.com>
parents: 19194
diff changeset
    47
globchars = ".*{}[]?/\\_"
14551
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
    48
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    49
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
def tokenize(program):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
    pos, l = 0, len(program)
32523
1fb0a85fb20e py3: use pycompat.bytestr so that we don't get ascii values
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32291
diff changeset
    52
    program = pycompat.bytestr(program)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
    while pos < l:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
        c = program[pos]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    55
        if c.isspace():  # skip inter-token whitespace
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
            pass
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    57
        elif c in "(),-:|&+!":  # handle simple operators
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    58
            yield (c, None, pos)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    59
        elif (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    60
            c in '"\'' or c == 'r' and program[pos : pos + 2] in ("r'", 'r"')
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    61
        ):  # handle quoted strings
12408
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    62
            if c == 'r':
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    63
                pos += 1
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    64
                c = program[pos]
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    65
                decode = lambda x: x
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    66
            else:
26233
d3dbb65c8dc6 fileset: handle error of string unescaping
Yuya Nishihara <yuya@tcha.org>
parents: 26195
diff changeset
    67
                decode = parser.unescapestr
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
            pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
            s = pos
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    70
            while pos < l:  # find closing quote
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
                d = program[pos]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    72
                if d == '\\':  # skip over escaped characters
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
                    pos += 2
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
                    continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
                if d == c:
12408
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    76
                    yield ('string', decode(program[s:pos]), s)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
                    break
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
                pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
            else:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
    80
                raise error.ParseError(_("unterminated string"), s)
14551
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
    81
        elif c.isalnum() or c in globchars or ord(c) > 127:
14513
85fe676c27e9 fileset: fix long line
Matt Mackall <mpm@selenic.com>
parents: 14511
diff changeset
    82
            # gather up a symbol/keyword
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
            s = pos
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
            pos += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    85
            while pos < l:  # find end of symbol
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
                d = program[pos]
14551
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
    87
                if not (d.isalnum() or d in globchars or ord(d) > 127):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
                    break
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
                pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
            sym = program[s:pos]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
    91
            if sym in keywords:  # operator keywords
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    92
                yield (sym, None, s)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
            else:
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    94
                yield ('symbol', sym, s)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
            pos -= 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
        else:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
    97
            raise error.ParseError(_("syntax error"), pos)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
        pos += 1
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    99
    yield ('end', None, pos)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   101
20208
61a47fd64f30 fileset, revset: do not use global parser object for thread safety
Yuya Nishihara <yuya@tcha.org>
parents: 19470
diff changeset
   102
def parse(expr):
25654
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25633
diff changeset
   103
    p = parser.parser(elements)
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25633
diff changeset
   104
    tree, pos = p.parse(tokenize(expr))
25252
ac381dd7a21f fileset: move validation of incomplete parsing to parse() function
Yuya Nishihara <yuya@tcha.org>
parents: 24408
diff changeset
   105
    if pos != len(expr):
ac381dd7a21f fileset: move validation of incomplete parsing to parse() function
Yuya Nishihara <yuya@tcha.org>
parents: 24408
diff changeset
   106
        raise error.ParseError(_("invalid token"), pos)
38804
d82c4d42b615 fileset: flatten 'or' nodes to unnest unionmatchers
Yuya Nishihara <yuya@tcha.org>
parents: 38803
diff changeset
   107
    return parser.simplifyinfixops(tree, {'list', 'or'})
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   109
35691
735f47b41521 fileset: make it robust for bad function calls
Yuya Nishihara <yuya@tcha.org>
parents: 35615
diff changeset
   110
def getsymbol(x):
735f47b41521 fileset: make it robust for bad function calls
Yuya Nishihara <yuya@tcha.org>
parents: 35615
diff changeset
   111
    if x and x[0] == 'symbol':
735f47b41521 fileset: make it robust for bad function calls
Yuya Nishihara <yuya@tcha.org>
parents: 35615
diff changeset
   112
        return x[1]
735f47b41521 fileset: make it robust for bad function calls
Yuya Nishihara <yuya@tcha.org>
parents: 35615
diff changeset
   113
    raise error.ParseError(_('not a symbol'))
735f47b41521 fileset: make it robust for bad function calls
Yuya Nishihara <yuya@tcha.org>
parents: 35615
diff changeset
   114
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   115
14551
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
   116
def getstring(x, err):
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
   117
    if x and (x[0] == 'string' or x[0] == 'symbol'):
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
   118
        return x[1]
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
   119
    raise error.ParseError(err)
68d814a3cefd fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents: 14513
diff changeset
   120
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   121
38805
b9162ea1b815 fileset: extract language processing part to new module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38804
diff changeset
   122
def getkindpat(x, y, allkinds, err):
35741
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   123
    kind = getsymbol(x)
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   124
    pat = getstring(y, err)
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   125
    if kind not in allkinds:
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   126
        raise error.ParseError(_("invalid pattern kind: %s") % kind)
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   127
    return '%s:%s' % (kind, pat)
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   128
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   129
35741
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   130
def getpattern(x, allkinds, err):
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   131
    if x and x[0] == 'kindpat':
38805
b9162ea1b815 fileset: extract language processing part to new module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38804
diff changeset
   132
        return getkindpat(x[1], x[2], allkinds, err)
35741
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   133
    return getstring(x, err)
73432eee0ac4 fileset: add kind:pat operator
Yuya Nishihara <yuya@tcha.org>
parents: 35739
diff changeset
   134
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   135
38598
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   136
def getlist(x):
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   137
    if not x:
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   138
        return []
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   139
    if x[0] == 'list':
38803
4dc498d61d86 fileset: flatten arguments list
Yuya Nishihara <yuya@tcha.org>
parents: 38772
diff changeset
   140
        return list(x[1:])
38598
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   141
    return [x]
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   142
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   143
38598
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   144
def getargs(x, min, max, err):
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   145
    l = getlist(x)
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   146
    if len(l) < min or len(l) > max:
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   147
        raise error.ParseError(err)
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   148
    return l
d046bf37f1ba fileset: move helper functions to top
Yuya Nishihara <yuya@tcha.org>
parents: 38414
diff changeset
   149
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   150
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   151
def _analyze(x):
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   152
    if x is None:
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   153
        return x
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   154
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   155
    op = x[0]
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   156
    if op in {'string', 'symbol'}:
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   157
        return x
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   158
    if op == 'kindpat':
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   159
        getsymbol(x[1])  # kind must be a symbol
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   160
        t = _analyze(x[2])
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   161
        return (op, x[1], t)
38827
48fc2a8af345 fileset: drop 'group' node from tree to be evaluated
Yuya Nishihara <yuya@tcha.org>
parents: 38826
diff changeset
   162
    if op == 'group':
48fc2a8af345 fileset: drop 'group' node from tree to be evaluated
Yuya Nishihara <yuya@tcha.org>
parents: 38826
diff changeset
   163
        return _analyze(x[1])
38828
3ea6ce609747 fileset: reject 'negate' node early while transforming parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38827
diff changeset
   164
    if op == 'negate':
3ea6ce609747 fileset: reject 'negate' node early while transforming parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38827
diff changeset
   165
        raise error.ParseError(_("can't use negate operator in this context"))
3ea6ce609747 fileset: reject 'negate' node early while transforming parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38827
diff changeset
   166
    if op == 'not':
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   167
        t = _analyze(x[1])
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   168
        return (op, t)
38832
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   169
    if op == 'and':
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   170
        ta = _analyze(x[1])
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   171
        tb = _analyze(x[2])
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   172
        return (op, ta, tb)
38832
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   173
    if op == 'minus':
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   174
        return _analyze(('and', x[1], ('not', x[2])))
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   175
    if op in {'list', 'or'}:
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   176
        ts = tuple(_analyze(y) for y in x[1:])
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   177
        return (op,) + ts
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   178
    if op == 'func':
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   179
        getsymbol(x[1])  # function name must be a symbol
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   180
        ta = _analyze(x[2])
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   181
        return (op, x[1], ta)
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   182
    raise error.ProgrammingError('invalid operator %r' % op)
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   183
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   184
38879
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   185
def _insertstatushints(x):
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   186
    """Insert hint nodes where status should be calculated (first path)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   187
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   188
    This works in bottom-up way, summing up status names and inserting hint
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   189
    nodes at 'and' and 'or' as needed. Thus redundant hint nodes may be left.
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   190
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   191
    Returns (status-names, new-tree) at the given subtree, where status-names
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   192
    is a sum of status names referenced in the given subtree.
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   193
    """
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   194
    if x is None:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   195
        return (), x
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   196
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   197
    op = x[0]
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   198
    if op in {'string', 'symbol', 'kindpat'}:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   199
        return (), x
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   200
    if op == 'not':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   201
        h, t = _insertstatushints(x[1])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   202
        return h, (op, t)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   203
    if op == 'and':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   204
        ha, ta = _insertstatushints(x[1])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   205
        hb, tb = _insertstatushints(x[2])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   206
        hr = ha + hb
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   207
        if ha and hb:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   208
            return hr, ('withstatus', (op, ta, tb), ('string', ' '.join(hr)))
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   209
        return hr, (op, ta, tb)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   210
    if op == 'or':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   211
        hs, ts = zip(*(_insertstatushints(y) for y in x[1:]))
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   212
        hr = sum(hs, ())
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   213
        if sum(bool(h) for h in hs) > 1:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   214
            return hr, ('withstatus', (op,) + ts, ('string', ' '.join(hr)))
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   215
        return hr, (op,) + ts
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   216
    if op == 'list':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   217
        hs, ts = zip(*(_insertstatushints(y) for y in x[1:]))
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   218
        return sum(hs, ()), (op,) + ts
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   219
    if op == 'func':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   220
        f = getsymbol(x[1])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   221
        # don't propagate 'ha' crossing a function boundary
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   222
        ha, ta = _insertstatushints(x[2])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   223
        if getattr(symbols.get(f), '_callstatus', False):
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   224
            return (f,), ('withstatus', (op, x[1], ta), ('string', f))
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   225
        return (), (op, x[1], ta)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   226
    raise error.ProgrammingError('invalid operator %r' % op)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   227
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   228
38879
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   229
def _mergestatushints(x, instatus):
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   230
    """Remove redundant status hint nodes (second path)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   231
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   232
    This is the top-down path to eliminate inner hint nodes.
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   233
    """
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   234
    if x is None:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   235
        return x
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   236
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   237
    op = x[0]
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   238
    if op == 'withstatus':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   239
        if instatus:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   240
            # drop redundant hint node
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   241
            return _mergestatushints(x[1], instatus)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   242
        t = _mergestatushints(x[1], instatus=True)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   243
        return (op, t, x[2])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   244
    if op in {'string', 'symbol', 'kindpat'}:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   245
        return x
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   246
    if op == 'not':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   247
        t = _mergestatushints(x[1], instatus)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   248
        return (op, t)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   249
    if op == 'and':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   250
        ta = _mergestatushints(x[1], instatus)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   251
        tb = _mergestatushints(x[2], instatus)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   252
        return (op, ta, tb)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   253
    if op in {'list', 'or'}:
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   254
        ts = tuple(_mergestatushints(y, instatus) for y in x[1:])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   255
        return (op,) + ts
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   256
    if op == 'func':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   257
        # don't propagate 'instatus' crossing a function boundary
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   258
        ta = _mergestatushints(x[2], instatus=False)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   259
        return (op, x[1], ta)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   260
    raise error.ProgrammingError('invalid operator %r' % op)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   261
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   262
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   263
def analyze(x):
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   264
    """Transform raw parsed tree to evaluatable tree which can be fed to
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   265
    optimize() or getmatch()
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   266
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   267
    All pseudo operations should be mapped to real operations or functions
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   268
    defined in methods or symbols table respectively.
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   269
    """
38879
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   270
    t = _analyze(x)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   271
    _h, t = _insertstatushints(t)
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   272
    return _mergestatushints(t, instatus=False)
38826
6371ab78c3b3 fileset: add phase to transform parsed tree
Yuya Nishihara <yuya@tcha.org>
parents: 38805
diff changeset
   273
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   274
38832
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   275
def _optimizeandops(op, ta, tb):
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   276
    if tb is not None and tb[0] == 'not':
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   277
        return ('minus', ta, tb[1])
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   278
    return (op, ta, tb)
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   279
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   280
38865
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   281
def _optimizeunion(xs):
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   282
    # collect string patterns so they can be compiled into a single regexp
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   283
    ws, ts, ss = [], [], []
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   284
    for x in xs:
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   285
        w, t = _optimize(x)
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   286
        if t is not None and t[0] in {'string', 'symbol', 'kindpat'}:
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   287
            ss.append(t)
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   288
            continue
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   289
        ws.append(w)
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   290
        ts.append(t)
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   291
    if ss:
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   292
        ws.append(WEIGHT_CHECK_FILENAME)
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   293
        ts.append(('patterns',) + tuple(ss))
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   294
    return ws, ts
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   295
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   296
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   297
def _optimize(x):
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   298
    if x is None:
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   299
        return 0, x
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   300
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   301
    op = x[0]
38879
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   302
    if op == 'withstatus':
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   303
        w, t = _optimize(x[1])
e79a69af1593 fileset: insert hints where status should be computed
Yuya Nishihara <yuya@tcha.org>
parents: 38865
diff changeset
   304
        return w, (op, t, x[2])
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   305
    if op in {'string', 'symbol'}:
38863
61ab546b71c3 fileset: introduce weight constants for readability
Yuya Nishihara <yuya@tcha.org>
parents: 38832
diff changeset
   306
        return WEIGHT_CHECK_FILENAME, x
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   307
    if op == 'kindpat':
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   308
        w, t = _optimize(x[2])
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   309
        return w, (op, x[1], t)
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   310
    if op == 'not':
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   311
        w, t = _optimize(x[1])
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   312
        return w, (op, t)
38831
b975c5801487 fileset: reorder 'and' expression to evaluate basic patterns first
Yuya Nishihara <yuya@tcha.org>
parents: 38829
diff changeset
   313
    if op == 'and':
b975c5801487 fileset: reorder 'and' expression to evaluate basic patterns first
Yuya Nishihara <yuya@tcha.org>
parents: 38829
diff changeset
   314
        wa, ta = _optimize(x[1])
b975c5801487 fileset: reorder 'and' expression to evaluate basic patterns first
Yuya Nishihara <yuya@tcha.org>
parents: 38829
diff changeset
   315
        wb, tb = _optimize(x[2])
b975c5801487 fileset: reorder 'and' expression to evaluate basic patterns first
Yuya Nishihara <yuya@tcha.org>
parents: 38829
diff changeset
   316
        if wa <= wb:
38832
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   317
            return wa, _optimizeandops(op, ta, tb)
38831
b975c5801487 fileset: reorder 'and' expression to evaluate basic patterns first
Yuya Nishihara <yuya@tcha.org>
parents: 38829
diff changeset
   318
        else:
38832
ca4de8ba5b5f fileset: optimize 'x and not y' to 'x - y'
Yuya Nishihara <yuya@tcha.org>
parents: 38831
diff changeset
   319
            return wb, _optimizeandops(op, tb, ta)
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   320
    if op == 'or':
38865
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   321
        ws, ts = _optimizeunion(x[1:])
899b4c74209c fileset: combine union of basic patterns into single matcher
Yuya Nishihara <yuya@tcha.org>
parents: 38864
diff changeset
   322
        if len(ts) == 1:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   323
            return ws[0], ts[0]  # 'or' operation is fully optimized out
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   324
        ts = tuple(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   325
            it[1] for it in sorted(enumerate(ts), key=lambda it: ws[it[0]])
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   326
        )
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   327
        return max(ws), (op,) + ts
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   328
    if op == 'list':
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   329
        ws, ts = zip(*(_optimize(y) for y in x[1:]))
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   330
        return sum(ws), (op,) + ts
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   331
    if op == 'func':
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   332
        f = getsymbol(x[1])
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   333
        w = getattr(symbols.get(f), '_weight', 1)
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   334
        wa, ta = _optimize(x[2])
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   335
        return w + wa, (op, x[1], ta)
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   336
    raise error.ProgrammingError('invalid operator %r' % op)
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   337
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   338
38829
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   339
def optimize(x):
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   340
    """Reorder/rewrite evaluatable tree for optimization
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   341
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   342
    All pseudo operations should be transformed beforehand.
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   343
    """
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   344
    _w, t = _optimize(x)
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   345
    return t
7e7e2b2ff284 fileset: add stub for weight-based optimization
Yuya Nishihara <yuya@tcha.org>
parents: 38828
diff changeset
   346
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38879
diff changeset
   347
25255
ad1d2c952889 fileset: pretty print syntax tree in debug output
Yuya Nishihara <yuya@tcha.org>
parents: 25252
diff changeset
   348
def prettyformat(tree):
ad1d2c952889 fileset: pretty print syntax tree in debug output
Yuya Nishihara <yuya@tcha.org>
parents: 25252
diff changeset
   349
    return parser.prettyformat(tree, ('string', 'symbol'))