forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 2
Format Cpp2
Johel Ernesto Guerrero Peña edited this page Oct 9, 2024
·
13 revisions
See https://clang.llvm.org/get_started.html.
git clone --depth 1 --branch format-cpp2 https://github.com/JohelEGP/llvm-project.git
cmake \
-B format-cpp2 \
-S llvm-project/llvm \
-G Ninja \
-D CMAKE_BUILD_TYPE=Debug \
-D CMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-D LLVM_BUILD_TOOLS=OFF \
-D LLVM_ENABLE_DIA_SDK=OFF \
-D LLVM_ENABLE_IDE=ON \
-D LLVM_ENABLE_LIBPFM=OFF \
-D LLVM_ENABLE_PIC=OFF \
-D LLVM_ENABLE_PROJECTS="clang" \
-D LLVM_ENABLE_RUNTIMES="" \
-D LLVM_INCLUDE_BENCHMARKS=OFF \
-D LLVM_INCLUDE_EXAMPLES=OFF \
-D LLVM_INCLUDE_TESTS=OFF \
-D LLVM_PARALLEL_COMPILE_JOBS=4 \
-D LLVM_PARALLEL_LINK_JOBS=4 \
-D LLVM_TARGETS_TO_BUILD=X86 \
-D LLVM_VERSION_SUFFIX=""
cmake --build format-cpp2 --target clang-format -j4
Just use Clang Format normally. There's no opt-in.
- Add a GitHub Action to build and upload a portable
clang-format
binary. - Test CMake target
FormatTests
. - Add tests for Cpp2 to CMake target
FormatTests
. - Post the branch to https://reviews.llvm.org/.
- Review all the style options for Cpp2.
- Handle parsing failure more gracefully.
Here's my formatted Cpp2 test file and .clang-format
configuration.
Be warned, my configuration is themed around stuffing a lot into a single line.
Configuration
AccessModifierOffset: -2
AlignAfterOpenBracket: AlwaysBreak
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: true
PadOperators: false
AlignConsecutiveBitFields: Consecutive
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: None
AlignConsecutiveShortCaseStatements:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignCaseColons: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowBreakBeforeNoexceptSpecifier: Always
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortCompoundRequirementOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakBeforeMultilineStrings: false
BinPackArguments: true
BinPackParameters: BinPack
BitFieldColonSpacing: Both
BreakAdjacentStringLiterals: true
BreakAfterAttributes: Never
BreakAfterReturnType: Automatic
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeConceptDeclarations: Allowed
BreakBeforeTernaryOperators: true
BreakBinaryOperations: RespectPrecedence
BreakConstructorInitializers: BeforeColon
BreakFunctionDefinitionParameters: false
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
BreakTemplateDeclarations: No
ColumnLimit: 120
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: Always
FixNamespaceComments: true
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '<(experimental/)?[a-z_]+>' # C++ standard library
Priority: 1
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentPPDirectives: AfterHash
IndentRequiresClause: true
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: true
IntegerLiteralSeparator:
Binary: 0
Decimal: 0
Hex: 0
KeepEmptyLines:
AtEndOfFile: false
AtStartOfBlock: false
AtStartOfFile: false
LambdaBodyIndentation: Signature
Language: Cpp
LineEnding: LF
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
PackConstructorInitializers: NextLine
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Custom
QualifierOrder: ["static", "friend", "inline", "constexpr", "const", "volatile", "type"]
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RequiresClausePosition: SingleLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 0
SkipMacroDefinitionBody: false
SortIncludes: CaseInsensitive
SortUsingDeclarations: LexicographicNumeric
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: true
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
SpacesInParens: Never
SpacesInSquareBrackets: false
Standard: Latest
StatementMacros: ["BOOST_GEOMETRY_REGISTER_POINT_2D"]
TabWidth: 2
TypeNames: []
UseCRLF: false
UseTab: Never
Formatted Cpp2 test file
// Clang Format (and some highlighting) test cases.
// Cpp1 and Cpp2 next to each other
// to show degree of consistent formatting.
int x = 0;
const int x = 0;
const int* x = 0;
int* const x = 0;
const int* const x = 0;
x: i32 = 0;
x: const i32 = 0;
x: * const i32 = 0;
x: const * i32 = 0;
x: const * const i32 = 0;
auto x = 0;
auto* x = 0;
const auto x = 0;
const auto* x = 0;
x: _ = 0;
x := 0;
x: * _ = 0;
x: * = 0;
x: const _ = 0;
x: const = 0;
x: * const _ = 0;
x: * const = 0;
auto x = "a"
"b";
auto x = u8R"(a)"
u8R"(b)";
x := "a"
"b";
x := u8R"(a)"
u8R"(b)";
void f() { }
f: () = { }
void f() { int x = 0; }
f: () = { x: i32 = 0; }
int f() { return 0; }
f: () -> i32 = { return 0; }
f: () -> i32 = 0;
auto f(const auto& x) { return x; }
f: (in x: _) -> _ = { return x; }
f: (in x: _, ) -> _ = { return x; }
f: (x) -> _ = x;
f: (x, ) -> _ = x;
f: (in_ref x) -> _ = x;
void f(const int) { }
void f(const int x) { }
f: (:i32) = { } // Pending [grammar][].
f: (x: i32) = { }
void f(int) { }
f: (copy: i32) = { } // Pending [grammar][].
void f(buffer& x) { }
f: (inout x: buffer) = { }
f: (out x: buffer) = { }
int&& f(int&&);
f: (move: i32) -> move i32; // Pending [grammar][].
auto&& f(uncvref_same<int>&& x) { return FWD(x); }
f: (forward x: i32) -> forward _ = forward x; // Pending [hsutter/cppfront#408][].
f: (forward x: i32) -> forward_ref _ = x;
void f(std::regular auto) { }
f: (copy _: _ is std::regular) = { }
void f() { std::regular auto x = 0; }
f: () = { x: _ is std::regular = 0; }
void f(int = 0) { }
f: (copy _: int = 0) = { }
void f() {
g();
g();
}
f: () = {
g();
g();
}
class t { };
class t final { };
t: type = { }
t: final type = { }
class t {
int x = 0;
};
t: type = {
x: i32 = 0;
}
class t : base {
t() : base{""} { }
};
t: type = {
this: base = "";
}
class t {
private:
void f() const { }
};
t: type = {
private f: (this) = { }
}
class t {
private:
void f() const { }
private:
void f() const { }
};
t: type = {
private f: (this) = { }
private f: (this) = { }
}
class t {
void f() const { g(); }
};
t: type = {
f: (this) = g();
f: (this) = { g(); }
}
class t {
static void f() {
g();
g();
}
};
t: type = {
f: () = {
g();
g();
}
}
class t {
[[nodiscard]] bool operator==(const t&) const = default;
};
t: type = {
operator==: (this, that) -> bool;
}
class t {
virtual ~t() { }
virtual void f() const = 0;
};
t: type = {
operator=: (virtual move this) = { }
f: (virtual this);
}
t: @interface type = {
f: (this);
}
class t {
int x = 0;
[[nodiscard]] int get() const { return x; }
void set(const int y) { x = y; }
};
t: type = {
x: i32 = 0;
get: (this) -> i32 = x;
set: (inout this, y: i32) = x = y;
}
namespace ns { }
ns: namespace = { }
namespace ns {
int x = 0;
} // namespace ns
ns: namespace = {
x: i32 = 0;
} // namespace ns
namespace ns {
int x = 0;
void f() { }
} // namespace ns
ns: namespace = {
x: i32 = 0;
f: () = { }
} // namespace ns
namespace a {
namespace b {
int x = 0;
} // namespace b
} // namespace a
a: namespace = {
b: namespace = {
x: i32 = 0;
} // namespace b
} // namespace a
using t = int;
namespace ns = a::b;
const auto& x = y;
t: type == i32;
ns: namespace == a::b;
x :== y;
void f() {
[] { };
}
f: () = {
:() = { };
}
void f() {
[] { }();
[] { return 0; }();
[] { g(); }();
}
f: () = {
:() = { }();
:() -> _ = { return 0; }();
:() -> _ = 0;();
:() = { g(); }();
:() = g();();
}
void f() {
[] {
g();
g()
};
[] {
g();
g()
}();
}
f: () = {
:() = {
g();
g();
};
:() = {
g();
g();
}();
}
void f() {
[] { [] { }; };
[] { }([] { });
}
f: () = {
:() = { :() = { }; };
:() = { }(:() = { });
}
f: () = :() = { :() = { }; };
f: () = :() = { }(:() = { });
f: () = {
// _primary-expression_.
(:() = 0);
(:() = 0;);
(:() = 0;());
(:() = 0, );
(:() = 0;, );
(:() = 0;(), );
:int = 0;
// _postfix-expression_.
:int = 0;();
:() = 0;();
g(:() = 0);
g(:() = 0;);
g(:() = 0;());
g(:() = 0, a);
g(:() = 0;, a);
g(:() = 0;(), a);
g(:() = 0, );
g(:() = 0;, );
g(:() = 0;(), );
g(:() = 0, a, );
x[:() = 0];
x[:() = 0;];
x[:() = 0;()];
x[:() = 0, a];
x[:() = 0;, a];
x[:() = 0;(), a];
x[:() = 0, ];
x[:() = 0;, ];
x[:() = 0;(), ];
x[:() = 0, a, ];
x*;
x&;
x~;
x$; // clang-format off
x *;
x &;
x ~;
x $; // clang-format on
x*&~$;
x$~&*;
x.y;
x..y;
x ..< y;
x ..= y;
// _prefix-expression_.
move x; // Pending [hsutter/cppfront#408][].
+move x; // Pending [hsutter/cppfront#408][].
// _is-as-expression_.
x is t;
x is 0;
x as t;
is is * (); // Pending [grammar][].
is is is;
(is) is (is);
(is) is (is)&;
(is) is (is&);
is is (); // Pending [grammar][].
is as is;
is as * (); // Pending [grammar][].
(is) as * (); // Pending [grammar][].
:() = 0; as t;
:() = 0; is t;
x is :() = 0;
x is :() = 0;();
// Chained comparisons.
min <= x < max;
a == b == c;
// _postfix-operator_ symbols as unary/binary.
x * x;
x* * x;
x * 0;
x* * 0;
x * (x);
x* * (x);
x & x;
x& & x;
x & 0;
x& & 0;
x & (x);
x& & (x);
x~(x);
x~~(x);
x$(x);
}
void f() {
if (a || b) g();
if (a || b) { g(); }
}
f: () = {
if (a || b) { g(); }
if a || b { g(); }
(x := 0) if a || b { g(); }
(x := 0, ) if a || b { g(); }
}
void f() {
if (a || b) g();
else x = 0;
if (a || b) {
g();
} else {
x = 0;
}
}
f: () = {
if (a || b) {
g();
} else {
x = 0;
}
if a || b {
g();
} else {
x = 0;
}
(x := 0)
if a || b {
g();
} else {
x = 0;
}
}
void f() {
if (a || b) g();
else if (true) x = 0;
else x = 1;
if (a || b) {
g();
} else if (true) {
x = 0;
} else {
x = 1;
}
}
f: () = {
if (a || b) {
g();
} else if (true) {
x = 0;
} else {
x = 1;
}
if a || b {
g();
} else if true {
x = 0;
} else {
x = 1;
}
}
void f() {
if constexpr (a || b) g();
else if constexpr (true) x = 0;
else x = 1;
if constexpr (a || b) {
g();
} else if constexpr (true) {
x = 0;
} else {
x = 1;
}
}
f: () = {
if constexpr (a || b) {
g();
} else if constexpr (true) {
x = 0;
} else {
x = 1;
}
if constexpr a || b {
g();
} else if constexpr true {
x = 0;
} else {
x = 1;
}
}
namespace ns {
using std::string;
using namespace std::chrono_literals;
} // namespace ns
ns: namespace = {
using std::string;
using std::chrono_literals::_;
} // namespace ns
f: () = {
inspect x { is _ = g(); }
(x := 0) inspect x { is _ = g(); }
inspect constexpr x { y: is _ = g(); }
inspect x {
is t = g();
is _ = g();
}
(x := 0)
inspect x {
is t = g();
is _ = g();
}
inspect x {
is t = {
g();
g();
}
is _ = g();
}
(inspect x -> i32 { is _ = 0; });
(inspect x -> i32 {
is i32 = 0;
is _ = 1;
});
std::cout << inspect x -> i32 { is _ = 0; } << '\n';
std::cout << inspect x -> i32 {
is i32 = 0;
is _ = 1;
} << '\n';
}
f: () = {
return (move x);
return move x; // Pending [hsutter/cppfront#408][].
return :int = 0;
return :() = 0;();
return x&;
(x := 0) return x&;
break;
break pre;
continue;
continue pre;
(x := 0) continue pre;
}
void f() {
while (a || b) g();
while (a || b) { g(); }
}
f: () = {
while (a || b) { g(); }
while a || b { g(); }
(x := 0) while a || b { g(); }
}
void f() {
while (a || b) {
g();
g();
}
}
f: () = {
while (a || b) {
g();
g();
}
while a || b {
g();
g();
}
}
void f() {
while (a || b) {
g();
++x;
}
}
f: () = {
while (a || b) next x++ { g(); }
while a || b next x++ { g(); }
while (a || b) next x++ {
g();
g();
}
while a || b next x++ {
g();
g();
}
(x := 0)
while a || b next x++ {
g();
g();
}
}
void f() {
do { g(); } while (a || b);
}
f: () = {
do { g(); } while (a || b);
do { g(); } while a || b;
(x := 0) do { g(); } while a || b;
}
void f() {
do {
g();
g();
} while (a || b);
}
f: () = {
do {
g();
g();
} while (a || b);
do {
g();
g();
} while a || b;
}
f: () = {
do { g(); } while (a || b) next x++;
do { g(); } while a || b next x++;
do {
g();
g();
} while (a || b) next x++;
do {
g();
g();
} while a || b next x++;
(x := 0)
do {
g();
g();
} while a || b next x++;
}
void f() {
for (const auto& e : r) g(e);
for (const auto& e : r) { g(e); }
for (const auto& x = 0; const auto& e : r) { g(e); }
for (const auto& : std::views::iota(17, 30)) { }
for (const auto& : std::ranges::subrange(v.begin(), v.end())) { }
}
f: () = {
for r do (e) g(e);
for r do (e) { g(e); }
(x := 0) for r do (e) { g(e); }
for 17 ..= 29 do (_) { }
for v.begin() ..< v.end() do (_) { }
}
void f() {
for (const auto& e : r) {
g(e);
++x;
}
}
f: () = {
for r next x++ do (e) g(e);
for r next x++ do (e) { g(e); }
for r next x++ do (e) {
g(e);
g(e);
}
(x := 0)
for r next x++ do (e) {
g(e);
g(e);
}
}
void f() {
pre:
while (a || b) g();
pre:
do { g(); } while (a || b);
pre:
for (const auto& e : r) g(e);
}
f: () = {
pre:
while a || b { g(); }
pre:
do { g(); } while a || b;
pre:
for r do (e) g(e);
(x := 0)
pre:
for r do (e) g(e);
}
void f() {
{ g(); }
{
g();
g();
}
}
f: () = {
{ g(); }
(x := 0) { g(); }
{
g();
g();
}
(x := 0) {
g();
g();
}
}
f: () = {
(x := 0) (x := 0) g();
(x := 0) (:() = 0;());
(x := 0) :int = 0;();
(x := 0)
:() = {
g();
g();
};
(x := 0) g(:() = 0;(), a);
(x := 0) x$~&*;
(x := 0) move x; // Pending [hsutter/cppfront#408][].
(x := 0) (is) as * (); // Pending [grammar][].
}
void f() { assert(a || b); }
f: () = { assert(a || b); }
f: () = { assert(a || b, ); }
void f() {
[] { assert(a || b); };
}
f: () = {
:() = { assert(a || b); };
}
f: () = {
assert(a || b);
assert(a || b);
}
f: () = {
assert(:() -> _ = true;());
assert(:() -> _ = { return true; }());
}
f: () = { assert(a || b, "!a && !b"); }
f: () = { assert(a || b, "!a && !b", ); }
f: () = { assert(a || b, "!(a)$ && !(b)$"); }
void f() noexcept { }
f: () throws = { }
void f() requires a { }
void f() requires a || b { }
void f() requires(a || b) { }
f: () requires a = { }
f: () requires a || b = { }
f: () requires(a || b) = { }
void f() requires([] { g(); }()) { }
f: () requires :() = { g(); }() = { }
f: () requires :() = g();() = { }
void f() requires([] {
g();
g();
}()) { }
f: () requires :() = {
g();
g();
}() = { }
void f() //
requires a || b {
g();
}
f: () //
requires a || b = {
g();
}
f: () pre(true) = { }
f: () pre(:() -> _ = { }) = { }
f: () pre(:() -> _ = true;()) = { }
f: () pre(:() -> _ = { return true; }()) = { }
f: ()
pre(true)
post(true)
= { }
f: ()
pre(:() = {
g();
g();
}())
= { }
f: @meta () = { }
f: @meta<T> () = { }
f: @meta<T, > () = { }
f: @meta <T: type> () = { }
f: @meta <T: type, > () = { }
f: @meta <T, T: type> () = { }
f: (x, move y: t) throws -> void = g();
f: <T, V: _> (x, move y: t) throws -> void requires a || b = g();
f: <T, V: _> (x, move y: t) throws -> void pre(true) requires a || b = g();
f: <T, V: _> (x, move y: t) throws -> void pre(true, ) requires a || b = g();
f: <T, V: _> (x, move y: t) throws -> void pre(true) requires a || b = { g(); }
f: @meta <T, V: _> (x, move y: t) throws -> void pre(true) requires a || b = { g(); }
f: @meta <T, V: _> (x, move y: t) throws -> void pre(true) requires a || b = {
g();
g();
}
x := $R"()";
using t = void();
using t = void (*)();
using t = int (*)();
t: type == (); // Pending [grammar][].
t: type == * (); // Pending [grammar][].
t: type == * () -> i32; // Pending [grammar][].
using t = auto (*)() -> auto (*)() -> void;
using t = auto (*)() -> auto (*)(int) -> auto (*)() -> int;
t: type == * () -> * (); // Pending [grammar][].
t: type == * () -> * (:i32) -> * () -> i32; // Pending [grammar][].
// Adapted from <https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-operators>.
g: () = { // clang-format off
f: (:i32) -> * (:i32) -> std::string; // Pending [grammar][].
assert(f is (:i32) -> * (:i32) -> std::string); // Pending [grammar][].
// / | |
// / | |
assert(f(42) is * (:i32) -> std::string); // Pending [grammar][].
// ______/ |
// / |
assert((f(42)*) is (:i32) -> std::string); // Pending [grammar][].
// ______/
// /
assert((f(42)*)(1) is std::string); // Pending [grammar][].
} // clang-format on
I<8> x;
x: I<8>;
I<[] { }> x;
I<[] { }()> x;
x: I<:() = { }>;
x: I<:() = { }()>;
template<class T> const I<8>* x;
template<class T> const I<8>* const x;
x: <T> * const I<8>;
x: <T> const * const I<8>;
template<I<[] { }> V> int x;
x: <V: I<:() = { }>> i32;
I<[] { return 0; }()> x;
x: I<:() -> _ = { return 0; }()>;
x: I<:() -> _ = 0;()>;
template<I<[] { return 0; }()> V> int x;
x: <V: I<:() -> _ = { return 0; }()>> i32;
I<8> f(int l, I<8> r);
f: (l: i32, r: I<8>) -> I<8>;
I<8> (*f)(int l, I<8> r);
f: * (l: i32, r: I<8>) -> I<8>;
std::tuple<int> f();
f: () -> (a: i32);
f: () -> (a: i32, );
std::tuple<int, auto (*)(int)->void (*)()> f();
f: () -> std::tuple<i32, * (:i32) -> * ()>;
f: () -> (a: i32, b: * (:i32) -> * ());
f := :() = x*$;
// f: <T> (x: T<N() <<= 1>) = { }
// f: <T> (x: T<N() >>= 1>) = { }
// f: <V: T<N() <<= 1>> (x) = { }
// f: <V: T<N() >>= 1>> (x) = { }
x := y$;
x := 0;
x = 0;
x := 0;
xx := 0;
xx = 0;
x := 0;
x: _ = y;
xx: _ == y;
x: _ == y;
x :== y;
xx :== y;
zero :== int_c<0>;
f5: <T> (_: std::vector<T>) = { }
f1: () = { v0 := 0; }
f2: () = { v0 := cp(0); }
f4: (inout v0: i8, v1: * i8) = {
v0&* = 1;
v1* *= 1;
}
cp: <T> (x: T) -> T = x;
t0: <v0: _> type == i8;
t0: <v0: _> final type = { }
t0: <v0: _> requires true = 0;
main: () -> int = {
f3();
// next(u8(255));
v0: i8 = 1;
f4(v0, v0&);
v: std::vector<int> = ();
f5(v);
return next(-v0);
}
x: long long;
// Interpolated raw string literal.
x := $R"()";
x := $R"(x)";
x := $R"~()~";
x := u8$R"~(x)~";
// Clang Format regression tests.
// // Not yet fixed.
// x := :() -> forward () throws = f0$*;
f: () = {
dark_grey :== :sf::Color = (0x64, 0x64, 0x64);
light_grey :== :sf::Color = (0x90, 0x90, 0x90);
x : = f ( : ( ) = {
if true { }
}, z) ;
}
// f: () = {
// a
// }
jegp: namespace = {
qty: namespace = {
unit_symbol: type = {
operator(): <N> (this, forward number: N) -> quantity<U*.default_name, U, std::remove_reference_t<N>> = (number, this);
}
} // namespace qty
} // namespace jegp
f: () = {
fffffffffff(:jegp__ui__rectangle = (
jegp__ui__vectorrrrr(200000000000000.x()),
jegp__ui__vectorrrrr(128000000000000.x().x())));
(l := (:jegp::ui::vector = (1.px().wide(), 1.px().tall())).from(jegp::ui::window()),
r := (:jegp::ui::vector = (2.px().wide(), 2.px().tall())).from(jegp::ui::window()))
std::cout << distance(l, r) << '\n';
}
fffffffffffffffffffffffffffffffffffffffffff: (this) -> _ = :tttttttttttttttttttttttttttttttttttttt =
vvvvvvvvvvvvvvvvvvv;
export renumber: <NewNumber, Name, Unit, Number> (q: quantity<Name, Unit, Number>) -> quantity<Name, Unit, NewNumber>
requires std::convertible_to<Number, NewNumber> = :quantity = (q.name, forward q.number as Number, q.unit);
// f: () = {
// static_assert(false, x{} + "");
// }
// x := 0.std::views::iota();
// f: () = {
// t.add_member($R"(
// (value())$
// for vec do (i)
// if (i % 2 == 0) { count++; }
// return count;
// )");
// }
// Breaks into two adjacent *string-literal*s.
// f: () = {
// loop_constraints.add("std::invocable<decltype((arg)$), "
// "~~~~decltype(std::declval<std::ranges::range_reference_t<R>>().std::as_const())>");
// }
// f: () = {
// g := :() 0;
// (x := 0) _ = x;
// }
f: () = {
require_arguments := :(s: step, n: int) (require&$*)(
s.arguments.empty() == (n == 0), ("`(s.name())$` needs (n)$ argument(s)").error());
}
// (..., _ = args);
empty2: @ ::noop type = { }
// // Fixed.
x: function_ref<(_: i32) -> i32>;
x := 0..<n;
test_function: type == () -> void;
f: <T: type = my_type> () = { }
f: () = { return $R"(
)"; }
f: (_) a;
x :== f.operator()<i32>();
_ := :() = {
x;
assert(true);
};
f: () = _ = : ::x = 0;
to_vector_ref: <V> (inout v: V) -> _ requires is_specialization_of<V, cartesian_vector>() = //
:geo::vector2d = (v.x.number&, v.y.number&);
export to: <Unit> (forward q: quantity) -> _ requires std::derived_from<Unit, qty::unit> = //
:quantity = (q.name, cpp2::unsafe_narrow<Number>(forward q.number), :Unit = ());
f: () = {
is_close :=
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
visibleArea :==
sf::FloatRect(:sf::Vector2f = (), sf::Vector2f(event.size.width as float, event.size.height as float));
if full() { }
(x := 0)
//
_ = x;
}
t: @struct type = { }
or: @and type = { }
f: () = {
for args next (:() = 0) do (arg) std::cout << arg;
// for args next :() = 0 do (arg) std::cout << arg;
}
t: type = {
f: (inout this, x) -> i32 = 42;
}
x: Type = (a, 0);
f: () = {
v0<:int = 0>;
assert(x is () -> void); // When not formatted.
operator==(this, this);
operator[](this, this);
x := t<* day>;
(x := 0) (move x);
// (x: t<* t> = g("('(')$")) (move x);
:<move V: _> () = { };
}
x := (:int = 0);
t: type = {
operator is: (this, that) -> bool;
operator[]: (inout this, x: i32) = { } // When further indented.
}
f: () = {
:() pre(1) = 0;
:() pre(1) = { };
:() pre(1) requires 1 = { };
:() pre(1)
= :() = {
x;
x;
};
}
f: () = {
x * x;
x & x;
x * as;
x * (0);
}
f: () = {
(move x);
(:int = 0);
(x := 0) (move x);
(move x);
();
}
f: () -> std::tuple<i32, * (:i32) -> * ()>; // `->*` is split into `->` `*`.
f: () = {
:int = 0;
+x;
:int = 0;
-x;
g();
();
}
f: () = {
for r do (e) g(e);
}
f: (is: * ()) = {
assert(is is is);
assert((is) is (is));
assert(is as * ());
assert((is) as * ());
}
I<[] {
auto y = 0;
return y < z;
}()>
x = 0;
x: I<:() -> _ = {
y := 0;
return y < z;
}()> = 0;
int_c: <V: int> const std::integral_constant<int, V> = ();
x := (type);
f3: () = {
v0: i8 = 0;
v1: i8 = i8(0);
v2: i8 = cp(:i8 = 0);
v3: i8 = cp(0 as i8);
v4: t0<:i8 = 0> = 0;
v5 := v0&;
v6 := v5*;
}
// Syntax highlighting test cases.
// Highlighted interpolation (I want them formatted, too).
x := "Next is (current++)$\n";
x := "(inspect 1->i32{is _=2;})$";
x := "(\"0\")$\n"; // Known limitation.
// Type-only contexts.
x: i32 = 0;
x: int = 0;
x: day = Wednesday;
x: type == i32;
x: type == day;
x := x as day;
f: () -> day = { }
// Types.
x := t<i32>;
x := t<* day>;
x := i32(0);
// `_` wildcard.
// // Anonymous declarations.
f: <_> (_) = { _: std::lock = mutex; }
_: namespace = {
// // Using namespace.
using std::chrono_literals::_;
} // namespace _
// // Deduced types.
x: _ = 0;
f: (:_) -> _ = {
// // Placeholder.
x := x is _;
// // Discard.
x := _ = 0;
// // Just an identifier.
f(_);
}
f: () = {
// Keyword, declaration, type, identifier.
(move move: move = move) { } // Pending [hsutter/cppfront#408][].
}
int x = 0;
const int* const x = 0;
x: i32 = 0;
x: const * const i32 = 0; // clang-format off
x : i32 = 0 ;
x:i32=0;
x:const*const i32=0; // clang-format on
x: char = 0;
x: _schar = 0;
x: _uchar = 0;
x: short = 0;
x: ushort = 0;
x: int = 0;
x: uint = 0;
x: signed = 0;
x: unsigned = 0;
x: long = 0;
x: ulong = 0;
x: longlong = 0;
x: ulonglong = 0;
x: float = 0;
x: double = 0;
x: longdouble = 0;
long int x = 0;
x: long int = 0;
::day x = 0;
ns::day x = 0;
::t::day x = 0;
t<0>::day x = 0;
::t<0>::day x = 0;
x: ::day = 0;
x: ns::day = 0;
x: ::t::day = 0;
x: t<0>::day = 0;
x: ::t<0>::day = 0;
export day x = 0;
export x: day = 0; // clang-format off
export x: day = 0; // clang-format on
exportx: day = 0;
x: @x i32 = 0;
x: @x::x i32 = 0;
x: @x.x i32 = 0;
x: @x<T> i32 = 0;
x: @x<T>::x i32 = 0;
x: @x<T>.x i32 = 0;
x: @x <T: type> i32 = 0;
x: @x<T> <T: type> i32 = 0; // clang-format off
x:@x@x i32=0;
x : @ x @ x i32 = 0; // clang-format on
template<class T> int x = 0;
template<class> day x = 0;
x: <T: type> i32 = 0;
x: <T> i32 = 0;
x: <:type> day = 0; // clang-format off
x:<T,T>i32=0;
x : < T , T > i32 = 0; // clang-format on
template<auto V> int x = 0;
template<auto> int x = 0;
template<const auto& V> day x = 0;
template<const auto&> day x = 0;
x: <V: _> i32 = 0;
x: <:_> i32 = 0;
x: <:__> i32 = 0;
x: <in V: _> day = 0;
x: <in: _> day = 0;
x: <inV: _> day = 0;
void f() { }
void f(const auto& x) { }
void f(const auto&) { }
void f(auto) { }
void f(const auto) { }
void f(const day x) { }
void f(const day) { }
f: () = { }
f: (in x: _) = { }
f: (in x) = { }
f: (x) = { }
f: (in: _) = { }
f: (:_) = { }
f: (copy: _) = { }
f: (copy: const _) = { }
f: (in x: day) = { }
f: (x: day) = { }
f: (in: day) = { }
f: (:day) = { } // clang-format off
f:(x,y)={}
f : ( in x : _ , : day ) = { }
f: (in :_) = { } // clang-format on
f: (inx: _) = { }
f: (inx) = { }
f: (:const_) = { }
void f() noexcept { }
f: () throws = { } // clang-format off
f:()throws={} // clang-format on
_: throws_ = { }
int f() { }
day f() { }
auto f() { }
auto&& f() { }
auto f() -> int { }
auto f() -> day { }
auto f() -> auto { }
auto f() -> auto&& { }
f: () -> i32 { }
f: () -> day { }
f: () -> _ { }
f: () -> forward _ { } // clang-format off
f:()->i32{}
f:()->forward _{}
f:()->forward_{} // clang-format on
auto f() -> move { }
auto f() -> ns::move { }
auto f() -> ::ns::move { }
f: () -> ::move { }
f: () -> ns::move { }
f: () -> ::ns::move { }
f: () pre(true) = { }
f: () pre(true, "") = { }
f: () pre<::x<0>>(true) = { }
f: () pre<bounds_safety>(true) = { }
f: () pre<bounds_safety, audit>(true) = { }
void f() requires true { }
f: () requires true = { }
_: requires_ = { }
struct t { };
struct t final { };
struct t : base {
int x = 0;
day x;
bool operator==(const t&) const = default;
void operator[](int x) { }
virtual void f() const = 0;
};
t: type = { }
t: final type = { }
t: type = {
x: i32 = 0;
x: day;
this: base;
operator==: (this, that) -> bool;
operator[]: (inout this, x_: i32) = {
x = x_;
this.x = x_;
operator==(this, this);
this.operator==(this);
}
f: (virtual in this); // clang-format off
x:i32=0;
x :day ;
this :base ;
operator == :( this ,that )->bool ;
operator [ ] :( inout this ,x :i32 )={} // clang-format on
f: (in this_, that_);
f: (virtual_);
f: (inthis);
f: (virtualthis);
f: (virtualinthis);
}
t: type = {
operator is: (this, that) -> bool;
}
_: final_ = { }
_: type_ = { }
namespace ns { }
ns: namespace = { }
// clang-format off
ns :namespace={} // clang-format on
_: namespace_ = { }
x = 0.0e+0f;
x := 0.0e+0f;
x = 0x0'0u;
x := 0x0'0u;
x = 0b0'0;
x := 0b0'0;
x = 0'0;
x := 0'0;
x = '\0';
x := '\0';
x = nullptr;
x := nullptr;
x = false;
x := false;
x = u8"";
x := u8"";
x = "(x)$";
x := "\(x)$";
x := "(x)$";
x := "(x)$(x)$";
x := "@(x)$@(x)$@";
x = R"()";
x := R"()";
x = u8R"()";
x := u8R"()";
x := $R"()";
x := u8$R"()";
// Highlight interpolation also in non-interpolated raw string literal as it's most likely used for reflection.
x = R"((x)$)";
x := $R"(\(x)$)";
x := R"(\(x)$)";
x := R"((x)$)";
x := R"((x)$(x)$)";
x := R"(@(x)$@(x)$@)";
x := "(:()->_=0;())$";
x := "(inspect 1->i32{is _=2;})$";
x = x = x.x = x::x = x<0> = x<0>.x = x<0>::x;
x := x = x.x = x::x = x<0> = x<0>.x = x<0>::x;
x = (0);
x := (0);
x := :int = 0;
x := (:int = 0);
x := (:int = 0;);
x := :() -> _ = 0;();
x := :() -> _ = 0;(x, :int = 0);
x := :() -> _ = 0;(x, :int = 0;);
x = *x = &x;
x := x* = x&;
x = x[0](0).x;
x := x[0](0).x;
x = std::iota(0, n);
x := 0 ..< n;
x := 0 ..= n;
x = std::ranges::subrange(v.begin(), --v.end());
x := v.begin() ..< v.end()--;
x := v.begin() ..= v.end()--;
x = +x;
x := +x = move x = +move x;
x = x * x + x << x <=> x < x == x & x ^ x | x && x || x;
x := x * x + x << x <=> x < x == x & x ^ x | x && x || x;
struct t {
struct t { };
struct t {
int x = 0;
void f() { }
};
};
t: type = {
t: type = { }
t: type = {
x: i32 = 0;
f: () = { }
}
}
namespace ns {
int x = 0;
void f() { }
struct t {
int x = 0;
void f() { }
};
} // namespace ns
ns: namespace = {
x: i32 = 0;
f: () = { }
t: type = {
x: i32 = 0;
f: () = { }
}
} // namespace ns
namespace ns {
int x = 0;
namespace ns {
void f() { }
struct t {
int x = 0;
struct t {
void f() {
[] { };
}
};
};
} // namespace ns
} // namespace ns
ns: namespace = {
x: i32 = 0;
ns: namespace = {
f: () = { }
t: type = {
x: i32 = 0;
t: type = {
f: () = {
:() = { };
}
}
}
} // namespace ns
} // namespace ns
// Cpp1 colons.
int x = a ? b : c;
int x = a ? // clang-format off
b : c; // clang-format on
void f() {
switch (x) {
case x:
default:
label:
goto label;
}
for (auto x : r) { }
}
enum t : int;
class t : base {
public:
unsigned x : 1;
t() : x{} { }
t() requires x : x{} { }
t() // clang-format off
requires x : x{} { } // clang-format on
t() noexcept : x{} { }
t() try : x{} {
} catch (...) { }
t() // clang-format off
try : x{} { // clang-format on
} catch (...) { }
};
module a:b;
module: private;
int x = a::b;
// Cpp2 colons.
f: () = {
// Declaration colons.
pre:
while true { }
pre: //
while true { }
x := 0;
x: i32 = 0;
:i32 = 0;
x :== y;
x: _ == y;
f: () = { }
:() = { };
:(in x: i32) = { };
:(x: i32) = { };
:(in: i32) = { }; // Pending [grammar][].
:(:i32) = { }; // Pending [grammar][].
t: <V: _> type = {
x: i32;
this: u;
operator=: ();
operator==: ();
operator(): ();
operator[]: ();
}
inspect x { y: is _ = g(); }
a::b;
}
struct t {
void f(override) override; // Declaration, keyword.
void f(final) final; // Declaration, keyword.
};
f: () = {
// Declaration followed by keyword.
:(implicit, implicit this) = { };
:(override, override this) = { };
:(final, final this) = { };
:(final, final in this) = { };
:(throws) throws = { };
f: (pre) pre(1) = { }
f: (post) post(1) = { }
f: (assert) assert(1) = { }
t: <type> type = { }
t: <final> final type = { }
t: <type> type requires 1 = { }
t: <type> type == i32;
:<type: type> () = { };
}
f: () = {
move; // Identifier.
-move; // Identifier.
move*; // Identifier.
x is move; // Type.
x + move x; // Keyword. // Pending [hsutter/cppfront#408][].
x + move; // Identifier.
move x; // Keyword. // Pending [hsutter/cppfront#408][].
move move x; // Keywords. // Pending [hsutter/cppfront#408][].
move: i8; // Declaration.
x: move; // Type.
f(move); // Identifier.
x[move]; // Identifier.
x[move x]; // Keyword.
f(move x, move x); // Keywords.
:(move, move) = { }; // Declarations.
:(move: i8) = { }; // Keyword. // Pending [grammar][].
:(move x) = { }; // Keyword.
:(move x: i8) = { }; // Keyword.
:(move move) = { }; // Keyword, declaration.
:(move move: i8) = { }; // Keyword, declaration.
:(:move) = { }; // Type.
:(move: move) = { }; // Keyword, type. // Pending [hsutter/cppfront#408][].
:() -> move i8 = { }; // Keyword.
:() -> ::move = { }; // Type.
return move x; // Keyword. // Pending [hsutter/cppfront#408][].
:<move V: _> () = { }; // Keyword. // Pending [hsutter/cppfront#425][].
(move move: move = move) { } // Keyword, declaration, type, identifier. // Pending [hsutter/cppfront#408][].
}
void f() {
x and y; // Keyword.
new int; // Keyword.
class t; // Keyword.
struct t; // Keyword.
}
f: () = {
// Reclaimed identifiers.
f(and);
f(::new);
f(class);
f(struct);
// Special identifiers.
x := new<i32>();
x := unique.new<i32>();
x := shared.new<i32>();
_: finally = finally(:() = { });
_: finally<std::function<void()>> = finally<std::function<void()>>();
_: cpp1_ref<int> = cpp1_ref(x);
_: cpp1_ref = cpp1_ref<int>(x);
_: cpp1_rvalue_ref<int> = cpp1_rvalue_ref(x);
_: cpp1_rvalue_ref = cpp1_rvalue_ref<int>(x);
unsafe_narrow<int>(0.0);
unsafe_cast<derived>(base);
_: type_of(0) = type_of(0)(0);
assert<bounds_safety>(min <= x < max);
// Normal identifiers.
x := ::new<i32>();
x := ::unique.new<i32>();
x := shared.old<i32>();
_: ::finally = ::finally();
_: ::cpp1_ref = ::cpp1_ref<int>;
_: ::cpp1_rvalue_ref<int> = ::cpp1_rvalue_ref(x);
_ = ::unsafe_narrow;
_ = ::unsafe_cast;
_ = ::type_of;
_: type_of<u> = 0;
assert<my_bounds_safety>(min <= x < max);
casset<testing>("reverse side");
}
// Syntax highlighting regression tests.
// // Not yet fixed.
f: <T: type = my_type> () = { }
x: function_ref<(_: i32) -> i32>;
// clang-format off
// x: t<y>= 0;
t: @struct<T: type> type = { } // clang-format on
i: (x) (x);
s :== "x(:t=0:t)$x";
s :== "x(:t=0;:t)$x";
s :== "x(:t=0;++:t)$x";
main: (args) = {
// for args next :() = 0 do (arg) std::cout << arg;
assert<testing, testing>();
}
// sfml_argument_list: (mf: cpp2::meta::function_declaration) -> std::string =
// "(" + mf.get_parameters().drop(1).map(sfml_argument).intersperse("(',')$ ").flatten().to<std::string>() + ")";
// // Fixed.
f: () = { static_assert(true); }
c := 'X';
c := '?';
s: (f, g) :(x) f$(x, g$(x));
b: (f, g) :(x) f$(g$(x));
_ := x is () -> void;
a: span<const int>;
i: (x) x;
s :== "x(:t=0)$x";
s :== "x(x:t)$x";
s :== "x(x&:t)$x";
s :== "x(x...:t)$x";
s :== R"(x(+"": <10.2f)$x)";
s :== "x(x.price(): <10.2f)$x";
f: (x...: int) = ... && g(x...);
a: unit<"">;
x := (inspect y -> int {
is (0) = 1;
is _ = 2;
});
// clang-format off
x := (0)is 0; // clang-format on
t: type = {
operatoris: ();
}
x := "()$ ()";
// [grammar]: https://github.com/hsutter/cppfront/issues/387
// [hsutter/cppfront#408]: https://github.com/hsutter/cppfront/issues/408
// [hsutter/cppfront#425]: https://github.com/hsutter/cppfront/issues/425