1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Made implicit tuple cast check names, fixed explicit tuple cast

This commit is contained in:
Brian Fiete 2020-01-24 10:36:22 -08:00
parent 1f77412536
commit fd64aa64d9
12 changed files with 92 additions and 87 deletions

View file

@ -2119,7 +2119,7 @@ namespace System
return false; return false;
} }
public (char32 c, int8 len) GetChar32(int idx) public (char32 c, int8 length) GetChar32(int idx)
{ {
Debug.Assert((uint)idx < (uint)mLength); Debug.Assert((uint)idx < (uint)mLength);
char8* ptr = Ptr; char8* ptr = Ptr;
@ -2131,7 +2131,7 @@ namespace System
return UTF8.Decode(ptr + idx, mLength - idx); return UTF8.Decode(ptr + idx, mLength - idx);
} }
public (char32 c, int idx, int8 len) GetChar32WithBacktrack(int idx) public (char32 c, int idx, int8 length) GetChar32WithBacktrack(int idx)
{ {
Debug.Assert((uint)idx < (uint)mLength); Debug.Assert((uint)idx < (uint)mLength);
char8* ptr = Ptr; char8* ptr = Ptr;

View file

@ -44,7 +44,7 @@ namespace System.Text
return UTF8.sTrailingBytesForUTF8[firstChar] + 1; return UTF8.sTrailingBytesForUTF8[firstChar] + 1;
} }
public static (char32 c, int8 cSize) Decode(char8* buf, int bufSize) public static (char32 c, int8 length) Decode(char8* buf, int bufSize)
{ {
char32 c = *buf; char32 c = *buf;
int8 trailingBytes = UTF8.sTrailingBytesForUTF8[c]; int8 trailingBytes = UTF8.sTrailingBytesForUTF8[c];

View file

@ -721,7 +721,7 @@ void BfAutoComplete::AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeIn
if ((fieldDef->mIsStatic) && (CheckProtection(fieldDef->mProtection, allowProtected, allowPrivate))) if ((fieldDef->mIsStatic) && (CheckProtection(fieldDef->mProtection, allowProtected, allowPrivate)))
{ {
if (!mModule->CanImplicitlyCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), fieldInst.mResolvedType), selfType)) if (!mModule->CanCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), fieldInst.mResolvedType), selfType))
continue; continue;
if ((!typeInst->IsTypeMemberIncluded(fieldDef->mDeclaringType, activeTypeDef, mModule)) || if ((!typeInst->IsTypeMemberIncluded(fieldDef->mDeclaringType, activeTypeDef, mModule)) ||
@ -772,7 +772,7 @@ void BfAutoComplete::AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeIn
continue; continue;
if (methodInstance->mReturnType->IsUnspecializedType()) if (methodInstance->mReturnType->IsUnspecializedType())
continue; continue;
if (!mModule->CanImplicitlyCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodInstance->mReturnType), selfType)) if (!mModule->CanCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodInstance->mReturnType), selfType))
continue; continue;
if (canUseMethod) if (canUseMethod)

View file

@ -240,7 +240,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
{ {
if (!arguments[argIdx].mTypedValue.mValue) if (!arguments[argIdx].mTypedValue.mValue)
return false; return false;
if (mModule->CanImplicitlyCast(arguments[argIdx].mTypedValue, wantType)) if (mModule->CanCast(arguments[argIdx].mTypedValue, wantType))
isDirectPass = true; isDirectPass = true;
} }

View file

