]> git.saurik.com Git - apple/javascriptcore.git/blame - generate-js-builtins
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / generate-js-builtins
CommitLineData
81345200
A
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
ed1e77d3 25import argparse
81345200
A
26import filecmp
27import fnmatch
28import os
29import re
30import shutil
31import sys
32import datetime
33import json
34
ed1e77d3
A
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
81345200
A
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)
ed1e77d3 69functionParameterFinder = re.compile(r"^function\s+(?:\w+)\s*\(((?:\s*\w+)?\s*(?:\s*,\s*\w+)*)?\s*\)", re.MULTILINE | re.S)
81345200
A
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 = []
ed1e77d3
A
161copyrights = []
162(output_base, _) = os.path.splitext(args.output)
81345200 163
ed1e77d3
A
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))
81345200 167
ed1e77d3 168for file in args.input_file:
81345200
A
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("""
81345200
A
275#define JSC_DEFINE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
276FunctionExecutable* codeName##Generator(VM& vm) \\
277{ \\
ed1e77d3 278 return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source()); \\
81345200
A
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)):
ed1e77d3
A
291 if (os.path.exists(output_base + ".h")):
292 os.remove(output_base + ".h")
81345200
A
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)):
ed1e77d3
A
298 if (os.path.exists(output_base + ".cpp")):
299 os.remove(output_base + ".cpp")
81345200
A
300 os.rename(output_base + ".cpp.tmp", output_base + ".cpp")
301else:
302 os.remove(output_base + ".cpp.tmp")