Skip to content

Commit 97f4ddc

Browse files
committed
Merge remote-tracking branch 'origin/main' into temp
2 parents 28ae594 + 3604626 commit 97f4ddc

File tree

244 files changed

+6385
-6102
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

244 files changed

+6385
-6102
lines changed

.github/workflows/build-cppfront.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ jobs:
3535
- compiler: clang++-14
3636
cxx-std: 'c++2b'
3737
include:
38-
- runs-on: macos-11
39-
compiler: clang++
40-
cxx-std: 'c++20'
4138
- runs-on: macos-latest
4239
compiler: clang++
4340
cxx-std: 'c++20'

.github/workflows/docs.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: docs
2+
on:
3+
push:
4+
branches:
5+
- main
6+
permissions:
7+
contents: write
8+
jobs:
9+
deploy:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v3
13+
- uses: actions/setup-python@v4
14+
with:
15+
python-version: 3.x
16+
- uses: actions/cache@v2
17+
with:
18+
key: ${{ github.ref }}
19+
path: .cache
20+
- run: pip install mkdocs-material
21+
- run: mkdocs gh-deploy --force

CITATION.cff

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cff-version: 1.2.0
2+
message: >-
3+
If you use this software, please cite it using the
4+
metadata from this file.
5+
type: software
6+
title: cppfront
7+
authors:
8+
- given-names: Herb
9+
family-names: Sutter
10+
repository-code: 'https://github.com/hsutter/cppfront'
11+
abstract: A personal experimental C++ Syntax 2 -> Syntax 1 compiler
12+
license: CC-BY-NC-ND-4.0

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
# cppfront
22

3-
An experimental C++ Syntax 2 -> Syntax 1 transpiler
4-
5-
Copyright (c) Herb Sutter
6-
SPDX-License-Identifier: CC-BY-NC-ND-4.0
7-
See [License](LICENSE)
3+
This project is an experimental C++ Syntax 2 -> Syntax 1 transpiler, copyright (c) Herb Sutter • See [License](LICENSE)
84

95
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
106

README.md

Lines changed: 30 additions & 97 deletions
Large diffs are not rendered by default.

