Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: tools/testing/frogpad/frogpad.py

Issue 9422027: frogpad now uses vm to bootstrap instead of node (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: small fixes Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/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 Generates an html file (frogpad.html) that can be used to execute the frog 9 Generates an html file (frogpad.html) that can be used to execute the frog
10 compiler in a web browser or DumpRenderTree, 10 compiler in a web browser or DumpRenderTree,
11 11
12 The generated frogpad.html will contain: 12 The generated frogpad.html will contain:
13 13
14 1. all the dart files that compose a dart program 14 1. all the dart files that compose a dart program
15 2. all the dart files of dart:core and other standard dart libraries 15 2. all the dart files of dart:core and other standard dart libraries
16 3. frogpad.dart (compiled to javascript) 16 3. frogpad.dart (compiled to javascript)
17 17
18 The contents of each dart file is placed in a separate <script> tag. 18 The contents of each dart file is placed in a separate <script> tag.
19 19
20 When the html page is loaded by a browser, the frog compiler will be invoked 20 When the html page is loaded by a browser, the frog compiler will be invoked
21 and the user's dart program will be compiled to javascript. The generated 21 and the user's dart program will be compiled to javascript. The generated
22 javascript will be placed in the <pre> element with id "output". 22 javascript will be placed in the <pre> element with id "output".
23 23
24 If using DumpRenderTree, the output javascript can be obtained by dumping 24 If using DumpRenderTree, the output javascript can be obtained by dumping
25 the page as text and looking for the contents of the output textarea. 25 the page as text and looking for the contents of the output textarea.
26 """ 26 """
27 27
28 import logging
Jennifer Messerly 2012/02/21 21:02:22 nice use of logging :)
mattsh 2012/02/21 21:21:39 thanks
28 import optparse 29 import optparse
29 import os.path 30 import os.path
30 import re 31 import re
32 import subprocess
31 import sys 33 import sys
32 34
35 class Error(Exception):
Jennifer Messerly 2012/02/21 21:02:22 why not use StandardError? http://docs.python.org/
mattsh 2012/02/21 21:21:39 Done.
36 """Base class for exceptions in this module."""
37 pass
38
39 class FileNotFoundException(Error):
40 def __init__(self, file_name):
41 self._name = file_name
42
43 def __str__(self):
44 return self._name
45
46
47 class CommandFailedException(Error):
48 def __init__(self, message):
49 self._message = message
50
51 def GetMessage(self):
52 return self._message
53
54
55 # This file is produced by compiling frogpad.dart to javascript. To do this
56 # we run frogc.dart on the dart vm.
57 #
58 # Note, we use ".frogc.js" as the extension (instead of simply ".js"),
59 # because this file is generated by frogc and not by frogpad.
60 #
61 # (For testing, it's useful to be able to distinguish files that are generated
62 # by frogc from files that are generated by frogpad.)
63 #
64 FROGPAD_JS = "frogpad.dart.frogc.js"
65
33 # Template for the html page we're going to generate. 66 # Template for the html page we're going to generate.
34 HTML = """<html> 67 HTML = """<html>
35 <head> 68 <head>
36 <style type="text/css"> 69 <style type="text/css">
37 textarea { 70 textarea {
38 width: 100%; 71 width: 100%;
39 height: 200px; 72 height: 200px;
40 } 73 }
41 .label { 74 .label {
42 margin-top: 5px; 75 margin-top: 5px;
(...skipping 12 matching lines...) Expand all
55 <body> 88 <body>
56 <h1>Frogpad</h1> 89 <h1>Frogpad</h1>
57 <div class="label">Input:</div> 90 <div class="label">Input:</div>
58 <textarea id="input"></textarea> 91 <textarea id="input"></textarea>
59 <div class="label">Compiler Messages:</div> 92 <div class="label">Compiler Messages:</div>
60 <pre id="warnings"></pre> 93 <pre id="warnings"></pre>
61 <div class="label">Timing:</div> 94 <div class="label">Timing:</div>
62 <pre id="timing"></pre> 95 <pre id="timing"></pre>
63 <div class="label">Output:</div> 96 <div class="label">Output:</div>
64 <pre id="output"></pre> 97 <pre id="output"></pre>
65 <script type="text/javascript" src="frogpad.dart.js" ></script> 98 <script type="text/javascript" src={{FROGPAD_JS}} ></script>
66 </body> 99 </body>
67 </html> 100 </html>
68 """ 101 """
69 102
70 # We use "application/inert" here to make the browser ignore the 103 # We use "application/inert" here to make the browser ignore the
71 # these script tags. (frogpad.dart will fish out the contents as needed.) 104 # these script tags. (frogpad.dart will fish out the contents as needed.)
72 # 105 #
73 SCRIPT_TAG = """<script type="application/inert" id="{{id}}"> 106 SCRIPT_TAG = """<script type="application/inert" id="{{id}}">
74 {{contents}} 107 {{contents}}
75 </script> 108 </script>
(...skipping 17 matching lines...) Expand all
93 "json": "../lib/json/json_frog.dart" 126 "json": "../lib/json/json_frog.dart"
94 } 127 }
95 128
96 129
97 class Pad(object): 130 class Pad(object):
98 """ 131 """
99 Accumulates all source files that are needed to compile a dart program, 132 Accumulates all source files that are needed to compile a dart program,
100 and places them in <script> tags on an html page. 133 and places them in <script> tags on an html page.
101 """ 134 """
102 135
103 def __init__(self, frog_dir, main_file): 136 def __init__(self, argv):
137 parser = optparse.OptionParser()
138 parser.add_option("-m", "--main", help="which dart file to compile")
139 parser.add_option("-r", "--rebuild", action="store_true",
140 help="forces rebuild of frogpad_js")
141 (options, args) = parser.parse_args(argv)
142
143 if len(args) < 2:
144 usage()
Jennifer Messerly 2012/02/21 21:02:22 I'd pull all of the option parsing out of Pad.__in
mattsh 2012/02/21 21:21:39 Yes, but let's do in a later CL if needed. It's s
145
146 self.main_file = os.path.abspath(args[1])
147
148 # directory of this script
149 self.frogpad_dir = os.path.abspath(os.path.dirname(argv[0]))
150
151 # root of dart source repo
152 self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname(
153 self.frogpad_dir)))
154
104 # directory of frog compiler source code 155 # directory of frog compiler source code
105 self.frog_dir = frog_dir 156 self.frog_dir = os.path.join(self.dart_dir, "frog")
106 157
107 # which .dart file to compile 158 logging.debug("dartdir_dir: '%s'" % self.dart_dir)
108 self.main_file = main_file 159 logging.debug("frog_dir: '%s'" % self.frog_dir)
160 logging.debug("frogpad_dir: '%s'" % self.frogpad_dir)
161
162 # name of frogpad_js file
163 self.frogpad_js = os.path.join(self.frogpad_dir, FROGPAD_JS)
164
165 html_file = self.main_file + ".frogpad.html"
109 166
110 # map from file name to File object (contains entries for all corelib 167 # map from file name to File object (contains entries for all corelib
111 # and all other dart files needed to compile main_file) 168 # and all other dart files needed to compile main_file)
112 self.name_to_file = {} 169 self.name_to_file = {}
113 170
114 # map from script tag id to File object 171 # map from script tag id to File object
115 self.id_to_file = {} 172 self.id_to_file = {}
116 173
174 if not os.path.exists(self.frogpad_js):
175 options.rebuild = True
176
177 if options.rebuild:
178 self.build_frogpad_js()
179
117 self.load_libraries() 180 self.load_libraries()
118 self.load_file(self.main_file) 181 self.load_file(self.main_file)
119 182
183 html = self.generate_html()
184
185 with open(html_file, "w") as output:
186 output.write(html)
187 logging.info("generated '%s' (%d bytes)" % (html_file, len(html)))
188
189
190 def build_frogpad_js(self):
191 dart_vm = os.path.join(self.dart_dir, "out/Release_ia32/dart")
192 check_exists(dart_vm)
193
194 frogc_dart = os.path.join(self.frog_dir, "frogc.dart")
195 frogpad_dart = os.path.join(self.frogpad_dir, "frogpad.dart")
196 check_exists(frogc_dart)
197 check_exists(frogpad_dart)
198
199 args = []
200 args.append(dart_vm)
201
202 # command line arguments for the dart vm
203
204 # We leave out --enable_type_checks here for speed.
205 # args.append("--enable_type_checks")
206
207 args.append("--enable_asserts")
208
209 # The dart program we're going to run on the dart vm.
210 args.append(frogc_dart)
211
212 # Command line arguments for frogc.dart
213 args.append("--libdir=%s/lib" % self.frog_dir)
214 args.append("--compile-only")
215 args.append("--enable_type_checks")
216 args.append("--enable_asserts")
217 args.append("--out=%s" % self.frogpad_js)
218
219 # The dart program that we want frogc.dart to compile.
220 args.append(frogpad_dart)
221
222 run_command(args)
223 check_exists(self.frogpad_js)
224
120 def generate_html(self): 225 def generate_html(self):
121 tags = [] 226 tags = []
122 for f in self.id_to_file.values(): 227 for f in self.id_to_file.values():
123 tags.append(self._create_tag(f.id, f.contents)) 228 tags.append(self._create_tag(f.id, f.contents))
124 tags.append(self._create_tag(MAIN_ID, self.main_file)) 229 tags.append(self._create_tag(MAIN_ID, self.main_file))
125 html = HTML.replace("{{script_tags}}", "".join(tags)) 230 html = HTML.replace("{{script_tags}}", "".join(tags))
231 html = html.replace("{{FROGPAD_JS}}", FROGPAD_JS)
Jennifer Messerly 2012/02/21 21:02:22 Another way to do this would be to use "%(FROGPAD_
mattsh 2012/02/21 21:21:39 I think if the source template has any extra %s or
126 return html 232 return html
127 233
128 @staticmethod 234 @staticmethod
129 def _create_tag(id, contents): 235 def _create_tag(id, contents):
130 s = SCRIPT_TAG 236 s = SCRIPT_TAG
131 s = s.replace("{{id}}", id) 237 s = s.replace("{{id}}", id)
132 s = s.replace("{{contents}}", contents) 238 s = s.replace("{{contents}}", contents)
133 return s 239 return s
134 240
135 def dart_library(self, name): 241 def dart_library(self, name):
136 path = DART_LIBRARIES[name] 242 path = DART_LIBRARIES[name]
137 if not path: 243 if not path:
138 raise Exception("unrecognized 'dart:%s'", name) 244 raise Exception("unrecognized 'dart:%s'", name)
139 return os.path.join(self.frog_dir, path) 245 return os.path.join(self.frog_dir, path)
140 246
141 def load_libraries(self): 247 def load_libraries(self):
142 for name in DART_LIBRARIES: 248 for name in DART_LIBRARIES:
143 self.load_file(self.dart_library(name)) 249 self.load_file(self.dart_library(name))
144 250
145 def load_file(self, name): 251 def load_file(self, name):
252 logging.debug("load_file " + name)
146 name = os.path.abspath(name) 253 name = os.path.abspath(name)
147 if name in self.name_to_file: 254 if name in self.name_to_file:
148 print "already loaded %s, skipping" % name 255 logging.debug("already loaded %s, skipping" % name)
149 return 256 return
150 f = File(self, name) 257 f = File(self, name)
151 self.name_to_file[f.name] = f 258 self.name_to_file[f.name] = f
152 if f.id in self.id_to_file: 259 if f.id in self.id_to_file:
153 raise Exception("ambiguous id '%s'" % f.id) 260 raise Exception("ambiguous id '%s'" % f.id)
154 self.id_to_file[f.id] = f 261 self.id_to_file[f.id] = f
155 f.directives() 262 f.directives()
156 263
157 class File(object): 264 class File(object):
158 def __init__(self, pad, name): 265 def __init__(self, pad, name):
159 self.pad = pad 266 self.pad = pad
160 self.name = name 267 self.name = name
161 self.id = self._make_id() 268 self.id = self._make_id()
162 if not os.path.exists(name): 269 check_exists(name)
163 raise Exception("cannot find file '%s'" % name)
164 with open(self.name, "r") as f: 270 with open(self.name, "r") as f:
165 self.contents = f.read() 271 self.contents = f.read()
166 print "creating File '%s' (%d lines)" % (self.name, len(self.contents)) 272 logging.debug("creating File '%s' (%d lines)" %
273 (self.name, len(self.contents)))
167 274
168 def _make_id(self): 275 def _make_id(self):
169 """ 276 """
170 Generates an id (based on the file name) for the <script> tag that will 277 Generates an id (based on the file name) for the <script> tag that will
171 hold the contents of this file. 278 hold the contents of this file.
172 """ 279 """
173 (dirname, name) = os.path.split(self.name) 280 (dirname, name) = os.path.split(self.name)
174 dirname = os.path.basename(dirname) 281 dirname = os.path.basename(dirname)
175 name = name.replace(".", "_") 282 name = name.replace(".", "_")
176 return dirname + "_" + name 283 return dirname + "_" + name
(...skipping 11 matching lines...) Expand all
188 if not match: 295 if not match:
189 return 296 return
190 url = match.group(2) 297 url = match.group(2)
191 if url.startswith("dart:"): 298 if url.startswith("dart:"):
192 path = self.pad.dart_library(url[len("dart:"):]) 299 path = self.pad.dart_library(url[len("dart:"):])
193 else: 300 else:
194 path = os.path.join(os.path.dirname(self.name), url) 301 path = os.path.join(os.path.dirname(self.name), url)
195 self.pad.load_file(path) 302 self.pad.load_file(path)
196 303
197 304
305 def check_exists(file_name):
306 if not os.path.exists(file_name):
307 raise FileNotFoundException(file_name)
308
309
310 def format_command(args):
311 return ' '.join(args)
312
313
314 def run_command(args):
315 """
316 Args:
317 command: comamnd with arguments to exec
318 """
319
320 command = format_command(args)
321 logging.info("RUNNING " + command)
322 proc = subprocess.Popen(args)
323 exit_code = proc.wait()
324
325 if exit_code:
326 msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command)
327 logging.error(msg)
328 raise CommandFailedException(msg)
329
330 logging.debug("SUCCEEDED " + command)
331
332
333 def usage():
334 print("""
335 Usage:
336 frogpad.py hello.dart
337 """)
Jennifer Messerly 2012/02/21 21:02:22 Perhaps use http://docs.python.org/library/optpars
mattsh 2012/02/21 21:21:39 Yes, reasonable for a later CL.
Jennifer Messerly 2012/02/21 21:40:50 sgtm. It just occurred to me that I don't think a
338 sys.exit(1)
339
340
198 def main(argv): 341 def main(argv):
199 parser = optparse.OptionParser() 342 logging.basicConfig(level=logging.INFO)
200 parser.add_option("-o", "--out", dest="out_file") 343 Pad(argv)
201
202 (options, args) = parser.parse_args(argv)
203 main_file = os.path.abspath(args[1])
204
205 script_dir = os.path.abspath(os.path.dirname(argv[0]))
206 frog_dir = os.path.abspath(os.path.join(script_dir, "../../../frog"))
207
208 pad = Pad(frog_dir, main_file)
209 html = pad.generate_html()
210
211 filename = "frogpad.html"
212 with open(filename, "w") as output:
213 output.write(html)
214 print "generated '%s' (%d bytes)" % (filename, len(html))
215 344
216 if __name__ == "__main__": 345 if __name__ == "__main__":
217 sys.exit(main(sys.argv)) 346 sys.exit(main(sys.argv))
218
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698