Skip to content

Ensure valid type name for operators with multiple returns. #796

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

Merged
merged 6 commits into from
Dec 28, 2023
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
*.bin
*.exe
source/gen_version.bat
build*/
34 changes: 34 additions & 0 deletions regression-tests/pure2-return-tuple-operator.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

A : type = {
operator() : (this) -> (x: int, y: int) = {
x = 12;
y = 34;
return;
}
operator* : (this) -> (x: int, y: int) = {
x = 23;
y = 45;
return;
}
operator[] : (this, idx: int) -> (x: int, y: int) = {
x = 34 * (idx+1);
y = 56 * (idx+1);
return;
}
}


main : () = {

a : A = ();

t1 := a();
std::cout << t1.x << " , " << t1.y << "\n";

t2 := a*;
std::cout << t2.x << " , " << t2.y << "\n";

t3 := a[0];
std::cout << t3.x << " , " << t3.y << "\n";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
12 , 34
23 , 45
34 , 56
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
12 , 34
23 , 45
34 , 56
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
12 , 34
23 , 45
34 , 56
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
12 , 34
23 , 45
34 , 56
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pure2-return-tuple-operator.cpp
94 changes: 94 additions & 0 deletions regression-tests/test-results/pure2-return-tuple-operator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

#define CPP2_IMPORT_STD Yes

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


#include "cpp2util.h"

#line 1 "pure2-return-tuple-operator.cpp2"

#line 2 "pure2-return-tuple-operator.cpp2"
class A;


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

#line 1 "pure2-return-tuple-operator.cpp2"

#line 2 "pure2-return-tuple-operator.cpp2"
class A {
struct operator_call_ret { int x; int y; };


#line 3 "pure2-return-tuple-operator.cpp2"
public: [[nodiscard]] auto operator()() const& -> operator_call_ret;
struct operator_dereference_ret { int x; int y; };



#line 8 "pure2-return-tuple-operator.cpp2"
public: [[nodiscard]] auto operator*() const& -> operator_dereference_ret;
struct operator_subscript_ret { int x; int y; };



#line 13 "pure2-return-tuple-operator.cpp2"
public: [[nodiscard]] auto operator[](cpp2::in<int> idx) const& -> operator_subscript_ret;
public: A() = default;
public: A(A const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(A const&) -> void = delete;


#line 18 "pure2-return-tuple-operator.cpp2"
};

#line 21 "pure2-return-tuple-operator.cpp2"
auto main() -> int;

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

#line 1 "pure2-return-tuple-operator.cpp2"

#line 3 "pure2-return-tuple-operator.cpp2"
[[nodiscard]] auto A::operator()() const& -> operator_call_ret{
cpp2::deferred_init<int> x;
cpp2::deferred_init<int> y;
#line 4 "pure2-return-tuple-operator.cpp2"
x.construct(12);
y.construct(34);
return { std::move(x.value()), std::move(y.value()) };
}
[[nodiscard]] auto A::operator*() const& -> operator_dereference_ret{
cpp2::deferred_init<int> x;
cpp2::deferred_init<int> y;
#line 9 "pure2-return-tuple-operator.cpp2"
x.construct(23);
y.construct(45);
return { std::move(x.value()), std::move(y.value()) };
}
[[nodiscard]] auto A::operator[](cpp2::in<int> idx) const& -> operator_subscript_ret{
cpp2::deferred_init<int> x;
cpp2::deferred_init<int> y;
#line 14 "pure2-return-tuple-operator.cpp2"
x.construct(34 * (idx + 1));
y.construct(56 * (idx + 1));
return { std::move(x.value()), std::move(y.value()) };
}

#line 21 "pure2-return-tuple-operator.cpp2"
auto main() -> int{

A a {};

auto t1 {a()};
std::cout << t1.x << " , " << std::move(t1).y << "\n";

auto t2 {*cpp2::assert_not_null(a)};
std::cout << t2.x << " , " << std::move(t2).y << "\n";

auto t3 {CPP2_ASSERT_IN_BOUNDS(std::move(a), 0)};
std::cout << t3.x << " , " << std::move(t3).y << "\n";

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pure2-return-tuple-operator.cpp2... ok (all Cpp2, passes safety checks)

55 changes: 35 additions & 20 deletions source/to_cpp1.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,32 @@ auto pad(int padding)
};
}

auto multi_return_type_name(declaration_node const& n)
-> std::string
{
// When generating a multi-return struct, also enable multi-return
// from a (), [], or * operator. We can expand this in the future,
// but with care because most operators should 'do as the ints do'
// (e.g., it doesn't seem sensible for == to return multiple values)
constexpr std::pair<std::string_view, std::string_view> canonized_names[] = {
{ "operator()", "operator_call" },
{ "operator[]", "operator_subscript" },
{ "operator*", "operator_dereference" }
};

assert (n.is_function() && n.name());
auto ret = n.name()->to_string();
for (auto [op, canon] : canonized_names) {
if (ret == op) {
ret = canon;
break;
}
}
ret += "_ret";

return ret;
}


//-----------------------------------------------------------------------
//
Expand Down Expand Up @@ -1119,7 +1145,6 @@ class cppfront
bool in_definite_init = false;
bool in_parameter_list = false;

std::string function_return_name;
struct function_return {
parameter_declaration_list_node* param_list;
passing_style pass;
Expand Down Expand Up @@ -4613,7 +4638,6 @@ class cppfront
//
auto emit(
function_type_node const& n,
token const* ident,
bool is_main = false,
bool is_ctor_or_dtor = false,
std::string suffix1 = {},
Expand Down Expand Up @@ -4742,13 +4766,8 @@ class cppfront
// Otherwise, handle multiple/named returns
else {
printer.print_cpp2( " -> ", n.position() );
function_return_name = {};
printer.emit_to_string(&function_return_name);
assert(ident);
printer.print_cpp2( *ident, ident->position() );
printer.print_cpp2( "_ret", ident->position() );
printer.emit_to_string();
printer.print_cpp2( function_return_name, ident->position() );
assert (n.my_decl);
printer.print_cpp2( multi_return_type_name(*n.my_decl), n.position());
}
}

Expand Down Expand Up @@ -5245,7 +5264,7 @@ class cppfront
printer.print_cpp2( prefix, n.position() );
printer.print_cpp2( type_qualification_if_any_for(n), n.position() );
printer.print_cpp2( print_to_string( *n.parent_declaration->name() ), n.position() );
emit( *func, n.name(), false, true );
emit( *func, false, true );
}
// For an assignment operator, similar to emitting an ordinary function
else
Expand All @@ -5254,7 +5273,7 @@ class cppfront
current_functions.back().epilog.push_back( "return *this;");
printer.print_cpp2( prefix, n.position() );
printer.print_cpp2( "auto " + type_qualification_if_any_for(n) + print_to_string( *n.name() ), n.position());
emit( *func, n.name() );
emit( *func );
}
}

Expand Down Expand Up @@ -5601,11 +5620,7 @@ class cppfront
// Else just emit it as an ordinary struct
else
{
printer.print_extra(
"\nstruct "
+ n.name()->to_string()
+ "_ret "
);
printer.print_extra( "\nstruct " + multi_return_type_name(n) + " ");
emit(*r, true);
}
printer.print_extra( "\n" );
Expand Down Expand Up @@ -6012,9 +6027,9 @@ class cppfront
// so print the provided intro instead, which will be a Cpp1 lambda-introducer
if (capture_intro != "")
{
assert (!n.identifier);
assert (!n.identifier && !is_main);
printer.print_cpp2(capture_intro, n.position());
emit( *func, nullptr, is_main);
emit( *func );
}

// Else start introducing a normal function
Expand Down Expand Up @@ -6259,7 +6274,7 @@ class cppfront
+ "~" + print_to_string(*n.parent_declaration->name()),
n.position()
);
emit( *func, n.name(), false, true);
emit( *func, false, true);
printer.print_cpp2( suffix2, n.position() );
}

Expand All @@ -6281,7 +6296,7 @@ class cppfront
}

emit( *n.name() );
emit( *func, n.name(), is_main, false, suffix1, generating_postfix_inc_dec_from != nullptr );
emit( *func, is_main, false, suffix1, generating_postfix_inc_dec_from != nullptr );
printer.print_cpp2( suffix2, n.position() );

// If this is ++ or --, also generate a Cpp1 postfix version of the operator
Expand Down