docs/cpp2/common.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# Common programming concepts
2+
3+
## <a id="main"></a> `main`
4+
5+
As always, `main` is the entry point of the program. For example:
6+
7+
`main` can have either:
8+
9+
- No parameters: &emsp; **`#!cpp main: () /*etc.*/`**
10+
11+
- One parameter of implicit type named `args`: &emsp; **`#!cpp main: (args) /*etc.*/`**
12+
13+
- The type of `args` cannot be explicitly specified. It is always `cpp2::args_t`, which behaves similarly to a `#!cpp const std::array<std::string_view>`.
14+
15+
- Using `args` performs zero heap allocations. Every `string_view` is directly bound to the string storage provided by host environment.
16+
17+
- `args.argc` and `args.argv` additionally provide access to the raw C/C++ `main` parameters.
18+
19+
``` cpp title="main with (args)" hl_lines="5 9"
20+
// Print out command line arguments, then invoke
21+
// a Qt event loop for a non-UI Qt application
22+
main: (args) -> int
23+
= {
24+
for args do (arg) {
25+
std::cout << arg << "\n";
26+
}
27+
28+
app: QCoreApplication = (args.argc, args.argv);
29+
return app.exec();
30+
}
31+
```
32+
33+
`main` can return:
34+
35+
- `#!cpp void`, the default return value for functions. No `#!cpp return` statement is allowed in the body. In this case, the compiled Cpp1 code behaves as if `main` returned `#!cpp int`.
36+
37+
- `#!cpp int`. If the body has no `#!cpp return` statement, the default is to `#!cpp return 0;` at the end of the function body.
38+
39+
- Some other type that your Cpp1 compiler(s) supports as a nonstandard extension.
40+
41+
42+
## <a id="comments"></a> Comments
43+
44+
The usual `#!cpp // line comments` and `#!cpp /* stream comments */` are supported. For example:
45+
46+
``` cpp title="Writing comments"
47+
// A line comment: After //, the entire
48+
// rest of the line is part of the comment
49+
50+
/*
51+
A stream comment: After /*, everything until the
52+
next * / (without a space between) is part of the
53+
comment. Note that stream comments do not nest.
54+
*/
55+
```
56+
57+
58+
## <a id="lists"></a> Lists and commas
59+
60+
All lists use `,` commas between list items, and may be enclosed by
61+
62+
- `(` `)` parentheses, for most lists
63+
64+
- `[` `]` brackets, for calling the subscript operator
65+
66+
- `<` `>` angle brackets, for template parameter/argument lists
67+
68+
For example:
69+
70+
``` cpp title="Lists, using optional trailing commas just because we can" hl_lines="1 4 6 7"
71+
print: <T,U> (t: T, u: U) = std::cout << t << u << "\n";
72+
73+
main: () = {
74+
array: std::array = ('A', 'B', 'C');
75+
76+
for (0, 1, 2) do (e) {
77+
print( e, array[e] );
78+
}
79+
// Prints:
80+
// 0A
81+
// 1B
82+
// 2C
83+
}
84+
```
85+
86+
87+
An extra comma at the end of the list, before the closing `)` or `>`, is always allowed but ignored if present (for details, see [Design note: Commas](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Commas)).
88+
89+
For example:
90+
91+
``` cpp title="Lists, using optional trailing commas just because we can" hl_lines="1 4 6 7"
92+
print: <T,U,> (t: T, u: U,) = std::cout << t << u << "\n";
93+
94+
main: () = {
95+
array: std::array = ('A', 'B', 'C',);
96+
97+
for (0, 1, 2,) do (e) {
98+
print( e, array[e,], );
99+
}
100+
// Prints:
101+
// 0A
102+
// 1B
103+
// 2C
104+
}
105+
```
106+
107+
108+
## <a id="keywords"></a> Reserved keywords
109+
110+
Cpp2 has very few globally reserved keywords; nearly all keywords are contextual, where they have their special meaning when they appear in a particular place in the grammar. For example:
111+
112+
- `new` is used as an ordinary function to do allocation (e.g., `shared.new<widget>(1, 2, 3)`).
113+
114+
- `struct` and `enum` are used as function names in the metafunctions library.
115+
116+
- `type` can be used as an ordinary name (e.g., `std::common_type<T1,T2>::type`).
117+
118+
In rare cases, usually when consuming code written in other languages, you may need to write a name that is a reserved keyword. The way to do that is to prefix it with `__identifer__`, which treats it as an ordinary identifier (without the prefix).
119+
120+
121+
## <a id="fundamental-types"></a> Fundamental data types
122+
123+
Cpp2 supports the same fundamental types as today's Cpp1, but additionally provides the following aliases in namespace `cpp2`:
124+
125+
| Fixed-width types | Synonym for |
126+
|---|---|
127+
| `i8` | `std::int8_t` |
128+
| `i16` | `std::int16_t` |
129+
| `i32` | `std::int32_t` |
130+
| `i64` | `std::int64_t` |
131+
| `u8` | `std::uint8_t` |
132+
| `u16` | `std::uint16_t` |
133+
| `u32` | `std::uint32_t` |
134+
| `u64` | `std::uint64_t` |
135+
136+
| Variable-width types <br> (Cpp2-compatible single-word names) | Synonym for (these multi-word<br> names are not allowed in Cpp2) |
137+
|---|---|
138+
| `ushort` | `#!cpp unsigned short` |
139+
| `uint` | `#!cpp unsigned int` |
140+
| `ulong` | `#!cpp unsigned long` |
141+
| `longlong` | `#!cpp long long` |
142+
| `ulonglong` | `#!cpp unsigned long long` |
143+
| `longdouble` | `#!cpp long double` |
144+
145+
| For compatibility/interop only,<br> so deliberately ugly names | Synonym for (these multi-word<br> names are not allowed in Cpp2) | Notes |
146+
|---|---|---|
147+
| `_schar` | `#!cpp signed char` | Normally, prefer `i8` instead |
148+
| `_uchar` | `#!cpp unsigned char` | Normally, prefer `u8` instead |
149+
150+
## <a id="type-qualifiers"></a> Type qualifiers
151+
152+
Types can be qualified with `#!cpp const` and `#!cpp *`. Types are written left-to-right, so a qualifier always applies to what immediately follows it. For example, to declare a `#!cpp const` pointer to a non-`#!cpp const` pointer to a `#!cpp const i32` object, write:
153+
154+
``` cpp title="Using type qualifiers"
155+
// A const pointer to a non-const pointer to a const i32 object
156+
p: const * * const i32;
157+
```
158+
159+
## <a id="literals"></a> Literals
160+
161+
Cpp2 supports the same `#!cpp 'c'`haracter, `#!cpp "string"`, binary, integer, and floating point literals as Cpp1, including most Unicode encoding prefixes and raw string literals.
162+
163+
Cpp2 supports using Cpp1 user-defined literals for compatibility, to support seamlessly using existing libraries. However, because Cpp2 has [unified function call syntax (UFCS)](expressions.md#ufcs), the preferred way to author the equivalent in Cpp2 is to just write a function or type name as a `.` call suffix. For example:
164+
165+
- You can create a `u8` value by writing either `u8(123)` or **`123.u8()`**. [^u8using]
166+
167+
- You can write a 'constexpr' function like `#!cpp nm: (value: i64) -> my_nanometer_type == { /*...*/ }` that takes an integer and returns a value of a strongly typed "nanometer" type, and then create a `nm` value by writing either `nm(123)` or **`123.nm()`**.
168+
169+
Both **`123.nm()`** and **`123.u8()`** are very similar to user-defined literal syntax, and more general.
170+
171+
## <a id="operators"></a> Operators
172+
173+
Operators have the same precedence and associativity as in Cpp1, but some unary operators that are prefix (always or sometimes) in Cpp1 are postfix (always) in Cpp2.
174+
175+
### <a id="unary-operators"></a> Unary operators
176+
177+
The operators `!`, `+`, and `-` are prefix, as in Cpp1. For example:
178+
179+
``` cpp title="Using prefix operators"
180+
if !vec.empty() {
181+
vec.emplace_back( -123.45 );
182+
}
183+
```
184+
185+
| Unary operator | Cpp2 example | Cpp1 equivalent |
186+
|---|---|---|
187+
| `!` | `!vec.empty()` | `!vec.empty()` |
188+
| `+` | `#!cpp +100` | `#!cpp +100` |
189+
| `-` | `#!cpp -100` | `#!cpp -100` |
190+
191+
The operators `.`, `*`, `&`, `~`, `++`, `--`, `()`, `[]`, and `$` are postfix. For example:
192+
193+
``` cpp title="Using postfix operators"
194+
// Cpp1 examples, from cppfront's own source code:
195+
// address = &(*tokens)[pos + num];
196+
// is_void = *(*u)->identifier == "void";
197+
// Cpp2 equivalents:
198+
address = tokens*[pos + num]&;
199+
is_void = u**.identifier* == "void";
200+
```
201+
202+
Postfix notation lets the code read fluidly left-to-right, in the same order in which the operators will be applied, and lets declaration syntax be consistent with usage syntax. For more details, see [Design note: Postfix operators](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-operators).
203+
204+
> Note: The function call syntax `f(x)` calls a namespace-scope function, or a function object, named `f`. The function call syntax `x.f()` is a unified function call syntax (aka UFCS) that calls a type-scope function in the type of `x` if available, otherwise calls the same as `f(x)`. For details, see [Design note: UFCS](https://github.com/hsutter/cppfront/wiki/Design-note%3A-UFCS).
205+
206+
| Unary operator | Cpp2 example | Cpp1 equivalent |
207+
|---|---|---|
208+
| `#!cpp .` | `#!cpp obj.f()` | `#!cpp obj.f()` |
209+
| `#!cpp *` | `#!cpp pobj*.f()` | `#!cpp (*pobj).f()` or `#!cpp pobj->f()` |
210+
| `#!cpp &` | `#!cpp obj&` | `#!cpp &obj` |
211+
| `#!cpp ~` | `#!cpp val~` | `#!cpp ~val` |
212+
| `#!cpp ++` | `#!cpp iter++` | `#!cpp ++iter` |
213+
| `#!cpp --` | `#!cpp iter--` | `#!cpp --iter` |
214+
| `(` `)` | `#!cpp f( 1, 2, 3)` | `#!cpp f( 1, 2, 3)` |
215+
| `[` `]` | `#!cpp vec[123]` | `#!cpp vec[123]` |
216+
| `$` | `val$` | _reflection — no Cpp1 equivalent yet_ |
217+
218+
> Because `++` and `--` always have in-place update semantics, we never need to remember "use prefix `++`/`--` unless you need a copy of the old value." If you do need a copy of the old value, just take the copy before calling `++`/`--`.
219+
220+
Unary suffix operators must not be preceded by whitespace. When `*`, `&`, and `~` are used as binary operators they must be preceded by whitespace. For example:
221+
222+
| Unary postfix operators that<br>are also binary operators | Cpp2 example | Cpp1 equivalent |
223+
|---|---|---|
224+
| `#!cpp *` | `#!cpp pobj* * 42` | `#!cpp (*pobj)*42` |
225+
| `#!cpp &` | `#!cpp obj& & mask` <p> (note: allowed in unsafe code only) | `#!cpp &obj & mask` |
226+
227+
For more details, see [Design note: Postfix unary operators vs binary operators](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-unary-operators-vs-binary-operators).
228+
229+
230+
### <a id="binary-operators"></a> Binary operators
231+
232+
Binary operators are the same as in Cpp1. From highest to lowest precedence:
233+
234+
| Binary operators grouped by precedence |
235+
|---|
236+
| `*`, `/`, `%` |
237+
| `+`, `-` |
238+
| `<<`, `>>` |
239+
| `<=>` |
240+
| `<`, `>`, `<=`, `>=` |
241+
| `==`, `!=` |
242+
| `&` |
243+
| `^` |
244+
| `|` |
245+
| `&&` |
246+
| `||` |
247+
| `=` and compound assignment |
248+
249+
250+
[^u8using]: Or `123.cpp2::u8()` if you aren't `using` the namespace or that specific name.

0 commit comments

Comments
 (0)