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