Code review comment: Why we had to check pkg

Code under review:
public BType readType(int cpI) throws IOException {
            byte tag = inputStream.readByte();
            Name name = names.fromString(getStringCPEntryValue(inputStream));
            var flags = inputStream.readLong();

            
            inputStream.readInt();

            switch (tag) {
                case TypeTags.INT:
                    return typeParamAnalyzer.getNominalType(symTable.intType, name, flags);
                case TypeTags.BYTE:
                    return typeParamAnalyzer.getNominalType(symTable.byteType, name, flags);
                case TypeTags.FLOAT:
                    return typeParamAnalyzer.getNominalType(symTable.floatType, name, flags);
                case TypeTags.DECIMAL:
                    return typeParamAnalyzer.getNominalType(symTable.decimalType, name, flags);
                case TypeTags.STRING:
                    return typeParamAnalyzer.getNominalType(symTable.stringType, name, flags);
                case TypeTags.BOOLEAN:
                    return typeParamAnalyzer.getNominalType(symTable.booleanType, name, flags);
                
                case TypeTags.JSON:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.jsonType) : symTable.jsonType;
                case TypeTags.XML:
                    BType constraintType = readTypeFromCp();
                    BXMLType mutableXmlType = new BXMLType(constraintType, symTable.xmlType.tsymbol);
                    if (Symbols.isFlagOn(flags, Flags.PARAMETERIZED)) {
                        mutableXmlType.flags |= Flags.PARAMETERIZED;
                    }
                    return isImmutable(flags) ? getEffectiveImmutableType(mutableXmlType) : mutableXmlType;
                case TypeTags.NIL:
                    return symTable.nilType;
                case TypeTags.NEVER:
                    return symTable.neverType;
                case TypeTags.ANYDATA:
                    if (name.getValue().equals(Names.ANYDATA.getValue())) {
                        name = Names.EMPTY;
                    }
                    BType anydataNominalType = typeParamAnalyzer.getNominalType(symTable.anydataType, name, flags);
                    return isImmutable(flags) ? getEffectiveImmutableType(anydataNominalType,
                            symTable.anydataType.tsymbol.pkgID,
                            symTable.anydataType.tsymbol.owner) :
                            anydataNominalType;
                case TypeTags.RECORD:
                    int pkgCpIndex = inputStream.readInt();
                    PackageID pkgId = getPackageId(pkgCpIndex);

                    String recordName = getStringCPEntryValue(inputStream);
                     BRecordTypeSymbol recordSymbol = Symbols.createRecordSymbol(Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                                names.fromString(recordName),
                                                                                env.pkgSymbol.pkgID, null,
                                                                                env.pkgSymbol, symTable.builtinPos,
                                                                                COMPILED_SOURCE);
                    recordSymbol.flags |= flags;
                    recordSymbol.scope = new Scope(recordSymbol);
                    BRecordType recordType = new BRecordType(recordSymbol, recordSymbol.flags);
                    recordType.flags |= flags;

                    if (isImmutable(flags)) {
                        recordSymbol.flags |= Flags.READONLY;
                    }

                    recordSymbol.type = recordType;

                    compositeStack.push(recordType);
                    addShapeCP(recordType, cpI);

                    recordType.sealed = inputStream.readBoolean();
                    recordType.restFieldType = readTypeFromCp();

                    int recordFields = inputStream.readInt();
                    for (int i = 0; i < recordFields; i++) {
                        String fieldName = getStringCPEntryValue(inputStream);
                        var fieldFlags = inputStream.readLong();

                        byte[] docBytes = readDocBytes(inputStream);

                        BType fieldType = readTypeFromCp();

                        BVarSymbol varSymbol = new BVarSymbol(fieldFlags, names.fromString(fieldName),
                                                              recordSymbol.pkgID, fieldType,
                                                              recordSymbol.scope.owner, symTable.builtinPos,
                                                              COMPILED_SOURCE);

                        defineMarkDownDocAttachment(varSymbol, docBytes);

                        BField structField = new BField(varSymbol.name, varSymbol.pos, varSymbol);
                        recordType.fields.put(structField.name.value, structField);
                        recordSymbol.scope.define(varSymbol.name, varSymbol);
                    }

                    boolean isInitAvailable = inputStream.readByte() == 1;
                    if (isInitAvailable) {
                        
                        String recordInitFuncName = getStringCPEntryValue(inputStream);
                        var recordInitFuncFlags = inputStream.readLong();
                        BInvokableType recordInitFuncType = (BInvokableType) readTypeFromCp();
                        Name initFuncName = names.fromString(recordInitFuncName);
                        boolean isNative = Symbols.isFlagOn(recordInitFuncFlags, Flags.NATIVE);
                        BInvokableSymbol recordInitFuncSymbol =
                                Symbols.createFunctionSymbol(recordInitFuncFlags, initFuncName,
                                                             initFuncName, env.pkgSymbol.pkgID, recordInitFuncType,
                                                             env.pkgSymbol, isNative, symTable.builtinPos,
                                                             COMPILED_SOURCE);
                        recordInitFuncSymbol.retType = recordInitFuncType.retType;
                        
                        recordSymbol.initializerFunc = new BAttachedFunction(initFuncName, recordInitFuncSymbol,
                                                                             recordInitFuncType, symTable.builtinPos);
                        recordSymbol.scope.define(initFuncName, recordInitFuncSymbol);
                    }

                    recordType.typeInclusions = readTypeInclusions();



                    Object poppedRecordType = compositeStack.pop();
                    assert poppedRecordType == recordType;

                    if (pkgId.equals(env.pkgSymbol.pkgID)) {
                        return recordType;
                    }

                    SymbolEnv pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkgId));
                    return symbolResolver.lookupSymbolInMainSpace(pkgEnv, names.fromString(recordName)).type;
                case TypeTags.TYPEDESC:
                    BTypedescType typedescType = new BTypedescType(null, symTable.typeDesc.tsymbol);
                    typedescType.constraint = readTypeFromCp();
                    typedescType.flags = flags;
                    return typedescType;
                case TypeTags.TYPEREFDESC:
                    int pkgIndex = inputStream.readInt();
                    PackageID pkg = getPackageId(pkgIndex);

                    String typeDefName = getStringCPEntryValue(inputStream);
                    BTypeSymbol typeSymbol = Symbols.createTypeSymbol(SymTag.TYPE_REF,
                            Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                            names.fromString(typeDefName), env.pkgSymbol.pkgID, null, env.pkgSymbol,
                            symTable.builtinPos, COMPILED_SOURCE);
                    BTypeReferenceType typeReferenceType = new BTypeReferenceType(null,
                            typeSymbol, flags);
                    addShapeCP(typeReferenceType, cpI);
                    compositeStack.push(typeReferenceType);
                    typeReferenceType.referredType = readTypeFromCp();

                    Object poppedRefType = compositeStack.pop();
                    assert poppedRefType == typeReferenceType;
                    if (pkg.equals(env.pkgSymbol.pkgID)) {
                        return typeReferenceType;
                    }

                    SymbolEnv pkgenv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkg));
                    return symbolResolver.lookupSymbolInMainSpace(pkgenv, names.fromString(typeDefName)).type;

                case TypeTags.PARAMETERIZED_TYPE:
                    BParameterizedType type = new BParameterizedType(null, null, null, name, -1);
                    type.paramValueType = readTypeFromCp();
                    type.flags = flags;
                    type.paramIndex = inputStream.readInt();
                    return type;
                case TypeTags.STREAM:
                    BStreamType bStreamType = new BStreamType(TypeTags.STREAM, null, null, symTable.streamType.tsymbol);
                    bStreamType.constraint = readTypeFromCp();
                    bStreamType.completionType = readTypeFromCp();
                    bStreamType.flags = flags;
                    return bStreamType;
                case TypeTags.TABLE:
                    BTableType bTableType = new BTableType(TypeTags.TABLE, null, symTable.tableType.tsymbol, flags);
                    bTableType.constraint = readTypeFromCp();

                    boolean hasFieldNameList = inputStream.readByte() == 1;
                    if (hasFieldNameList) {
                        int fieldNameListSize = inputStream.readInt();
                        bTableType.fieldNameList = new ArrayList<>(fieldNameListSize);
                        for (int i = 0; i < fieldNameListSize; i++) {
                            String fieldName = getStringCPEntryValue(inputStream);
                            bTableType.fieldNameList.add(fieldName);
                        }
                    }

                    boolean hasKeyConstraint = inputStream.readByte() == 1;
                    if (hasKeyConstraint) {
                        bTableType.keyTypeConstraint = readTypeFromCp();
                        if (bTableType.keyTypeConstraint.tsymbol == null) {
                            bTableType.keyTypeConstraint.tsymbol =
                                    Symbols.createTypeSymbol(SymTag.TYPE, Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                             Names.EMPTY, env.pkgSymbol.pkgID,
                                                             bTableType.keyTypeConstraint, env.pkgSymbol.owner,
                                                             symTable.builtinPos, COMPILED_SOURCE);
                        }
                    }
                    return bTableType;
                case TypeTags.MAP:
                    BMapType bMapType = new BMapType(TypeTags.MAP, null, symTable.mapType.tsymbol, flags);
                    bMapType.constraint = readTypeFromCp();
                    return bMapType;
                case TypeTags.INVOKABLE:
                    BInvokableType bInvokableType = new BInvokableType(null, null, null, null);
                    bInvokableType.flags = flags;
                    if (inputStream.readBoolean()) {
                        return bInvokableType;
                    }
                    int paramCount = inputStream.readInt();
                    List<BType> paramTypes = new ArrayList<>(paramCount);
                    for (int i = 0; i < paramCount; i++) {
                        paramTypes.add(readTypeFromCp());
                    }
                    bInvokableType.paramTypes = paramTypes;
                    if (inputStream.readBoolean()) { 
                        bInvokableType.restType = readTypeFromCp();
                    }
                    bInvokableType.retType = readTypeFromCp();
                    return bInvokableType;
                
                case TypeTags.ANY:
                    BType anyNominalType = typeParamAnalyzer.getNominalType(symTable.anyType, name, flags);
                    return isImmutable(flags) ? getEffectiveImmutableType(anyNominalType,
                            symTable.anyType.tsymbol.pkgID,
                            symTable.anyType.tsymbol.owner) :
                            anyNominalType;
                case TypeTags.HANDLE:
                    return symTable.handleType;
                case TypeTags.READONLY:
                    return symTable.readonlyType;
                case TypeTags.ENDPOINT:
                    
                    break;
                case TypeTags.ARRAY:
                    byte state = inputStream.readByte();
                    int size = inputStream.readInt();
                    BTypeSymbol arrayTypeSymbol = Symbols.createTypeSymbol(SymTag.ARRAY_TYPE,
                                                                           Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                           Names.EMPTY, env.pkgSymbol.pkgID, null,
                                                                           env.pkgSymbol.owner, symTable.builtinPos,
                                                                           COMPILED_SOURCE);
                    BArrayType bArrayType = new BArrayType(null, arrayTypeSymbol, size, BArrayState.valueOf(state),
                            flags);
                    bArrayType.eType = readTypeFromCp();
                    return bArrayType;
                case TypeTags.UNION:
                    boolean isCyclic = inputStream.readByte() == 1;
                    boolean hasName = inputStream.readByte() == 1;
                    PackageID unionsPkgId = env.pkgSymbol.pkgID;
                    Name unionName = Names.EMPTY;
                    if (hasName) {
                        pkgCpIndex = inputStream.readInt();
                        unionsPkgId = getPackageId(pkgCpIndex);
                        String unionNameStr = getStringCPEntryValue(inputStream);
                        unionName = names.fromString(unionNameStr);
                    }
                    BTypeSymbol unionTypeSymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE,
                            Flags.asMask(EnumSet.of(Flag.PUBLIC)), unionName, unionsPkgId,
                            null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE);

                    int unionMemberCount = inputStream.readInt();
                    BUnionType unionType = BUnionType.create(unionTypeSymbol, new LinkedHashSet<>(unionMemberCount));
                    unionType.name = unionName;

                    addShapeCP(unionType, cpI);
                    compositeStack.push(unionType);

                    unionType.flags = flags;
                    unionType.isCyclic = isCyclic;
                    for (int i = 0; i < unionMemberCount; i++) {
                        unionType.add(readTypeFromCp());
                    }

                    int unionOriginalMemberCount = inputStream.readInt();
                    LinkedHashSet<BType> originalMemberTypes = new LinkedHashSet<>(unionOriginalMemberCount);
                    for (int i = 0; i < unionOriginalMemberCount; i++) {
                        originalMemberTypes.add(readTypeFromCp());
                    }
                    unionType.setOriginalMemberTypes(originalMemberTypes);

                    var poppedUnionType = compositeStack.pop();
                    assert poppedUnionType == unionType;

                    boolean isEnum = inputStream.readBoolean();
                    if (isEnum) {
                        readAndSetEnumSymbol(unionType, flags);
                    }

                    if (hasName) {
                        if (unionsPkgId.equals(env.pkgSymbol.pkgID)) {
                            return unionType;
                        } else {
                            pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(unionsPkgId));
                            if (pkgEnv != null) {
                                BType existingUnionType =
                                        symbolResolver.lookupSymbolInMainSpace(pkgEnv, unionName).type;
                                if (existingUnionType != symTable.noType) {
                                    return existingUnionType;
                                }
                            }
                        }
                    }
                    return unionType;
                case TypeTags.INTERSECTION:
                    BTypeSymbol intersectionTypeSymbol = Symbols.createTypeSymbol(SymTag.INTERSECTION_TYPE,
                                                                                  Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                                  Names.EMPTY, env.pkgSymbol.pkgID,
                                                                                  null, env.pkgSymbol,
                                                                                  symTable.builtinPos, COMPILED_SOURCE);
                    int intersectionMemberCount = inputStream.readInt();
                    LinkedHashSet<BType> constituentTypes = new LinkedHashSet<>(intersectionMemberCount);
                    for (int i = 0; i < intersectionMemberCount; i++) {
                        constituentTypes.add(readTypeFromCp());
                    }

                    IntersectableReferenceType effectiveType = (IntersectableReferenceType) readTypeFromCp();
                    return new BIntersectionType(intersectionTypeSymbol, constituentTypes, effectiveType, flags);
                case TypeTags.PACKAGE:
                    
                    break;
                case TypeTags.NONE:
                    return symTable.noType;
                case TypeTags.VOID:
                    
                    break;
                case TypeTags.XMLNS:
                    
                    break;
                case TypeTags.ANNOTATION:
                    
                    break;
                case TypeTags.SEMANTIC_ERROR:
                    
                    break;
                case TypeTags.ERROR:
                    pkgCpIndex = inputStream.readInt();
                    pkgId = getPackageId(pkgCpIndex);
                    BPackageSymbol owner = packageCache.getSymbol(pkgId);
                    
                    BTypeSymbol errorSymbol;
                    if (owner != null) {
                        errorSymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.EMPTY, owner.pkgID,
                                null, owner, symTable.builtinPos, COMPILED_SOURCE);
                    } else {
                        errorSymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.EMPTY,
                                env.pkgSymbol.pkgID, null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE);
                    }
                    BErrorType errorType = new BErrorType(errorSymbol);
                    addShapeCP(errorType, cpI);
                    compositeStack.push(errorType);
                    String errorName = getStringCPEntryValue(inputStream);
                    BType detailsType = readTypeFromCp();
                    errorType.detailType = detailsType;
                    errorType.flags = flags;
                    errorSymbol.type = errorType;
                    errorSymbol.pkgID = pkgId;
                    errorSymbol.name = names.fromString(errorName);
                    Object poppedErrorType = compositeStack.pop();
                    assert poppedErrorType == errorType;
                    if (!env.pkgSymbol.pkgID.equals(PackageID.ANNOTATIONS)
                            && Symbols.isFlagOn(flags, Flags.NATIVE)) {
                        
                        return symTable.errorType;
                    }
                    errorType.typeIdSet = readTypeIdSet(inputStream);
                    return errorType;
                case TypeTags.ITERATOR:
                    
                    break;
                case TypeTags.TUPLE:
                    BTypeSymbol tupleTypeSymbol = Symbols.createTypeSymbol(SymTag.TUPLE_TYPE,
                                                                           Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                           Names.EMPTY, env.pkgSymbol.pkgID, null,
                                                                           env.pkgSymbol.owner, symTable.builtinPos,
                                                                           COMPILED_SOURCE);
                    BTupleType bTupleType = new BTupleType(tupleTypeSymbol, null);
                    bTupleType.flags = flags;
                    int tupleMemberCount = inputStream.readInt();
                    List<BType> tupleMemberTypes = new ArrayList<>(tupleMemberCount);
                    for (int i = 0; i < tupleMemberCount; i++) {
                        tupleMemberTypes.add(readTypeFromCp());
                    }
                    bTupleType.tupleTypes = tupleMemberTypes;

                    if (inputStream.readBoolean()) {
                        bTupleType.restType = readTypeFromCp();
                    }

                    return bTupleType;
                case TypeTags.FUTURE:
                    BFutureType bFutureType = new BFutureType(TypeTags.FUTURE, null, symTable.futureType.tsymbol);
                    bFutureType.constraint = readTypeFromCp();
                    bFutureType.flags = flags;
                    return bFutureType;
                case TypeTags.FINITE:
                    String finiteTypeName = getStringCPEntryValue(inputStream);
                    var finiteTypeFlags = inputStream.readLong();
                    BTypeSymbol symbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, finiteTypeFlags,
                                                                  names.fromString(finiteTypeName), env.pkgSymbol.pkgID,
                                                                  null, env.pkgSymbol, symTable.builtinPos,
                                                                  COMPILED_SOURCE);
                    symbol.scope = new Scope(symbol);
                    BFiniteType finiteType = new BFiniteType(symbol);
                    finiteType.flags = flags;
                    symbol.type = finiteType;
                    int valueSpaceSize = inputStream.readInt();
                    for (int i = 0; i < valueSpaceSize; i++) {
                        defineValueSpace(inputStream, finiteType, this);
                    }
                    return finiteType;
                case TypeTags.OBJECT:
                    boolean service = inputStream.readByte() == 1;

                    pkgCpIndex = inputStream.readInt();
                    pkgId = getPackageId(pkgCpIndex);

                    String objName = getStringCPEntryValue(inputStream);
                    var objFlags = (inputStream.readBoolean() ? Flags.CLASS : 0) | Flags.PUBLIC;
                    objFlags = inputStream.readBoolean() ? objFlags | Flags.CLIENT : objFlags;
                    BObjectTypeSymbol objectSymbol;

                    if (Symbols.isFlagOn(objFlags, Flags.CLASS)) {
                        objectSymbol = Symbols.createClassSymbol(objFlags, names.fromString(objName),
                                                                 env.pkgSymbol.pkgID, null, env.pkgSymbol,
                                                                 symTable.builtinPos, COMPILED_SOURCE, false);
                    } else {
                        objectSymbol = Symbols.createObjectSymbol(objFlags, names.fromString(objName),
                                                                  env.pkgSymbol.pkgID, null, env.pkgSymbol,
                                                                  symTable.builtinPos, COMPILED_SOURCE);
                    }

                    objectSymbol.scope = new Scope(objectSymbol);
                    BObjectType objectType;
                    
                    objectType = new BObjectType(objectSymbol);

                    if (service) {
                        objectType.flags |= Flags.SERVICE;
                        objectSymbol.flags |= Flags.SERVICE;
                    }
                    if (isImmutable(flags)) {
                        objectSymbol.flags |= Flags.READONLY;
                    }
                    if (Symbols.isFlagOn(flags, Flags.ANONYMOUS)) {
                        objectSymbol.flags |= Flags.ANONYMOUS;
                    }
                    objectType.flags = flags;
                    objectSymbol.type = objectType;
                    addShapeCP(objectType, cpI);
                    compositeStack.push(objectType);
                    int fieldCount = inputStream.readInt();
                    for (int i = 0; i < fieldCount; i++) {
                        String fieldName = getStringCPEntryValue(inputStream);
                        var fieldFlags = inputStream.readLong();
                        var defaultable = inputStream.readBoolean();
                        byte[] docBytes = readDocBytes(inputStream);

                        BType fieldType = readTypeFromCp();
                        BVarSymbol objectVarSymbol = new BVarSymbol(fieldFlags, names.fromString(fieldName),
                                                                    objectSymbol.pkgID, fieldType,
                                                                    objectSymbol.scope.owner, symTable.builtinPos,
                                                                    COMPILED_SOURCE);
                        objectVarSymbol.isDefaultable = defaultable;
                        defineMarkDownDocAttachment(objectVarSymbol, docBytes);

                        BField structField = new BField(objectVarSymbol.name, null, objectVarSymbol);
                        objectType.fields.put(structField.name.value, structField);
                        objectSymbol.scope.define(objectVarSymbol.name, objectVarSymbol);
                    }
                    boolean generatedConstructorPresent = inputStream.readBoolean();
                    if (generatedConstructorPresent) {
                        ignoreAttachedFunc();
                    }
                    boolean constructorPresent = inputStream.readBoolean();
                    if (constructorPresent) {
                        ignoreAttachedFunc();
                    }
                    int funcCount = inputStream.readInt();
                    for (int i = 0; i < funcCount; i++) {
                        
                        if (isImmutable(objectSymbol.flags) && Symbols.isFlagOn(flags, Flags.ANONYMOUS)) {
                            populateIntersectionTypeReferencedFunctions(inputStream, objectSymbol);
                        } else {
                            ignoreAttachedFunc();
                        }
                    }

                    objectType.typeInclusions = readTypeInclusions();
                    objectType.typeIdSet = readTypeIdSet(inputStream);

                    Object poppedObjType = compositeStack.pop();
                    assert poppedObjType == objectType;

                    if (pkgId.equals(env.pkgSymbol.pkgID)) {
                        return objectType;
                    }

                    pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkgId));
                    return symbolResolver.lookupSymbolInMainSpace(pkgEnv, names.fromString(objName)).type;
                case TypeTags.BYTE_ARRAY:
                    
                    break;
                case TypeTags.FUNCTION_POINTER:
                    
                    break;
                case SERVICE_TYPE_TAG:
                    throw new AssertionError();
                case TypeTags.SIGNED32_INT:
                    return symTable.signed32IntType;
                case TypeTags.SIGNED16_INT:
                    return symTable.signed16IntType;
                case TypeTags.SIGNED8_INT:
                    return symTable.signed8IntType;
                case TypeTags.UNSIGNED32_INT:
                    return symTable.unsigned32IntType;
                case TypeTags.UNSIGNED16_INT:
                    return symTable.unsigned16IntType;
                case TypeTags.UNSIGNED8_INT:
                    return symTable.unsigned8IntType;
                case TypeTags.CHAR_STRING:
                    return symTable.charStringType;
                case TypeTags.XML_ELEMENT:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.xmlElementType) :
                            symTable.xmlElementType;
                case TypeTags.XML_PI:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.xmlPIType) : symTable.xmlPIType;
                case TypeTags.XML_COMMENT:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.xmlCommentType) :
                            symTable.xmlCommentType;
                case TypeTags.XML_TEXT:
                    return symTable.xmlTextType;
            }
            return null;
        }

