// Path: engine/src/main/java/com/impossibl/stencil/engine/ExecutionException.java
// public class ExecutionException extends RuntimeException {
// 
//   private static final long serialVersionUID = 376006343757200461L;
//   
//   ExecutionLocation location;
// 
//   public ExecutionException() {
//   }
// 
//   public ExecutionException(String message, Throwable cause, ExecutionLocation location) {
//     super(location + ": " + message, cause);
//     this.location = location;
//   }
//   
//   public ExecutionException(String message, ExecutionLocation location) {
//     super(location + ": " + message);
//     this.location = location;
//   }
// 
//   public ExecutionException(Throwable cause, ExecutionLocation location) {
//     super(cause);
//     this.location = location;
//   }
// 
//   public ExecutionLocation getLocation() {
//     return location;
//   }
// 
//   public void setLocation(ExecutionLocation location) {
//     this.location = location;
//   }
// 
// }


import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.antlr.v4.runtime.ParserRuleContext;
import com.impossibl.stencil.engine.ExecutionException;

    try {

      // if either are floating point (double or float) use double
      if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
        double l = toDouble(left);
        double r = toDouble(right);
        return new Double(l + r);
      }

      // if either are bigdecimal use that type
      if (left instanceof BigDecimal || right instanceof BigDecimal) {
        BigDecimal l = toBigDecimal(left);
        BigDecimal r = toBigDecimal(right);
        BigDecimal result = l.add(r, getMathContext());
        return narrowBigDecimal(left, right, result);
      }

      // if either are numbers use integers
      if (left instanceof Number || right instanceof Number) {
        BigInteger l = toBigInteger(left);
        BigInteger r = toBigInteger(right);
        BigInteger result = l.add(r);
        return narrowBigInteger(left, right, result);
      }

    }
    catch (java.lang.NumberFormatException nfe) {
    }

// Path: engine/src/main/java/com/impossibl/stencil/engine/ExecutionException.java
// public class ExecutionException extends RuntimeException {
// 
//   private static final long serialVersionUID = 376006343757200461L;
//   
//   ExecutionLocation location;
// 
//   public ExecutionException() {
//   }
// 
//   public ExecutionException(String message, Throwable cause, ExecutionLocation location) {
//     super(location + ": " + message, cause);
//     this.location = location;
//   }
//   
//   public ExecutionException(String message, ExecutionLocation location) {
//     super(location + ": " + message);
//     this.location = location;
//   }
// 
//   public ExecutionException(Throwable cause, ExecutionLocation location) {
//     super(cause);
//     this.location = location;
//   }
// 
//   public ExecutionLocation getLocation() {
//     return location;
//   }
// 
//   public void setLocation(ExecutionLocation location) {
//     this.location = location;
//   }
// 
// }


// Path: engine/src/main/java/com/impossibl/stencil/engine/internal/StencilOperands.java
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.antlr.v4.runtime.ParserRuleContext;
import com.impossibl.stencil.engine.ExecutionException;


    try {

      // if either are floating point (double or float) use double
      if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
        double l = toDouble(left);
        double r = toDouble(right);
        return new Double(l + r);
      }

      // if either are bigdecimal use that type
      if (left instanceof BigDecimal || right instanceof BigDecimal) {
        BigDecimal l = toBigDecimal(left);
        BigDecimal r = toBigDecimal(right);
        BigDecimal result = l.add(r, getMathContext());
        return narrowBigDecimal(left, right, result);
      }

      // if either are numbers use integers
      if (left instanceof Number || right instanceof Number) {
        BigInteger l = toBigInteger(left);
        BigInteger r = toBigInteger(right);
        BigInteger result = l.add(r);
        return narrowBigInteger(left, right, result);
      }

    }
    catch (java.lang.NumberFormatException nfe) {
    }

    throw new ExecutionException("invalid operands for +", interpreter.getLocation(errCtx));