Skip to content

Commit 538a729

Browse files
committed
Add FunctionObjects test
1 parent 0b5a29a commit 538a729

File tree

11 files changed

+365
-0
lines changed

11 files changed

+365
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build
2+
out
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package;
2+
3+
import haxe.PosInfos;
4+
5+
class Main {
6+
static var returnCode = 0;
7+
static function assert(b: Bool, infos: Null<PosInfos> = null) {
8+
if(!b) {
9+
haxe.Log.trace("Assert failed", infos);
10+
returnCode = 1;
11+
}
12+
}
13+
14+
static var thing = 0;
15+
static function bla() {
16+
thing++;
17+
}
18+
19+
public static function main() {
20+
final func: () -> Void = bla;
21+
func();
22+
assert(thing == 1);
23+
24+
var func2: Null<() -> Void> = null;
25+
if(func2 == null) {
26+
func2 = bla;
27+
}
28+
func2();
29+
assert(thing == 2);
30+
31+
if(returnCode != 0) {
32+
Sys.exit(returnCode);
33+
}
34+
}
35+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# The following are added automatically:
2+
# -lib reflaxe.cpp
3+
# -D cpp-output=out
4+
5+
-D mainClass=Main
6+
-main Main
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
src/_main_.cpp
2+
src/Main.cpp
3+
include/haxe_PosInfos.h
4+
include/cxx_DynamicToString.h
5+
include/_AnonUtils.h
6+
include/_AnonStructs.h
7+
include/Main.h
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <optional>
5+
#include "haxe_PosInfos.h"
6+
7+
class Main {
8+
public:
9+
static int thing;
10+
static int returnCode;
11+
12+
static void assert(bool b, std::optional<std::shared_ptr<haxe::PosInfos>> infos = std::nullopt);
13+
static void bla();
14+
static void main();
15+
};
16+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include "_AnonUtils.h"
4+
5+
#include <optional>
6+
7+
namespace haxe {
8+
9+
10+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#include <memory>
5+
6+
// haxe::shared_anon | haxe::unique_anon
7+
// Helper functions for generating "anonymous struct" smart pointers.
8+
namespace haxe {
9+
10+
template<typename Anon, class... Args>
11+
std::shared_ptr<Anon> shared_anon(Args... args) {
12+
return std::make_shared<Anon>(Anon::make(args...));
13+
}
14+
15+
template<typename Anon, class... Args>
16+
std::unique_ptr<Anon> unique_anon(Args... args) {
17+
return std::make_unique<Anon>(Anon::make(args...));
18+
}
19+
20+
}
21+
22+
// ---------------------------------------------------------------------
23+
24+
// haxe::optional_info
25+
// Returns information about std::optional<T> types.
26+
namespace haxe {
27+
28+
template <typename T>
29+
struct optional_info {
30+
using inner = T;
31+
static constexpr bool isopt = false;
32+
};
33+
34+
template <typename T>
35+
struct optional_info<std::optional<T>> {
36+
using inner = typename optional_info<T>::inner;
37+
static constexpr bool isopt = true;
38+
};
39+
40+
}
41+
42+
// ---------------------------------------------------------------------
43+
44+
45+
// haxe::_unwrap_mm
46+
// Unwraps all the "memory management" types to get the underlying
47+
// value type. Also provided whether or not that type is deref-able.
48+
namespace haxe {
49+
50+
template<typename T>
51+
struct _unwrap_mm {
52+
using inner = T;
53+
constexpr static bool can_deref = false;
54+
static inline inner& get(T& in) { return in; }
55+
};
56+
57+
template<typename T>
58+
struct _unwrap_mm<T*> {
59+
using inner = typename _unwrap_mm<T>::inner;
60+
constexpr static bool can_deref = true;
61+
static inline inner& get(T* in) { return _unwrap_mm<T>::get(*in); }
62+
};
63+
64+
template<typename T>
65+
struct _unwrap_mm<T&> {
66+
using inner = typename _unwrap_mm<T>::inner;
67+
constexpr static bool can_deref = false;
68+
static inline inner& get(T& in) { return _unwrap_mm<T>::get(in); }
69+
};
70+
71+
template<typename T>
72+
struct _unwrap_mm<std::shared_ptr<T>> {
73+
using inner = typename _unwrap_mm<T>::inner;
74+
constexpr static bool can_deref = true;
75+
static inline inner& get(std::shared_ptr<T> in) { return _unwrap_mm<T>::get(*in); }
76+
};
77+
78+
template<typename T>
79+
struct _unwrap_mm<std::unique_ptr<T>> {
80+
using inner = typename _unwrap_mm<T>::inner;
81+
constexpr static bool can_deref = true;
82+
static inline inner& get(std::unique_ptr<T> in) { return _unwrap_mm<T>::get(*in); }
83+
};
84+
85+
template<typename T, typename U = typename _unwrap_mm<T>::inner>
86+
static inline U& unwrap(T in) { return _unwrap_mm<T>::get(in); }
87+
88+
}
89+
90+
// ---------------------------------------------------------------------
91+
92+
// GEN_EXTRACTOR_FUNC
93+
// Generates a function named extract_[fieldName].
94+
//
95+
// Given any object, it checks whether that object has a field of the same name
96+
// and type as the class this function is a member of (using `haxe::optional_info`).
97+
//
98+
// If it does, it returns the object's field's value; otherwise, it returns `std::nullopt`.
99+
//
100+
// Useful for extracting values for optional parameters for anonymous structure
101+
// classes since the input object may or may not have the field.
102+
103+
#define GEN_EXTRACTOR_FUNC(fieldName)\
104+
template<typename T, typename Other = decltype(T().fieldName), typename U = typename haxe::optional_info<Other>::inner>\
105+
static auto extract_##fieldName(T other) {\
106+
if constexpr(!haxe::optional_info<decltype(fieldName)>::isopt && haxe::optional_info<Other>::isopt) {\
107+
return other.customParam.get();\
108+
} else if constexpr(std::is_same<U,haxe::optional_info<decltype(fieldName)>::inner>::value) {\
109+
return other.customParam;\
110+
} else {\
111+
return std::nullopt;\
112+
}\
113+
}
114+
115+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#pragma once
2+
3+
#include <deque>
4+
#include <memory>
5+
#include <sstream>
6+
#include <string>
7+
#include <type_traits>
8+
#include <utility>
9+
#include "_AnonUtils.h"
10+
11+
namespace haxe {
12+
13+
template<typename T, typename = std::string>
14+
struct has_to_string : std::false_type { };
15+
16+
template<typename T>
17+
struct has_to_string <T, decltype(std::declval<T>().toString())> : std::true_type { };
18+
19+
template<typename>
20+
struct is_deque : std::false_type {};
21+
22+
template<typename T>
23+
struct is_deque<std::deque<T>> : std::true_type {};
24+
25+
struct DynamicToString: public std::string {
26+
template<typename T>
27+
DynamicToString(T s): std::string(ToString(s)) {}
28+
29+
template<typename T>
30+
static std::string ToString(T s) {
31+
if constexpr(std::is_pointer<T>::value) {
32+
if(s == nullptr) {
33+
return "nullptr";
34+
}
35+
}
36+
if constexpr(haxe::optional_info<T>::isopt) {
37+
if(s.has_value()) {
38+
return ToString(s.value());
39+
} else {
40+
return "null";
41+
}
42+
} else if constexpr(std::is_same_v<T, bool>) {
43+
return s ? "true" : "false";
44+
} else if constexpr(std::is_integral_v<T> || std::is_floating_point_v<T>) {
45+
return std::to_string(s);
46+
} else if constexpr(std::is_convertible<T, std::string>::value) {
47+
return std::string(s);
48+
} else if constexpr(has_to_string<T>::value) {
49+
return s.toString();
50+
} else if constexpr(haxe::_unwrap_mm<T>::can_deref) {
51+
if constexpr(std::is_trivially_copy_assignable_v<std::remove_reference_t<decltype(*std::declval<T>())>>) {
52+
return ToString(*s);
53+
}
54+
} else if constexpr(is_deque<T>::value) {
55+
std::string result = "[";
56+
auto len = s.size();
57+
for(decltype(len) i = 0; i < len; i++) {
58+
result += (i > 0 ? ", " : "") + ToString(s[i]);
59+
}
60+
return result + "]";
61+
}
62+
63+
// Print address if all else fails
64+
std::stringstream pointer_stream;
65+
pointer_stream << std::addressof(s);
66+
return "<unknown(address:" + pointer_stream.str() + ")>";
67+
}
68+
};
69+
70+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
3+
#include <deque>
4+
#include <memory>
5+
#include <optional>
6+
#include <string>
7+
#include "_AnonStructs.h"
8+
#include "_AnonUtils.h"
9+
#include "cxx_DynamicToString.h"
10+
11+
namespace haxe {
12+
13+
// { className: String, fileName: String, lineNumber: Int, methodName: String, customParams: Null<Array<cxx.DynamicToString>> }
14+
struct PosInfos {
15+
16+
// default constructor
17+
PosInfos() {}
18+
19+
// auto-construct from any object's fields
20+
template<typename T>
21+
PosInfos(T o):
22+
className(haxe::unwrap(o).className),
23+
fileName(haxe::unwrap(o).fileName),
24+
lineNumber(haxe::unwrap(o).lineNumber),
25+
methodName(haxe::unwrap(o).methodName),
26+
customParams(extract_customParams(haxe::unwrap(o)))
27+
{}
28+
29+
// construct fields directly
30+
static PosInfos make(std::string className, std::string fileName, int lineNumber, std::string methodName, std::optional<std::shared_ptr<std::deque<haxe::DynamicToString>>> customParams = std::nullopt) {
31+
PosInfos result;
32+
result.className = className;
33+
result.fileName = fileName;
34+
result.lineNumber = lineNumber;
35+
result.methodName = methodName;
36+
result.customParams = customParams;
37+
return result;
38+
}
39+
40+
// fields
41+
std::string className;
42+
std::string fileName;
43+
int lineNumber;
44+
std::string methodName;
45+
std::optional<std::shared_ptr<std::deque<haxe::DynamicToString>>> customParams;
46+
47+
GEN_EXTRACTOR_FUNC(customParams)
48+
};
49+
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include "Main.h"
2+
3+
#include <cstdlib>
4+
#include <functional>
5+
#include <iostream>
6+
#include <string>
7+
#include "_AnonStructs.h"
8+
9+
using namespace std::string_literals;
10+
11+
int Main::thing = 0;
12+
13+
int Main::returnCode = 0;
14+
15+
void Main::assert(bool b, std::optional<std::shared_ptr<haxe::PosInfos>> infos) {
16+
if(!b) {
17+
{
18+
auto temp = infos.value_or(haxe::shared_anon<haxe::PosInfos>("", "test/unit_testing/tests/FunctionObjects/Main.hx"s, 9, ""));
19+
std::cout << temp->fileName << ":" << temp->lineNumber << ": " << "Assert failed"s << std::endl;
20+
};
21+
Main::returnCode = 1;
22+
};
23+
}
24+
25+
void Main::bla() {
26+
Main::thing++;
27+
}
28+
29+
void Main::main() {
30+
std::function<void()> func = Main::bla;
31+
32+
func();
33+
Main::assert(Main::thing == 1, haxe::shared_anon<haxe::PosInfos>("Main"s, "test/unit_testing/tests/FunctionObjects/Main.hx"s, 22, "main"s));
34+
35+
std::optional<std::function<void()>> func2 = std::nullopt;
36+
37+
if(!func2.has_value()) {
38+
func2 = Main::bla;
39+
};
40+
41+
func2.value_or(nullptr)();
42+
Main::assert(Main::thing == 2, haxe::shared_anon<haxe::PosInfos>("Main"s, "test/unit_testing/tests/FunctionObjects/Main.hx"s, 29, "main"s));
43+
44+
if(Main::returnCode != 0) {
45+
exit(Main::returnCode);
46+
};
47+
}

0 commit comments

Comments
 (0)