Prepare for improved error recovery from compile-time errors.

R=paulberry@google.com

Review-Url: https://codereview.chromium.org/2931423002 .
This commit is contained in:
Peter von der Ahé 2017-06-13 15:59:17 +02:00
parent d920dacad8
commit 14e9d0bd89
7 changed files with 85 additions and 13 deletions

View file

@ -877,16 +877,21 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
message = "Method not found: '$errorName'.";
}
if (constantExpressionRequired) {
// TODO(ahe): Use error below instead of building a compile-time error,
// should be:
// return library.loader.throwCompileConstantError(error, charOffset);
return buildCompileTimeError(message, charOffset);
} else {
Expression error = library.loader.instantiateNoSuchMethodError(
receiver, name, arguments, charOffset,
isMethod: !isGetter && !isSetter,
isGetter: isGetter,
isSetter: isSetter,
isStatic: isStatic,
isTopLevel: !isStatic && !isSuper);
warning(message, charOffset);
return new Throw(error);
}
warning(message, charOffset);
return new Throw(library.loader.instantiateNoSuchMethodError(
receiver, name, arguments, charOffset,
isMethod: !isGetter && !isSetter,
isGetter: isGetter,
isSetter: isSetter,
isStatic: isStatic,
isTopLevel: !isStatic && !isSuper));
}
@override
@ -2883,11 +2888,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
// extracted. Similar for statements and initializers. See also [issue
// 29717](https://github.com/dart-lang/sdk/issues/29717)
addCompileTimeError(charOffset, error);
String message = formatUnexpected(uri, charOffset, error);
Builder constructor = library.loader.getCompileTimeError();
return new Throw(buildStaticInvocation(constructor.target,
new KernelArguments(<Expression>[new StringLiteral(message)]),
charOffset: charOffset));
return library.loader.throwCompileConstantError(library.loader
.buildCompileTimeError(
formatUnexpected(uri, charOffset, error), charOffset));
}
Expression wrapInCompileTimeError(Expression expression, String message) {

View file

@ -517,4 +517,13 @@ class SourceLoader<L> extends Loader<L> {
isConstructor: isConstructor,
isTopLevel: isTopLevel);
}
Expression throwCompileConstantError(Expression error) {
return target.backendTarget.throwCompileConstantError(coreTypes, error);
}
Expression buildCompileTimeError(String message, int offset) {
return target.backendTarget
.buildCompileTimeError(coreTypes, message, offset);
}
}

View file

@ -61,6 +61,8 @@ class CoreTypes {
Procedure _listFromConstructor;
Procedure _printProcedure;
Procedure _identicalProcedure;
Constructor _constantExpressionErrorDefaultConstructor;
Constructor _compileTimeErrorDefaultConstructor;
Class _internalSymbolClass;
@ -255,4 +257,14 @@ class CoreTypes {
Class get typeClass {
return _typeClass ??= _index.getClass('dart:core', 'Type');
}
Constructor get constantExpressionErrorDefaultConstructor {
return _constantExpressionErrorDefaultConstructor ??=
_index.getMember('dart:core', '_ConstantExpressionError', '');
}
Constructor get compileTimeErrorDefaultConstructor {
return _compileTimeErrorDefaultConstructor ??=
_index.getMember('dart:core', '_CompileTimeError', '');
}
}

View file

@ -130,6 +130,34 @@ abstract class Target {
bool isConstructor: false,
bool isTopLevel: false});
/// Builds an expression that throws [error] as compile-time error. The
/// target must be able to handle this expression in a constant expression.
Expression throwCompileConstantError(CoreTypes coreTypes, Expression error) {
// This method returns `const _ConstantExpressionError()._throw(error)`.
int offset = error.fileOffset;
var receiver = new ConstructorInvocation(
coreTypes.constantExpressionErrorDefaultConstructor,
new Arguments.empty()..fileOffset = offset,
isConst: true)
..fileOffset = offset;
return new MethodInvocation(
receiver,
new Name("_throw", coreTypes.coreLibrary),
new Arguments(<Expression>[error])..fileOffset = error.fileOffset)
..fileOffset = offset;
}
/// Builds an expression that represents a compile-time error which is
/// suitable for being passed to [throwCompileConstantError].
Expression buildCompileTimeError(
CoreTypes coreTypes, String message, int offset) {
return new ConstructorInvocation(
coreTypes.compileTimeErrorDefaultConstructor,
new Arguments(<Expression>[new StringLiteral(message)])
..fileOffset = offset)
..fileOffset = offset;
}
String toString() => 'Target($name)';
}

View file

@ -430,3 +430,9 @@ class _DuplicatedFieldInitializerError extends Error {
toString() => "Error: field '$_name' is already initialized.";
}
@patch
class _ConstantExpressionError {
@patch
_throw(error) => throw error;
}

View file

@ -746,3 +746,9 @@ _unresolvedTopLevelMethodError(receiver, memberName, positionalArguments,
return new NoSuchMethodError(
receiver, memberName, positionalArguments, namedArguments);
}
@patch
class _ConstantExpressionError {
@patch
_throw(error) => throw error;
}

View file

@ -557,3 +557,11 @@ class CyclicInitializationError extends Error {
? "Reading static variable during its initialization"
: "Reading static variable '$variableName' during its initialization";
}
/// Used by Fasta to throw a compile-time error in a way that is compatible
/// with compile-time constant evaluation.
class _ConstantExpressionError {
const _ConstantExpressionError();
external _throw(error);
}