mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Added nullable(T), Result<T> can use null conditionals
This commit is contained in:
parent
336226d686
commit
68bf7bc801
19 changed files with 343 additions and 210 deletions
|
@ -59,6 +59,15 @@ namespace System
|
|||
return default(T);
|
||||
}
|
||||
|
||||
public static nullable(T) operator?(Self val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case .Ok(let inner): return inner;
|
||||
case .Err: return null;
|
||||
}
|
||||
}
|
||||
|
||||
[SkipCall]
|
||||
public void Dispose()
|
||||
{
|
||||
|
@ -151,6 +160,15 @@ namespace System
|
|||
return default(T);
|
||||
}
|
||||
|
||||
public static nullable(T) operator?(Self val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case .Ok(let inner): return inner;
|
||||
case .Err: return null;
|
||||
}
|
||||
}
|
||||
|
||||
[SkipCall]
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
@ -50,6 +50,15 @@ namespace System
|
|||
return default(T);
|
||||
}
|
||||
|
||||
public static nullable(T) operator?(Self val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case .Ok(let inner): return inner;
|
||||
case .Err: return null;
|
||||
}
|
||||
}
|
||||
|
||||
[SkipCall]
|
||||
public void Dispose()
|
||||
{
|
||||
|
@ -84,6 +93,18 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
/*extension Result<T> where T : class
|
||||
{
|
||||
public static T operator?(Self val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case .Ok(let inner): return inner;
|
||||
case .Err: return default;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
enum Result<T, TErr>
|
||||
{
|
||||
case Ok(T val);
|
||||
|
@ -138,6 +159,15 @@ namespace System
|
|||
return default(T);
|
||||
}
|
||||
|
||||
public static nullable(T) operator?(Self val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case .Ok(let inner): return inner;
|
||||
case .Err: return null;
|
||||
}
|
||||
}
|
||||
|
||||
[SkipCall]
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
@ -149,6 +149,7 @@ enum BfToken : uint8
|
|||
BfToken_Namespace,
|
||||
BfToken_New,
|
||||
BfToken_Null,
|
||||
BfToken_Nullable,
|
||||
BfToken_Operator,
|
||||
BfToken_Out,
|
||||
BfToken_Override,
|
||||
|
@ -359,7 +360,7 @@ class BfGenericConstraintsDeclaration;
|
|||
class BfAttributeDirective;
|
||||
class BfNullableTypeRef;
|
||||
class BfRefTypeRef;
|
||||
class BfRetTypeTypeRef;
|
||||
class BfModifiedTypeRef;
|
||||
class BfConstTypeRef;
|
||||
class BfConstExprTypeRef;
|
||||
class BfInlineAsmStatement;
|
||||
|
@ -443,7 +444,7 @@ public:
|
|||
virtual void Visit(BfConstTypeRef* typeRef);
|
||||
virtual void Visit(BfConstExprTypeRef* typeRef);
|
||||
virtual void Visit(BfRefTypeRef* typeRef);
|
||||
virtual void Visit(BfRetTypeTypeRef* typeRef);
|
||||
virtual void Visit(BfModifiedTypeRef* typeRef);
|
||||
virtual void Visit(BfArrayTypeRef* typeRef);
|
||||
virtual void Visit(BfGenericInstanceTypeRef* typeRef);
|
||||
virtual void Visit(BfTupleTypeRef* typeRef);
|
||||
|
@ -1737,6 +1738,7 @@ enum BfUnaryOp
|
|||
BfUnaryOp_Decrement,
|
||||
BfUnaryOp_PostIncrement,
|
||||
BfUnaryOp_PostDecrement,
|
||||
BfUnaryOp_NullConditional,
|
||||
BfUnaryOp_Ref,
|
||||
BfUnaryOp_Out,
|
||||
BfUnaryOp_Mut,
|
||||
|
@ -2317,15 +2319,15 @@ public:
|
|||
ASTREF(BfTypeReference*) mElementType;
|
||||
}; BF_AST_DECL(BfElementedTypeRef, BfTypeReference);
|
||||
|
||||
class BfRetTypeTypeRef : public BfElementedTypeRef
|
||||
class BfModifiedTypeRef : public BfElementedTypeRef
|
||||
{
|
||||
public:
|
||||
BF_AST_TYPE(BfRetTypeTypeRef, BfElementedTypeRef);
|
||||
BF_AST_TYPE(BfModifiedTypeRef, BfElementedTypeRef);
|
||||
|
||||
BfTokenNode* mRetTypeToken;
|
||||
BfTokenNode* mOpenParen;
|
||||
BfTokenNode* mCloseParen;
|
||||
}; BF_AST_DECL(BfRetTypeTypeRef, BfElementedTypeRef);
|
||||
}; BF_AST_DECL(BfModifiedTypeRef, BfElementedTypeRef);
|
||||
|
||||
class BfArrayTypeRef : public BfElementedTypeRef
|
||||
{
|
||||
|
@ -3195,6 +3197,7 @@ BfBinaryOp BfGetFlippedBinaryOp(BfBinaryOp origOp);
|
|||
int BfGetBinaryOpPrecendence(BfBinaryOp binOp);
|
||||
const char* BfGetOpName(BfBinaryOp binOp);
|
||||
const char* BfGetOpName(BfUnaryOp unaryOp);
|
||||
bool BfCanOverloadOperator(BfUnaryOp unaryOp);
|
||||
BfBinaryOp BfTokenToBinaryOp(BfToken token);
|
||||
BfUnaryOp BfTokenToUnaryOp(BfToken token);
|
||||
BfAssignmentOp BfTokenToAssignmentOp(BfToken token);
|
||||
|
|
|
@ -1511,6 +1511,16 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken
|
|||
{
|
||||
if (dotTokenNode->GetToken() == BfToken_QuestionDot)
|
||||
{
|
||||
if (!targetValue.mType->IsNullable())
|
||||
{
|
||||
// We need this for Result<T>
|
||||
SetAndRestoreValue<bool> prevIgnore(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||
BfExprEvaluator exprEvaluator(mModule);
|
||||
auto opResult = exprEvaluator.PerformUnaryOperation_TryOperator(targetValue, NULL, BfUnaryOp_NullConditional, dotTokenNode);
|
||||
if (opResult)
|
||||
targetValue = opResult;
|
||||
}
|
||||
|
||||
// ?. should look inside nullable types
|
||||
if (targetValue.mType->IsNullable())
|
||||
{
|
||||
|
|
|
@ -4150,7 +4150,7 @@ void BfCompiler::AddToRebuildTypeList(BfTypeInstance* typeInst, HashSet<BfTypeIn
|
|||
|
||||
bool allowRebuild = ((!typeInst->IsGenericTypeInstance()) ||
|
||||
((typeInst->IsUnspecializedType()) && (!typeInst->IsUnspecializedTypeVariation())));
|
||||
if ((typeInst->IsClosure()) || (typeInst->IsConcreteInterfaceType()) || (typeInst->IsRetTypeType()))
|
||||
if ((typeInst->IsClosure()) || (typeInst->IsConcreteInterfaceType()) || (typeInst->IsModifiedTypeType()))
|
||||
allowRebuild = false;
|
||||
if (allowRebuild)
|
||||
rebuildTypeInstList.Add(typeInst);
|
||||
|
|
|
@ -370,7 +370,7 @@ public:
|
|||
BfAllocPool<BfBoxedType> mBoxedTypePool;
|
||||
BfAllocPool<BfTupleType> mTupleTypePool;
|
||||
BfAllocPool<BfRefType> mRefTypePool;
|
||||
BfAllocPool<BfRetTypeType> mRetTypeTypePool;
|
||||
BfAllocPool<BfModifiedTypeType> mRetTypeTypePool;
|
||||
BfAllocPool<BfGenericTypeInstance> mGenericTypeInstancePool;
|
||||
BfAllocPool<BfGenericTypeAliasType> mGenericTypeAliasPool;
|
||||
BfAllocPool<BfArrayType> mArrayTypeInstancePool;
|
||||
|
|
|
@ -325,7 +325,7 @@ void BfElementVisitor::Visit(BfRefTypeRef* typeRef)
|
|||
VisitChild(typeRef->mElementType);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfRetTypeTypeRef * typeRef)
|
||||
void BfElementVisitor::Visit(BfModifiedTypeRef * typeRef)
|
||||
{
|
||||
Visit((BfTypeReference*)typeRef); // Skip the Elemented part so we can put the element in the right spot
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
virtual void Visit(BfConstTypeRef* typeRef);
|
||||
virtual void Visit(BfConstExprTypeRef* typeRef);
|
||||
virtual void Visit(BfRefTypeRef* typeRef);
|
||||
virtual void Visit(BfRetTypeTypeRef* typeRef);
|
||||
virtual void Visit(BfModifiedTypeRef* typeRef);
|
||||
virtual void Visit(BfArrayTypeRef* typeRef);
|
||||
virtual void Visit(BfGenericInstanceTypeRef* typeRef);
|
||||
virtual void Visit(BfTupleTypeRef* typeRef);
|
||||
|
|
|
@ -6695,7 +6695,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
delegateFailed = false;
|
||||
if (mModule->mCurMethodInstance->mIsUnspecialized)
|
||||
{
|
||||
auto retTypeType = mModule->CreateRetTypeType(fieldVal.mType);
|
||||
auto retTypeType = mModule->CreateModifiedTypeType(fieldVal.mType, BfToken_RetType);
|
||||
return mModule->GetFakeTypedValue(retTypeType);
|
||||
}
|
||||
}
|
||||
|
@ -15919,6 +15919,10 @@ BfTypedValue BfExprEvaluator::SetupNullConditional(BfTypedValue thisValue, BfTok
|
|||
return thisValue;
|
||||
}
|
||||
|
||||
auto opResult = PerformUnaryOperation_TryOperator(thisValue, NULL, BfUnaryOp_NullConditional, dotToken);
|
||||
if (opResult)
|
||||
thisValue = opResult;
|
||||
|
||||
//TODO: But make null conditional work for Nullable types
|
||||
if (thisValue.mType->IsNullable())
|
||||
{
|
||||
|
@ -15956,6 +15960,7 @@ BfTypedValue BfExprEvaluator::SetupNullConditional(BfTypedValue thisValue, BfTok
|
|||
}
|
||||
|
||||
BfIRValue isNotNull;
|
||||
|
||||
if (thisValue.mType->IsNullable())
|
||||
{
|
||||
BfGenericTypeInstance* nullableType = (BfGenericTypeInstance*)thisValue.mType->ToTypeInstance();
|
||||
|
@ -16645,35 +16650,17 @@ void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp
|
|||
BfExprEvaluator::PerformUnaryOperation_OnResult(unaryOpExpr, unaryOp, opToken);
|
||||
}
|
||||
|
||||
void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken)
|
||||
BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken)
|
||||
{
|
||||
BfAstNode* propSrc = mPropSrc;
|
||||
BfTypedValue propTarget = mPropTarget;
|
||||
BfPropertyDef* propDef = mPropDef;
|
||||
SizedArray<BfResolvedArg, 2> indexerVals = mIndexerValues;
|
||||
BfTypedValue writeToProp;
|
||||
if ((!inValue.mType->IsTypeInstance()) && (!inValue.mType->IsGenericParam()))
|
||||
return BfTypedValue();
|
||||
|
||||
GetResult();
|
||||
if (!mResult)
|
||||
return;
|
||||
|
||||
if (mResult.mType->IsRef())
|
||||
mResult.mType = mResult.mType->GetUnderlyingType();
|
||||
|
||||
if (mResult.mType->IsVar())
|
||||
{
|
||||
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mResult.mType->IsTypeInstance()) || (mResult.mType->IsGenericParam()))
|
||||
{
|
||||
SizedArray<BfResolvedArg, 1> args;
|
||||
BfResolvedArg resolvedArg;
|
||||
resolvedArg.mTypedValue = mResult;
|
||||
resolvedArg.mTypedValue = inValue;
|
||||
args.push_back(resolvedArg);
|
||||
BfMethodMatcher methodMatcher(opToken, mModule, "", args, NULL);
|
||||
BfBaseClassWalker baseClassWalker(mResult.mType, NULL, mModule);
|
||||
BfBaseClassWalker baseClassWalker(inValue.mType, NULL, mModule);
|
||||
|
||||
BfUnaryOp findOp = unaryOp;
|
||||
bool isPostOp = false;
|
||||
|
@ -16709,35 +16696,8 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
|
|||
}
|
||||
}
|
||||
|
||||
if (methodMatcher.mBestMethodDef != NULL)
|
||||
if (methodMatcher.mBestMethodDef == NULL)
|
||||
{
|
||||
if (!baseClassWalker.mMayBeFromInterface)
|
||||
mModule->SetElementType(opToken, BfSourceElementType_Method);
|
||||
|
||||
auto methodDef = methodMatcher.mBestMethodDef;
|
||||
auto autoComplete = GetAutoComplete();
|
||||
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(opToken)))
|
||||
{
|
||||
auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDef->mMethodDeclaration);
|
||||
if ((operatorDecl != NULL) && (operatorDecl->mOpTypeToken != NULL))
|
||||
autoComplete->SetDefinitionLocation(operatorDecl->mOpTypeToken);
|
||||
}
|
||||
|
||||
SizedArray<BfExpression*, 2> argSrcs;
|
||||
argSrcs.push_back(unaryOpExpr);
|
||||
mResult = CreateCall(&methodMatcher, BfTypedValue());
|
||||
|
||||
if ((mResult.mType != NULL) && (methodMatcher.mSelfType != NULL) && (mResult.mType->IsSelf()))
|
||||
{
|
||||
BF_ASSERT(mModule->IsInGeneric());
|
||||
mResult = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
|
||||
}
|
||||
|
||||
if (isPostOp)
|
||||
mResult = args[0].mTypedValue;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check method generic constraints
|
||||
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
|
||||
{
|
||||
|
@ -16750,8 +16710,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
|
|||
{
|
||||
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))
|
||||
{
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||
return;
|
||||
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16771,12 +16730,71 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
|
|||
{
|
||||
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))
|
||||
{
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BfTypedValue();
|
||||
}
|
||||
|
||||
if (!baseClassWalker.mMayBeFromInterface)
|
||||
mModule->SetElementType(opToken, BfSourceElementType_Method);
|
||||
|
||||
auto methodDef = methodMatcher.mBestMethodDef;
|
||||
auto autoComplete = GetAutoComplete();
|
||||
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(opToken)))
|
||||
{
|
||||
auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDef->mMethodDeclaration);
|
||||
if ((operatorDecl != NULL) && (operatorDecl->mOpTypeToken != NULL))
|
||||
autoComplete->SetDefinitionLocation(operatorDecl->mOpTypeToken);
|
||||
}
|
||||
|
||||
SizedArray<BfExpression*, 2> argSrcs;
|
||||
argSrcs.push_back(unaryOpExpr);
|
||||
auto result = CreateCall(&methodMatcher, BfTypedValue());
|
||||
|
||||
if ((result.mType != NULL) && (methodMatcher.mSelfType != NULL) && (result.mType->IsSelf()))
|
||||
{
|
||||
BF_ASSERT(mModule->IsInGeneric());
|
||||
result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
|
||||
}
|
||||
|
||||
if (isPostOp)
|
||||
result = args[0].mTypedValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken)
|
||||
{
|
||||
BfAstNode* propSrc = mPropSrc;
|
||||
BfTypedValue propTarget = mPropTarget;
|
||||
BfPropertyDef* propDef = mPropDef;
|
||||
SizedArray<BfResolvedArg, 2> indexerVals = mIndexerValues;
|
||||
BfTypedValue writeToProp;
|
||||
|
||||
GetResult();
|
||||
if (!mResult)
|
||||
return;
|
||||
|
||||
if (mResult.mType->IsRef())
|
||||
mResult.mType = mResult.mType->GetUnderlyingType();
|
||||
|
||||
if (mResult.mType->IsVar())
|
||||
{
|
||||
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BfCanOverloadOperator(unaryOp))
|
||||
{
|
||||
auto opResult = PerformUnaryOperation_TryOperator(mResult, unaryOpExpr, unaryOp, opToken);
|
||||
if (opResult)
|
||||
{
|
||||
mResult = opResult;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -389,6 +389,7 @@ public:
|
|||
void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
|
||||
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
|
||||
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);
|
||||
BfTypedValue PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);
|
||||
void PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);
|
||||
void PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue = NULL);
|
||||
void PopulateDeferrredTupleAssignData(BfTupleExpression* tupleExr, DeferredTupleAssignData& deferredTupleAssignData);
|
||||
|
|
|
@ -2050,7 +2050,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
|
|||
trackDIType = true;
|
||||
}
|
||||
}
|
||||
else if ((type->IsGenericParam()) || (type->IsRetTypeType()))
|
||||
else if ((type->IsGenericParam()) || (type->IsModifiedTypeType()))
|
||||
{
|
||||
//mModule->PopulateType(mModule->mContext->mBfObjectType, BfPopulateType_Declaration);
|
||||
irType = MapType(mModule->mContext->mBfObjectType);
|
||||
|
|
|
@ -539,10 +539,15 @@ void BfGNUMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType
|
|||
AddPrefix(mangleContext, name, startIdx, "R");
|
||||
return;
|
||||
}
|
||||
else if (type->IsRetTypeType())
|
||||
else if (type->IsModifiedTypeType())
|
||||
{
|
||||
BfRetTypeType* retTypeType = (BfRetTypeType*)type;
|
||||
BfModifiedTypeType* retTypeType = (BfModifiedTypeType*)type;
|
||||
if (retTypeType->mModifiedKind == BfToken_RetType)
|
||||
name += "U7rettype";
|
||||
else if (retTypeType->mModifiedKind == BfToken_Nullable)
|
||||
name += "U8nullable";
|
||||
else
|
||||
BF_FATAL("Unhandled");
|
||||
Mangle(mangleContext, name, retTypeType->mElementType);
|
||||
return;
|
||||
}
|
||||
|
@ -1573,10 +1578,15 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType*
|
|||
name += "out$";
|
||||
Mangle(mangleContext, name, refType->mElementType);
|
||||
}
|
||||
else if (type->IsRetTypeType())
|
||||
else if (type->IsModifiedTypeType())
|
||||
{
|
||||
auto retType = (BfRetTypeType*)type;
|
||||
auto retType = (BfModifiedTypeType*)type;
|
||||
if (retType->mModifiedKind == BfToken_RetType)
|
||||
name += "rettype$";
|
||||
else if (retType->mModifiedKind == BfToken_Nullable)
|
||||
name += "nullable$";
|
||||
else
|
||||
BF_FATAL("Unhandled");
|
||||
Mangle(mangleContext, name, retType->mElementType);
|
||||
}
|
||||
else if (type->IsConcreteInterfaceType())
|
||||
|
|
|
@ -1352,7 +1352,7 @@ BfIRValue BfModule::GetDefaultValue(BfType* type)
|
|||
}
|
||||
|
||||
if (type->IsPointer() || type->IsObjectOrInterface() || type->IsGenericParam() || type->IsVar() || type->IsRef() || type->IsNull() ||
|
||||
type->IsRetTypeType() || type->IsConcreteInterfaceType())
|
||||
type->IsModifiedTypeType() || type->IsConcreteInterfaceType())
|
||||
return mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(type));
|
||||
if ((type->IsIntegral()) || (type->IsBoolean()))
|
||||
{
|
||||
|
|
|
@ -1628,7 +1628,7 @@ public:
|
|||
BfTupleType* CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames);
|
||||
BfTupleType* SantizeTupleType(BfTupleType* tupleType);
|
||||
BfRefType* CreateRefType(BfType* resolvedTypeRef, BfRefType::RefKind refKind = BfRefType::RefKind_Ref);
|
||||
BfRetTypeType* CreateRetTypeType(BfType* resolvedTypeRef);
|
||||
BfModifiedTypeType* CreateModifiedTypeType(BfType* resolvedTypeRef, BfToken modifiedKind);
|
||||
BfConcreteInterfaceType* CreateConcreteInterfaceType(BfTypeInstance* interfaceType);
|
||||
BfTypeInstance* GetWrappedStructType(BfType* type, bool allowSpecialized = true);
|
||||
BfTypeInstance* GetPrimitiveStructType(BfTypeCode typeCode);
|
||||
|
|
|
@ -1023,9 +1023,9 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
|||
return true;
|
||||
}
|
||||
|
||||
if (resolvedTypeRef->IsRetTypeType())
|
||||
if (resolvedTypeRef->IsModifiedTypeType())
|
||||
{
|
||||
BfRetTypeType* retTypeType = (BfRetTypeType*)resolvedTypeRef;
|
||||
BfModifiedTypeType* retTypeType = (BfModifiedTypeType*)resolvedTypeRef;
|
||||
BF_ASSERT(retTypeType->mElementType->IsGenericParam());
|
||||
resolvedTypeRef->mSize = mContext->mBfObjectType->mSize;
|
||||
resolvedTypeRef->mAlign = mContext->mBfObjectType->mAlign;
|
||||
|
@ -4967,15 +4967,16 @@ BfRefType* BfModule::CreateRefType(BfType* resolvedTypeRef, BfRefType::RefKind r
|
|||
return (BfRefType*)resolvedRefType;
|
||||
}
|
||||
|
||||
BfRetTypeType* BfModule::CreateRetTypeType(BfType* resolvedTypeRef)
|
||||
BfModifiedTypeType* BfModule::CreateModifiedTypeType(BfType* resolvedTypeRef, BfToken modifiedKind)
|
||||
{
|
||||
auto retTypeType = mContext->mRetTypeTypePool.Get();
|
||||
retTypeType->mContext = mContext;
|
||||
retTypeType->mModifiedKind = modifiedKind;
|
||||
retTypeType->mElementType = resolvedTypeRef;
|
||||
auto resolvedRetTypeType = ResolveType(retTypeType);
|
||||
if (resolvedRetTypeType != retTypeType)
|
||||
mContext->mRetTypeTypePool.GiveBack(retTypeType);
|
||||
return (BfRetTypeType*)resolvedRetTypeType;
|
||||
return (BfModifiedTypeType*)resolvedRetTypeType;
|
||||
}
|
||||
|
||||
BfConcreteInterfaceType* BfModule::CreateConcreteInterfaceType(BfTypeInstance* interfaceType)
|
||||
|
@ -7147,7 +7148,9 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
return ResolveTypeResult(typeRef, resolvedTypeRef->mType, populateType, resolveFlags);
|
||||
}
|
||||
|
||||
if (auto retTypeTypeRef = BfNodeDynCastExact<BfRetTypeTypeRef>(typeRef))
|
||||
if (auto retTypeTypeRef = BfNodeDynCastExact<BfModifiedTypeRef>(typeRef))
|
||||
{
|
||||
if (retTypeTypeRef->mRetTypeToken->mToken == BfToken_RetType)
|
||||
{
|
||||
bool allowThrough = false;
|
||||
BfType* resolvedType = NULL;
|
||||
|
@ -7208,6 +7211,36 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
return ResolveTypeResult(typeRef, resolvedType, populateType, resolveFlags);
|
||||
}
|
||||
}
|
||||
else if (retTypeTypeRef->mRetTypeToken->mToken == BfToken_Nullable)
|
||||
{
|
||||
bool allowThrough = false;
|
||||
BfType* resolvedType = NULL;
|
||||
if (retTypeTypeRef->mElementType != NULL)
|
||||
{
|
||||
resolvedType = ResolveTypeRef(retTypeTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue);
|
||||
}
|
||||
|
||||
if ((resolvedType != NULL) && (resolvedType->IsGenericParam()))
|
||||
{
|
||||
//resolvedType = CreateModifiedTypeType(resolvedType, BfToken_Nullable);
|
||||
BfTypeVector typeVec;
|
||||
typeVec.push_back(resolvedType);
|
||||
resolvedType = ResolveTypeDef(mCompiler->mNullableTypeDef, typeVec, BfPopulateType_Declaration);
|
||||
}
|
||||
else if ((resolvedType != NULL) && (resolvedType->IsValueType()))
|
||||
{
|
||||
BfTypeVector typeVec;
|
||||
typeVec.push_back(resolvedType);
|
||||
resolvedType = ResolveTypeDef(mCompiler->mNullableTypeDef, typeVec, BfPopulateType_Declaration);
|
||||
}
|
||||
if (resolvedType != NULL)
|
||||
PopulateType(resolvedType, populateType);
|
||||
|
||||
return resolvedType;
|
||||
}
|
||||
else
|
||||
BF_FATAL("Unhandled");
|
||||
}
|
||||
|
||||
if (auto refTypeRef = BfNodeDynCastExact<BfRefTypeRef>(typeRef))
|
||||
{
|
||||
|
@ -7799,9 +7832,10 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
BF_ASSERT(BfResolvedTypeSet::Hash(genericParamType, &lookupCtx) == resolvedEntry->mHash);
|
||||
return ResolveTypeResult(typeRef, genericParamType, populateType, resolveFlags);
|
||||
}
|
||||
else if (auto retTypeTypeRef = BfNodeDynCast<BfRetTypeTypeRef>(typeRef))
|
||||
else if (auto retTypeTypeRef = BfNodeDynCast<BfModifiedTypeRef>(typeRef))
|
||||
{
|
||||
auto retTypeType = new BfRetTypeType();
|
||||
auto retTypeType = new BfModifiedTypeType();
|
||||
retTypeType->mModifiedKind = retTypeTypeRef->mRetTypeToken->mToken;
|
||||
retTypeType->mElementType = ResolveTypeRef(retTypeTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue);
|
||||
// We know this is a generic param type, it can't fail to resolve
|
||||
BF_ASSERT(retTypeType->mElementType);
|
||||
|
@ -8467,7 +8501,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
((toType->IsInterface()) || (toType == mContext->mBfObjectType)))
|
||||
{
|
||||
// Make sure there's no conversion operator before we box
|
||||
if ((!typedVal.mType->IsRef()) && (!typedVal.mType->IsRetTypeType()))
|
||||
if ((!typedVal.mType->IsRef()) && (!typedVal.mType->IsModifiedTypeType()))
|
||||
mayBeBox = true;
|
||||
}
|
||||
|
||||
|
@ -10060,7 +10094,7 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
|||
str += "]";
|
||||
return;
|
||||
}
|
||||
else if ((resolvedType->IsNullable()) && (!resolvedType->IsUnspecializedType()))
|
||||
else if (resolvedType->IsNullable())
|
||||
{
|
||||
auto genericType = (BfGenericTypeInstance*)resolvedType;
|
||||
auto elementType = genericType->mTypeGenericArguments[0];
|
||||
|
@ -10508,10 +10542,11 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (resolvedType->IsRetTypeType())
|
||||
else if (resolvedType->IsModifiedTypeType())
|
||||
{
|
||||
auto retTypeType = (BfRetTypeType*)resolvedType;
|
||||
str += "rettype(";
|
||||
auto retTypeType = (BfModifiedTypeType*)resolvedType;
|
||||
str += BfTokenToString(retTypeType->mModifiedKind);
|
||||
str += "(";
|
||||
DoTypeToString(str, retTypeType->mElementType, typeNameFlags, genericMethodNameOverrides);
|
||||
str += ")";
|
||||
return;
|
||||
|
|
|
@ -2784,6 +2784,8 @@ void BfParser::NextToken(int endIdx)
|
|||
case TOKEN_HASH('n', 'u', 'l', 'l'):
|
||||
if (SrcPtrHasToken("null"))
|
||||
mToken = BfToken_Null;
|
||||
else if (SrcPtrHasToken("nullable"))
|
||||
mToken = BfToken_Nullable;
|
||||
break;
|
||||
case TOKEN_HASH('o', 'p', 'e', 'r'):
|
||||
if (SrcPtrHasToken("operator"))
|
||||
|
|
|
@ -267,7 +267,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
|
|||
{
|
||||
// Tuple start
|
||||
}
|
||||
else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_RetType))
|
||||
else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable))
|
||||
{
|
||||
// Decltype start
|
||||
}
|
||||
|
@ -760,7 +760,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
|
|||
checkIdx = funcEndNode;
|
||||
continue;
|
||||
}
|
||||
else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_RetType))
|
||||
else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable))
|
||||
{
|
||||
int endNodeIdx = checkIdx + 1;
|
||||
|
||||
|
@ -4168,6 +4168,7 @@ bool BfReducer::IsTerminatingExpression(BfAstNode* node)
|
|||
case BfToken_Scope:
|
||||
case BfToken_New:
|
||||
case BfToken_RetType:
|
||||
case BfToken_Nullable:
|
||||
case BfToken_SizeOf:
|
||||
case BfToken_This:
|
||||
case BfToken_TypeOf:
|
||||
|
@ -4572,9 +4573,9 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
|
|||
return elementType;
|
||||
}
|
||||
}
|
||||
else if (token == BfToken_RetType)
|
||||
else if ((token == BfToken_RetType) || (token == BfToken_Nullable))
|
||||
{
|
||||
auto retTypeTypeRef = mAlloc->Alloc<BfRetTypeTypeRef>();
|
||||
auto retTypeTypeRef = mAlloc->Alloc<BfModifiedTypeRef>();
|
||||
ReplaceNode(firstNode, retTypeTypeRef);
|
||||
MEMBER_SET(retTypeTypeRef, mRetTypeToken, tokenNode);
|
||||
|
||||
|
@ -6269,6 +6270,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
|
|||
else if ((token == BfToken_Var) ||
|
||||
(token == BfToken_Let) ||
|
||||
(token == BfToken_RetType) ||
|
||||
(token == BfToken_Nullable) ||
|
||||
(token == BfToken_Decltype) ||
|
||||
(token == BfToken_LParen))
|
||||
{
|
||||
|
|
|
@ -2199,9 +2199,9 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef)
|
|||
int elemHash = Hash(refType->mElementType, ctx) ^ (HASH_VAL_REF + (int)refType->mRefKind);
|
||||
return (elemHash << 5) - elemHash;
|
||||
}
|
||||
else if (type->IsRetTypeType())
|
||||
else if (type->IsModifiedTypeType())
|
||||
{
|
||||
auto retTypeType = (BfRetTypeType*)type;
|
||||
auto retTypeType = (BfModifiedTypeType*)type;
|
||||
int elemHash = Hash(retTypeType->mElementType, ctx) ^ HASH_RETTYPE;
|
||||
return (elemHash << 5) - elemHash;
|
||||
}
|
||||
|
@ -2621,7 +2621,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
auto primType = ctx->mModule->GetPrimitiveType(BfTypeCode_Let);
|
||||
return Hash(primType, ctx);
|
||||
}
|
||||
else if (auto retTypeTypeRef = BfNodeDynCastExact<BfRetTypeTypeRef>(typeRef))
|
||||
else if (auto retTypeTypeRef = BfNodeDynCastExact<BfModifiedTypeRef>(typeRef))
|
||||
{
|
||||
// Don't cause infinite loop, but if we have an inner 'rettype' then try to directly resolve that --
|
||||
// Only use the HAS_RETTYPE for root-level rettype insertions
|
||||
|
@ -2882,13 +2882,14 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
|
|||
BfRefType* rhsRefType = (BfRefType*)rhs;
|
||||
return (lhsRefType->mElementType == rhsRefType->mElementType) && (lhsRefType->mRefKind == rhsRefType->mRefKind);
|
||||
}
|
||||
else if (lhs->IsRetTypeType())
|
||||
else if (lhs->IsModifiedTypeType())
|
||||
{
|
||||
if (!rhs->IsRetTypeType())
|
||||
if (!rhs->IsModifiedTypeType())
|
||||
return false;
|
||||
BfRetTypeType* lhsRetTypeType = (BfRetTypeType*)lhs;
|
||||
BfRetTypeType* rhsRetTypeType = (BfRetTypeType*)rhs;
|
||||
return (lhsRetTypeType->mElementType == rhsRetTypeType->mElementType);
|
||||
BfModifiedTypeType* lhsRetTypeType = (BfModifiedTypeType*)lhs;
|
||||
BfModifiedTypeType* rhsRetTypeType = (BfModifiedTypeType*)rhs;
|
||||
return (lhsRetTypeType->mModifiedKind == rhsRetTypeType->mModifiedKind) &&
|
||||
(lhsRetTypeType->mElementType == rhsRetTypeType->mElementType);
|
||||
}
|
||||
else if (lhs->IsConcreteInterfaceType())
|
||||
{
|
||||
|
@ -3093,7 +3094,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
|
|||
|
||||
if (ctx->mRootTypeRef != rhs)
|
||||
{
|
||||
if (auto retTypeRef = BfNodeDynCastExact<BfRetTypeTypeRef>(rhs))
|
||||
if (auto retTypeRef = BfNodeDynCastExact<BfModifiedTypeRef>(rhs))
|
||||
{
|
||||
auto resolvedType = ctx->mModule->ResolveTypeRef(rhs);
|
||||
return lhs == resolvedType;
|
||||
|
@ -3341,12 +3342,14 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
|
|||
return (lhsRefType->mRefKind == refKind) &&
|
||||
Equals(lhsRefType->mElementType, rhsRefTypeRef->mElementType, ctx);
|
||||
}
|
||||
else if (lhs->IsRetTypeType())
|
||||
else if (lhs->IsModifiedTypeType())
|
||||
{
|
||||
auto lhsRetTypeType = (BfRetTypeType*)lhs;
|
||||
auto rhsRetTypeTypeRef = BfNodeDynCastExact<BfRetTypeTypeRef>(rhs);
|
||||
auto lhsRetTypeType = (BfModifiedTypeType*)lhs;
|
||||
auto rhsRetTypeTypeRef = BfNodeDynCastExact<BfModifiedTypeRef>(rhs);
|
||||
if (rhsRetTypeTypeRef == NULL)
|
||||
return false;
|
||||
if (lhsRetTypeType->mModifiedKind != rhsRetTypeTypeRef->mRetTypeToken->mToken)
|
||||
return false;
|
||||
return Equals(lhsRetTypeType->mElementType, rhsRetTypeTypeRef->mElementType, ctx);
|
||||
}
|
||||
else if (lhs->IsConcreteInterfaceType())
|
||||
|
|
|
@ -489,7 +489,7 @@ public:
|
|||
virtual bool IsTuple() { return false; }
|
||||
virtual bool IsOnDemand() { return false; }
|
||||
virtual bool IsTemporary() { return false; }
|
||||
virtual bool IsRetTypeType() { return false; }
|
||||
virtual bool IsModifiedTypeType() { return false; }
|
||||
virtual bool IsConcreteInterfaceType() { return false; }
|
||||
virtual bool IsTypeAlias() { return false; }
|
||||
virtual bool HasPackingHoles() { return false; }
|
||||
|
@ -921,13 +921,14 @@ public:
|
|||
virtual bool IsReified() override { return false; }
|
||||
};
|
||||
|
||||
// This just captures rettype(T) since it can't be resolved directly
|
||||
class BfRetTypeType : public BfType
|
||||
// This just captures rettype(T)/nullable(T) since it can't be resolved directly
|
||||
class BfModifiedTypeType : public BfType
|
||||
{
|
||||
public:
|
||||
BfToken mModifiedKind;
|
||||
BfType* mElementType;
|
||||
|
||||
virtual bool IsRetTypeType() override { return true; }
|
||||
virtual bool IsModifiedTypeType() override { return true; }
|
||||
virtual bool CanBeValuelessType() override { return true; }
|
||||
virtual bool IsValuelessType() override { return true; }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue