OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2006-2008 the V8 project authors. All rights reserved. | 3 # Copyright 2006-2008 the V8 project authors. All rights reserved. |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 # allowed in the natives files. | 97 # allowed in the natives files. |
98 eval_match = EVAL_PATTERN.search(lines) | 98 eval_match = EVAL_PATTERN.search(lines) |
99 if eval_match: | 99 if eval_match: |
100 raise ("Eval disallowed in natives: %s" % file) | 100 raise ("Eval disallowed in natives: %s" % file) |
101 with_match = WITH_PATTERN.search(lines) | 101 with_match = WITH_PATTERN.search(lines) |
102 if with_match: | 102 if with_match: |
103 raise ("With statements disallowed in natives: %s" % file) | 103 raise ("With statements disallowed in natives: %s" % file) |
104 | 104 |
105 | 105 |
106 def ExpandConstants(lines, constants): | 106 def ExpandConstants(lines, constants): |
107 for key, value in constants.items(): | 107 for key, value in constants: |
108 lines = lines.replace(key, str(value)) | 108 lines = key.sub(str(value), lines) |
109 return lines | 109 return lines |
110 | 110 |
111 | 111 |
112 def ExpandMacros(lines, macros): | 112 def ExpandMacros(lines, macros): |
113 for name, macro in macros.items(): | 113 # We allow macros to depend on the previously declared macros, but |
114 start = lines.find(name + '(', 0) | 114 # we don't allow self-dependecies or recursion. |
115 while start != -1: | 115 for name_pattern, macro in reversed(macros): |
| 116 pattern_match = name_pattern.search(lines, 0) |
| 117 while pattern_match is not None: |
116 # Scan over the arguments | 118 # Scan over the arguments |
117 assert lines[start + len(name)] == '(' | |
118 height = 1 | 119 height = 1 |
119 end = start + len(name) + 1 | 120 start = pattern_match.start() |
| 121 end = pattern_match.end() |
| 122 assert lines[end - 1] == '(' |
120 last_match = end | 123 last_match = end |
121 arg_index = 0 | 124 arg_index = 0 |
122 mapping = { } | 125 mapping = { } |
123 def add_arg(str): | 126 def add_arg(str): |
124 # Remember to expand recursively in the arguments | 127 # Remember to expand recursively in the arguments |
125 replacement = ExpandMacros(str.strip(), macros) | 128 replacement = ExpandMacros(str.strip(), macros) |
126 mapping[macro.args[arg_index]] = replacement | 129 mapping[macro.args[arg_index]] = replacement |
127 while end < len(lines) and height > 0: | 130 while end < len(lines) and height > 0: |
128 # We don't count commas at higher nesting levels. | 131 # We don't count commas at higher nesting levels. |
129 if lines[end] == ',' and height == 1: | 132 if lines[end] == ',' and height == 1: |
130 add_arg(lines[last_match:end]) | 133 add_arg(lines[last_match:end]) |
131 last_match = end + 1 | 134 last_match = end + 1 |
132 elif lines[end] in ['(', '{', '[']: | 135 elif lines[end] in ['(', '{', '[']: |
133 height = height + 1 | 136 height = height + 1 |
134 elif lines[end] in [')', '}', ']']: | 137 elif lines[end] in [')', '}', ']']: |
135 height = height - 1 | 138 height = height - 1 |
136 end = end + 1 | 139 end = end + 1 |
137 # Remember to add the last match. | 140 # Remember to add the last match. |
138 add_arg(lines[last_match:end-1]) | 141 add_arg(lines[last_match:end-1]) |
139 result = macro.expand(mapping) | 142 result = macro.expand(mapping) |
140 # Replace the occurrence of the macro with the expansion | 143 # Replace the occurrence of the macro with the expansion |
141 lines = lines[:start] + result + lines[end:] | 144 lines = lines[:start] + result + lines[end:] |
142 start = lines.find(name + '(', end) | 145 pattern_match = name_pattern.search(lines, start + len(result)) |
143 return lines | 146 return lines |
144 | 147 |
145 class TextMacro: | 148 class TextMacro: |
146 def __init__(self, args, body): | 149 def __init__(self, args, body): |
147 self.args = args | 150 self.args = args |
148 self.body = body | 151 self.body = body |
149 def expand(self, mapping): | 152 def expand(self, mapping): |
150 result = self.body | 153 result = self.body |
151 for key, value in mapping.items(): | 154 for key, value in mapping.items(): |
152 result = result.replace(key, value) | 155 result = result.replace(key, value) |
153 return result | 156 return result |
154 | 157 |
155 class PythonMacro: | 158 class PythonMacro: |
156 def __init__(self, args, fun): | 159 def __init__(self, args, fun): |
157 self.args = args | 160 self.args = args |
158 self.fun = fun | 161 self.fun = fun |
159 def expand(self, mapping): | 162 def expand(self, mapping): |
160 args = [] | 163 args = [] |
161 for arg in self.args: | 164 for arg in self.args: |
162 args.append(mapping[arg]) | 165 args.append(mapping[arg]) |
163 return str(self.fun(*args)) | 166 return str(self.fun(*args)) |
164 | 167 |
165 CONST_PATTERN = re.compile(r'^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$') | 168 CONST_PATTERN = re.compile(r'^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$') |
166 MACRO_PATTERN = re.compile(r'^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*
);$') | 169 MACRO_PATTERN = re.compile(r'^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*
);$') |
167 PYTHON_MACRO_PATTERN = re.compile(r'^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*
)\)\s*=\s*([^;]*);$') | 170 PYTHON_MACRO_PATTERN = re.compile(r'^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*
)\)\s*=\s*([^;]*);$') |
168 | 171 |
| 172 |
169 def ReadMacros(lines): | 173 def ReadMacros(lines): |
170 constants = { } | 174 constants = [] |
171 macros = { } | 175 macros = [] |
172 for line in lines: | 176 for line in lines: |
173 hash = line.find('#') | 177 hash = line.find('#') |
174 if hash != -1: line = line[:hash] | 178 if hash != -1: line = line[:hash] |
175 line = line.strip() | 179 line = line.strip() |
176 if len(line) is 0: continue | 180 if len(line) is 0: continue |
177 const_match = CONST_PATTERN.match(line) | 181 const_match = CONST_PATTERN.match(line) |
178 if const_match: | 182 if const_match: |
179 name = const_match.group(1) | 183 name = const_match.group(1) |
180 value = const_match.group(2).strip() | 184 value = const_match.group(2).strip() |
181 constants[name] = value | 185 constants.append((re.compile("\\b%s\\b" % name), value)) |
182 else: | 186 else: |
183 macro_match = MACRO_PATTERN.match(line) | 187 macro_match = MACRO_PATTERN.match(line) |
184 if macro_match: | 188 if macro_match: |
185 name = macro_match.group(1) | 189 name = macro_match.group(1) |
186 args = map(string.strip, macro_match.group(2).split(',')) | 190 args = map(string.strip, macro_match.group(2).split(',')) |
187 body = macro_match.group(3).strip() | 191 body = macro_match.group(3).strip() |
188 macros[name] = TextMacro(args, body) | 192 macros.append((re.compile("\\b%s\\(" % name), TextMacro(args, body))) |
189 else: | 193 else: |
190 python_match = PYTHON_MACRO_PATTERN.match(line) | 194 python_match = PYTHON_MACRO_PATTERN.match(line) |
191 if python_match: | 195 if python_match: |
192 name = python_match.group(1) | 196 name = python_match.group(1) |
193 args = map(string.strip, python_match.group(2).split(',')) | 197 args = map(string.strip, python_match.group(2).split(',')) |
194 body = python_match.group(3).strip() | 198 body = python_match.group(3).strip() |
195 fun = eval("lambda " + ",".join(args) + ': ' + body) | 199 fun = eval("lambda " + ",".join(args) + ': ' + body) |
196 macros[name] = PythonMacro(args, fun) | 200 macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun))) |
197 else: | 201 else: |
198 raise ("Illegal line: " + line) | 202 raise ("Illegal line: " + line) |
199 return (constants, macros) | 203 return (constants, macros) |
200 | 204 |
201 | 205 |
202 HEADER_TEMPLATE = """\ | 206 HEADER_TEMPLATE = """\ |
203 // Copyright 2008 Google Inc. All Rights Reserved. | 207 // Copyright 2008 Google Inc. All Rights Reserved. |
204 | 208 |
205 // This file was generated from .js source files by SCons. If you | 209 // This file was generated from .js source files by SCons. If you |
206 // want to make changes to this file you should either change the | 210 // want to make changes to this file you should either change the |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 | 371 |
368 def main(): | 372 def main(): |
369 natives = sys.argv[1] | 373 natives = sys.argv[1] |
370 natives_empty = sys.argv[2] | 374 natives_empty = sys.argv[2] |
371 type = sys.argv[3] | 375 type = sys.argv[3] |
372 source_files = sys.argv[4:] | 376 source_files = sys.argv[4:] |
373 JS2C(source_files, [natives, natives_empty], { 'TYPE': type }) | 377 JS2C(source_files, [natives, natives_empty], { 'TYPE': type }) |
374 | 378 |
375 if __name__ == "__main__": | 379 if __name__ == "__main__": |
376 main() | 380 main() |
OLD | NEW |