evaluateOpBinary method

EvaluateOutput evaluateOpBinary(
  1. EvaluateInput input
)

Implementation

EvaluateOutput evaluateOpBinary(EvaluateInput input) {
  final op = input.expr.opBinary;
  final ol =
      evaluateExpr(EvaluateInput(defStack: input.defStack, expr: op.left));
  if (ol.status != EvaluateOutput_Status.OK) {
    return ol;
  }
  final or =
      evaluateExpr(EvaluateInput(defStack: input.defStack, expr: op.right));
  if (or.status != EvaluateOutput_Status.OK) {
    return or;
  }
  final operandL = ol.value;
  final operandR = or.value;
  switch (op.op) {
    case OpBinary_Op.SUB:
      if (operandL.type != Value_Type.NUM) {
        return _errorUnexpectedType(input.expr.path.append(['sub', 0]),
            operandL.type, [Value_Type.NUM]);
      }
      if (operandR.type != Value_Type.NUM) {
        return _errorUnexpectedType(input.expr.path.append(['sub', 1]),
            operandR.type, [Value_Type.NUM]);
      }
      final v = operandL.num - operandR.num;
      if (!v.isFinite) {
        return _errorNotFiniteNumber(input.expr.path);
      }
      return EvaluateOutput(value: numValue(v));
    case OpBinary_Op.DIV:
      if (operandL.type != Value_Type.NUM) {
        return _errorUnexpectedType(input.expr.path.append(['div', 0]),
            operandL.type, [Value_Type.NUM]);
      }
      if (operandR.type != Value_Type.NUM) {
        return _errorUnexpectedType(input.expr.path.append(['div', 1]),
            operandR.type, [Value_Type.NUM]);
      }
      final v = operandL.num / operandR.num;
      if (!v.isFinite) {
        return _errorNotFiniteNumber(input.expr.path);
      }
      return EvaluateOutput(value: numValue(v));
    case OpBinary_Op.EQ:
      return EvaluateOutput(value: _equal(operandL, operandR));
    case OpBinary_Op.NEQ:
      return EvaluateOutput(
          value: boolValue(!_equal(operandL, operandR).bool_2));
    case OpBinary_Op.LT:
      final cmpVal =
          _compare(input.expr.path.append(['lt']), operandL, operandR);
      if (cmpVal.status != EvaluateOutput_Status.OK) {
        return cmpVal;
      }
      return EvaluateOutput(value: boolValue(cmpVal.value.num < 0));
    case OpBinary_Op.LTE:
      final cmpVal =
          _compare(input.expr.path.append(['lte']), operandL, operandR);
      if (cmpVal.status != EvaluateOutput_Status.OK) {
        return cmpVal;
      }
      return EvaluateOutput(value: boolValue(cmpVal.value.num <= 0));
    case OpBinary_Op.GT:
      final cmpVal =
          _compare(input.expr.path.append(['gt']), operandL, operandR);
      if (cmpVal.status != EvaluateOutput_Status.OK) {
        return cmpVal;
      }
      return EvaluateOutput(value: boolValue(cmpVal.value.num > 0));
    case OpBinary_Op.GTE:
      final cmpVal =
          _compare(input.expr.path.append(['gte']), operandL, operandR);
      if (cmpVal.status != EvaluateOutput_Status.OK) {
        return cmpVal;
      }
      return EvaluateOutput(value: boolValue(cmpVal.value.num >= 0));
    default:
      throw ArgumentError('unexpected binary operator ${op.op}');
  }
}