Simplify backend + create at right place
diff --git a/lib/src/codegen/backend/backend.dart b/lib/src/codegen/backend.dart
similarity index 81%
rename from lib/src/codegen/backend/backend.dart
rename to lib/src/codegen/backend.dart
index 29c3791..32bc255 100644
--- a/lib/src/codegen/backend/backend.dart
+++ b/lib/src/codegen/backend.dart
@@ -5,29 +5,47 @@
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
-import '../../js/js_ast.dart' as JS;
+import 'es6_backend.dart';
+import 'typescript_backend.dart';
+import 'module_builder.dart';
+
+import '../js/js_ast.dart' as JS;
+import '../options.dart';
+import '../utils.dart';
+import '../compiler.dart';
abstract class Backend {
+ Backend.base();
+ factory Backend(AbstractCompiler compiler) {
+ moduleBuilderFactory() =>
+ new ModuleBuilder(compiler.options.codegenOptions.moduleFormat);
+
+ if (compiler.options.codegenOptions.closure) {
+ return new TypeScriptBackend(compiler, moduleBuilderFactory);
+ } else {
+ return new Es6Backend(compiler, moduleBuilderFactory);
+ }
+ }
+
LibraryBuilder libraryBuilder(LibraryElement element);
// JS.Expression buildTypeLiteral(JS.TypeRef typeRef);
}
abstract class LibraryBuilder {
+ String jsModuleValue;
LibraryElement get element;
- LibraryPartBuilder libraryPartBuilder(CompilationUnitElement element);
+ JS.Expression get exportsVar;
- void build();
-}
-
-abstract class LibraryPartBuilder {
- CompilationUnitElement get element;
void buildTypedef(
FunctionTypeAliasElement element,
JS.TypeRef returnType, List<JS.TypeRef> paramTypes);
ClassBuilder classBuilder(ClassElement element, ClassDeclaration node);
+
+ void build();
}
+
abstract class ClassBuilder {
ClassElement get element;
ClassDeclaration get node;
diff --git a/lib/src/codegen/backend/es6_backend.dart b/lib/src/codegen/backend/es6_backend.dart
deleted file mode 100644
index 3a6db97..0000000
--- a/lib/src/codegen/backend/es6_backend.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2016, 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.
-
-import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
-
-import 'backend.dart';
-import '../../js/js_ast.dart' as JS;
-import '../module_builder.dart';
-import '../../utils.dart' show FileSystem;
-
-class Es6Backend extends Backend {
- final ModuleBuilder _moduleBuilder;
- final FileSystem _fileSystem;
- Es6Backend(this._moduleBuilder, this._fileSystem);
-
- LibraryBuilder libraryBuilder(LibraryElement element) =>
- new Es6LibraryBuilder(this, element);
-}
-
-class Es6LibraryBuilder extends LibraryBuilder {
- final Es6Backend _backend;
- final LibraryElement element;
- Es6LibraryBuilder(this._backend, this.element);
-
- LibraryPartBuilder libraryPartBuilder(CompilationUnitElement element) =>
- new Es6LibraryPartBuilder(_backend, element);
-
- void build() {
- // TODO(ochafik)
- }
-}
-
-class Es6LibraryPartBuilder extends LibraryPartBuilder {
- final Es6Backend _backend;
- final CompilationUnitElement element;
- Es6LibraryPartBuilder(this._backend, this.element);
-
- void buildTypedef(
- FunctionTypeAliasElement element,
- JS.TypeRef returnType, List<JS.TypeRef> paramTypes) {
- // TODO(ochafik)
- }
-
- ClassBuilder classBuilder(ClassElement element, ClassDeclaration node) =>
- new Es6ClassBuilder(_backend, element, node);
-}
-
-class Es6ClassBuilder extends DefaultClassBuilder {
- final Es6Backend _backend;
- final ClassElement element;
- final ClassDeclaration node;
-
- Es6ClassBuilder(this._backend, this.element, this.node);
-
- void build() {
- // TODO(ochafik)
- }
-}
diff --git a/lib/src/codegen/es6_backend.dart b/lib/src/codegen/es6_backend.dart
new file mode 100644
index 0000000..83f05b4
--- /dev/null
+++ b/lib/src/codegen/es6_backend.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2016, 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.
+
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
+
+import 'backend.dart';
+import 'module_builder.dart';
+import '../compiler.dart' show AbstractCompiler;
+import '../js/js_ast.dart' as JS;
+import 'js_names.dart' as JS;
+import 'js_metalet.dart' as JS;
+
+class Es6Backend extends Backend {
+ final AbstractCompiler compiler;
+ final ModuleBuilderFactory moduleBuilderFactory;
+ Es6Backend(this.compiler, this.moduleBuilderFactory) : super.base();
+
+ LibraryBuilder libraryBuilder(LibraryElement element) =>
+ new Es6LibraryBuilder(this, moduleBuilderFactory(), element);
+}
+
+class Es6LibraryBuilder extends LibraryBuilder {
+ final moduleItems = <JS.ModuleItem>[];
+ final Es6Backend _backend;
+ final LibraryElement element;
+ final ModuleBuilder moduleBuilder;
+ Es6LibraryBuilder(this._backend, this.moduleBuilder, this.element);
+ JS.Expression get exportsVar => moduleBuilder.exportsVar;
+
+ get compiler => _backend.compiler;
+
+ void buildTypedef(
+ FunctionTypeAliasElement element,
+ JS.TypeRef returnType, List<JS.TypeRef> paramTypes) {
+ // TODO(ochafik)
+ // moduleItems.add();
+ }
+
+ ClassBuilder classBuilder(ClassElement element, ClassDeclaration node) =>
+ new Es6ClassBuilder(moduleItems, element, node);
+
+ void build() {
+ var moduleBuilder = _backend.moduleBuilderFactory();
+ var module = moduleBuilder.build(
+ _backend.compiler.getModuleName(element.source.uri),
+ jsModuleValue,
+ moduleItems);
+
+ // TODO(ochafik).
+ // var out = _backend.compiler.getOutputPath(element.source.uri);
+ // var flags = compiler.options;
+ // var serverUri = flags.serverMode
+ // ? Uri.parse('http://${flags.host}:${flags.port}/')
+ // : null;
+ // return writeJsLibrary(module, out, compiler.inputBaseDir, serverUri,
+ // emitSourceMaps: _backend.compiler.options.codegenOptions.emitSourceMaps);
+ // TODO(ochafik)
+ }
+}
+
+class Es6ClassBuilder extends DefaultClassBuilder {
+ final List<JS.ModuleItem> out;
+ final ClassElement element;
+ final ClassDeclaration node;
+
+ Es6ClassBuilder(this.out, this.element, this.node);
+
+ void build() {
+ // TODO(ochafik)
+ }
+}
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index 2b3fddf..f59b0c0 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -29,6 +29,7 @@
import '../options.dart' show CodegenOptions;
import '../utils.dart';
+import 'backend.dart';
import 'code_generator.dart';
import 'js_field_storage.dart';
import 'js_interop.dart';
@@ -56,7 +57,8 @@
class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
final AbstractCompiler compiler;
final CodegenOptions options;
- final LibraryElement currentLibrary;
+ final LibraryBuilder libraryBuilder;
+ LibraryElement get currentLibrary => libraryBuilder.element;
final StrongTypeSystemImpl rules;
/// The global extension type table.
@@ -90,7 +92,7 @@
/// The name for the library's exports inside itself.
/// `exports` was chosen as the most similar to ES module patterns.
final _dartxVar = new JS.Identifier('dartx');
- final _exportsVar = new JS.TemporaryId('exports');
+ JS.Expression get _exportsVar => libraryBuilder.exportsVar;
final _runtimeLibVar = new JS.Identifier('dart');
final _namedArgTemp = new JS.TemporaryId('opts');
@@ -108,7 +110,7 @@
bool _isDartRuntime;
- JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary,
+ JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.libraryBuilder,
this._extensionTypes, this._fieldsNeedingStorage)
: compiler = compiler,
options = compiler.options.codegenOptions,
@@ -213,7 +215,6 @@
return moduleBuilder.build(
compiler.getModuleName(currentLibrary.source.uri),
_jsModuleValue,
- _exportsVar,
items);
}
@@ -3546,8 +3547,10 @@
class JSGenerator extends CodeGenerator {
final _extensionTypes = new HashSet<ClassElement>();
final TypeProvider _types;
+ final Backend _backend;
JSGenerator(AbstractCompiler compiler)
: _types = compiler.context.typeProvider,
+ _backend = new Backend(compiler),
super(compiler) {
// TODO(jacobr): determine the the set of types with extension methods from
// the annotations rather than hard coding the list once the analyzer
@@ -3580,8 +3583,11 @@
var library = unit.library.element.library;
var fields = findFieldsNeedingStorage(unit, _extensionTypes);
var rules = new StrongTypeSystemImpl();
+ var libraryBuilder = _backend.libraryBuilder(library);
var codegen =
- new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields);
+ new JSCodegenVisitor(compiler, rules, libraryBuilder, _extensionTypes, fields);
+ libraryBuilder.build();
+ // TODO(ochafik): Move the following lines to [LibraryBuilder.build]:
var module = codegen.emitLibrary(unit);
var out = compiler.getOutputPath(library.source.uri);
var flags = compiler.options;
diff --git a/lib/src/codegen/module_builder.dart b/lib/src/codegen/module_builder.dart
index 22cc871..de65a18 100644
--- a/lib/src/codegen/module_builder.dart
+++ b/lib/src/codegen/module_builder.dart
@@ -6,8 +6,12 @@
import '../js/js_ast.dart' as JS;
import '../js/js_ast.dart' show js;
+import 'js_names.dart' as JS;
+import 'js_metalet.dart' as JS;
import '../options.dart' show ModuleFormat;
+typedef ModuleBuilder ModuleBuilderFactory();
+
/// Helper that builds JS modules in a given [ModuleFormat].
abstract class ModuleBuilder {
final _exports = <String, String>{};
@@ -15,13 +19,15 @@
ModuleBuilder._();
+ /// Name of the object on which items are exported.
+ /// Lazy variables and constants are assumed to be declared on this instance.
+ JS.Expression get exportsVar;
+
/// Returns a [format]-specific [ModuleBuilder].
/// - [jsPath] is the path of the module being built.
/// - [jsModuleValue] is the default value to use for the library, in case of
/// js interop (comes from the @js.JS(jsModuleValue) annotation on the
/// library directive). It is null in any other case.
- /// - [exportsVar] is the name of the object on which items are exported. Lazy
- /// variables and constants are assumed to be declared on this instance.
factory ModuleBuilder(ModuleFormat format) {
switch (format) {
case ModuleFormat.legacy:
@@ -49,7 +55,7 @@
/// Builds a program out of menu items.
JS.Program build(String jsPath, String jsModuleValue,
- JS.Identifier exportsVar, Iterable<JS.ModuleItem> moduleItems);
+ Iterable<JS.ModuleItem> moduleItems);
}
class _ModuleImport {
@@ -65,9 +71,10 @@
/// Generates modules for with DDC's `dart_library.js` loading mechanism.
class LegacyModuleBuilder extends ModuleBuilder {
LegacyModuleBuilder() : super._();
+ final exportsVar = new JS.TemporaryId('exports');
JS.Program build(String jsPath, String jsModuleValue,
- JS.Identifier exportsVar, Iterable<JS.ModuleItem> moduleItems) {
+ Iterable<JS.ModuleItem> moduleItems) {
// TODO(jmesserly): it would be great to run the renamer on the body,
// then figure out if we really need each of these parameters.
// See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
@@ -123,9 +130,10 @@
// TODO(ochafik): Break strong dep cycles to accommodate the Closure Compiler.
class ES6ModuleBuilder extends ModuleBuilder {
ES6ModuleBuilder() : super._();
+ final exportsVar = new JS.TemporaryId('exports');
JS.Program build(String jsPath, String jsModuleValue,
- JS.Identifier exportsVar, Iterable<JS.ModuleItem> moduleItems) {
+ Iterable<JS.ModuleItem> moduleItems) {
var moduleStatements = <JS.ModuleItem>[
js.statement("const # = {};", [exportsVar])
];
@@ -165,9 +173,11 @@
/// Generates node modules.
class NodeModuleBuilder extends ModuleBuilder {
NodeModuleBuilder() : super._();
+ /// This is *not* a [JS.TemporaryId].
+ final exportsVar = new JS.Identifier('exports');
JS.Program build(String jsPath, String jsModuleValue,
- JS.Identifier exportsVar, Iterable<JS.ModuleItem> moduleItems) {
+ Iterable<JS.ModuleItem> moduleItems) {
var moduleStatements = <JS.ModuleItem>[js.statement("'use strict';"),];
for (var i in _imports) {
diff --git a/lib/src/codegen/typescript_backend.dart b/lib/src/codegen/typescript_backend.dart
new file mode 100644
index 0000000..fc59c86
--- /dev/null
+++ b/lib/src/codegen/typescript_backend.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, 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.
+
+import 'es6_backend.dart';
+import 'module_builder.dart';
+import '../utils.dart';
+import '../compiler.dart';
+
+class TypeScriptBackend extends Es6Backend {
+ TypeScriptBackend(
+ AbstractCompiler compiler, ModuleBuilderFactory moduleBuilderFactory)
+ : super(compiler, moduleBuilderFactory);
+}
diff --git a/lib/src/compiler.dart b/lib/src/compiler.dart
index 097a2dc..aabff36 100644
--- a/lib/src/compiler.dart
+++ b/lib/src/compiler.dart
@@ -32,7 +32,7 @@
import 'options.dart';
import 'report.dart';
import 'report/html_reporter.dart';
-import 'utils.dart' show isStrongModeError;
+import 'utils.dart' show FileSystem, isStrongModeError;
/// Sets up the type checker logger to print a span that highlights error
/// messages.
@@ -358,6 +358,9 @@
final AnalysisContext context;
final AnalysisErrorListener reporter;
+ // TODO(ochafik): Update transformer CL.
+ FileSystem fileSystem;
+
AbstractCompiler(this.context, this.options, [AnalysisErrorListener listener])
: reporter = listener ?? AnalysisErrorListener.NULL_LISTENER;