-
Notifications
You must be signed in to change notification settings - Fork 260
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add order-independent type definitions
Add order-independent type definitions, including order-independent dependencies between type definitions - see new test case code, pasted below in this commit message for convenience Note: This looks in pretty good shape, but it's a significant restructuring in the way the code is lowered to Cpp1, so there will probably be some corner cases to tweak in follow-on commits There are now three (not two) Cpp1 lowering passes: 1. type forward declarations (new) 2. type definitions (new) and function forward declarations (existing) 3. function definitions, including type-scope/member function out-of-line definitions (new) and non-type-scope functions (existing) When compiling `.h2` files, phases 1 and 2 go into the generated `.h` and phase 3 goes into the generated `.hpp` Comments written in Cpp2 all go on an entity's definition, because there are no forward declarations. So when lowering to Cpp1, comments are now split into two groups to put them where a reader of the Cpp1 code would naturally expect to see them: - comments not within function bodies are emitted in phase 2, where they belong on the types and function declarations (new) - comments within function bodies are emitted in phase 3, likewise where they belong Also: - Added support for `out` parameters on constructors. For example, this is useful when safely creating pointer cycles among types that refer to each other, respecting Cpp2's guaranteed program-meaningful initialization safety rules (demonstrated in the test case in this commit, pasted below) - Added support for `_` as the name of an anonymous object. This supports uses of RAII guards such as `_ := std::lock_guard(my_mutex);` and `_ := finally( :()= print("done"); ); );` - see example in test case below - Removed unused `offset` variable, closes #309 ### Regression test to demonstrate code that now works... convenience copy of `regression-tests\pure2-types-order-independence-and-nesting.cpp2` ``` N: namespace = { // A type X, that uses Y (defined later) // X: type = { py: *Y; // Note: A constructor with an 'out' parameter operator=: (out this, out y: Y) = { // === The following comments will stay close to, but not exactly at, // the corresponding lines that get moved to the Cpp1 mem-init-list // At this point, 'this' is now in scope and can safely be used. // The guaranteed initialization rules ensure we cannot use an // unconstructed object, and if a constructor that has begun chooses to // hand out 'this&' (as in the next line below) then it is explicitly // aware it's doing so - this constructor knows that if y's constructor // uses the pointer it will see 'this' object's state as of this line // 'out' parameters are constructed first y = this&; // ok, construct 'y' to refer to 'this' // at this point, 'y' is now initialized and can safely be used // then members are constructed next py = y&; // ok, set 'this' to refer to 'y' // === from here onward, the comments stick with their code // then do anything else the constructor wants to do std::cout << "made a safely initialized cycle\n"; } // X::exx member function description here exx: (this, count: int) = { // Exercise '_' anonymous objects too while we're at it _ := cpp2::finally( :()= std::cout << "leaving call to 'why((count)$)'\n"; ); if count < 5 { py*.why( count+1 ); // use Y object from X } } } // Another type Y, that uses X // Y: type = { px: *X; operator=: (out this, x: *X) = px = x; why: (this, count: int) = px*.exx( count+1 ); // use X object from Y } M: namespace = { // Testing nested templated types A: <T, U> type = { B: <I: int> type = { f: <V, J: int, W> (w: W) = std::cout << "hallo (w)$\n"; } } } } // Mainline - gratuitous comment just to check that this comment // stays on the function declaration when lowering main: () = { y: N::Y; // declare an uninitialized Y object x: N::X = (out y); // construct y and x, and point them at each other // now have the two objects call each other back and forth a few times x.exx(1); // and test a nested template out-of-line definition N::M::A<int, int>::B<42>::f<int, 43>("welt"); } ```
- Loading branch information
Showing
83 changed files
with
2,057 additions
and
859 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
regression-tests/pure2-types-order-independence-and-nesting.cpp2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
|
||
N: namespace = { | ||
|
||
// A type X, that uses Y (defined later) | ||
// | ||
X: type = { | ||
py: *Y; | ||
|
||
// Note: A constructor with an 'out' parameter | ||
operator=: (out this, out y: Y) = { | ||
// === The following comments will stay close to, but not exactly at, | ||
// the corresponding lines that get moved to the Cpp1 mem-init-list | ||
|
||
// At this point, 'this' is now in scope and can safely be used. | ||
// The guaranteed initialization rules ensure we cannot use an | ||
// unconstructed object, and if a constructor that has begun chooses to | ||
// hand out 'this&' (as in the next line below) then it is explicitly | ||
// aware it's doing so - this constructor knows that if y's constructor | ||
// uses the pointer it will see 'this' object's state as of this line | ||
|
||
// 'out' parameters are constructed first | ||
y = this&; // ok, construct 'y' to refer to 'this' | ||
// at this point, 'y' is now initialized and can safely be used | ||
|
||
// then members are constructed next | ||
py = y&; // ok, set 'this' to refer to 'y' | ||
|
||
// === from here onward, the comments stick with their code | ||
|
||
// then do anything else the constructor wants to do | ||
std::cout << "made a safely initialized cycle\n"; | ||
} | ||
|
||
// X::exx member function description here | ||
exx: (this, count: int) = { | ||
// Exercise '_' anonymous objects too while we're at it | ||
_ := cpp2::finally( :()= std::cout << "leaving call to 'why((count)$)'\n"; ); | ||
if count < 5 { | ||
py*.why( count+1 ); // use Y object from X | ||
} | ||
} | ||
} | ||
|
||
// Another type Y, that uses X | ||
// | ||
Y: type = { | ||
px: *X; | ||
|
||
operator=: (out this, x: *X) = px = x; | ||
|
||
why: (this, count: int) = | ||
px*.exx( count+1 ); // use X object from Y | ||
} | ||
|
||
M: namespace = { | ||
|
||
// Testing nested templated types | ||
A: <T, U> type = { | ||
B: <I: int> type = { | ||
f: <V, J: int, W> (w: W) = std::cout << "hallo (w)$\n"; | ||
} | ||
} | ||
|
||
} | ||
|
||
} | ||
|
||
// Mainline - gratuitous comment just to check that this comment | ||
// stays on the function declaration when lowering | ||
main: () = | ||
{ | ||
y: N::Y; // declare an uninitialized Y object | ||
x: N::X = (out y); // construct y and x, and point them at each other | ||
|
||
// now have the two objects call each other back and forth a few times | ||
x.exx(1); | ||
|
||
// and test a nested template out-of-line definition | ||
N::M::A<int, int>::B<42>::f<int, 43>("welt"); | ||
} |
80 changes: 40 additions & 40 deletions
80
regression-tests/test-results/clang-12/mixed-float-literals.cpp.output
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
...sion-tests/test-results/clang-12/pure2-types-order-independence-and-nesting.cpp.execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
made a safely initialized cycle | ||
leaving call to 'why(5)' | ||
leaving call to 'why(3)' | ||
leaving call to 'why(1)' | ||
hallo welt |
Empty file.
5 changes: 5 additions & 0 deletions
5
...ession-tests/test-results/gcc-10/pure2-types-order-independence-and-nesting.cpp.execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
made a safely initialized cycle | ||
leaving call to 'why(5)' | ||
leaving call to 'why(3)' | ||
leaving call to 'why(1)' | ||
hallo welt |
Empty file.
14 changes: 10 additions & 4 deletions
14
regression-tests/test-results/mixed-as-for-variant-20-types.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.