visitSuperExpression method

  1. @override
Object? visitSuperExpression(
  1. SSuperExpression node
)
override

Visit a SSuperExpression.

Implementation

@override
Object? visitSuperExpression(SSuperExpression node) {
  if (currentFunction == null || currentFunction?.ownerType == null) {
    // Use ownerType
    throw RuntimeD4rtException(
      "'super' can only be used within an instance method.",
    );
  }
  final ownerType = currentFunction!.ownerType!; // Use ownerType
  // Need to ensure ownerType is actually a class for super access
  if (ownerType is! InterpretedClass) {
    throw RuntimeD4rtException(
      "'super' used outside of a class context (found ${ownerType.runtimeType}).",
    );
  }
  final definingClass =
      ownerType; // Can safely use ownerType as InterpretedClass now

  InterpretedClass? standardSuperclass = definingClass.superclass;
  BridgedClass? bridgedSuperclass = definingClass.bridgedSuperclass;

  // Step 3 (testlog 20260518-1449): when the class has neither a standard
  // nor a bridged superclass but DOES apply bridged mixins (e.g.
  // `class _Node with DiagnosticableTreeMixin`), Dart's mixin desugaring
  // produces an implicit super of `(Object with M1 with M2 ...)`. Treat
  // the most-derived bridged mixin (last in the `with` clause) as the
  // bridged superclass for super-call resolution so that scripts can
  // invoke the mixin's default implementation via `super.foo(...)`.
  if (standardSuperclass == null &&
      bridgedSuperclass == null &&
      definingClass.bridgedMixins.isNotEmpty) {
    bridgedSuperclass = definingClass.bridgedMixins.last;
  }

  if (standardSuperclass == null && bridgedSuperclass == null) {
    throw RuntimeD4rtException(
      "Class '${definingClass.name}' does not have a standard or bridged superclass, cannot use 'super'.",
    );
  }

  // Get the current 'this' instance
  try {
    final thisInstance = environment.get('this');
    if (thisInstance is InterpretedInstance) {
      // Pass the correct superclass type to BoundSuper
      if (standardSuperclass != null) {
        return BoundSuper(thisInstance, standardSuperclass);
      } else {
        // bridgedSuperclass cannot be null here due to the check above
        return BoundBridgedSuper(thisInstance, bridgedSuperclass!);
      }
    } else {
      // Should not happen if currentFunction is set correctly
      throw RuntimeD4rtException(
        "Cannot find 'this' instance when using 'super'.",
      );
    }
  } on RuntimeD4rtException {
    throw RuntimeD4rtException(
      "Cannot find 'this' instance when using 'super'.",
    );
  }
}