OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2012 the V8 project authors. All rights reserved. | 3 # Copyright 2012 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 if with_match: | 109 if with_match: |
110 raise ("With statements disallowed in natives: %s" % file) | 110 raise ("With statements disallowed in natives: %s" % file) |
111 | 111 |
112 | 112 |
113 def ExpandConstants(lines, constants): | 113 def ExpandConstants(lines, constants): |
114 for key, value in constants: | 114 for key, value in constants: |
115 lines = key.sub(str(value), lines) | 115 lines = key.sub(str(value), lines) |
116 return lines | 116 return lines |
117 | 117 |
118 | 118 |
119 def ExpandMacroDefinition(lines, pos, name_pattern, macro, expander): | |
120 pattern_match = name_pattern.search(lines, pos) | |
121 while pattern_match is not None: | |
122 # Scan over the arguments | |
123 height = 1 | |
124 start = pattern_match.start() | |
125 end = pattern_match.end() | |
126 assert lines[end - 1] == '(' | |
127 last_match = end | |
128 arg_index = [0] # Wrap state into array, to work around Python "scoping" | |
129 mapping = { } | |
130 def add_arg(str): | |
131 # Remember to expand recursively in the arguments | |
132 replacement = expander(str.strip()) | |
133 mapping[macro.args[arg_index[0]]] = replacement | |
134 arg_index[0] += 1 | |
135 while end < len(lines) and height > 0: | |
136 # We don't count commas at higher nesting levels. | |
137 if lines[end] == ',' and height == 1: | |
138 add_arg(lines[last_match:end]) | |
139 last_match = end + 1 | |
140 elif lines[end] in ['(', '{', '[']: | |
141 height = height + 1 | |
142 elif lines[end] in [')', '}', ']']: | |
143 height = height - 1 | |
144 end = end + 1 | |
145 # Remember to add the last match. | |
146 add_arg(lines[last_match:end-1]) | |
147 result = macro.expand(mapping) | |
148 # Replace the occurrence of the macro with the expansion | |
149 lines = lines[:start] + result + lines[end:] | |
150 pattern_match = name_pattern.search(lines, start + len(result)) | |
151 return lines | |
152 | |
119 def ExpandMacros(lines, macros): | 153 def ExpandMacros(lines, macros): |
120 # We allow macros to depend on the previously declared macros, but | 154 # We allow macros to depend on the previously declared macros, but |
121 # we don't allow self-dependecies or recursion. | 155 # we don't allow self-dependecies or recursion. |
122 for name_pattern, macro in reversed(macros): | 156 for name_pattern, macro in reversed(macros): |
123 pattern_match = name_pattern.search(lines, 0) | 157 def expander(s): |
124 while pattern_match is not None: | 158 return ExpandMacros(s, macros) |
125 # Scan over the arguments | 159 lines = ExpandMacroDefinition(lines, 0, name_pattern, macro, expander) |
126 height = 1 | |
127 start = pattern_match.start() | |
128 end = pattern_match.end() | |
129 assert lines[end - 1] == '(' | |
130 last_match = end | |
131 arg_index = [0] # Wrap state into array, to work around Python "scoping" | |
132 mapping = { } | |
133 def add_arg(str): | |
134 # Remember to expand recursively in the arguments | |
135 replacement = ExpandMacros(str.strip(), macros) | |
136 mapping[macro.args[arg_index[0]]] = replacement | |
137 arg_index[0] += 1 | |
138 while end < len(lines) and height > 0: | |
139 # We don't count commas at higher nesting levels. | |
140 if lines[end] == ',' and height == 1: | |
141 add_arg(lines[last_match:end]) | |
142 last_match = end + 1 | |
143 elif lines[end] in ['(', '{', '[']: | |
144 height = height + 1 | |
145 elif lines[end] in [')', '}', ']']: | |
146 height = height - 1 | |
147 end = end + 1 | |
148 # Remember to add the last match. | |
149 add_arg(lines[last_match:end-1]) | |
150 result = macro.expand(mapping) | |
151 # Replace the occurrence of the macro with the expansion | |
152 lines = lines[:start] + result + lines[end:] | |
153 pattern_match = name_pattern.search(lines, start + len(result)) | |
154 return lines | 160 return lines |
155 | 161 |
156 class TextMacro: | 162 class TextMacro: |
157 def __init__(self, args, body): | 163 def __init__(self, args, body): |
158 self.args = args | 164 self.args = args |
159 self.body = body | 165 self.body = body |
160 def expand(self, mapping): | 166 def expand(self, mapping): |
161 result = self.body | 167 result = self.body |
162 for key, value in mapping.items(): | 168 for key, value in mapping.items(): |
163 result = result.replace(key, value) | 169 result = result.replace(key, value) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 if python_match: | 209 if python_match: |
204 name = python_match.group(1) | 210 name = python_match.group(1) |
205 args = [match.strip() for match in python_match.group(2).split(',')] | 211 args = [match.strip() for match in python_match.group(2).split(',')] |
206 body = python_match.group(3).strip() | 212 body = python_match.group(3).strip() |
207 fun = eval("lambda " + ",".join(args) + ': ' + body) | 213 fun = eval("lambda " + ",".join(args) + ': ' + body) |
208 macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun))) | 214 macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun))) |
209 else: | 215 else: |
210 raise ("Illegal line: " + line) | 216 raise ("Illegal line: " + line) |
211 return (constants, macros) | 217 return (constants, macros) |
212 | 218 |
219 INLINE_MACRO_PATTERN = re.compile(r'macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*\n') | |
220 INLINE_MACRO_END_PATTERN = re.compile(r'endmacro\s*\n') | |
221 | |
222 def ExpandInlineMacros(lines, filename): | |
223 pos = 0 | |
224 while True: | |
rossberg
2013/10/28 10:40:55
Wait, you iterate over the whole file N times, onc
Dmitry Lomov (no reviews)
2013/11/02 12:56:16
Macros in macros + the macro scope is from definit
| |
225 macro_match = INLINE_MACRO_PATTERN.search(lines, pos) | |
226 if macro_match is None: | |
227 # no more macros | |
228 return lines | |
229 name = macro_match.group(1) | |
230 args = [match.strip() for match in macro_match.group(2).split(',')] | |
231 end_macro_match = INLINE_MACRO_END_PATTERN.search(lines, macro_match.end()); | |
232 if end_macro_match is None: | |
233 raise ("Macro %s unclosed in %s" % (name, filename)) | |
234 body = lines[macro_match.end():end_macro_match.start()] | |
235 | |
236 # remove macro definition | |
237 lines = lines[:macro_match.start()] + lines[end_macro_match.end():] | |
238 name_pattern = re.compile("\\b%s\\(" % name) | |
239 macro = TextMacro(args, body) | |
240 | |
241 # advance position to where the macro defintion was | |
242 pos = macro_match.start() | |
243 | |
244 def non_expander(s): | |
245 return s | |
246 lines = ExpandMacroDefinition(lines, pos, name_pattern, macro, non_expander) | |
213 | 247 |
214 HEADER_TEMPLATE = """\ | 248 HEADER_TEMPLATE = """\ |
215 // Copyright 2011 Google Inc. All Rights Reserved. | 249 // Copyright 2011 Google Inc. All Rights Reserved. |
216 | 250 |
217 // This file was generated from .js source files by GYP. If you | 251 // This file was generated from .js source files by GYP. If you |
218 // want to make changes to this file you should either change the | 252 // want to make changes to this file you should either change the |
219 // javascript source files or the GYP script. | 253 // javascript source files or the GYP script. |
220 | 254 |
221 #include "v8.h" | 255 #include "v8.h" |
222 #include "natives.h" | 256 #include "natives.h" |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 minifier = jsmin.JavaScriptMinifier() | 352 minifier = jsmin.JavaScriptMinifier() |
319 | 353 |
320 module_offset = 0 | 354 module_offset = 0 |
321 all_sources = [] | 355 all_sources = [] |
322 for module in modules: | 356 for module in modules: |
323 filename = str(module) | 357 filename = str(module) |
324 debugger = filename.endswith('-debugger.js') | 358 debugger = filename.endswith('-debugger.js') |
325 lines = ReadFile(filename) | 359 lines = ReadFile(filename) |
326 lines = ExpandConstants(lines, consts) | 360 lines = ExpandConstants(lines, consts) |
327 lines = ExpandMacros(lines, macros) | 361 lines = ExpandMacros(lines, macros) |
362 lines = RemoveCommentsAndTrailingWhitespace(lines) | |
rossberg
2013/10/28 10:40:55
Why is this needed?
Dmitry Lomov (no reviews)
2013/11/02 12:56:16
To handle cases like
macro abc(f,g,h) // this i
| |
363 lines = ExpandInlineMacros(lines, filename) | |
328 Validate(lines, filename) | 364 Validate(lines, filename) |
329 lines = minifier.JSMinify(lines) | 365 lines = minifier.JSMinify(lines) |
330 id = (os.path.split(filename)[1])[:-3] | 366 id = (os.path.split(filename)[1])[:-3] |
331 if debugger: id = id[:-9] | 367 if debugger: id = id[:-9] |
332 raw_length = len(lines) | 368 raw_length = len(lines) |
333 if debugger: | 369 if debugger: |
334 debugger_ids.append((id, raw_length, module_offset)) | 370 debugger_ids.append((id, raw_length, module_offset)) |
335 else: | 371 else: |
336 ids.append((id, raw_length, module_offset)) | 372 ids.append((id, raw_length, module_offset)) |
337 all_sources.append(lines) | 373 all_sources.append(lines) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 | 423 |
388 def main(): | 424 def main(): |
389 natives = sys.argv[1] | 425 natives = sys.argv[1] |
390 type = sys.argv[2] | 426 type = sys.argv[2] |
391 compression = sys.argv[3] | 427 compression = sys.argv[3] |
392 source_files = sys.argv[4:] | 428 source_files = sys.argv[4:] |
393 JS2C(source_files, [natives], { 'TYPE': type, 'COMPRESSION': compression }) | 429 JS2C(source_files, [natives], { 'TYPE': type, 'COMPRESSION': compression }) |
394 | 430 |
395 if __name__ == "__main__": | 431 if __name__ == "__main__": |
396 main() | 432 main() |
OLD | NEW |