blob: 4950113ca66f919afca915dc283b64f89b7a928d [file] [log] [blame]
bburg@apple.coma95212f2015-10-22 04:39:01 +00001#!/usr/bin/env python
2#
3# Copyright (c) 2014, 2015 Apple Inc. All rights reserved.
4# Copyright (c) 2014 University of Washington. All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25# THE POSSIBILITY OF SUCH DAMAGE.
26
27import logging
28import os.path
29import re
30from string import Template
31import json
32
33from builtins_model import BuiltinFunction, BuiltinObject
34from builtins_templates import BuiltinsGeneratorTemplates as Templates
35
36log = logging.getLogger('global')
37
38# These match WK_lcfirst and WK_ucfirst defined in CodeGenerator.pm.
39def WK_lcfirst(str):
40 str = str[:1].lower() + str[1:]
commit-queue@webkit.orgac1e56e2016-07-25 06:28:35 +000041 str = str.replace('dOM', 'dom')
bburg@apple.coma95212f2015-10-22 04:39:01 +000042 str = str.replace('uRL', 'url')
43 str = str.replace('jS', 'js')
44 str = str.replace('xML', 'xml')
45 str = str.replace('xSLT', 'xslt')
46 str = str.replace('cSS', 'css')
youenn.fablet@crf.canon.fr2f74c972015-12-11 07:45:09 +000047 str = str.replace('rTC', 'rtc')
bburg@apple.coma95212f2015-10-22 04:39:01 +000048 return str
49
50def WK_ucfirst(str):
51 str = str[:1].upper() + str[1:]
52 str = str.replace('Xml', 'XML')
53 str = str.replace('Svg', 'SVG')
54 return str
55
56class BuiltinsGenerator:
57 def __init__(self, model):
58 self._model = model
59
60 def model(self):
61 return self._model
62
63 # These methods are overridden by subclasses.
64
65 def generate_output(self):
66 pass
67
68 def output_filename(self):
69 pass
70
71
72 # Shared code generation methods.
73 def generate_license(self):
74 raw_license = Template(Templates.LicenseText).substitute(None)
75 copyrights = self._model.copyrights()
76 copyrights.sort()
77
78 license_block = []
79 license_block.append("/*")
80 for copyright in copyrights:
81 license_block.append(" * Copyright (c) %s" % copyright)
82 if len(copyrights) > 0:
83 license_block.append(" * ")
84
85 for line in raw_license.split('\n'):
86 license_block.append(" * " + line)
87
88 license_block.append(" */")
89
90 return '\n'.join(license_block)
91
92 def generate_includes_from_entries(self, entries):
93 includes = set()
94 for entry in entries:
95 (allowed_framework_names, data) = entry
96 (framework_name, header_path) = data
97
98 if self.model().framework.name not in allowed_framework_names:
99 continue
100 if self.model().framework.name != framework_name:
101 includes.add("#include <%s>" % header_path)
102 else:
103 includes.add("#include \"%s\"" % os.path.basename(header_path))
104
bburg@apple.com3e82ff02015-10-28 20:00:36 +0000105 return sorted(list(includes))
bburg@apple.coma95212f2015-10-22 04:39:01 +0000106
bburg@apple.com3e82ff02015-10-28 20:00:36 +0000107 def generate_primary_header_includes(self):
108 name, _ = os.path.splitext(self.output_filename())
109 return '\n'.join([
110 "#include \"config.h\"",
111 "#include \"%s.h\"" % name,
112 ])
bburg@apple.coma95212f2015-10-22 04:39:01 +0000113
114 def generate_embedded_code_string_section_for_function(self, function):
115 text = function.function_source
116 # Wrap it in parens to avoid adding to global scope.
117 text = "(function " + text[text.index("("):] + ")"
118 embeddedSourceLength = len(text) + 1 # For extra \n.
119 # Lazy way to escape quotes, I think?
120 textLines = json.dumps(text)[1:-1].split("\\n")
121 # This looks scary because we need the JS source itself to have newlines.
122 embeddedSource = '\n'.join([' "%s\\n" \\' % line for line in textLines])
123
124 constructAbility = "CannotConstruct"
125 if function.is_constructor:
126 constructAbility = "CanConstruct"
127
128 args = {
129 'codeName': BuiltinsGenerator.mangledNameForFunction(function) + 'Code',
130 'embeddedSource': embeddedSource,
131 'embeddedSourceLength': embeddedSourceLength,
sbarati@apple.com50b25722016-03-29 21:04:21 +0000132 'canConstruct': constructAbility,
133 'intrinsic': function.intrinsic
bburg@apple.coma95212f2015-10-22 04:39:01 +0000134 }
135
136 lines = []
137 lines.append("const JSC::ConstructAbility s_%(codeName)sConstructAbility = JSC::ConstructAbility::%(canConstruct)s;" % args);
138 lines.append("const int s_%(codeName)sLength = %(embeddedSourceLength)d;" % args);
sbarati@apple.com50b25722016-03-29 21:04:21 +0000139 lines.append("static const JSC::Intrinsic s_%(codeName)sIntrinsic = JSC::%(intrinsic)s;" % args);
bburg@apple.coma95212f2015-10-22 04:39:01 +0000140 lines.append("const char* s_%(codeName)s =\n%(embeddedSource)s\n;" % args);
141 return '\n'.join(lines)
142
143 # Helper methods.
144
145 @staticmethod
commit-queue@webkit.orgd1ae6592016-07-08 10:42:25 +0000146 def wrap_with_guard(guard, text):
147 if not guard:
148 return text
149 return '\n'.join([
150 '#if %s' % guard,
151 text,
152 '#endif // %s' % guard,
153 ])
154
155 @staticmethod
bburg@apple.coma95212f2015-10-22 04:39:01 +0000156 def mangledNameForObject(object):
157 if not isinstance(object, BuiltinObject):
158 raise Exception("Invalid argument passed to mangledNameForObject()")
159
160 def toCamel(match):
161 str = match.group(0)
162 return str[1].upper()
163 return re.sub(r'\.[a-z]', toCamel, object.object_name, flags=re.IGNORECASE)
164
165
166 @staticmethod
167 def mangledNameForFunction(function):
168 if not isinstance(function, BuiltinFunction):
169 raise Exception("Invalid argument passed to mangledNameForFunction()")
170
171 function_name = WK_ucfirst(function.function_name)
172
173 def toCamel(match):
174 str = match.group(0)
175 return str[1].upper()
176 function_name = re.sub(r'\.[a-z]', toCamel, function_name, flags=re.IGNORECASE)
177 if function.is_constructor:
178 function_name = function_name + "Constructor"
179
180 object_name = BuiltinsGenerator.mangledNameForObject(function.object)
181 return WK_lcfirst(object_name + function_name)