1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# coding=utf-8
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Copyright © 2011 Intel Corporation
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Permission is hereby granted, free of charge, to any person obtaining a
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# copy of this software and associated documentation files (the "Software"),
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# to deal in the Software without restriction, including without limitation
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# and/or sell copies of the Software, and to permit persons to whom the
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Software is furnished to do so, subject to the following conditions:
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# The above copyright notice and this permission notice (including the next
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# paragraph) shall be included in all copies or substantial portions of the
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Software.
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# This file contains helper functions for manipulating sexps in Python.
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# We represent a sexp in Python using nested lists containing strings.
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# So, for example, the sexp (constant float (1.000000)) is represented
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# as ['constant', 'float', ['1.000000']].
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport re
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef check_sexp(sexp):
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Verify that the argument is a proper sexp.
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    That is, raise an exception if the argument is not a string or a
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    list, or if it contains anything that is not a string or a list at
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    any nesting level.
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if isinstance(sexp, list):
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for s in sexp:
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            check_sexp(s)
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    elif not isinstance(sexp, basestring):
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise Exception('Not a sexp: {0!r}'.format(sexp))
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef parse_sexp(sexp):
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Convert a string, of the form that would be output by mesa,
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    into a sexp represented as nested lists containing strings.
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    sexp_token_regexp = re.compile(
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        '[a-zA-Z_]+(@[0-9]+)?|[0-9]+(\\.[0-9]+)?|[^ \n]')
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    stack = [[]]
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for match in sexp_token_regexp.finditer(sexp):
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        token = match.group(0)
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if token == '(':
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stack.append([])
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        elif token == ')':
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if len(stack) == 1:
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                raise Exception('Unmatched )')
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            sexp = stack.pop()
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stack[-1].append(sexp)
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        else:
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stack[-1].append(token)
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if len(stack) != 1:
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise Exception('Unmatched (')
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if len(stack[0]) != 1:
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        raise Exception('Multiple sexps')
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return stack[0][0]
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef sexp_to_string(sexp):
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Convert a sexp, represented as nested lists containing strings,
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    into a single string of the form parseable by mesa.
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if isinstance(sexp, basestring):
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return sexp
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert isinstance(sexp, list)
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    result = ''
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for s in sexp:
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        sub_result = sexp_to_string(s)
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if result == '':
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            result = sub_result
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        elif '\n' not in result and '\n' not in sub_result and \
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                len(result) + len(sub_result) + 1 <= 70:
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            result += ' ' + sub_result
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        else:
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            result += '\n' + sub_result
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return '({0})'.format(result.replace('\n', '\n '))
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef sort_decls(sexp):
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Sort all toplevel variable declarations in sexp.
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    This is used to work around the fact that
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ir_reader::read_instructions reorders declarations.
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert isinstance(sexp, list)
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decls = []
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    other_code = []
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for s in sexp:
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if isinstance(s, list) and len(s) >= 4 and s[0] == 'declare':
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            decls.append(s)
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        else:
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            other_code.append(s)
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return sorted(decls) + other_code
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104