Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 the V8 project authors. All rights reserved. | 2 # Copyright 2014 the V8 project authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import js2c | 6 import js2c |
| 7 import os | 7 import os |
| 8 import re | 8 import re |
| 9 import sys | 9 import sys |
| 10 | 10 |
| 11 FILENAME = "src/runtime.cc" | 11 FILENAME = "src/runtime.h" |
| 12 FUNCTION = re.compile("^RUNTIME_FUNCTION\(Runtime_(\w+)") | 12 LISTHEAD = re.compile("#define\s+(\w+LIST\w*)\((\w+)\)") |
| 13 FUNCTIONEND = "}\n" | 13 LISTBODY = re.compile(".*\\\\$") |
|
Jakob Kummerow
2014/09/24 10:53:13
nit: if you use Python's r"..." notation, that'll
Yang
2014/09/24 11:52:17
Done.
The loop is written in a way to append the
| |
| 14 MACRO = re.compile(r"^#define ([^ ]+)\(([^)]*)\) *([^\\]*)\\?\n$") | 14 BLACKLIST = ['INLINE_FUNCTION_LIST'] |
| 15 FIRST_WORD = re.compile("^\s*(.*?)[\s({\[]") | |
| 16 | |
| 17 # Expand these macros, they define further runtime functions. | |
| 18 EXPAND_MACROS = [ | |
| 19 "BUFFER_VIEW_GETTER", | |
| 20 "DATA_VIEW_GETTER", | |
| 21 "DATA_VIEW_SETTER", | |
| 22 "ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION", | |
| 23 "FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION", | |
| 24 "RUNTIME_UNARY_MATH", | |
| 25 "TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION", | |
| 26 ] | |
| 27 | 15 |
| 28 | 16 |
| 29 class Function(object): | 17 class Function(object): |
| 30 def __init__(self, match): | 18 def __init__(self, match): |
| 31 self.name = match.group(1) | 19 self.name = match.group(1).strip() |
| 32 | 20 |
| 33 | 21 |
| 34 class Macro(object): | 22 def ListName(list): |
| 35 def __init__(self, match): | 23 return LISTHEAD.match(list[0]).group(1) |
| 36 self.name = match.group(1) | |
| 37 self.args = [s.strip() for s in match.group(2).split(",")] | |
| 38 self.lines = [] | |
| 39 self.indentation = 0 | |
| 40 self.AddLine(match.group(3)) | |
| 41 | |
| 42 def AddLine(self, line): | |
| 43 if not line: return | |
| 44 if not self.lines: | |
| 45 # This is the first line, detect indentation. | |
| 46 self.indentation = len(line) - len(line.lstrip()) | |
| 47 line = line.rstrip("\\\n ") | |
| 48 if not line: return | |
| 49 assert len(line[:self.indentation].strip()) == 0, \ | |
| 50 ("expected whitespace: '%s', full line: '%s'" % | |
| 51 (line[:self.indentation], line)) | |
| 52 line = line[self.indentation:] | |
| 53 if not line: return | |
| 54 self.lines.append(line + "\n") | |
| 55 | |
| 56 def Finalize(self): | |
| 57 for arg in self.args: | |
| 58 pattern = re.compile(r"(##|\b)%s(##|\b)" % arg) | |
| 59 for i in range(len(self.lines)): | |
| 60 self.lines[i] = re.sub(pattern, "%%(%s)s" % arg, self.lines[i]) | |
| 61 | |
| 62 def FillIn(self, arg_values): | |
| 63 filler = {} | |
| 64 assert len(arg_values) == len(self.args) | |
| 65 for i in range(len(self.args)): | |
| 66 filler[self.args[i]] = arg_values[i] | |
| 67 result = [] | |
| 68 for line in self.lines: | |
| 69 result.append(line % filler) | |
| 70 return result | |
| 71 | 24 |
| 72 | 25 |
| 73 def ReadFileAndExpandMacros(filename): | 26 def ListMacroRe(list): |
| 74 found_macros = {} | 27 macro = LISTHEAD.match(list[0]).group(2) |
| 28 re_string = "\s*%s\((\w+)" % macro | |
| 29 return re.compile(re_string) | |
| 30 | |
| 31 | |
| 32 def ReadFile(filename): | |
| 75 expanded_lines = [] | 33 expanded_lines = [] |
| 76 with open(filename, "r") as f: | 34 with open(filename, "r") as f: |
| 77 found_macro = None | |
| 78 for line in f: | 35 for line in f: |
| 79 if found_macro is not None: | |
| 80 found_macro.AddLine(line) | |
| 81 if not line.endswith("\\\n"): | |
| 82 found_macro.Finalize() | |
| 83 found_macro = None | |
| 84 continue | |
| 85 | |
| 86 match = MACRO.match(line) | |
| 87 if match: | |
| 88 found_macro = Macro(match) | |
| 89 if found_macro.name in EXPAND_MACROS: | |
| 90 found_macros[found_macro.name] = found_macro | |
| 91 else: | |
| 92 found_macro = None | |
| 93 continue | |
| 94 | |
| 95 match = FIRST_WORD.match(line) | |
| 96 if match: | |
| 97 first_word = match.group(1) | |
| 98 if first_word in found_macros: | |
| 99 MACRO_CALL = re.compile("%s\(([^)]*)\)" % first_word) | |
| 100 match = MACRO_CALL.match(line) | |
| 101 assert match | |
| 102 args = [s.strip() for s in match.group(1).split(",")] | |
| 103 expanded_lines += found_macros[first_word].FillIn(args) | |
| 104 continue | |
| 105 | |
| 106 expanded_lines.append(line) | 36 expanded_lines.append(line) |
| 107 return expanded_lines | 37 return expanded_lines |
| 108 | 38 |
| 109 | 39 |
| 40 def FindLists(lines): | |
| 41 lists = [] | |
| 42 current_list = [] | |
| 43 for line in lines: | |
|
Jakob Kummerow
2014/09/24 10:53:13
I'd inline ReadFile here and iterate over the open
Yang
2014/09/24 11:52:17
Done.
| |
| 44 if len(current_list) == 0: | |
| 45 match = LISTHEAD.match(line) | |
| 46 if match: | |
| 47 current_list.append(line) | |
| 48 else: | |
| 49 current_list.append(line) | |
| 50 match = LISTBODY.match(line) | |
| 51 if not match: | |
| 52 lists.append(current_list) | |
| 53 current_list = [] | |
| 54 return lists | |
| 55 | |
| 56 | |
| 110 # Detects runtime functions by parsing FILENAME. | 57 # Detects runtime functions by parsing FILENAME. |
| 111 def FindRuntimeFunctions(): | 58 def FindRuntimeFunctions(): |
| 112 functions = [] | 59 functions = [] |
| 113 expanded_lines = ReadFileAndExpandMacros(FILENAME) | 60 lines = ReadFile(FILENAME) |
| 114 function = None | 61 lists = FindLists(lines) |
| 115 partial_line = "" | 62 for list in lists: |
| 116 for line in expanded_lines: | 63 if ListName(list) in BLACKLIST: |
|
Jakob Kummerow
2014/09/24 10:53:13
I'd be inclined to move this logic into the first
Yang
2014/09/24 11:52:17
Done.
| |
| 117 # Multi-line definition support, ignoring macros. | |
| 118 if line.startswith("RUNTIME_FUNCTION") and not line.endswith("{\n"): | |
| 119 if line.endswith("\\\n"): continue | |
| 120 partial_line = line.rstrip() | |
| 121 continue | 64 continue |
| 122 if partial_line: | 65 function_re = ListMacroRe(list) |
| 123 partial_line += " " + line.strip() | 66 for line in list: |
| 124 if partial_line.endswith("{"): | 67 match = function_re.match(line) |
| 125 line = partial_line | 68 if match: |
| 126 partial_line = "" | 69 functions.append(Function(match)) |
| 127 else: | 70 print(match.group(1)) |
|
Jakob Kummerow
2014/09/24 10:53:13
debugging leftover?
Yang
2014/09/24 11:52:17
Done.
| |
| 128 continue | |
| 129 | |
| 130 match = FUNCTION.match(line) | |
| 131 if match: | |
| 132 function = Function(match) | |
| 133 continue | |
| 134 if function is None: continue | |
| 135 | |
| 136 if line == FUNCTIONEND: | |
| 137 if function is not None: | |
| 138 functions.append(function) | |
| 139 function = None | |
| 140 return functions | 71 return functions |
| 141 | 72 |
| 142 | 73 |
| 143 class Builtin(object): | 74 class Builtin(object): |
| 144 def __init__(self, match): | 75 def __init__(self, match): |
| 145 self.name = match.group(1) | 76 self.name = match.group(1) |
| 146 | 77 |
| 147 | 78 |
| 148 def FindJSNatives(): | 79 def FindJSNatives(): |
| 149 PATH = "src" | 80 PATH = "src" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 | 123 |
| 193 if errors > 0: | 124 if errors > 0: |
| 194 return 1 | 125 return 1 |
| 195 print("Runtime/Natives name clashes: checked %d/%d functions, all good." % | 126 print("Runtime/Natives name clashes: checked %d/%d functions, all good." % |
| 196 (len(functions), len(natives))) | 127 (len(functions), len(natives))) |
| 197 return 0 | 128 return 0 |
| 198 | 129 |
| 199 | 130 |
| 200 if __name__ == "__main__": | 131 if __name__ == "__main__": |
| 201 sys.exit(Main()) | 132 sys.exit(Main()) |
| OLD | NEW |