Skip to content

Instantly share code, notes, and snippets.

@nikki93
Created December 20, 2021 21:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikki93/97ff376abb6718427387bb9cca2f548a to your computer and use it in GitHub Desktop.
Save nikki93/97ff376abb6718427387bb9cca2f548a to your computer and use it in GitHub Desktop.
#include <string.h>
#include "rect.hh"
#include "sum_fields.hh"
#include "person/person.hh"
#include "gx.hh"
//
// Types
//
struct Point;
struct Before;
struct Inner;
struct Outer;
struct PtrPtr;
template<typename T>
struct Holder;
struct HasArray;
template<typename T>
using Seq = gx::Slice<T>;
struct SingleIncr;
struct DoubleIncr;
struct Nums;
struct HasDefaults;
struct HasString;
struct Foo;
struct Bar;
struct Point {
float x;
float y;
};
struct Before {
Point p;
};
struct Inner {
int z;
};
struct Outer {
int x;
int y;
Inner inner;
};
struct PtrPtr {
int **pp;
};
template<typename T>
struct Holder {
T Item;
};
struct HasArray {
gx::Array<int, 4> arr;
};
struct SingleIncr {
int val;
};
struct DoubleIncr {
int val;
};
struct Nums {
int A;
int B;
int C;
int D;
};
struct HasDefaults {
int foo = 42;
float bar = 6.4;
Point point = { 1, 2 };
};
struct HasString {
gx::String s;
};
struct Foo {
int val;
};
struct Bar {
int X;
int Y;
};
//
// Meta
//
inline void forEachField(Point &val, auto &&func) {
}
inline void forEachField(Before &val, auto &&func) {
}
inline void forEachField(Inner &val, auto &&func) {
}
inline void forEachField(Outer &val, auto &&func) {
}
inline void forEachField(PtrPtr &val, auto &&func) {
}
template<typename T>
struct gx::FieldTag<Holder<T>, 0> {
inline static constexpr gx::FieldAttribs attribs { .name = "item" };
};
template<typename T>
inline void forEachField(Holder<T> &val, auto &&func) {
func(gx::FieldTag<Holder<T>, 0>(), val.Item);
}
inline void forEachField(HasArray &val, auto &&func) {
}
inline void forEachField(SingleIncr &val, auto &&func) {
}
inline void forEachField(DoubleIncr &val, auto &&func) {
}
template<>
struct gx::FieldTag<Nums, 0> {
inline static constexpr gx::FieldAttribs attribs { .name = "a" };
};
template<>
struct gx::FieldTag<Nums, 1> {
inline static constexpr gx::FieldAttribs attribs { .name = "b" };
};
template<>
struct gx::FieldTag<Nums, 2> {
inline static constexpr gx::FieldAttribs attribs { .name = "c" };
};
template<>
struct gx::FieldTag<Nums, 3> {
inline static constexpr gx::FieldAttribs attribs { .name = "d", .twice = true };
};
inline void forEachField(Nums &val, auto &&func) {
func(gx::FieldTag<Nums, 0>(), val.A);
func(gx::FieldTag<Nums, 1>(), val.B);
func(gx::FieldTag<Nums, 2>(), val.C);
func(gx::FieldTag<Nums, 3>(), val.D);
}
inline void forEachField(HasDefaults &val, auto &&func) {
}
inline void forEachField(HasString &val, auto &&func) {
}
inline void forEachField(Foo &val, auto &&func) {
}
template<>
struct gx::FieldTag<Bar, 0> {
inline static constexpr gx::FieldAttribs attribs { .name = "x" };
};
template<>
struct gx::FieldTag<Bar, 1> {
inline static constexpr gx::FieldAttribs attribs { .name = "y" };
};
inline void forEachField(Bar &val, auto &&func) {
func(gx::FieldTag<Bar, 0>(), val.X);
func(gx::FieldTag<Bar, 1>(), val.Y);
}
//
// Function declarations
//
int fib(int n);
void testFib();
void testUnary();
void testVariables();
void testIncDec();
void testIf();
void testFor();
void setToFortyTwo(int *ptr);
void testPointer();
int outerSum(Outer o);
void setXToFortyTwo(Outer *o);
void testStruct();
float sum(Point p);
void setZero(Point *p);
void testMethod();
template<typename T>
T add(T a, T b);
template<typename T>
void incrHolder(Holder<T> *h);
template<typename T>
T get(Holder<T> h);
template<typename T>
void set(Holder<T> *h, T Item);
void testGenerics();
void iterateOneToTen(auto &&f);
void testLambdas();
void setSecondElementToThree(gx::Array<int, 4> *arr);
void testArrays();
void appendFortyTwo(gx::Slice<int> *s);
void testSlices();
template<typename T>
int len(Seq<T> *s);
template<typename T>
void add(Seq<T> *s, T val);
template<typename T, typename PT>
void incrSeq(Seq<T> *s);
void incr(SingleIncr *s);
void incr(DoubleIncr *s);
void testSeqs();
void setGlobalXToFortyTwo();
void checkGlobalXIsFortyTwo();
int three();
bool isGlobalSliceEmpty();
int apply(int val, auto &&fn);
void testGlobalVariables();
void testImports();
void testExterns();
void testConversions();
void testMeta();
void testDefaults();
void testStrings();
int main();
void check(bool val);
int Val(Foo *f);
Foo NewFoo(int val);
//
// Variables
//
inline constexpr auto initialGlobalX = 23;
inline auto globalX = initialGlobalX;
inline auto globalZ = 14;
inline auto globalW = globalX + 42;
inline auto globalY = globalX - three();
inline gx::Slice<int> globalSlice;
inline auto globalApplied = apply(3, [](int i) {
return 2 * i;
});
//
// Function definitions
//
int fib(int n) {
if (n <= 1) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
void testFib() {
check(fib(6) == 8);
}
void testUnary() {
check(-(3) == -3);
check(+(3) == 3);
}
void testVariables() {
auto x = 3;
auto y = 4;
check(x == 3);
check(y == 4);
y = y + 2;
x = x + 1;
check(y == 6);
check(x == 4);
y += 2;
x += 1;
check(y == 8);
check(x == 5);
}
void testIncDec() {
auto x = 0;
(x)++;
check(x == 1);
(x)--;
check(x == 0);
}
void testIf() {
auto x = 0;
if (auto cond = false; cond) {
x = 2;
}
check(x == 0);
}
void testFor() {
{
auto sum = 0;
for (auto i = 0; i < 5; (i)++) {
sum += i;
}
check(sum == 10);
}
{
auto sum = 0;
auto i = 0;
for (; i < 5; ) {
sum += i;
(i)++;
}
check(sum == 10);
}
{
auto sum = 0;
auto i = 0;
for (; ; ) {
if (i >= 5) {
break;
}
sum += i;
(i)++;
}
check(sum == 10);
}
}
void setToFortyTwo(int *ptr) {
*ptr = 42;
}
void testPointer() {
auto val = 42;
check(val == 42);
auto ptr = &val;
*ptr = 14;
check(val == 14);
setToFortyTwo(ptr);
check(val == 42);
}
int outerSum(Outer o) {
return o.x + o.y + o.inner.z;
}
void setXToFortyTwo(Outer *o) {
gx::deref(o).x = 42;
}
void testStruct() {
{
auto s = Outer {};
check(s.x == 0);
check(s.y == 0);
check(s.inner.z == 0);
{
auto p = &s;
gx::deref(p).x = 2;
check(gx::deref(p).x == 2);
check(s.x == 2);
s.y = 4;
check(gx::deref(p).y == 4);
}
check(outerSum(s) == 6);
setXToFortyTwo(&s);
check(s.x == 42);
}
{
auto s = Outer { 2, 3, Inner { 4 } };
check(s.x == 2);
check(s.y == 3);
check(s.inner.z == 4);
s.x += 1;
s.y += 1;
s.inner.z += 1;
check(s.x == 3);
check(s.y == 4);
check(s.inner.z == 5);
}
{
auto s = Outer { .x = 2, .y = 3, .inner = Inner { .z = 4 } };
check(s.x == 2);
check(s.y == 3);
check(s.inner.z == 4);
}
{
auto s = Outer {
.x = 2,
.y = 3,
.inner = Inner {
.z = 4,
},
};
check(s.x == 2);
check(s.y == 3);
check(s.inner.z == 4);
}
{
}
{
auto i = 42;
auto p = &i;
auto pp = &p;
auto d = PtrPtr { pp };
**d.pp = 14;
check(d.pp != nullptr);
check(i == 14);
}
{
auto p = PtrPtr {};
check(p.pp == nullptr);
}
}
float sum(Point p) {
return p.x + p.y;
}
void setZero(Point *p) {
gx::deref(p).x = 0;
gx::deref(p).y = 0;
}
void testMethod() {
auto p = Point { 2, 3 };
check(sum(p) == 5);
auto ptr = &p;
check(sum(gx::deref(ptr)) == 5);
setZero(&(p));
check(p.x == 0);
check(p.y == 0);
}
template<typename T>
T add(T a, T b) {
return a + b;
}
template<typename T>
void incrHolder(Holder<T> *h) {
gx::deref(h).Item += 1;
}
template<typename T>
T get(Holder<T> h) {
return h.Item;
}
template<typename T>
void set(Holder<T> *h, T Item) {
gx::deref(h).Item = Item;
}
void testGenerics() {
{
check(add<int>(1, 2) == 3);
check(add<float>(1.2f, 2.0f) == 3.2f);
check(add<float>(1.2f, 2.0f) == 3.2f);
}
{
auto i = Holder<int> { 42 };
check(i.Item == 42);
incrHolder<int>(&i);
check(i.Item == 43);
auto f = Holder<float> { 42 };
check(f.Item == 42);
check(add<float>(f.Item, 20) == 62);
incrHolder<float>(&f);
check(f.Item == 43);
auto p = Holder<Point> { Point { 1, 2 } };
check(p.Item.x == 1);
check(p.Item.y == 2);
setZero(&(p.Item));
check(p.Item.x == 0);
check(p.Item.y == 0);
set(&(p), Point { 3, 2 });
check(p.Item.x == 3);
check(p.Item.y == 2);
check(get(p).x == 3);
check(get(p).y == 2);
}
}
void iterateOneToTen(auto &&f) {
for (auto i = 1; i <= 10; (i)++) {
f(i);
}
}
void testLambdas() {
{
auto val = 42;
check(val == 42);
auto foo = [&](int newVal) {
val = newVal;
};
foo(14);
check(val == 14);
auto val2 = [&]() {
return val;
}();
check(val2 == val);
}
{
auto sum = 0;
iterateOneToTen([&](int i) {
sum += i;
});
check(sum == 55);
}
}
void setSecondElementToThree(gx::Array<int, 4> *arr) {
gx::deref(arr)[1] = 3;
}
void testArrays() {
{
auto arr = gx::Array<int, 4> { 1, 2, 3, 4 };
check(arr[2] == 3);
auto sum = 0;
for (auto i = 0; i < gx::len(arr); (i)++) {
sum += arr[i];
}
check(sum == 10);
check(arr[1] == 2);
setSecondElementToThree(&arr);
check(arr[1] == 3);
}
{
auto stuff = gx::Array<int, 3> { 1, 2, 3 };
check(gx::len(stuff) == 3);
auto sum = 0;
for (auto i = -1; auto &elem : stuff) {
++i;
check(i + 1 == elem);
sum += elem;
}
check(sum == 6);
}
{
auto arr = gx::Array<gx::Array<int, 2>, 2> { gx::Array<int, 2> { 1, 2 }, gx::Array<int, 2> { 3, 4 } };
check(gx::len(arr) == 2);
check(arr[0][0] == 1);
check(arr[0][1] == 2);
check(arr[1][0] == 3);
check(arr[1][1] == 4);
}
{
auto h = HasArray {};
check(gx::len(h.arr) == 4);
check(h.arr[0] == 0);
check(h.arr[1] == 0);
check(h.arr[2] == 0);
check(h.arr[3] == 0);
}
{
auto h = HasArray { gx::Array<int, 4> { 1, 2, 3, 4 } };
check(gx::len(h.arr) == 4);
check(h.arr[2] == 3);
}
}
void appendFortyTwo(gx::Slice<int> *s) {
*s = gx::append(*s, 42);
}
void testSlices() {
{
auto s = gx::Slice<int> {};
check(gx::len(s) == 0);
s = gx::append(s, 1);
s = gx::append(s, 2);
check(gx::len(s) == 2);
check(s[0] == 1);
check(s[1] == 2);
appendFortyTwo(&s);
check(gx::len(s) == 3);
check(s[2] == 42);
}
{
auto s = gx::Slice<gx::Slice<int>> { gx::Slice<int> { 1 }, gx::Slice<int> {}, gx::Slice<int> { 3, 4 } };
check(gx::len(s) == 3);
check(gx::len(s[0]) == 1);
check(s[0][0] == 1);
check(gx::len(s[1]) == 0);
check(gx::len(s[2]) == 2);
check(s[2][0] == 3);
check(s[2][1] == 4);
}
{
auto stuff = gx::Slice<int> { 1, 2 };
stuff = gx::append(stuff, 3);
check(gx::len(stuff) == 3);
{
auto sum = 0;
for (auto i = -1; auto &elem : stuff) {
++i;
check(i + 1 == elem);
sum += elem;
}
check(sum == 6);
}
{
auto sum = 0;
for (auto i = -1; auto &_ [[maybe_unused]] : stuff) {
++i;
sum += i;
}
check(sum == 3);
}
{
auto sum = 0;
for (auto &elem : stuff) {
sum += elem;
}
check(sum == 6);
}
{
auto count = 0;
for (auto &_ [[maybe_unused]] : stuff) {
count += 1;
}
check(count == 3);
}
{
stuff = gx::Slice<int> {};
auto count = 0;
for (auto &_ [[maybe_unused]] : stuff) {
count += 1;
}
check(count == 0);
}
}
}
template<typename T>
int len(Seq<T> *s) {
return gx::len(*s);
}
template<typename T>
void add(Seq<T> *s, T val) {
*s = gx::append(*s, val);
}
template<typename T, typename PT>
void incrSeq(Seq<T> *s) {
for (auto i = -1; auto &_ [[maybe_unused]] : *s) {
++i;
incr(PT(&(*s)[i]));
}
}
void incr(SingleIncr *s) {
gx::deref(s).val += 1;
}
void incr(DoubleIncr *s) {
gx::deref(s).val += 2;
}
void testSeqs() {
{
auto s = Seq<int> {};
check(len(&(s)) == 0);
add(&(s), 1);
add(&(s), 2);
check(len(&(s)) == 2);
check(s[0] == 1);
check(s[1] == 2);
}
{
auto s = Seq<int> { 1, 2, 3 };
check(len(&(s)) == 3);
auto sum = 0;
for (auto i = -1; auto &elem : s) {
++i;
check(i + 1 == elem);
sum += elem;
}
check(sum == 6);
}
{
auto s = Seq<Point> { Point { 1, 2 }, Point { 3, 4 } };
check(len(&(s)) == 2);
check(s[0].x == 1);
check(s[0].y == 2);
check(s[1].x == 3);
check(s[1].y == 4);
add(&(s), Point { 5, 6 });
check(s[2].x == 5);
check(s[2].y == 6);
}
{
auto s = Seq<Point> { Point { .x = 1, .y = 2 }, Point { .x = 3, .y = 4 } };
check(len(&(s)) == 2);
}
{
auto s = Seq<Seq<int>> { Seq<int> { 1 }, Seq<int> {}, Seq<int> { 3, 4 } };
check(len(&(s)) == 3);
check(gx::len(s[0]) == 1);
check(s[0][0] == 1);
check(len(&(s[1])) == 0);
check(len(&(s[2])) == 2);
check(s[2][0] == 3);
check(s[2][1] == 4);
}
{
auto s = Seq<SingleIncr> { SingleIncr { 1 }, SingleIncr { 2 }, SingleIncr { 3 } };
incrSeq<SingleIncr, SingleIncr *>(&s);
check(s[0].val == 2);
check(s[1].val == 3);
check(s[2].val == 4);
}
{
auto s = Seq<DoubleIncr> { DoubleIncr { 1 }, DoubleIncr { 2 }, DoubleIncr { 3 } };
incrSeq<DoubleIncr, DoubleIncr *>(&s);
check(s[0].val == 3);
check(s[1].val == 4);
check(s[2].val == 5);
}
}
void setGlobalXToFortyTwo() {
globalX = 42;
}
void checkGlobalXIsFortyTwo() {
check(globalX == 42);
}
int three() {
return 3;
}
bool isGlobalSliceEmpty() {
return gx::len(globalSlice) == 0;
}
int apply(int val, auto &&fn) {
return fn(val);
}
void testGlobalVariables() {
{
check(globalX == 23);
check(globalY == 20);
check(globalZ == 14);
setGlobalXToFortyTwo();
checkGlobalXIsFortyTwo();
check(initialGlobalX == 23);
}
{
check(isGlobalSliceEmpty());
globalSlice = gx::append(globalSlice, 1);
globalSlice = gx::append(globalSlice, 2);
check(gx::len(globalSlice) == 2);
check(globalSlice[0] == 1);
check(globalSlice[1] == 2);
check(!isGlobalSliceEmpty());
}
{
check(globalApplied == 6);
}
}
void testImports() {
{
auto f = Foo {};
check(Val(&(f)) == 0);
}
{
auto f = NewFoo(42);
check(Val(&(f)) == 42);
}
{
auto b = Bar { .X = 2, .Y = 3 };
check(b.X == 2);
check(b.Y == 3);
}
}
void testExterns() {
{
check(rect::NUM_VERTICES == 4);
auto r = rect::Rect { .x = 100, .y = 100, .width = 20, .height = 30 };
check(r.x == 100);
check(r.y == 100);
check(r.width == 20);
check(r.height == 30);
check(rect::area(r) == 600);
check(rect::area(r) == 600);
}
{
check(person::Population == 0);
auto p = person::NewPerson(20, 100);
check(person::Population == 1);
check(person::GetAge(p) == 20);
check(person::GetHealth(p) == 100);
person::Grow(&(p));
check(person::GetAge(p) == 21);
check(p.cppValue == 42);
check(person::GetAgeAdder(&(p))(1) == 22);
}
}
void testConversions() {
{
auto f = float(2.2f);
auto i = int(f);
check(i == 2);
auto d = 2.2f;
check(f - float(d) == 0);
}
{
auto slice = gx::Slice<int> { 1, 2 };
auto seq = Seq<int>(slice);
add(&(seq), 3);
check(len(&(seq)) == 3);
check(seq[0] == 1);
check(seq[1] == 2);
check(seq[2] == 3);
}
}
void testMeta() {
auto n = Nums { 1, 2, 3, 4 };
check(sumFields(n) == 14);
}
void testDefaults() {
auto h = HasDefaults {};
check(h.foo == 42);
check(h.bar == 6.4f);
check(h.point.x == 1);
check(h.point.y == 2);
}
void testStrings() {
{
gx::String s0 = "";
check(gx::len(s0) == 0);
check(std::strcmp(s0, "") == 0);
gx::String s1 = "foo";
check(gx::len(s1) == 3);
check(s1[0] == 'f');
check(s1[1] == 'o');
check(s1[2] == 'o');
check(std::strcmp(s1, "foo") == 0);
gx::String s2 = "foo";
check(std::strcmp(s1, s2) == 0);
check(std::strcmp(s1, "nope") != 0);
check(std::strcmp(s1, "foo") == 0);
gx::String s3 = s2;
check(std::strcmp(s1, s3) == 0);
auto sum = 0;
for (auto i = -1; auto &c : s3) {
++i;
sum += i;
if (i == 0) {
check(c == 'f');
}
if (i == 1) {
check(c == 'o');
}
if (i == 2) {
check(c == 'o');
}
}
check(sum == 3);
}
{
auto h0 = HasString {};
check(gx::len(h0.s) == 0);
check(std::strcmp(h0.s, "") == 0);
auto h1 = HasString { "foo" };
check(gx::len(h1.s) == 3);
check(h1.s[0] == 'f');
check(h1.s[1] == 'o');
check(h1.s[2] == 'o');
check(std::strcmp(h1.s, "foo") == 0);
auto h2 = HasString { "foo" };
check(std::strcmp(h1.s, h2.s) == 0);
check(std::strcmp(h1.s, HasString { "nope" }.s) != 0);
check(std::strcmp(h1.s, HasString { "foo" }.s) == 0);
auto h3 = h2;
check(std::strcmp(h1.s, h3.s) == 0);
}
}
int main() {
testFib();
testUnary();
testVariables();
testIf();
testFor();
testPointer();
testStruct();
testMethod();
testGenerics();
testLambdas();
testArrays();
testSlices();
testSeqs();
testGlobalVariables();
testImports();
testExterns();
testConversions();
testMeta();
testDefaults();
testStrings();
}
void check(bool val) {
if (val) {
gx::println("ok");
} else {
gx::println("not ok");
}
}
int Val(Foo *f) {
return gx::deref(f).val;
}
Foo NewFoo(int val) {
return Foo { val };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment