#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <format>
#include <iostream>
#include <js.h>
#include <stdlib.h>
#include <string>
#include <utility>

class bit {
  private:
    static constexpr bit nor(const bit& a, const bit& b);

  public:
    bit() = default;
    bit(bool n) : n(n), composition(n ? "1" : "0") {
    }
    bit(bool n, std::string_view composition) : n(n), composition(composition) {
    }
    bit(const bit& other) : bit(other.n, other.composition) {
    }

    constexpr bit operator!() const {
        const bit& a = *this;
        return nor(a, a);
    }

    constexpr bit operator|(const bit& b) const {
        const bit& a = *this;
        return !nor(a, b);
    }

    constexpr bit operator&(const bit& b) const {
        const bit& a = *this;
        return nor(!a, !b);
    }

    constexpr bit operator^(const bit& b) const {
        const bit& a = *this;

        return (!a & b) | (a & !b);
    }

    constexpr std::pair<bit, bit> operator+(const bit& b) const {
        const bit& a = *this;

        return {
            a ^ b,
            a & b,
        };
    }

    operator bool() const {
        return n;
    }

    friend std::ostream& operator<<(std::ostream& stream, const bit& val) {
        return stream << val.composition;
    }

    friend std::istream& operator>>(std::istream& stream, bit& val) {
        return stream >> val.n;
    }

  private:
    bool n = 0;
    std::string composition = "";
};

constexpr bit bit::nor(const bit& a, const bit& b) {
    bit result{
        !(a.n || b.n),
        "(" + a.composition + " NOR " + b.composition + ")",
    };

    return result;
}

JS_EXPORT uint64_t awoo() {
    bit a{1, "a"};
    bit b{1, "b"};

    auto [sum, carry] = a + b;

    std::cout << "sum = " << sum << "\ncarry = " << carry << std::endl;

    return sum;
}

JS_EXPORT void play() {
    auto awoo = std::format("{2} {1}{0}!\n", 23, "C++", "Hello");
    std::puts(awoo.c_str());
}

int main() {
    awoo();
    play();
}
