Types and literals
| Cuarzo type | Generated C type | Example |
|---|---|---|
int |
int64_t: 64 bits on every system |
42 |
i8, i16, i32, i64 |
fixed-width signed integer | 42 |
uint |
uint64_t |
42 |
u8, u16, u32, u64 |
fixed-width unsigned integer | 42 |
float, f32 |
float |
3.14 |
f64 |
double |
3.14 |
str |
char* |
"text" |
bytes |
pointer to a length and the data | b"GET \x00" |
char |
char |
'C' |
bool |
int |
true, false |
void |
void |
function returns only |
| enum | int |
Color.RED |
| enum whose members carry values | pointer to a tagged object | Shape.CIRCLE(1.0) |
| struct | pointer to a C struct | Point(1, 2) |
T[] |
dynamic array | [1, 2, 3] |
map[K, V] |
hash map | {"a": 1} |
func(T, U) R |
function value | func(int n) => n * 2 |
(T, U) |
tuple | (1, "one") |
Number literals
Integers are written in decimal, in hexadecimal after 0x, in octal after
0o, or in binary after 0b; floats have a decimal point, an exponent, or
both. A _ can separate digits anywhere between two of them:
int mask = 0xff
int mode = 0o755
int flags = 0b1010_0001
i64 big = 9_000_000_000
f64 tiny = 1.5e-9
f64 avogadro = 6.022e23An integer literal is an int, 64 bits, so 1 << 40 and
100000 * 100000 are exact; one that does not fit in an int is an
error. Written where a narrower type is expected, a literal must fit it:
u8 b = 300 and i32 n = 3000000000 are errors, not values that wrap
around. int and uint are as wide as i64 and u64 on every system;
the narrower types are for binary data and for C, and arithmetic on them
works as in C, where a value narrower than 32 bits becomes an i32 first.
Conversions
Numbers convert to each other on their own when nothing is lost: an int
can be used where an f64 is expected, and an int where an i32 is, with
the value wrapping around if it does not fit, unless the value is a
literal, which must fit. A float never becomes an
integer on its own, since that would silently drop its fraction:
f64 average = 7.5
int count = average // error: write int(average)
int rounded = int(round(average))A conversion is written with the name of a numeric type, as in int(x),
i64(x), u8(x), or f64(x):
- a float becomes an integer by dropping its fraction, toward zero, and a value that does not fit, or NaN, stops the program with a runtime error;
- an integer becomes a narrower integer by wrapping around, so
u8(300)is 44; - a
charbecomes an integer as its byte code, soint('a')is 97.
For bool, compare instead, as in x != 0.
null is the empty reference. It can initialize or be compared with any
reference type (str, bytes, arrays, maps, and structs):
str value = nullStrings and characters accept these escapes:
| Escape | Meaning |
|---|---|
\n, \t, \r |
line feed, tab, carriage return |
\a, \b, \f, \v |
bell, backspace, form feed, vertical tab |
\\, \", \' |
backslash and quotes |
\e |
the escape character, which starts terminal codes such as colors |
\xHH |
the byte with two hexadecimal digits, such as \x1b; not \x00 |
\u{H...} |
a Unicode character as UTF-8, such as \u{e9} or \u{1F600} |
Any other escape is rejected, and no escape can produce a NUL byte. A char
holds one byte: an escape that yields one byte, or one printable ASCII
character other than ' and \. UTF-8 text can also be written directly in
strings and comments.
void is only valid as a function return type.