| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 4 # for details. All rights reserved. Use of this source code is governed by a | 4 # for details. All rights reserved. Use of this source code is governed by a |
| 5 # BSD-style license that can be found in the LICENSE file. | 5 # BSD-style license that can be found in the LICENSE file. |
| 6 # | 6 # |
| 7 | 7 |
| 8 """ | 8 """ |
| 9 Frogpad is used to compile .dart files to javascript. | 9 Frogpad is used to compile .dart files to javascript. |
| 10 | 10 |
| 11 This is accomplished by first creating an html file (usually called | 11 This is accomplished by first creating an html file (usually called |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 </script> | 100 </script> |
| 101 </body> | 101 </body> |
| 102 </html> | 102 </html> |
| 103 """ | 103 """ |
| 104 | 104 |
| 105 # This finds everything after the word "Output:" in the html page. | 105 # This finds everything after the word "Output:" in the html page. |
| 106 # (Note, because the javascript we're fishing out spans multiple lines | 106 # (Note, because the javascript we're fishing out spans multiple lines |
| 107 # we need to use the DOTALL switch here.) | 107 # we need to use the DOTALL switch here.) |
| 108 OUTPUT_JAVASCRIPT_REGEX = re.compile(".*\nOutput:(.*)#EOF", re.DOTALL) | 108 OUTPUT_JAVASCRIPT_REGEX = re.compile(".*\nOutput:(.*)#EOF", re.DOTALL) |
| 109 | 109 |
| 110 # If the frogpad.dart encounters a compilation error, the generated |
| 111 # javascript will start with the word 'throw'. |
| 112 COMPILATION_ERROR_REGEX = re.compile(r"\s*throw\s") |
| 113 |
| 110 # We use "application/inert" here to make the browser ignore the | 114 # We use "application/inert" here to make the browser ignore the |
| 111 # these script tags. (frogpad.dart will fish out the contents as needed.) | 115 # these script tags. (frogpad.dart will fish out the contents as needed.) |
| 112 # | 116 # |
| 113 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> | 117 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> |
| 114 {{contents}} | 118 {{contents}} |
| 115 </script> | 119 </script> |
| 116 """ | 120 """ |
| 117 | 121 |
| 118 # Regex that finds #import, #source and #native directives in .dart files. | 122 # Regex that finds #import, #source and #native directives in .dart files. |
| 119 # match.group(1) = "import", "source" or "native" | 123 # match.group(1) = "import", "source" or "native" |
| 120 # match.group(2) = url of file being imported | 124 # match.group(2) = url of file being imported |
| 121 DIRECTIVE_RE = re.compile(r"^#(import|source|native)\([\"']([^\"']*)[\"']") | 125 DIRECTIVE_RE = re.compile(r"^#(import|source|native)\([\"']([^\"']*)[\"']") |
| 122 | 126 |
| 123 # id of script tag that holds name of the top dart file to be compiled, | 127 # id of script tag that holds name of the top dart file to be compiled, |
| 124 # (This file name passed will be passed to the frog compiler by frogpad.dart.) | 128 # (This file name passed will be passed to the frog compiler by frogpad.dart.) |
| 125 MAIN_ID = "main_id" | 129 MAIN_ID = "main_id" |
| 126 | 130 |
| 127 DART_LIBRARIES = { | 131 DART_LIBRARIES = { |
| 128 "core": "lib/corelib.dart", | 132 "core": "lib/corelib.dart", |
| 129 "coreimpl": "lib/corelib_impl.dart", | 133 "coreimpl": "lib/corelib_impl.dart", |
| 130 "dom": "../client/dom/frog/dom_frog.dart", | 134 "dom": "../client/dom/frog/dom_frog.dart", |
| 131 "html": "../client/html/release/html.dart", | 135 "html": "../client/html/release/html.dart", |
| 132 "htmlimpl": "../client/html/release/htmlimpl.dart", | 136 "htmlimpl": "../client/html/release/htmlimpl.dart", |
| 137 "isolate": "../lib/isolate/isolate_frog.dart", |
| 133 "json": "../lib/json/json_frog.dart" | 138 "json": "../lib/json/json_frog.dart" |
| 134 } | 139 } |
| 135 | 140 |
| 136 | 141 |
| 137 class Pad(object): | 142 class Pad(object): |
| 138 """ | 143 """ |
| 139 Accumulates all source files that are needed to compile a dart program, | 144 Accumulates all source files that are needed to compile a dart program, |
| 140 and places them in <script> tags on an html page. | 145 and places them in <script> tags on an html page. |
| 141 """ | 146 """ |
| 142 | 147 |
| 143 def __init__(self, argv): | 148 def __init__(self, argv): |
| 144 parser = optparse.OptionParser(usage= | 149 parser = optparse.OptionParser(usage= |
| 145 "%prog [options] file_to_compile.dart" | 150 "%prog [options] file_to_compile.dart" |
| 146 ) | 151 ) |
| 147 parser.add_option("-r", "--rebuild", action="store_true", | 152 parser.add_option("-f", "--frogpad_js", |
| 148 help="forces rebuild of the frogpad javascript") | 153 help="location of frogpad.js file") |
| 149 parser.add_option("-o", "--out", | 154 parser.add_option("-o", "--out", |
| 150 help="name of javascript output file") | 155 help="name of javascript output file") |
| 151 parser.add_option("-v", "--verbose", action="store_true", | 156 parser.add_option("-v", "--verbose", action="store_true", |
| 152 help="more verbose logging") | 157 help="more verbose logging") |
| 153 (options, args) = parser.parse_args(argv) | 158 (options, args) = parser.parse_args(argv) |
| 154 | 159 |
| 155 log_level = logging.INFO | 160 log_level = logging.INFO |
| 156 if options.verbose: | 161 if options.verbose: |
| 157 log_level = logging.DEBUG | 162 log_level = logging.DEBUG |
| 158 logging.basicConfig(level=log_level) | 163 logging.basicConfig(level=log_level) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 170 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname( | 175 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname( |
| 171 self.frogpad_dir))) | 176 self.frogpad_dir))) |
| 172 | 177 |
| 173 # directory of frog compiler source code | 178 # directory of frog compiler source code |
| 174 self.frog_dir = os.path.join(self.dart_dir, "frog") | 179 self.frog_dir = os.path.join(self.dart_dir, "frog") |
| 175 | 180 |
| 176 logging.debug("dartdir_dir: '%s'" % self.dart_dir) | 181 logging.debug("dartdir_dir: '%s'" % self.dart_dir) |
| 177 logging.debug("frog_dir: '%s'" % self.frog_dir) | 182 logging.debug("frog_dir: '%s'" % self.frog_dir) |
| 178 logging.debug("frogpad_dir: '%s'" % self.frogpad_dir) | 183 logging.debug("frogpad_dir: '%s'" % self.frogpad_dir) |
| 179 | 184 |
| 180 # name of frogpad_js file | 185 # location frogpad.js file |
| 181 self.frogpad_js = os.path.join(self.frogpad_dir, FROGPAD_JS) | 186 if not options.frogpad_js: |
| 187 raise Exception("--frogpad_js is required") |
| 188 |
| 189 if not os.path.exists(options.frogpad_js): |
| 190 raise FileNotFoundException(options.frogpad_js) |
| 191 |
| 192 self.frogpad_js = options.frogpad_js |
| 182 | 193 |
| 183 if options.out: | 194 if options.out: |
| 184 # user has specified an output file | 195 # user has specified an output file |
| 185 self.js_file = os.path.abspath(options.out) | 196 self.js_file = os.path.abspath(options.out) |
| 186 else: | 197 else: |
| 187 # user didn't specify an output file, so base the name on the | 198 # user didn't specify an output file, so base the name on the |
| 188 # input file | 199 # input file |
| 189 self.js_file = self.main_file + ".frogpad.js" | 200 self.js_file = self.main_file + ".frogpad.js" |
| 190 | 201 |
| 191 logging.debug("js_file: '%s" % self.js_file) | 202 logging.debug("js_file: '%s" % self.js_file) |
| 192 | 203 |
| 193 # this is the html file that we pass to DumpRenderTree | 204 # this is the html file that we pass to DumpRenderTree |
| 194 self.html_file = self.js_file + ".frogpad.html" | 205 self.html_file = self.js_file + ".frogpad.html" |
| 195 logging.debug("html_file: '%s'" % self.html_file) | 206 logging.debug("html_file: '%s'" % self.html_file) |
| 196 | 207 |
| 197 # map from file name to File object (contains entries for all corelib | 208 # map from file name to File object (contains entries for all corelib |
| 198 # and all other dart files needed to compile main_file) | 209 # and all other dart files needed to compile main_file) |
| 199 self.name_to_file = {} | 210 self.name_to_file = {} |
| 200 | 211 |
| 201 # map from script tag id to File object | 212 # map from script tag id to File object |
| 202 self.id_to_file = {} | 213 self.id_to_file = {} |
| 203 | 214 |
| 204 if not os.path.exists(self.frogpad_js): | |
| 205 options.rebuild = True | |
| 206 | |
| 207 if options.rebuild: | |
| 208 self.build_frogpad_js() | |
| 209 | |
| 210 self.load_libraries() | 215 self.load_libraries() |
| 211 self.load_file(self.main_file) | 216 self.load_file(self.main_file) |
| 212 | 217 |
| 213 html = self.generate_html() | 218 html = self.generate_html() |
| 214 write_file(self.html_file, html) | 219 write_file(self.html_file, html) |
| 215 | 220 |
| 216 js = self.generate_js() | 221 js = self.generate_js() |
| 217 write_file(self.js_file, js) | 222 write_file(self.js_file, js) |
| 218 | 223 |
| 219 line_count = len(js.splitlines()) | 224 line_count = len(js.splitlines()) |
| 220 logging.info("generated '%s' (%d lines)", self.js_file, line_count) | 225 logging.debug("generated '%s' (%d lines)", self.js_file, line_count) |
| 221 | 226 |
| 222 def build_frogpad_js(self): | 227 match = COMPILATION_ERROR_REGEX.match(js) |
| 223 dart_vm = os.path.join(self.dart_dir, "out/Release_ia32/dart") | 228 if match: |
| 224 check_exists(dart_vm) | 229 sys.exit(1) |
| 225 | |
| 226 frogc_dart = os.path.join(self.frog_dir, "frogc.dart") | |
| 227 frogpad_dart = os.path.join(self.frogpad_dir, "frogpad.dart") | |
| 228 check_exists(frogc_dart) | |
| 229 check_exists(frogpad_dart) | |
| 230 | |
| 231 args = [] | |
| 232 args.append(dart_vm) | |
| 233 | |
| 234 # command line arguments for the dart vm | |
| 235 | |
| 236 # We leave out --enable_type_checks here for speed. | |
| 237 # args.append("--enable_type_checks") | |
| 238 | |
| 239 args.append("--enable_asserts") | |
| 240 | |
| 241 # The dart program we're going to run on the dart vm. | |
| 242 args.append(frogc_dart) | |
| 243 | |
| 244 # Command line arguments for frogc.dart | |
| 245 args.append("--libdir=%s/lib" % self.frog_dir) | |
| 246 args.append("--compile-only") | |
| 247 args.append("--enable_type_checks") | |
| 248 args.append("--enable_asserts") | |
| 249 args.append("--out=%s" % self.frogpad_js) | |
| 250 | |
| 251 # The dart program that we want frogc.dart to compile. | |
| 252 args.append(frogpad_dart) | |
| 253 logging.info("generating '%s'" % self.frogpad_js) | |
| 254 | |
| 255 run_command(args) | |
| 256 check_exists(self.frogpad_js) | |
| 257 | 230 |
| 258 def generate_html(self): | 231 def generate_html(self): |
| 259 tags = [] | 232 tags = [] |
| 260 for f in self.id_to_file.values(): | 233 for f in self.id_to_file.values(): |
| 261 tags.append(self._create_tag(f.id, f.contents)) | 234 tags.append(self._create_tag(f.id, f.contents)) |
| 262 tags.append(self._create_tag(MAIN_ID, self.main_file)) | 235 tags.append(self._create_tag(MAIN_ID, self.main_file)) |
| 263 html = HTML.replace("{{script_tags}}", "".join(tags)) | 236 html = HTML.replace("{{script_tags}}", "".join(tags)) |
| 264 html = html.replace("{{FROGPAD_JS}}", read_file(self.frogpad_js)) | 237 html = html.replace("{{FROGPAD_JS}}", read_file(self.frogpad_js)) |
| 265 return html | 238 return html |
| 266 | 239 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 raise CommandFailedException(msg) | 365 raise CommandFailedException(msg) |
| 393 logging.debug("SUCCEEDED (%d bytes)" % len(stdout)) | 366 logging.debug("SUCCEEDED (%d bytes)" % len(stdout)) |
| 394 return stdout | 367 return stdout |
| 395 | 368 |
| 396 | 369 |
| 397 def main(argv): | 370 def main(argv): |
| 398 Pad(argv) | 371 Pad(argv) |
| 399 | 372 |
| 400 if __name__ == "__main__": | 373 if __name__ == "__main__": |
| 401 sys.exit(main(sys.argv)) | 374 sys.exit(main(sys.argv)) |
| OLD | NEW |