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

Side by Side Diff: lib/src/codegen/dart_codegen.dart

Issue 1148283010: Remove dart backend (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « lib/runtime/dart_runtime.dart ('k') | lib/src/codegen/html_codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dev_compiler.src.codegen.dart_codegen;
6
7 import 'dart:io' show File;
8
9 import 'package:analyzer/analyzer.dart' as analyzer;
10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/element.dart';
12 import 'package:analyzer/src/generated/java_core.dart' as java_core;
13 import 'package:analyzer/src/generated/scanner.dart' show Token;
14 import 'package:logging/logging.dart' as logger;
15 import 'package:path/path.dart' as path;
16
17 import 'package:dev_compiler/devc.dart' show AbstractCompiler;
18 import 'package:dev_compiler/src/info.dart';
19 import 'package:dev_compiler/src/options.dart';
20 import 'package:dev_compiler/src/utils.dart' as utils;
21 import 'ast_builder.dart';
22 import 'code_generator.dart' as codegenerator;
23 import 'reify_coercions.dart'
24 show CoercionReifier, NewTypeIdDesc, InstrumentedRuntime;
25
26 final _log = new logger.Logger('dev_compiler.dart_codegen');
27
28 class DevCompilerRuntime extends InstrumentedRuntime {
29 Identifier _runtimeId = AstBuilder.identifierFromString("DEVC\$RT");
30
31 Identifier _castId;
32 Identifier _typeToTypeId;
33 Identifier _wrapId;
34
35 DevCompilerRuntime() {
36 _castId = _prefixId(AstBuilder.identifierFromString("cast"));
37 _typeToTypeId = _prefixId(AstBuilder.identifierFromString("type"));
38 _wrapId = _prefixId(AstBuilder.identifierFromString("wrap"));
39 }
40
41 String get importString {
42 var name = _runtimeId;
43 var uri = "package:dev_compiler/runtime/dart_logging_runtime.dart";
44 return "import '$uri' as $name;";
45 }
46
47 Identifier _prefixId(Identifier id) =>
48 AstBuilder.prefixedIdentifier(_runtimeId, id);
49
50 Identifier runtimeId(RuntimeOperation oper) {
51 if (oper.operation == "cast") return _castId;
52 if (oper.operation == "wrap") return _wrapId;
53 if (oper.operation == "type") return _typeToTypeId;
54 assert(false);
55 return null;
56 }
57
58 Expression runtimeOperation(RuntimeOperation oper) {
59 var id = runtimeId(oper);
60 var args = oper.arguments;
61 return AstBuilder.application(id, args);
62 }
63
64 @override
65 Expression wrap(Expression coercion, Expression e, Expression fromType,
66 Expression toType, Expression dartIs, String kind, String location) {
67 var k = AstBuilder.stringLiteral(kind);
68 var key = AstBuilder.multiLineStringLiteral(location);
69 var arguments = <Expression>[coercion, e, fromType, toType, k, key, dartIs];
70 return new RuntimeOperation("wrap", arguments);
71 }
72
73 Expression cast(Expression e, Expression fromType, Expression toType,
74 Expression dartIs, String kind, String location, bool ground) {
75 var k = AstBuilder.stringLiteral(kind);
76 var key = AstBuilder.multiLineStringLiteral(location);
77 var g = AstBuilder.booleanLiteral(ground);
78 var arguments = <Expression>[e, fromType, toType, k, key, dartIs, g];
79 return new RuntimeOperation("cast", arguments);
80 }
81
82 Expression type(Expression witnessFunction) {
83 return new RuntimeOperation("type", <Expression>[witnessFunction]);
84 }
85 }
86
87 // TODO(leafp) This is kind of a hack, but it works for now.
88 class FileWriter extends java_core.PrintStringWriter {
89 final CompilerOptions options;
90 String _path;
91 FileWriter(this.options, this._path);
92 int indent = 0;
93 int withinInterpolationExpression = 0;
94 bool insideForLoop = false;
95
96 void print(x) {
97 if (!options.formatOutput) {
98 super.print(x);
99 return;
100 }
101
102 switch (x) {
103 case '{':
104 indent++;
105 x = '{\n${" " * indent}';
106 break;
107 case ';':
108 if (!insideForLoop) {
109 x = ';\n${" " * indent}';
110 }
111 break;
112 case 'for (':
113 insideForLoop = true;
114 break;
115 case ') ':
116 insideForLoop = false;
117 break;
118 case r'${':
119 withinInterpolationExpression++;
120 break;
121 case '}':
122 if (withinInterpolationExpression > 0) {
123 withinInterpolationExpression--;
124 } else {
125 indent--;
126 x = '}\n${" " * indent}';
127 }
128 break;
129 }
130 super.print(x);
131 }
132
133 void finalize() {
134 String s = toString();
135 _log.fine("Writing file $_path");
136 new File(_path).writeAsStringSync(s);
137 }
138 }
139
140 bool _identifierNeedsQualification(Identifier id, NewTypeIdDesc desc) {
141 var library = desc.importedFrom;
142 if (library == null) return false;
143 if (library.isDartCore) return false;
144 if (desc.fromCurrent) return false;
145 return true;
146 }
147
148 // This class just holds some additional syntactic helpers and
149 // fixes to the general ToSourceVisitor for use by subclasses.
150 abstract class UnitGeneratorCommon extends analyzer.ToSourceVisitor {
151 UnitGeneratorCommon(java_core.PrintWriter out) : super(out);
152
153 void output(String s);
154 void outputln(String s);
155
156 // Copied from ast.dart
157 void visitNodeListWithSeparatorAndSuffix(
158 NodeList<AstNode> nodes, String separator, String suffix) {
159 if (nodes != null) {
160 int size = nodes.length;
161 if (size > 0) {
162 for (int i = 0; i < size; i++) {
163 if (i > 0) {
164 output(separator);
165 }
166 nodes[i].accept(this);
167 }
168 output(suffix);
169 }
170 }
171 }
172
173 // Copied from ast.dart
174 void visitListWithSeparatorAndPrefix(
175 String prefix, List<AstNode> nodes, String separator) {
176 if (nodes != null) {
177 int size = nodes.length;
178 if (size > 0) {
179 output(prefix);
180 for (int i = 0; i < size; i++) {
181 if (i > 0) {
182 output(separator);
183 }
184 nodes[i].accept(this);
185 }
186 }
187 }
188 }
189
190 // Copied from ast.dart
191 void visitNodeListWithSeparatorAndPrefix(
192 String prefix, NodeList<AstNode> nodes, String separator) {
193 visitListWithSeparatorAndPrefix(prefix, nodes, separator);
194 }
195
196 // Copied from ast.dart
197 void visitTokenWithSuffix(Token token, String suffix) {
198 if (token != null) {
199 output(token.lexeme);
200 output(suffix);
201 }
202 }
203
204 // Copied from ast.dart
205 void safelyVisitNode(AstNode node) {
206 if (node != null) {
207 node.accept(this);
208 }
209 }
210
211 // Copied from ast.dart
212 void visitNodeWithPrefix(String prefix, AstNode node) {
213 if (node != null) {
214 output(prefix);
215 node.accept(this);
216 }
217 }
218
219 // Copied from ast.dart
220 void visitNodeWithSuffix(AstNode node, String suffix) {
221 if (node != null) {
222 node.accept(this);
223 output(suffix);
224 }
225 }
226
227 // Overridden to add external keyword if present
228 @override
229 Object visitFunctionDeclaration(FunctionDeclaration node) {
230 visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
231 visitTokenWithSuffix(node.externalKeyword, " ");
232 visitNodeWithSuffix(node.returnType, " ");
233 visitTokenWithSuffix(node.propertyKeyword, " ");
234 safelyVisitNode(node.name);
235 safelyVisitNode(node.functionExpression);
236 return null;
237 }
238 }
239
240 // TODO(leafp) Not sure if this is the right way to generate
241 // Dart source going forward, but it's a quick way to get started.
242 class UnitGenerator extends UnitGeneratorCommon with ConversionVisitor<Object> {
243 CompilationUnit unit;
244 final java_core.PrintWriter _out;
245 final String outDir;
246 Set<LibraryElement> _extraImports;
247 final _runtime;
248 bool _qualifyNames = true;
249 Map<Identifier, NewTypeIdDesc> _newIdentifiers;
250
251 UnitGenerator(this.unit, java_core.PrintWriter out, String this.outDir,
252 this._extraImports, this._newIdentifiers, this._runtime)
253 : _out = out,
254 super(out);
255
256 void output(String s) => _out.print(s);
257 void outputln(String s) => _out.println(s);
258
259 // Choose a canonical prefix for a library that we are adding.
260 // Currently just chooses something unlikely to conflict with a user
261 // prefix.
262 // TODO(leafp): Make this robust.
263 String canonizeLibraryName(String name) {
264 name = name.replaceAll(".", "DOT");
265 name = "DDC\$$name\$";
266 return name;
267 }
268
269 // Split the directives into the various kinds (since there are restrictions
270 // in the syntax as to order of directives).
271 Map<String, List<Directive>> splitDirectives(NodeList<Directive> directives) {
272 return {
273 'export': directives.where((d) => d is ExportDirective).toList(),
274 'import': directives.where((d) => d is ImportDirective).toList(),
275 'library': directives.where((d) => d is LibraryDirective).toList(),
276 'part': directives.where((d) => d is PartDirective).toList(),
277 'partof': directives.where((d) => d is PartOfDirective).toList(),
278 };
279 }
280
281 // Build the set of import directives corresponding to the
282 // extra imports required by the types that we add in via
283 // inference
284 List<String> buildExtraImportDirectives() {
285 return _extraImports.map((lib) {
286 var name = utils.canonicalLibraryName(lib);
287 name = canonizeLibraryName(name);
288 var uri = codegenerator.CodeGenerator.uriFor(lib);
289 return "import '$uri' as $name;";
290 }).toList();
291 }
292
293 // Rewrite the import directives with additional library imports
294 // covering the inferred types added in as part of this pass.
295 void _visitDirectives(String prefix, List<Directive> directives) {
296 _qualifyNames = false;
297 var ds = splitDirectives(directives);
298 visitListWithSeparatorAndPrefix(prefix, ds['library'], " ");
299 if (ds['library'].length != 0) {
300 assert(ds['partof'].length == 0);
301 var es = buildExtraImportDirectives();
302 es.add(_runtime.importString);
303 es.forEach(outputln);
304 }
305 visitListWithSeparatorAndPrefix(prefix, ds['partof'], " ");
306 visitListWithSeparatorAndPrefix(prefix, ds['import'], " ");
307 visitListWithSeparatorAndPrefix(prefix, ds['export'], " ");
308 visitListWithSeparatorAndPrefix(prefix, ds['part'], " ");
309 _qualifyNames = true;
310 }
311
312 @override
313 Object visitNode(AstNode node) {
314 if (node != null) {
315 node.visitChildren(this);
316 }
317 return null;
318 }
319
320 @override
321 Object visitRuntimeOperation(RuntimeOperation oper) {
322 var e = _runtime.runtimeOperation(oper);
323 e.accept(this);
324 return null;
325 }
326
327 @override
328 Object visitAsExpression(AsExpression node) {
329 _log.severe("Unlowered as expression");
330 assert(false);
331 return null;
332 }
333
334 @override
335 Object visitCompilationUnit(CompilationUnit node) {
336 ScriptTag scriptTag = node.scriptTag;
337 NodeList<Directive> directives = node.directives;
338 safelyVisitNode(scriptTag);
339 String prefix = scriptTag == null ? "" : " ";
340 _visitDirectives(prefix, directives);
341 prefix = scriptTag == null && directives.isEmpty ? "" : " ";
342 visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
343 return null;
344 }
345
346 @override
347 Object visitPrefixedIdentifier(PrefixedIdentifier id) {
348 safelyVisitNode(id.prefix);
349 output('.');
350 output(id.identifier.token.lexeme);
351 return null;
352 }
353
354 @override
355 Object visitSimpleIdentifier(SimpleIdentifier id) {
356 if (!(_qualifyNames &&
357 _newIdentifiers.containsKey(id) &&
358 _identifierNeedsQualification(id, _newIdentifiers[id]))) {
359 return super.visitSimpleIdentifier(id);
360 }
361 var library = _newIdentifiers[id].importedFrom;
362 if (!utils.isDartPrivateLibrary(library)) {
363 var lib = utils.canonicalLibraryName(library);
364 var libname = canonizeLibraryName(lib);
365 output(libname);
366 output('.');
367 }
368 output(id.name);
369 return null;
370 }
371
372 void generate() {
373 visitCompilationUnit(unit);
374 }
375 }
376
377 class DartGenerator extends codegenerator.CodeGenerator {
378 final DevCompilerRuntime _runtime = new DevCompilerRuntime();
379
380 DartGenerator(AbstractCompiler compiler) : super(compiler);
381
382 Set<LibraryElement> computeExtraImports(Map<Identifier, NewTypeIdDesc> ids) {
383 var imports = new Set<LibraryElement>();
384 void process(Identifier id, NewTypeIdDesc desc) {
385 if (_identifierNeedsQualification(id, desc)) {
386 var library = desc.importedFrom;
387 if (utils.isDartPrivateLibrary(library)) {
388 _log.severe("Dropping import of private library ${library}\n");
389 return;
390 }
391 imports.add(library);
392 }
393 }
394 ids.forEach(process);
395 return imports;
396 }
397
398 String generateLibrary(LibraryUnit library, LibraryInfo info) {
399 var r = new CoercionReifier(library, compiler, _runtime);
400 var ids = r.reify();
401 var extraImports = computeExtraImports(ids);
402
403 for (var unit in library.partsThenLibrary) {
404 var libraryDir = makeOutputDirectory(info, unit);
405 var uri = unit.element.source.uri;
406 _log.fine("Generating unit $uri");
407 FileWriter out = new FileWriter(
408 options, path.join(libraryDir, '${uri.pathSegments.last}'));
409 var unitGen =
410 new UnitGenerator(unit, out, outDir, extraImports, ids, _runtime);
411 unitGen.generate();
412 out.finalize();
413 }
414
415 return null;
416 }
417 }
418
419 class EmptyUnitGenerator extends UnitGeneratorCommon {
420 final java_core.PrintWriter _out;
421 CompilationUnit unit;
422
423 EmptyUnitGenerator(this.unit, java_core.PrintWriter out)
424 : _out = out,
425 super(out);
426
427 void output(String s) => _out.print(s);
428 void outputln(String s) => _out.println(s);
429
430 void generate() {
431 unit.visitChildren(this);
432 }
433 }
434
435 // This class emits the code unchanged, for comparison purposes.
436 class EmptyDartGenerator extends codegenerator.CodeGenerator {
437 EmptyDartGenerator(AbstractCompiler compiler) : super(compiler);
438
439 String generateLibrary(LibraryUnit library, LibraryInfo info) {
440 for (var unit in library.partsThenLibrary) {
441 var outputDir = makeOutputDirectory(info, unit);
442 generateUnit(unit, info, outputDir);
443 }
444 return null;
445 }
446
447 void generateUnit(CompilationUnit unit, LibraryInfo info, String libraryDir) {
448 var uri = unit.element.source.uri;
449 _log.fine("Emitting original unit " + uri.toString());
450 FileWriter out = new FileWriter(
451 options, path.join(libraryDir, '${uri.pathSegments.last}'));
452 var unitGen = new EmptyUnitGenerator(unit, out);
453 unitGen.generate();
454 out.finalize();
455 }
456 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.dart ('k') | lib/src/codegen/html_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698