ScopeInfo.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.functional.core.tree;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Tracks variable scope information for loop analysis.
*
* <p>This class maintains information about variables in scope, including
* which variables are modified and which are effectively final. This is
* crucial for determining if a loop can be safely converted to use lambda
* expressions, which require effectively final variables.</p>
*
* @since 1.0.0
*/
public final class ScopeInfo {
private final Set<String> outerScopeVariables;
private final Set<String> modifiedVariables;
private final Set<String> localVariables;
/**
* Creates a new empty scope info.
*/
public ScopeInfo() {
this.outerScopeVariables = new HashSet<>();
this.modifiedVariables = new HashSet<>();
this.localVariables = new HashSet<>();
}
private ScopeInfo(Set<String> outerScopeVariables, Set<String> modifiedVariables, Set<String> localVariables) {
this.outerScopeVariables = new HashSet<>(outerScopeVariables);
this.modifiedVariables = new HashSet<>(modifiedVariables);
this.localVariables = new HashSet<>(localVariables);
}
/**
* Creates a child scope that inherits this scope's variables.
*
* <p>The child scope will see all variables from outer scope plus
* this scope's local variables. Modifications are tracked across scopes.</p>
*
* @return a new ScopeInfo representing a child scope
*/
public ScopeInfo createChildScope() {
Set<String> childOuter = new HashSet<>(outerScopeVariables);
childOuter.addAll(localVariables);
return new ScopeInfo(childOuter, new HashSet<>(modifiedVariables), new HashSet<>());
}
/**
* Adds a local variable to this scope.
*
* @param name the variable name
*/
public void addLocalVariable(String name) {
localVariables.add(name);
}
/**
* Marks a variable as modified.
*
* @param name the variable name
*/
public void addModifiedVariable(String name) {
modifiedVariables.add(name);
}
/**
* Checks if a variable is effectively final (not modified).
*
* @param variableName the variable name to check
* @return true if the variable is not in the modified set
*/
public boolean isEffectivelyFinal(String variableName) {
return !modifiedVariables.contains(variableName);
}
/**
* Gets an unmodifiable view of outer scope variables.
*
* @return unmodifiable set of outer scope variables
*/
public Set<String> getOuterScopeVariables() {
return Collections.unmodifiableSet(outerScopeVariables);
}
/**
* Gets an unmodifiable view of modified variables.
*
* @return unmodifiable set of modified variables
*/
public Set<String> getModifiedVariables() {
return Collections.unmodifiableSet(modifiedVariables);
}
/**
* Gets an unmodifiable view of local variables.
*
* @return unmodifiable set of local variables
*/
public Set<String> getLocalVariables() {
return Collections.unmodifiableSet(localVariables);
}
}