package openmods.calc; import com.google.common.collect.Maps; import java.util.Map; import openmods.utils.OptionalInt; import openmods.utils.StackValidationException; public class TopSymbolMap<E> extends SymbolMap<E> { private static class CallableSymbol<E> implements ISymbol<E> { private final ICallable<E> callable; public CallableSymbol(ICallable<E> callable) { this.callable = callable; } @Override public void call(Frame<E> frame, OptionalInt argumentsCount, OptionalInt returnsCount) { callable.call(frame, argumentsCount, returnsCount); } @Override public E get() { throw new UnsupportedOperationException("Cannot use function as value"); } } private abstract static class ValueSymbol<E> extends SingleReturnCallable<E> implements ISymbol<E> { @Override public E call(Frame<E> frame, OptionalInt argumentsCount) { if (!argumentsCount.compareIfPresent(0)) throw new StackValidationException("Expected no arguments but got %s", argumentsCount.get()); return get(); } } private static class GettableSymbol<E> extends ValueSymbol<E> { private final IGettable<E> gettable; public GettableSymbol(IGettable<E> gettable) { this.gettable = gettable; } @Override public E get() { return gettable.get(); } } private static class ConstantSymbol<E> extends ValueSymbol<E> { private final E value; public ConstantSymbol(E value) { this.value = value; } @Override public E get() { return value; } } private final Map<String, ISymbol<E>> globals = Maps.newHashMap(); @Override protected ISymbol<E> createSymbol(ICallable<E> callable) { return new CallableSymbol<E>(callable); } @Override protected ISymbol<E> createSymbol(IGettable<E> gettable) { return new GettableSymbol<E>(gettable); } @Override protected ISymbol<E> createSymbol(E value) { return new ConstantSymbol<E>(value); } @Override public void put(String name, ISymbol<E> symbol) { globals.put(name, symbol); } @Override public ISymbol<E> get(String name) { return globals.get(name); } }