]>
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")