evaluateGetElem method

EvaluateExprOutput evaluateGetElem(
  1. EvaluateExprInput input
)

Implementation

EvaluateExprOutput evaluateGetElem(EvaluateExprInput input) {
  final path = input.path;
  final get = evaluateExpr(EvaluateExprInput(
      path: pathAppendKey(path, "get"),
      defs: input.defs,
      expr: input.expr.obj["get"]));
  if (get.status != EvaluateExprOutput_Status.OK) {
    return get;
  }
  final from = evaluateExpr(EvaluateExprInput(
      path: pathAppendKey(path, "from"),
      defs: input.defs,
      expr: input.expr.obj["from"]));
  if (from.status != EvaluateExprOutput_Status.OK) {
    return from;
  }

  switch (from.value.type) {
    case Type.TYPE_STR:
      if (get.value.type != Type.TYPE_NUM) {
        return _errorUnexpectedType(
            pathAppendKey(path, "get"), [Type.TYPE_NUM], get.value.type);
      }
      if (!valueCanInt(get.value)) {
        return _errorArithmeticError(pathAppendKey(path, "get"),
            "index ${get.value.num} is not an integer");
      }
      final pos = get.value.num.toInt();
      final fromChars = from.value.str.characters;
      if (pos < 0 || pos >= fromChars.length) {
        return _errorIndexOutOfBounds(
            pathAppendKey(path, "get"), 0, fromChars.length, pos);
      }
      return EvaluateExprOutput(
          value: Value(
              type: Type.TYPE_STR,
              str: fromChars.characterAt(pos).toString()));
    case Type.TYPE_ARR:
      if (get.value.type != Type.TYPE_NUM) {
        return _errorUnexpectedType(
            pathAppendKey(path, "get"), [Type.TYPE_NUM], get.value.type);
      }
      if (!valueCanInt(get.value)) {
        return _errorArithmeticError(pathAppendKey(path, "get"),
            "index ${get.value.num} is not an integer");
      }
      final pos = get.value.num.toInt();
      if (pos < 0 || pos >= from.value.arr.length) {
        return _errorIndexOutOfBounds(
            pathAppendKey(path, "get"), 0, from.value.arr.length, pos);
      }
      return EvaluateExprOutput(value: from.value.arr[pos]);
    case Type.TYPE_OBJ:
      if (get.value.type != Type.TYPE_STR) {
        return _errorUnexpectedType(
            pathAppendKey(path, "get"), [Type.TYPE_STR], get.value.type);
      }
      final pos = get.value.str;
      final val = from.value.obj[pos];
      if (val == null) {
        return _errorKeyNotFound(
            pathAppendKey(path, "get"), from.value.obj.keys.toList(), pos);
      }
      return EvaluateExprOutput(value: from.value.obj[pos]);
    default:
      return _errorUnexpectedType(pathAppendKey(path, "from"),
          [Type.TYPE_STR, Type.TYPE_ARR, Type.TYPE_OBJ], from.value.type);
  }
}