Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for enum class #47

Merged
merged 9 commits into from
Oct 4, 2024
4 changes: 2 additions & 2 deletions nautilus/include/nautilus/val_concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ concept convertible_to_integral = (std::is_convertible_v<T, int> || std::is_conv
template <typename T>
concept is_fundamental_val = requires {
typename std::remove_reference_t<T>::basic_type; // Ensure T has a member type 'basic_type'
requires std::is_fundamental_v<typename std::remove_reference_t<T>::basic_type>; // Ensure 'basic_type' is integral
requires !std::is_enum_v<typename std::remove_reference_t<T>::basic_type> && std::is_fundamental_v<typename std::remove_reference_t<T>::basic_type>; // Ensure 'basic_type' is integral
};

template <typename T>
concept convertible_to_fundamental = !is_fundamental_val<T> && (convertible_to_integral<T> || std::is_convertible_v<T, float> || std::is_convertible_v<T, double> || std::is_convertible_v<T, bool>);
concept convertible_to_fundamental = !std::is_enum_v<T> && !is_fundamental_val<T> && (convertible_to_integral<T> || std::is_convertible_v<T, float> || std::is_convertible_v<T, double> || std::is_convertible_v<T, bool>);

template <typename T>
concept is_arithmetic = std::is_arithmetic_v<T>;
Expand Down
86 changes: 76 additions & 10 deletions nautilus/include/nautilus/val_enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "nautilus/val_concepts.hpp"
#include <iostream>
#include <memory>
#include <utility>

#ifdef ENABLE_TRACING

Expand All @@ -20,21 +21,80 @@ class val<T> {
using raw_type = underlying_type_t;
using basic_type = raw_type;

val() : value() {}

#ifdef ENABLE_TRACING
val(val<underlying_type_t> t) : state(t.state), value((T) details::getRawValue(t)) {}
val(val<T>& t) : state(tracing::traceCopy(t.state)), value(t.value) {}
val(val<T>&& t) : state(t.state), value(t.value) {}
val(T val) : state(tracing::traceConstant((underlying_type_t) val)), value(val) {}
template <T>
requires std::is_enum_v<T> && (!std::is_convertible_v<T, std::underlying_type_t<T>>)
val(T val) : state(tracing::traceConstant(static_cast<std::underlying_type_t<T>>(val))), value(static_cast<std::underlying_type_t<T>>(val)) {
}

template <T>
requires std::is_enum_v<T> && (!std::is_convertible_v<T, std::underlying_type_t<T>>)
val(val<T>& val) : state(tracing::traceConstant(static_cast<std::underlying_type_t<T>>(val))), value(static_cast<std::underlying_type_t<T>>(val)) {
}
val(val<underlying_type_t> t) : state(t.state), value((T) details::getRawValue(t)) {
}
val(val<T>& t) : state(tracing::traceCopy(t.state)), value(t.value) {
}
val(val<T>&& t) : state(t.state), value(t.value) {
}
val(T val) : state(tracing::traceConstant(static_cast<std::underlying_type_t<T>>(val))), value(val) {
}
#else
val(val<underlying_type_t> t) : value((T) details::getRawValue(t)) {}
val(val<T>& t) : value(t.value) {}
val(T val) : value(val) {}
template <T>
requires std::is_enum_v<T> && (!std::is_convertible_v<T, std::underlying_type_t<T>>)
val(T val) : value(static_cast<std::underlying_type_t<T>>(val)) {
}

template <T>
requires std::is_enum_v<T> && (!std::is_convertible_v<T, std::underlying_type_t<T>>)
val(val<T>& val) : value(static_cast<std::underlying_type_t<T>>(val)) {
}

val(val<underlying_type_t> t) : value((T) details::getRawValue(t)) {
}
val(val<T>& t) : value(t.value) {
}
val(T val) : value(val) {
}
#endif


val<bool> operator==(val<T>& other) const {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp(tracing::EQ, Type::b, state, other.state);
return val<bool>(tc);
}
#endif
return value == other.value;
}

val<bool> operator==(const T& other) const {
auto res = val<T>(other);
return *this == res;
}

val<bool> operator!=(val<T>& other) const {
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
auto tc = tracing::traceBinaryOp(tracing::NEQ, Type::b, state, other.state);
return val<bool>(tc);
}
#endif
return value != other.value;
}

val<bool> operator!=(const T& other) const {
return *this == val<T>(other);
}

operator val<underlying_type_t>() const {
return value;
#ifdef ENABLE_TRACING
if (tracing::inTracer()) {
return val<underlying_type_t>(state);
}
#endif
return val<underlying_type_t>(static_cast<std::underlying_type_t<T>>(value));
}

val<T>& operator=(const val<T>& other) {
Expand All @@ -56,4 +116,10 @@ class val<T> {
const T value;
};

template <typename Type>
requires std::is_enum_v<Type>
auto inline make_value(const Type& value) {
return val<Type>(value);
}

} // namespace nautilus
34 changes: 33 additions & 1 deletion nautilus/test/common/EnumFunction.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
#pragma once

#include <nautilus/Engine.hpp>
#include <nautilus/val.hpp>

