| // 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. |
| |
| library kernel.transformations.reify.standalone_runner; |
| |
| import 'analysis/program_analysis.dart'; |
| import 'dart:io' show File, IOSink; |
| |
| import '../../binary/ast_to_binary.dart' show BinaryPrinter; |
| |
| import '../../ast.dart'; |
| |
| import '../../kernel.dart'; |
| import '../../verifier.dart'; |
| import '../../text/ast_to_text.dart' show Printer; |
| |
| import 'transformation/remove_generics.dart'; |
| import 'transformation/transformer.dart' |
| show ReifyVisitor, RuntimeLibrary, RuntimeTypeSupportBuilder; |
| |
| import '../../core_types.dart' show CoreTypes; |
| |
| RuntimeLibrary findRuntimeTypeLibrary(Program p) { |
| Library findLibraryEndingWith(String postfix) { |
| Iterable<Library> candidates = p.libraries.where((Library l) { |
| return l.importUri.toString().endsWith(postfix); |
| }); |
| if (candidates.length != 1) { |
| String howMany = candidates.isEmpty ? "No" : "Multiple"; |
| throw new Exception( |
| "$howMany candidates for runtime support library found."); |
| } |
| return candidates.single; |
| } |
| |
| Library types = findLibraryEndingWith("reify/types.dart"); |
| Library declarations = findLibraryEndingWith("reify/declarations.dart"); |
| Library interceptors = findLibraryEndingWith("reify/interceptors.dart"); |
| return new RuntimeLibrary(types, declarations, interceptors); |
| } |
| |
| Program transformProgramUsingLibraries( |
| CoreTypes coreTypes, Program program, RuntimeLibrary runtimeLibrary, |
| [Library libraryToTransform]) { |
| LibraryFilter filter = libraryToTransform != null |
| ? (Library library) => library == libraryToTransform |
| : (_) => true; |
| ProgramKnowledge knowledge = analyze(program, analyzeLibrary: filter); |
| Library mainLibrary = program.mainMethod.parent; |
| RuntimeTypeSupportBuilder builder = |
| new RuntimeTypeSupportBuilder(runtimeLibrary, coreTypes, mainLibrary); |
| ReifyVisitor transformer = |
| new ReifyVisitor(runtimeLibrary, builder, knowledge, libraryToTransform); |
| // Transform the main program. |
| program = program.accept(transformer); |
| if (!filter(runtimeLibrary.interceptorsLibrary)) { |
| // We need to transform the interceptor function in any case to make sure |
| // that the type literals in the interceptor function are rewritten. |
| runtimeLibrary.interceptorFunction.accept(transformer); |
| } |
| builder.createDeclarations(); |
| program = program.accept(new Erasure(transformer)); |
| // TODO(karlklose): skip checks in debug mode |
| verifyProgram(program); |
| return program; |
| } |
| |
| Program transformProgram(CoreTypes coreTypes, Program program) { |
| RuntimeLibrary runtimeLibrary = findRuntimeTypeLibrary(program); |
| Library mainLibrary = program.mainMethod.enclosingLibrary; |
| return transformProgramUsingLibraries( |
| coreTypes, program, runtimeLibrary, mainLibrary); |
| } |
| |
| main(List<String> arguments) async { |
| String path = arguments.first; |
| Uri output; |
| if (arguments.length > 1) { |
| output = Uri.base.resolve(arguments[1]); |
| } |
| Uri uri = Uri.base.resolve(path); |
| Program program = loadProgramFromBinary(uri.toFilePath()); |
| CoreTypes coreTypes = new CoreTypes(program); |
| |
| RuntimeLibrary runtimeLibrary = findRuntimeTypeLibrary(program); |
| Library mainLibrary = program.mainMethod.enclosingLibrary; |
| program = transformProgramUsingLibraries( |
| coreTypes, program, runtimeLibrary, mainLibrary); |
| |
| if (output == null) { |
| // Print result |
| StringBuffer sb = new StringBuffer(); |
| Printer printer = new Printer(sb); |
| printer.writeLibraryFile(mainLibrary); |
| print("$sb"); |
| } else { |
| IOSink sink = new File.fromUri(output).openWrite(); |
| try { |
| new BinaryPrinter(sink).writeProgramFile(program); |
| } finally { |
| await sink.close(); |
| } |
| try { |
| // Check that we can read the binary file. |
| loadProgramFromBinary(output.toFilePath()); |
| } catch (e) { |
| print("Error when attempting to read $output."); |
| rethrow; |
| } |
| } |
| } |