/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package de.monticore.symboltable;
import de.monticore.ast.ASTNode;
import de.monticore.symboltable.modifiers.AccessModifier;
import de.monticore.symboltable.resolving.ResolvingFilter;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
/**
* Super type of all scopes in the symbol table. A scope defines/contains a collection of symbols
* and can have an enclosing and several sub scopes. An example is the method scope in Java. A
* method scope can define variables and can have sub scopes, such as if-blocks. The enclosing
* scope is the scope of the class which defines the method.
*
* @author Pedram Mir Seyed Nazari
*
*/
public interface Scope {
/**
* @return the name of the scope, if it is a named scope. If a symbol spans this scope, the name usually is the same
* as the spanning symbol's name.
*
* @see Scope#getSpanningSymbol()
*/
Optional<String> getName();
/**
* @return the enclosing scope. In Java, for example, the enclosing scope of a method scope is
* the class scope that defines the method.
*/
Optional<? extends Scope> getEnclosingScope();
/**
* @return the sub scopes. In Java, for example, method scopes are the sub scopes of a class
* scope.
*/
List<? extends Scope> getSubScopes();
/**
* Resolves the symbol with the given <code>name</code> and <code>kind</code> starting from
* this scope. If no symbols are found, the resolving is continued in the enclosing scope. Note
* that hiding has also an impact on whether the resolving should continue in the enclosing scope.
*
* @param name the symbol name to be resolved
* @param kind the symbol kind to be resolved
* @param <T> the type of the resolved symbol
*
* @return the symbol with the given <code>name</code> and <code>kind</code> starting from
* this scope.
*
* @throws de.monticore.symboltable.resolving.ResolvedSeveralEntriesException Thrown if more than one
* symbol is resolved.
*/
<T extends Symbol> Optional<T> resolve(String name, SymbolKind kind);
/**
*
* Resolves the symbol with the given <code>name</code> and <code>kind</code> starting from
* this scope. Additionally, the symbol must have a proper access <code>modifier</code>. For
* example, in Java, if <code>modifier</code> was <code>protected</code>, the symbol would have
* to be declared as <code>protected</code> or <code>public</code>. If no symbols are found,
* the resolving is continued in the enclosing scope. Note that hiding has also an impact on whether the
* resolving should continue in the enclosing scope.
*
* @param name the symbol name to be resolved
* @param kind the symbol kind to be resolved
* @param modifier the access modifier of the symbol
* @param <T> the type of the resolved symbol
*
* @return the symbol with the given <code>name</code> and <code>kind</code> starting from
* this scope.
*
* @throws de.monticore.symboltable.resolving.ResolvedSeveralEntriesException Thrown if more than one
* symbol is resolved.
*/
<T extends Symbol> Optional<T> resolve(String name, SymbolKind kind, AccessModifier modifier);
<T extends Symbol> Optional<T> resolve(String name, SymbolKind kind, AccessModifier modifier, Predicate<Symbol> predicate);
/**
* Resolves only explicitly imported symbols (i.e., symbols from imported scopes) and locally defined symbols.
* For example, consider the Java classes <code>A</code>, <code>B</code>, and <code>C</code>, where
* <code>A</code> subclasses <code>B</code> which itself subclasses <code>C</code>.
* Then, <code>A</code> imports all (non-private) symbols defined in <code>B</code>. Further, <code>A</code>
* imports all symbols <b>explicitly</b> imported by <code>B</code>, that means, all (non-private) symbols
* defined in <code>C</code>.
* <br /><br />
* In contrast, <code>A</code> does not import symbols that are <b>implicitly</b> imported by <code>B</code>.
* That means, symbols defined in the enclosing scope of <code>B</code>.
*
*
*
* @param name the symbol name to be resolved
* @param kind the symbol kind to be resolved
* @param modifier the access modifier of the symbol
* @param <T> the type of the resolved symbol
*
* @return the symbol with the given <code>name</code> and <code>kind</code> starting from
* this scope.
*
* @throws de.monticore.symboltable.resolving.ResolvedSeveralEntriesException Thrown if more than one
* symbol is resolved.
*/
<T extends Symbol> Optional<T> resolveImported(String name, SymbolKind kind, AccessModifier modifier);
<T extends Symbol> Collection<T> resolveMany(String name, SymbolKind kind);
<T extends Symbol> Collection<T> resolveMany(String name, SymbolKind kind, AccessModifier modifier);
<T extends Symbol> Collection<T> resolveMany(String name, SymbolKind kind, Predicate<Symbol> predicate);
<T extends Symbol> Collection<T> resolveMany(String name, SymbolKind kind, AccessModifier modifier, Predicate<Symbol> predicate);
/**
* Resolves the symbol with the given <code>name</code> and <code>kind</code> only within scope.
*
* @param name the symbol name to be resolved
* @param kind the symbol kind to be resolved
* @param <T> the type of the resolved symbol
*
* @return the symbol with the given <code>name</code> and <code>kind</code> only within scope.
*
* @throws de.monticore.symboltable.resolving.ResolvedSeveralEntriesException Thrown if more than one
* symbol is resolved.
*/
<T extends Symbol> Optional<T> resolveLocally(String name, SymbolKind kind);
/**
* Resolves all symbols with the given <code>kind</code> only within this scope.
*
* @param kind the symbol kind to be resolved
* @param <T> the type of the resolved symbols
*
* @return the symbols with the given <code>name</code> and <code>kind</code> only within scope.
*/
<T extends Symbol> Collection<T> resolveLocally(SymbolKind kind);
/**
* Resolves the symbol fulfilling the <code>predicate</code>, starting from this scope. If no
* symbols are found, the resolving is continued in the enclosing scope.
*
*
* @param predicate the predicate that has to be fulfilled by the symbol
*
* @return the symbol fulfilling the <code>predicate</code>, starting from this scope.
*
* @deprecated use {@link #resolveMany(String, SymbolKind, Predicate)} instead
*/
@Deprecated
Optional<? extends Symbol> resolve(SymbolPredicate predicate);
<T extends Symbol> Optional<T> resolveDown(String name, SymbolKind kind);
<T extends Symbol> Optional<T> resolveDown(String name, SymbolKind kind, AccessModifier modifier);
<T extends Symbol> Optional<T> resolveDown(String name, SymbolKind kind, AccessModifier modifier, Predicate<Symbol> predicate);
<T extends Symbol> Collection<T> resolveDownMany(String name, SymbolKind kind);
<T extends Symbol> Collection<T> resolveDownMany(String name, SymbolKind kind, AccessModifier modifier);
<T extends Symbol> Collection<T> resolveDownMany(String name, SymbolKind kind, AccessModifier modifier, Predicate<Symbol> predicate);
/**
*
* @return all symbols directly defined/contained in this scope (not in enclosing scope).
*/
Map<String, Collection<Symbol>> getLocalSymbols();
/**
* @deprecated use {@link #getLocalSymbols()} instead
*/
Map<String, Collection<Symbol>> getSymbols();
/**
* @return number of symbols directly defined/contained in this scope (not in enclosing scope).
*/
int getSymbolsSize();
/**
* @return true, if this scope shadows symbols of the enclosing scope. By default, named scopes
* (see #getName()) are shadowing scopes.
*/
boolean isShadowingScope();
/**
* @return true, if this scope is spanned by a symbol. For example, a Java method spans a
* method scope.
*/
boolean isSpannedBySymbol();
/**
* @return the symbol that spans this scope. For example, a Java method spans a
* method scope.
*/
Optional<? extends ScopeSpanningSymbol> getSpanningSymbol();
/**
* States whether this scope exports symbols that can be used from outside the scope.
* For example, a Java class exports symbols. In contrast, a Java if-block does not
* export any symbols, hence, its locally defined variables cannot be referenced
* from outside. By default, a scope with a name exports its symbols (although
* this does not apply for Java methods).
*
* @return true, if this scope exports symbols that can be used from outside the scope.
*/
boolean exportsSymbols();
/**
* Returns the resolvers that are available in this scope. Within a simple grammarlanguage, these
* resolvers are usually the same for all scopes of the grammarlanguage. The composing languages this
* may vary.
*
* @return the resolvers available in this scope.
*/
Set<ResolvingFilter<? extends Symbol>> getResolvingFilters();
/**
* @return the corresponding ast node
*/
Optional<? extends ASTNode> getAstNode();
/**
* Returns this scope as a {@link MutableScope}. Note that each scope must
* implement {@link MutableScope}.
*
* @return this scope as a {@link MutableScope}.
*/
MutableScope getAsMutableScope();
}