evaluateOpVariadic method

EvaluateOutput evaluateOpVariadic(
  1. EvaluateInput input
)

Implementation

EvaluateOutput evaluateOpVariadic(EvaluateInput input) {
  final op = input.expr.opVariadic;
  final operands = <Value>[];

  for (final elem in op.operands) {
    final val =
        evaluateExpr(EvaluateInput(defStack: input.defStack, expr: elem));
    if (val.status != EvaluateOutput_Status.OK) {
      return val;
    }
    operands.add(val.value);
  }

  switch (op.op) {
    case OpVariadic_Op.ADD:
      var addVal = 0.0;
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.NUM) {
          return _errorUnexpectedType(input.expr.path.append(['add', i]),
              operand.type, [Value_Type.NUM]);
        }
        addVal += operand.num;
      }
      if (!addVal.isFinite) {
        return _errorNotFiniteNumber(input.expr.path.append(['add']));
      }
      return EvaluateOutput(value: numValue(addVal));
    case OpVariadic_Op.MUL:
      var mulVal = 1.0;
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.NUM) {
          return _errorUnexpectedType(input.expr.path.append(['mul', i]),
              operand.type, [Value_Type.NUM]);
        }
        mulVal *= operand.num;
      }
      if (!mulVal.isFinite) {
        return _errorNotFiniteNumber(input.expr.path.append(['mul']));
      }
      return EvaluateOutput(value: numValue(mulVal));
    case OpVariadic_Op.AND:
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.BOOL) {
          return _errorUnexpectedType(input.expr.path.append(['and', i]),
              operand.type, [Value_Type.BOOL]);
        }
        if (!operand.bool_2) {
          return EvaluateOutput(value: boolValue(false));
        }
      }
      return EvaluateOutput(value: boolValue(true));
    case OpVariadic_Op.OR:
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.BOOL) {
          return _errorUnexpectedType(input.expr.path.append(['or', i]),
              operand.type, [Value_Type.BOOL]);
        }
        if (operand.bool_2) {
          return EvaluateOutput(value: boolValue(true));
        }
      }
      return EvaluateOutput(value: boolValue(false));
    case OpVariadic_Op.CAT:
      var catVal = '';
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.STR) {
          return _errorUnexpectedType(input.expr.path.append(['cat', i]),
              operand.type, [Value_Type.STR]);
        }
        catVal += operand.str;
      }
      return EvaluateOutput(value: strValue(catVal));
    case OpVariadic_Op.MIN:
      var minVal = double.infinity;
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.NUM) {
          return _errorUnexpectedType(input.expr.path.append(['min', i]),
              operand.type, [Value_Type.NUM]);
        }
        minVal = min(minVal, operand.num);
      }
      return EvaluateOutput(value: numValue(minVal));
    case OpVariadic_Op.MAX:
      var maxVal = double.negativeInfinity;
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.NUM) {
          return _errorUnexpectedType(input.expr.path.append(['max', i]),
              operand.type, [Value_Type.NUM]);
        }
        maxVal = max(maxVal, operand.num);
      }
      return EvaluateOutput(value: numValue(maxVal));
    case OpVariadic_Op.MERGE:
      final mergeVal = <String, Value>{};
      for (final (i, operand) in operands.indexed) {
        if (operand.type != Value_Type.OBJ) {
          return _errorUnexpectedType(input.expr.path.append(['merge', i]),
              operand.type, [Value_Type.OBJ]);
        }
        mergeVal.addEntries(operand.obj.entries);
      }
      return EvaluateOutput(value: objValue(mergeVal));
    default:
      throw ArgumentError('unexpected variadic operator ${op.op}');
  }
}