createAndInitializeInstance method
InterpretedInstance
createAndInitializeInstance(
- InterpreterVisitor visitor,
- List<
RuntimeType> ? typeArguments
Implementation
InterpretedInstance createAndInitializeInstance(
InterpreterVisitor visitor, List<RuntimeType>? typeArguments) {
// Prevent direct instantiation of abstract classes
if (isAbstract) {
throw RuntimeD4rtException("Cannot instantiate abstract class '$name'.");
}
// Get validated effective type arguments
final effectiveTypeArgs = _getValidatedTypeArguments(typeArguments);
// 1. Create the instance with a link to the class
final instance = InterpretedInstance(this,
typeArguments: effectiveTypeArgs); // Pass only the class
// Use the environment where the class was defined as the outer scope
// for evaluating initializers. We need to traverse the hierarchy.
final originalVisitorEnv = visitor.environment;
// Traverse the class hierarchy from top (Object/superclass) down to this class
List<InterpretedClass> hierarchy = [];
InterpretedClass? current = this;
while (current != null) {
hierarchy.insert(0, current); // Insert at beginning to get top-down order
current = current.superclass;
}
// Initialize fields for each class in the hierarchy
for (final klassInHierarchy in hierarchy) {
// Create a temporary environment for this specific class's initializers,
// enclosing the environment where *that* class was defined.
final fieldInitEnv =
Environment(enclosing: klassInHierarchy.classDefinitionEnvironment);
fieldInitEnv.define('this', instance); // Define 'this' for initializers
try {
visitor.environment =
fieldInitEnv; // Set visitor env for this class's initializers
// Initialize fields declared IN THIS CLASS
for (final fieldDecl in klassInHierarchy.fieldDeclarations) {
if (!fieldDecl.isStatic) {
for (final variable in fieldDecl.fields?.variables ?? []) {
final fieldName = variable.name?.name ?? '';
final isLate = fieldDecl.fields?.isLate ?? false;
final isFinal = fieldDecl.fields?.isFinal ?? false;
if (isLate) {
// Handle late instance field
if (variable.initializer != null) {
// Late instance field with lazy initializer
final lateVar = LateVariable(fieldName, () {
// Create a closure that will evaluate the initializer when accessed
final savedEnv = visitor.environment;
try {
visitor.environment = fieldInitEnv;
return variable.initializer!.accept<Object?>(visitor);
} finally {
visitor.environment = savedEnv;
}
}, isFinal: isFinal);
instance._fields[fieldName] = lateVar;
Logger.debug(
"[Instance Init] Defined late instance field '$fieldName' with lazy initializer.");
} else {
// Late instance field without initializer
final lateVar =
LateVariable(fieldName, null, isFinal: isFinal);
instance._fields[fieldName] = lateVar;
Logger.debug(
"[Instance Init] Defined late instance field '$fieldName' without initializer.");
}
} else {
// Regular field handling
if (variable.initializer != null) {
final value = variable.initializer!.accept<Object?>(visitor);
// Directly set the field on the instance map
instance._fields[fieldName] = value;
} else {
// Ensure field exists even without initializer (Dart default is null)
instance._fields.putIfAbsent(fieldName, () => null);
}
}
}
}
}
// Initialize fields from MIXINS applied to this class
// Iterate in application order (0 to n-1) so later mixins overwrite earlier ones
for (final mixin in klassInHierarchy.mixins) {
// Each mixin's field initializers run in the mixin's definition environment
// with 'this' bound to the instance being created.
final mixinFieldInitEnv =
Environment(enclosing: mixin.classDefinitionEnvironment);
mixinFieldInitEnv.define('this', instance);
// Temporarily set visitor environment for this mixin's initializers
final originalEnvBeforeMixin = visitor.environment;
try {
visitor.environment = mixinFieldInitEnv;
for (final fieldDecl in mixin.fieldDeclarations) {
if (!fieldDecl.isStatic) {
for (final variable in fieldDecl.fields?.variables ?? []) {
final fieldName = variable.name?.name ?? '';
if (variable.initializer != null) {
final value =
variable.initializer!.accept<Object?>(visitor);
// Set (or overwrite) the field on the instance
instance._fields[fieldName] = value;
Logger.debug(
"[Instance Init] Initialized mixin field '${klassInHierarchy.name}.$fieldName' from mixin '${mixin.name}' with value: $value");
} else {
// Ensure field exists even if not initialized (Dart default is null)
// Only set null if field wasn't already set by class or previous mixin
instance._fields.putIfAbsent(fieldName, () {
Logger.debug(
"[Instance Init] Initialized mixin field '${klassInHierarchy.name}.$fieldName' from mixin '${mixin.name}' to null (default)");
return null;
});
}
}
}
}
} finally {
// Restore visitor environment after this mixin's initializers
visitor.environment = originalEnvBeforeMixin;
}
}
} finally {
// Restore visitor environment after this class's initializers
visitor.environment = originalVisitorEnv;
}
}
// Instance fields from class hierarchy AND mixins should now be initialized.
Logger.debug(
"[Instance Init] Finished instance initialization for '$name'. Fields: ${instance._fields}");
return instance;
}