Line commented on: if (pkg.equals(env.pkgSymbol.pkgID)) {

Revised code:
public BType readType(int cpI) throws IOException {
            byte tag = inputStream.readByte();
            Name name = names.fromString(getStringCPEntryValue(inputStream));
            var flags = inputStream.readLong();

            
            inputStream.readInt();

            switch (tag) {
                case TypeTags.INT:
                    return typeParamAnalyzer.getNominalType(symTable.intType, name, flags);
                case TypeTags.BYTE:
                    return typeParamAnalyzer.getNominalType(symTable.byteType, name, flags);
                case TypeTags.FLOAT:
                    return typeParamAnalyzer.getNominalType(symTable.floatType, name, flags);
                case TypeTags.DECIMAL:
                    return typeParamAnalyzer.getNominalType(symTable.decimalType, name, flags);
                case TypeTags.STRING:
                    return typeParamAnalyzer.getNominalType(symTable.stringType, name, flags);
                case TypeTags.BOOLEAN:
                    return typeParamAnalyzer.getNominalType(symTable.booleanType, name, flags);
                
                case TypeTags.JSON:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.jsonType) : symTable.jsonType;
                case TypeTags.XML:
                    BType constraintType = readTypeFromCp();
                    BXMLType mutableXmlType = new BXMLType(constraintType, symTable.xmlType.tsymbol);
                    if (Symbols.isFlagOn(flags, Flags.PARAMETERIZED)) {
                        mutableXmlType.flags |= Flags.PARAMETERIZED;
                    }
                    return isImmutable(flags) ? getEffectiveImmutableType(mutableXmlType) : mutableXmlType;
                case TypeTags.NIL:
                    return symTable.nilType;
                case TypeTags.NEVER:
                    return symTable.neverType;
                case TypeTags.ANYDATA:
                    if (name.getValue().equals(Names.ANYDATA.getValue())) {
                        name = Names.EMPTY;
                    }
                    BType anydataNominalType = typeParamAnalyzer.getNominalType(symTable.anydataType, name, flags);
                    return isImmutable(flags) ? getEffectiveImmutableType(anydataNominalType,
                            symTable.anydataType.tsymbol.pkgID,
                            symTable.anydataType.tsymbol.owner) :
                            anydataNominalType;
                case TypeTags.RECORD:
                    int pkgCpIndex = inputStream.readInt();
                    PackageID pkgId = getPackageId(pkgCpIndex);

                    String recordName = getStringCPEntryValue(inputStream);
                     BRecordTypeSymbol recordSymbol = Symbols.createRecordSymbol(Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                                names.fromString(recordName),
                                                                                env.pkgSymbol.pkgID, null,
                                                                                env.pkgSymbol, symTable.builtinPos,
                                                                                COMPILED_SOURCE);
                    recordSymbol.flags |= flags;
                    recordSymbol.scope = new Scope(recordSymbol);
                    BRecordType recordType = new BRecordType(recordSymbol, recordSymbol.flags);
                    recordType.flags |= flags;

                    if (isImmutable(flags)) {
                        recordSymbol.flags |= Flags.READONLY;
                    }

                    recordSymbol.type = recordType;

                    compositeStack.push(recordType);
                    addShapeCP(recordType, cpI);

                    recordType.sealed = inputStream.readBoolean();
                    recordType.restFieldType = readTypeFromCp();

                    int recordFields = inputStream.readInt();
                    for (int i = 0; i < recordFields; i++) {
                        String fieldName = getStringCPEntryValue(inputStream);
                        var fieldFlags = inputStream.readLong();

                        byte[] docBytes = readDocBytes(inputStream);

                        BType fieldType = readTypeFromCp();

                        BVarSymbol varSymbol = new BVarSymbol(fieldFlags, names.fromString(fieldName),
                                                              recordSymbol.pkgID, fieldType,
                                                              recordSymbol.scope.owner, symTable.builtinPos,
                                                              COMPILED_SOURCE);

                        defineMarkDownDocAttachment(varSymbol, docBytes);

                        BField structField = new BField(varSymbol.name, varSymbol.pos, varSymbol);
                        recordType.fields.put(structField.name.value, structField);
                        recordSymbol.scope.define(varSymbol.name, varSymbol);
                    }

                    boolean isInitAvailable = inputStream.readByte() == 1;
                    if (isInitAvailable) {
                        
                        String recordInitFuncName = getStringCPEntryValue(inputStream);
                        var recordInitFuncFlags = inputStream.readLong();
                        BInvokableType recordInitFuncType = (BInvokableType) readTypeFromCp();
                        Name initFuncName = names.fromString(recordInitFuncName);
                        boolean isNative = Symbols.isFlagOn(recordInitFuncFlags, Flags.NATIVE);
                        BInvokableSymbol recordInitFuncSymbol =
                                Symbols.createFunctionSymbol(recordInitFuncFlags, initFuncName,
                                                             initFuncName, env.pkgSymbol.pkgID, recordInitFuncType,
                                                             env.pkgSymbol, isNative, symTable.builtinPos,
                                                             COMPILED_SOURCE);
                        recordInitFuncSymbol.retType = recordInitFuncType.retType;
                        
                        recordSymbol.initializerFunc = new BAttachedFunction(initFuncName, recordInitFuncSymbol,
                                                                             recordInitFuncType, symTable.builtinPos);
                        recordSymbol.scope.define(initFuncName, recordInitFuncSymbol);
                    }

                    recordType.typeInclusions = readTypeInclusions();



                    Object poppedRecordType = compositeStack.pop();
                    assert poppedRecordType == recordType;

                    if (pkgId.equals(env.pkgSymbol.pkgID)) {
                        return recordType;
                    }

                    SymbolEnv pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkgId));
                    return symbolResolver.lookupSymbolInMainSpace(pkgEnv, names.fromString(recordName)).type;
                case TypeTags.TYPEDESC:
                    BTypedescType typedescType = new BTypedescType(null, symTable.typeDesc.tsymbol);
                    typedescType.constraint = readTypeFromCp();
                    typedescType.flags = flags;
                    return typedescType;
                case TypeTags.TYPEREFDESC:
                    int pkgIndex = inputStream.readInt();
                    PackageID pkg = getPackageId(pkgIndex);

                    String typeDefName = getStringCPEntryValue(inputStream);
                    BTypeSymbol typeSymbol = Symbols.createTypeSymbol(SymTag.TYPE_REF,
                            Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                            names.fromString(typeDefName), env.pkgSymbol.pkgID, null, env.pkgSymbol,
                            symTable.builtinPos, COMPILED_SOURCE);
                    BTypeReferenceType typeReferenceType = new BTypeReferenceType(null, typeSymbol, flags);
                    addShapeCP(typeReferenceType, cpI);
                    compositeStack.push(typeReferenceType);
                    typeReferenceType.referredType = readTypeFromCp();

                    Object poppedRefType = compositeStack.pop();
                    assert poppedRefType == typeReferenceType;
                    return typeReferenceType;
                case TypeTags.PARAMETERIZED_TYPE:
                    BParameterizedType type = new BParameterizedType(null, null, null, name, -1);
                    type.paramValueType = readTypeFromCp();
                    type.flags = flags;
                    type.paramIndex = inputStream.readInt();
                    return type;
                case TypeTags.STREAM:
                    BStreamType bStreamType = new BStreamType(TypeTags.STREAM, null, null, symTable.streamType.tsymbol);
                    bStreamType.constraint = readTypeFromCp();
                    bStreamType.completionType = readTypeFromCp();
                    bStreamType.flags = flags;
                    return bStreamType;
                case TypeTags.TABLE:
                    BTableType bTableType = new BTableType(TypeTags.TABLE, null, symTable.tableType.tsymbol, flags);
                    bTableType.constraint = readTypeFromCp();

                    boolean hasFieldNameList = inputStream.readByte() == 1;
                    if (hasFieldNameList) {
                        int fieldNameListSize = inputStream.readInt();
                        bTableType.fieldNameList = new ArrayList<>(fieldNameListSize);
                        for (int i = 0; i < fieldNameListSize; i++) {
                            String fieldName = getStringCPEntryValue(inputStream);
                            bTableType.fieldNameList.add(fieldName);
                        }
                    }

                    boolean hasKeyConstraint = inputStream.readByte() == 1;
                    if (hasKeyConstraint) {
                        bTableType.keyTypeConstraint = readTypeFromCp();
                        if (bTableType.keyTypeConstraint.tsymbol == null) {
                            bTableType.keyTypeConstraint.tsymbol =
                                    Symbols.createTypeSymbol(SymTag.TYPE, Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                             Names.EMPTY, env.pkgSymbol.pkgID,
                                                             bTableType.keyTypeConstraint, env.pkgSymbol.owner,
                                                             symTable.builtinPos, COMPILED_SOURCE);
                        }
                    }
                    return bTableType;
                case TypeTags.MAP:
                    BMapType bMapType = new BMapType(TypeTags.MAP, null, symTable.mapType.tsymbol, flags);
                    bMapType.constraint = readTypeFromCp();
                    return bMapType;
                case TypeTags.INVOKABLE:
                    BInvokableType bInvokableType = new BInvokableType(null, null, null, null);
                    bInvokableType.flags = flags;
                    if (inputStream.readBoolean()) {
                        return bInvokableType;
                    }
                    int paramCount = inputStream.readInt();
                    List<BType> paramTypes = new ArrayList<>(paramCount);
                    for (int i = 0; i < paramCount; i++) {
                        paramTypes.add(readTypeFromCp());
                    }
                    bInvokableType.paramTypes = paramTypes;
                    if (inputStream.readBoolean()) { 
                        bInvokableType.restType = readTypeFromCp();
                    }
                    bInvokableType.retType = readTypeFromCp();
                    return bInvokableType;
                
                case TypeTags.ANY:
                    BType anyNominalType = typeParamAnalyzer.getNominalType(symTable.anyType, name, flags);
                    return isImmutable(flags) ? getEffectiveImmutableType(anyNominalType,
                            symTable.anyType.tsymbol.pkgID,
                            symTable.anyType.tsymbol.owner) :
                            anyNominalType;
                case TypeTags.HANDLE:
                    return symTable.handleType;
                case TypeTags.READONLY:
                    return symTable.readonlyType;
                case TypeTags.ENDPOINT:
                    
                    break;
                case TypeTags.ARRAY:
                    byte state = inputStream.readByte();
                    int size = inputStream.readInt();
                    BTypeSymbol arrayTypeSymbol = Symbols.createTypeSymbol(SymTag.ARRAY_TYPE,
                                                                           Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                           Names.EMPTY, env.pkgSymbol.pkgID, null,
                                                                           env.pkgSymbol.owner, symTable.builtinPos,
                                                                           COMPILED_SOURCE);
                    BArrayType bArrayType = new BArrayType(null, arrayTypeSymbol, size, BArrayState.valueOf(state),
                            flags);
                    bArrayType.eType = readTypeFromCp();
                    return bArrayType;
                case TypeTags.UNION:
                    boolean isCyclic = inputStream.readByte() == 1;
                    boolean hasName = inputStream.readByte() == 1;
                    PackageID unionsPkgId = env.pkgSymbol.pkgID;
                    Name unionName = Names.EMPTY;
                    if (hasName) {
                        pkgCpIndex = inputStream.readInt();
                        unionsPkgId = getPackageId(pkgCpIndex);
                        String unionNameStr = getStringCPEntryValue(inputStream);
                        unionName = names.fromString(unionNameStr);
                    }
                    BTypeSymbol unionTypeSymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE,
                            Flags.asMask(EnumSet.of(Flag.PUBLIC)), unionName, unionsPkgId,
                            null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE);

                    int unionMemberCount = inputStream.readInt();
                    BUnionType unionType = BUnionType.create(unionTypeSymbol, new LinkedHashSet<>(unionMemberCount));
                    unionType.name = unionName;

                    addShapeCP(unionType, cpI);
                    compositeStack.push(unionType);

                    unionType.flags = flags;
                    unionType.isCyclic = isCyclic;
                    for (int i = 0; i < unionMemberCount; i++) {
                        unionType.add(readTypeFromCp());
                    }

                    int unionOriginalMemberCount = inputStream.readInt();
                    LinkedHashSet<BType> originalMemberTypes = new LinkedHashSet<>(unionOriginalMemberCount);
                    for (int i = 0; i < unionOriginalMemberCount; i++) {
                        originalMemberTypes.add(readTypeFromCp());
                    }
                    unionType.setOriginalMemberTypes(originalMemberTypes);

                    var poppedUnionType = compositeStack.pop();
                    assert poppedUnionType == unionType;

                    boolean isEnum = inputStream.readBoolean();
                    if (isEnum) {
                        readAndSetEnumSymbol(unionType, flags);
                    }

                    if (hasName) {
                        if (unionsPkgId.equals(env.pkgSymbol.pkgID)) {
                            return unionType;
                        } else {
                            pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(unionsPkgId));
                            if (pkgEnv != null) {
                                BType existingUnionType =
                                        symbolResolver.lookupSymbolInMainSpace(pkgEnv, unionName).type;
                                if (existingUnionType != symTable.noType) {
                                    return existingUnionType;
                                }
                            }
                        }
                    }
                    return unionType;
                case TypeTags.INTERSECTION:
                    BTypeSymbol intersectionTypeSymbol = Symbols.createTypeSymbol(SymTag.INTERSECTION_TYPE,
                                                                                  Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                                  Names.EMPTY, env.pkgSymbol.pkgID,
                                                                                  null, env.pkgSymbol,
                                                                                  symTable.builtinPos, COMPILED_SOURCE);
                    int intersectionMemberCount = inputStream.readInt();
                    LinkedHashSet<BType> constituentTypes = new LinkedHashSet<>(intersectionMemberCount);
                    for (int i = 0; i < intersectionMemberCount; i++) {
                        constituentTypes.add(readTypeFromCp());
                    }

                    IntersectableReferenceType effectiveType = (IntersectableReferenceType) readTypeFromCp();
                    return new BIntersectionType(intersectionTypeSymbol, constituentTypes, effectiveType, flags);
                case TypeTags.PACKAGE:
                    
                    break;
                case TypeTags.NONE:
                    return symTable.noType;
                case TypeTags.VOID:
                    
                    break;
                case TypeTags.XMLNS:
                    
                    break;
                case TypeTags.ANNOTATION:
                    
                    break;
                case TypeTags.SEMANTIC_ERROR:
                    
                    break;
                case TypeTags.ERROR:
                    pkgCpIndex = inputStream.readInt();
                    pkgId = getPackageId(pkgCpIndex);
                    BPackageSymbol owner = packageCache.getSymbol(pkgId);
                    
                    BTypeSymbol errorSymbol;
                    if (owner != null) {
                        errorSymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.EMPTY, owner.pkgID,
                                null, owner, symTable.builtinPos, COMPILED_SOURCE);
                    } else {
                        errorSymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.EMPTY,
                                env.pkgSymbol.pkgID, null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE);
                    }
                    BErrorType errorType = new BErrorType(errorSymbol);
                    addShapeCP(errorType, cpI);
                    compositeStack.push(errorType);
                    String errorName = getStringCPEntryValue(inputStream);
                    BType detailsType = readTypeFromCp();
                    errorType.detailType = detailsType;
                    errorType.flags = flags;
                    errorSymbol.type = errorType;
                    errorSymbol.pkgID = pkgId;
                    errorSymbol.name = names.fromString(errorName);
                    Object poppedErrorType = compositeStack.pop();
                    assert poppedErrorType == errorType;
                    if (!env.pkgSymbol.pkgID.equals(PackageID.ANNOTATIONS)
                            && Symbols.isFlagOn(flags, Flags.NATIVE)) {
                        
                        return symTable.errorType;
                    }
                    errorType.typeIdSet = readTypeIdSet(inputStream);
                    return errorType;
                case TypeTags.ITERATOR:
                    
                    break;
                case TypeTags.TUPLE:
                    BTypeSymbol tupleTypeSymbol = Symbols.createTypeSymbol(SymTag.TUPLE_TYPE,
                                                                           Flags.asMask(EnumSet.of(Flag.PUBLIC)),
                                                                           Names.EMPTY, env.pkgSymbol.pkgID, null,
                                                                           env.pkgSymbol.owner, symTable.builtinPos,
                                                                           COMPILED_SOURCE);
                    BTupleType bTupleType = new BTupleType(tupleTypeSymbol, null);
                    bTupleType.flags = flags;
                    int tupleMemberCount = inputStream.readInt();
                    List<BType> tupleMemberTypes = new ArrayList<>(tupleMemberCount);
                    for (int i = 0; i < tupleMemberCount; i++) {
                        tupleMemberTypes.add(readTypeFromCp());
                    }
                    bTupleType.tupleTypes = tupleMemberTypes;

                    if (inputStream.readBoolean()) {
                        bTupleType.restType = readTypeFromCp();
                    }

                    return bTupleType;
                case TypeTags.FUTURE:
                    BFutureType bFutureType = new BFutureType(TypeTags.FUTURE, null, symTable.futureType.tsymbol);
                    bFutureType.constraint = readTypeFromCp();
                    bFutureType.flags = flags;
                    return bFutureType;
                case TypeTags.FINITE:
                    String finiteTypeName = getStringCPEntryValue(inputStream);
                    var finiteTypeFlags = inputStream.readLong();
                    BTypeSymbol symbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, finiteTypeFlags,
                                                                  names.fromString(finiteTypeName), env.pkgSymbol.pkgID,
                                                                  null, env.pkgSymbol, symTable.builtinPos,
                                                                  COMPILED_SOURCE);
                    symbol.scope = new Scope(symbol);
                    BFiniteType finiteType = new BFiniteType(symbol);
                    finiteType.flags = flags;
                    symbol.type = finiteType;
                    int valueSpaceSize = inputStream.readInt();
                    for (int i = 0; i < valueSpaceSize; i++) {
                        defineValueSpace(inputStream, finiteType, this);
                    }
                    return finiteType;
                case TypeTags.OBJECT:
                    boolean service = inputStream.readByte() == 1;

                    pkgCpIndex = inputStream.readInt();
                    pkgId = getPackageId(pkgCpIndex);

                    String objName = getStringCPEntryValue(inputStream);
                    var objFlags = (inputStream.readBoolean() ? Flags.CLASS : 0) | Flags.PUBLIC;
                    objFlags = inputStream.readBoolean() ? objFlags | Flags.CLIENT : objFlags;
                    BObjectTypeSymbol objectSymbol;

                    if (Symbols.isFlagOn(objFlags, Flags.CLASS)) {
                        objectSymbol = Symbols.createClassSymbol(objFlags, names.fromString(objName),
                                                                 env.pkgSymbol.pkgID, null, env.pkgSymbol,
                                                                 symTable.builtinPos, COMPILED_SOURCE, false);
                    } else {
                        objectSymbol = Symbols.createObjectSymbol(objFlags, names.fromString(objName),
                                                                  env.pkgSymbol.pkgID, null, env.pkgSymbol,
                                                                  symTable.builtinPos, COMPILED_SOURCE);
                    }

                    objectSymbol.scope = new Scope(objectSymbol);
                    BObjectType objectType;
                    
                    objectType = new BObjectType(objectSymbol);

                    if (service) {
                        objectType.flags |= Flags.SERVICE;
                        objectSymbol.flags |= Flags.SERVICE;
                    }
                    if (isImmutable(flags)) {
                        objectSymbol.flags |= Flags.READONLY;
                    }
                    if (Symbols.isFlagOn(flags, Flags.ANONYMOUS)) {
                        objectSymbol.flags |= Flags.ANONYMOUS;
                    }
                    objectType.flags = flags;
                    objectSymbol.type = objectType;
                    addShapeCP(objectType, cpI);
                    compositeStack.push(objectType);
                    int fieldCount = inputStream.readInt();
                    for (int i = 0; i < fieldCount; i++) {
                        String fieldName = getStringCPEntryValue(inputStream);
                        var fieldFlags = inputStream.readLong();
                        var defaultable = inputStream.readBoolean();
                        byte[] docBytes = readDocBytes(inputStream);

                        BType fieldType = readTypeFromCp();
                        BVarSymbol objectVarSymbol = new BVarSymbol(fieldFlags, names.fromString(fieldName),
                                                                    objectSymbol.pkgID, fieldType,
                                                                    objectSymbol.scope.owner, symTable.builtinPos,
                                                                    COMPILED_SOURCE);
                        objectVarSymbol.isDefaultable = defaultable;
                        defineMarkDownDocAttachment(objectVarSymbol, docBytes);

                        BField structField = new BField(objectVarSymbol.name, null, objectVarSymbol);
                        objectType.fields.put(structField.name.value, structField);
                        objectSymbol.scope.define(objectVarSymbol.name, objectVarSymbol);
                    }
                    boolean generatedConstructorPresent = inputStream.readBoolean();
                    if (generatedConstructorPresent) {
                        ignoreAttachedFunc();
                    }
                    boolean constructorPresent = inputStream.readBoolean();
                    if (constructorPresent) {
                        ignoreAttachedFunc();
                    }
                    int funcCount = inputStream.readInt();
                    for (int i = 0; i < funcCount; i++) {
                        
                        if (isImmutable(objectSymbol.flags) && Symbols.isFlagOn(flags, Flags.ANONYMOUS)) {
                            populateIntersectionTypeReferencedFunctions(inputStream, objectSymbol);
                        } else {
                            ignoreAttachedFunc();
                        }
                    }

                    objectType.typeInclusions = readTypeInclusions();
                    objectType.typeIdSet = readTypeIdSet(inputStream);

                    Object poppedObjType = compositeStack.pop();
                    assert poppedObjType == objectType;

                    if (pkgId.equals(env.pkgSymbol.pkgID)) {
                        return objectType;
                    }

                    pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkgId));
                    return symbolResolver.lookupSymbolInMainSpace(pkgEnv, names.fromString(objName)).type;
                case TypeTags.BYTE_ARRAY:
                    
                    break;
                case TypeTags.FUNCTION_POINTER:
                    
                    break;
                case SERVICE_TYPE_TAG:
                    throw new AssertionError();
                case TypeTags.SIGNED32_INT:
                    return symTable.signed32IntType;
                case TypeTags.SIGNED16_INT:
                    return symTable.signed16IntType;
                case TypeTags.SIGNED8_INT:
                    return symTable.signed8IntType;
                case TypeTags.UNSIGNED32_INT:
                    return symTable.unsigned32IntType;
                case TypeTags.UNSIGNED16_INT:
                    return symTable.unsigned16IntType;
                case TypeTags.UNSIGNED8_INT:
                    return symTable.unsigned8IntType;
                case TypeTags.CHAR_STRING:
                    return symTable.charStringType;
                case TypeTags.XML_ELEMENT:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.xmlElementType) :
                            symTable.xmlElementType;
                case TypeTags.XML_PI:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.xmlPIType) : symTable.xmlPIType;
                case TypeTags.XML_COMMENT:
                    return isImmutable(flags) ? getEffectiveImmutableType(symTable.xmlCommentType) :
                            symTable.xmlCommentType;
                case TypeTags.XML_TEXT:
                    return symTable.xmlTextType;
            }
            return null;
        }