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 |