mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
'var' improvements, fixed cast issues with typed prim & constraint check
This commit is contained in:
parent
1b9e97a65c
commit
5267e18783
3 changed files with 108 additions and 41 deletions
|
@ -10962,6 +10962,12 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
|
||||||
mModule->AddDependency(targetType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
mModule->AddDependency(targetType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
||||||
|
|
||||||
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
||||||
|
if (targetValue.mType->IsVar())
|
||||||
|
{
|
||||||
|
mResult = mModule->GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (targetValue.mType->IsValueTypeOrValueTypePtr())
|
if (targetValue.mType->IsValueTypeOrValueTypePtr())
|
||||||
{
|
{
|
||||||
auto typeInstance = targetValue.mType->ToTypeInstance();
|
auto typeInstance = targetValue.mType->ToTypeInstance();
|
||||||
|
@ -11113,6 +11119,12 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
targetType = typeConstraint;
|
targetType = typeConstraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetType->IsVar())
|
||||||
|
{
|
||||||
|
mResult = mModule->GetDefaultTypedValue(targetType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((!targetType->IsObjectOrInterface()) && (!targetType->IsNullable()))
|
if ((!targetType->IsObjectOrInterface()) && (!targetType->IsNullable()))
|
||||||
{
|
{
|
||||||
mModule->Fail(StrFormat("The as operator must be used with a reference type or nullable type ('%s' is a non-nullable value type)",
|
mModule->Fail(StrFormat("The as operator must be used with a reference type or nullable type ('%s' is a non-nullable value type)",
|
||||||
|
@ -11159,6 +11171,12 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetValue.mType->IsVar())
|
||||||
|
{
|
||||||
|
mResult = mModule->GetDefaultTypedValue(targetType, false, BfDefaultValueKind_Undef);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (targetValue.mType->IsValueTypeOrValueTypePtr())
|
if (targetValue.mType->IsValueTypeOrValueTypePtr())
|
||||||
{
|
{
|
||||||
mModule->Warn(0, StrFormat("Type '%s' is not applicable for dynamic casting",
|
mModule->Warn(0, StrFormat("Type '%s' is not applicable for dynamic casting",
|
||||||
|
@ -15254,7 +15272,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
|
||||||
|
|
||||||
if (genericArg->IsVar())
|
if (genericArg->IsVar())
|
||||||
{
|
{
|
||||||
BF_ASSERT(methodMatcher.mHasVarArguments);
|
//BF_ASSERT(methodMatcher.mHasVarArguments);
|
||||||
hasVarGenerics = true;
|
hasVarGenerics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19373,14 +19391,14 @@ BfTypedValue BfExprEvaluator::SetupNullConditional(BfTypedValue thisValue, BfTok
|
||||||
return thisValue;
|
return thisValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thisValue.mType->IsNullable())
|
if ((thisValue.mType->IsNullable()) || (thisValue.mType->IsVar()))
|
||||||
{
|
{
|
||||||
// Success
|
// Success
|
||||||
}
|
}
|
||||||
else if ((thisValue.mType->IsPointer()) || (thisValue.mType->IsObjectOrInterface()))
|
else if ((thisValue.mType->IsPointer()) || (thisValue.mType->IsObjectOrInterface()))
|
||||||
{
|
{
|
||||||
// Also good
|
// Also good
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mModule->Warn(0, StrFormat("Null conditional reference is unnecessary since value type '%s' can never be null", mModule->TypeToString(thisValue.mType).c_str()), dotToken);
|
mModule->Warn(0, StrFormat("Null conditional reference is unnecessary since value type '%s' can never be null", mModule->TypeToString(thisValue.mType).c_str()), dotToken);
|
||||||
|
@ -22345,8 +22363,17 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
|
|
||||||
auto underlyingType = resultType->GetUnderlyingType();
|
auto underlyingType = resultType->GetUnderlyingType();
|
||||||
|
|
||||||
BfIRValue convResultValue = mModule->CastToValue(resultTypeSrc, *resultTypedValue, underlyingType, BfCastFlags_Explicit);
|
BfIRValue convResultValue;
|
||||||
BfIRValue convOtherValue = mModule->CastToValue(otherTypeSrc, *otherTypedValue, underlyingType, BfCastFlags_Explicit);
|
if (resultTypedValue->mType == resultType)
|
||||||
|
convResultValue = mModule->LoadValue(*resultTypedValue).mValue;
|
||||||
|
else
|
||||||
|
convResultValue = mModule->CastToValue(resultTypeSrc, *resultTypedValue, underlyingType, BfCastFlags_Explicit);
|
||||||
|
|
||||||
|
BfIRValue convOtherValue;
|
||||||
|
if (otherTypedValue->mType == resultType)
|
||||||
|
convOtherValue = mModule->LoadValue(*otherTypedValue).mValue;
|
||||||
|
else
|
||||||
|
convOtherValue = mModule->CastToValue(otherTypeSrc, *otherTypedValue, underlyingType, BfCastFlags_Explicit);
|
||||||
|
|
||||||
if ((!underlyingType->IsValuelessType()) && ((!convResultValue) || (!convOtherValue)))
|
if ((!underlyingType->IsValuelessType()) && ((!convResultValue) || (!convOtherValue)))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2800,6 +2800,8 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde
|
||||||
if (typeInstance->mTypeInfoEx == NULL)
|
if (typeInstance->mTypeInfoEx == NULL)
|
||||||
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
|
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
|
||||||
|
|
||||||
|
bool isAllInt64 = true;
|
||||||
|
|
||||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||||
{
|
{
|
||||||
auto fieldInstance = &fieldInstanceRef;
|
auto fieldInstance = &fieldInstanceRef;
|
||||||
|
@ -2810,7 +2812,8 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||||
BF_ASSERT((constant->mTypeCode == BfTypeCode_Int64) || (!underlyingTypeDeferred));
|
if (constant->mTypeCode != BfTypeCode_Int64)
|
||||||
|
isAllInt64 = false;
|
||||||
|
|
||||||
if (isFirst)
|
if (isFirst)
|
||||||
{
|
{
|
||||||
|
@ -2851,7 +2854,7 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde
|
||||||
if (typeInstance->mIsCRepr)
|
if (typeInstance->mIsCRepr)
|
||||||
typeCode = BfTypeCode_Int32;
|
typeCode = BfTypeCode_Int32;
|
||||||
|
|
||||||
if (typeCode != BfTypeCode_Int64)
|
if ((typeCode != BfTypeCode_Int64) || (!isAllInt64))
|
||||||
{
|
{
|
||||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||||
{
|
{
|
||||||
|
@ -2861,6 +2864,8 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde
|
||||||
if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry())
|
if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry())
|
||||||
continue;
|
continue;
|
||||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||||
|
if (constant->mTypeCode == typeCode)
|
||||||
|
continue;
|
||||||
BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64);
|
BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64);
|
||||||
fieldInstance->mConstIdx = newConstant.mId;
|
fieldInstance->mConstIdx = newConstant.mId;
|
||||||
}
|
}
|
||||||
|
@ -4849,6 +4854,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_CheckTypeDone())
|
||||||
|
return;
|
||||||
|
|
||||||
if (typeInstance->mDefineState < BfTypeDefineState_Defined)
|
if (typeInstance->mDefineState < BfTypeDefineState_Defined)
|
||||||
{
|
{
|
||||||
typeInstance->mDefineState = BfTypeDefineState_Defined;
|
typeInstance->mDefineState = BfTypeDefineState_Defined;
|
||||||
|
@ -10551,9 +10559,9 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
{
|
{
|
||||||
auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue));
|
auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue));
|
||||||
if ((genericArg == NULL) || (genericArg->IsVar()))
|
if ((genericArg == NULL) || (genericArg->IsVar()))
|
||||||
{
|
{
|
||||||
mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
|
mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
|
||||||
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
|
return ResolveTypeResult(typeRef, genericArg->IsVar() ? genericArg : NULL, populateType, resolveFlags);
|
||||||
}
|
}
|
||||||
genericArgs.Add(genericArg);
|
genericArgs.Add(genericArg);
|
||||||
}
|
}
|
||||||
|
@ -12713,7 +12721,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
{
|
{
|
||||||
auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType);
|
auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType);
|
||||||
if (result.mType != toType)
|
if (result.mType != toType)
|
||||||
return CastToValue(srcNode, result, toType, BfCastFlags_Explicit, resultFlags);
|
return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator), resultFlags);
|
||||||
if (result)
|
if (result)
|
||||||
return result.mValue;
|
return result.mValue;
|
||||||
}
|
}
|
||||||
|
@ -12741,50 +12749,74 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool doCall = true;
|
||||||
|
|
||||||
auto moduleMethodInstance = exprEvaluator.GetSelectedMethod(methodMatcher);
|
auto moduleMethodInstance = exprEvaluator.GetSelectedMethod(methodMatcher);
|
||||||
if (moduleMethodInstance.mMethodInstance != NULL)
|
if (moduleMethodInstance.mMethodInstance != NULL)
|
||||||
{
|
{
|
||||||
auto paramType = moduleMethodInstance.mMethodInstance->GetParamType(0);
|
auto returnType = moduleMethodInstance.mMethodInstance->mReturnType;
|
||||||
auto wantType = paramType;
|
if (typedVal.mType->IsTypedPrimitive())
|
||||||
if (wantType->IsRef())
|
|
||||||
wantType = wantType->GetUnderlyingType();
|
|
||||||
auto typedVal = methodMatcher.mArguments[0].mTypedValue;
|
|
||||||
if (wantType != typedVal.mType)
|
|
||||||
{
|
{
|
||||||
if ((typedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(typedVal.mType)))
|
auto underlyingType = typedVal.mType->GetUnderlyingType();
|
||||||
|
if ((returnType != underlyingType) && (CanCast(GetFakeTypedValue(underlyingType), toType, (BfCastFlags)(castFlags | BfCastFlags_NoConversionOperator))))
|
||||||
{
|
{
|
||||||
typedVal = MakeAddressable(typedVal);
|
if ((CanCast(GetFakeTypedValue(underlyingType), returnType)) &&
|
||||||
methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())),
|
(!CanCast(GetFakeTypedValue(returnType), underlyingType)))
|
||||||
paramType, paramType->IsRef() ? BfTypedValueKind_Value : BfTypedValueKind_Addr);
|
{
|
||||||
|
doCall = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
doCall = false;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
|
||||||
|
if (doCall)
|
||||||
|
{
|
||||||
|
auto paramType = moduleMethodInstance.mMethodInstance->GetParamType(0);
|
||||||
|
auto wantType = paramType;
|
||||||
|
if (wantType->IsRef())
|
||||||
|
wantType = wantType->GetUnderlyingType();
|
||||||
|
auto typedVal = methodMatcher.mArguments[0].mTypedValue;
|
||||||
|
if (wantType != typedVal.mType)
|
||||||
{
|
{
|
||||||
methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator));
|
if ((typedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(typedVal.mType)))
|
||||||
if (paramType->IsRef())
|
|
||||||
{
|
{
|
||||||
typedVal = MakeAddressable(typedVal);
|
typedVal = MakeAddressable(typedVal);
|
||||||
typedVal.mKind = BfTypedValueKind_Addr;
|
methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())),
|
||||||
|
paramType, paramType->IsRef() ? BfTypedValueKind_Value : BfTypedValueKind_Addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator));
|
||||||
|
if (paramType->IsRef())
|
||||||
|
{
|
||||||
|
typedVal = MakeAddressable(typedVal);
|
||||||
|
typedVal.mKind = BfTypedValueKind_Addr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = exprEvaluator.CreateCall(&methodMatcher, BfTypedValue());
|
if (doCall)
|
||||||
if (resultFlags != NULL)
|
|
||||||
{
|
{
|
||||||
if (result.IsAddr())
|
result = exprEvaluator.CreateCall(&methodMatcher, BfTypedValue());
|
||||||
*resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsAddr);
|
if (resultFlags != NULL)
|
||||||
if (result.mKind == BfTypedValueKind_TempAddr)
|
{
|
||||||
*resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsTemp);
|
if (result.IsAddr())
|
||||||
|
*resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsAddr);
|
||||||
|
if (result.mKind == BfTypedValueKind_TempAddr)
|
||||||
|
*resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsTemp);
|
||||||
|
}
|
||||||
|
else if (result.IsAddr())
|
||||||
|
result = LoadValue(result);
|
||||||
|
|
||||||
|
if (result.mType != toType)
|
||||||
|
return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator), resultFlags);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
return result.mValue;
|
||||||
}
|
}
|
||||||
else if (result.IsAddr())
|
|
||||||
result = LoadValue(result);
|
|
||||||
|
|
||||||
if (result.mType != toType)
|
|
||||||
return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator), resultFlags);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
return result.mValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1209,7 +1209,7 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
|
||||||
|
|
||||||
if (CanCast(initValue, varType))
|
if (CanCast(initValue, varType))
|
||||||
{
|
{
|
||||||
if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface()))
|
if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface()) && (!varType->IsVar()))
|
||||||
{
|
{
|
||||||
if (!IsInSpecializedSection())
|
if (!IsInSpecializedSection())
|
||||||
{
|
{
|
||||||
|
@ -1260,7 +1260,11 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
|
||||||
mBfIRBuilder->CreateAlignedStore(initValue.mValue, localVar->mAddr, initValue.mType->mAlign);
|
mBfIRBuilder->CreateAlignedStore(initValue.mValue, localVar->mAddr, initValue.mType->mAlign);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((varType->IsPointer()) || (varType->IsObjectOrInterface()))
|
if (varType->IsVar())
|
||||||
|
{
|
||||||
|
checkResult = GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef);
|
||||||
|
}
|
||||||
|
else if ((varType->IsPointer()) || (varType->IsObjectOrInterface()))
|
||||||
{
|
{
|
||||||
checkResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType);
|
checkResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType);
|
||||||
}
|
}
|
||||||
|
@ -1841,8 +1845,12 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
||||||
{
|
{
|
||||||
exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType);
|
exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType);
|
||||||
}
|
}
|
||||||
else
|
else if (resolvedType->IsVar())
|
||||||
{
|
{
|
||||||
|
exprEvaluator->mResult = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Boolean), false, BfDefaultValueKind_Undef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Always true
|
// Always true
|
||||||
if ((!IsInSpecializedSection()) && (!resolvedType->IsGenericParam()))
|
if ((!IsInSpecializedSection()) && (!resolvedType->IsGenericParam()))
|
||||||
Warn(BfWarning_CS0472_ValueTypeNullCompare, StrFormat("Variable declaration is always 'true' since a value of type '%s' can never be null",
|
Warn(BfWarning_CS0472_ValueTypeNullCompare, StrFormat("Variable declaration is always 'true' since a value of type '%s' can never be null",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue