parseTypeTag method

TypeTag parseTypeTag()

Implementation

TypeTag parseTypeTag() {
  if (tokens.isEmpty) {
    bail("Invalid type tag.");
  }

  final item = tokens.removeAt(0);

  final (tokenTy, tokenVal) = item;
  if (tokenVal == "u8") {
    return TypeTagU8();
  }
  if (tokenVal == "u16") {
    return TypeTagU16();
  }
  if (tokenVal == "u32") {
    return TypeTagU32();
  }
  if (tokenVal == "u64") {
    return TypeTagU64();
  }
  if (tokenVal == "u128") {
    return TypeTagU128();
  }
  if (tokenVal == "u256") {
    return TypeTagU256();
  }
  if (tokenVal == "bool") {
    return TypeTagBool();
  }
  if (tokenVal == "address") {
    return TypeTagAddress();
  }
  if (tokenVal == "vector") {
    _consume("<");
    final res = parseTypeTag();
    _consume(">");
    return TypeTagVector(res);
  }
  if (tokenVal == "string") {
    return TypeTagStruct(stringStructTag);
  }
  if (tokenTy == "IDENT" &&
      (tokenVal.startsWith("0x") || tokenVal.startsWith("0X"))) {
    String address = tokenVal;
    _consume("::");
    var item = tokens.removeAt(0);
    final (moduleTokenTy, module) = item;
    if (moduleTokenTy != "IDENT") {
      bail("Invalid type tag.");
    }
    _consume("::");
    item = tokens.removeAt(0);
    final (nameTokenTy, name) = item;
    if (nameTokenTy != "IDENT") {
      bail("Invalid type tag.");
    }

    // Objects can contain either concrete types e.g. 0x1::object::ObjectCore or generics e.g. T
    // Neither matter as we can't do type checks, so just the address applies and we consume the entire generic.
    // TODO: Support parsing structs that don't come from core code address
    if (address == AccountAddress.CORE_CODE_ADDRESS && module == "object" && name == "Object") {
      _consumeWholeGeneric();
      return TypeTagAddress();
    }

    var tyTags = <TypeTag>[];
    // Check if the struct has ty args
    if (tokens.isNotEmpty && tokens[0].$2 == "<") {
      _consume("<");
      tyTags = _parseCommaList(">", true);
      _consume(">");
    }

    final structTag = StructTag(
      AccountAddress.fromHex(address),
      Identifier(module),
      Identifier(name),
      tyTags,
    );
    return TypeTagStruct(structTag);
  }

  if (tokenTy == "GENERIC") {
    if (_typeTags.isEmpty) {
      bail("Can't convert generic type since no typeTags were specified.");
    }
    // a generic tokenVal has the format of `T<digit>`, for example `T1`.
    // The digit (i.e 1) indicates the the index of this type in the typeTags array.
    // For a tokenVal == T1, should be parsed as the type in typeTags[1]
    final idx = int.parse(tokenVal.substring(1), radix: 10);
    return TypeTagParser(_typeTags[idx]).parseTypeTag();
  }

  throw ArgumentError("Invalid type tag.");
}