]>
git.saurik.com Git - apple/javascriptcore.git/blob - generate-js-builtins
2 # Copyright (C) 2014 Apple Inc. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
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.
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.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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.
58 generatorString
= "/* Generated by %s do not hand edit. */\n" % os
.path
.basename(__file__
)
60 functionHeadRegExp
= re
.compile(r
"function\s+\w+\s*\(.*?\)", re
.MULTILINE | re
.S
)
61 functionNameRegExp
= re
.compile(r
"function\s+(\w+)\s*\(", re
.MULTILINE | re
.S
)
62 functionParameterFinder
= re
.compile(r
"^function\s+(?:\w+)\s*\(((?:\s*\w+)?\s*(?:\s*,\s*\w+)*)?\)", re
.MULTILINE | re
.S
)
64 multilineCommentRegExp
= re
.compile(r
"\/\*.*?\*\/", re
.MULTILINE | re
.S
)
65 singleLineCommentRegExp
= re
.compile(r
"\/\/.*?\n", re
.MULTILINE | re
.S
)
67 def getCopyright(source
):
68 copyrightBlock
= multilineCommentRegExp
.findall(source
)[0]
69 copyrightBlock
= copyrightBlock
[:copyrightBlock
.index("Redistribution")]
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)", "")
84 copyRightLines
.append(line
)
86 return list(set(copyRightLines
))
90 def getFunctions(source
):
92 source
= multilineCommentRegExp
.sub("/**/", singleLineCommentRegExp
.sub("//\n", source
))
94 matches
= [ f
for f
in functionHeadRegExp
.finditer(source
)]
103 while source
[end
] != '{':
108 if source
[end
] == '{':
110 elif source
[end
] == '}':
113 functionBounds
.append((start
, end
))
115 functions
= [source
[start
:end
].strip() for (start
, end
) in functionBounds
]
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
= []
124 result
.append((functionName
, function
, functionParameters
))
128 def generateCode(source
):
129 inputFile
= open(source
, "r")
130 baseName
= os
.path
.basename(source
).replace(".js", "")
133 for line
in inputFile
:
134 source
= source
+ line
136 if sys
.platform
== "cygwin":
137 source
= source
.replace("\r\n", "\n")
138 return (baseName
, getFunctions(source
), getCopyright(source
))
140 def mangleName(object, name
):
141 qName
= object + "." + name
144 while i
< len(qName
):
146 mangledName
= mangledName
+ qName
[i
+ 1].upper()
149 mangledName
= mangledName
+ qName
[i
]
155 baseName
= sys
.argv
[-1]
156 builtin_definitions
= sys
.argv
[1:-1]
157 (output_base
, _
) = os
.path
.splitext(sys
.argv
[-1])
160 for 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
))
166 copyrights
= list(set(copyrights
))
169 for copyright
in copyrights
:
170 copyrightBody
= copyrightBody
+" * Copyright (C) " + copyright
+ "\n"
172 builtinsHeader
= open(output_base
+ ".h.tmp", "w")
173 builtinsImplementation
= open(output_base
+ ".cpp.tmp", "w")
174 copyrightText
= "/*\n" + copyrightBody
+ copyrightText
175 builtinsHeader
.write("""%s
178 #ifndef JSCBuiltins_H
179 #define JSCBuiltins_H
183 class FunctionExecutable;
185 class JSGlobalObject;
187 class UnlinkedFunctionExecutable;
190 FunctionExecutable* createBuiltinExecutable(VM&, UnlinkedFunctionExecutable*, const SourceCode&);
192 """ % (generatorString
, copyrightText
))
196 for (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")
215 builtinsHeader
.write("#define JSC_FOREACH_BUILTIN(macro)\\\n")
216 for (codeReference
, functionName
, source
) in codeReferences
:
217 builtinsHeader
.write(" macro(%s, %s, s_%sLength) \\\n" % (codeReference
, functionName
, codeReference
))
218 names
.append(functionName
)
220 builtinsHeader
.write("\n\n")
221 builtinsHeader
.write("#define JSC_FOREACH_BUILTIN_FUNCTION_NAME(macro) \\\n")
222 for name
in sorted(set(names
)):
223 builtinsHeader
.write(" macro(%s) \\\n" % name
)
224 builtinsHeader
.write("""
226 #define JSC_DECLARE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
227 FunctionExecutable* codeName##Generator(VM&);
229 JSC_FOREACH_BUILTIN(JSC_DECLARE_BUILTIN_GENERATOR)
230 #undef JSC_DECLARE_BUILTIN_GENERATOR
232 #define JSC_BUILTIN_EXISTS(name) defined JSC_BUILTIN_ ## name
240 builtinsImplementation
.write("""%s
245 #include "JSCBuiltins.h"
247 #include "BuiltinExecutables.h"
248 #include "Executable.h"
249 #include "JSCellInlines.h"
254 """ % (generatorString
, copyrightText
))
256 for (codeReference
, name
, source
) in codeReferences
:
257 source
= "(function " + source
[source
.index("("):] + ")"
258 lines
= json
.dumps(source
)[1:-1].split("\\n")
259 sourceLength
= len(source
)
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
266 builtinsImplementation
.write("""
267 FunctionExecutable* createBuiltinExecutable(VM& vm, UnlinkedFunctionExecutable* unlinkedExecutable, const SourceCode& source)
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);
281 #define JSC_DEFINE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
282 FunctionExecutable* codeName##Generator(VM& vm) \\
284 return createBuiltinExecutable(vm, vm.builtinExecutables()->codeName##Executable(), vm.builtinExecutables()->codeName##Source()); \\
287 JSC_FOREACH_BUILTIN(JSC_DEFINE_BUILTIN_GENERATOR)
288 #undef JSC_DEFINE_BUILTIN_GENERATOR
293 builtinsHeader
.close()
294 builtinsImplementation
.close()
296 if (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")
299 os
.remove(output_base
+ ".h.tmp")
301 if (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")
304 os
.remove(output_base
+ ".cpp.tmp")