Files
sdk/pkg/kernel/lib/binary/loader.dart
T
Asger Feldthaus 795ce44ec7 [kernel] Refactor the frontend classes.
dartk and other command-line tools no longer rely on analyzer classes
like AnalysisContext or DartSdk, and instead use only the interface
defined in loader.dart.

The class AnalyzerLoader has been renamed to DartLoader.

The sharing of state in batch mode is now owned by loader.dart, so
dartk.dart does not deal with DartSdk and package_config.

Repository no longer has a package or SDK path. These concepts are
now specific to the Dart frontend. Consequently, loading a binary
file no longer relies on URI resolution.

The Repository class is now more clearly focused on linking symbolic
names to their IR objects, which for the time being is only
URI-to-library bindings, but should be extended to support linking
class and member references across different files and different
loaders.

BUG=
R=kmillikin@google.com

Review URL: https://chromereviews.googleplex.com/512907013 .
2016-09-23 16:11:41 +02:00

124 lines
3.8 KiB
Dart

// 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.binary.loader;
import '../repository.dart';
import '../ast.dart';
import 'tag.dart';
import 'dart:io';
import 'ast_from_binary.dart';
abstract class BinaryReferenceLoader {
Library getLibraryReference(Library from, String relativePath);
Class getClassReference(Library library, int tag, int index);
Member getMemberReference(TreeNode classOrLibrary, int tag, int index);
Member getLibraryMemberReference(Library library, int tag, int index);
Member getClassMemberReference(Class classNode, int tag, int index);
}
class BinaryLoader implements BinaryReferenceLoader {
final Repository repository;
BinaryLoader(this.repository);
Library getLibraryReference(Library from, String relativePath) {
var fullUri = from.importUri.resolve(relativePath);
return repository.getLibraryReference(fullUri);
}
static int _pow2roundup(int x) {
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
TreeNode _extendList(
TreeNode parent, List<TreeNode> items, int index, TreeNode build()) {
if (items.length <= index) {
// Avoid excessive resizing by growing the list in steps.
items.length = _pow2roundup(index + 1);
}
return items[index] ??= build()..parent = parent;
}
Class getClassReference(Library library, int tag, int index) {
return _extendList(
library, library.classes, index, () => _buildClassReference(tag));
}
Class _buildClassReference(int tag) {
return new Class();
}
Field _buildFieldReference() {
return new Field(null);
}
Constructor _buildConstructorReference() {
return new Constructor(null);
}
Procedure _buildProcedureReference() {
return new Procedure(null, null, null);
}
Member getMemberReference(TreeNode classOrLibrary, int tag, int index) {
if (classOrLibrary is Class) {
return getClassMemberReference(classOrLibrary, tag, index);
} else {
return getLibraryMemberReference(classOrLibrary, tag, index);
}
}
Member getLibraryMemberReference(Library library, int tag, int index) {
switch (tag) {
case Tag.LibraryFieldReference:
case Tag.Field:
return _extendList(
library, library.fields, index, _buildFieldReference);
case Tag.LibraryProcedureReference:
case Tag.Procedure:
return _extendList(
library, library.procedures, index, _buildProcedureReference);
default:
throw 'Invalid library member reference tag: $tag';
}
}
Member getClassMemberReference(Class classNode, int tag, int index) {
switch (tag) {
case Tag.ClassFieldReference:
case Tag.Field:
return _extendList(
classNode, classNode.fields, index, _buildFieldReference);
case Tag.ClassConstructorReference:
case Tag.Constructor:
return _extendList(classNode, classNode.constructors, index,
_buildConstructorReference);
case Tag.ClassProcedureReference:
case Tag.Procedure:
return _extendList(
classNode, classNode.procedures, index, _buildProcedureReference);
default:
throw 'Invalid library member reference tag: $tag';
}
}
Program loadProgram(String filename) {
var bytes = new File(filename).readAsBytesSync();
return new BinaryBuilder(this, bytes, filename).readProgramFile();
}
TreeNode loadProgramOrLibrary(String filename) {
var uri = repository.normalizePath(filename);
var bytes = new File(filename).readAsBytesSync();
return new BinaryBuilder(this, bytes, filename).readProgramOrLibraryFile(
() => repository.getLibraryReference(uri));
}
}