Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Unified Diff: pkg/compiler/lib/src/kernel/element_map.dart

Issue 2858223004: Rename KernelElementAdapter and element_adapter.dart to IrToElementMap and ir_map.dart (Closed)
Patch Set: Updated cf. comments. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/kernel/element_adapter.dart ('k') | pkg/compiler/lib/src/kernel/element_map_impl.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/kernel/element_map.dart
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index e2ae7c741fde6414d3f1967f441bb4f4988b7836..dcdb92bc009224cbc3eaf29b51f76cdf5c877938 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -2,1310 +2,787 @@
// 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 dart2js.kernel.element_map;
-
import 'package:kernel/ast.dart' as ir;
import '../common.dart';
-import '../common/names.dart' show Identifiers;
-import '../common/resolution.dart';
-import '../compile_time_constants.dart';
-import '../constants/constant_system.dart';
+import '../common/names.dart';
import '../constants/constructors.dart';
-import '../constants/evaluation.dart';
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../common_elements.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
+import '../elements/operators.dart';
import '../elements/types.dart';
-import '../environment.dart';
-import '../frontend_strategy.dart';
-import '../js_backend/constant_system_javascript.dart';
-import '../js_backend/native_data.dart';
-import '../js_backend/no_such_method_registry.dart';
+import '../js_backend/backend.dart' show JavaScriptBackend;
import '../native/native.dart' as native;
-import '../native/resolver.dart';
-import '../ordered_typeset.dart';
-import '../ssa/kernel_impact.dart';
import '../universe/call_structure.dart';
-import '../universe/world_builder.dart';
-import '../util/util.dart' show Link, LinkBuilder;
-import 'element_adapter.dart';
-import 'elements.dart';
-
-part 'native_basic_data.dart';
-part 'no_such_method_resolver.dart';
-part 'types.dart';
-
-/// Element builder used for creating elements and types corresponding to Kernel
-/// IR nodes.
-class KernelToElementMap extends KernelElementAdapterMixin {
- final Environment _environment;
- CommonElements _commonElements;
- native.BehaviorBuilder _nativeBehaviorBuilder;
- final DiagnosticReporter reporter;
- ElementEnvironment _elementEnvironment;
- DartTypeConverter _typeConverter;
- KernelConstantEnvironment _constantEnvironment;
- _KernelDartTypes _types;
-
- /// Library environment. Used for fast lookup.
- _KEnv _env = new _KEnv();
-
- /// List of library environments by `KLibrary.libraryIndex`. This is used for
- /// fast lookup into library classes and members.
- List<_KLibraryEnv> _libraryEnvs = <_KLibraryEnv>[];
-
- /// List of class environments by `KClass.classIndex`. This is used for
- /// fast lookup into class members.
- List<_KClassEnv> _classEnvs = <_KClassEnv>[];
-
- Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{};
- Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{};
- Map<ir.TypeParameter, KTypeVariable> _typeVariableMap =
- <ir.TypeParameter, KTypeVariable>{};
-
- List<_MemberData> _memberList = <_MemberData>[];
-
- Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{};
- Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{};
- Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{};
-
- Map<ir.TreeNode, KLocalFunction> _localFunctionMap =
- <ir.TreeNode, KLocalFunction>{};
-
- KernelToElementMap(this.reporter, this._environment) {
- _elementEnvironment = new KernelElementEnvironment(this);
- _commonElements = new CommonElements(_elementEnvironment);
- _constantEnvironment = new KernelConstantEnvironment(this);
- _nativeBehaviorBuilder = new KernelBehaviorBuilder(_commonElements);
- _types = new _KernelDartTypes(this);
- _typeConverter = new DartTypeConverter(this);
- }
+import '../universe/selector.dart';
+import 'kernel_debug.dart';
- /// Adds libraries in [program] to the set of libraries.
- ///
- /// The main method of the first program is used as the main method for the
- /// compilation.
- void addProgram(ir.Program program) {
- _env.addProgram(program);
- }
+/// Interface that translates between Kernel IR nodes and entities.
+abstract class KernelToElementMap {
+ /// Access to the commonly used elements and types.
+ CommonElements get commonElements;
- KMethod get _mainFunction {
- return _env.mainMethod != null ? _getMethod(_env.mainMethod) : null;
- }
+ /// [ElementEnvironment] for library, class and member lookup.
+ ElementEnvironment get elementEnvironment;
- KLibrary get _mainLibrary {
- return _env.mainMethod != null
- ? _getLibrary(_env.mainMethod.enclosingLibrary)
- : null;
- }
+ /// Returns the [DartType] corresponding to [type].
+ DartType getDartType(ir.DartType type);
- Iterable<LibraryEntity> get _libraries {
- if (_env.length != _libraryMap.length) {
- // Create a [KLibrary] for each library.
- _env.forEachLibrary((_KLibraryEnv env) {
- _getLibrary(env.library, env);
- });
- }
- return _libraryMap.values;
- }
+ /// Returns the list of [DartType]s corresponding to [types].
+ List<DartType> getDartTypes(List<ir.DartType> types);
- @override
- CommonElements get commonElements => _commonElements;
+ /// Returns the [InterfaceType] corresponding to [type].
+ InterfaceType getInterfaceType(ir.InterfaceType type);
- @override
- ElementEnvironment get elementEnvironment => _elementEnvironment;
+ /// Return the [InterfaceType] corresponding to the [cls] with the given
+ /// [typeArguments].
+ InterfaceType createInterfaceType(
+ ir.Class cls, List<ir.DartType> typeArguments);
- ConstantEnvironment get constantEnvironment => _constantEnvironment;
+ /// Returns the [CallStructure] corresponding to the [arguments].
+ CallStructure getCallStructure(ir.Arguments arguments);
- DartTypes get types => _types;
+ /// Returns the [Selector] corresponding to the invocation or getter/setter
+ /// access of [node].
+ Selector getSelector(ir.Expression node);
- @override
- native.BehaviorBuilder get nativeBehaviorBuilder => _nativeBehaviorBuilder;
+ /// Returns the [ConstructorEntity] corresponding to the generative or factory
+ /// constructor [node].
+ ConstructorEntity getConstructor(ir.Member node);
- @override
- ConstantValue computeConstantValue(ConstantExpression constant) {
- return _constantEnvironment.getConstantValue(constant);
- }
+ /// Returns the [MemberEntity] corresponding to the member [node].
+ MemberEntity getMember(ir.Member node);
- LibraryEntity lookupLibrary(Uri uri) {
- _KLibraryEnv libraryEnv = _env.lookupLibrary(uri);
- if (libraryEnv == null) return null;
- return _getLibrary(libraryEnv.library, libraryEnv);
- }
+ /// Returns the [FunctionEntity] corresponding to the procedure [node].
+ FunctionEntity getMethod(ir.Procedure node);
- KLibrary _getLibrary(ir.Library node, [_KLibraryEnv libraryEnv]) {
- return _libraryMap.putIfAbsent(node, () {
- Uri canonicalUri = node.importUri;
- _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(canonicalUri));
- String name = node.name;
- if (name == null) {
- // Use the file name as script name.
- String path = canonicalUri.path;
- name = path.substring(path.lastIndexOf('/') + 1);
- }
- return new KLibrary(_libraryMap.length, name, canonicalUri);
- });
- }
+ /// Returns the [FieldEntity] corresponding to the field [node].
+ FieldEntity getField(ir.Field node);
- MemberEntity lookupLibraryMember(KLibrary library, String name,
- {bool setter: false}) {
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex];
- ir.Member member = libraryEnv.lookupMember(name, setter: setter);
- return member != null ? getMember(member) : null;
- }
+ /// Returns the [ClassEntity] corresponding to the class [node].
+ ClassEntity getClass(ir.Class node);
- ClassEntity lookupClass(KLibrary library, String name) {
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex];
- _KClassEnv classEnv = libraryEnv.lookupClass(name);
- if (classEnv != null) {
- return _getClass(classEnv.cls, classEnv);
- }
- return null;
- }
+ /// Returns the [Local] corresponding to the [node]. The node must be either
+ /// a [ir.FunctionDeclaration] or [ir.FunctionExpression].
+ Local getLocalFunction(ir.TreeNode node);
- void _forEachClass(KLibrary library, void f(ClassEntity cls)) {
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex];
- libraryEnv.forEachClass((_KClassEnv classEnv) {
- if (!classEnv.isUnnamedMixinApplication) {
- f(_getClass(classEnv.cls, classEnv));
- }
- });
- }
+ /// Returns the [LibraryEntity] corresponding to the library [node].
+ LibraryEntity getLibrary(ir.Library node);
- MemberEntity lookupClassMember(KClass cls, String name,
- {bool setter: false}) {
- _KClassEnv classEnv = _classEnvs[cls.classIndex];
- ir.Member member = classEnv.lookupMember(name, setter: setter);
- return member != null ? getMember(member) : null;
- }
+ /// Returns the [Name] corresponding to [name].
+ Name getName(ir.Name name);
- ConstructorEntity lookupConstructor(KClass cls, String name) {
- _KClassEnv classEnv = _classEnvs[cls.classIndex];
- ir.Member member = classEnv.lookupConstructor(name);
- return member != null ? getConstructor(member) : null;
- }
+ /// Returns `true` is [node] has a `@Native(...)` annotation.
+ bool isNativeClass(ir.Class node);
- KClass _getClass(ir.Class node, [_KClassEnv classEnv]) {
- return _classMap.putIfAbsent(node, () {
- KLibrary library = _getLibrary(node.enclosingLibrary);
- if (classEnv == null) {
- classEnv = _libraryEnvs[library.libraryIndex].lookupClass(node.name);
- }
- _classEnvs.add(classEnv);
- return new KClass(library, _classMap.length, node.name,
- isAbstract: node.isAbstract);
- });
- }
+ /// Return `true` if [node] is the `dart:_foreign_helper` library.
+ bool isForeignLibrary(ir.Library node);
- Iterable<ConstantValue> _getClassMetadata(KClass cls) {
- return _classEnvs[cls.classIndex].getMetadata(this);
- }
+ /// Computes the native behavior for reading the native [field].
+ native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field);
- KTypeVariable _getTypeVariable(ir.TypeParameter node) {
- return _typeVariableMap.putIfAbsent(node, () {
- if (node.parent is ir.Class) {
- ir.Class cls = node.parent;
- int index = cls.typeParameters.indexOf(node);
- return new KTypeVariable(_getClass(cls), node.name, index);
- }
- if (node.parent is ir.FunctionNode) {
- ir.FunctionNode func = node.parent;
- int index = func.typeParameters.indexOf(node);
- if (func.parent is ir.Constructor) {
- ir.Constructor constructor = func.parent;
- ir.Class cls = constructor.enclosingClass;
- return _getTypeVariable(cls.typeParameters[index]);
- }
- if (func.parent is ir.Procedure) {
- ir.Procedure procedure = func.parent;
- if (procedure.kind == ir.ProcedureKind.Factory) {
- ir.Class cls = procedure.enclosingClass;
- return _getTypeVariable(cls.typeParameters[index]);
- } else {
- return new KTypeVariable(_getMethod(procedure), node.name, index);
- }
- }
- }
- throw new UnsupportedError('Unsupported type parameter type node $node.');
- });
- }
+ /// Computes the native behavior for writing to the native [field].
+ native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field);
- ParameterStructure _getParameterStructure(ir.FunctionNode node) {
- // TODO(johnniwinther): Cache the computed function type.
- int requiredParameters = node.requiredParameterCount;
- int positionalParameters = node.positionalParameters.length;
- List<String> namedParameters =
- node.namedParameters.map((p) => p.name).toList()..sort();
- return new ParameterStructure(
- requiredParameters, positionalParameters, namedParameters);
- }
+ /// Computes the native behavior for calling [procedure].
+ native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure);
- KConstructor _getConstructor(ir.Member node) {
- return _constructorMap.putIfAbsent(node, () {
- int memberIndex = _memberList.length;
- KConstructor constructor;
- KClass enclosingClass = _getClass(node.enclosingClass);
- Name name = getName(node.name);
- bool isExternal = node.isExternal;
-
- ir.FunctionNode functionNode;
- if (node is ir.Constructor) {
- functionNode = node.function;
- constructor = new KGenerativeConstructor(memberIndex, enclosingClass,
- name, _getParameterStructure(functionNode),
- isExternal: isExternal, isConst: node.isConst);
- } else if (node is ir.Procedure) {
- functionNode = node.function;
- constructor = new KFactoryConstructor(memberIndex, enclosingClass, name,
- _getParameterStructure(functionNode),
- isExternal: isExternal, isConst: node.isConst);
- } else {
- // TODO(johnniwinther): Convert `node.location` to a [SourceSpan].
- throw new SpannableAssertionFailure(
- NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}.");
- }
- _memberList.add(new _ConstructorData(node, functionNode));
- return constructor;
- });
- }
+ /// Computes the [native.NativeBehavior] for a call to the [JS] function.
+ native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
- KFunction _getMethod(ir.Procedure node) {
- return _methodMap.putIfAbsent(node, () {
- int memberIndex = _memberList.length;
- KLibrary library;
- KClass enclosingClass;
- if (node.enclosingClass != null) {
- enclosingClass = _getClass(node.enclosingClass);
- library = enclosingClass.library;
- } else {
- library = _getLibrary(node.enclosingLibrary);
- }
- Name name = getName(node.name);
- bool isStatic = node.isStatic;
- bool isExternal = node.isExternal;
- bool isAbstract = node.isAbstract;
- KFunction function;
- switch (node.kind) {
- case ir.ProcedureKind.Factory:
- throw new UnsupportedError("Cannot create method from factory.");
- case ir.ProcedureKind.Getter:
- function = new KGetter(memberIndex, library, enclosingClass, name,
- isStatic: isStatic,
- isExternal: isExternal,
- isAbstract: isAbstract);
- break;
- case ir.ProcedureKind.Method:
- case ir.ProcedureKind.Operator:
- function = new KMethod(memberIndex, library, enclosingClass, name,
- _getParameterStructure(node.function),
- isStatic: isStatic,
- isExternal: isExternal,
- isAbstract: isAbstract);
- break;
- case ir.ProcedureKind.Setter:
- function = new KSetter(
- memberIndex, library, enclosingClass, getName(node.name).setter,
- isStatic: isStatic,
- isExternal: isExternal,
- isAbstract: isAbstract);
- break;
- }
- _memberList.add(new _FunctionData(node, node.function));
- return function;
- });
- }
+ /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
+ /// function.
+ native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
+ ir.StaticInvocation node);
- /// Returns the kernel [ir.Procedure] node for the [method].
- ir.Procedure _lookupProcedure(KFunction method) {
- return _memberList[method.memberIndex].node;
- }
+ /// Computes the [native.NativeBehavior] for a call to the
+ /// [JS_EMBEDDED_GLOBAL] function.
+ native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
+ ir.StaticInvocation node);
- KField _getField(ir.Field node) {
- return _fieldMap.putIfAbsent(node, () {
- int memberIndex = _memberList.length;
- KLibrary library;
- KClass enclosingClass;
- if (node.enclosingClass != null) {
- enclosingClass = _getClass(node.enclosingClass);
- library = enclosingClass.library;
- } else {
- library = _getLibrary(node.enclosingLibrary);
- }
- Name name = getName(node.name);
- bool isStatic = node.isStatic;
- _memberList.add(new _FieldData(node));
- return new KField(memberIndex, library, enclosingClass, name,
- isStatic: isStatic,
- isAssignable: node.isMutable,
- isConst: node.isConst);
- });
- }
+ /// Compute the kind of foreign helper function called by [node], if any.
+ ForeignKind getForeignKind(ir.StaticInvocation node);
- KLocalFunction _getLocal(ir.TreeNode node) {
- return _localFunctionMap.putIfAbsent(node, () {
- MemberEntity memberContext;
- Entity executableContext;
- ir.TreeNode parent = node.parent;
- while (parent != null) {
- if (parent is ir.Member) {
- executableContext = memberContext = getMember(parent);
- break;
- }
- if (parent is ir.FunctionDeclaration ||
- parent is ir.FunctionExpression) {
- KLocalFunction localFunction = _getLocal(parent);
- executableContext = localFunction;
- memberContext = localFunction.memberContext;
- break;
- }
- parent = parent.parent;
- }
- String name;
- FunctionType functionType;
- if (node is ir.FunctionDeclaration) {
- name = node.variable.name;
- functionType = getFunctionType(node.function);
- } else if (node is ir.FunctionExpression) {
- functionType = getFunctionType(node.function);
- }
- return new KLocalFunction(
- name, memberContext, executableContext, functionType);
- });
- }
+ /// Computes the [InterfaceType] referenced by a call to the
+ /// [JS_INTERCEPTOR_CONSTANT] function, if any.
+ InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node);
- @override
- DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
+ /// Computes the [ConstantValue] for the constant [expression].
+ ConstantValue getConstantValue(ir.Expression expression);
+}
- @override
- InterfaceType createInterfaceType(
- ir.Class cls, List<ir.DartType> typeArguments) {
- return new InterfaceType(getClass(cls), getDartTypes(typeArguments));
- }
+/// Kinds of foreign functions.
+enum ForeignKind {
+ JS,
+ JS_BUILTIN,
+ JS_EMBEDDED_GLOBAL,
+ JS_INTERCEPTOR_CONSTANT,
+ NONE,
+}
- @override
- InterfaceType getInterfaceType(ir.InterfaceType type) =>
- _typeConverter.convert(type);
+abstract class KernelToElementMapMixin implements KernelToElementMap {
+ DiagnosticReporter get reporter;
+ FunctionType getFunctionType(ir.FunctionNode node);
+ native.BehaviorBuilder get nativeBehaviorBuilder;
+ ConstantValue computeConstantValue(ConstantExpression constant);
@override
- List<DartType> getDartTypes(List<ir.DartType> types) {
- // TODO(johnniwinther): Add the type argument to the list literal when we
- // no longer use resolution types.
- List<DartType> list = /*<DartType>*/ [];
- types.forEach((ir.DartType type) {
- list.add(getDartType(type));
- });
- return list;
+ Name getName(ir.Name name) {
+ return new Name(
+ name.name, name.isPrivate ? getLibrary(name.library) : null);
}
- void _ensureThisAndRawType(KClass cls, _KClassEnv env) {
- if (env.thisType == null) {
- ir.Class node = env.cls;
- // TODO(johnniwinther): Add the type argument to the list literal when we
- // no longer use resolution types.
- if (node.typeParameters.isEmpty) {
- env.thisType =
- env.rawType = new InterfaceType(cls, const/*<DartType>*/ []);
- } else {
- env.thisType = new InterfaceType(
- cls,
- new List/*<DartType>*/ .generate(node.typeParameters.length,
- (int index) {
- return new TypeVariableType(
- _getTypeVariable(node.typeParameters[index]));
- }));
- env.rawType = new InterfaceType(
- cls,
- new List/*<DartType>*/ .filled(
- node.typeParameters.length, const DynamicType()));
- }
- }
- }
-
- InterfaceType _getThisType(KClass cls) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureThisAndRawType(cls, env);
- return env.thisType;
- }
-
- InterfaceType _getRawType(KClass cls) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureThisAndRawType(cls, env);
- return env.rawType;
- }
-
- InterfaceType _asInstanceOf(InterfaceType type, KClass cls) {
- OrderedTypeSet orderedTypeSet = _getOrderedTypeSet(type.element);
- InterfaceType supertype =
- orderedTypeSet.asInstanceOf(cls, _getHierarchyDepth(cls));
- if (supertype != null) {
- supertype = _substByContext(supertype, type);
- }
- return supertype;
+ @override
+ CallStructure getCallStructure(ir.Arguments arguments) {
+ int argumentCount = arguments.positional.length + arguments.named.length;
+ List<String> namedArguments = arguments.named.map((e) => e.name).toList();
+ return new CallStructure(argumentCount, namedArguments);
}
- void _ensureSupertypes(KClass cls, _KClassEnv env) {
- if (env.orderedTypeSet == null) {
- _ensureThisAndRawType(cls, env);
-
- ir.Class node = env.cls;
-
- if (node.supertype == null) {
- env.orderedTypeSet = new OrderedTypeSet.singleton(env.thisType);
- } else {
- InterfaceType processSupertype(ir.Supertype node) {
- InterfaceType type = _typeConverter.visitSupertype(node);
- KClass superclass = type.element;
- _KClassEnv env = _classEnvs[superclass.classIndex];
- _ensureSupertypes(superclass, env);
- return type;
- }
-
- env.supertype = processSupertype(node.supertype);
- LinkBuilder<InterfaceType> linkBuilder =
- new LinkBuilder<InterfaceType>();
- if (node.mixedInType != null) {
- linkBuilder
- .addLast(env.mixedInType = processSupertype(node.mixedInType));
- }
- node.implementedTypes.forEach((ir.Supertype supertype) {
- linkBuilder.addLast(processSupertype(supertype));
- });
- Link<InterfaceType> interfaces = linkBuilder.toLink();
- OrderedTypeSetBuilder setBuilder =
- new _KernelOrderedTypeSetBuilder(this, cls);
- env.orderedTypeSet =
- setBuilder.createOrderedTypeSet(env.supertype, interfaces);
- }
+ @override
+ Selector getSelector(ir.Expression node) {
+ // TODO(efortuna): This is screaming for a common interface between
+ // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
+ // folks.
+ if (node is ir.PropertyGet) {
+ return getGetterSelector(node.name);
}
- }
-
- OrderedTypeSet _getOrderedTypeSet(KClass cls) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureSupertypes(cls, env);
- return env.orderedTypeSet;
- }
-
- int _getHierarchyDepth(KClass cls) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureSupertypes(cls, env);
- return env.orderedTypeSet.maxDepth;
- }
-
- InterfaceType _substByContext(InterfaceType type, InterfaceType context) {
- return type.subst(
- context.typeArguments, _getThisType(context.element).typeArguments);
- }
-
- InterfaceType _getSuperType(KClass cls) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureSupertypes(cls, env);
- return env.supertype;
- }
-
- bool _isUnnamedMixinApplication(KClass cls) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureSupertypes(cls, env);
- return env.isUnnamedMixinApplication;
- }
-
- void _forEachSupertype(KClass cls, void f(InterfaceType supertype)) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureSupertypes(cls, env);
- env.orderedTypeSet.supertypes.forEach(f);
- }
-
- void _forEachMixin(KClass cls, void f(ClassEntity mixin)) {
- while (cls != null) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- _ensureSupertypes(cls, env);
- if (env.mixedInType != null) {
- f(env.mixedInType.element);
- }
- cls = env.supertype?.element;
+ if (node is ir.SuperPropertyGet) {
+ return getGetterSelector(node.name);
}
- }
-
- void _forEachClassMember(
- KClass cls, void f(ClassEntity cls, MemberEntity member)) {
- _KClassEnv env = _classEnvs[cls.classIndex];
- env.forEachMember((ir.Member member) {
- f(cls, getMember(member));
- });
- _ensureSupertypes(cls, env);
- if (env.supertype != null) {
- _forEachClassMember(env.supertype.element, f);
+ if (node is ir.PropertySet) {
+ return getSetterSelector(node.name);
}
- }
-
- @override
- FunctionType getFunctionType(ir.FunctionNode node) {
- DartType returnType = getDartType(node.returnType);
- List<DartType> parameterTypes = /*<DartType>*/ [];
- List<DartType> optionalParameterTypes = /*<DartType>*/ [];
- for (ir.VariableDeclaration variable in node.positionalParameters) {
- if (parameterTypes.length == node.requiredParameterCount) {
- optionalParameterTypes.add(getDartType(variable.type));
- } else {
- parameterTypes.add(getDartType(variable.type));
- }
+ if (node is ir.SuperPropertySet) {
+ return getSetterSelector(node.name);
}
- List<String> namedParameters = <String>[];
- List<DartType> namedParameterTypes = /*<DartType>*/ [];
- List<ir.VariableDeclaration> sortedNamedParameters =
- node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name));
- for (ir.VariableDeclaration variable in sortedNamedParameters) {
- namedParameters.add(variable.name);
- namedParameterTypes.add(getDartType(variable.type));
+ if (node is ir.InvocationExpression) {
+ return getInvocationSelector(node);
}
- return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
- namedParameters, namedParameterTypes);
- }
-
- LibraryEntity getLibrary(ir.Library node) => _getLibrary(node);
-
- ir.Library getKernelLibrary(KLibrary entity) =>
- _libraryEnvs[entity.libraryIndex].library;
-
- ir.Class getKernelClass(KClass entity) => _classEnvs[entity.classIndex].cls;
-
- @override
- Local getLocalFunction(ir.TreeNode node) => _getLocal(node);
-
- @override
- ClassEntity getClass(ir.Class node) => _getClass(node);
-
- @override
- FieldEntity getField(ir.Field node) => _getField(node);
-
- TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
- _getTypeVariable(node);
-
- @override
- FunctionEntity getMethod(ir.Procedure node) => _getMethod(node);
-
- @override
- MemberEntity getMember(ir.Member node) {
- if (node is ir.Field) {
- return _getField(node);
- } else if (node is ir.Constructor) {
- return _getConstructor(node);
- } else if (node is ir.Procedure) {
- if (node.kind == ir.ProcedureKind.Factory) {
- return _getConstructor(node);
+ throw new SpannableAssertionFailure(
+ CURRENT_ELEMENT_SPANNABLE,
+ "Can only get the selector for a property get or an invocation: "
+ "${node}");
+ }
+
+ Selector getInvocationSelector(ir.InvocationExpression invocation) {
+ Name name = getName(invocation.name);
+ SelectorKind kind;
+ if (Elements.isOperatorName(invocation.name.name)) {
+ if (name == Names.INDEX_NAME || name == Names.INDEX_SET_NAME) {
+ kind = SelectorKind.INDEX;
} else {
- return _getMethod(node);
+ kind = SelectorKind.OPERATOR;
}
+ } else {
+ kind = SelectorKind.CALL;
}
- throw new UnsupportedError("Unexpected member: $node");
- }
-
- @override
- FunctionEntity getConstructor(ir.Member node) => _getConstructor(node);
- ConstantConstructor _getConstructorConstant(KConstructor constructor) {
- _ConstructorData data = _memberList[constructor.memberIndex];
- return data.getConstructorConstant(this, constructor);
+ CallStructure callStructure = getCallStructure(invocation.arguments);
+ return new Selector(kind, name, callStructure);
}
- ConstantExpression _getFieldConstant(KField field) {
- _FieldData data = _memberList[field.memberIndex];
- return data.getFieldConstant(this, field);
+ Selector getGetterSelector(ir.Name irName) {
+ Name name = new Name(
+ irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
+ return new Selector.getter(name);
}
- FunctionType _getFunctionType(KFunction function) {
- _FunctionData data = _memberList[function.memberIndex];
- return data.getFunctionType(this);
+ Selector getSetterSelector(ir.Name irName) {
+ Name name = new Name(
+ irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
+ return new Selector.setter(name);
}
- ResolutionImpact computeWorldImpact(KMember member) {
- return _memberList[member.memberIndex].getWorldImpact(this);
- }
-}
-
-/// Environment for fast lookup of program libraries.
-class _KEnv {
- final Set<ir.Program> programs = new Set<ir.Program>();
-
- Map<Uri, _KLibraryEnv> _libraryMap;
-
- /// TODO(johnniwinther): Handle arbitrary load order if needed.
- ir.Member get mainMethod => programs.first?.mainMethod;
-
- void addProgram(ir.Program program) {
- if (programs.add(program)) {
- if (_libraryMap != null) {
- _addLibraries(program);
- }
+ ConstantValue getConstantValue(ir.Expression node) {
+ ConstantExpression constant = new Constantifier(this).visit(node);
+ if (constant == null) {
+ throw new UnsupportedError(
+ 'No constant for ${DebugPrinter.prettyPrint(node)}');
}
+ return computeConstantValue(constant);
}
- void _addLibraries(ir.Program program) {
- for (ir.Library library in program.libraries) {
- _libraryMap[library.importUri] = new _KLibraryEnv(library);
- }
- }
-
- void _ensureLibraryMap() {
- if (_libraryMap == null) {
- _libraryMap = <Uri, _KLibraryEnv>{};
- for (ir.Program program in programs) {
- _addLibraries(program);
- }
- }
- }
-
- /// Return the [_KLibraryEnv] for the library with the canonical [uri].
- _KLibraryEnv lookupLibrary(Uri uri) {
- _ensureLibraryMap();
- return _libraryMap[uri];
- }
-
- /// Calls [f] for each library in this environment.
- void forEachLibrary(void f(_KLibraryEnv library)) {
- _ensureLibraryMap();
- _libraryMap.values.forEach(f);
- }
-
- /// Returns the number of libraries in this environment.
- int get length {
- _ensureLibraryMap();
- return _libraryMap.length;
+ /// Converts [annotations] into a list of [ConstantValue]s.
+ List<ConstantValue> getMetadata(List<ir.Expression> annotations) {
+ if (annotations.isEmpty) return const <ConstantValue>[];
+ List<ConstantValue> metadata = <ConstantValue>[];
+ annotations.forEach((ir.Expression node) {
+ metadata.add(getConstantValue(node));
+ });
+ return metadata;
}
-}
-
-/// Environment for fast lookup of library classes and members.
-class _KLibraryEnv {
- final ir.Library library;
- Map<String, _KClassEnv> _classMap;
- Map<String, ir.Member> _memberMap;
- Map<String, ir.Member> _setterMap;
-
- _KLibraryEnv(this.library);
-
- void _ensureClassMap() {
- if (_classMap == null) {
- _classMap = <String, _KClassEnv>{};
- for (ir.Class cls in library.classes) {
- _classMap[cls.name] = new _KClassEnv(cls);
+ /// Returns `true` is [node] has a `@Native(...)` annotation.
+ // TODO(johnniwinther): Cache this for later use.
+ bool isNativeClass(ir.Class node) {
+ for (ir.Expression annotation in node.annotations) {
+ if (annotation is ir.ConstructorInvocation) {
+ FunctionEntity target = getConstructor(annotation.target);
+ if (target.enclosingClass == commonElements.nativeAnnotationClass) {
+ return true;
+ }
}
}
+ return false;
}
- /// Return the [_KClassEnv] for the class [name] in [library].
- _KClassEnv lookupClass(String name) {
- _ensureClassMap();
- return _classMap[name];
- }
-
- /// Calls [f] for each class in this library.
- void forEachClass(void f(_KClassEnv cls)) {
- _ensureClassMap();
- _classMap.values.forEach(f);
- }
-
- /// Return the [ir.Member] for the member [name] in [library].
- ir.Member lookupMember(String name, {bool setter: false}) {
- if (_memberMap == null) {
- _memberMap = <String, ir.Member>{};
- _setterMap = <String, ir.Member>{};
- for (ir.Member member in library.members) {
- if (member is ir.Procedure) {
- if (member.kind == ir.ProcedureKind.Setter) {
- _setterMap[member.name.name] = member;
- } else {
- _memberMap[member.name.name] = member;
- }
- } else if (member is ir.Field) {
- _memberMap[member.name.name] = member;
- if (member.isMutable) {
- _setterMap[member.name.name] = member;
- }
- } else {
- throw new SpannableAssertionFailure(
- NO_LOCATION_SPANNABLE, "Unexpected library member node: $member");
- }
+ /// Compute the kind of foreign helper function called by [node], if any.
+ ForeignKind getForeignKind(ir.StaticInvocation node) {
+ if (isForeignLibrary(node.target.enclosingLibrary)) {
+ switch (node.target.name.name) {
+ case JavaScriptBackend.JS:
+ return ForeignKind.JS;
+ case JavaScriptBackend.JS_BUILTIN:
+ return ForeignKind.JS_BUILTIN;
+ case JavaScriptBackend.JS_EMBEDDED_GLOBAL:
+ return ForeignKind.JS_EMBEDDED_GLOBAL;
+ case JavaScriptBackend.JS_INTERCEPTOR_CONSTANT:
+ return ForeignKind.JS_INTERCEPTOR_CONSTANT;
}
}
- return _memberMap[name];
- }
-}
-
-/// Environment for fast lookup of class members.
-class _KClassEnv {
- final ir.Class cls;
- final bool isUnnamedMixinApplication;
-
- InterfaceType thisType;
- InterfaceType rawType;
- InterfaceType supertype;
- InterfaceType mixedInType;
- OrderedTypeSet orderedTypeSet;
-
- Map<String, ir.Member> _constructorMap;
- Map<String, ir.Member> _memberMap;
- Map<String, ir.Member> _setterMap;
-
- Iterable<ConstantValue> _metadata;
-
- _KClassEnv(this.cls)
- // TODO(johnniwinther): Change this to use a property on [cls] when such
- // is added to kernel.
- : isUnnamedMixinApplication = cls.name.contains('+');
-
- void _ensureMaps() {
- if (_memberMap == null) {
- _memberMap = <String, ir.Member>{};
- _setterMap = <String, ir.Member>{};
- _constructorMap = <String, ir.Member>{};
-
- void addMembers(ir.Class c) {
- for (ir.Member member in c.members) {
- if (member is ir.Constructor ||
- member is ir.Procedure &&
- member.kind == ir.ProcedureKind.Factory) {
- _constructorMap[member.name.name] = member;
- } else if (member is ir.Procedure) {
- if (member.kind == ir.ProcedureKind.Setter) {
- _setterMap[member.name.name] = member;
- } else {
- _memberMap[member.name.name] = member;
- }
- } else if (member is ir.Field) {
- _memberMap[member.name.name] = member;
- if (member.isMutable) {
- _setterMap[member.name.name] = member;
- }
- _memberMap[member.name.name] = member;
- } else {
- throw new SpannableAssertionFailure(
- NO_LOCATION_SPANNABLE, "Unexpected class member node: $member");
+ return ForeignKind.NONE;
+ }
+
+ /// Return `true` if [node] is the `dart:_foreign_helper` library.
+ bool isForeignLibrary(ir.Library node) {
+ return node.importUri == Uris.dart__foreign_helper;
+ }
+
+ /// Looks up [typeName] for use in the spec-string of a `JS` called.
+ // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
+ // the `ForeignResolver`.
+ // TODO(johnniwinther): Cache the result to avoid redundant lookups?
+ native.TypeLookup typeLookup({bool resolveAsRaw: true}) {
+ DartType lookup(String typeName, {bool required}) {
+ DartType findIn(Uri uri) {
+ LibraryEntity library = elementEnvironment.lookupLibrary(uri);
+ if (library != null) {
+ ClassEntity cls = elementEnvironment.lookupClass(library, typeName);
+ if (cls != null) {
+ // TODO(johnniwinther): Align semantics.
+ return resolveAsRaw
+ ? elementEnvironment.getRawType(cls)
+ : elementEnvironment.getThisType(cls);
}
}
+ return null;
}
- if (cls.mixedInClass != null) {
- addMembers(cls.mixedInClass);
+ // TODO(johnniwinther): Narrow the set of lookups base on the depending
+ // library.
+ DartType type = findIn(Uris.dart_core);
+ type ??= findIn(Uris.dart__js_helper);
+ type ??= findIn(Uris.dart__interceptors);
+ type ??= findIn(Uris.dart__isolate_helper);
+ type ??= findIn(Uris.dart__native_typed_data);
+ type ??= findIn(Uris.dart_collection);
+ type ??= findIn(Uris.dart_math);
+ type ??= findIn(Uris.dart_html);
+ type ??= findIn(Uris.dart_html_common);
+ type ??= findIn(Uris.dart_svg);
+ type ??= findIn(Uris.dart_web_audio);
+ type ??= findIn(Uris.dart_web_gl);
+ type ??= findIn(Uris.dart_web_sql);
+ type ??= findIn(Uris.dart_indexed_db);
+ type ??= findIn(Uris.dart_typed_data);
+ if (type == null && required) {
+ reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
+ MessageKind.GENERIC, {'text': "Type '$typeName' not found."});
}
- addMembers(cls);
+ return type;
}
- }
- /// Return the [ir.Member] for the member [name] in [library].
- ir.Member lookupMember(String name, {bool setter: false}) {
- _ensureMaps();
- return setter ? _setterMap[name] : _memberMap[name];
+ return lookup;
}
- /// Return the [ir.Member] for the member [name] in [library].
- ir.Member lookupConstructor(String name) {
- _ensureMaps();
- return _constructorMap[name];
+ String _getStringArgument(ir.StaticInvocation node, int index) {
+ return node.arguments.positional[index].accept(new Stringifier());
}
- void forEachMember(f(ir.Member member)) {
- _ensureMaps();
- _memberMap.values.forEach(f);
- for (ir.Member member in _setterMap.values) {
- if (member is ir.Procedure) {
- f(member);
- } else {
- // Skip fields; these are also in _memberMap.
- }
+ /// Computes the [native.NativeBehavior] for a call to the [JS] function.
+ // TODO(johnniwinther): Cache this for later use.
+ native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
+ if (node.arguments.positional.length < 2 ||
+ node.arguments.named.isNotEmpty) {
+ reporter.reportErrorMessage(
+ CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS);
+ return new native.NativeBehavior();
+ }
+ String specString = _getStringArgument(node, 0);
+ if (specString == null) {
+ reporter.reportErrorMessage(
+ CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
+ return new native.NativeBehavior();
}
- }
-
- Iterable<ConstantValue> getMetadata(KernelToElementMap elementMap) {
- return _metadata ??= elementMap.getMetadata(cls.annotations);
- }
-}
-
-class _MemberData {
- final ir.Member node;
- Iterable<ConstantValue> _metadata;
- _MemberData(this.node);
+ String codeString = _getStringArgument(node, 1);
+ if (codeString == null) {
+ reporter.reportErrorMessage(
+ CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
+ return new native.NativeBehavior();
+ }
- ResolutionImpact getWorldImpact(KernelToElementMap elementMap) {
- return buildKernelImpact(node, elementMap);
+ return native.NativeBehavior.ofJsCall(
+ specString,
+ codeString,
+ typeLookup(resolveAsRaw: true),
+ CURRENT_ELEMENT_SPANNABLE,
+ reporter,
+ commonElements);
+ }
+
+ /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
+ /// function.
+ // TODO(johnniwinther): Cache this for later use.
+ native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
+ ir.StaticInvocation node) {
+ if (node.arguments.positional.length < 1) {
+ reporter.internalError(
+ CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
+ return new native.NativeBehavior();
+ }
+ if (node.arguments.positional.length < 2) {
+ reporter.internalError(
+ CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name.");
+ return new native.NativeBehavior();
+ }
+ String specString = _getStringArgument(node, 0);
+ if (specString == null) {
+ reporter.internalError(
+ CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
+ return new native.NativeBehavior();
+ }
+ return native.NativeBehavior.ofJsBuiltinCall(
+ specString,
+ typeLookup(resolveAsRaw: true),
+ CURRENT_ELEMENT_SPANNABLE,
+ reporter,
+ commonElements);
+ }
+
+ /// Computes the [native.NativeBehavior] for a call to the
+ /// [JS_EMBEDDED_GLOBAL] function.
+ // TODO(johnniwinther): Cache this for later use.
+ native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
+ ir.StaticInvocation node) {
+ if (node.arguments.positional.length < 1) {
+ reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+ "JS embedded global expression has no type.");
+ return new native.NativeBehavior();
+ }
+ if (node.arguments.positional.length < 2) {
+ reporter.internalError(
+ CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name.");
+ return new native.NativeBehavior();
+ }
+ if (node.arguments.positional.length > 2 ||
+ node.arguments.named.isNotEmpty) {
+ reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+ "JS embedded global has more than 2 arguments.");
+ return new native.NativeBehavior();
+ }
+ String specString = _getStringArgument(node, 0);
+ if (specString == null) {
+ reporter.internalError(
+ CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
+ return new native.NativeBehavior();
+ }
+ return native.NativeBehavior.ofJsEmbeddedGlobalCall(
+ specString,
+ typeLookup(resolveAsRaw: true),
+ CURRENT_ELEMENT_SPANNABLE,
+ reporter,
+ commonElements);
+ }
+
+ /// Computes the [InterfaceType] referenced by a call to the
+ /// [JS_INTERCEPTOR_CONSTANT] function, if any.
+ InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) {
+ if (node.arguments.positional.length != 1 ||
+ node.arguments.named.isNotEmpty) {
+ reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
+ MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+ }
+ ir.Node argument = node.arguments.positional.first;
+ if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) {
+ return getInterfaceType(argument.type);
+ }
+ return null;
}
- Iterable<ConstantValue> getMetadata(KernelToElementMap elementMap) {
- return _metadata ??= elementMap.getMetadata(node.annotations);
+ /// Computes the native behavior for reading the native [field].
+ // TODO(johnniwinther): Cache this for later use.
+ native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) {
+ DartType type = getDartType(field.type);
+ List<ConstantValue> metadata = getMetadata(field.annotations);
+ // TODO(johnniwinther): Provide the correct value for [isJsInterop].
+ return nativeBehaviorBuilder.buildFieldLoadBehavior(
+ type, metadata, typeLookup(resolveAsRaw: false),
+ isJsInterop: false);
}
-}
-class _FunctionData extends _MemberData {
- final ir.FunctionNode functionNode;
- FunctionType _type;
- CallStructure _callStructure;
-
- _FunctionData(ir.Member node, this.functionNode) : super(node);
-
- FunctionType getFunctionType(KernelToElementMap elementMap) {
- return _type ??= elementMap.getFunctionType(functionNode);
+ /// Computes the native behavior for writing to the native [field].
+ // TODO(johnniwinther): Cache this for later use.
+ native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
+ DartType type = getDartType(field.type);
+ return nativeBehaviorBuilder.buildFieldStoreBehavior(type);
}
- CallStructure get callStructure {
- return _callStructure ??= new CallStructure(
- functionNode.positionalParameters.length +
- functionNode.namedParameters.length,
- functionNode.namedParameters.map((d) => d.name).toList());
+ /// Computes the native behavior for calling [procedure].
+ // TODO(johnniwinther): Cache this for later use.
+ native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) {
+ DartType type = getFunctionType(procedure.function);
+ List<ConstantValue> metadata = getMetadata(procedure.annotations);
+ // TODO(johnniwinther): Provide the correct value for [isJsInterop].
+ return nativeBehaviorBuilder.buildMethodBehavior(
+ type, metadata, typeLookup(resolveAsRaw: false),
+ isJsInterop: false);
}
}
-class _ConstructorData extends _FunctionData {
- ConstantConstructor _constantConstructor;
-
- _ConstructorData(ir.Member node, ir.FunctionNode functionNode)
- : super(node, functionNode);
+/// Visitor that converts string literals and concatenations of string literals
+/// into the string value.
+class Stringifier extends ir.ExpressionVisitor<String> {
+ @override
+ String visitStringLiteral(ir.StringLiteral node) => node.value;
- ConstantConstructor getConstructorConstant(
- KernelToElementMap elementMap, KConstructor constructor) {
- if (_constantConstructor == null) {
- if (node is ir.Constructor && constructor.isConst) {
- _constantConstructor =
- new Constantifier(elementMap).computeConstantConstructor(node);
- } else {
- throw new SpannableAssertionFailure(
- constructor,
- "Unexpected constructor $constructor in "
- "KernelWorldBuilder._getConstructorConstant");
- }
+ @override
+ String visitStringConcatenation(ir.StringConcatenation node) {
+ StringBuffer sb = new StringBuffer();
+ for (ir.Expression expression in node.expressions) {
+ String value = expression.accept(this);
+ if (value == null) return null;
+ sb.write(value);
}
- return _constantConstructor;
+ return sb.toString();
}
}
-class _FieldData extends _MemberData {
- ConstantExpression _constant;
+/// Visitor that converts a kernel constant expression into a
+/// [ConstantExpression].
+class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
+ final bool requireConstant;
+ final KernelToElementMapMixin elementAdapter;
- _FieldData(ir.Field node) : super(node);
+ Constantifier(this.elementAdapter, {this.requireConstant: true});
- ir.Field get node => super.node;
+ CommonElements get _commonElements => elementAdapter.commonElements;
- ConstantExpression getFieldConstant(
- KernelToElementMap elementMap, KField field) {
- if (_constant == null) {
- if (node.isConst) {
- _constant = new Constantifier(elementMap).visit(node.initializer);
- } else {
- throw new SpannableAssertionFailure(
- field,
- "Unexpected field $field in "
- "KernelWorldBuilder._getConstructorConstant");
- }
+ ConstantExpression visit(ir.Expression node) {
+ ConstantExpression constant = node.accept(this);
+ if (constant == null && requireConstant) {
+ throw new UnsupportedError(
+ "No constant computed for $node (${node.runtimeType})");
}
- return _constant;
+ return constant;
}
-}
-
-class KernelElementEnvironment implements ElementEnvironment {
- final KernelToElementMap elementMap;
-
- KernelElementEnvironment(this.elementMap);
- @override
- DartType get dynamicType => const DynamicType();
-
- @override
- LibraryEntity get mainLibrary => elementMap._mainLibrary;
-
- @override
- FunctionEntity get mainFunction => elementMap._mainFunction;
-
- @override
- Iterable<LibraryEntity> get libraries => elementMap._libraries;
-
- @override
- InterfaceType getThisType(ClassEntity cls) {
- return elementMap._getThisType(cls);
- }
-
- @override
- InterfaceType getRawType(ClassEntity cls) {
- return elementMap._getRawType(cls);
- }
-
- @override
- bool isGenericClass(ClassEntity cls) {
- return getThisType(cls).typeArguments.isNotEmpty;
- }
-
- @override
- DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
+ ConstantExpression defaultExpression(ir.Expression node) {
throw new UnimplementedError(
- 'KernelElementEnvironment.getTypeVariableBound');
- }
-
- @override
- InterfaceType createInterfaceType(
- ClassEntity cls, List<DartType> typeArguments) {
- return new InterfaceType(cls, typeArguments);
+ 'Unimplemented constant expression $node (${node.runtimeType})');
}
- @override
- bool isSubtype(DartType a, DartType b) {
- return elementMap.types.isSubtype(a, b);
- }
-
- @override
- FunctionType getFunctionType(KFunction function) {
- return elementMap._getFunctionType(function);
- }
-
- @override
- FunctionType getLocalFunctionType(KLocalFunction function) {
- return function.functionType;
- }
-
- @override
- DartType getUnaliasedType(DartType type) => type;
-
- @override
- ConstructorEntity lookupConstructor(ClassEntity cls, String name,
- {bool required: false}) {
- ConstructorEntity constructor = elementMap.lookupConstructor(cls, name);
- if (constructor == null && required) {
- throw new SpannableAssertionFailure(
- CURRENT_ELEMENT_SPANNABLE,
- "The constructor '$name' was not found in class '${cls.name}' "
- "in library ${cls.library.canonicalUri}.");
+ List<ConstantExpression> _computeList(List<ir.Expression> expressions) {
+ List<ConstantExpression> list = <ConstantExpression>[];
+ for (ir.Expression expression in expressions) {
+ ConstantExpression constant = visit(expression);
+ if (constant == null) return null;
+ list.add(constant);
}
- return constructor;
+ return list;
}
- @override
- MemberEntity lookupClassMember(ClassEntity cls, String name,
- {bool setter: false, bool required: false}) {
- MemberEntity member =
- elementMap.lookupClassMember(cls, name, setter: setter);
- if (member == null && required) {
- throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
- "The member '$name' was not found in ${cls.name}.");
+ List<ConstantExpression> _computeArguments(ir.Arguments node) {
+ List<ConstantExpression> arguments = <ConstantExpression>[];
+ for (ir.Expression argument in node.positional) {
+ ConstantExpression constant = visit(argument);
+ if (constant == null) return null;
+ arguments.add(constant);
}
- return member;
- }
-
- @override
- ClassEntity getSuperClass(ClassEntity cls,
- {bool skipUnnamedMixinApplications: false}) {
- ClassEntity superclass = elementMap._getSuperType(cls)?.element;
- if (skipUnnamedMixinApplications) {
- while (superclass != null &&
- elementMap._isUnnamedMixinApplication(superclass)) {
- superclass = elementMap._getSuperType(superclass)?.element;
- }
+ for (ir.NamedExpression argument in node.named) {
+ ConstantExpression constant = visit(argument.value);
+ if (constant == null) return null;
+ arguments.add(constant);
}
- return superclass;
- }
-
- @override
- void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype)) {
- elementMap._forEachSupertype(cls, f);
+ return arguments;
}
- @override
- void forEachMixin(ClassEntity cls, void f(ClassEntity mixin)) {
- elementMap._forEachMixin(cls, f);
+ ConstructedConstantExpression _computeConstructorInvocation(
+ ir.Constructor target, ir.Arguments arguments) {
+ return new ConstructedConstantExpression(
+ elementAdapter.createInterfaceType(
+ target.enclosingClass, arguments.types),
+ elementAdapter.getConstructor(target),
+ elementAdapter.getCallStructure(arguments),
+ _computeArguments(arguments));
}
@override
- void forEachClassMember(
- ClassEntity cls, void f(ClassEntity declarer, MemberEntity member)) {
- elementMap._forEachClassMember(cls, f);
+ ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) {
+ return _computeConstructorInvocation(node.target, node.arguments);
}
@override
- MemberEntity lookupLibraryMember(LibraryEntity library, String name,
- {bool setter: false, bool required: false}) {
- MemberEntity member =
- elementMap.lookupLibraryMember(library, name, setter: setter);
- if (member == null && required) {
- throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
- "The member '${name}' was not found in library '${library.name}'.");
+ ConstantExpression visitVariableGet(ir.VariableGet node) {
+ if (node.variable.parent is ir.FunctionNode) {
+ ir.FunctionNode function = node.variable.parent;
+ int index = function.positionalParameters.indexOf(node.variable);
+ if (index != -1) {
+ return new PositionalArgumentReference(index);
+ } else {
+ assert(function.namedParameters.contains(node.variable));
+ return new NamedArgumentReference(node.variable.name);
+ }
}
- return member;
+ throw new UnimplementedError(
+ 'Unimplemented constant expression $node (${node.runtimeType})');
}
@override
- ClassEntity lookupClass(LibraryEntity library, String name,
- {bool required: false}) {
- ClassEntity cls = elementMap.lookupClass(library, name);
- if (cls == null && required) {
- throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
- "The class '$name' was not found in library '${library.name}'.");
+ ConstantExpression visitStaticGet(ir.StaticGet node) {
+ if (node.target is ir.Field) {
+ return new FieldConstantExpression(elementAdapter.getField(node.target));
+ } else if (node.target is ir.Procedure) {
+ FunctionEntity function = elementAdapter.getMethod(node.target);
+ DartType type = elementAdapter.getFunctionType(node.target.function);
+ return new FunctionConstantExpression(function, type);
}
- return cls;
+ throw new UnimplementedError(
+ 'Unexpected constant expression $node (${node.runtimeType})');
}
@override
- void forEachClass(KLibrary library, void f(ClassEntity cls)) {
- elementMap._forEachClass(library, f);
+ ConstantExpression visitNullLiteral(ir.NullLiteral node) {
+ return new NullConstantExpression();
}
@override
- LibraryEntity lookupLibrary(Uri uri, {bool required: false}) {
- LibraryEntity library = elementMap.lookupLibrary(uri);
- if (library == null && required) {
- throw new SpannableAssertionFailure(
- CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found.");
- }
- return library;
+ ConstantExpression visitBoolLiteral(ir.BoolLiteral node) {
+ return new BoolConstantExpression(node.value);
}
@override
- CallStructure getCallStructure(KFunction function) {
- _FunctionData data = elementMap._memberList[function.memberIndex];
- return data.callStructure;
+ ConstantExpression visitIntLiteral(ir.IntLiteral node) {
+ return new IntConstantExpression(node.value);
}
@override
- bool isDeferredLoadLibraryGetter(KMember member) {
- // TODO(johnniwinther): Support these.
- return false;
+ ConstantExpression visitDoubleLiteral(ir.DoubleLiteral node) {
+ return new DoubleConstantExpression(node.value);
}
@override
- Iterable<ConstantValue> getMemberMetadata(KMember member) {
- _MemberData memberData = elementMap._memberList[member.memberIndex];
- return memberData.getMetadata(elementMap);
- }
-}
-
-/// Visitor that converts kernel dart types into [DartType].
-class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
- final KernelToElementMap elementAdapter;
- bool topLevel = true;
-
- DartTypeConverter(this.elementAdapter);
-
- DartType convert(ir.DartType type) {
- topLevel = true;
- return type.accept(this);
- }
-
- /// Visit a inner type.
- DartType visitType(ir.DartType type) {
- topLevel = false;
- return type.accept(this);
- }
-
- InterfaceType visitSupertype(ir.Supertype node) {
- ClassEntity cls = elementAdapter.getClass(node.classNode);
- return new InterfaceType(cls, visitTypes(node.typeArguments));
- }
-
- List<DartType> visitTypes(List<ir.DartType> types) {
- topLevel = false;
- return new List.generate(
- types.length, (int index) => types[index].accept(this));
+ ConstantExpression visitStringLiteral(ir.StringLiteral node) {
+ return new StringConstantExpression(node.value);
}
@override
- DartType visitTypeParameterType(ir.TypeParameterType node) {
- return new TypeVariableType(elementAdapter.getTypeVariable(node.parameter));
+ ConstantExpression visitSymbolLiteral(ir.SymbolLiteral node) {
+ return new SymbolConstantExpression(node.value);
}
@override
- DartType visitFunctionType(ir.FunctionType node) {
- return new FunctionType(
- visitType(node.returnType),
- visitTypes(node.positionalParameters
- .take(node.requiredParameterCount)
- .toList()),
- visitTypes(node.positionalParameters
- .skip(node.requiredParameterCount)
- .toList()),
- node.namedParameters.map((n) => n.name).toList(),
- node.namedParameters.map((n) => visitType(n.type)).toList());
+ ConstantExpression visitStringConcatenation(ir.StringConcatenation node) {
+ return new ConcatenateConstantExpression(_computeList(node.expressions));
}
@override
- DartType visitInterfaceType(ir.InterfaceType node) {
- ClassEntity cls = elementAdapter.getClass(node.classNode);
- return new InterfaceType(cls, visitTypes(node.typeArguments));
+ ConstantExpression visitMapLiteral(ir.MapLiteral node) {
+ if (!node.isConst) {
+ throw new UnimplementedError(
+ 'Unexpected constant expression $node (${node.runtimeType})');
+ }
+ DartType keyType = elementAdapter.getDartType(node.keyType);
+ DartType valueType = elementAdapter.getDartType(node.valueType);
+ List<ConstantExpression> keys = <ConstantExpression>[];
+ List<ConstantExpression> values = <ConstantExpression>[];
+ for (ir.MapEntry entry in node.entries) {
+ keys.add(visit(entry.key));
+ values.add(visit(entry.value));
+ }
+ return new MapConstantExpression(
+ _commonElements.mapType(keyType, valueType), keys, values);
}
@override
- DartType visitVoidType(ir.VoidType node) {
- return const VoidType();
+ ConstantExpression visitListLiteral(ir.ListLiteral node) {
+ if (!node.isConst) {
+ throw new UnimplementedError(
+ 'Unexpected constant expression $node (${node.runtimeType})');
+ }
+ DartType elementType = elementAdapter.getDartType(node.typeArgument);
+ List<ConstantExpression> values = <ConstantExpression>[];
+ for (ir.Expression value in node.expressions) {
+ values.add(visit(value));
+ }
+ return new ListConstantExpression(
+ _commonElements.listType(elementType), values);
}
@override
- DartType visitDynamicType(ir.DynamicType node) {
- return const DynamicType();
+ ConstantExpression visitConditionalExpression(ir.ConditionalExpression node) {
+ ConstantExpression condition = visit(node.condition);
+ ConstantExpression trueExp = visit(node.then);
+ ConstantExpression falseExp = visit(node.otherwise);
+ return new ConditionalConstantExpression(condition, trueExp, falseExp);
}
@override
- DartType visitInvalidType(ir.InvalidType node) {
- if (topLevel) {
+ ConstantExpression visitPropertyGet(ir.PropertyGet node) {
+ if (node.name.name != 'length') {
throw new UnimplementedError(
- "Outermost invalid types not currently supported");
+ 'Unexpected constant expression $node (${node.runtimeType})');
}
- // Nested invalid types are treated as `dynamic`.
- return const DynamicType();
+ ConstantExpression receiver = visit(node.receiver);
+ return new StringLengthConstantExpression(receiver);
}
-}
-
-/// [native.BehaviorBuilder] for kernel based elements.
-class KernelBehaviorBuilder extends native.BehaviorBuilder {
- final CommonElements commonElements;
-
- KernelBehaviorBuilder(this.commonElements);
@override
- bool get trustJSInteropTypeAnnotations {
+ ConstantExpression visitMethodInvocation(ir.MethodInvocation node) {
+ // Method invocations are generally not constant expressions but unary
+ // and binary expressions are encoded as method invocations in kernel.
+ if (node.arguments.named.isNotEmpty) {
+ throw new UnimplementedError(
+ 'Unexpected constant expression $node (${node.runtimeType})');
+ }
+ if (node.arguments.positional.length == 0) {
+ UnaryOperator operator;
+ if (node.name.name == UnaryOperator.NEGATE.selectorName) {
+ operator = UnaryOperator.NEGATE;
+ } else {
+ operator = UnaryOperator.parse(node.name.name);
+ }
+ if (operator != null) {
+ ConstantExpression expression = visit(node.receiver);
+ return new UnaryConstantExpression(operator, expression);
+ }
+ }
+ if (node.arguments.positional.length == 1) {
+ BinaryOperator operator = BinaryOperator.parse(node.name.name);
+ if (operator != null) {
+ ConstantExpression left = visit(node.receiver);
+ ConstantExpression right = visit(node.arguments.positional.single);
+ return new BinaryConstantExpression(left, operator, right);
+ }
+ }
throw new UnimplementedError(
- "KernelNativeBehaviorComputer.trustJSInteropTypeAnnotations");
- }
-
- @override
- DiagnosticReporter get reporter {
- throw new UnimplementedError("KernelNativeBehaviorComputer.reporter");
- }
-
- @override
- NativeData get nativeData {
- throw new UnimplementedError("KernelNativeBehaviorComputer.nativeData");
+ 'Unexpected constant expression $node (${node.runtimeType})');
}
-}
-
-/// Constant environment mapping [ConstantExpression]s to [ConstantValue]s using
-/// [_EvaluationEnvironment] for the evaluation.
-class KernelConstantEnvironment implements ConstantEnvironment {
- KernelToElementMap _worldBuilder;
- Map<ConstantExpression, ConstantValue> _valueMap =
- <ConstantExpression, ConstantValue>{};
-
- KernelConstantEnvironment(this._worldBuilder);
@override
- ConstantSystem get constantSystem => const JavaScriptConstantSystem();
-
- @override
- ConstantValue getConstantValueForVariable(VariableElement element) {
+ ConstantExpression visitStaticInvocation(ir.StaticInvocation node) {
+ MemberEntity member = elementAdapter.getMember(node.target);
+ if (member == _commonElements.identicalFunction) {
+ if (node.arguments.positional.length == 2 &&
+ node.arguments.named.isEmpty) {
+ ConstantExpression left = visit(node.arguments.positional[0]);
+ ConstantExpression right = visit(node.arguments.positional[1]);
+ return new IdenticalConstantExpression(left, right);
+ }
+ } else if (member.name == 'fromEnvironment' &&
+ node.arguments.positional.length == 1) {
+ ConstantExpression name = visit(node.arguments.positional.single);
+ ConstantExpression defaultValue;
+ if (node.arguments.named.length == 1) {
+ if (node.arguments.named.single.name != 'defaultValue') {
+ throw new UnimplementedError(
+ 'Unexpected constant expression $node (${node.runtimeType})');
+ }
+ defaultValue = visit(node.arguments.named.single.value);
+ }
+ if (member.enclosingClass == _commonElements.boolClass) {
+ return new BoolFromEnvironmentConstantExpression(name, defaultValue);
+ } else if (member.enclosingClass == _commonElements.intClass) {
+ return new IntFromEnvironmentConstantExpression(name, defaultValue);
+ } else if (member.enclosingClass == _commonElements.stringClass) {
+ return new StringFromEnvironmentConstantExpression(name, defaultValue);
+ }
+ }
throw new UnimplementedError(
- "KernelConstantEnvironment.getConstantValueForVariable");
+ 'Unexpected constant expression $node (${node.runtimeType})');
}
@override
- ConstantValue getConstantValue(ConstantExpression expression) {
- return _valueMap.putIfAbsent(expression, () {
- return expression.evaluate(
- new _EvaluationEnvironment(_worldBuilder), constantSystem);
+ ConstantExpression visitLogicalExpression(ir.LogicalExpression node) {
+ BinaryOperator operator = BinaryOperator.parse(node.operator);
+ if (operator != null) {
+ ConstantExpression left = visit(node.left);
+ ConstantExpression right = visit(node.right);
+ return new BinaryConstantExpression(left, operator, right);
+ }
+ throw new UnimplementedError(
+ 'Unexpected constant expression $node (${node.runtimeType})');
+ }
+
+ /// Compute the [ConstantConstructor] corresponding to the const constructor
+ /// [node].
+ ConstantConstructor computeConstantConstructor(ir.Constructor node) {
+ assert(node.isConst);
+ ir.Class cls = node.enclosingClass;
+ InterfaceType type = elementAdapter.elementEnvironment
+ .getThisType(elementAdapter.getClass(cls));
+
+ Map<dynamic, ConstantExpression> defaultValues =
+ <dynamic, ConstantExpression>{};
+ int parameterIndex = 0;
+ node.function.positionalParameters
+ .forEach((ir.VariableDeclaration parameter) {
+ if (parameterIndex >= node.function.requiredParameterCount) {
+ if (parameter.initializer != null) {
+ defaultValues[parameterIndex] = parameter.initializer.accept(this);
+ } else {
+ defaultValues[parameterIndex] = new NullConstantExpression();
+ }
+ }
+ parameterIndex++;
+ });
+ node.function.namedParameters.forEach((ir.VariableDeclaration parameter) {
+ defaultValues[parameter.name] = parameter.initializer.accept(this);
});
- }
-
- @override
- bool hasConstantValue(ConstantExpression expression) {
- throw new UnimplementedError("KernelConstantEnvironment.hasConstantValue");
- }
-}
-
-/// Evaluation environment used for computing [ConstantValue]s for
-/// kernel based [ConstantExpression]s.
-class _EvaluationEnvironment implements EvaluationEnvironment {
- final KernelToElementMap _elementMap;
-
- _EvaluationEnvironment(this._elementMap);
-
- @override
- CommonElements get commonElements => _elementMap.commonElements;
-
- @override
- InterfaceType substByContext(InterfaceType base, InterfaceType target) {
- return _elementMap._substByContext(base, target);
- }
-
- @override
- ConstantConstructor getConstructorConstant(ConstructorEntity constructor) {
- return _elementMap._getConstructorConstant(constructor);
- }
-
- @override
- ConstantExpression getFieldConstant(FieldEntity field) {
- return _elementMap._getFieldConstant(field);
- }
-
- @override
- ConstantExpression getLocalConstant(Local local) {
- throw new UnimplementedError("_EvaluationEnvironment.getLocalConstant");
- }
-
- @override
- String readFromEnvironment(String name) {
- return _elementMap._environment.valueOf(name);
- }
-}
-
-class KernelResolutionWorldBuilder extends KernelResolutionWorldBuilderBase {
- final KernelToElementMap elementMap;
-
- KernelResolutionWorldBuilder(this.elementMap, NativeBasicData nativeBasicData,
- SelectorConstraintsStrategy selectorConstraintsStrategy)
- : super(elementMap.elementEnvironment, elementMap.commonElements,
- nativeBasicData, selectorConstraintsStrategy);
-
- @override
- Iterable<InterfaceType> getSupertypes(ClassEntity cls) {
- return elementMap._getOrderedTypeSet(cls).supertypes;
- }
-
- @override
- ClassEntity getSuperClass(ClassEntity cls) {
- return elementMap._getSuperType(cls)?.element;
- }
-
- @override
- bool implementsFunction(ClassEntity cls) {
- // TODO(johnniwinther): Implement this.
- return false;
- }
-
- @override
- int getHierarchyDepth(ClassEntity cls) {
- return elementMap._getHierarchyDepth(cls);
- }
-
- @override
- ClassEntity getAppliedMixin(ClassEntity cls) {
- // TODO(johnniwinther): Implement this.
- return null;
- }
-
- @override
- bool validateClass(ClassEntity cls) => true;
-
- @override
- bool checkClass(ClassEntity cls) => true;
-}
-// Interface for testing equivalence of Kernel-based entities.
-class WorldDeconstructionForTesting {
- final KernelToElementMap elementMap;
+ bool isRedirecting = node.initializers.length == 1 &&
+ node.initializers.single is ir.RedirectingInitializer;
- WorldDeconstructionForTesting(this.elementMap);
+ Map<FieldEntity, ConstantExpression> fieldMap =
+ <FieldEntity, ConstantExpression>{};
- KClass getSuperclassForClass(KClass cls) {
- _KClassEnv env = elementMap._classEnvs[cls.classIndex];
- ir.Supertype supertype = env.cls.supertype;
- if (supertype == null) return null;
- return elementMap.getClass(supertype.classNode);
- }
+ void registerField(ir.Field field, ConstantExpression constant) {
+ fieldMap[elementAdapter.getField(field)] = constant;
+ }
- bool isUnnamedMixinApplication(KClass cls) {
- return elementMap._isUnnamedMixinApplication(cls);
- }
+ if (!isRedirecting) {
+ for (ir.Field field in cls.fields) {
+ if (field.initializer != null) {
+ registerField(field, field.initializer.accept(this));
+ }
+ }
+ }
- InterfaceType getMixinTypeForClass(KClass cls) {
- _KClassEnv env = elementMap._classEnvs[cls.classIndex];
- ir.Supertype mixedInType = env.cls.mixedInType;
- if (mixedInType == null) return null;
- return elementMap.createInterfaceType(
- mixedInType.classNode, mixedInType.typeArguments);
+ ConstructedConstantExpression superConstructorInvocation;
+ for (ir.Initializer initializer in node.initializers) {
+ if (initializer is ir.FieldInitializer) {
+ registerField(initializer.field, initializer.value.accept(this));
+ } else if (initializer is ir.SuperInitializer) {
+ superConstructorInvocation = _computeConstructorInvocation(
+ initializer.target, initializer.arguments);
+ } else if (initializer is ir.RedirectingInitializer) {
+ superConstructorInvocation = _computeConstructorInvocation(
+ initializer.target, initializer.arguments);
+ } else {
+ throw new UnsupportedError(
+ 'Unexpected initializer $node (${node.runtimeType})');
+ }
+ }
+ if (isRedirecting) {
+ return new RedirectingGenerativeConstantConstructor(
+ defaultValues, superConstructorInvocation);
+ } else {
+ return new GenerativeConstantConstructor(
+ type, defaultValues, fieldMap, superConstructorInvocation);
+ }
}
}
« no previous file with comments | « pkg/compiler/lib/src/kernel/element_adapter.dart ('k') | pkg/compiler/lib/src/kernel/element_map_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698