| Index: lib/src/codegen/dart_codegen.dart
|
| diff --git a/lib/src/codegen/dart_codegen.dart b/lib/src/codegen/dart_codegen.dart
|
| deleted file mode 100644
|
| index 679831bf059002584550b8ce900f05d52b4cbf89..0000000000000000000000000000000000000000
|
| --- a/lib/src/codegen/dart_codegen.dart
|
| +++ /dev/null
|
| @@ -1,456 +0,0 @@
|
| -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library dev_compiler.src.codegen.dart_codegen;
|
| -
|
| -import 'dart:io' show File;
|
| -
|
| -import 'package:analyzer/analyzer.dart' as analyzer;
|
| -import 'package:analyzer/src/generated/ast.dart';
|
| -import 'package:analyzer/src/generated/element.dart';
|
| -import 'package:analyzer/src/generated/java_core.dart' as java_core;
|
| -import 'package:analyzer/src/generated/scanner.dart' show Token;
|
| -import 'package:logging/logging.dart' as logger;
|
| -import 'package:path/path.dart' as path;
|
| -
|
| -import 'package:dev_compiler/devc.dart' show AbstractCompiler;
|
| -import 'package:dev_compiler/src/info.dart';
|
| -import 'package:dev_compiler/src/options.dart';
|
| -import 'package:dev_compiler/src/utils.dart' as utils;
|
| -import 'ast_builder.dart';
|
| -import 'code_generator.dart' as codegenerator;
|
| -import 'reify_coercions.dart'
|
| - show CoercionReifier, NewTypeIdDesc, InstrumentedRuntime;
|
| -
|
| -final _log = new logger.Logger('dev_compiler.dart_codegen');
|
| -
|
| -class DevCompilerRuntime extends InstrumentedRuntime {
|
| - Identifier _runtimeId = AstBuilder.identifierFromString("DEVC\$RT");
|
| -
|
| - Identifier _castId;
|
| - Identifier _typeToTypeId;
|
| - Identifier _wrapId;
|
| -
|
| - DevCompilerRuntime() {
|
| - _castId = _prefixId(AstBuilder.identifierFromString("cast"));
|
| - _typeToTypeId = _prefixId(AstBuilder.identifierFromString("type"));
|
| - _wrapId = _prefixId(AstBuilder.identifierFromString("wrap"));
|
| - }
|
| -
|
| - String get importString {
|
| - var name = _runtimeId;
|
| - var uri = "package:dev_compiler/runtime/dart_logging_runtime.dart";
|
| - return "import '$uri' as $name;";
|
| - }
|
| -
|
| - Identifier _prefixId(Identifier id) =>
|
| - AstBuilder.prefixedIdentifier(_runtimeId, id);
|
| -
|
| - Identifier runtimeId(RuntimeOperation oper) {
|
| - if (oper.operation == "cast") return _castId;
|
| - if (oper.operation == "wrap") return _wrapId;
|
| - if (oper.operation == "type") return _typeToTypeId;
|
| - assert(false);
|
| - return null;
|
| - }
|
| -
|
| - Expression runtimeOperation(RuntimeOperation oper) {
|
| - var id = runtimeId(oper);
|
| - var args = oper.arguments;
|
| - return AstBuilder.application(id, args);
|
| - }
|
| -
|
| - @override
|
| - Expression wrap(Expression coercion, Expression e, Expression fromType,
|
| - Expression toType, Expression dartIs, String kind, String location) {
|
| - var k = AstBuilder.stringLiteral(kind);
|
| - var key = AstBuilder.multiLineStringLiteral(location);
|
| - var arguments = <Expression>[coercion, e, fromType, toType, k, key, dartIs];
|
| - return new RuntimeOperation("wrap", arguments);
|
| - }
|
| -
|
| - Expression cast(Expression e, Expression fromType, Expression toType,
|
| - Expression dartIs, String kind, String location, bool ground) {
|
| - var k = AstBuilder.stringLiteral(kind);
|
| - var key = AstBuilder.multiLineStringLiteral(location);
|
| - var g = AstBuilder.booleanLiteral(ground);
|
| - var arguments = <Expression>[e, fromType, toType, k, key, dartIs, g];
|
| - return new RuntimeOperation("cast", arguments);
|
| - }
|
| -
|
| - Expression type(Expression witnessFunction) {
|
| - return new RuntimeOperation("type", <Expression>[witnessFunction]);
|
| - }
|
| -}
|
| -
|
| -// TODO(leafp) This is kind of a hack, but it works for now.
|
| -class FileWriter extends java_core.PrintStringWriter {
|
| - final CompilerOptions options;
|
| - String _path;
|
| - FileWriter(this.options, this._path);
|
| - int indent = 0;
|
| - int withinInterpolationExpression = 0;
|
| - bool insideForLoop = false;
|
| -
|
| - void print(x) {
|
| - if (!options.formatOutput) {
|
| - super.print(x);
|
| - return;
|
| - }
|
| -
|
| - switch (x) {
|
| - case '{':
|
| - indent++;
|
| - x = '{\n${" " * indent}';
|
| - break;
|
| - case ';':
|
| - if (!insideForLoop) {
|
| - x = ';\n${" " * indent}';
|
| - }
|
| - break;
|
| - case 'for (':
|
| - insideForLoop = true;
|
| - break;
|
| - case ') ':
|
| - insideForLoop = false;
|
| - break;
|
| - case r'${':
|
| - withinInterpolationExpression++;
|
| - break;
|
| - case '}':
|
| - if (withinInterpolationExpression > 0) {
|
| - withinInterpolationExpression--;
|
| - } else {
|
| - indent--;
|
| - x = '}\n${" " * indent}';
|
| - }
|
| - break;
|
| - }
|
| - super.print(x);
|
| - }
|
| -
|
| - void finalize() {
|
| - String s = toString();
|
| - _log.fine("Writing file $_path");
|
| - new File(_path).writeAsStringSync(s);
|
| - }
|
| -}
|
| -
|
| -bool _identifierNeedsQualification(Identifier id, NewTypeIdDesc desc) {
|
| - var library = desc.importedFrom;
|
| - if (library == null) return false;
|
| - if (library.isDartCore) return false;
|
| - if (desc.fromCurrent) return false;
|
| - return true;
|
| -}
|
| -
|
| -// This class just holds some additional syntactic helpers and
|
| -// fixes to the general ToSourceVisitor for use by subclasses.
|
| -abstract class UnitGeneratorCommon extends analyzer.ToSourceVisitor {
|
| - UnitGeneratorCommon(java_core.PrintWriter out) : super(out);
|
| -
|
| - void output(String s);
|
| - void outputln(String s);
|
| -
|
| - // Copied from ast.dart
|
| - void visitNodeListWithSeparatorAndSuffix(
|
| - NodeList<AstNode> nodes, String separator, String suffix) {
|
| - if (nodes != null) {
|
| - int size = nodes.length;
|
| - if (size > 0) {
|
| - for (int i = 0; i < size; i++) {
|
| - if (i > 0) {
|
| - output(separator);
|
| - }
|
| - nodes[i].accept(this);
|
| - }
|
| - output(suffix);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Copied from ast.dart
|
| - void visitListWithSeparatorAndPrefix(
|
| - String prefix, List<AstNode> nodes, String separator) {
|
| - if (nodes != null) {
|
| - int size = nodes.length;
|
| - if (size > 0) {
|
| - output(prefix);
|
| - for (int i = 0; i < size; i++) {
|
| - if (i > 0) {
|
| - output(separator);
|
| - }
|
| - nodes[i].accept(this);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Copied from ast.dart
|
| - void visitNodeListWithSeparatorAndPrefix(
|
| - String prefix, NodeList<AstNode> nodes, String separator) {
|
| - visitListWithSeparatorAndPrefix(prefix, nodes, separator);
|
| - }
|
| -
|
| - // Copied from ast.dart
|
| - void visitTokenWithSuffix(Token token, String suffix) {
|
| - if (token != null) {
|
| - output(token.lexeme);
|
| - output(suffix);
|
| - }
|
| - }
|
| -
|
| - // Copied from ast.dart
|
| - void safelyVisitNode(AstNode node) {
|
| - if (node != null) {
|
| - node.accept(this);
|
| - }
|
| - }
|
| -
|
| - // Copied from ast.dart
|
| - void visitNodeWithPrefix(String prefix, AstNode node) {
|
| - if (node != null) {
|
| - output(prefix);
|
| - node.accept(this);
|
| - }
|
| - }
|
| -
|
| - // Copied from ast.dart
|
| - void visitNodeWithSuffix(AstNode node, String suffix) {
|
| - if (node != null) {
|
| - node.accept(this);
|
| - output(suffix);
|
| - }
|
| - }
|
| -
|
| - // Overridden to add external keyword if present
|
| - @override
|
| - Object visitFunctionDeclaration(FunctionDeclaration node) {
|
| - visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
|
| - visitTokenWithSuffix(node.externalKeyword, " ");
|
| - visitNodeWithSuffix(node.returnType, " ");
|
| - visitTokenWithSuffix(node.propertyKeyword, " ");
|
| - safelyVisitNode(node.name);
|
| - safelyVisitNode(node.functionExpression);
|
| - return null;
|
| - }
|
| -}
|
| -
|
| -// TODO(leafp) Not sure if this is the right way to generate
|
| -// Dart source going forward, but it's a quick way to get started.
|
| -class UnitGenerator extends UnitGeneratorCommon with ConversionVisitor<Object> {
|
| - CompilationUnit unit;
|
| - final java_core.PrintWriter _out;
|
| - final String outDir;
|
| - Set<LibraryElement> _extraImports;
|
| - final _runtime;
|
| - bool _qualifyNames = true;
|
| - Map<Identifier, NewTypeIdDesc> _newIdentifiers;
|
| -
|
| - UnitGenerator(this.unit, java_core.PrintWriter out, String this.outDir,
|
| - this._extraImports, this._newIdentifiers, this._runtime)
|
| - : _out = out,
|
| - super(out);
|
| -
|
| - void output(String s) => _out.print(s);
|
| - void outputln(String s) => _out.println(s);
|
| -
|
| - // Choose a canonical prefix for a library that we are adding.
|
| - // Currently just chooses something unlikely to conflict with a user
|
| - // prefix.
|
| - // TODO(leafp): Make this robust.
|
| - String canonizeLibraryName(String name) {
|
| - name = name.replaceAll(".", "DOT");
|
| - name = "DDC\$$name\$";
|
| - return name;
|
| - }
|
| -
|
| - // Split the directives into the various kinds (since there are restrictions
|
| - // in the syntax as to order of directives).
|
| - Map<String, List<Directive>> splitDirectives(NodeList<Directive> directives) {
|
| - return {
|
| - 'export': directives.where((d) => d is ExportDirective).toList(),
|
| - 'import': directives.where((d) => d is ImportDirective).toList(),
|
| - 'library': directives.where((d) => d is LibraryDirective).toList(),
|
| - 'part': directives.where((d) => d is PartDirective).toList(),
|
| - 'partof': directives.where((d) => d is PartOfDirective).toList(),
|
| - };
|
| - }
|
| -
|
| - // Build the set of import directives corresponding to the
|
| - // extra imports required by the types that we add in via
|
| - // inference
|
| - List<String> buildExtraImportDirectives() {
|
| - return _extraImports.map((lib) {
|
| - var name = utils.canonicalLibraryName(lib);
|
| - name = canonizeLibraryName(name);
|
| - var uri = codegenerator.CodeGenerator.uriFor(lib);
|
| - return "import '$uri' as $name;";
|
| - }).toList();
|
| - }
|
| -
|
| - // Rewrite the import directives with additional library imports
|
| - // covering the inferred types added in as part of this pass.
|
| - void _visitDirectives(String prefix, List<Directive> directives) {
|
| - _qualifyNames = false;
|
| - var ds = splitDirectives(directives);
|
| - visitListWithSeparatorAndPrefix(prefix, ds['library'], " ");
|
| - if (ds['library'].length != 0) {
|
| - assert(ds['partof'].length == 0);
|
| - var es = buildExtraImportDirectives();
|
| - es.add(_runtime.importString);
|
| - es.forEach(outputln);
|
| - }
|
| - visitListWithSeparatorAndPrefix(prefix, ds['partof'], " ");
|
| - visitListWithSeparatorAndPrefix(prefix, ds['import'], " ");
|
| - visitListWithSeparatorAndPrefix(prefix, ds['export'], " ");
|
| - visitListWithSeparatorAndPrefix(prefix, ds['part'], " ");
|
| - _qualifyNames = true;
|
| - }
|
| -
|
| - @override
|
| - Object visitNode(AstNode node) {
|
| - if (node != null) {
|
| - node.visitChildren(this);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @override
|
| - Object visitRuntimeOperation(RuntimeOperation oper) {
|
| - var e = _runtime.runtimeOperation(oper);
|
| - e.accept(this);
|
| - return null;
|
| - }
|
| -
|
| - @override
|
| - Object visitAsExpression(AsExpression node) {
|
| - _log.severe("Unlowered as expression");
|
| - assert(false);
|
| - return null;
|
| - }
|
| -
|
| - @override
|
| - Object visitCompilationUnit(CompilationUnit node) {
|
| - ScriptTag scriptTag = node.scriptTag;
|
| - NodeList<Directive> directives = node.directives;
|
| - safelyVisitNode(scriptTag);
|
| - String prefix = scriptTag == null ? "" : " ";
|
| - _visitDirectives(prefix, directives);
|
| - prefix = scriptTag == null && directives.isEmpty ? "" : " ";
|
| - visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
|
| - return null;
|
| - }
|
| -
|
| - @override
|
| - Object visitPrefixedIdentifier(PrefixedIdentifier id) {
|
| - safelyVisitNode(id.prefix);
|
| - output('.');
|
| - output(id.identifier.token.lexeme);
|
| - return null;
|
| - }
|
| -
|
| - @override
|
| - Object visitSimpleIdentifier(SimpleIdentifier id) {
|
| - if (!(_qualifyNames &&
|
| - _newIdentifiers.containsKey(id) &&
|
| - _identifierNeedsQualification(id, _newIdentifiers[id]))) {
|
| - return super.visitSimpleIdentifier(id);
|
| - }
|
| - var library = _newIdentifiers[id].importedFrom;
|
| - if (!utils.isDartPrivateLibrary(library)) {
|
| - var lib = utils.canonicalLibraryName(library);
|
| - var libname = canonizeLibraryName(lib);
|
| - output(libname);
|
| - output('.');
|
| - }
|
| - output(id.name);
|
| - return null;
|
| - }
|
| -
|
| - void generate() {
|
| - visitCompilationUnit(unit);
|
| - }
|
| -}
|
| -
|
| -class DartGenerator extends codegenerator.CodeGenerator {
|
| - final DevCompilerRuntime _runtime = new DevCompilerRuntime();
|
| -
|
| - DartGenerator(AbstractCompiler compiler) : super(compiler);
|
| -
|
| - Set<LibraryElement> computeExtraImports(Map<Identifier, NewTypeIdDesc> ids) {
|
| - var imports = new Set<LibraryElement>();
|
| - void process(Identifier id, NewTypeIdDesc desc) {
|
| - if (_identifierNeedsQualification(id, desc)) {
|
| - var library = desc.importedFrom;
|
| - if (utils.isDartPrivateLibrary(library)) {
|
| - _log.severe("Dropping import of private library ${library}\n");
|
| - return;
|
| - }
|
| - imports.add(library);
|
| - }
|
| - }
|
| - ids.forEach(process);
|
| - return imports;
|
| - }
|
| -
|
| - String generateLibrary(LibraryUnit library, LibraryInfo info) {
|
| - var r = new CoercionReifier(library, compiler, _runtime);
|
| - var ids = r.reify();
|
| - var extraImports = computeExtraImports(ids);
|
| -
|
| - for (var unit in library.partsThenLibrary) {
|
| - var libraryDir = makeOutputDirectory(info, unit);
|
| - var uri = unit.element.source.uri;
|
| - _log.fine("Generating unit $uri");
|
| - FileWriter out = new FileWriter(
|
| - options, path.join(libraryDir, '${uri.pathSegments.last}'));
|
| - var unitGen =
|
| - new UnitGenerator(unit, out, outDir, extraImports, ids, _runtime);
|
| - unitGen.generate();
|
| - out.finalize();
|
| - }
|
| -
|
| - return null;
|
| - }
|
| -}
|
| -
|
| -class EmptyUnitGenerator extends UnitGeneratorCommon {
|
| - final java_core.PrintWriter _out;
|
| - CompilationUnit unit;
|
| -
|
| - EmptyUnitGenerator(this.unit, java_core.PrintWriter out)
|
| - : _out = out,
|
| - super(out);
|
| -
|
| - void output(String s) => _out.print(s);
|
| - void outputln(String s) => _out.println(s);
|
| -
|
| - void generate() {
|
| - unit.visitChildren(this);
|
| - }
|
| -}
|
| -
|
| -// This class emits the code unchanged, for comparison purposes.
|
| -class EmptyDartGenerator extends codegenerator.CodeGenerator {
|
| - EmptyDartGenerator(AbstractCompiler compiler) : super(compiler);
|
| -
|
| - String generateLibrary(LibraryUnit library, LibraryInfo info) {
|
| - for (var unit in library.partsThenLibrary) {
|
| - var outputDir = makeOutputDirectory(info, unit);
|
| - generateUnit(unit, info, outputDir);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - void generateUnit(CompilationUnit unit, LibraryInfo info, String libraryDir) {
|
| - var uri = unit.element.source.uri;
|
| - _log.fine("Emitting original unit " + uri.toString());
|
| - FileWriter out = new FileWriter(
|
| - options, path.join(libraryDir, '${uri.pathSegments.last}'));
|
| - var unitGen = new EmptyUnitGenerator(unit, out);
|
| - unitGen.generate();
|
| - out.finalize();
|
| - }
|
| -}
|
|
|