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;