package openmods.calc; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import openmods.utils.OptionalInt; public class SymbolCall<E> implements IExecutable<E> { public static final OptionalInt DEFAULT_ARG_COUNT = OptionalInt.absent(); public static final OptionalInt DEFAULT_RET_COUNT = OptionalInt.absent(); private final String id; private final OptionalInt argCount; private final OptionalInt returnCount; public SymbolCall(String id) { this(id, DEFAULT_ARG_COUNT, DEFAULT_RET_COUNT); } public SymbolCall(String id, int argumentCount, int returnCount) { this.id = id; this.argCount = OptionalInt.of(argumentCount); this.returnCount = OptionalInt.of(returnCount); } public SymbolCall(String id, OptionalInt argumentCount, OptionalInt returnCount) { this.id = id; this.argCount = argumentCount; this.returnCount = returnCount; } @Override public void execute(Frame<E> frame) { final ISymbol<E> symbol = frame.symbols().get(id); Preconditions.checkNotNull(symbol, "Unknown symbol: %s", id); try { symbol.call(frame, argCount, returnCount); } catch (ExecutionErrorException e) { throw e; } catch (Exception e) { throw new RuntimeException("Failed to execute symbol '" + id + "'", e); } } @Override public int hashCode() { return Objects.hashCode(id, argCount, returnCount); } @Override public boolean equals(Object obj) { if (obj instanceof SymbolCall) { final SymbolCall<?> other = (SymbolCall<?>)obj; return other.id.equals(this.id) && other.argCount.equals(this.argCount) && other.returnCount.equals(this.returnCount); } return false; } private static String printOptional(OptionalInt value) { return value.isPresent()? String.valueOf(value.get()) : "?"; } @Override public String toString() { return id + "[-" + printOptional(argCount) + "+" + printOptional(returnCount) + "]"; } }