namespace nautilus {

enum Color { BLUE, GREEN };
enum class LogLevel : uint8_t { LOG_NONE = 1, LOG_FATAL_ERROR = 2, LOG_ERROR = 3, LOG_WARNING = 4, LOG_INFO = 5, LOG_DEBUG = 6, LOG_TRACE = 7 };


val<bool> handleEnum(val<Color> enumVal) {
return enumVal == Color::BLUE;
}

val<bool> handleEnumLogLevel(val<LogLevel> enumVal) {
return enumVal == LogLevel::LOG_DEBUG || enumVal == LogLevel::LOG_INFO;
}

val<int32_t> isEnum(val<Color> enumVal) {
if (enumVal == Color::BLUE) {
return 1;
Expand All @@ -33,7 +40,32 @@ int32_t enumFunction(Color value) {
}
}

auto enumClassFunction(LogLevel level) {
switch (level) {
case LogLevel::LOG_NONE:
return 1;
case LogLevel::LOG_FATAL_ERROR:
return 2;
case LogLevel::LOG_ERROR:
return 3;
case LogLevel::LOG_WARNING:
return 4;
case LogLevel::LOG_INFO:
return 5;
case LogLevel::LOG_DEBUG:
return 6;
case LogLevel::LOG_TRACE:
return 7;
}

return 43;
}

val<int32_t> callEnumFunction(val<Color> enumVal) {
return invoke(enumFunction, enumVal);
}
} // namespace nautilus

val<int32_t> callEnumClassFunction(val<LogLevel> enumClassVal) {
return invoke(enumClassFunction, enumClassVal);
}
} // namespace nautilus

This file was deleted.

3 changes: 0 additions & 3 deletions nautilus/test/data/enum-tests/after_ssa/getEnum.trace

This file was deleted.

4 changes: 0 additions & 4 deletions nautilus/test/data/enum-tests/after_ssa/handleEnum.trace

This file was deleted.

19 changes: 0 additions & 19 deletions nautilus/test/data/enum-tests/after_ssa/isEnum.trace

This file was deleted.

7 changes: 0 additions & 7 deletions nautilus/test/data/enum-tests/ir/callEnumFunction.trace

This file was deleted.

7 changes: 0 additions & 7 deletions nautilus/test/data/enum-tests/ir/getEnum.trace

This file was deleted.

8 changes: 0 additions & 8 deletions nautilus/test/data/enum-tests/ir/handleEnum.trace

This file was deleted.

28 changes: 0 additions & 28 deletions nautilus/test/data/enum-tests/ir/isEnum.trace

This file was deleted.

3 changes: 0 additions & 3 deletions nautilus/test/data/enum-tests/tracing/callEnumFunction.trace

This file was deleted.

3 changes: 0 additions & 3 deletions nautilus/test/data/enum-tests/tracing/getEnum.trace

This file was deleted.

4 changes: 0 additions & 4 deletions nautilus/test/data/enum-tests/tracing/handleEnum.trace

This file was deleted.

17 changes: 0 additions & 17 deletions nautilus/test/data/enum-tests/tracing/isEnum.trace

This file was deleted.

13 changes: 13 additions & 0 deletions nautilus/test/execution-tests/ExecutionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ void expressionTests(engine::NautilusEngine& engine) {
REQUIRE(f((char) CHAR_MIN) == (char) CHAR_MAX);
}

SECTION("callEnumClassFunction") {
auto f = engine.registerFunction(callEnumClassFunction);
REQUIRE(f(LogLevel::LOG_DEBUG) == 6);
REQUIRE(f(LogLevel::LOG_NONE) == 1);
}

SECTION("handleEnumLogLevel") {
auto f = engine.registerFunction(handleEnumLogLevel);
REQUIRE(f(LogLevel::LOG_INFO));
REQUIRE(f(LogLevel::LOG_DEBUG));
REQUIRE(!f(LogLevel::LOG_NONE));
}

SECTION("callEnumFunction") {
auto f = engine.registerFunction(callEnumFunction);
REQUIRE(f(Color::BLUE) == 42);
Expand Down
4 changes: 3 additions & 1 deletion nautilus/test/execution-tests/TracingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ void runTraceTests(const std::string& category, std::vector<std::tuple<std::stri
for (auto& test : tests) {
auto func = std::get<1>(test);
auto name = std::get<0>(test);
auto executionTrace = tracing::TraceContext::trace(func);
DYNAMIC_SECTION(name) {
auto executionTrace = tracing::TraceContext::trace(func);
DYNAMIC_SECTION("tracing") {
REQUIRE(checkTestFile(executionTrace.get(), category, "tracing", name));
}
Expand Down Expand Up @@ -276,6 +276,8 @@ TEST_CASE("Enum Trace Test") {
{"isEnum", details::createFunctionWrapper(isEnum)},
{"getEnum", details::createFunctionWrapper(getEnum)},
{"callEnumFunction", details::createFunctionWrapper(callEnumFunction)},
{"callEnumClassFunction", details::createFunctionWrapper(callEnumClassFunction)},
{"handleEnumLogLevel", details::createFunctionWrapper(handleEnumLogLevel)},
};
runTraceTests("enum-tests", tests);
}
Expand Down