mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Support for operators with ref
parameters, sized array->span
This commit is contained in:
parent
5c05b15b37
commit
1e52dce7c4
9 changed files with 183 additions and 31 deletions
|
@ -20,11 +20,23 @@ namespace System
|
||||||
return val.mVal;
|
return val.mVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public implicit static operator Span<T> (ref Self val)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return .(&val.mVal, CSize);
|
||||||
|
}
|
||||||
|
|
||||||
public override void ToString(String strBuffer) mut
|
public override void ToString(String strBuffer) mut
|
||||||
{
|
{
|
||||||
if (typeof(T) == typeof(char8))
|
if (typeof(T) == typeof(char8))
|
||||||
{
|
{
|
||||||
strBuffer.Append((char8*)&mVal, CSize);
|
int len = 0;
|
||||||
|
for (; len < CSize; len++)
|
||||||
|
{
|
||||||
|
if (mVal[len] == default)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strBuffer.Append((char8*)&mVal, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +99,7 @@ namespace System
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return mIndex - 1;
|
return mIndex - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<T> GetNext() mut
|
public Result<T> GetNext() mut
|
||||||
|
|
|
@ -177,6 +177,7 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
|
||||||
mAllowNonStatic = true;
|
mAllowNonStatic = true;
|
||||||
mSkipImplicitParams = false;
|
mSkipImplicitParams = false;
|
||||||
mAllowImplicitThis = false;
|
mAllowImplicitThis = false;
|
||||||
|
mAllowImplicitRef = false;
|
||||||
mHadVarConflictingReturnType = false;
|
mHadVarConflictingReturnType = false;
|
||||||
mAutoFlushAmbiguityErrors = true;
|
mAutoFlushAmbiguityErrors = true;
|
||||||
mMethodCheckCount = 0;
|
mMethodCheckCount = 0;
|
||||||
|
@ -2066,8 +2067,13 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
||||||
|
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
}
|
}
|
||||||
else if (!mModule->CanCast(argTypedValue, wantType))
|
else
|
||||||
goto NoMatch;
|
{
|
||||||
|
if ((mAllowImplicitRef) && (wantType->IsRef()) && (!argTypedValue.mType->IsRef()))
|
||||||
|
wantType = wantType->GetUnderlyingType();
|
||||||
|
if (!mModule->CanCast(argTypedValue, wantType))
|
||||||
|
goto NoMatch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paramIdx++;
|
paramIdx++;
|
||||||
|
@ -5964,7 +5970,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTyped
|
||||||
|
|
||||||
PerformCallChecks(moduleMethodInstance.mMethodInstance, methodMatcher->mTargetSrc);
|
PerformCallChecks(moduleMethodInstance.mMethodInstance, methodMatcher->mTargetSrc);
|
||||||
|
|
||||||
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, false, methodMatcher->mArguments);
|
BfCreateFallFlags callFlags = BfCreateFallFlags_None;
|
||||||
|
if (methodMatcher->mAllowImplicitRef)
|
||||||
|
callFlags = (BfCreateFallFlags)(callFlags | BfCreateFallFlags_AllowImplicitRef);
|
||||||
|
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, callFlags, methodMatcher->mArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::MakeBaseConcrete(BfTypedValue& typedValue)
|
void BfExprEvaluator::MakeBaseConcrete(BfTypedValue& typedValue)
|
||||||
|
@ -6295,8 +6304,11 @@ void BfExprEvaluator::AddCallDependencies(BfMethodInstance* methodInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: delete argumentsZ
|
//TODO: delete argumentsZ
|
||||||
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade, bool skipThis)
|
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, BfCreateFallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade)
|
||||||
{
|
{
|
||||||
|
bool bypassVirtual = (callFlags & BfCreateFallFlags_BypassVirtual) != 0;
|
||||||
|
bool skipThis = (callFlags & BfCreateFallFlags_SkipThis) != 0;;
|
||||||
|
|
||||||
static int sCallIdx = 0;
|
static int sCallIdx = 0;
|
||||||
if (!mModule->mCompiler->mIsResolveOnly)
|
if (!mModule->mCompiler->mIsResolveOnly)
|
||||||
sCallIdx++;
|
sCallIdx++;
|
||||||
|
@ -6999,6 +7011,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
if (refNode == NULL)
|
if (refNode == NULL)
|
||||||
refNode = targetSrc;
|
refNode = targetSrc;
|
||||||
|
|
||||||
|
if (((callFlags & BfCreateFallFlags_AllowImplicitRef) != 0) &&
|
||||||
|
(wantType->IsRef()) && (!argValue.mType->IsRef()))
|
||||||
|
argValue = mModule->ToRef(argValue, (BfRefType*)wantType);
|
||||||
|
|
||||||
if (mModule->mCurMethodState != NULL)
|
if (mModule->mCurMethodState != NULL)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<BfScopeData*> prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData);
|
SetAndRestoreValue<BfScopeData*> prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData);
|
||||||
|
@ -7413,7 +7429,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
|
||||||
if (isFailurePass)
|
if (isFailurePass)
|
||||||
mModule->Fail(StrFormat("'%s' is inaccessible due to its protection level", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
mModule->Fail(StrFormat("'%s' is inaccessible due to its protection level", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||||
prevBindResult.Restore();
|
prevBindResult.Restore();
|
||||||
return CreateCall(methodMatcher.mTargetSrc, target, BfTypedValue(), methodMatcher.mBestMethodDef, moduleMethodInstance, false, methodMatcher.mArguments);
|
return CreateCall(methodMatcher.mTargetSrc, target, BfTypedValue(), methodMatcher.mBestMethodDef, moduleMethodInstance, BfCreateFallFlags_None, methodMatcher.mArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sInvocationIdx = 0;
|
static int sInvocationIdx = 0;
|
||||||
|
@ -8987,7 +9003,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, bypassVirtual, argValues.mResolvedArgs, &argCascade, skipThis);
|
BfCreateFallFlags subCallFlags = BfCreateFallFlags_None;
|
||||||
|
if (bypassVirtual)
|
||||||
|
subCallFlags = (BfCreateFallFlags)(subCallFlags | BfCreateFallFlags_BypassVirtual);
|
||||||
|
if (skipThis)
|
||||||
|
subCallFlags = (BfCreateFallFlags)(subCallFlags | BfCreateFallFlags_SkipThis);
|
||||||
|
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overrideReturnType != NULL)
|
if (overrideReturnType != NULL)
|
||||||
|
@ -19429,6 +19450,7 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
|
||||||
args.push_back(resolvedArg);
|
args.push_back(resolvedArg);
|
||||||
BfMethodMatcher methodMatcher(opToken, mModule, "", args, NULL);
|
BfMethodMatcher methodMatcher(opToken, mModule, "", args, NULL);
|
||||||
methodMatcher.mBfEvalExprFlags = BfEvalExprFlags_NoAutoComplete;
|
methodMatcher.mBfEvalExprFlags = BfEvalExprFlags_NoAutoComplete;
|
||||||
|
methodMatcher.mAllowImplicitRef = true;
|
||||||
BfBaseClassWalker baseClassWalker(inValue.mType, NULL, mModule);
|
BfBaseClassWalker baseClassWalker(inValue.mType, NULL, mModule);
|
||||||
|
|
||||||
BfUnaryOp findOp = unaryOp;
|
BfUnaryOp findOp = unaryOp;
|
||||||
|
@ -20885,9 +20907,13 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
args.push_back(leftArg);
|
args.push_back(leftArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto checkLeftType = leftValue.mType;
|
||||||
|
auto checkRightType = rightValue.mType;
|
||||||
|
|
||||||
BfMethodMatcher methodMatcher(opToken, mModule, "", args, NULL);
|
BfMethodMatcher methodMatcher(opToken, mModule, "", args, NULL);
|
||||||
|
methodMatcher.mAllowImplicitRef = true;
|
||||||
methodMatcher.mBfEvalExprFlags = BfEvalExprFlags_NoAutoComplete;
|
methodMatcher.mBfEvalExprFlags = BfEvalExprFlags_NoAutoComplete;
|
||||||
BfBaseClassWalker baseClassWalker(leftValue.mType, rightValue.mType, mModule);
|
BfBaseClassWalker baseClassWalker(checkLeftType, checkRightType, mModule);
|
||||||
|
|
||||||
bool invertResult = false;
|
bool invertResult = false;
|
||||||
BfType* operatorConstraintReturnType = NULL;
|
BfType* operatorConstraintReturnType = NULL;
|
||||||
|
@ -21461,7 +21487,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
argValues.push_back(resolvedArg);
|
argValues.push_back(resolvedArg);
|
||||||
resolvedArg.mTypedValue = rightValue;
|
resolvedArg.mTypedValue = rightValue;
|
||||||
argValues.push_back(resolvedArg);
|
argValues.push_back(resolvedArg);
|
||||||
mResult = CreateCall(opToken, BfTypedValue(), BfTypedValue(), moduleMethodInstance.mMethodInstance->mMethodDef, moduleMethodInstance, false, argValues);
|
mResult = CreateCall(opToken, BfTypedValue(), BfTypedValue(), moduleMethodInstance.mMethodInstance->mMethodDef, moduleMethodInstance, BfCreateFallFlags_None, argValues);
|
||||||
if ((mResult) &&
|
if ((mResult) &&
|
||||||
((binaryOp == BfBinaryOp_InEquality) || (binaryOp == BfBinaryOp_StrictInEquality)))
|
((binaryOp == BfBinaryOp_InEquality) || (binaryOp == BfBinaryOp_StrictInEquality)))
|
||||||
mResult.mValue = mModule->mBfIRBuilder->CreateNot(mResult.mValue);
|
mResult.mValue = mModule->mBfIRBuilder->CreateNot(mResult.mValue);
|
||||||
|
|
|
@ -41,6 +41,14 @@ enum BfResolveArgFlags
|
||||||
BfResolveArgFlag_FromGenericParam = 2
|
BfResolveArgFlag_FromGenericParam = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BfCreateFallFlags
|
||||||
|
{
|
||||||
|
BfCreateFallFlags_None,
|
||||||
|
BfCreateFallFlags_BypassVirtual = 1,
|
||||||
|
BfCreateFallFlags_SkipThis = 2,
|
||||||
|
BfCreateFallFlags_AllowImplicitRef = 4
|
||||||
|
};
|
||||||
|
|
||||||
class BfResolvedArg
|
class BfResolvedArg
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -186,10 +194,11 @@ public:
|
||||||
bool mHadVarConflictingReturnType;
|
bool mHadVarConflictingReturnType;
|
||||||
bool mBypassVirtual;
|
bool mBypassVirtual;
|
||||||
bool mAllowImplicitThis;
|
bool mAllowImplicitThis;
|
||||||
|
bool mAllowImplicitRef;
|
||||||
bool mAllowStatic;
|
bool mAllowStatic;
|
||||||
bool mAllowNonStatic;
|
bool mAllowNonStatic;
|
||||||
bool mSkipImplicitParams;
|
bool mSkipImplicitParams;
|
||||||
bool mAutoFlushAmbiguityErrors;
|
bool mAutoFlushAmbiguityErrors;
|
||||||
BfEvalExprFlags mBfEvalExprFlags;
|
BfEvalExprFlags mBfEvalExprFlags;
|
||||||
int mMethodCheckCount;
|
int mMethodCheckCount;
|
||||||
BfType* mExplicitInterfaceCheck;
|
BfType* mExplicitInterfaceCheck;
|
||||||
|
@ -435,7 +444,7 @@ public:
|
||||||
void AddCallDependencies(BfMethodInstance* methodInstance);
|
void AddCallDependencies(BfMethodInstance* methodInstance);
|
||||||
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
|
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
|
||||||
BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false);
|
BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false);
|
||||||
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL, bool skipThis = false);
|
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, BfCreateFallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL);
|
||||||
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
|
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
|
||||||
void MakeBaseConcrete(BfTypedValue& typedValue);
|
void MakeBaseConcrete(BfTypedValue& typedValue);
|
||||||
void SplatArgs(BfTypedValue value, SizedArrayImpl<BfIRValue>& irArgs);
|
void SplatArgs(BfTypedValue value, SizedArrayImpl<BfIRValue>& irArgs);
|
||||||
|
|
|
@ -11512,6 +11512,23 @@ BfTypedValue BfModule::RemoveRef(BfTypedValue typedValue)
|
||||||
return typedValue;
|
return typedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfTypedValue BfModule::ToRef(BfTypedValue typedValue, BfRefType* refType)
|
||||||
|
{
|
||||||
|
if (refType == NULL)
|
||||||
|
refType = CreateRefType(typedValue.mType);
|
||||||
|
|
||||||
|
if ((refType->mRefKind == BfRefType::RefKind_Mut) && (typedValue.mType->IsObjectOrInterface()))
|
||||||
|
{
|
||||||
|
return LoadValue(typedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refType->mRefKind == BfRefType::RefKind_Mut)
|
||||||
|
refType = CreateRefType(typedValue.mType);
|
||||||
|
|
||||||
|
typedValue = MakeAddressable(typedValue);
|
||||||
|
return BfTypedValue(typedValue.mValue, refType);
|
||||||
|
}
|
||||||
|
|
||||||
BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bool isVolatile)
|
BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bool isVolatile)
|
||||||
{
|
{
|
||||||
if (!typedValue.IsAddr())
|
if (!typedValue.IsAddr())
|
||||||
|
@ -18299,10 +18316,17 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
Fail("Binary operators must declare two parameters", paramErrorRefNode);
|
Fail("Binary operators must declare two parameters", paramErrorRefNode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((mCurMethodInstance->GetParamType(0) != mCurTypeInstance) && (!mCurMethodInstance->GetParamType(0)->IsSelf()) &&
|
auto checkParam0 = mCurMethodInstance->GetParamType(0);
|
||||||
(mCurMethodInstance->GetParamType(1) != mCurTypeInstance) && (!mCurMethodInstance->GetParamType(1)->IsSelf()))
|
if ((checkParam0->IsRef()) && (!checkParam0->IsOut()))
|
||||||
{
|
checkParam0 = checkParam0->GetUnderlyingType();
|
||||||
|
auto checkParam1 = mCurMethodInstance->GetParamType(1);
|
||||||
|
if ((checkParam1->IsRef()) && (!checkParam1->IsOut()))
|
||||||
|
checkParam1 = checkParam1->GetUnderlyingType();
|
||||||
|
|
||||||
|
if ((checkParam0 != mCurTypeInstance) && (!checkParam0->IsSelf()) &&
|
||||||
|
(checkParam1 != mCurTypeInstance) && (!checkParam1->IsSelf()))
|
||||||
|
{
|
||||||
Fail("At least one of the parameters of a binary operator must be the containing type", paramErrorRefNode);
|
Fail("At least one of the parameters of a binary operator must be the containing type", paramErrorRefNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18321,11 +18345,15 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
{
|
{
|
||||||
if (methodDef->mIsStatic)
|
if (methodDef->mIsStatic)
|
||||||
{
|
{
|
||||||
|
auto checkParam0 = mCurMethodInstance->GetParamType(0);
|
||||||
|
if ((checkParam0->IsRef()) && (!checkParam0->IsOut()))
|
||||||
|
checkParam0 = checkParam0->GetUnderlyingType();
|
||||||
|
|
||||||
if (methodDef->mParams.size() != 1)
|
if (methodDef->mParams.size() != 1)
|
||||||
{
|
{
|
||||||
Fail("Unary operators must declare one parameter", paramErrorRefNode);
|
Fail("Unary operators must declare one parameter", paramErrorRefNode);
|
||||||
}
|
}
|
||||||
else if ((mCurMethodInstance->GetParamType(0) != mCurTypeInstance) && (!mCurMethodInstance->GetParamType(0)->IsSelf()))
|
else if ((checkParam0 != mCurTypeInstance) && (!checkParam0->IsSelf()))
|
||||||
{
|
{
|
||||||
Fail("The parameter of a unary operator must be the containing type", paramErrorRefNode);
|
Fail("The parameter of a unary operator must be the containing type", paramErrorRefNode);
|
||||||
}
|
}
|
||||||
|
@ -18379,18 +18407,22 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((mCurMethodInstance->GetParamType(0) != mCurTypeInstance) && (!mCurMethodInstance->GetParamType(0)->IsSelf()) &&
|
auto checkParam0 = mCurMethodInstance->GetParamType(0);
|
||||||
|
if ((checkParam0->IsRef()) && (!checkParam0->IsOut()))
|
||||||
|
checkParam0 = checkParam0->GetUnderlyingType();
|
||||||
|
|
||||||
|
if ((checkParam0 != mCurTypeInstance) && (!checkParam0->IsSelf()) &&
|
||||||
(mCurMethodInstance->mReturnType != mCurTypeInstance) && (!mCurMethodInstance->mReturnType->IsSelf()))
|
(mCurMethodInstance->mReturnType != mCurTypeInstance) && (!mCurMethodInstance->mReturnType->IsSelf()))
|
||||||
Fail("User-defined conversion must convert to or from the enclosing type", paramErrorRefNode);
|
Fail("User-defined conversion must convert to or from the enclosing type", paramErrorRefNode);
|
||||||
if (mCurMethodInstance->GetParamType(0) == mCurMethodInstance->mReturnType)
|
if (checkParam0 == mCurMethodInstance->mReturnType)
|
||||||
Fail("User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type", operatorDef->mOperatorDeclaration->mReturnType);
|
Fail("User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type", operatorDef->mOperatorDeclaration->mReturnType);
|
||||||
|
|
||||||
// On type lookup error we default to 'object', so don't do the 'base class' error if that may have
|
// On type lookup error we default to 'object', so don't do the 'base class' error if that may have
|
||||||
// happened here
|
// happened here
|
||||||
if ((!mHadBuildError) || ((mCurMethodInstance->mReturnType != mContext->mBfObjectType) && (mCurMethodInstance->GetParamType(0) != mContext->mBfObjectType)))
|
if ((!mHadBuildError) || ((mCurMethodInstance->mReturnType != mContext->mBfObjectType) && (checkParam0 != mContext->mBfObjectType)))
|
||||||
{
|
{
|
||||||
auto isToBase = TypeIsSubTypeOf(mCurTypeInstance->mBaseType, mCurMethodInstance->mReturnType->ToTypeInstance());
|
auto isToBase = TypeIsSubTypeOf(mCurTypeInstance->mBaseType, mCurMethodInstance->mReturnType->ToTypeInstance());
|
||||||
bool isFromBase = TypeIsSubTypeOf(mCurTypeInstance->mBaseType, mCurMethodInstance->GetParamType(0)->ToTypeInstance());
|
bool isFromBase = TypeIsSubTypeOf(mCurTypeInstance->mBaseType, checkParam0->ToTypeInstance());
|
||||||
|
|
||||||
if ((mCurTypeInstance->IsObject()) && (isToBase || isFromBase))
|
if ((mCurTypeInstance->IsObject()) && (isToBase || isFromBase))
|
||||||
Fail("User-defined conversions to or from a base class are not allowed", paramErrorRefNode);
|
Fail("User-defined conversions to or from a base class are not allowed", paramErrorRefNode);
|
||||||
|
@ -22218,16 +22250,22 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
methodDef->mIsVirtual = false;
|
methodDef->mIsVirtual = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((methodDeclaration != NULL) && (methodDeclaration->mMutSpecifier != NULL) && (!mCurTypeInstance->IsBoxed()) && (!methodInstance->mIsForeignMethodDef))
|
BfAstNode* mutSpecifier = NULL;
|
||||||
|
if (methodDeclaration != NULL)
|
||||||
|
mutSpecifier = methodDeclaration->mMutSpecifier;
|
||||||
|
else if (methodDef->GetPropertyMethodDeclaration() != NULL)
|
||||||
|
mutSpecifier = methodDef->GetPropertyMethodDeclaration()->mMutSpecifier;
|
||||||
|
|
||||||
|
if ((mutSpecifier != NULL) && (!mCurTypeInstance->IsBoxed()) && (!methodInstance->mIsForeignMethodDef))
|
||||||
{
|
{
|
||||||
if (methodDef->mIsStatic)
|
if (methodDef->mIsStatic)
|
||||||
Warn(0, "Unnecessary 'mut' specifier, static methods have no implicit 'this' target to mutate", methodDeclaration->mMutSpecifier);
|
Warn(0, "Unnecessary 'mut' specifier, static methods have no implicit 'this' target to mutate", mutSpecifier);
|
||||||
else if ((!mCurTypeInstance->IsValueType()) && (!mCurTypeInstance->IsInterface()))
|
else if ((!mCurTypeInstance->IsValueType()) && (!mCurTypeInstance->IsInterface()))
|
||||||
Warn(0, "Unnecessary 'mut' specifier, methods of reference types are implicitly mutating", methodDeclaration->mMutSpecifier);
|
Warn(0, "Unnecessary 'mut' specifier, methods of reference types are implicitly mutating", mutSpecifier);
|
||||||
else if (methodDef->mMethodType == BfMethodType_Ctor)
|
else if (methodDef->mMethodType == BfMethodType_Ctor)
|
||||||
Warn(0, "Unnecessary 'mut' specifier, constructors are implicitly mutating", methodDeclaration->mMutSpecifier);
|
Warn(0, "Unnecessary 'mut' specifier, constructors are implicitly mutating", mutSpecifier);
|
||||||
else if (methodDef->mMethodType == BfMethodType_Dtor)
|
else if (methodDef->mMethodType == BfMethodType_Dtor)
|
||||||
Warn(0, "Unnecessary 'mut' specifier, destructors are implicitly mutating", methodDeclaration->mMutSpecifier);
|
Warn(0, "Unnecessary 'mut' specifier, destructors are implicitly mutating", mutSpecifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTemporaryFunc)
|
if (isTemporaryFunc)
|
||||||
|
|
|
@ -1627,6 +1627,7 @@ public:
|
||||||
void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull);
|
void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull);
|
||||||
void CheckStaticAccess(BfTypeInstance* typeInstance);
|
void CheckStaticAccess(BfTypeInstance* typeInstance);
|
||||||
BfTypedValue RemoveRef(BfTypedValue typedValue);
|
BfTypedValue RemoveRef(BfTypedValue typedValue);
|
||||||
|
BfTypedValue ToRef(BfTypedValue typedValue, BfRefType* refType = NULL);
|
||||||
BfTypedValue LoadOrAggregateValue(BfTypedValue typedValue);
|
BfTypedValue LoadOrAggregateValue(BfTypedValue typedValue);
|
||||||
BfTypedValue LoadValue(BfTypedValue typedValue, BfAstNode* refNode = NULL, bool isVolatile = false);
|
BfTypedValue LoadValue(BfTypedValue typedValue, BfAstNode* refNode = NULL, bool isVolatile = false);
|
||||||
BfTypedValue PrepareConst(BfTypedValue& typedValue);
|
BfTypedValue PrepareConst(BfTypedValue& typedValue);
|
||||||
|
|
|
@ -11597,7 +11597,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
|
|
||||||
// Check user-defined operators
|
// Check user-defined operators
|
||||||
if ((castFlags & BfCastFlags_NoConversionOperator) == 0)
|
if ((castFlags & BfCastFlags_NoConversionOperator) == 0)
|
||||||
{
|
{
|
||||||
auto fromType = typedVal.mType;
|
auto fromType = typedVal.mType;
|
||||||
auto fromTypeInstance = typedVal.mType->ToTypeInstance();
|
auto fromTypeInstance = typedVal.mType->ToTypeInstance();
|
||||||
auto toTypeInstance = toType->ToTypeInstance();
|
auto toTypeInstance = toType->ToTypeInstance();
|
||||||
|
@ -11620,7 +11620,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
BfMethodInstance* opMethodInstance = NULL;
|
BfMethodInstance* opMethodInstance = NULL;
|
||||||
BfType* opMethodSrcType = NULL;
|
BfType* opMethodSrcType = NULL;
|
||||||
BfOperatorInfo* constraintOperatorInfo = NULL;
|
BfOperatorInfo* constraintOperatorInfo = NULL;
|
||||||
|
|
||||||
// Normal, lifted, execute
|
// Normal, lifted, execute
|
||||||
for (int pass = 0; pass < 3; pass++)
|
for (int pass = 0; pass < 3; pass++)
|
||||||
{
|
{
|
||||||
|
@ -11643,8 +11643,12 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfType* searchFromType = checkFromType;
|
||||||
|
if (searchFromType->IsSizedArray())
|
||||||
|
searchFromType = GetWrappedStructType(checkFromType);
|
||||||
|
|
||||||
bool isConstraintCheck = ((castFlags & BfCastFlags_IsConstraintCheck) != 0);
|
bool isConstraintCheck = ((castFlags & BfCastFlags_IsConstraintCheck) != 0);
|
||||||
BfBaseClassWalker baseClassWalker(fromType, toType, this);
|
BfBaseClassWalker baseClassWalker(searchFromType, toType, this);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -11687,6 +11691,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
methodToType = methodInst->mReturnType;
|
methodToType = methodInst->mReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (methodFromType->IsRef())
|
||||||
|
methodFromType = methodFromType->GetUnderlyingType();
|
||||||
|
|
||||||
if (methodFromType->IsSelf())
|
if (methodFromType->IsSelf())
|
||||||
methodFromType = entry.mSrcType;
|
methodFromType = entry.mSrcType;
|
||||||
if (methodToType->IsSelf())
|
if (methodToType->IsSelf())
|
||||||
|
@ -11708,6 +11715,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
int fromDist = GetTypeDistance(methodCheckFromType, checkFromType);
|
int fromDist = GetTypeDistance(methodCheckFromType, checkFromType);
|
||||||
|
if ((fromDist == INT_MAX) && (searchFromType != checkFromType))
|
||||||
|
{
|
||||||
|
fromDist = GetTypeDistance(methodCheckFromType, searchFromType);
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -11842,10 +11854,19 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually perform conversion
|
// Actually perform conversion
|
||||||
BfExprEvaluator exprEvaluator(this);
|
BfExprEvaluator exprEvaluator(this);
|
||||||
auto castedFromValue = Cast(srcNode, typedVal, bestFromType, castFlags);
|
BfTypedValue castedFromValue;
|
||||||
|
if ((typedVal.mType->IsSizedArray()) && (bestFromType->IsInstanceOf(mCompiler->mSizedArrayTypeDef)))
|
||||||
|
{
|
||||||
|
castedFromValue = MakeAddressable(typedVal);
|
||||||
|
if (!bestFromType->IsValuelessType())
|
||||||
|
castedFromValue.mValue = mBfIRBuilder->CreateBitCast(castedFromValue.mValue, mBfIRBuilder->MapTypeInstPtr(bestFromType->ToTypeInstance()));
|
||||||
|
castedFromValue.mType = bestFromType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
castedFromValue = Cast(srcNode, typedVal, bestFromType, castFlags);
|
||||||
if (!castedFromValue)
|
if (!castedFromValue)
|
||||||
return BfIRValue();
|
return BfIRValue();
|
||||||
|
|
||||||
|
@ -11864,6 +11885,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
BfModuleMethodInstance moduleMethodInstance = GetMethodInstance(opMethodInstance->GetOwner(), opMethodInstance->mMethodDef, BfTypeVector());
|
BfModuleMethodInstance moduleMethodInstance = GetMethodInstance(opMethodInstance->GetOwner(), opMethodInstance->mMethodDef, BfTypeVector());
|
||||||
exprEvaluator.PerformCallChecks(moduleMethodInstance.mMethodInstance, srcNode);
|
exprEvaluator.PerformCallChecks(moduleMethodInstance.mMethodInstance, srcNode);
|
||||||
|
|
||||||
|
if (moduleMethodInstance.mMethodInstance->GetParamType(0)->IsRef())
|
||||||
|
castedFromValue = ToRef(castedFromValue);
|
||||||
|
|
||||||
SizedArray<BfIRValue, 1> args;
|
SizedArray<BfIRValue, 1> args;
|
||||||
exprEvaluator.PushArg(castedFromValue, args);
|
exprEvaluator.PushArg(castedFromValue, args);
|
||||||
operatorOut = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
|
operatorOut = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
|
||||||
|
|
|
@ -568,6 +568,8 @@ public:
|
||||||
virtual bool IsAllocType() { return false; }
|
virtual bool IsAllocType() { return false; }
|
||||||
virtual bool IsIntPtrable() { return false; }
|
virtual bool IsIntPtrable() { return false; }
|
||||||
virtual bool IsRef() { return false; }
|
virtual bool IsRef() { return false; }
|
||||||
|
virtual bool IsMut() { return false; }
|
||||||
|
virtual bool IsOut() { return false; }
|
||||||
virtual bool IsGenericParam() { return false; }
|
virtual bool IsGenericParam() { return false; }
|
||||||
virtual bool IsClosure() { return false; }
|
virtual bool IsClosure() { return false; }
|
||||||
virtual bool IsMethodRef() { return false; }
|
virtual bool IsMethodRef() { return false; }
|
||||||
|
@ -2280,6 +2282,8 @@ public:
|
||||||
virtual bool IsReified() override { return mElementType->IsReified(); }
|
virtual bool IsReified() override { return mElementType->IsReified(); }
|
||||||
|
|
||||||
virtual bool IsRef() override { return true; }
|
virtual bool IsRef() override { return true; }
|
||||||
|
virtual bool IsMut() override { return mRefKind == RefKind_Mut; }
|
||||||
|
virtual bool IsOut() override { return mRefKind == RefKind_Out; }
|
||||||
virtual bool IsDependentOnUnderlyingType() override { return true; }
|
virtual bool IsDependentOnUnderlyingType() override { return true; }
|
||||||
virtual BfType* GetUnderlyingType() override { return mElementType; }
|
virtual BfType* GetUnderlyingType() override { return mElementType; }
|
||||||
virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType(); }
|
virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType(); }
|
||||||
|
|
|
@ -176,6 +176,28 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StructG : this(int a)
|
||||||
|
{
|
||||||
|
public static StructG operator+(ref StructG lhs, ref StructG rhs)
|
||||||
|
{
|
||||||
|
lhs.a += 1000;
|
||||||
|
rhs.a += 1000;
|
||||||
|
|
||||||
|
return .(lhs.a + rhs.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StructG operator-(ref StructG val)
|
||||||
|
{
|
||||||
|
val.a += 1000;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator int(ref StructG val)
|
||||||
|
{
|
||||||
|
return val.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct StructOp<T, T2> where T : operator T + T2
|
struct StructOp<T, T2> where T : operator T + T2
|
||||||
{
|
{
|
||||||
public T DoIt(T val, T2 val2)
|
public T DoIt(T val, T2 val2)
|
||||||
|
@ -407,6 +429,15 @@ namespace Tests
|
||||||
Test.Assert(sf + 1.0f == 3);
|
Test.Assert(sf + 1.0f == 3);
|
||||||
Test.Assert(2.0f + sf == 3);
|
Test.Assert(2.0f + sf == 3);
|
||||||
|
|
||||||
|
StructG sg = .(100);
|
||||||
|
StructG sg2 = .(200);
|
||||||
|
var sg3 = sg + sg2;
|
||||||
|
var sg4 = -sg3;
|
||||||
|
Test.Assert(sg.a == 1100);
|
||||||
|
Test.Assert(sg2.a == 1200);
|
||||||
|
Test.Assert(sg3.a == 3300);
|
||||||
|
Test.Assert(sg4.a == 3300);
|
||||||
|
|
||||||
/*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100);
|
/*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100);
|
||||||
Test.Assert(oai == 101.0f);
|
Test.Assert(oai == 101.0f);
|
||||||
|
|
||||||
|
@ -443,6 +474,8 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestCompareWithCastOperator()
|
public static void TestCompareWithCastOperator()
|
||||||
{
|
{
|
||||||
|
@ -504,3 +537,4 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,10 @@ namespace Tests
|
||||||
ClassA[2] caArr0 = .(ca0, ca0);
|
ClassA[2] caArr0 = .(ca0, ca0);
|
||||||
ClassA[2] caArr1 = .(ca1, ca1);
|
ClassA[2] caArr1 = .(ca1, ca1);
|
||||||
Test.Assert(caArr0 == caArr1);
|
Test.Assert(caArr0 == caArr1);
|
||||||
|
|
||||||
|
Span<int> span = val1;
|
||||||
|
Test.Assert(span[0] == 7);
|
||||||
|
Test.Assert(span[1] == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue