mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Expanded const generic params to support structs
This commit is contained in:
parent
d9de51a019
commit
b80db38cdc
13 changed files with 443 additions and 36 deletions
|
@ -105,6 +105,7 @@ public:
|
||||||
BeIRTypeEntry& GetTypeEntry(int typeId);
|
BeIRTypeEntry& GetTypeEntry(int typeId);
|
||||||
|
|
||||||
void FixValues(BeStructType* structType, CmdParamVec<BeValue*>& values);
|
void FixValues(BeStructType* structType, CmdParamVec<BeValue*>& values);
|
||||||
|
void FixValues(BeStructType* structType, SizedArrayImpl<BeConstant*>& values);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BeIRCodeGen();
|
BeIRCodeGen();
|
||||||
|
|
|
@ -1085,6 +1085,9 @@ bool BfAstNode::Equals(const StringView& str)
|
||||||
|
|
||||||
bool BfAstNode::Equals(const char* str)
|
bool BfAstNode::Equals(const char* str)
|
||||||
{
|
{
|
||||||
|
if (mSrcEnd == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
auto source = GetSourceData();
|
auto source = GetSourceData();
|
||||||
const char* ptrLhs = source->mSrc + mSrcStart;
|
const char* ptrLhs = source->mSrc + mSrcStart;
|
||||||
const char* ptrLhsEnd = source->mSrc + mSrcEnd;
|
const char* ptrLhsEnd = source->mSrc + mSrcEnd;
|
||||||
|
|
|
@ -78,6 +78,12 @@ static bool CheckProtection(BfProtection protection, bool allowProtected, bool a
|
||||||
|
|
||||||
struct BfVariant
|
struct BfVariant
|
||||||
{
|
{
|
||||||
|
struct StructData
|
||||||
|
{
|
||||||
|
int mSize;
|
||||||
|
uint8 mData[1];
|
||||||
|
};
|
||||||
|
|
||||||
BfTypeCode mTypeCode;
|
BfTypeCode mTypeCode;
|
||||||
int mWarnType;
|
int mWarnType;
|
||||||
union
|
union
|
||||||
|
@ -111,6 +117,63 @@ struct BfVariant
|
||||||
mWarnType = 0;
|
mWarnType = 0;
|
||||||
mUInt64 = 0;
|
mUInt64 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfVariant(const BfVariant& variant)
|
||||||
|
{
|
||||||
|
mTypeCode = BfTypeCode_None;
|
||||||
|
mWarnType = 0;
|
||||||
|
mUInt64 = 0;
|
||||||
|
*this = variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfVariant(BfVariant&& variant)
|
||||||
|
{
|
||||||
|
mTypeCode = variant.mTypeCode;
|
||||||
|
mWarnType = variant.mWarnType;
|
||||||
|
mUInt64 = variant.mUInt64;
|
||||||
|
variant.mTypeCode = BfTypeCode_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BfVariant()
|
||||||
|
{
|
||||||
|
if (mTypeCode == BfTypeCode_Struct)
|
||||||
|
delete mPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfVariant& operator=(const BfVariant& variant)
|
||||||
|
{
|
||||||
|
if (mTypeCode == BfTypeCode_Struct)
|
||||||
|
delete mPtr;
|
||||||
|
mTypeCode = variant.mTypeCode;
|
||||||
|
mWarnType = variant.mWarnType;
|
||||||
|
mUInt64 = variant.mUInt64;
|
||||||
|
|
||||||
|
if (variant.mTypeCode == BfTypeCode_Struct)
|
||||||
|
{
|
||||||
|
StructData* srcStructData = (StructData*)mPtr;
|
||||||
|
StructData* destStructData = (StructData*)(new uint8[srcStructData->mSize + 4]);
|
||||||
|
destStructData->mSize = srcStructData->mSize;
|
||||||
|
memcpy(destStructData->mData, srcStructData->mData, destStructData->mSize);
|
||||||
|
mPtr = destStructData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const BfVariant& variant) const
|
||||||
|
{
|
||||||
|
if (mTypeCode != variant.mTypeCode)
|
||||||
|
return false;
|
||||||
|
if (mTypeCode == BfTypeCode_Struct)
|
||||||
|
{
|
||||||
|
StructData* structDataA = (StructData*)mPtr;
|
||||||
|
StructData* structDataB = (StructData*)variant.mPtr;
|
||||||
|
if (structDataA->mSize != structDataB->mSize)
|
||||||
|
return false;
|
||||||
|
return memcmp(structDataA->mData, structDataB->mData, structDataA->mSize) == 0;
|
||||||
|
}
|
||||||
|
return mUInt64 == variant.mUInt64;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfToken : uint8
|
enum BfToken : uint8
|
||||||
|
@ -3494,6 +3557,20 @@ BfUnaryOp BfTokenToUnaryOp(BfToken token);
|
||||||
BfAssignmentOp BfTokenToAssignmentOp(BfToken token);
|
BfAssignmentOp BfTokenToAssignmentOp(BfToken token);
|
||||||
bool BfIsCommentBlock(BfCommentKind commentKind);
|
bool BfIsCommentBlock(BfCommentKind commentKind);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct BeefHash<Beefy::BfVariant>
|
||||||
|
{
|
||||||
|
size_t operator()(const Beefy::BfVariant& val) const
|
||||||
|
{
|
||||||
|
if (val.mTypeCode == BfTypeCode_Struct)
|
||||||
|
{
|
||||||
|
BfVariant::StructData* structData = (Beefy::BfVariant::StructData*)val.mPtr;
|
||||||
|
return HashBytes(structData->mData, structData->mSize);
|
||||||
|
}
|
||||||
|
return (size_t)val.mUInt64;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
NS_BF_END
|
NS_BF_END
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
|
|
@ -987,7 +987,8 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
||||||
if (type->IsConstExprValue())
|
if (type->IsConstExprValue())
|
||||||
{
|
{
|
||||||
auto constExprType = (BfConstExprValueType*)type;
|
auto constExprType = (BfConstExprValueType*)type;
|
||||||
if ((constExprType->mValue.mTypeCode != BfTypeCode_StringId) && (constExprType->mType->mSize != mScratchModule->GetPrimitiveType(constExprType->mValue.mTypeCode)->mSize))
|
if ((constExprType->mValue.mTypeCode != BfTypeCode_StringId) && (constExprType->mValue.mTypeCode != BfTypeCode_Struct) &&
|
||||||
|
(constExprType->mType->mSize != mScratchModule->GetPrimitiveType(constExprType->mValue.mTypeCode)->mSize))
|
||||||
wantDeleteType = true;
|
wantDeleteType = true;
|
||||||
}
|
}
|
||||||
if (wantDeleteType)
|
if (wantDeleteType)
|
||||||
|
|
|
@ -3933,7 +3933,7 @@ bool BfExprEvaluator::IsVar(BfType* type, bool forceIgnoreWrites)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant)
|
void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant, BfType* type)
|
||||||
{
|
{
|
||||||
switch (variant.mTypeCode)
|
switch (variant.mTypeCode)
|
||||||
{
|
{
|
||||||
|
@ -4036,6 +4036,13 @@ void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant)
|
||||||
}
|
}
|
||||||
mModule->Fail("Invalid undef literal", refNode);
|
mModule->Fail("Invalid undef literal", refNode);
|
||||||
break;
|
break;
|
||||||
|
case BfTypeCode_Struct:
|
||||||
|
if (type != NULL)
|
||||||
|
{
|
||||||
|
BfVariant::StructData* structData = (BfVariant::StructData*)variant.mPtr;
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->ReadConstant(structData->mData, type), type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
mModule->Fail("Invalid literal", refNode);
|
mModule->Fail("Invalid literal", refNode);
|
||||||
break;
|
break;
|
||||||
|
@ -12382,6 +12389,23 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
|
||||||
if (autoComplete != NULL)
|
if (autoComplete != NULL)
|
||||||
autoComplete->CheckTypeRef(checkTypeExpr->mTypeRef, false, true);
|
autoComplete->CheckTypeRef(checkTypeExpr->mTypeRef, false, true);
|
||||||
|
|
||||||
|
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
||||||
|
|
||||||
|
if (checkTypeExpr->mTypeRef->IsA<BfVarTypeReference>())
|
||||||
|
{
|
||||||
|
bool isVar = false;
|
||||||
|
if ((targetValue.mType != NULL) && (targetValue.mType->IsVar()))
|
||||||
|
{
|
||||||
|
auto irb = mModule->mBfIRBuilder;
|
||||||
|
BfIRValue boolResult = mModule->CreateAlloca(boolType);
|
||||||
|
irb->CreateAlignedStore(irb->CreateConst(BfTypeCode_Boolean, 1), boolResult, 1);
|
||||||
|
mResult = BfTypedValue(irb->CreateAlignedLoad(boolResult, 1), boolType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mResult = BfTypedValue(mModule->GetConstValue(0, boolType), boolType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto targetType = mModule->ResolveTypeRef(checkTypeExpr->mTypeRef, BfPopulateType_Declaration);
|
auto targetType = mModule->ResolveTypeRef(checkTypeExpr->mTypeRef, BfPopulateType_Declaration);
|
||||||
if (!targetType)
|
if (!targetType)
|
||||||
{
|
{
|
||||||
|
@ -12391,7 +12415,6 @@ 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);
|
|
||||||
if (targetValue.mType->IsVar())
|
if (targetValue.mType->IsVar())
|
||||||
{
|
{
|
||||||
mResult = mModule->GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef);
|
mResult = mModule->GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef);
|
||||||
|
@ -12638,11 +12661,13 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
auto elementType = targetType->GetUnderlyingType();
|
auto elementType = targetType->GetUnderlyingType();
|
||||||
if (elementType == targetValue.mType)
|
if (elementType == targetValue.mType)
|
||||||
{
|
{
|
||||||
|
mModule->mBfIRBuilder->PopulateType(targetType);
|
||||||
|
|
||||||
// We match nullable element
|
// We match nullable element
|
||||||
auto allocaInst = mModule->CreateAlloca(targetType);
|
auto allocaInst = mModule->CreateAlloca(targetType);
|
||||||
auto hasValueAddr = mModule->mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 1); // has_value
|
auto hasValueAddr = mModule->mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 2); // has_value
|
||||||
mModule->mBfIRBuilder->CreateStore(mModule->GetConstValue(1, boolType), hasValueAddr);
|
mModule->mBfIRBuilder->CreateStore(mModule->GetConstValue(1, boolType), hasValueAddr);
|
||||||
hasValueAddr = mModule->mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 0); // value
|
hasValueAddr = mModule->mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 1); // value
|
||||||
mModule->mBfIRBuilder->CreateStore(targetValue.mValue, hasValueAddr);
|
mModule->mBfIRBuilder->CreateStore(targetValue.mValue, hasValueAddr);
|
||||||
mResult = BfTypedValue(allocaInst, targetType, true);
|
mResult = BfTypedValue(allocaInst, targetType, true);
|
||||||
_CheckResult();
|
_CheckResult();
|
||||||
|
|
|
@ -438,7 +438,7 @@ public:
|
||||||
|
|
||||||
bool CheckForMethodName(BfAstNode* refNode, BfTypeInstance* typeInst, const StringImpl& findName);
|
bool CheckForMethodName(BfAstNode* refNode, BfTypeInstance* typeInst, const StringImpl& findName);
|
||||||
bool IsVar(BfType* type, bool forceIgnoreWrites = false);
|
bool IsVar(BfType* type, bool forceIgnoreWrites = false);
|
||||||
void GetLiteral(BfAstNode* refNode, const BfVariant& variant);
|
void GetLiteral(BfAstNode* refNode, const BfVariant& variant, BfType* type = NULL);
|
||||||
void FinishExpressionResult();
|
void FinishExpressionResult();
|
||||||
virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode);
|
virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode);
|
||||||
BfAutoComplete* GetAutoComplete();
|
BfAutoComplete* GetAutoComplete();
|
||||||
|
|
|
@ -8149,7 +8149,11 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_DisallowComptime);
|
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_DisallowComptime);
|
||||||
// We we have a deferredResolveTypes then we defer the generic validation, because we may have a case like
|
// We we have a deferredResolveTypes then we defer the generic validation, because we may have a case like
|
||||||
// `where T : Dictionay<TElem, int> and TElem : IHashable` and we don't want to throw the error on `T` before we build `TElem`
|
// `where T : Dictionay<TElem, int> and TElem : IHashable` and we don't want to throw the error on `T` before we build `TElem`
|
||||||
auto constraintType = ResolveTypeRef(constraintTypeRef, (deferredResolveTypes != NULL) ? BfPopulateType_Identity : BfPopulateType_Declaration, resolveFlags);
|
BfType* constraintType;
|
||||||
|
if (constraintTypeRef->IsA<BfVarTypeReference>())
|
||||||
|
constraintType = GetPrimitiveType(BfTypeCode_Var);
|
||||||
|
else
|
||||||
|
constraintType = ResolveTypeRef(constraintTypeRef, (deferredResolveTypes != NULL) ? BfPopulateType_Identity : BfPopulateType_Declaration, resolveFlags);
|
||||||
if (constraintType != NULL)
|
if (constraintType != NULL)
|
||||||
{
|
{
|
||||||
if (deferredResolveTypes != NULL)
|
if (deferredResolveTypes != NULL)
|
||||||
|
@ -8176,6 +8180,12 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
if (constraintType->IsInstanceOf(mCompiler->mStringTypeDef))
|
if (constraintType->IsInstanceOf(mCompiler->mStringTypeDef))
|
||||||
isValidTypeCode = true;
|
isValidTypeCode = true;
|
||||||
|
|
||||||
|
if (constraintType->IsValueType())
|
||||||
|
isValidTypeCode = true;
|
||||||
|
|
||||||
|
if (constraintType->IsVar())
|
||||||
|
isValidTypeCode = true;
|
||||||
|
|
||||||
switch (typeCode)
|
switch (typeCode)
|
||||||
{
|
{
|
||||||
case BfTypeCode_StringId:
|
case BfTypeCode_StringId:
|
||||||
|
@ -8208,7 +8218,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Fail("Const constraint must be a primitive type", constraintTypeRef);
|
Fail("Const constraint must be a valuetype or string", constraintTypeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8572,7 +8582,8 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
// actual expression comparisons, but we are overly permissive now and then we may fail on specialization
|
// actual expression comparisons, but we are overly permissive now and then we may fail on specialization
|
||||||
if ((constExprValueType->mValue.mTypeCode != primType->mTypeDef->mTypeCode) &&
|
if ((constExprValueType->mValue.mTypeCode != primType->mTypeDef->mTypeCode) &&
|
||||||
(constExprValueType->mValue.mTypeCode != BfTypeCode_Let) &&
|
(constExprValueType->mValue.mTypeCode != BfTypeCode_Let) &&
|
||||||
(primType->mTypeDef->mTypeCode != BfTypeCode_Let))
|
(primType->mTypeDef->mTypeCode != BfTypeCode_Let) &&
|
||||||
|
(primType->mTypeDef->mTypeCode != BfTypeCode_Var))
|
||||||
{
|
{
|
||||||
bool doError = true;
|
bool doError = true;
|
||||||
|
|
||||||
|
@ -12844,6 +12855,14 @@ BfVariant BfModule::TypedValueToVariant(BfAstNode* refNode, const BfTypedValue&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BfVariant::StructData* structData = (BfVariant::StructData*)(new uint8[value.mType->mSize + 4]);
|
||||||
|
structData->mSize = value.mType->mSize;
|
||||||
|
mBfIRBuilder->WriteConstant(value.mValue, structData->mData, value.mType);
|
||||||
|
variant.mTypeCode = BfTypeCode_Struct;
|
||||||
|
variant.mPtr = structData;
|
||||||
|
}
|
||||||
|
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1653,7 +1653,8 @@ public:
|
||||||
BfIRValue GetStringObjectValue(int idx, bool define, bool force);
|
BfIRValue GetStringObjectValue(int idx, bool define, bool force);
|
||||||
BfIRValue GetStringObjectValue(const StringImpl& str, bool define = false, bool force = false);
|
BfIRValue GetStringObjectValue(const StringImpl& str, bool define = false, bool force = false);
|
||||||
BfIRValue CreateGlobalConstValue(const StringImpl& name, BfIRValue constant, BfIRType type, bool external);
|
BfIRValue CreateGlobalConstValue(const StringImpl& name, BfIRValue constant, BfIRType type, bool external);
|
||||||
void VariantToString(StringImpl& str, const BfVariant& variant);
|
void DataToString(StringImpl& str, void* ptr, BfType* type);
|
||||||
|
void VariantToString(StringImpl& str, const BfVariant& variant, BfType* type = NULL);
|
||||||
StringT<128> TypeToString(BfType* resolvedType, Array<String>* genericMethodParamNameOverrides = NULL);
|
StringT<128> TypeToString(BfType* resolvedType, Array<String>* genericMethodParamNameOverrides = NULL);
|
||||||
StringT<128> TypeToString(BfType* resolvedType, BfTypeNameFlags typeNameFlags, Array<String>* genericMethodParamNameOverrides = NULL);
|
StringT<128> TypeToString(BfType* resolvedType, BfTypeNameFlags typeNameFlags, Array<String>* genericMethodParamNameOverrides = NULL);
|
||||||
void DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None, Array<String>* genericMethodParamNameOverrides = NULL);
|
void DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None, Array<String>* genericMethodParamNameOverrides = NULL);
|
||||||
|
|
|
@ -1495,9 +1495,13 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
||||||
|
|
||||||
if (resolvedTypeRef->IsConstExprValue())
|
if (resolvedTypeRef->IsConstExprValue())
|
||||||
{
|
{
|
||||||
|
BfConstExprValueType* constExprType = (BfConstExprValueType*)resolvedTypeRef;
|
||||||
|
resolvedTypeRef->mRevision = mRevision;
|
||||||
resolvedTypeRef->mSize = 0;
|
resolvedTypeRef->mSize = 0;
|
||||||
resolvedTypeRef->mAlign = 0;
|
resolvedTypeRef->mAlign = 0;
|
||||||
resolvedTypeRef->mDefineState = BfTypeDefineState_Defined;
|
resolvedTypeRef->mDefineState = BfTypeDefineState_Defined;
|
||||||
|
if (constExprType->mType->IsTypeInstance())
|
||||||
|
AddDependency(constExprType->mType, resolvedTypeRef, BfDependencyMap::DependencyFlag_TypeGenericArg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7576,7 +7580,7 @@ BfConstExprValueType* BfModule::CreateConstExprValueType(const BfTypedValue& typ
|
||||||
mContext->mConstExprValueTypePool.GiveBack(constExprValueType);
|
mContext->mConstExprValueTypePool.GiveBack(constExprValueType);
|
||||||
|
|
||||||
if (resolvedConstExprValueType != NULL)
|
if (resolvedConstExprValueType != NULL)
|
||||||
BF_ASSERT(resolvedConstExprValueType->mValue.mInt64 == constExprValueType->mValue.mInt64);
|
BF_ASSERT(resolvedConstExprValueType->mValue == constExprValueType->mValue);
|
||||||
|
|
||||||
return resolvedConstExprValueType;
|
return resolvedConstExprValueType;
|
||||||
}
|
}
|
||||||
|
@ -7599,7 +7603,7 @@ BfConstExprValueType* BfModule::CreateConstExprValueType(const BfVariant& varian
|
||||||
mContext->mConstExprValueTypePool.GiveBack(constExprValueType);
|
mContext->mConstExprValueTypePool.GiveBack(constExprValueType);
|
||||||
|
|
||||||
if (resolvedConstExprValueType != NULL)
|
if (resolvedConstExprValueType != NULL)
|
||||||
BF_ASSERT(resolvedConstExprValueType->mValue.mInt64 == constExprValueType->mValue.mInt64);
|
BF_ASSERT(resolvedConstExprValueType->mValue == constExprValueType->mValue);
|
||||||
|
|
||||||
return resolvedConstExprValueType;
|
return resolvedConstExprValueType;
|
||||||
}
|
}
|
||||||
|
@ -10729,18 +10733,27 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
|
||||||
if (constType == NULL)
|
if (constType == NULL)
|
||||||
constType = GetPrimitiveType(BfTypeCode_IntPtr);
|
constType = GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
|
|
||||||
BfExprEvaluator exprEvaluator(this);
|
if (constType->IsVar())
|
||||||
exprEvaluator.mExpectingType = constType;
|
|
||||||
exprEvaluator.GetLiteral(identifierNode, constExprValueType->mValue);
|
|
||||||
|
|
||||||
if (exprEvaluator.mResult)
|
|
||||||
{
|
{
|
||||||
auto castedVal = CastToValue(identifierNode, exprEvaluator.mResult, constType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail));
|
BfExprEvaluator exprEvaluator(this);
|
||||||
if (castedVal)
|
exprEvaluator.GetLiteral(identifierNode, constExprValueType->mValue, constExprValueType->mType);
|
||||||
return BfTypedValue(castedVal, constType);
|
return exprEvaluator.mResult;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BfExprEvaluator exprEvaluator(this);
|
||||||
|
exprEvaluator.mExpectingType = constType;
|
||||||
|
exprEvaluator.GetLiteral(identifierNode, constExprValueType->mValue, constExprValueType->mType);
|
||||||
|
|
||||||
return exprEvaluator.mResult;
|
if (exprEvaluator.mResult)
|
||||||
|
{
|
||||||
|
auto castedVal = CastToValue(identifierNode, exprEvaluator.mResult, constType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail));
|
||||||
|
if (castedVal)
|
||||||
|
return BfTypedValue(castedVal, constType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exprEvaluator.mResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (genericParamResult->IsGenericParam())
|
else if (genericParamResult->IsGenericParam())
|
||||||
{
|
{
|
||||||
|
@ -12031,7 +12044,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
}
|
}
|
||||||
if (!BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx))
|
if (!BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx))
|
||||||
{
|
{
|
||||||
BF_ASSERT(BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx));
|
BF_ASSERT(BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx) || (mCompiler->mCanceling));
|
||||||
}
|
}
|
||||||
|
|
||||||
BfLogSysM("Generic type %p typeHash: %8X\n", genericTypeInst, resolvedEntry->mHashCode);
|
BfLogSysM("Generic type %p typeHash: %8X\n", genericTypeInst, resolvedEntry->mHashCode);
|
||||||
|
@ -13259,9 +13272,15 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
|
|
||||||
BfTypedValue fromTypedValue;
|
BfTypedValue fromTypedValue;
|
||||||
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
||||||
fromTypedValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint, false, BfDefaultValueKind_Undef);
|
{
|
||||||
|
if (genericParamInst->mTypeConstraint->IsVar())
|
||||||
|
fromTypedValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint);
|
||||||
|
else
|
||||||
|
fromTypedValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint, false, BfDefaultValueKind_Undef);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fromTypedValue = BfTypedValue(mBfIRBuilder->GetFakeVal(), genericParamInst->mTypeConstraint, genericParamInst->mTypeConstraint->IsValueType());
|
fromTypedValue = BfTypedValue(mBfIRBuilder->GetFakeVal(), genericParamInst->mTypeConstraint, genericParamInst->mTypeConstraint->IsValueType());
|
||||||
|
prevIgnoreWrites.Restore();
|
||||||
|
|
||||||
auto result = CastToValue(srcNode, fromTypedValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
|
auto result = CastToValue(srcNode, fromTypedValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
|
||||||
if (result)
|
if (result)
|
||||||
|
@ -13768,7 +13787,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
auto variantVal = TypedValueToVariant(srcNode, typedVal, true);
|
auto variantVal = TypedValueToVariant(srcNode, typedVal, true);
|
||||||
if ((mBfIRBuilder->IsIntable(variantVal.mTypeCode)) && (mBfIRBuilder->IsIntable(toConstExprValueType->mValue.mTypeCode)))
|
if ((mBfIRBuilder->IsIntable(variantVal.mTypeCode)) && (mBfIRBuilder->IsIntable(toConstExprValueType->mValue.mTypeCode)))
|
||||||
{
|
{
|
||||||
if (variantVal.mInt64 == toConstExprValueType->mValue.mInt64)
|
if (variantVal == toConstExprValueType->mValue)
|
||||||
return typedVal.mValue;
|
return typedVal.mValue;
|
||||||
}
|
}
|
||||||
else if ((mBfIRBuilder->IsFloat(variantVal.mTypeCode)) && (mBfIRBuilder->IsFloat(toConstExprValueType->mValue.mTypeCode)))
|
else if ((mBfIRBuilder->IsFloat(variantVal.mTypeCode)) && (mBfIRBuilder->IsFloat(toConstExprValueType->mValue.mTypeCode)))
|
||||||
|
@ -15337,7 +15356,181 @@ StringT<128> BfModule::TypeToString(BfType* resolvedType, BfTypeNameFlags typeNa
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::VariantToString(StringImpl& str, const BfVariant& variant)
|
void BfModule::DataToString(StringImpl& str, void* ptr, BfType* type)
|
||||||
|
{
|
||||||
|
if (type->IsPrimitiveType())
|
||||||
|
{
|
||||||
|
BfPrimitiveType* primType = (BfPrimitiveType*)type;
|
||||||
|
BfTypeCode typeCode = primType->GetTypeCode();
|
||||||
|
|
||||||
|
if (typeCode == BfTypeCode_IntPtr)
|
||||||
|
{
|
||||||
|
if (mSystem->mPtrSize == 8)
|
||||||
|
typeCode = BfTypeCode_Int64;
|
||||||
|
else
|
||||||
|
typeCode = BfTypeCode_Int32;
|
||||||
|
}
|
||||||
|
else if (typeCode == BfTypeCode_UIntPtr)
|
||||||
|
{
|
||||||
|
if (mSystem->mPtrSize == 8)
|
||||||
|
typeCode = BfTypeCode_UInt64;
|
||||||
|
else
|
||||||
|
typeCode = BfTypeCode_UInt32;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (typeCode)
|
||||||
|
{
|
||||||
|
case BfTypeCode_Boolean:
|
||||||
|
if (*(uint8*)ptr == 0)
|
||||||
|
str += "false";
|
||||||
|
else if (*(uint8*)ptr == 1)
|
||||||
|
str += "true";
|
||||||
|
else
|
||||||
|
str += StrFormat("%d", *(uint8*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Int8:
|
||||||
|
str += StrFormat("%d", *(int8*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_UInt8:
|
||||||
|
str += StrFormat("%d", *(uint8*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Int16:
|
||||||
|
str += StrFormat("%d", *(int16*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_UInt16:
|
||||||
|
str += StrFormat("%d", *(uint16*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Int32:
|
||||||
|
str += StrFormat("%d", *(int32*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Char8:
|
||||||
|
case BfTypeCode_Char16:
|
||||||
|
case BfTypeCode_Char32:
|
||||||
|
{
|
||||||
|
uint32 c = 0;
|
||||||
|
if (typeCode == BfTypeCode_Char8)
|
||||||
|
c = *(uint8*)ptr;
|
||||||
|
else if (typeCode == BfTypeCode_Char16)
|
||||||
|
c = *(uint16*)ptr;
|
||||||
|
else if (typeCode == BfTypeCode_Char32)
|
||||||
|
c = *(uint32*)ptr;
|
||||||
|
|
||||||
|
if ((c >= 32) && (c <= 0x7E))
|
||||||
|
str += StrFormat("'%c'", (char)c);
|
||||||
|
else if (c <= 0xFF)
|
||||||
|
str += StrFormat("'\\x%2X'", c);
|
||||||
|
else
|
||||||
|
str += StrFormat("'\\u{%X}'", c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BfTypeCode_UInt32:
|
||||||
|
str += StrFormat("%lu", *(uint32*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Int64:
|
||||||
|
str += StrFormat("%lld", *(int64*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_UInt64:
|
||||||
|
str += StrFormat("%llu", *(uint64*)ptr);
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Float:
|
||||||
|
{
|
||||||
|
char cstr[64];
|
||||||
|
ExactMinimalFloatToStr(*(float*)ptr, cstr);
|
||||||
|
str += cstr;
|
||||||
|
if (strchr(cstr, '.') == NULL)
|
||||||
|
str += ".0f";
|
||||||
|
else
|
||||||
|
str += "f";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Double:
|
||||||
|
{
|
||||||
|
char cstr[64];
|
||||||
|
ExactMinimalDoubleToStr(*(double*)ptr, cstr);
|
||||||
|
str += cstr;
|
||||||
|
if (strchr(cstr, '.') == NULL)
|
||||||
|
str += ".0";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BfTypeCode_StringId:
|
||||||
|
{
|
||||||
|
int stringId = *(int32*)ptr;
|
||||||
|
auto stringPoolEntry = mContext->mStringObjectIdMap[stringId];
|
||||||
|
str += '"';
|
||||||
|
str += SlashString(stringPoolEntry.mString, false, false, true);
|
||||||
|
str += '"';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BfTypeCode_Let:
|
||||||
|
str += "?";
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (type->IsInstanceOf(mCompiler->mClosedRangeTypeDef))
|
||||||
|
{
|
||||||
|
if (type->mSize == 16)
|
||||||
|
str += StrFormat("%d...%d", ((int64*)ptr)[0], ((int64*)ptr)[1]);
|
||||||
|
else
|
||||||
|
str += StrFormat("%d...%d", ((int32*)ptr)[0], ((int32*)ptr)[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type->IsInstanceOf(mCompiler->mRangeTypeDef))
|
||||||
|
{
|
||||||
|
if (type->mSize == 16)
|
||||||
|
str += StrFormat("%d..<%d", ((int64*)ptr)[0], ((int64*)ptr)[1]);
|
||||||
|
else
|
||||||
|
str += StrFormat("%d..<%d", ((int32*)ptr)[0], ((int32*)ptr)[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfTypeInstance* typeInstance = type->ToTypeInstance();
|
||||||
|
if (typeInstance != NULL)
|
||||||
|
{
|
||||||
|
str += "(";
|
||||||
|
DoPopulateType(typeInstance);
|
||||||
|
|
||||||
|
int showIdx = 0;
|
||||||
|
|
||||||
|
if ((typeInstance->mBaseType != NULL) && (!typeInstance->mBaseType->IsInstanceOf(mCompiler->mValueTypeTypeDef)))
|
||||||
|
{
|
||||||
|
DataToString(str, ptr, typeInstance->mBaseType);
|
||||||
|
showIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& fieldInstance : typeInstance->mFieldInstances)
|
||||||
|
{
|
||||||
|
if (fieldInstance.mDataOffset >= 0)
|
||||||
|
{
|
||||||
|
if (showIdx > 0)
|
||||||
|
str += ", ";
|
||||||
|
DataToString(str, (uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType);
|
||||||
|
showIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str += ")";
|
||||||
|
}
|
||||||
|
else if (type->IsPointer())
|
||||||
|
str += "null";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str += "uint8[](";
|
||||||
|
for (int i = 0; i < type->mSize; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
str += ", ";
|
||||||
|
str += StrFormat("%d", ((uint8_t*)ptr)[i]);
|
||||||
|
}
|
||||||
|
str += ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfModule::VariantToString(StringImpl& str, const BfVariant& variant, BfType* type)
|
||||||
{
|
{
|
||||||
switch (variant.mTypeCode)
|
switch (variant.mTypeCode)
|
||||||
{
|
{
|
||||||
|
@ -15407,6 +15600,24 @@ void BfModule::VariantToString(StringImpl& str, const BfVariant& variant)
|
||||||
case BfTypeCode_Let:
|
case BfTypeCode_Let:
|
||||||
str += "?";
|
str += "?";
|
||||||
break;
|
break;
|
||||||
|
case BfTypeCode_Struct:
|
||||||
|
{
|
||||||
|
BfVariant::StructData* structData = (BfVariant::StructData*)variant.mPtr;
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
str += "uint8[](";
|
||||||
|
for (int i = 0; i < structData->mSize; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
str += ", ";
|
||||||
|
str += StrFormat("%d", structData->mData[i]);
|
||||||
|
}
|
||||||
|
str += ")";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DataToString(str, structData->mData, type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15991,11 +16202,16 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
||||||
{
|
{
|
||||||
str += "const ";
|
str += "const ";
|
||||||
|
|
||||||
DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides);
|
if ((!constExprValueType->mType->IsInstanceOf(mCompiler->mRangeTypeDef)) &&
|
||||||
str += " ";
|
(!constExprValueType->mType->IsInstanceOf(mCompiler->mClosedRangeTypeDef)))
|
||||||
|
{
|
||||||
|
DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides);
|
||||||
|
if (constExprValueType->mValue.mTypeCode != BfTypeCode_Boolean)
|
||||||
|
str += " ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantToString(str, constExprValueType->mValue);
|
VariantToString(str, constExprValueType->mValue, constExprValueType->mType);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -899,6 +899,13 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int
|
||||||
{
|
{
|
||||||
isDone = true;
|
isDone = true;
|
||||||
|
|
||||||
|
auto prevNode = mVisitorPos.Get(checkIdx + 1);
|
||||||
|
if (prevNode = BfNodeDynCast<BfLiteralExpression>(prevNode))
|
||||||
|
{
|
||||||
|
// Allow expressions like '3...'
|
||||||
|
isDone = false;
|
||||||
|
}
|
||||||
|
|
||||||
auto nextNode = mVisitorPos.Get(checkIdx + 1);
|
auto nextNode = mVisitorPos.Get(checkIdx + 1);
|
||||||
if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
|
if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
|
||||||
{
|
{
|
||||||
|
@ -906,6 +913,10 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int
|
||||||
isDone = false;
|
isDone = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((checkToken == BfToken_Minus) && (chevronDepth > 0))
|
||||||
|
{
|
||||||
|
// Allow - literal
|
||||||
|
}
|
||||||
else if (checkToken != BfToken_LBracket)
|
else if (checkToken != BfToken_LBracket)
|
||||||
isDone = true;
|
isDone = true;
|
||||||
|
|
||||||
|
@ -5341,14 +5352,20 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
|
||||||
bool doAddType = genericIdentifier != NULL;
|
bool doAddType = genericIdentifier != NULL;
|
||||||
bool addAsExpr = false;
|
bool addAsExpr = false;
|
||||||
|
|
||||||
//if (mCompatMode)
|
if (BfNodeDynCast<BfLiteralExpression>(nextNode) != NULL)
|
||||||
{
|
{
|
||||||
if (BfNodeDynCast<BfLiteralExpression>(nextNode) != NULL)
|
doAddType = true;
|
||||||
|
addAsExpr = true;
|
||||||
|
}
|
||||||
|
else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
|
||||||
|
{
|
||||||
|
if (tokenNode->mToken == BfToken_Minus)
|
||||||
{
|
{
|
||||||
doAddType = true;
|
doAddType = true;
|
||||||
addAsExpr = true;
|
addAsExpr = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (genericIdentifier == NULL)
|
if (genericIdentifier == NULL)
|
||||||
{
|
{
|
||||||
auto nextNode = mVisitorPos.GetNext();
|
auto nextNode = mVisitorPos.GetNext();
|
||||||
|
|
|
@ -3100,6 +3100,12 @@ BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression*
|
||||||
{
|
{
|
||||||
outType = NULL;
|
outType = NULL;
|
||||||
|
|
||||||
|
BfMethodState methodState;
|
||||||
|
methodState.mTempKind = BfMethodState::TempKind_Static;
|
||||||
|
SetAndRestoreValue<BfMethodState*> prevMethodState;
|
||||||
|
if (ctx->mModule->mCurMethodState == NULL)
|
||||||
|
prevMethodState.Init(ctx->mModule->mCurMethodState, &methodState);
|
||||||
|
|
||||||
BfConstResolver constResolver(ctx->mModule);
|
BfConstResolver constResolver(ctx->mModule);
|
||||||
BfVariant variant;
|
BfVariant variant;
|
||||||
constResolver.mBfEvalExprFlags = BfEvalExprFlags_NoCast;
|
constResolver.mBfEvalExprFlags = BfEvalExprFlags_NoCast;
|
||||||
|
@ -3303,7 +3309,8 @@ int BfResolvedTypeSet::DoHash(BfType* type, LookupContext* ctx, bool allowRef, i
|
||||||
else if (type->IsConstExprValue())
|
else if (type->IsConstExprValue())
|
||||||
{
|
{
|
||||||
BfConstExprValueType* constExprValueType = (BfConstExprValueType*)type;
|
BfConstExprValueType* constExprValueType = (BfConstExprValueType*)type;
|
||||||
int hashVal = ((int)constExprValueType->mValue.mTypeCode << 17) ^ (constExprValueType->mValue.mInt32 << 3) ^ HASH_CONSTTYPE;
|
int32 dataHash = BeefHash<BfVariant>()(constExprValueType->mValue);
|
||||||
|
int hashVal = ((int)constExprValueType->mValue.mTypeCode << 17) ^ (dataHash << 3) ^ HASH_CONSTTYPE;
|
||||||
hashVal = ((hashVal ^ (Hash(constExprValueType->mType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal;
|
hashVal = ((hashVal ^ (Hash(constExprValueType->mType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal;
|
||||||
return hashVal;
|
return hashVal;
|
||||||
}
|
}
|
||||||
|
@ -4078,7 +4085,8 @@ int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHa
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hashVal = ((int)result.mTypeCode << 17) ^ (result.mInt32 << 3) ^ HASH_CONSTTYPE;
|
int32 dataHash = BeefHash<BfVariant>()(result);
|
||||||
|
auto hashVal = ((int)result.mTypeCode << 17) ^ (dataHash << 3) ^ HASH_CONSTTYPE;
|
||||||
hashVal = ((hashVal ^ (Hash(resultType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal;
|
hashVal = ((hashVal ^ (Hash(resultType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal;
|
||||||
return hashVal;
|
return hashVal;
|
||||||
}
|
}
|
||||||
|
@ -4331,7 +4339,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
|
||||||
BfConstExprValueType* rhsConstExprValueType = (BfConstExprValueType*)rhs;
|
BfConstExprValueType* rhsConstExprValueType = (BfConstExprValueType*)rhs;
|
||||||
|
|
||||||
return (lhsConstExprValueType->mType == rhsConstExprValueType->mType) &&
|
return (lhsConstExprValueType->mType == rhsConstExprValueType->mType) &&
|
||||||
(lhsConstExprValueType->mValue.mInt64 == rhsConstExprValueType->mValue.mInt64);
|
(lhsConstExprValueType->mValue == rhsConstExprValueType->mValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -5032,8 +5040,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (result.mTypeCode == lhsConstExprType->mValue.mTypeCode) &&
|
return result == lhsConstExprType->mValue;
|
||||||
(result.mInt64 == lhsConstExprType->mValue.mInt64);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2827,7 +2827,7 @@ public:
|
||||||
|
|
||||||
// checkEntry->mType can be NULL if we're in the process of filling it in (and this Insert is from an element type)
|
// checkEntry->mType can be NULL if we're in the process of filling it in (and this Insert is from an element type)
|
||||||
// OR if the type resolution failed after node insertion
|
// OR if the type resolution failed after node insertion
|
||||||
if ((checkEntry->mValue != NULL) && (hashVal == checkEntry->mHashCode) && (Equals(checkEntry->mValue, findType, ctx)))
|
if ((checkEntry->mValue != NULL) && (hashVal == checkEntry->mHashCode) && (Equals(checkEntry->mValue, findType, ctx)))
|
||||||
{
|
{
|
||||||
*entryPtr = EntryRef(this, checkEntryIdx);
|
*entryPtr = EntryRef(this, checkEntryIdx);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -48,6 +48,43 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TestRangedArray<T, TRange> where TRange : const var
|
||||||
|
{
|
||||||
|
[OnCompile(.TypeInit), Comptime]
|
||||||
|
static void TypeInit()
|
||||||
|
{
|
||||||
|
if (TRange is var)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int rangeStart = 0;
|
||||||
|
int rangeEnd = 0;
|
||||||
|
|
||||||
|
if (ClosedRange range = TRange as ClosedRange?)
|
||||||
|
{
|
||||||
|
rangeStart = range.Start;
|
||||||
|
rangeEnd = range.End+1;
|
||||||
|
}
|
||||||
|
else if (Range range = TRange as Range?)
|
||||||
|
{
|
||||||
|
rangeStart = range.Start;
|
||||||
|
rangeEnd = range.End;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Compiler.EmitTypeBody(typeof(Self), scope $"""
|
||||||
|
public const String cError = "Invalid type: {TRange}";
|
||||||
|
""");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler.EmitTypeBody(typeof(Self), scope $"""
|
||||||
|
public const int cRangeStart = {rangeStart};
|
||||||
|
public const int cRangeEnd = {rangeEnd};
|
||||||
|
public T[{rangeEnd-rangeStart}] mData;
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -61,6 +98,9 @@ namespace Tests
|
||||||
|
|
||||||
ClassC<const EnumA.A> cc = scope .();
|
ClassC<const EnumA.A> cc = scope .();
|
||||||
Test.Assert(cc.Test() == 1);
|
Test.Assert(cc.Test() == 1);
|
||||||
|
|
||||||
|
Test.Assert(TestRangedArray<int32, -3...3>.cRangeEnd - TestRangedArray<int32, -3...3>.cRangeStart == 7);
|
||||||
|
Test.Assert(TestRangedArray<int32, -3...>.cError == "Invalid type: -3...^1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue