Skip to content

Implement Type is Type #782

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

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/cpp2util.h
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,15 @@ inline auto to_string(auto&& value, std::string_view) -> std::string
// TODO: Does this really warrant a new synonym? Perhaps "is void" is enough
using empty = void;

// Type is Type
//

template <typename X, typename C>
auto is() -> std::false_type { return {}; }

template <typename X, typename C>
requires std::same_as<X, C> || std::derived_from<X,C>

This comment was marked as resolved.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I was wrong.
std::same_as can be true for non-class types,
whereas std::derived_from can only be true for classes.

auto is() -> std::true_type { return {}; }

// Templates
//
Expand Down
10 changes: 5 additions & 5 deletions regression-tests/mixed-inspect-templates.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ fun: (v : _) -> std::string = {
}

fun2: (v : _) -> std::string = {
if v is std::vector { return "std::vector"; }
if v is std::array { return "std::array"; }
if v is std::variant { return "std::variant"; }
if v is my_type { return "my_type"; }
if (v) is std::vector { return "std::vector"; }
if (v) is std::array { return "std::array"; }
if (v) is std::variant { return "std::variant"; }
if (v) is my_type { return "my_type"; }
return "unknown";
}

Expand All @@ -38,4 +38,4 @@ main: () -> int = {
std::cout << "inspected arr : (fun2(arr))$" << std::endl;
std::cout << "inspected var : (fun2(var))$" << std::endl;
std::cout << "inspected myt : (fun2(myt))$" << std::endl;
}
}
6 changes: 3 additions & 3 deletions regression-tests/mixed-inspect-values-2.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ main: () -> int = {
is _ = "i is out of our interest";
} << std::endl;

if i is (less_than(20)) {
if (i) is (less_than(20)) {
std::cout << "less than 20" << std::endl;
}

if i is (in(10,30)) {
if (i) is (in(10,30)) {
std::cout << "i is between 10 and 30" << std::endl;
}

Expand All @@ -39,7 +39,7 @@ main: () -> int = {
std::cout << "v is empty" << std::endl;
}

if v is (empty) {
if (v) is (empty) {
std::cout << "v is empty" << std::endl;
}
}
12 changes: 6 additions & 6 deletions regression-tests/pure2-enum.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ main: () = {
else if skat_game::hearts == x { // ok, in either order
std::cout << "hearts";
}
else if x is (skat_game::spades) { // ok, using is
else if (x) is (skat_game::spades) { // ok, using is
std::cout << "spades";
}
else if skat_game::clubs is (x) { // ok, using is
else if (skat_game::clubs) is (x) { // ok, using is
std::cout << "clubs";
}
else {
Expand Down Expand Up @@ -95,8 +95,8 @@ main: () = {
std::cout << "f. get_raw_value() is (f. get_raw_value())$\n";
std::cout << "f2.get_raw_value() is (f2.get_raw_value())$\n";

std::cout << "f is (f2) is (f is (f2))$\n";
std::cout << "f2 is (f ) is (f2 is (f ))$\n\n";
std::cout << "(f ) is (f2) is ((f ) is (f2))$\n";
std::cout << "(f2) is (f ) is ((f2) is (f ))$\n\n";

f.clear( f2 );
f.set( file_attributes::current | f2 );
Expand All @@ -108,8 +108,8 @@ main: () = {
std::cout << "f. get_raw_value() is (f. get_raw_value())$\n";
std::cout << "f2.get_raw_value() is (f2.get_raw_value())$\n";
std::cout << "f == f2 is (f == f2 )$\n";
std::cout << "f is (f2) is (f is (f2))$\n";
std::cout << "f2 is (f ) is (f2 is (f ))$\n";
std::cout << "(f ) is (f2) is ((f ) is (f2))$\n";
std::cout << "(f2) is (f ) is ((f2) is (f ))$\n";
std::cout << "(f & f2) == f2 is ((f & f2) == f2)$\n";

std::cout << "inspecting f: " << inspect f -> std::string {
Expand Down
4 changes: 2 additions & 2 deletions regression-tests/pure2-more-wildcards.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ main: () -> int
p: * _ = x&;
q: * const _ = p&;

if x is (less_than(20)) {
if (x) is (less_than(20)) {
std::cout << "yes, less\n";
}

if x is _ {
if (x) is _ {
std::cout << "yes, always\n";
}
}
18 changes: 18 additions & 0 deletions regression-tests/pure2-type-is-type.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
main: () =
{
T: type == int;
b := *T is *int;
[[assert: b]]

b = bool is T;
[[assert: !b]]

b = T is long;
[[assert: !b]]

b = std::runtime_error is std::exception;
[[assert: b]]

b = std::exception is std::runtime_error;
[[assert: !b]]
}
2 changes: 1 addition & 1 deletion regression-tests/pure2-type-safety-1.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ main: () -> int =

test_generic: ( x, msg ) = {
msgx: std::string = msg;
print( msgx + " is int? ", x is int );
print( msgx + " is int? ", (x) is int );
}

print: ( msg: std::string, b: bool ) = {
Expand Down
8 changes: 4 additions & 4 deletions regression-tests/test-results/mixed-inspect-templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ struct my_type {};
}

[[nodiscard]] auto fun2(auto const& v) -> std::string{
if (cpp2::is<std::vector>(v)) {return "std::vector"; }
if (cpp2::is<std::array>(v)) {return "std::array"; }
if (cpp2::is<std::variant>(v)) {return "std::variant"; }
if (cpp2::is<my_type>(v)) {return "my_type"; }
if (cpp2::is<std::vector>((v))) {return "std::vector"; }
if (cpp2::is<std::array>((v))) {return "std::array"; }
if (cpp2::is<std::variant>((v))) {return "std::variant"; }
if (cpp2::is<my_type>((v))) {return "my_type"; }
return "unknown";
}

Expand Down
6 changes: 3 additions & 3 deletions regression-tests/test-results/mixed-inspect-values-2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ constexpr auto empty = [](auto&& x){
else return "i is out of our interest"; }
() << std::endl;

if (cpp2::is(i, (less_than(20)))) {
if (cpp2::is((i), (less_than(20)))) {
std::cout << "less than 20" << std::endl;
}

if (cpp2::is(std::move(i), (in(10, 30)))) {
if (cpp2::is((std::move(i)), (in(10, 30)))) {
std::cout << "i is between 10 and 30" << std::endl;
}

Expand All @@ -58,7 +58,7 @@ constexpr auto empty = [](auto&& x){
std::cout << "v is empty" << std::endl;
}

if (cpp2::is(std::move(v), (empty))) {
if (cpp2::is((std::move(v)), (empty))) {
std::cout << "v is empty" << std::endl;
}
}
Expand Down
12 changes: 6 additions & 6 deletions regression-tests/test-results/pure2-enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,10 @@ auto main() -> int{
else {if (skat_game::hearts == x) { // ok, in either order
std::cout << "hearts";
}
else {if (cpp2::is(x, (skat_game::spades))) {// ok, using is
else {if (cpp2::is((x), (skat_game::spades))) {// ok, using is
std::cout << "spades";
}
else {if (cpp2::is(skat_game::clubs, (x))) {// ok, using is
else {if (cpp2::is((skat_game::clubs), (x))) {// ok, using is
std::cout << "clubs";
}
else {
Expand Down Expand Up @@ -300,8 +300,8 @@ auto main() -> int{
std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f)) + "\n";
std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f2)) + "\n";

std::cout << "f is (f2) is " + cpp2::to_string(cpp2::is(f, (f2))) + "\n";
std::cout << "f2 is (f ) is " + cpp2::to_string(cpp2::is(f2, (f))) + "\n\n";
std::cout << "(f ) is (f2) is " + cpp2::to_string(cpp2::is((f), (f2))) + "\n";
std::cout << "(f2) is (f ) is " + cpp2::to_string(cpp2::is((f2), (f))) + "\n\n";

CPP2_UFCS(clear, f, f2);
CPP2_UFCS(set, f, file_attributes::current | f2);
Expand All @@ -313,8 +313,8 @@ auto main() -> int{
std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f)) + "\n";
std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f2)) + "\n";
std::cout << "f == f2 is " + cpp2::to_string(f == f2 ) + "\n";
std::cout << "f is (f2) is " + cpp2::to_string(cpp2::is(f, (f2))) + "\n";
std::cout << "f2 is (f ) is " + cpp2::to_string(cpp2::is(f2, (f))) + "\n";
std::cout << "(f ) is (f2) is " + cpp2::to_string(cpp2::is((f), (f2))) + "\n";
std::cout << "(f2) is (f ) is " + cpp2::to_string(cpp2::is((f2), (f))) + "\n";
std::cout << "(f & f2) == f2 is " + cpp2::to_string((f & f2) == f2) + "\n";

std::cout << "inspecting f: " << [&] () -> std::string { auto&& _expr = std::move(f);
Expand Down
2 changes: 1 addition & 1 deletion regression-tests/test-results/pure2-more-wildcards.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
auto* p {&x};
auto const* q {&p};

if (cpp2::is(x, (less_than(20)))) {
if (cpp2::is((x), (less_than(20)))) {
std::cout << "yes, less\n";
}

Expand Down
36 changes: 36 additions & 0 deletions regression-tests/test-results/pure2-type-is-type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

#define CPP2_IMPORT_STD Yes

//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"



//=== Cpp2 type definitions and function declarations ===========================

auto main() -> int;


//=== Cpp2 function definitions =================================================

auto main() -> int
{
using T = int;
auto b {bool(cpp2::is<T*, int*>())};
cpp2::Default.expects(b, "");

b = bool(cpp2::is<bool, T>());
cpp2::Default.expects(!(b), "");

b = bool(cpp2::is<T, long>());
cpp2::Default.expects(!(b), "");

b = bool(cpp2::is<std::runtime_error, std::exception>());
cpp2::Default.expects(b, "");

b = bool(cpp2::is<std::exception, std::runtime_error>());
cpp2::Default.expects(!(std::move(b)), "");
}

2 changes: 1 addition & 1 deletion regression-tests/test-results/pure2-type-safety-1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ auto print(cpp2::in<std::string> msg, cpp2::in<bool> b) -> void;

auto test_generic(auto const& x, auto const& msg) -> void{
std::string msgx {msg};
print(std::move(msgx) + " is int? ", cpp2::is<int>(x));
print(std::move(msgx) + " is int? ", cpp2::is<int>((x)));
}

auto print(cpp2::in<std::string> msg, cpp2::in<bool> b) -> void{
Expand Down
23 changes: 18 additions & 5 deletions source/cppfront.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3195,12 +3195,25 @@ class cppfront
auto wildcard_found = false;
bool as_on_literal = false;

assert(
n.expr
&& n.expr->get_postfix_expression_node()
&& n.expr->get_postfix_expression_node()->expr
);
if (n.type) {
assert(
n.ops.size() == 1
&& *n.ops[0].op == "is"
&& n.ops[0].type
);
printer.print_cpp2("bool(cpp2::is<", n.position());
emit(*n.type);
printer.print_cpp2(", ", n.position());
emit(*n.ops[0].type);
printer.print_cpp2(">())", n.position());
return;
}
else if (n.expr)
{
assert(
n.expr->get_postfix_expression_node()
&& n.expr->get_postfix_expression_node()->expr
);
auto& p = n.expr->get_postfix_expression_node()->expr;
if (auto t = p->get_token();
t
Expand Down
Loading