@@ -0,0 +1,1503 @@
+package openmods.calc;%0A%0Aimport com.google.common.base.Strings;%0Aimport com.google.common.base.Supplier;%0Aimport openmods.Log;%0A%0Apublic class SingleExprEvaluator%3CE, M%3E %7B%0A%0A%09public interface EnvironmentConfigurator%3CE%3E %7B%0A%09%09public void accept(Environment%3CE%3E env);%0A%09%7D%0A%0A%09private final Calculator%3CE, M%3E calculator;%0A%0A%09private boolean useFallback;%0A%0A%09private M exprType;%0A%0A%09private String expr;%0A%0A%09private IExecutable%3CE%3E compiledExpr;%0A%0A%09public SingleExprEvaluator(Calculator%3CE, M%3E calculator) %7B%0A%09%09this.calculator = calculator;%0A%09%7D%0A%0A%09public static %3CE, M%3E SingleExprEvaluator%3CE, M%3E create(Calculator%3CE, M%3E calculator) %7B%0A%09%09return new SingleExprEvaluator%3CE, M%3E(calculator);%0A%09%7D%0A%0A%09public void setExpr(M exprType, String expr) %7B%0A%09%09this.exprType = exprType;%0A%09%09this.expr = expr;%0A%09%09this.compiledExpr = null;%0A%09%09this.useFallback = false;%0A%09%7D%0A%0A%09public E evaluate(EnvironmentConfigurator%3CE%3E conf, Supplier%3CE%3E fallbackValue) %7B%0A%09%09if (useFallback %7C%7C Strings.isNullOrEmpty(expr) %7C%7C exprType == null) return fallbackValue.get();%0A%0A%09%09if (compiledExpr == null) %7B%0A%09%09%09try %7B%0A%09%09%09%09compiledExpr = calculator.compilers.compile(exprType, expr);%0A%09%09%09%7D catch (Exception ex) %7B%0A%09%09%09%09useFallback = true;%0A%09%09%09%09Log.warn(ex, %22Failed to compile formula %25s%22, expr);%0A%09%09%09%09return fallbackValue.get();%0A%09%09%09%7D%0A%09%09%7D%0A%0A%09%09conf.accept(calculator.environment);%0A%0A%09%09try %7B%0A%09%09%09return calculator.environment.executeAndPop(compiledExpr);%0A%09%09%7D catch (Exception ex) %7B%0A%09%09%09useFallback = true;%0A%09%09%09Log.warn(ex, %22Failed to execute formula %25s%22, expr);%0A%09%09%09return fallbackValue.get();%0A%09%09%7D%0A%09%7D%0A%0A%7D%0A

Add helper for single-formula calculators