Add ModularNamerImpl

To use for modular codegen. Creates ModularName and ModularVariableUse
for naming decisions that need to be deferred to world-impact application
time.

The class is still unused, awaiting refactoring of world-impact application.

Change-Id: I7d4d30da587ccf814b2d879b26f76de2eb3ca276
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101525
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index c6b3d1c..ecc4dcc 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -712,7 +712,7 @@
         rtiChecksBuilder,
         emitterTask.nativeEmitter);
 
-    CodegenInputs codegen = new CodegenImpl(emitterTask.emitter,
+    CodegenInputs codegen = new CodegenInputsImpl(emitterTask.emitter,
         oneShotInterceptorData, rtiSubstitutions, rtiEncoder, namer, tracer);
 
     functionCompiler.onCodegenStart(codegen);
@@ -812,7 +812,7 @@
   Tracer get tracer;
 }
 
-class CodegenImpl implements CodegenInputs {
+class CodegenInputsImpl implements CodegenInputs {
   @override
   final ModularEmitter emitter;
 
@@ -837,6 +837,6 @@
   @override
   final Tracer tracer;
 
-  CodegenImpl(this.emitter, this.oneShotInterceptorData, this.rtiSubstitutions,
-      this.rtiEncoder, this.namer, this.tracer);
+  CodegenInputsImpl(this.emitter, this.oneShotInterceptorData,
+      this.rtiSubstitutions, this.rtiEncoder, this.namer, this.tracer);
 }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index f28aa79..138e4cd 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -438,9 +438,6 @@
     return _jsVariableReserved;
   }
 
-  final String asyncPrefix = r"$async$";
-  @override
-  final String staticStateHolder = r'$';
   final String getterPrefix = r'get$';
   final String lazyGetterPrefix = r'$get$';
   final String setterPrefix = r'set$';
@@ -470,7 +467,6 @@
   static final jsAst.Name literalPlus = new StringBackedName('+');
   static final jsAst.Name _literalDynamic = new StringBackedName("dynamic");
 
-  jsAst.Name _literalAsyncPrefix;
   jsAst.Name _literalGetterPrefix;
   jsAst.Name _literalSetterPrefix;
 
@@ -600,7 +596,6 @@
   final Map<LibraryEntity, String> _libraryKeys = HashMap();
 
   Namer(this._closedWorld) {
-    _literalAsyncPrefix = new StringBackedName(asyncPrefix);
     _literalGetterPrefix = new StringBackedName(getterPrefix);
     _literalSetterPrefix = new StringBackedName(setterPrefix);
   }
@@ -1726,16 +1721,6 @@
     return name;
   }
 
