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