evaluateOpVariadic method

EvaluateExprOutput evaluateOpVariadic(
  1. EvaluateExprInput input
)

Implementation

EvaluateExprOutput evaluateOpVariadic(EvaluateExprInput input) {
  final operator = input.expr.obj.keys.first;
  final pathOp = pathAppendKey(input.path, operator);
  final operands = <Value>[];
  for (final (pos, o) in input.expr.obj[operator]!.arr.indexed) {
    final op = evaluateExpr(EvaluateExprInput(
        path: pathAppendIndex(pathOp, pos), defs: input.defs, expr: o));
    if (op.status != EvaluateExprOutput_Status.OK) {
      return op;
    }
    operands.add(op.value);
  }
  if (operator == opVariadicKeyName(OpVariadic_Operator.ADD)) {
    var add = 0.0;
    for (final operand in operands) {
      if (operand.type != Type.TYPE_NUM) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_NUM], operand.type);
      }
      add += operand.num;
    }
    final v = Value(type: Type.TYPE_NUM, num: add);
    if (!_isFiniteNumber(v)) {
      return _errorArithmeticError(pathOp,
          "add(${operands.map((o) => o.num.toInt().toString()).join(',')}) is not a finite number");
    }
    return EvaluateExprOutput(value: v);
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.MUL)) {
    var mul = 1.0;
    for (final operand in operands) {
      if (operand.type != Type.TYPE_NUM) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_NUM], operand.type);
      }
      mul *= operand.num;
    }
    final v = Value(type: Type.TYPE_NUM, num: mul);
    if (!_isFiniteNumber(v)) {
      return _errorArithmeticError(pathOp,
          "mul(${operands.map((e) => e.num.toInt().toString()).join(',')}) is not a finite number");
    }
    return EvaluateExprOutput(value: v);
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.AND)) {
    for (final operand in operands) {
      if (operand.type != Type.TYPE_BOOL) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_BOOL], operand.type);
      }
      if (!operand.bool_2) {
        return EvaluateExprOutput(
            value: Value(type: Type.TYPE_BOOL, bool_2: false));
      }
    }
    return EvaluateExprOutput(
        value: Value(type: Type.TYPE_BOOL, bool_2: true));
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.OR)) {
    for (final operand in operands) {
      if (operand.type != Type.TYPE_BOOL) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_BOOL], operand.type);
      }
      if (operand.bool_2) {
        return EvaluateExprOutput(
            value: Value(type: Type.TYPE_BOOL, bool_2: true));
      }
    }
    return EvaluateExprOutput(
        value: Value(type: Type.TYPE_BOOL, bool_2: false));
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.CAT)) {
    var cat = '';
    for (final operand in operands) {
      if (operand.type != Type.TYPE_STR) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_STR], operand.type);
      }
      cat += operand.str;
    }
    return EvaluateExprOutput(value: Value(type: Type.TYPE_STR, str: cat));
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.MIN)) {
    var min_ = double.infinity;
    for (final operand in operands) {
      if (operand.type != Type.TYPE_NUM) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_NUM], operand.type);
      }
      min_ = min(min_, operand.num);
    }
    return EvaluateExprOutput(value: Value(type: Type.TYPE_NUM, num: min_));
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.MAX)) {
    var max_ = double.negativeInfinity;
    for (final operand in operands) {
      if (operand.type != Type.TYPE_NUM) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_NUM], operand.type);
      }
      max_ = max(max_, operand.num);
    }
    return EvaluateExprOutput(value: Value(type: Type.TYPE_NUM, num: max_));
  } else if (operator == opVariadicKeyName(OpVariadic_Operator.MERGE)) {
    final merge = <String, Value>{};
    for (final operand in operands) {
      if (operand.type != Type.TYPE_OBJ) {
        return _errorUnexpectedType(pathOp, [Type.TYPE_OBJ], operand.type);
      }
      for (final k in operand.obj.keys) {
        merge[k] = operand.obj[k]!;
      }
    }
    return EvaluateExprOutput(value: Value(type: Type.TYPE_OBJ, obj: merge));
  }
  return _errorUnsupportedOperation(input.path, operator);
}