-  @override
-  String safeVariablePrefixForAsyncRewrite(String name) {
-    return "$asyncPrefix$name";
-  }
-
-  @override
-  jsAst.Name deriveAsyncBodyName(jsAst.Name original) {
-    return new _AsyncName(_literalAsyncPrefix, original);
-  }
-
   String operatorNameToIdentifier(String name) {
     if (name == null) return null;
     if (name == '==') {
@@ -2349,23 +2334,23 @@
   /// Returns a variable use for accessing [library].
   ///
   /// This is one of the [reservedGlobalObjectNames]
-  jsAst.VariableUse readGlobalObjectForLibrary(LibraryEntity library);
+  jsAst.Expression readGlobalObjectForLibrary(LibraryEntity library);
 
   /// Returns a variable use for accessing the class [element].
   ///
   /// This is one of the [reservedGlobalObjectNames]
-  jsAst.VariableUse readGlobalObjectForClass(ClassEntity element);
+  jsAst.Expression readGlobalObjectForClass(ClassEntity element);
 
   /// Returns a variable use for accessing the type [element].
   ///
   /// This is one of the [reservedGlobalObjectNames]
-  jsAst.VariableUse readGlobalObjectForType(Entity element);
+  jsAst.Expression readGlobalObjectForType(Entity element);
 
   /// Returns a variable use for accessing the member [element].
   ///
   /// This is either the [staticStateHolder] or one of the
   /// [reservedGlobalObjectNames]
-  jsAst.VariableUse readGlobalObjectForMember(MemberEntity element);
+  jsAst.Expression readGlobalObjectForMember(MemberEntity element);
 
   /// Returns a JavaScript property name used to store the class [element] on
   /// one of the global objects.
@@ -2448,10 +2433,6 @@
   /// from the type name.
   jsAst.Name runtimeTypeName(Entity element);
 
-  /// Returns the name for the async body of the method with the [original]
-  /// name.
-  jsAst.Name deriveAsyncBodyName(jsAst.Name original);
-
   /// Property name in which to store the given static or instance [method].
   /// For instance methods, this includes the suffix encoding arity and named
   /// parameters.
@@ -2460,19 +2441,6 @@
   /// may share its name with an instance method.
   jsAst.Name methodPropertyName(FunctionEntity method);
 
-  /// Returns a safe variable name for use in async rewriting.
-  ///
-  /// Has the same property as [safeVariableName] but does not clash with
-  /// names returned from there.
-  /// Additionally, when used as a prefix to a variable name, the result
-  /// will be safe to use, as well.
-  String safeVariablePrefixForAsyncRewrite(String name);
-
-  /// Returns the name for the holder of static state.
-  ///
-  /// This is used for mutable static fields.
-  String get staticStateHolder;
-
   /// Returns the name of the `isX` property for classes that implement
   /// [element].
   jsAst.Name operatorIs(ClassEntity element);
@@ -2490,6 +2458,36 @@
   /// Returns the name of the closure of the static method [element].
   jsAst.Name staticClosureName(FunctionEntity element);
 
+  /// The prefix used for encoding async properties.
+  final String asyncPrefix = r"$async$";
+
+  /// Returns the name for the holder of static state.
+  ///
+  /// This is used for mutable static fields.
+  final String staticStateHolder = r'$';
+
+  jsAst.Name _literalAsyncPrefix;
+
+  ModularNamer() {
+    _literalAsyncPrefix = new StringBackedName(asyncPrefix);
+  }
+
+  /// Returns a safe variable name for use in async rewriting.
+  ///
+  /// Has the same property as [safeVariableName] but does not clash with
+  /// names returned from there.
+  /// Additionally, when used as a prefix to a variable name, the result
+  /// will be safe to use, as well.
+  String safeVariablePrefixForAsyncRewrite(String name) {
+    return "$asyncPrefix$name";
+  }
+
+  /// Returns the name for the async body of the method with the [original]
+  /// name.
+  jsAst.Name deriveAsyncBodyName(jsAst.Name original) {
+    return new _AsyncName(_literalAsyncPrefix, original);
+  }
+
   /// Returns the label name for [label] used as a break target.
   String breakLabelName(LabelDefinition label) {
     return '\$${label.labelName}\$${label.target.nestingLevel}';
@@ -2515,3 +2513,197 @@
     return 'c\$${target.nestingLevel}';
   }
 }
+
+class ModularNamerImpl extends ModularNamer {
+  @override
+  jsAst.Name get rtiFieldJsName {
+    return new ModularName(ModularNameKind.rtiField);
+  }
+
+  @override
+  jsAst.Name runtimeTypeName(Entity element) {
+    return new ModularName(ModularNameKind.runtimeTypeName, element);
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForLibrary(LibraryEntity library) {
+    return new ModularVariableUse(
+        ModularVariableUseKind.globalObjectForLibrary, library);
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForClass(ClassEntity element) {
+    return new ModularVariableUse(
+        ModularVariableUseKind.globalObjectForClass, element);
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForType(Entity element) {
+    return new ModularVariableUse(
+        ModularVariableUseKind.globalObjectForType, element);
+  }
+
+  @override
+  jsAst.Expression readGlobalObjectForMember(MemberEntity element) {
+    return new ModularVariableUse(
+        ModularVariableUseKind.globalObjectForMember, element);
+  }
+
+  @override
+  jsAst.Name aliasedSuperMemberPropertyName(MemberEntity member) {
+    return new ModularName(ModularNameKind.aliasedSuperMember, member);
+  }
+
+  @override
+  jsAst.Name staticClosureName(FunctionEntity element) {
+    return new ModularName(ModularNameKind.staticClosure, element);
+  }
+
+  @override
+  jsAst.Name methodPropertyName(FunctionEntity method) {
+    return new ModularName(ModularNameKind.methodProperty, method);
+  }
+
+  @override
+  jsAst.Name instanceFieldPropertyName(FieldEntity element) {
+    return new ModularName(ModularNameKind.instanceField, element);
+  }
+
+  @override
+  jsAst.Name operatorIsType(DartType type) {
+    return new ModularName(ModularNameKind.operatorIsType, type);
+  }
+
+  @override
+  jsAst.Name instanceMethodName(FunctionEntity method) {
+    return new ModularName(ModularNameKind.instanceMethod, method);
+  }
+
+  @override
+  jsAst.Name invocationName(Selector selector) {
+    return new ModularName(ModularNameKind.invocation, selector);
+  }
+
+  @override
+  jsAst.Name lazyInitializerName(FieldEntity element) {
+    return new ModularName(ModularNameKind.lazyInitializer, element);
+  }
+
+  @override
+  jsAst.Name operatorIs(ClassEntity element) {
+    return new ModularName(ModularNameKind.operatorIs, element);
+  }
+
+  @override
+  jsAst.Name globalPropertyNameForType(Entity element) {
+    return new ModularName(ModularNameKind.globalPropertyNameForType, element);
+  }
+
+  @override
+  jsAst.Name globalPropertyNameForClass(ClassEntity element) {
+    return new ModularName(ModularNameKind.globalPropertyNameForClass, element);
+  }
+
+  @override
+  jsAst.Name globalPropertyNameForMember(MemberEntity element) {
+    return new ModularName(ModularNameKind.globalPropertyNameForClass, element);
+  }
+
+  @override
+  jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes) {
+    return new ModularName(ModularNameKind.nameForGetInterceptor, classes);
+  }
+
+  @override
+  jsAst.Name asName(String name) {
+    return new ModularName(ModularNameKind.asName, name);
+  }
+
+  @override
+  jsAst.Name substitutionName(ClassEntity element) {
+    return new ModularName(ModularNameKind.substitution, element);
+  }
+}
+
+enum ModularNameKind {
+  rtiField,
+  runtimeTypeName,
+  aliasedSuperMember,
+  staticClosure,
+  methodProperty,
+  operatorIs,
+  operatorIsType,
+  substitution,
+  instanceMethod,
+  instanceField,
+  invocation,
+  lazyInitializer,
+  globalPropertyNameForClass,
+  globalPropertyNameForType,
+  globalPropertyNameForMember,
+  nameForGetInterceptor,
+  asName,
+}
+
+class ModularName extends jsAst.Name {
+  final ModularNameKind kind;
+  jsAst.Name deferred;
+  final Object data;
+
+  ModularName(this.kind, [this.data]);
+
+  @override
+  String get key {
+    assert(deferred != null);
+    return deferred.key;
+  }
+
+  @override
+  String get name {
+    assert(deferred != null);
+    return deferred.name;
+  }
+
+  @override
+  bool get allowRename {
+    assert(deferred != null);
+    return deferred.allowRename;
+  }
+
+  @override
+  int compareTo(covariant ModularName other) {
+    assert(deferred != null);
+    assert(other.deferred != null);
+    return deferred.compareTo(other.deferred);
+  }
+}
+
+enum ModularVariableUseKind {
+  globalObjectForLibrary,
+  globalObjectForClass,
+  globalObjectForType,
+  globalObjectForMember,
+}
+
+class ModularVariableUse extends jsAst.DeferredExpression {
+  final ModularVariableUseKind kind;
+  final Entity element;
+  jsAst.VariableUse _value;
+
+  ModularVariableUse(this.kind, this.element);
+
+  @override
+  jsAst.VariableUse get value {
+    assert(_value != null);
+    return _value;
+  }
+
+  void set value(jsAst.VariableUse value) {
+    assert(_value == null);
+    assert(value != null);
+    _value = value;
+  }
+
+  @override
+  int get precedenceLevel => value.precedenceLevel;
+}