CFE support for expression evaluation, refactored.
Change-Id: I7eac1020b7aa11ea0276f909d7b11ee6388b1aa7
Reviewed-on: https://dart-review.googlesource.com/53209
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index c60a782..76e4075 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -4,7 +4,8 @@
import 'dart:async' show Future;
-import 'package:kernel/kernel.dart' show Component;
+import 'package:kernel/kernel.dart'
+ show Component, Procedure, DartType, TypeParameter;
import '../base/processed_options.dart' show ProcessedOptions;
@@ -12,6 +13,8 @@
import '../fasta/incremental_compiler.dart' show IncrementalCompiler;
+import '../fasta/scanner/string_scanner.dart' show StringScanner;
+
import 'compiler_options.dart' show CompilerOptions;
abstract class IncrementalKernelGenerator {
@@ -30,4 +33,39 @@
/// valid files. This guarantees that those files will be re-read on the
/// next call to [computeDelta]).
void invalidate(Uri uri);
+
+ /// Compile [expression] as an [Expression]. A function returning that
+ /// expression is compiled.
+ ///
+ /// [expression] may use the variables supplied in [definitions] as free
+ /// variables and [typeDefinitions] as free type variables. These will become
+ /// required parameters to the compiled function. All elements of
+ /// [definitions] and [typeDefinitions] will become parameters/type
+ /// parameters, whether or not they appear free in [expression]. The type
+ /// parameters should have a null parent pointer.
+ ///
+ /// [libraryUri] must refer to either a previously compiled library.
+ /// [className] may optionally refer to a class within such library to use for
+ /// the scope of the expression. In that case, [isStatic] indicates whether
+ /// the scope can access [this].
+ ///
+ /// It is illegal to use "await" in [expression] and the compiled function
+ /// will always be synchronous.
+ ///
+ /// [computeDelta] must have been called at least once prior.
+ ///
+ /// [compileExpression] will return [null] if the library or class for
+ /// [enclosingNode] could not be found. Otherwise, errors are reported in the
+ /// normal way.
+ Future<Procedure> compileExpression(
+ String expression,
+ Map<String, DartType> definitions,
+ List<TypeParameter> typeDefinitions,
+ Uri libraryUri,
+ [String className,
+ bool isStatic = false]);
+}
+
+bool isLegalIdentifier(String identifier) {
+ return StringScanner.isLegalIdentifier(identifier);
}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 1513772..6a3bbab 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -1348,6 +1348,8 @@
const Code<Message Function(String name)> codeDuplicatedNamePreviouslyUsed =
const Code<Message Function(String name)>(
"DuplicatedNamePreviouslyUsed", templateDuplicatedNamePreviouslyUsed,
+ analyzerCode: "REFERENCED_BEFORE_DECLARATION",
+ dart2jsCode: "*ignored*",
severity: Severity.error);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1725,6 +1727,15 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedOneExpression = messageExpectedOneExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedOneExpression = const MessageCode(
+ "ExpectedOneExpression",
+ severity: Severity.error,
+ message: r"""Expected one expression, but found additional input.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExpectedOpenParens = messageExpectedOpenParens;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/testing/hybrid_file_system.dart b/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
similarity index 79%
rename from pkg/front_end/lib/src/testing/hybrid_file_system.dart
rename to pkg/front_end/lib/src/fasta/hybrid_file_system.dart
index ba2a2fe..4b388a3 100644
--- a/pkg/front_end/lib/src/testing/hybrid_file_system.dart
+++ b/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
@@ -8,17 +8,18 @@
import 'dart:async';
-import 'package:front_end/src/api_prototype/file_system.dart';
-import 'package:front_end/src/api_prototype/memory_file_system.dart';
-import 'package:front_end/src/api_prototype/standard_file_system.dart';
+import '../api_prototype/file_system.dart';
+import '../api_prototype/memory_file_system.dart';
+import '../api_prototype/standard_file_system.dart';
/// A file system that mixes files from memory and a physical file system. All
/// memory entities take priotity over file system entities.
class HybridFileSystem implements FileSystem {
final MemoryFileSystem memory;
- final StandardFileSystem physical = StandardFileSystem.instance;
+ final FileSystem physical;
- HybridFileSystem(this.memory);
+ HybridFileSystem(this.memory, [FileSystem _physical])
+ : physical = _physical ?? StandardFileSystem.instance;
@override
FileSystemEntity entityForUri(Uri uri) =>
@@ -37,7 +38,8 @@
Future<FileSystemEntity> get delegate async {
if (_delegate != null) return _delegate;
FileSystemEntity entity = _fs.memory.entityForUri(uri);
- if ((uri.scheme != 'file' && uri.scheme != 'data') ||
+ if (((uri.scheme != 'file' && uri.scheme != 'data') &&
+ _fs.physical is StandardFileSystem) ||
await entity.exists()) {
_delegate = entity;
return _delegate;
diff --git a/pkg/front_end/lib/src/fasta/import.dart b/pkg/front_end/lib/src/fasta/import.dart
index 1ae3b3b..d48f2a2 100644
--- a/pkg/front_end/lib/src/fasta/import.dart
+++ b/pkg/front_end/lib/src/fasta/import.dart
@@ -88,7 +88,7 @@
}
}
-createPrefixBuilder(
+KernelPrefixBuilder createPrefixBuilder(
String prefix,
LibraryBuilder importer,
LibraryBuilder imported,
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 17a2764..68033b6 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -8,13 +8,33 @@
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
-import 'package:kernel/kernel.dart'
- show Component, Library, LibraryPart, Procedure, Source;
-
import '../api_prototype/file_system.dart' show FileSystemEntity;
+import 'package:kernel/kernel.dart'
+ show
+ Library,
+ Name,
+ ReturnStatement,
+ FunctionNode,
+ Class,
+ Expression,
+ DartType,
+ LibraryPart,
+ Component,
+ LibraryDependency,
+ Source,
+ Procedure,
+ TypeParameter,
+ ProcedureKind;
+
+import '../api_prototype/memory_file_system.dart' show MemoryFileSystem;
+
+import 'hybrid_file_system.dart' show HybridFileSystem;
+
+import 'package:kernel/kernel.dart' as kernel show Combinator;
+
import '../api_prototype/incremental_kernel_generator.dart'
- show IncrementalKernelGenerator;
+ show IncrementalKernelGenerator, isLegalIdentifier;
import 'builder/builder.dart' show LibraryBuilder;
@@ -31,12 +51,17 @@
import 'library_graph.dart' show LibraryGraph;
+import 'kernel/kernel_library_builder.dart' show KernelLibraryBuilder;
+import 'kernel/kernel_shadow_ast.dart' show ShadowVariableDeclaration;
+
import 'source/source_library_builder.dart' show SourceLibraryBuilder;
import 'ticker.dart' show Ticker;
import 'uri_translator.dart' show UriTranslator;
+import 'combinator.dart' show Combinator;
+
class IncrementalCompiler implements IncrementalKernelGenerator {
final CompilerContext context;
@@ -132,11 +157,18 @@
ticker.logMs("Decided to reuse ${reusedLibraries.length}"
" of ${userCode.loader.builders.length} libraries");
}
+
reusedLibraries.addAll(platformBuilders);
KernelIncrementalTarget userCodeOld = userCode;
userCode = new KernelIncrementalTarget(
- c.fileSystem, false, dillLoadedData, uriTranslator,
+ new HybridFileSystem(
+ new MemoryFileSystem(
+ new Uri(scheme: "org-dartlang-debug", path: "/")),
+ c.fileSystem),
+ false,
+ dillLoadedData,
+ uriTranslator,
uriToSource: c.uriToSource);
for (LibraryBuilder library in reusedLibraries) {
@@ -168,8 +200,11 @@
return new Component(
libraries: compiledLibraries, uriToSource: <Uri, Source>{});
}
- userCodeOld?.loader?.builders?.clear();
- userCodeOld = null;
+ if (componentWithDill != null) {
+ userCodeOld?.loader?.releaseAncillaryResources();
+ userCodeOld?.loader?.builders?.clear();
+ userCodeOld = null;
+ }
List<Library> compiledLibraries =
new List<Library>.from(userCode.loader.libraries);
@@ -188,8 +223,10 @@
outputLibraries = compiledLibraries;
}
- // Clean up.
- userCode.loader.releaseAncillaryResources();
+ if (componentWithDill == null) {
+ userCode.loader.builders.clear();
+ userCode = userCodeOld;
+ }
// This is the incremental component.
return new Component(libraries: outputLibraries, uriToSource: uriToSource)
@@ -318,6 +355,107 @@
ticker.logMs("Appended libraries");
}
+ @override
+ Future<Procedure> compileExpression(
+ String expression,
+ Map<String, DartType> definitions,
+ List<TypeParameter> typeDefinitions,
+ Uri libraryUri,
+ [String className,
+ bool isStatic = false]) async {
+ assert(dillLoadedData != null && userCode != null);
+
+ return await context.runInContext((_) async {
+ LibraryBuilder library = userCode.loader.read(libraryUri, -1);
+
+ Class kernelClass;
+ if (className != null) {
+ kernelClass = library.scopeBuilder[className]?.target;
+ if (kernelClass == null) return null;
+ }
+
+ userCode.loader.seenMessages.clear();
+
+ for (TypeParameter typeParam in typeDefinitions) {
+ if (!isLegalIdentifier(typeParam.name)) return null;
+ }
+ for (String name in definitions.keys) {
+ if (!isLegalIdentifier(name)) return null;
+ }
+
+ Uri debugExprUri = new Uri(
+ scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
+
+ KernelLibraryBuilder debugLibrary = new KernelLibraryBuilder(
+ libraryUri,
+ debugExprUri,
+ userCode.loader,
+ null,
+ library.scope.createNestedScope("expression"),
+ library.target);
+
+ if (library is DillLibraryBuilder) {
+ for (LibraryDependency dependency in library.target.dependencies) {
+ if (!dependency.isImport) continue;
+
+ List<Combinator> combinators;
+
+ for (kernel.Combinator combinator in dependency.combinators) {
+ combinators ??= <Combinator>[];
+
+ combinators.add(combinator.isShow
+ ? new Combinator.show(
+ combinator.names, combinator.fileOffset, library.fileUri)
+ : new Combinator.hide(
+ combinator.names, combinator.fileOffset, library.fileUri));
+ }
+
+ debugLibrary.addImport(
+ null,
+ dependency.importedLibraryReference.canonicalName.name,
+ null,
+ dependency.name,
+ combinators,
+ dependency.isDeferred,
+ -1,
+ -1,
+ -1);
+ }
+
+ debugLibrary.addImportsToScope();
+ }
+
+ HybridFileSystem hfs = userCode.fileSystem;
+ MemoryFileSystem fs = hfs.memory;
+ fs.entityForUri(debugExprUri).writeAsStringSync(expression);
+
+ FunctionNode parameters = new FunctionNode(null,
+ typeParameters: typeDefinitions,
+ positionalParameters: definitions.keys
+ .map((name) => new ShadowVariableDeclaration(name, 0))
+ .toList());
+
+ debugLibrary.build(userCode.loader.coreLibrary, modifyTarget: false);
+ Expression compiledExpression = await userCode.loader.buildExpression(
+ debugLibrary, className, className != null && !isStatic, parameters);
+
+ Procedure procedure = new Procedure(
+ new Name("debugExpr"), ProcedureKind.Method, parameters,
+ isStatic: isStatic);
+
+ parameters.body = new ReturnStatement(compiledExpression)
+ ..parent = parameters;
+
+ procedure.fileUri = debugLibrary.fileUri;
+ procedure.parent = className != null ? kernelClass : library.target;
+
+ userCode.uriToSource.remove(debugExprUri);
+ userCode.loader.sourceBytes.remove(debugExprUri);
+
+ return procedure;
+ });
+ }
+
List<LibraryBuilder> computeReusedLibraries(
Set<Uri> invalidatedUris, UriTranslator uriTranslator) {
if (userCode == null && userBuilders == null) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index e4b47b1..8273574 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -19,6 +19,7 @@
import '../parser.dart'
show
Assert,
+ Parser,
FormalParameterKind,
IdentifierContext,
MemberKind,
@@ -714,6 +715,42 @@
return expressions;
}
+ @override
+ Expression parseSingleExpression(
+ Parser parser, Token token, FunctionNode parameters) {
+ List<KernelTypeVariableBuilder> typeParameterBuilders;
+ for (TypeParameter typeParameter in parameters.typeParameters) {
+ typeParameterBuilders ??= <KernelTypeVariableBuilder>[];
+ typeParameterBuilders.add(
+ new KernelTypeVariableBuilder.fromKernel(typeParameter, library));
+ }
+ enterFunctionTypeScope(typeParameterBuilders);
+
+ enterLocalScope(
+ null,
+ new FormalParameters(parameters.positionalParameters, null, -1)
+ .computeFormalParameterScope(scope, member, this));
+
+ token = parser.parseExpression(parser.syntheticPreviousToken(token));
+
+ Expression expression = popForValue();
+ Token eof = token.next;
+
+ if (!eof.isEof) {
+ expression = wrapInLocatedCompileTimeError(
+ expression,
+ fasta.messageExpectedOneExpression
+ .withLocation(uri, eof.charOffset, eof.length));
+ }
+
+ ShadowReturnStatement fakeReturn = new ShadowReturnStatement(expression);
+
+ _typeInferrer.inferFunctionBody(
+ this, const DynamicType(), AsyncMarker.Sync, fakeReturn);
+
+ return fakeReturn.expression;
+ }
+
void finishConstructor(
KernelConstructorBuilder builder, AsyncMarker asyncModifier) {
/// Quotes below are from [Dart Programming Language Specification, 4th
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 08ce85d..463f5b4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -111,9 +111,11 @@
/// the error message is the corresponding value in the map.
Map<String, String> unserializableExports;
- KernelLibraryBuilder(Uri uri, Uri fileUri, Loader loader, this.actualOrigin)
- : library = actualOrigin?.library ?? new Library(uri, fileUri: fileUri),
- super(loader, fileUri);
+ KernelLibraryBuilder(Uri uri, Uri fileUri, Loader loader, this.actualOrigin,
+ [Scope scope, Library target])
+ : library = target ??
+ (actualOrigin?.library ?? new Library(uri, fileUri: fileUri)),
+ super(loader, fileUri, scope);
@override
KernelLibraryBuilder get origin => actualOrigin ?? this;
@@ -828,13 +830,16 @@
}
@override
- Library build(LibraryBuilder coreLibrary) {
+ Library build(LibraryBuilder coreLibrary, {bool modifyTarget}) {
super.build(coreLibrary);
+ if (modifyTarget == false) return library;
+
addDependencies(library, new Set<KernelLibraryBuilder>());
loader.target.metadataCollector
?.setDocumentationComment(library, documentationComment);
+
library.name = name;
library.procedures.sort(compareProcedures);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
index b884fd5..1290f11 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
@@ -29,11 +29,19 @@
KernelTypeVariableBuilder(
String name, KernelLibraryBuilder compilationUnit, int charOffset,
- [KernelTypeBuilder bound])
- : actualParameter = new TypeParameter(name, null)
- ..fileOffset = charOffset,
+ [KernelTypeBuilder bound, TypeParameter actual])
+ // TODO(32378): We would like to use '??' here instead, but in conjuction
+ // with '..', it crashes Dart2JS.
+ : actualParameter = actual != null
+ ? (actual..fileOffset = charOffset)
+ : (new TypeParameter(name, null)..fileOffset = charOffset),
super(name, bound, compilationUnit, charOffset);
+ KernelTypeVariableBuilder.fromKernel(
+ TypeParameter parameter, KernelLibraryBuilder compilationUnit)
+ : actualParameter = parameter,
+ super(parameter.name, null, compilationUnit, parameter.fileOffset);
+
@override
KernelTypeVariableBuilder get origin => actualOrigin ?? this;
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
index 236b31e..7de4ef6 100644
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
@@ -4,7 +4,7 @@
library dart2js.scanner.string_scanner;
-import '../../scanner/token.dart' show SyntheticStringToken, TokenType;
+import '../../scanner/token.dart' show Token, SyntheticStringToken, TokenType;
import '../../scanner/token.dart' as analyzer show StringToken;
@@ -12,6 +12,8 @@
import 'token.dart' show CommentToken, DartDocToken, StringToken;
+import 'error_token.dart' show ErrorToken;
+
/**
* Scanner that reads from a String and creates tokens that points to
* substrings.
@@ -37,6 +39,12 @@
: string;
}
+ static bool isLegalIdentifier(String identifier) {
+ StringScanner scanner = new StringScanner(identifier);
+ Token startToken = scanner.tokenize();
+ return startToken is! ErrorToken && startToken.next.isEof;
+ }
+
int advance() => string.codeUnitAt(++scanOffset);
int peek() => string.codeUnitAt(scanOffset + 1);
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index cdf9a9b..f6b3309 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -66,6 +66,11 @@
: this(<String, Builder>{}, null, parent, debugName,
isModifiable: isModifiable);
+ Scope copyWithParent(Scope parent, String debugName) {
+ return new Scope(super.local, super.setters, parent, debugName,
+ isModifiable: isModifiable);
+ }
+
/// Don't use this. Use [becomePartOf] instead.
void set local(_) => unsupported("local=", -1, null);
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 68b1941..3f9ee22 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -527,13 +527,9 @@
StackListener createListener(
ModifierBuilder builder, Scope memberScope, bool isInstanceMember,
[Scope formalParameterScope]) {
- InterfaceType thisType;
- if (builder.isClassMember) {
- // Note: we set thisType regardless of whether we are building a static
- // member, since that provides better error recovery.
- Class cls = builder.parent.target;
- thisType = cls.thisType;
- }
+ // Note: we set thisType regardless of whether we are building a static
+ // member, since that provides better error recovery.
+ InterfaceType thisType = currentClass?.target?.thisType;
var typeInferrer = library.disableTypeInference
? typeInferenceEngine.createDisabledTypeInferrer()
: typeInferenceEngine.createLocalTypeInferrer(uri, thisType, library);
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 6c44178..25be339 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -109,9 +109,9 @@
bool canAddImplementationBuilders = false;
- SourceLibraryBuilder(SourceLoader loader, Uri fileUri)
+ SourceLibraryBuilder(SourceLoader loader, Uri fileUri, Scope scope)
: this.fromScopes(loader, fileUri, new DeclarationBuilder<T>.library(),
- new Scope.top());
+ scope ?? new Scope.top());
SourceLibraryBuilder.fromScopes(
this.loader, this.fileUri, this.libraryDeclaration, this.importScope)
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 75ebc59..5419f26 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -12,10 +12,12 @@
show
Arguments,
Class,
+ Component,
Expression,
+ FunctionNode,
Library,
LibraryDependency,
- Component,
+ ProcedureKind,
Supertype;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -64,13 +66,17 @@
import '../kernel/kernel_shadow_ast.dart'
show ShadowClass, ShadowTypeInferenceEngine;
+import '../kernel/kernel_builder.dart' show KernelProcedureBuilder;
+
import '../kernel/kernel_target.dart' show KernelTarget;
+import '../kernel/body_builder.dart' show BodyBuilder;
+
import '../loader.dart' show Loader;
import '../parser/class_member_parser.dart' show ClassMemberParser;
-import '../parser.dart' show lengthForToken, offsetForToken;
+import '../parser.dart' show Parser, lengthForToken, offsetForToken;
import '../problems.dart' show internalProblem;
@@ -207,6 +213,37 @@
}
}
+ Future<Expression> buildExpression(
+ SourceLibraryBuilder library,
+ String enclosingClass,
+ bool isInstanceMember,
+ FunctionNode parameters) async {
+ Token token = await tokenize(library, suppressLexicalErrors: false);
+ if (token == null) return null;
+ DietListener dietListener = createDietListener(library);
+
+ Builder parent = library;
+ if (enclosingClass != null) {
+ Builder cls = dietListener.memberScope.lookup(enclosingClass, -1, null);
+ if (cls is ClassBuilder) {
+ parent = cls;
+ dietListener
+ ..currentClass = cls
+ ..memberScope = cls.scope.copyWithParent(
+ dietListener.memberScope.withTypeVariables(cls.typeVariables),
+ "debugExpression in $enclosingClass");
+ }
+ }
+ KernelProcedureBuilder builder = new KernelProcedureBuilder(null, 0, null,
+ "debugExpr", null, null, ProcedureKind.Method, library, 0, -1, -1)
+ ..parent = parent;
+ BodyBuilder listener = dietListener.createListener(
+ builder, dietListener.memberScope, isInstanceMember);
+
+ return listener.parseSingleExpression(
+ new Parser(listener), token, parameters);
+ }
+
KernelTarget get target => super.target;
DietListener createDietListener(LibraryBuilder library) {
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index d440748..938ad81 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -4,7 +4,7 @@
library fasta.stack_listener;
-import 'package:kernel/ast.dart' show AsyncMarker, Expression;
+import 'package:kernel/ast.dart' show AsyncMarker, Expression, FunctionNode;
import '../deprecated_problems.dart' show deprecated_inputError;
@@ -14,7 +14,7 @@
messageNativeClauseShouldBeAnnotation,
templateInternalProblemStackNotEmpty;
-import '../parser.dart' show Listener, MemberKind;
+import '../parser.dart' show Listener, MemberKind, Parser;
import '../parser/identifier_context.dart' show IdentifierContext;
@@ -96,6 +96,12 @@
// and ast_builder.dart.
void exitLocalScope() => unsupported("exitLocalScope", -1, uri);
+ // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart.
+ dynamic parseSingleExpression(
+ Parser parser, Token token, FunctionNode parameters) {
+ return unsupported("finishSingleExpression", -1, uri);
+ }
+
void push(Object node) {
if (node == null) unhandled("null", "push", -1, uri);
stack.push(node);
diff --git a/pkg/front_end/lib/src/testing/compiler_common.dart b/pkg/front_end/lib/src/testing/compiler_common.dart
index 0193e73..d09c4c6 100644
--- a/pkg/front_end/lib/src/testing/compiler_common.dart
+++ b/pkg/front_end/lib/src/testing/compiler_common.dart
@@ -17,7 +17,7 @@
import '../compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
-import '../testing/hybrid_file_system.dart' show HybridFileSystem;
+import '../fasta/hybrid_file_system.dart' show HybridFileSystem;
/// Generate kernel for a script.
///
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 01a8aa0..2bd2b36 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -118,6 +118,8 @@
ExpectedClassMember/example: Fail
ExpectedDeclaration/example: Fail
ExpectedFunctionBody/example: Fail
+ExpectedOneExpression/analyzerCode: Fail
+ExpectedOneExpression/example: Fail
ExpectedOpenParens/analyzerCode: Fail
ExpectedOpenParens/example: Fail
ExpectedStatement/statement: Fail
@@ -411,4 +413,3 @@
UnterminatedToken/example: Fail
YieldAsIdentifier/example: Fail
YieldNotGenerator/example: Fail
-
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index bf341d7..59b79aa 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -2103,3 +2103,7 @@
template: "Can't invoke the type '#type' because its declaration of `.call` is not a method."
tip: "Change .call to a method or explicitly invoke .call."
severity: ERROR
+
+ExpectedOneExpression:
+ template: "Expected one expression, but found additional input."
+ severity: ERROR
diff --git a/pkg/front_end/test/fasta/expression_test.dart b/pkg/front_end/test/fasta/expression_test.dart
index c0611b0..4a21e78 100644
--- a/pkg/front_end/test/fasta/expression_test.dart
+++ b/pkg/front_end/test/fasta/expression_test.dart
@@ -11,13 +11,7 @@
import "dart:io" show File, IOSink;
import "package:kernel/ast.dart"
- show
- Procedure,
- Component,
- CanonicalName,
- DynamicType,
- DartType,
- TypeParameter;
+ show Procedure, Component, DynamicType, DartType, TypeParameter;
import "package:testing/testing.dart"
show Chain, ChainContext, Result, Step, TestDescription, runMe;
@@ -123,7 +117,9 @@
final bool isStaticMethod;
- final CanonicalName enclosingNode;
+ final Uri library;
+
+ final String className;
String expression;
@@ -135,7 +131,8 @@
this.definitions,
this.typeDefinitions,
this.isStaticMethod,
- this.enclosingNode,
+ this.library,
+ this.className,
this.expression);
String toString() {
@@ -143,7 +140,8 @@
"$entryPoint, "
"$definitions, "
"$typeDefinitions,"
- "$enclosingNode, "
+ "$library, "
+ "$className, "
"static = $isStaticMethod)";
}
@@ -155,7 +153,7 @@
if (!(new File.fromUri(entryPoint)).existsSync()) {
return "Entry point $entryPoint doesn't exist.";
}
- if (enclosingNode == null || enclosingNode == "") {
+ if (library == null) {
return "No enclosing node.";
}
if (expression == null) {
@@ -233,7 +231,8 @@
List<String> definitions = <String>[];
List<String> typeDefinitions = <String>[];
bool isStaticMethod = false;
- CanonicalName enclosingNode;
+ Uri library;
+ String className;
String expression;
dynamic maps = loadYamlNode(contents, sourceUrl: uri);
@@ -248,13 +247,10 @@
if (key == "entry_point") {
entryPoint = description.uri.resolveUri(Uri.parse(value as String));
} else if (key == "position") {
- Uri positionUri =
- description.uri.resolveUri(Uri.parse(value as String));
- enclosingNode = new CanonicalName.root();
- enclosingNode =
- enclosingNode.getChild("${positionUri.removeFragment()}");
- if (positionUri.fragment != null && positionUri.fragment != '') {
- enclosingNode = enclosingNode.getChild(positionUri.fragment);
+ Uri uri = description.uri.resolveUri(Uri.parse(value as String));
+ library = uri.removeFragment();
+ if (uri.fragment != null && uri.fragment != '') {
+ className = uri.fragment;
}
} else if (key == "definitions") {
definitions = (value as YamlList).map((x) => x as String).toList();
@@ -268,7 +264,7 @@
}
}
var test = new TestCase(description, entryPoint, definitions,
- typeDefinitions, isStaticMethod, enclosingNode, expression);
+ typeDefinitions, isStaticMethod, library, className, expression);
var result = test.validate();
if (result != null) {
return new Result.fail(tests, result);
@@ -325,9 +321,15 @@
}
for (var compiler in [sourceCompiler, dillCompiler]) {
- // TODO: actually run the compiler
- test.results
- .add(new CompilationResult(compiler == null ? null : null, []));
+ Procedure compiledProcedure = await compiler.compileExpression(
+ test.expression,
+ definitions,
+ typeParams,
+ test.library,
+ test.className,
+ test.isStaticMethod);
+ var errors = context.takeErrors();
+ test.results.add(new CompilationResult(compiledProcedure, errors));
}
}
return new Result.pass(tests);
@@ -357,7 +359,7 @@
final List<CompilationMessage> errors = <CompilationMessage>[];
final CompilerOptions optionBuilder = new CompilerOptions()
- ..strongMode = false
+ ..strongMode = true
..reportMessages = true
..verbose = true
..fileSystem = fs
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index 279bc8a..16f96a5 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -29,7 +29,7 @@
import 'package:front_end/src/fasta/severity.dart'
show Severity, severityEnumValues;
-import 'package:front_end/src/testing/hybrid_file_system.dart'
+import 'package:front_end/src/fasta/hybrid_file_system.dart'
show HybridFileSystem;
import "../../tool/_fasta/entry_points.dart" show BatchCompiler;
diff --git a/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart b/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
index 9ad0d40..023efa7 100644
--- a/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
@@ -36,7 +36,7 @@
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
-import 'package:front_end/src/testing/hybrid_file_system.dart'
+import 'package:front_end/src/fasta/hybrid_file_system.dart'
show HybridFileSystem;
import '../../tool/reload.dart' show RemoteVm;
diff --git a/pkg/front_end/test/subpackage_relationships_test.dart b/pkg/front_end/test/subpackage_relationships_test.dart
index ddacabc..bcf7288 100644
--- a/pkg/front_end/test/subpackage_relationships_test.dart
+++ b/pkg/front_end/test/subpackage_relationships_test.dart
@@ -49,6 +49,7 @@
'lib/src/base',
'lib/src/byte_store',
'lib/src/fasta',
+ 'lib/src/fasta/scanner'
]),
'lib/src/api_unstable': new SubpackageRules(allowedDependencies: [
'lib/src',
@@ -160,6 +161,7 @@
'lib/src/testing': new SubpackageRules(allowedDependencies: [
'lib/src',
'lib/src/api_prototype',
+ 'lib/src/fasta',
]),
};
diff --git a/pkg/front_end/testcases/expression.status b/pkg/front_end/testcases/expression.status
index 87a97a3..87869b0 100644
--- a/pkg/front_end/testcases/expression.status
+++ b/pkg/front_end/testcases/expression.status
@@ -1,47 +1,3 @@
// Copyright (c) 2018, 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.
-
-class_capture.expression: Fail
-class_getter.expression: Fail
-class_invalid_static.expression: Fail
-class_invalid_static_capture.expression: Fail
-class_invalid_static_getter.expression: Fail
-class_invalid_static_setter.expression: Fail
-class_method.expression: Fail
-class_setter.expression: Fail
-class_static.expression: Fail
-class_static2.expression: Fail
-class_static3.expression: Fail
-class_type_param_bound.expression: Fail
-class_type_param_bound_illegal.expression: Fail
-class_type_param_reference.expression: Fail
-class_type_param_reference_arg.expression: Fail
-class_type_param_reference_arg_inferred.expression: Fail
-class_type_param_reference_ctor.expression: Fail
-class_type_param_reference_ctor_inferred.expression: Fail
-class_type_param_reference_var.expression: Fail
-core_lib_imported.expression: Fail
-core_lib_internal.expression: Fail
-eval.dart: Fail
-invalid.expression: Fail
-lib_ctor.expression: Fail
-lib_external_ctor.expression: Fail
-lib_nonctor.expression: Fail
-lib_nonreference.expression: Fail
-lib_nonshown_ctor.expression: Fail
-lib_reference.expression: Fail
-lib_simple.expression: Fail
-missing_variable_types.expression: Fail
-param_assign.expression: Fail
-param_capture.expression: Fail
-param_conflict.expression: Fail
-param_conflict_class.expression: Fail
-param_method.expression: Fail
-type_param_bound.expression: Fail
-type_param_shadow.expression: Fail
-type_param_shadow_arg.expression: Fail
-type_param_shadow_arg_ctor_inferred.expression: Fail
-type_param_shadow_arg_inferred.expression: Fail
-type_param_shadow_ctor.expression: Fail
-type_param_shadow_var.expression: Fail
diff --git a/pkg/front_end/testcases/expression/invalid.expression.yaml.expect b/pkg/front_end/testcases/expression/invalid.expression.yaml.expect
index 1ce824d..1e3cd80 100644
--- a/pkg/front_end/testcases/expression/invalid.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/invalid.expression.yaml.expect
@@ -1,4 +1,5 @@
Errors: {
+ Can't find ')' to match '('. (@4)
Expected an identifier, but got '*'. (@0)
Method not found: 'foo'. (@1)
Getter not found: ''. (@0)
diff --git a/pkg/front_end/testcases/expression/lib_nonctor.expression.yaml b/pkg/front_end/testcases/expression/lib_nonctor.expression.yaml
index bae7baa..637ef0c 100644
--- a/pkg/front_end/testcases/expression/lib_nonctor.expression.yaml
+++ b/pkg/front_end/testcases/expression/lib_nonctor.expression.yaml
@@ -6,4 +6,4 @@
definitions: []
position: "main.dart"
expression: |
- new Random();
+ new Random()
diff --git a/pkg/front_end/testcases/expression/main.dart b/pkg/front_end/testcases/expression/main.dart
index ba2d61d..d946d39 100644
--- a/pkg/front_end/testcases/expression/main.dart
+++ b/pkg/front_end/testcases/expression/main.dart
@@ -2,10 +2,6 @@
// 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.
-// Copyright (c) 2018, 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 main;
import 'dart:io' show File, Process, exit;
diff --git a/pkg/front_end/testcases/expression/nolib.expression.yaml.expect b/pkg/front_end/testcases/expression/nolib.expression.yaml.expect
index ba1f145..c46c67f 100644
--- a/pkg/front_end/testcases/expression/nolib.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/nolib.expression.yaml.expect
@@ -1,3 +1,4 @@
Errors: {
}
-<no procedure>
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+ return 0;
diff --git a/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect b/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect
index 6368c6b..4802c5b 100644
--- a/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect
@@ -1,7 +1,7 @@
Errors: {
- A value of type 'main::A<dynamic>' can't be assigned to a variable of type 'main::A::debugExpr::T'. (@17)
+ A value of type 'main::A<dynamic>' can't be assigned to a variable of type 'T'. (@17)
}
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<T extends dynamic>() → dynamic
return () → dart.core::Null {
- main::A::debugExpr::T k = let final dynamic #t1 = new main::A::•<dynamic>() in let dynamic _ = null in invalid-expression "Error: A value of type 'main::A<dynamic>' can't be assigned to a variable of type 'main::A::debugExpr::T'.\nTry changing the type of the left hand side, or casting the right hand side to 'main::A::debugExpr::T'.";
+ main::A::debugExpr::T k = let final dynamic #t1 = let dynamic _ = null in invalid-expression "org-dartlang-debug:synthetic_debug_expression:2:13: Error: A value of type 'main::A<dynamic>' can't be assigned to a variable of type 'T'.\nTry changing the type of the left hand side, or casting the right hand side to 'T'.\n T k = new A();\n ^" in let final dynamic #t2 = new main::A::•<dynamic>() in null;
};
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index ef4c8ef..329b554 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -32,7 +32,7 @@
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
import 'package:front_end/src/fasta/kernel/utils.dart';
-import 'package:front_end/src/testing/hybrid_file_system.dart';
+import 'package:front_end/src/fasta/hybrid_file_system.dart';
import 'package:kernel/kernel.dart' show Component;
import 'package:kernel/target/targets.dart' show TargetFlags;
import 'package:kernel/target/vm.dart' show VmTarget;