Skip to content

Commit

Permalink
Added support for enum class (#47)
Browse files Browse the repository at this point in the history
This change adds support for enum classes as part nautilus vals
Signed-off-by: Nils Schubert <nilslpschubert@gmail.com>
Co-authored-by: Philipp Grulich <philippgrulich@hotmail.de>
  • Loading branch information
keyseven123 authored Oct 4, 2024
1 parent 8b78e3b commit c8b754a
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 120 deletions.
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

0 comments on commit c8b754a

Please sign in to comment.