diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 294aca47..45b8f984 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -1228,6 +1228,8 @@ const char* Beefy::BfTokenToString(BfToken token) return "abstract"; case BfToken_AlignOf: return "alignof"; + case BfToken_AllocType: + return "alloctype"; case BfToken_Append: return "append"; case BfToken_As: diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index f4b8e8e3..5b715e72 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -105,6 +105,7 @@ enum BfToken : uint8 BfToken_None, BfToken_Abstract, BfToken_AlignOf, + BfToken_AllocType, BfToken_Append, BfToken_As, BfToken_Asm, diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index d78b583a..b2f8c82d 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -315,13 +315,24 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is { SetAndRestoreValue prevIgnoreClassifying(mModule->mIsInsideAutoComplete, true); + auto _FixType = [](const BfTypedValue& typedValue) + { + if ((typedValue.mType != NULL) && (typedValue.mType->IsAllocType())) + { + BfTypedValue ret = typedValue; + ret.mType = ret.mType->GetUnderlyingType(); + return ret; + } + return typedValue; + }; + if (auto typeRef = BfNodeDynCast(node)) { auto type = mModule->ResolveTypeRef(typeRef); if (type != NULL) { *isStatic = true; - return BfTypedValue(type); + return _FixType(BfTypedValue(type)); } if (auto namedTypeRef = BfNodeDynCast(typeRef)) @@ -330,7 +341,7 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is auto identifierResult = exprEvaluator.LookupIdentifier(namedTypeRef->mNameNode); if (identifierResult) return identifierResult; - return exprEvaluator.GetResult(); // We need 'GetResult' to read property values + return _FixType(exprEvaluator.GetResult()); // We need 'GetResult' to read property values } else if (auto qualifiedTypeRef = BfNodeDynCast(typeRef)) { @@ -356,7 +367,7 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is if (!fieldResult) // Was property? fieldResult = exprEvaluator.GetResult(); *isStatic = false; - return fieldResult; + return _FixType(fieldResult); } } } @@ -368,7 +379,7 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is if (!identifierResult) identifierResult = exprEvaluator.GetResult(); if (identifierResult) - return identifierResult; + return _FixType(identifierResult); if (auto qualifiedIdentifier = BfNodeDynCast(node)) { @@ -388,7 +399,7 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is return fieldResult; auto result = exprEvaluator.GetResult(); if (result) - return result; + return _FixType(result); } } @@ -396,22 +407,22 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is if (type != NULL) { *isStatic = true; - return BfTypedValue(type); + return _FixType(BfTypedValue(type)); } } else if (auto memberRefExpr = BfNodeDynCast(node)) { - return mModule->CreateValueFromExpression(memberRefExpr, expectingType, evalExprFlags); + return _FixType(mModule->CreateValueFromExpression(memberRefExpr, expectingType, evalExprFlags)); } else if (auto parenExpr = BfNodeDynCast(node)) { // Don't pass BfEvalExprFlags_IgnoreNullConditional, since parenExprs end nullable chains and we actually // DO want the nullable at this point - return mModule->CreateValueFromExpression(parenExpr); + return _FixType(mModule->CreateValueFromExpression(parenExpr)); } else if (auto targetExpr = BfNodeDynCast(node)) { - return mModule->CreateValueFromExpression(targetExpr, NULL, evalExprFlags); + return _FixType(mModule->CreateValueFromExpression(targetExpr, NULL, evalExprFlags)); } return BfTypedValue(); @@ -1550,8 +1561,8 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken // Statics, inner types - auto checkType = targetValue.mType; - + auto checkType = targetValue.mType; + if (checkType->IsGenericParam()) { auto genericParamType = (BfGenericParamType*)checkType; diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index b8b07542..08e92bfa 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -372,7 +372,7 @@ public: HashSet mQueuedSpecializedMethodRebuildTypes; - BfAllocPool mPointerTypePool; + BfAllocPool mPointerTypePool; BfAllocPool mArrayTypePool; BfAllocPool mSizedArrayTypePool; BfAllocPool mUnknownSizedArrayTypePool; @@ -380,7 +380,7 @@ public: BfAllocPool mTupleTypePool; BfAllocPool mAliasTypePool; BfAllocPool mRefTypePool; - BfAllocPool mRetTypeTypePool; + BfAllocPool mModifiedTypeTypePool; BfAllocPool mGenericTypeInstancePool; BfAllocPool mArrayTypeInstancePool; BfAllocPool mGenericParamTypePool; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 5734716e..37897150 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -7997,8 +7997,8 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode* if (!mResult) return; - //if (mResult.mType->IsVar()) - //ResolveGenericType(); + if (mResult.mType->IsAllocType()) + mResult.mType = mResult.mType->GetUnderlyingType(); auto origResult = mResult; auto lookupType = BindGenericType(nameNode, mResult.mType); @@ -8040,7 +8040,7 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode* { mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType, true); return; - } + } if (!mResult.mType->IsTypeInstance()) { @@ -12272,7 +12272,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) if (resolvedTypeRef->IsVar()) { // Leave as a var - } + } else if ((!resolvedTypeRef->IsObjectOrInterface()) && (!resolvedTypeRef->IsGenericParam())) { resultType = mModule->CreatePointerType(resolvedTypeRef); @@ -12289,26 +12289,33 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) bool isGenericParam = unresolvedTypeRef->IsGenericParam(); if (resolvedTypeRef->IsGenericParam()) { - auto genericConstraint = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef); - if (genericConstraint->mTypeConstraint == NULL) + auto genericParam = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef); + if (genericParam->mTypeConstraint == NULL) { - if ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_New) == 0) + if ((genericParam->mGenericParamFlags & BfGenericParamFlag_New) == 0) { - mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericConstraint->GetGenericParamDef()->mName.c_str()), objCreateExpr->mTypeRef); + mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericParam->GetName().c_str()), objCreateExpr->mTypeRef); } if (objCreateExpr->mArguments.size() != 0) { - mModule->Fail(StrFormat("Only default parameterless constructors can be called on generic argument '%s'", genericConstraint->GetGenericParamDef()->mName.c_str()), objCreateExpr->mTypeRef); + mModule->Fail(StrFormat("Only default parameterless constructors can be called on generic argument '%s'", genericParam->GetName().c_str()), objCreateExpr->mTypeRef); } } - resultType = resolvedTypeRef; - bool isValueType = ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_Struct) != 0); - if (genericConstraint->mTypeConstraint != NULL) - isValueType = genericConstraint->mTypeConstraint->IsValueType(); - - if (isValueType) - resultType = mModule->CreatePointerType(resultType); + if (((genericParam->mTypeConstraint != NULL) && (genericParam->mTypeConstraint->IsValueType())) || + ((genericParam->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0)) + { + resultType = mModule->CreatePointerType(resolvedTypeRef); + } + else if (((genericParam->mTypeConstraint != NULL) && (!genericParam->mTypeConstraint->IsValueType())) || + ((genericParam->mGenericParamFlags & (BfGenericParamFlag_Class)) != 0)) + { + // Leave as 'T' + resultType = resolvedTypeRef; + } + else + resultType = mModule->CreateModifiedTypeType(resolvedTypeRef, BfToken_AllocType); + mResult.mType = resultType; if (typeInstance == NULL) @@ -14549,6 +14556,9 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m bool mayBeSkipCall = false; if (thisValue.mType != NULL) { + if (thisValue.mType->IsAllocType()) + thisValue.mType = thisValue.mType->GetUnderlyingType(); + auto checkTypeInst = thisValue.mType->ToTypeInstance(); while (checkTypeInst != NULL) { diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index af9b3d04..f0363f04 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -555,6 +555,8 @@ void BfGNUMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType BfModifiedTypeType* retTypeType = (BfModifiedTypeType*)type; if (retTypeType->mModifiedKind == BfToken_RetType) name += "U7rettype"; + else if (retTypeType->mModifiedKind == BfToken_AllocType) + name += "U5alloc"; else if (retTypeType->mModifiedKind == BfToken_Nullable) name += "U8nullable"; else @@ -1621,6 +1623,8 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType* auto retType = (BfModifiedTypeType*)type; if (retType->mModifiedKind == BfToken_RetType) name += "rettype$"; + else if (retType->mModifiedKind == BfToken_AllocType) + name += "alloc$"; else if (retType->mModifiedKind == BfToken_Nullable) name += "nullable$"; else diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index e782d0ab..3392886f 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -5488,13 +5488,13 @@ BfRefType* BfModule::CreateRefType(BfType* resolvedTypeRef, BfRefType::RefKind r BfModifiedTypeType* BfModule::CreateModifiedTypeType(BfType* resolvedTypeRef, BfToken modifiedKind) { - auto retTypeType = mContext->mRetTypeTypePool.Get(); + auto retTypeType = mContext->mModifiedTypeTypePool.Get(); retTypeType->mContext = mContext; retTypeType->mModifiedKind = modifiedKind; retTypeType->mElementType = resolvedTypeRef; auto resolvedRetTypeType = ResolveType(retTypeType); if (resolvedRetTypeType != retTypeType) - mContext->mRetTypeTypePool.GiveBack(retTypeType); + mContext->mModifiedTypeTypePool.GiveBack(retTypeType); return (BfModifiedTypeType*)resolvedRetTypeType; } @@ -8121,6 +8121,23 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula return ResolveTypeResult(typeRef, resolvedType, populateType, resolveFlags); } } + else if (retTypeTypeRef->mRetTypeToken->mToken == BfToken_AllocType) + { + BfType* resolvedType = NULL; + if (retTypeTypeRef->mElementType != NULL) + { + resolvedType = ResolveTypeRef(retTypeTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue); + if (resolvedType != NULL) + { + if (resolvedType->IsGenericParam()) + resolvedType = CreateModifiedTypeType(resolvedType, BfToken_AllocType); + else if (resolvedType->IsValueType()) + resolvedType = CreatePointerType(resolvedType); + } + } + + return ResolveTypeResult(typeRef, resolvedType, populateType, resolveFlags); + } else if (retTypeTypeRef->mRetTypeToken->mToken == BfToken_Nullable) { bool allowThrough = false; diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index c7016306..d7c5c789 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -2628,6 +2628,10 @@ void BfParser::NextToken(int endIdx) if ((!mCompatMode) && (SrcPtrHasToken("abstract"))) mToken = BfToken_Abstract; break; + case TOKEN_HASH('a', 'l', 'l', 'o'): + if (SrcPtrHasToken("alloctype")) + mToken = BfToken_AllocType; + break; case TOKEN_HASH('a', 'l', 'i', 'g'): if (SrcPtrHasToken("alignof")) mToken = BfToken_AlignOf; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index ae2a733f..105bc94c 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -267,7 +267,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int* { // Tuple start } - else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) + else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) { // Decltype start } @@ -774,7 +774,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int* checkIdx = funcEndNode; continue; } - else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) + else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) { int endNodeIdx = checkIdx + 1; @@ -4216,6 +4216,7 @@ bool BfReducer::IsTerminatingExpression(BfAstNode* node) break; case BfToken_As: + case BfToken_AllocType: case BfToken_Append: case BfToken_Default: case BfToken_Is: @@ -4626,7 +4627,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF return elementType; } } - else if ((token == BfToken_RetType) || (token == BfToken_Nullable)) + else if ((token == BfToken_AllocType) || (token == BfToken_Nullable) || (token == BfToken_RetType)) { auto retTypeTypeRef = mAlloc->Alloc(); ReplaceNode(firstNode, retTypeTypeRef); @@ -6373,6 +6374,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth) } else if ((token == BfToken_Var) || (token == BfToken_Let) || + (token == BfToken_AllocType) || (token == BfToken_RetType) || (token == BfToken_Nullable) || (token == BfToken_Decltype) || diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 7c07743b..a91b98dc 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2452,7 +2452,7 @@ BfResolvedTypeSet::~BfResolvedTypeSet() #define HASH_VAL_REF 3 #define HASH_VAL_OUT 4 #define HASH_VAL_MUT 5 -#define HASH_RETTYPE 6 +#define HASH_MODTYPE 6 #define HASH_CONCRETE_INTERFACE 7 #define HASH_SIZED_ARRAY 8 #define HASH_CONSTTYPE 9 @@ -2613,7 +2613,7 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) BfPointerType* pointerType = (BfPointerType*) type; int elemHash = Hash(pointerType->mElementType, ctx) ^ HASH_VAL_PTR; return (elemHash << 5) - elemHash; - } + } else if (type->IsGenericParam()) { auto genericParam = (BfGenericParamType*)type; @@ -2627,8 +2627,8 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) } else if (type->IsModifiedTypeType()) { - auto retTypeType = (BfModifiedTypeType*)type; - int elemHash = Hash(retTypeType->mElementType, ctx) ^ HASH_RETTYPE; + auto modifiedTypeType = (BfModifiedTypeType*)type; + int elemHash = Hash(modifiedTypeType->mElementType, ctx) ^ HASH_MODTYPE + (int)modifiedTypeType->mModifiedKind; return (elemHash << 5) - elemHash; } else if (type->IsConcreteInterfaceType()) @@ -3095,7 +3095,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash return Hash(type, ctx, flags); } - int elemHash = Hash(retTypeTypeRef->mElementType, ctx) ^ HASH_RETTYPE; + int elemHash = Hash(retTypeTypeRef->mElementType, ctx) ^ HASH_MODTYPE + retTypeTypeRef->mRetTypeToken->mToken; return (elemHash << 5) - elemHash; } else if (auto resolvedTypeRef = BfNodeDynCastExact(typeRef)) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index c2ab7da6..bbbf7087 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -538,6 +538,7 @@ public: virtual bool IsChar() { return false; } virtual bool IsFloat() { return false; } virtual bool IsPointer() { return false; } + virtual bool IsAllocType() { return false; } virtual bool IsIntPtrable() { return false; } virtual bool IsRef() { return false; } virtual bool IsGenericParam() { return false; } @@ -999,8 +1000,10 @@ public: virtual bool IsValuelessType() override { return true; } virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType(); } + virtual bool IsUnspecializedTypeVariation() override { return mElementType->IsUnspecializedType(); } virtual bool IsReified() override { return mElementType->IsReified(); } virtual bool IsDependentOnUnderlyingType() override { return true; } + virtual bool IsAllocType() { return mModifiedKind == BfToken_AllocType; } virtual BfType* GetUnderlyingType() override { return mElementType; } }; diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 268df78b..3b4254e9 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3807,6 +3807,8 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) if (!val) return; + if (val.mType->IsAllocType()) + val.mType = val.mType->GetUnderlyingType(); BfGenericParamType* genericType = NULL; if (val.mType->IsGenericParam())