package scotch.compiler.syntax.scope; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import scotch.compiler.syntax.pattern.PatternCase; import scotch.compiler.syntax.reference.ClassReference; import scotch.compiler.syntax.reference.ValueReference; import scotch.compiler.syntax.type.DefaultTypeScope; import scotch.compiler.syntax.type.SumType; import scotch.compiler.syntax.type.Type; import scotch.compiler.syntax.type.Unification; import scotch.compiler.syntax.type.VariableType; import scotch.compiler.syntax.util.SymbolGenerator; import scotch.symbol.MethodSignature; import scotch.symbol.Operator; import scotch.symbol.Symbol; import scotch.symbol.Symbol.QualifiedSymbol; import scotch.symbol.Symbol.SymbolVisitor; import scotch.symbol.Symbol.UnqualifiedSymbol; import scotch.symbol.SymbolEntry; import scotch.symbol.SymbolResolver; import scotch.symbol.descriptor.DataConstructorDescriptor; import scotch.symbol.descriptor.DataTypeDescriptor; import scotch.symbol.descriptor.TypeClassDescriptor; import scotch.symbol.descriptor.TypeInstanceDescriptor; import scotch.symbol.type.TypeDescriptor; public class RootScope extends Scope { private final SymbolGenerator symbolGenerator; private final RootResolver resolver; private final Map<String, Scope> children; RootScope(SymbolGenerator symbolGenerator, SymbolResolver resolver) { this.symbolGenerator = symbolGenerator; this.resolver = new RootResolver(resolver); this.children = new HashMap<>(); } @Override public void addDependency(Symbol symbol) { throw new IllegalStateException(); } @Override public void addPattern(Symbol symbol, PatternCase pattern) { throw new IllegalStateException(); } @Override public void defineDataType(Symbol symbol, DataTypeDescriptor descriptor) { throw new IllegalStateException(); } @Override public void defineDataConstructor(Symbol symbol, DataConstructorDescriptor descriptor) { throw new IllegalStateException(); } @Override public Unification bind(VariableType variableType, Type target) { throw new IllegalStateException(); } @Override public void defineOperator(Symbol symbol, Operator operator) { throw new IllegalStateException(); } @Override public void defineSignature(Symbol symbol, Type type) { throw new IllegalStateException(); } @Override public void defineValue(Symbol symbol, Type type) { throw new IllegalStateException(); } @Override public Scope enterScope(String moduleName) { Scope scope = new ModuleScope(this, new DefaultTypeScope(symbolGenerator, resolver), resolver, symbolGenerator, moduleName); children.put(moduleName, scope); return scope; } @Override public void extendContext(Type type, Set<Symbol> additionalContext) { throw new IllegalStateException(); } @Override public void generalize(Type type) { throw new IllegalStateException(); } @Override public Type generate(Type type) { throw new IllegalStateException(); } @Override public Set<Symbol> getContext(Type type) { throw new IllegalStateException(); } @Override public Set<Symbol> getDependencies() { throw new IllegalStateException(); } @Override public Optional<TypeClassDescriptor> getMemberOf(ValueReference valueRef) { throw new IllegalStateException(); } @Override public Optional<Operator> getOperator(Symbol symbol) { throw new IllegalStateException(); } @Override public Scope getParent() { throw new IllegalStateException(); } @Override public Map<Symbol, List<PatternCase>> getPatternCases() { throw new IllegalStateException(); } @Override public Optional<Type> getRawValue(Symbol symbol) { throw new IllegalStateException(); } @Override public Optional<Type> getSignature(Symbol symbol) { throw new IllegalStateException(); } @Override public Type getTarget(Type type) { throw new IllegalStateException(); } @Override public void implement(Symbol typeClass, SumType type) { throw new UnsupportedOperationException(); // TODO } @Override public Optional<TypeClassDescriptor> getTypeClass(ClassReference classRef) { throw new IllegalStateException(); } @Override public Set<TypeInstanceDescriptor> getTypeInstances(Symbol typeClass, List<? extends Type> parameters) { throw new IllegalStateException(); } @Override public Optional<MethodSignature> getValueSignature(Symbol symbol) { return resolver.getEntry(symbol).flatMap(SymbolEntry::getValueMethod); } @Override public boolean isBound(VariableType type) { throw new IllegalStateException(); } @Override public boolean isGeneric(VariableType variableType) { throw new IllegalStateException(); } @Override public boolean isImplemented(Symbol typeClass, SumType type) { throw new IllegalStateException(); } @Override public boolean isDefined(Symbol symbol) { return resolver.isDefined(symbol); } @Override public boolean isOperator_(Symbol symbol) { return symbol.accept(new SymbolVisitor<Boolean>() { @Override public Boolean visit(QualifiedSymbol symbol) { return children.containsKey(symbol.getModuleName()) && children.get(symbol.getModuleName()).isOperator_(symbol); } @Override public Boolean visit(UnqualifiedSymbol symbol) { return false; } }); } @Override public Scope leaveScope() { throw new IllegalStateException("Can't leave root scope"); } @Override public Optional<Symbol> qualify(Symbol symbol) { return symbol.accept(new SymbolVisitor<Optional<Symbol>>() { @Override public Optional<Symbol> visit(QualifiedSymbol symbol) { if (resolver.isDefined(symbol)) { return Optional.of(symbol); } else { return Optional.empty(); } } @Override public Optional<Symbol> visit(UnqualifiedSymbol symbol) { return Optional.empty(); } }); } @Override public Symbol qualifyCurrent(Symbol symbol) { throw new IllegalStateException(); } @Override protected String getModuleName() { throw new IllegalStateException(); } @Override public Symbol reserveSymbol() { return symbolGenerator.reserveSymbol(); } @Override public Symbol reserveSymbol(List<String> nestings) { return symbolGenerator.reserveSymbol(nestings); } @Override public VariableType reserveType() { return symbolGenerator.reserveType(); } @Override public void specialize(Type type) { throw new IllegalStateException(); } @Override protected Optional<SymbolEntry> getEntry(Symbol symbol) { return symbol.accept(new SymbolVisitor<Optional<SymbolEntry>>() { @Override public Optional<SymbolEntry> visit(QualifiedSymbol symbol) { return resolver.getEntry(symbol); } @Override public Optional<SymbolEntry> visit(UnqualifiedSymbol symbol) { return Optional.empty(); } }); } @Override protected boolean isDataConstructor(Symbol symbol) { return false; } @Override protected boolean isDefinedLocally(Symbol symbol) { return false; } @Override protected boolean isExternal(Symbol symbol) { return resolver.isExternal(symbol); } private final class RootResolver implements SymbolResolver { private final SymbolResolver resolver; public RootResolver(SymbolResolver resolver) { this.resolver = resolver; } @Override public Optional<SymbolEntry> getEntry(Symbol symbol) { return symbol.accept(new SymbolVisitor<Optional<SymbolEntry>>() { @Override public Optional<SymbolEntry> visit(QualifiedSymbol symbol) { if (children.containsKey(symbol.getModuleName()) && children.get(symbol.getModuleName()).isDefinedLocally(symbol)) { return children.get(symbol.getModuleName()).getEntry(symbol); } else { return resolver.getEntry(symbol); } } @Override public Optional<SymbolEntry> visit(UnqualifiedSymbol symbol) { return Optional.empty(); } }); } @Override public Set<TypeInstanceDescriptor> getTypeInstances(Symbol symbol, List<TypeDescriptor> types) { return resolver.getTypeInstances(symbol, types); } @Override public Set<TypeInstanceDescriptor> getTypeInstancesByModule(String moduleName) { return resolver.getTypeInstancesByModule(moduleName); } @Override public boolean isDefined(Symbol symbol) { return symbol.accept(new SymbolVisitor<Boolean>() { @Override public Boolean visit(QualifiedSymbol symbol) { return children.containsKey(symbol.getModuleName()) && children.get(symbol.getModuleName()).isDefinedLocally(symbol) || resolver.isDefined(symbol); } @Override public Boolean visit(UnqualifiedSymbol symbol) { return false; } }); } public boolean isExternal(Symbol symbol) { return resolver.isDefined(symbol); } } }