244 lines
6.8 KiB
C++
244 lines
6.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
// uLang Compiler Public API
|
|
|
|
#pragma once
|
|
|
|
#include "uLang/Common/Common.h"
|
|
#include "uLang/Common/Containers/RangeView.h"
|
|
|
|
namespace uLang
|
|
{
|
|
|
|
// If you change this enum macro, you must keep things in sync with both VVMVerseEffectSet.h and MakeEffectSet
|
|
#define VERSE_ENUM_EFFECTS(v) \
|
|
v(suspends) \
|
|
v(decides) \
|
|
v(diverges) \
|
|
v(reads) \
|
|
v(writes) \
|
|
v(allocates) \
|
|
v(dictates) \
|
|
v(no_rollback)
|
|
|
|
enum class EEffect
|
|
{
|
|
#define VISIT_EFFECT(Name) Name,
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
};
|
|
|
|
#define VISIT(Name) 1 +
|
|
inline constexpr int32_t EEffectNum = VERSE_ENUM_EFFECTS(VISIT) 0;
|
|
#undef VISIT
|
|
|
|
struct SEffectInfo
|
|
{
|
|
const char* _AttributeName;
|
|
EEffect _Effect;
|
|
};
|
|
|
|
VERSECOMPILER_API TRangeView<SEffectInfo*, SEffectInfo*> AllEffectInfos();
|
|
VERSECOMPILER_API SEffectInfo GetEffectInfo(EEffect Effect);
|
|
|
|
struct SEffectSetBase {};
|
|
|
|
struct SEffectSet : private SEffectSetBase
|
|
{
|
|
constexpr SEffectSet()
|
|
: SEffectSetBase()
|
|
#define VISIT_EFFECT(Name) , _##Name(false)
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
{}
|
|
constexpr SEffectSet(EEffect SingleEffect)
|
|
: SEffectSetBase()
|
|
#define VISIT_EFFECT(Name) , _##Name(SingleEffect == EEffect::Name)
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
{}
|
|
|
|
friend constexpr SEffectSet operator~(const SEffectSet Operand)
|
|
{
|
|
SEffectSet Result;
|
|
#define VISIT_EFFECT(Name) Result._##Name = !Operand._##Name;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
SEffectSet& operator|=(SEffectSet Rhs)
|
|
{
|
|
#define VISIT_EFFECT(Name) _##Name = _##Name || Rhs._##Name;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return *this;
|
|
}
|
|
friend constexpr SEffectSet operator|(const SEffectSet Lhs, const SEffectSet Rhs)
|
|
{
|
|
SEffectSet Result;
|
|
#define VISIT_EFFECT(Name) Result._##Name = Lhs._##Name || Rhs._##Name;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
SEffectSet& operator&=(SEffectSet Rhs)
|
|
{
|
|
#define VISIT_EFFECT(Name) _##Name = _##Name && Rhs._##Name;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return *this;
|
|
}
|
|
friend constexpr SEffectSet operator&(const SEffectSet Lhs, const SEffectSet Rhs)
|
|
{
|
|
SEffectSet Result;
|
|
#define VISIT_EFFECT(Name) Result._##Name = Lhs._##Name && Rhs._##Name;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
SEffectSet& operator^=(SEffectSet Rhs)
|
|
{
|
|
#define VISIT_EFFECT(Name) _##Name = (!_##Name && Rhs._##Name) || (_##Name && !Rhs._##Name);
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return *this;
|
|
}
|
|
friend constexpr SEffectSet operator^(const SEffectSet Lhs, const SEffectSet Rhs)
|
|
{
|
|
SEffectSet Result;
|
|
#define VISIT_EFFECT(Name) Result._##Name = (!Lhs._##Name && Rhs._##Name) || (Lhs._##Name && !Rhs._##Name);
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
bool operator[](EEffect Effect) const
|
|
{
|
|
return Get(Effect);
|
|
}
|
|
|
|
constexpr bool HasAny(SEffectSet Rhs) const
|
|
{
|
|
bool Result = false;
|
|
#define VISIT_EFFECT(Name) Result = Result || (_##Name && Rhs._##Name);
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
constexpr bool HasAll(SEffectSet Rhs) const
|
|
{
|
|
bool Result = true;
|
|
#define VISIT_EFFECT(Name) Result = Result && (!Rhs._##Name || _##Name);
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
friend constexpr bool operator==(const SEffectSet Lhs, const SEffectSet Rhs)
|
|
{
|
|
bool Result = true;
|
|
#define VISIT_EFFECT(Name) Result = Result && (Lhs._##Name == Rhs._##Name);
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
friend constexpr bool operator!=(const SEffectSet Lhs, const SEffectSet Rhs)
|
|
{
|
|
bool Result = false;
|
|
#define VISIT_EFFECT(Name) Result = Result || (Lhs._##Name != Rhs._##Name);
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
return Result;
|
|
}
|
|
|
|
SEffectSet With(EEffect SingleEffect, bool bEnable = true) const
|
|
{
|
|
SEffectSet Result = *this;
|
|
Result.Set(SingleEffect, bEnable);
|
|
return Result;
|
|
}
|
|
|
|
// The number of bits set - used for some ordering in effect decomposition
|
|
int32_t Num() const
|
|
{
|
|
return 0
|
|
#define VISIT_EFFECT(Name) + (_##Name ? 1 : 0)
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
;
|
|
}
|
|
|
|
private:
|
|
#define VISIT_EFFECT(Name) bool _##Name : 1;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
|
|
bool Get(EEffect Effect) const
|
|
{
|
|
switch (Effect)
|
|
{
|
|
#define VISIT_EFFECT(Name) case EEffect::Name: return _##Name;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
default: ULANG_UNREACHABLE();
|
|
};
|
|
}
|
|
|
|
void Set(EEffect Effect, bool Enable)
|
|
{
|
|
switch(Effect)
|
|
{
|
|
#define VISIT_EFFECT(Name) case EEffect::Name: _##Name = Enable; break;
|
|
VERSE_ENUM_EFFECTS(VISIT_EFFECT)
|
|
#undef VISIT_EFFECT
|
|
default: ULANG_UNREACHABLE();
|
|
};
|
|
}
|
|
};
|
|
|
|
constexpr SEffectSet operator|(const EEffect Lhs, const EEffect Rhs)
|
|
{
|
|
return SEffectSet(Lhs) | SEffectSet(Rhs);
|
|
}
|
|
|
|
ULANG_FORCEINLINE uint32_t GetTypeHash(const SEffectSet& Effects)
|
|
{
|
|
static_assert(EEffectNum <= sizeof(uint32_t) * 8);
|
|
|
|
uint32_t Hash{};
|
|
uint32_t I{};
|
|
#define VISIT(Name) if (Effects[EEffect::Name]) { Hash |= (1 << I); } ++I;
|
|
VERSE_ENUM_EFFECTS(VISIT);
|
|
#undef VISIT
|
|
return Hash;
|
|
}
|
|
|
|
namespace EffectSets
|
|
{
|
|
// Singular effects
|
|
constexpr SEffectSet Converges = SEffectSet{};
|
|
constexpr SEffectSet Suspends = EEffect::suspends;
|
|
constexpr SEffectSet Computes = EEffect::diverges;
|
|
constexpr SEffectSet NoRollback = EEffect::no_rollback;
|
|
constexpr SEffectSet Decides = EEffect::decides;
|
|
constexpr SEffectSet Dictates = EEffect::dictates;
|
|
|
|
// Aggregate effects
|
|
constexpr SEffectSet Reads = EEffect::reads | EEffect::dictates;
|
|
constexpr SEffectSet Writes = EEffect::writes | EEffect::dictates;
|
|
constexpr SEffectSet Allocates = EEffect::allocates | EEffect::dictates;
|
|
constexpr SEffectSet Transacts = EEffect::diverges | EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::dictates;
|
|
constexpr SEffectSet VariesDeprecated = Transacts;
|
|
|
|
// Contextual defaults
|
|
constexpr SEffectSet ClassAndInterfaceDefault = Transacts;
|
|
constexpr SEffectSet FunctionDefault = Transacts | EEffect::no_rollback;
|
|
constexpr SEffectSet ModuleDefault = EEffect::diverges;
|
|
}
|
|
|
|
}
|