@ -316,14 +316,14 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
if ((prevGenericMethodArg->IsIntUnknown()) && (!argType->IsIntUnknown())) if ((prevGenericMethodArg->IsIntUnknown()) && (!argType->IsIntUnknown()))
{ {
// Old int fits into new argType, that's good // Old int fits into new argType, that's good
if (mModule->CanImplicitlyCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType)) if (mModule->CanCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType))
{ {
_SetGeneric(); _SetGeneric();
return true; return true;
} }
// Doesn't fit, upgrade type to 'int' // Doesn't fit, upgrade type to 'int'
argType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); argType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
if (mModule->CanImplicitlyCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType)) if (mModule->CanCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType))
{ {
_SetGeneric(); _SetGeneric();
return true; return true;
@ -333,7 +333,7 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
if (argType->IsIntUnknown()) if (argType->IsIntUnknown())
{ {
// New int fits into previous arg type, that's good // New int fits into previous arg type, that's good
if (mModule->CanImplicitlyCast(BfTypedValue(argValue, argType), prevGenericMethodArg)) if (mModule->CanCast(BfTypedValue(argValue, argType), prevGenericMethodArg))
return true; return true;
// Doesn't fit, upgrade type to 'int' // Doesn't fit, upgrade type to 'int'
argType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); argType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
@ -341,12 +341,12 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
else else
{ {
// Prev is already best // Prev is already best
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(argType), prevGenericMethodArg)) if (mModule->CanCast(mModule->GetFakeTypedValue(argType), prevGenericMethodArg))
return true; return true;
} }
// New best? // New best?
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(prevGenericMethodArg), argType)) if (mModule->CanCast(mModule->GetFakeTypedValue(prevGenericMethodArg), argType))
{ {
_SetGeneric(); _SetGeneric();
return true; return true;
@ -556,8 +556,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
isWorse = true; isWorse = true;
else else
{ {
bool canCastFromCurToPrev = mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(paramType), prevParamType); bool canCastFromCurToPrev = mModule->CanCast(mModule->GetFakeTypedValue(paramType), prevParamType);
bool canCastFromPrevToCur = mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(prevParamType), paramType); bool canCastFromPrevToCur = mModule->CanCast(mModule->GetFakeTypedValue(prevParamType), paramType);
if ((canCastFromCurToPrev) && (!canCastFromPrevToCur)) if ((canCastFromCurToPrev) && (!canCastFromPrevToCur))
isBetter = true; isBetter = true;
@ -604,9 +604,9 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
} }
else else
{ {
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(paramType), prevParamType)) if (mModule->CanCast(mModule->GetFakeTypedValue(paramType), prevParamType))
isBetter = true; isBetter = true;
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(prevParamType), paramType)) if (mModule->CanCast(mModule->GetFakeTypedValue(prevParamType), paramType))
isWorse = true; isWorse = true;
}*/ }*/
} }
@ -1330,7 +1330,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0) if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0)
{ {
// Direct-pass params // Direct-pass params
if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType))) if ((argTypedValue.IsUntypedValue()) || (mModule->CanCast(argTypedValue, paramsArrayType)))
{ {
argIdx++; argIdx++;
argMatchCount++; argMatchCount++;
@ -1351,7 +1351,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType, genericArgumentsSubstitute); argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType, genericArgumentsSubstitute);
if (!argTypedValue.HasType()) if (!argTypedValue.HasType())
goto NoMatch; goto NoMatch;
if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType)) if (!mModule->CanCast(argTypedValue, paramsElementType))
goto NoMatch; goto NoMatch;
argIdx++; argIdx++;
argMatchCount++; argMatchCount++;
@ -1402,7 +1402,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
{ {
goto NoMatch; goto NoMatch;
} }
else if (!mModule->CanImplicitlyCast(argTypedValue, wantType)) else if (!mModule->CanCast(argTypedValue, wantType))
goto NoMatch; goto NoMatch;
} }
@ -5046,7 +5046,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (argIdx < (int)argValues.size()) if (argIdx < (int)argValues.size())
{ {
auto argValue = argValues[argIdx].mTypedValue; auto argValue = argValues[argIdx].mTypedValue;
if ((argValue.IsParams()) /*&& (mModule->CanImplicitlyCast(argValue, wantType))*/) if ((argValue.IsParams()) /*&& (mModule->CanCast(argValue, wantType))*/)
isDirectPass = true; isDirectPass = true;
} }
@ -14367,11 +14367,11 @@ void BfExprEvaluator::Visit(BfConditionalExpression* condExpr)
if ((ignoredValue) && (ignoredValue.mType != actualValue.mType)) if ((ignoredValue) && (ignoredValue.mType != actualValue.mType))
{ {
// Cast to more specific 'ignored' type if applicable // Cast to more specific 'ignored' type if applicable
if (mModule->CanImplicitlyCast(actualValue, ignoredValue.mType)) if (mModule->CanCast(actualValue, ignoredValue.mType))
{ {
actualValue = mModule->Cast(actualExpr, actualValue, ignoredValue.mType); actualValue = mModule->Cast(actualExpr, actualValue, ignoredValue.mType);
} }
else if (!mModule->CanImplicitlyCast(ignoredValue, actualValue.mType)) else if (!mModule->CanCast(ignoredValue, actualValue.mType))
{ {
mModule->Fail(StrFormat("Type of conditional expression cannot be determined because there is no implicit conversion between '%s' and '%s'", mModule->Fail(StrFormat("Type of conditional expression cannot be determined because there is no implicit conversion between '%s' and '%s'",
mModule->TypeToString(actualValue.mType).c_str(), mModule->TypeToString(ignoredValue.mType).c_str()), condExpr); mModule->TypeToString(actualValue.mType).c_str(), mModule->TypeToString(ignoredValue.mType).c_str()), condExpr);
@ -16377,7 +16377,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
{ {
if (opConstraint.mUnaryOp == findOp) if (opConstraint.mUnaryOp == findOp)
{ {
if (mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mRightType)) if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))
{ {
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType); mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
return; return;
@ -16398,7 +16398,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
{ {
if (opConstraint.mUnaryOp == findOp) if (opConstraint.mUnaryOp == findOp)
{ {
if (mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mRightType)) if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))
{ {
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType); mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
return; return;
@ -17246,7 +17246,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// If one of these is a constant that can be converted into a smaller type, then do that // If one of these is a constant that can be converted into a smaller type, then do that
if (rightValue.mValue.IsConst()) if (rightValue.mValue.IsConst())
{ {
if (mModule->CanImplicitlyCast(rightValue, leftValue.mType)) if (mModule->CanCast(rightValue, leftValue.mType))
{ {
resultType = leftValue.mType; resultType = leftValue.mType;
handled = true; handled = true;
@ -17258,7 +17258,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{ {
if (leftValue.mValue.IsConst()) if (leftValue.mValue.IsConst())
{ {
if (mModule->CanImplicitlyCast(leftValue, rightValue.mType)) if (mModule->CanCast(leftValue, rightValue.mType))
{ {
resultType = rightValue.mType; resultType = rightValue.mType;
handled = true; handled = true;
@ -17325,7 +17325,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// This case fixes cases like "c == 0" where "0" is technically an int but can be reduced // This case fixes cases like "c == 0" where "0" is technically an int but can be reduced
if ((binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_InEquality)) if ((binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_InEquality))
{ {
if ((resultType != otherType) && (resultTypedValue->mValue.IsConst()) && (mModule->CanImplicitlyCast(*resultTypedValue, otherType))) if ((resultType != otherType) && (resultTypedValue->mValue.IsConst()) && (mModule->CanCast(*resultTypedValue, otherType)))
{ {
std::swap(resultTypedValue, otherTypedValue); std::swap(resultTypedValue, otherTypedValue);
std::swap(resultTypeSrc, otherTypeSrc); std::swap(resultTypeSrc, otherTypeSrc);
@ -17582,8 +17582,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{ {
if (opConstraint.mBinaryOp == findBinaryOp) if (opConstraint.mBinaryOp == findBinaryOp)
{ {
if ((mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mLeftType)) && if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
(mModule->CanImplicitlyCast(args[1].mTypedValue, opConstraint.mRightType))) (mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
{ {
BF_ASSERT(genericParam->mExternType != NULL); BF_ASSERT(genericParam->mExternType != NULL);
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType); mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
@ -17605,8 +17605,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{ {
if (opConstraint.mBinaryOp == findBinaryOp) if (opConstraint.mBinaryOp == findBinaryOp)
{ {
if ((mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mLeftType)) && if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
(mModule->CanImplicitlyCast(args[1].mTypedValue, opConstraint.mRightType))) (mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
{ {
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType); mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
return; return;
@ -17891,9 +17891,9 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// We only do this for tuples, because we would allow an implicit struct // We only do this for tuples, because we would allow an implicit struct
// truncation if we allow it for all structs, which would result in only // truncation if we allow it for all structs, which would result in only
// the base class's fields being compared // the base class's fields being compared
if (mModule->CanImplicitlyCast(rightValue, leftValue.mType)) if (mModule->CanCast(rightValue, leftValue.mType))
rightValue = mModule->Cast(opToken, rightValue, leftValue.mType, BfCastFlags_Explicit); rightValue = mModule->Cast(opToken, rightValue, leftValue.mType, BfCastFlags_Explicit);
else if (mModule->CanImplicitlyCast(leftValue, rightValue.mType)) else if (mModule->CanCast(leftValue, rightValue.mType))
leftValue = mModule->Cast(opToken, leftValue, rightValue.mType, BfCastFlags_Explicit); leftValue = mModule->Cast(opToken, leftValue, rightValue.mType, BfCastFlags_Explicit);
} }
@ -17990,7 +17990,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
} }
else if ((!resultType->IsSigned()) && (otherType->IsSigned())) else if ((!resultType->IsSigned()) && (otherType->IsSigned()))
{ {
if (mModule->CanImplicitlyCast(*otherTypedValue, resultType)) if (mModule->CanCast(*otherTypedValue, resultType))
{ {
// If we can convert the 'other' value implicitly then it's a convertible literal, leave as uint // If we can convert the 'other' value implicitly then it's a convertible literal, leave as uint
} }

View file

@ -6627,7 +6627,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
constraintMatched = true; constraintMatched = true;
} }
else if (CanImplicitlyCast(GetFakeTypedValue(checkArgType), convCheckConstraint)) else if (CanCast(GetFakeTypedValue(checkArgType), convCheckConstraint))
{ {
constraintMatched = true; constraintMatched = true;
} }
@ -6654,7 +6654,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (!constraintMatched) if (!constraintMatched)
{ {
BfType* wrappedStructType = GetWrappedStructType(origCheckArgType, false); BfType* wrappedStructType = GetWrappedStructType(origCheckArgType, false);
if (CanImplicitlyCast(GetFakeTypedValue(wrappedStructType), convCheckConstraint)) if (CanCast(GetFakeTypedValue(wrappedStructType), convCheckConstraint))
constraintMatched = true; constraintMatched = true;
} }
} }
@ -6694,11 +6694,11 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
bool implementsInterface = false; bool implementsInterface = false;
if (origCheckArgType != checkArgType) if (origCheckArgType != checkArgType)
{ {
implementsInterface = CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, origCheckArgType), convCheckConstraint); implementsInterface = CanCast(BfTypedValue(BfIRValue::sValueless, origCheckArgType), convCheckConstraint);
} }
if (!implementsInterface) if (!implementsInterface)
implementsInterface = CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, checkArgType), convCheckConstraint); implementsInterface = CanCast(BfTypedValue(BfIRValue::sValueless, checkArgType), convCheckConstraint);
if ((!implementsInterface) && (origCheckArgType->IsWrappableType())) if ((!implementsInterface) && (origCheckArgType->IsWrappableType()))
{ {
@ -6762,7 +6762,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
} }
if ((!exprEvaluator.mResult) || if ((!exprEvaluator.mResult) ||
(!CanImplicitlyCast(exprEvaluator.mResult, origCheckArgType))) (!CanCast(exprEvaluator.mResult, origCheckArgType)))
{ {
if (!ignoreErrors) if (!ignoreErrors)
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(), *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(),
@ -6781,7 +6781,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (checkOpConstraint.mCastToken == BfToken_Implicit) if (checkOpConstraint.mCastToken == BfToken_Implicit)
{ {
if (!CanImplicitlyCast(rightValue, origCheckArgType, BfCastFlags_SilentFail)) if (!CanCast(rightValue, origCheckArgType, BfCastFlags_SilentFail))
failedOpName = "implicit conversion from '"; failedOpName = "implicit conversion from '";
} }
else else
@ -6801,7 +6801,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL); exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL);
if ((!exprEvaluator.mResult) || if ((!exprEvaluator.mResult) ||
(!CanImplicitlyCast(exprEvaluator.mResult, origCheckArgType))) (!CanCast(exprEvaluator.mResult, origCheckArgType)))
{ {
failedOpName += "unary operation '"; failedOpName += "unary operation '";
failedOpName += BfGetOpName(checkOpConstraint.mUnaryOp); failedOpName += BfGetOpName(checkOpConstraint.mUnaryOp);
@ -19260,7 +19260,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{ {
defaultValue = castedDefaultValue; // Good! defaultValue = castedDefaultValue; // Good!
} }
else if (!CanImplicitlyCast(defaultValue, resolvedParamType)) else if (!CanCast(defaultValue, resolvedParamType))
{ {
// We only care that we get a constant value that can be implicitly casted at the callsite- even if that requires // We only care that we get a constant value that can be implicitly casted at the callsite- even if that requires
// a conversion operator. // a conversion operator.

View file

@ -1482,7 +1482,7 @@ public:
BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false); BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false);
void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry); void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry);
void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail); void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
bool CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None); bool CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
bool AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting); bool AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting);
BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, bool callDtor = true); BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, bool callDtor = true);
BfIRValue CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodInstance, BfType* toType, BfCastFlags castFlags = BfCastFlags_None); BfIRValue CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodInstance, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);

View file

@ -3954,7 +3954,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
// Concrete // Concrete
if (matchedMethod->mReturnType->IsInterface()) if (matchedMethod->mReturnType->IsInterface())
hadMatch = false; hadMatch = false;
else if (!CanImplicitlyCast(GetFakeTypedValue(matchedMethod->mReturnType), iReturnType)) else if (!CanCast(GetFakeTypedValue(matchedMethod->mReturnType), iReturnType))
hadMatch = false; hadMatch = false;
} }
@ -4655,7 +4655,7 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
{ {
if ((lhs.mType != NULL) && (lhs.mType->IsIntUnknown()) && (rhs.mType != NULL) && (rhs.mType->IsInteger())) if ((lhs.mType != NULL) && (lhs.mType->IsIntUnknown()) && (rhs.mType != NULL) && (rhs.mType->IsInteger()))
{ {
if (CanImplicitlyCast(lhs, rhs.mType)) if (CanCast(lhs, rhs.mType))
{ {
lhs = Cast(NULL, lhs, rhs.mType, BfCastFlags_SilentFail); lhs = Cast(NULL, lhs, rhs.mType, BfCastFlags_SilentFail);
if (!lhs) if (!lhs)
@ -4666,7 +4666,7 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
if ((rhs.mType != NULL) && (rhs.mType->IsIntUnknown()) && (lhs.mType != NULL) && (lhs.mType->IsInteger())) if ((rhs.mType != NULL) && (rhs.mType->IsIntUnknown()) && (lhs.mType != NULL) && (lhs.mType->IsInteger()))
{ {
if (CanImplicitlyCast(rhs, lhs.mType)) if (CanCast(rhs, lhs.mType))
{ {
rhs = Cast(NULL, rhs, lhs.mType, BfCastFlags_SilentFail); rhs = Cast(NULL, rhs, lhs.mType, BfCastFlags_SilentFail);
if (!rhs) if (!rhs)
@ -6409,7 +6409,7 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
if ((genericTypeConstraint != NULL) && (expectingType != NULL)) if ((genericTypeConstraint != NULL) && (expectingType != NULL))
{ {
if (!CanImplicitlyCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType)) if (!CanCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType))
{ {
Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", TypeToString(genericTypeConstraint).c_str()), identifierNode); Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", TypeToString(genericTypeConstraint).c_str()), identifierNode);
} }
@ -7780,9 +7780,9 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeRe
} }
// This flow should mirror CastToValue // This flow should mirror CastToValue
bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags) bool BfModule::CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
{ {
BP_ZONE("BfModule::CanImplicitlyCast"); BP_ZONE("BfModule::CanCast");
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
return CastToValue(NULL, typedVal, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail)); return CastToValue(NULL, typedVal, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
@ -8837,7 +8837,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
if (fromDist < 0) if (fromDist < 0)
{ {
// Allow us to cast a constant int to a smaller type if it satisfies the cast operator // Allow us to cast a constant int to a smaller type if it satisfies the cast operator
if ((typedVal.mValue.IsConst()) && (CanImplicitlyCast(typedVal, methodCheckFromType, BfCastFlags_NoConversionOperator))) if ((typedVal.mValue.IsConst()) && (CanCast(typedVal, methodCheckFromType, BfCastFlags_NoConversionOperator)))
{ {
fromDist = 0; fromDist = 0;
} }
@ -9003,11 +9003,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit))) ((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
{ {
// If we can convert OUR fromVal to the constraint's fromVal then we may match // If we can convert OUR fromVal to the constraint's fromVal then we may match
if (CanImplicitlyCast(typedVal, opConstraint.mRightType)) if (CanCast(typedVal, opConstraint.mRightType))
{ {
// .. and we can convert the constraint's toType to OUR toType then we're good // .. and we can convert the constraint's toType to OUR toType then we're good
auto opToVal = genericParam->mExternType; auto opToVal = genericParam->mExternType;
if (CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType)) if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
return mBfIRBuilder->GetFakeVal(); return mBfIRBuilder->GetFakeVal();
} }
} }
@ -9028,11 +9028,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit))) ((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
{ {
// If we can convert OUR fromVal to the constraint's fromVal then we may match // If we can convert OUR fromVal to the constraint's fromVal then we may match
if (CanImplicitlyCast(typedVal, opConstraint.mRightType)) if (CanCast(typedVal, opConstraint.mRightType))
{ {
// .. and we can convert the constraint's toType to OUR toType then we're good // .. and we can convert the constraint's toType to OUR toType then we're good
auto opToVal = genericParam->mExternType; auto opToVal = genericParam->mExternType;
if (CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType)) if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
return mBfIRBuilder->GetFakeVal(); return mBfIRBuilder->GetFakeVal();
} }
} }
@ -9232,7 +9232,8 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
if (!toFieldDef->IsUnnamedTupleField()) if (!toFieldDef->IsUnnamedTupleField())
{ {
if ((!fromFieldDef->IsUnnamedTupleField()) && if ((!explicitCast) &&
(!fromFieldDef->IsUnnamedTupleField()) &&
(fromFieldDef->mName != toFieldDef->mName)) (fromFieldDef->mName != toFieldDef->mName))
isCompatible = false; isCompatible = false;
fieldNames.push_back(toFieldDef->mName); fieldNames.push_back(toFieldDef->mName);
@ -9247,10 +9248,14 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
if (fromFieldInst->mResolvedType != toFieldInst->mResolvedType) if (fromFieldInst->mResolvedType != toFieldInst->mResolvedType)
isExactTypeMatch = false; isExactTypeMatch = false;
BfCastFlags tryCastFlags = BfCastFlags_SilentFail;
if (explicitCast)
tryCastFlags = (BfCastFlags)(tryCastFlags | BfCastFlags_Explicit);
// The unused-token '?' comes out as 'void', so we allow that to match here. We may want to wrap that with a different fake type // The unused-token '?' comes out as 'void', so we allow that to match here. We may want to wrap that with a different fake type
// so we can give normal implicit-cast-to-void errors // so we can give normal implicit-cast-to-void errors
if ((fromFieldInst->mResolvedType != toFieldInst->mResolvedType) && (!toFieldInst->mResolvedType->IsVoid()) && if ((fromFieldInst->mResolvedType != toFieldInst->mResolvedType) && (!toFieldInst->mResolvedType->IsVoid()) &&
(!CanImplicitlyCast(GetFakeTypedValue(fromFieldInst->mResolvedType), toFieldInst->mResolvedType))) (!CanCast(GetFakeTypedValue(fromFieldInst->mResolvedType), toFieldInst->mResolvedType, tryCastFlags)))
isCompatible = false; isCompatible = false;
fieldTypes.push_back(toFieldInst->mResolvedType); fieldTypes.push_back(toFieldInst->mResolvedType);
} }
@ -9260,25 +9265,25 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
AddDependency(tupleType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields); AddDependency(tupleType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mBfIRBuilder->PopulateType(tupleType); mBfIRBuilder->PopulateType(tupleType);
if (isExactTypeMatch)
{
if (typedVal.mKind == BfTypedValueKind_TempAddr)
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_TempAddr);
}
else if (typedVal.IsAddr())
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_ReadOnlyAddr);
}
BfIRValue curTupleValue = CreateAlloca(tupleType);
auto loadedVal = LoadValue(typedVal);
mBfIRBuilder->CreateStore(loadedVal.mValue, mBfIRBuilder->CreateBitCast(curTupleValue, mBfIRBuilder->MapTypeInstPtr(fromTupleType)));
return BfTypedValue(curTupleValue, tupleType, BfTypedValueKind_TempAddr);
}
if (isCompatible) if (isCompatible)
{ {
if (isExactTypeMatch)
{
if (typedVal.mKind == BfTypedValueKind_TempAddr)
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_TempAddr);
}
else if (typedVal.IsAddr())
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_ReadOnlyAddr);
}
BfIRValue curTupleValue = CreateAlloca(tupleType);
auto loadedVal = LoadValue(typedVal);
mBfIRBuilder->CreateStore(loadedVal.mValue, mBfIRBuilder->CreateBitCast(curTupleValue, mBfIRBuilder->MapTypeInstPtr(fromTupleType)));
return BfTypedValue(curTupleValue, tupleType, BfTypedValueKind_TempAddr);
}
BfIRValue curTupleValue = CreateAlloca(tupleType); BfIRValue curTupleValue = CreateAlloca(tupleType);
for (int fieldIdx = 0; fieldIdx < (int)fromTupleType->mFieldInstances.size(); fieldIdx++) for (int fieldIdx = 0; fieldIdx < (int)fromTupleType->mFieldInstances.size(); fieldIdx++)
{ {

View file

@ -2451,7 +2451,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
/*BF_ASSERT(typedVal.mType->IsGenericParam()); /*BF_ASSERT(typedVal.mType->IsGenericParam());
auto genericParamInstance = ctx->mModule->GetGenericParamInstance((BfGenericParamType*)typedVal.mType); auto genericParamInstance = ctx->mModule->GetGenericParamInstance((BfGenericParamType*)typedVal.mType);
if ((genericParamInstance->mTypeConstraint == NULL) || if ((genericParamInstance->mTypeConstraint == NULL) ||
(!ctx->mModule->CanImplicitlyCast(BfTypedValue(ctx->mModule->mBfIRBuilder->GetFakeVal(), genericParamInstance->mTypeConstraint), (!ctx->mModule->CanCast(BfTypedValue(ctx->mModule->mBfIRBuilder->GetFakeVal(), genericParamInstance->mTypeConstraint),
ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr)))) ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr))))
{ {
ctx->mModule->Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", ctx->mModule->TypeToString(typedVal.mType).c_str()), sizeExpr); ctx->mModule->Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", ctx->mModule->TypeToString(typedVal.mType).c_str()), sizeExpr);

View file

@ -1018,7 +1018,7 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
BfTypeInstance* srcTypeInstance = initValue.mType->ToTypeInstance(); BfTypeInstance* srcTypeInstance = initValue.mType->ToTypeInstance();
BfTypeInstance* varTypeInstance = varType->ToTypeInstance(); BfTypeInstance* varTypeInstance = varType->ToTypeInstance();
if (CanImplicitlyCast(initValue, varType)) if (CanCast(initValue, varType))
{ {
if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface())) if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface()))
{ {
@ -1044,7 +1044,7 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
// // Class downcast // // Class downcast
// isDynamicCast = true; // isDynamicCast = true;
// } // }
// else if ((!CanImplicitlyCast(GetFakeTypedValue(varType), initType)) && (!initType->IsGenericParam())) // else if ((!CanCast(GetFakeTypedValue(varType), initType)) && (!initType->IsGenericParam()))
// { // {
// if (!IsInSpecializedSection()) // if (!IsInSpecializedSection())
// { // {

View file

@ -65,11 +65,11 @@ DwMethodMatcher::DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEva
} }
// Prev is already best // Prev is already best
if (mModule->CanImplicitlyCast(DbgTypedValue(NULL, argType), prevGenericMethodArg)) if (mModule->CanCast(DbgTypedValue(NULL, argType), prevGenericMethodArg))
return true; return true;
// New best? // New best?
if (mModule->CanImplicitlyCast(DbgTypedValue(NULL, prevGenericMethodArg), argType)) if (mModule->CanCast(DbgTypedValue(NULL, prevGenericMethodArg), argType))
{ {
mCheckMethodGenericArguments[wantGenericParam->mGenericParamIdx] = argType; mCheckMethodGenericArguments[wantGenericParam->mGenericParamIdx] = argType;
return true; return true;
@ -198,9 +198,9 @@ void DwMethodMatcher::CompareMethods(DbgSubprogram* prevMethodInstance, DwTypeVe
} }
else else
{ {
if (mExprEvaluator->CanImplicitlyCast(DbgTypedValue::GetValueless(paramType), prevParamType)) if (mExprEvaluator->CanCast(DbgTypedValue::GetValueless(paramType), prevParamType))
isBetter = true; isBetter = true;
if (mExprEvaluator->CanImplicitlyCast(DbgTypedValue::GetValueless(prevParamType), paramType)) if (mExprEvaluator->CanCast(DbgTypedValue::GetValueless(prevParamType), paramType))
isWorse = true; isWorse = true;
} }
} }
@ -387,7 +387,7 @@ bool DwMethodMatcher::CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMet
// Check to see if we're directly passing the params type (like an int[]) // Check to see if we're directly passing the params type (like an int[])
auto paramsArrayType = methodInstance->mParamTypes[paramIdx]; auto paramsArrayType = methodInstance->mParamTypes[paramIdx];
if (mModule->CanImplicitlyCast(mArguments[argIdx], paramsArrayType)) if (mModule->CanCast(mArguments[argIdx], paramsArrayType))
{ {
argIdx++; argIdx++;
paramIdx++; paramIdx++;
@ -402,7 +402,7 @@ bool DwMethodMatcher::CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMet
{ {
if (!mArguments[argIdx]) if (!mArguments[argIdx])
goto NoMatch; goto NoMatch;
if (!mModule->CanImplicitlyCast(mArguments[argIdx], paramsElementType)) if (!mModule->CanCast(mArguments[argIdx], paramsElementType))
goto NoMatch; goto NoMatch;
argIdx++; argIdx++;
} }
@ -428,7 +428,7 @@ bool DwMethodMatcher::CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMet
goto NoMatch; goto NoMatch;
if (!mExprEvaluator->CanImplicitlyCast(mArguments[argIdx], wantType)) if (!mExprEvaluator->CanCast(mArguments[argIdx], wantType))
goto NoMatch; goto NoMatch;
paramIdx++; paramIdx++;
@ -1510,7 +1510,7 @@ bool DbgExprEvaluator::CheckHasValue(DbgTypedValue typedValue, BfAstNode* refNod
} }
//TODO: Expand this //TODO: Expand this
bool DbgExprEvaluator::CanImplicitlyCast(DbgTypedValue typedVal, DbgType* toType) bool DbgExprEvaluator::CanCast(DbgTypedValue typedVal, DbgType* toType, BfCastFlags castFlags)
{ {
DbgType* fromType = typedVal.mType; DbgType* fromType = typedVal.mType;
@ -6003,7 +6003,7 @@ void DbgExprEvaluator::PerformBinaryOperation(ASTREF(BfExpression*)& leftExpress
} }
else if ((!resultType->IsSigned()) && (otherType->IsSigned())) else if ((!resultType->IsSigned()) && (otherType->IsSigned()))
{ {
/*if (CanImplicitlyCast(*otherTypedValue, resultType)) /*if (CanCast(*otherTypedValue, resultType))
{ {
// If we can convert the 'other' value implicitly then it's a convertible literal, leave as uint // If we can convert the 'other' value implicitly then it's a convertible literal, leave as uint
} }
@ -6864,7 +6864,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(BfAstNode* targetSrc, DbgTypedValue t
{ {
if (argValues[argIdx].mValue == NULL) if (argValues[argIdx].mValue == NULL)
return DbgTypedValue(); return DbgTypedValue();
if (mModule->CanImplicitlyCast(argValues[argIdx], wantType)) if (mModule->CanCast(argValues[argIdx], wantType))
isDirectPass = true; isDirectPass = true;
} }

View file

@ -362,7 +362,7 @@ public:
String TypeToString(DbgType* type); String TypeToString(DbgType* type);
bool CheckHasValue(DbgTypedValue typedValue, BfAstNode* refNode); bool CheckHasValue(DbgTypedValue typedValue, BfAstNode* refNode);
bool CanImplicitlyCast(DbgTypedValue typedVal, DbgType* toType); bool CanCast(DbgTypedValue typedVal, DbgType* toType, BfCastFlags castFlags = BfCastFlags_None);
DbgTypedValue Cast(BfAstNode* srcNode, const DbgTypedValue& val, DbgType* toType, bool explicitCast = false, bool silentFail = false); DbgTypedValue Cast(BfAstNode* srcNode, const DbgTypedValue& val, DbgType* toType, bool explicitCast = false, bool silentFail = false);
bool HasField(DbgType* type, const StringImpl& fieldName); bool HasField(DbgType* type, const StringImpl& fieldName);
DbgTypedValue DoLookupField(BfAstNode* targetSrc, DbgTypedValue target, DbgType* curCheckType, const StringImpl& fieldName, CPUStackFrame* stackFrame, bool allowImplicitThis); DbgTypedValue DoLookupField(BfAstNode* targetSrc, DbgTypedValue target, DbgType* curCheckType, const StringImpl& fieldName, CPUStackFrame* stackFrame, bool allowImplicitThis);