]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - generate-js-builtins
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / generate-js-builtins
... / ...
CommitLineData
1#!/usr/bin/python
2# Copyright (C) 2014 Apple Inc. All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions
6# are met:
7# 1. Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9# 2. Redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution.
12#
13# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25import argparse
26import filecmp
27import fnmatch
28import os
29import re
30import shutil
31import sys
32import datetime
33import json
34
35parser = argparse.ArgumentParser()
36parser.add_argument('input_file', nargs='*', help='Input JS files which builtins generated from')
37parser.add_argument('--input-directory', help='All JS files will be used as input from this directory.')
38parser.add_argument('--output', help='path to output cpp or h file')
39args = parser.parse_args()
40
41copyrightText = """ *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
52 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
55 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
58 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
59 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */\n
63"""
64
65generatorString = "/* Generated by %s do not hand edit. */\n" % os.path.basename(__file__)
66
67functionHeadRegExp = re.compile(r"function\s+\w+\s*\(.*?\)", re.MULTILINE | re.S)
68functionNameRegExp = re.compile(r"function\s+(\w+)\s*\(", re.MULTILINE | re.S)
69functionParameterFinder = re.compile(r"^function\s+(?:\w+)\s*\(((?:\s*\w+)?\s*(?:\s*,\s*\w+)*)?\s*\)", re.MULTILINE | re.S)
70
71multilineCommentRegExp = re.compile(r"\/\*.*?\*\/", re.MULTILINE | re.S)
72singleLineCommentRegExp = re.compile(r"\/\/.*?\n", re.MULTILINE | re.S)
73
74def getCopyright(source):
75 copyrightBlock = multilineCommentRegExp.findall(source)[0]
76 copyrightBlock = copyrightBlock[:copyrightBlock.index("Redistribution")]
77 copyRightLines = []
78
79 for line in copyrightBlock.split("\n"):
80 line = line.replace("/*", "")
81 line = line.replace("*/", "")
82 line = line.replace("*", "")
83 line = line.replace("Copyright", "")
84 line = line.replace("copyright", "")
85 line = line.replace("(C)", "")
86 line = line.replace("(c)", "")
87 line = line.strip()
88 if len(line) == 0:
89 continue
90
91 copyRightLines.append(line)
92
93 return list(set(copyRightLines))
94
95
96
97def getFunctions(source):
98
99 source = multilineCommentRegExp.sub("/**/", singleLineCommentRegExp.sub("//\n", source))
100
101 matches = [ f for f in functionHeadRegExp.finditer(source)]
102 functionBounds = []
103 start = 0
104 end = 0
105 for match in matches:
106 start = match.start()
107 if start < end:
108 continue
109 end = match.end()
110 while source[end] != '{':
111 end = end + 1
112 depth = 1
113 end = end + 1
114 while depth > 0:
115 if source[end] == '{':
116 depth = depth + 1
117 elif source[end] == '}':
118 depth = depth - 1
119 end = end + 1
120 functionBounds.append((start, end))
121
122 functions = [source[start:end].strip() for (start, end) in functionBounds]
123 result = []
124 for function in functions:
125 function = multilineCommentRegExp.sub("", function)
126 functionName = functionNameRegExp.findall(function)[0]
127 functionParameters = functionParameterFinder.findall(function)[0].split(',')
128 if len(functionParameters[0]) == 0:
129 functionParameters = []
130
131 result.append((functionName, function, functionParameters))
132 return result
133
134
135def generateCode(source):
136 inputFile = open(source, "r")
137 baseName = os.path.basename(source).replace(".js", "")
138
139 source = ""
140 for line in inputFile:
141 source = source + line
142
143 if sys.platform == "cygwin":
144 source = source.replace("\r\n", "\n")
145 return (baseName, getFunctions(source), getCopyright(source))
146
147def mangleName(object, name):
148 qName = object + "." + name
149 mangledName = ""
150 i = 0
151 while i < len(qName):
152 if qName[i] == '.':
153 mangledName = mangledName + qName[i + 1].upper()
154 i = i + 1
155 else:
156 mangledName = mangledName + qName[i]
157 i = i + 1
158 return mangledName
159
160builtins = []
161copyrights = []
162(output_base, _) = os.path.splitext(args.output)
163
164if args.input_directory:
165 for file in os.listdir(args.input_directory):
166 args.input_file.append(os.path.join(args.input_directory, file))
167
168for file in args.input_file:
169 if fnmatch.fnmatch(file, '*.js'):
170 (baseName, functions, objectCopyrights) = generateCode(file)
171 copyrights.extend(objectCopyrights)
172 builtins.append((baseName, functions))
173
174copyrights = list(set(copyrights))
175
176copyrightBody = ""
177for copyright in copyrights:
178 copyrightBody = copyrightBody +" * Copyright (C) " + copyright + "\n"
179
180builtinsHeader = open(output_base + ".h.tmp", "w")
181builtinsImplementation = open(output_base + ".cpp.tmp", "w")
182copyrightText = "/*\n" + copyrightBody + copyrightText
183builtinsHeader.write("""%s
184%s
185
186#ifndef JSCBuiltins_H
187#define JSCBuiltins_H
188
189namespace JSC {
190
191class FunctionExecutable;
192class Identifier;
193class JSGlobalObject;
194class SourceCode;
195class UnlinkedFunctionExecutable;
196class VM;
197
198FunctionExecutable* createBuiltinExecutable(VM&, UnlinkedFunctionExecutable*, const SourceCode&);
199
200""" % (generatorString, copyrightText))
201
202codeReferences = []
203
204for (objectName, functions) in builtins:
205 print("Generating bindings for the %s builtin." % objectName)
206 builtinsHeader.write("/* %s functions */\n" % objectName)
207 for (name, implementation, _) in functions:
208 mangledName = mangleName(objectName, name)
209 mangledName = mangledName[0].lower() + mangledName[1:] + "Code"
210 codeReferences.append((mangledName, name, implementation))
211 builtinsHeader.write("extern const char* s_%s;\n" % mangledName)
212 builtinsHeader.write("extern const int s_%sLength;\n" % mangledName)
213 builtinsHeader.write("\n")
214 builtinsHeader.write("#define JSC_FOREACH_%s_BUILTIN(macro) \\\n" % objectName.replace(".", "_").upper())
215 for (name, implementation, arguments) in functions:
216 mangledName = mangleName(objectName, name)
217 builtinsHeader.write(" macro(%s, %s, %d) \\\n" % (name, mangledName, len(arguments)))
218 builtinsHeader.write("\n")
219 for (name, implementation, arguments) in functions:
220 builtinsHeader.write("#define JSC_BUILTIN_%s 1\n" % mangleName(objectName, name).upper())
221 builtinsHeader.write("\n\n")
222names = []
223builtinsHeader.write("#define JSC_FOREACH_BUILTIN(macro)\\\n")
224for (codeReference, functionName, source) in codeReferences:
225 builtinsHeader.write(" macro(%s, %s, s_%sLength) \\\n" % (codeReference, functionName, codeReference))
226 names.append(functionName)
227
228builtinsHeader.write("\n\n")
229builtinsHeader.write("#define JSC_FOREACH_BUILTIN_FUNCTION_NAME(macro) \\\n")
230for name in sorted(set(names)):
231 builtinsHeader.write(" macro(%s) \\\n" % name)
232builtinsHeader.write("""
233
234#define JSC_DECLARE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
235 FunctionExecutable* codeName##Generator(VM&);
236
237JSC_FOREACH_BUILTIN(JSC_DECLARE_BUILTIN_GENERATOR)
238#undef JSC_DECLARE_BUILTIN_GENERATOR
239
240#define JSC_BUILTIN_EXISTS(name) defined JSC_BUILTIN_ ## name
241
242}
243
244#endif
245
246""")
247
248builtinsImplementation.write("""%s
249%s
250
251#include "config.h"
252
253#include "JSCBuiltins.h"
254
255#include "BuiltinExecutables.h"
256#include "Executable.h"
257#include "JSCellInlines.h"
258#include "VM.h"
259
260namespace JSC {
261
262""" % (generatorString, copyrightText))
263
264for (codeReference, name, source) in codeReferences:
265 source = "(function " + source[source.index("("):] + ")"
266 lines = json.dumps(source)[1:-1].split("\\n")
267 sourceLength = len(source)
268 source = ""
269 for line in lines:
270 source = source + (" \"%s\\n\" \\\n" % line)
271 builtinsImplementation.write("const char* s_%s =\n%s;\n\n" % (codeReference, source))
272 builtinsImplementation.write("const int s_%sLength = %d;\n\n" % (codeReference, sourceLength + 1)) # + 1 for \n
273
274builtinsImplementation.write("""
275#define JSC_DEFINE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
276FunctionExecutable* codeName##Generator(VM& vm) \\
277{ \\
278 return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source()); \\
279}
280
281JSC_FOREACH_BUILTIN(JSC_DEFINE_BUILTIN_GENERATOR)
282#undef JSC_DEFINE_BUILTIN_GENERATOR
283}
284
285""")
286
287builtinsHeader.close()
288builtinsImplementation.close()
289
290if (not os.path.exists(output_base + ".h")) or (not filecmp.cmp(output_base + ".h.tmp", output_base + ".h", shallow=False)):
291 if (os.path.exists(output_base + ".h")):
292 os.remove(output_base + ".h")
293 os.rename(output_base + ".h.tmp", output_base + ".h")
294else:
295 os.remove(output_base + ".h.tmp")
296
297if (not os.path.exists(output_base + ".cpp")) or (not filecmp.cmp(output_base + ".cpp.tmp", output_base + ".cpp", shallow=False)):
298 if (os.path.exists(output_base + ".cpp")):
299 os.remove(output_base + ".cpp")
300 os.rename(output_base + ".cpp.tmp", output_base + ".cpp")
301else:
302 os.remove(output_base + ".cpp.tmp")