zig/doc/langref.md

619 lines
18 KiB
Markdown
Raw Normal View History

2015-12-10 06:20:31 +08:00
# Language Reference
## Grammar
```
Root = many(TopLevelItem) "EOF"
2015-12-10 06:20:31 +08:00
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl)
TypeDecl = "type" Symbol "=" TypeExpr ";"
ErrorValueDecl = "error" Symbol ";"
GlobalVarDecl = VariableDeclaration ";"
2016-01-05 07:57:22 +08:00
VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"
StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl)
StructField = Symbol option(":" Expression) ",")
2016-01-11 02:48:54 +08:00
UseDecl = "use" Expression ";"
2015-12-10 06:20:31 +08:00
ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2015-12-10 06:20:31 +08:00
FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
2015-12-10 06:20:31 +08:00
VisibleMod = "pub" | "export"
2015-12-10 06:20:31 +08:00
FnDef = option("inline" | "extern") FnProto Block
2015-12-10 06:20:31 +08:00
ParamDeclList = "(" list(ParamDecl, ",") ")"
2015-12-10 06:20:31 +08:00
ParamDecl = option("noalias" | "inline") option(Symbol ":") TypeExpr | "..."
2015-12-10 06:20:31 +08:00
Block = "{" list(option(Statement), ";") "}"
2015-12-10 06:20:31 +08:00
Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression
2015-12-10 06:20:31 +08:00
Label = Symbol ":"
2015-12-10 06:20:31 +08:00
Expression = BlockExpression | NonBlockExpression
2015-12-10 06:20:31 +08:00
2016-09-08 12:24:48 +08:00
TypeExpr = PrefixOpExpression | "var"
NonBlockExpression = ReturnExpression | AssignmentExpression
2015-12-11 06:34:38 +08:00
AsmExpression = "asm" option("volatile") "(" String option(AsmOutput) ")"
2015-12-11 06:34:38 +08:00
AsmOutput = ":" list(AsmOutputItem, ",") option(AsmInput)
2015-12-11 06:34:38 +08:00
AsmInput = ":" list(AsmInputItem, ",") option(AsmClobbers)
2015-12-11 06:34:38 +08:00
AsmOutputItem = "[" Symbol "]" String "(" (Symbol | "->" TypeExpr) ")"
2015-12-11 18:55:26 +08:00
AsmInputItem = "[" Symbol "]" String "(" Expression ")"
2015-12-11 18:55:26 +08:00
AsmClobbers= ":" list(String, ",")
2015-12-10 06:20:31 +08:00
UnwrapExpression = BoolOrExpression (UnwrapMaybe | UnwrapError) | BoolOrExpression
2016-02-07 10:28:11 +08:00
UnwrapMaybe = "??" Expression
2016-01-26 04:53:40 +08:00
UnwrapError = "%%" option("|" Symbol "|") Expression
2016-01-26 04:53:40 +08:00
AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
2015-12-13 09:17:27 +08:00
AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
2015-12-10 06:20:31 +08:00
BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression
2015-12-25 05:37:43 +08:00
SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
2015-12-10 06:20:31 +08:00
SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" Symbol "|") Expression ","
SwitchItem = Expression | (Expression "..." Expression)
2015-12-10 06:20:31 +08:00
WhileExpression = option("inline") "while" "(" Expression option(";" Expression) ")" Expression
ForExpression = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") Expression
BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
ReturnExpression = option("%" | "?") "return" option(Expression)
2015-12-10 06:20:31 +08:00
Defer = option("%" | "?") "defer" option(Expression)
IfExpression = IfVarExpression | IfBoolExpression
2015-12-27 06:05:27 +08:00
IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
2015-12-10 06:20:31 +08:00
IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
2015-12-10 06:20:31 +08:00
Else = "else" Expression
2015-12-10 06:20:31 +08:00
BoolAndExpression = ComparisonExpression "&&" BoolAndExpression | ComparisonExpression
2015-12-10 06:20:31 +08:00
ComparisonExpression = BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression
2015-12-10 06:20:31 +08:00
ComparisonOperator = "==" | "!=" | "<" | ">" | "<=" | ">="
2015-12-10 06:20:31 +08:00
BinaryOrExpression = BinaryXorExpression "|" BinaryOrExpression | BinaryXorExpression
2015-12-10 06:20:31 +08:00
BinaryXorExpression = BinaryAndExpression "^" BinaryXorExpression | BinaryAndExpression
2015-12-10 06:20:31 +08:00
BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpression
2015-12-10 06:20:31 +08:00
BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
2015-12-10 06:20:31 +08:00
BitShiftOperator = "<<" | ">>" | "<<%"
2015-12-10 06:20:31 +08:00
AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
2015-12-10 06:20:31 +08:00
AdditionOperator = "+" | "-" | "++" | "+%" | "-%"
2015-12-10 06:20:31 +08:00
MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
2015-12-10 06:20:31 +08:00
MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
2015-12-10 06:20:31 +08:00
PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
2015-12-10 06:20:31 +08:00
SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
FieldAccessExpression = "." Symbol
2015-12-10 06:20:31 +08:00
FnCallExpression = "(" list(Expression, ",") ")"
2015-12-10 06:20:31 +08:00
ArrayAccessExpression = "[" Expression "]"
2015-12-10 06:20:31 +08:00
SliceExpression = "[" Expression "..." option(Expression) "]" option("const")
ContainerInitExpression = "{" ContainerInitBody "}"
2016-01-14 09:15:51 +08:00
ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
2016-01-14 09:15:51 +08:00
StructLiteralField = "." Symbol "=" Expression
2015-12-10 06:20:31 +08:00
PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
2015-12-24 15:00:23 +08:00
PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol)
2015-12-24 15:00:23 +08:00
ArrayType = "[" option(Expression) "]" option("const") TypeExpr
2015-12-10 06:20:31 +08:00
GotoExpression = "goto" Symbol
2015-12-10 06:20:31 +08:00
GroupedExpression = "(" Expression ")"
2015-12-10 06:20:31 +08:00
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this"
2015-12-10 06:20:31 +08:00
```
## Operator Precedence
```
x() x[] x.y
!x -x ~x *x &x ?x %x %%x
x{}
2015-12-10 06:20:31 +08:00
* / %
+ - ++
2015-12-10 06:20:31 +08:00
<< >>
&
^
|
== != < > <= >=
&&
||
2016-01-26 04:53:40 +08:00
?? %%
2015-12-13 09:17:27 +08:00
= *= /= %= += -= <<= >>= &= ^= |= &&= ||=
2015-12-10 06:20:31 +08:00
```
2016-01-20 16:27:53 +08:00
## Types
### Numeric Types
```
Type name C equivalent Description
i8 int8_t signed 8-bit integer
u8 uint8_t unsigned 8-bit integer
2016-01-20 16:27:53 +08:00
i16 int16_t signed 16-bit integer
u16 uint16_t unsigned 16-bit integer
2016-01-20 16:27:53 +08:00
i32 int32_t signed 32-bit integer
u32 uint32_t unsigned 32-bit integer
2016-01-20 16:27:53 +08:00
i64 int64_t signed 64-bit integer
u64 uint64_t unsigned 64-bit integer
2016-01-20 16:27:53 +08:00
isize intptr_t signed pointer sized integer
usize uintptr_t unsigned pointer sized integer
2016-01-20 16:27:53 +08:00
c_short short for ABI compatibility with C
c_ushort unsigned short for ABI compatibility with C
c_int int for ABI compatibility with C
c_uint unsigned int for ABI compatibility with C
c_long long for ABI compatibility with C
c_ulong unsigned long for ABI compatibility with C
c_longlong long long for ABI compatibility with C
c_ulonglong unsigned long long for ABI compatibility with C
c_long_double long double for ABI compatibility with C
c_void void for ABI compatibility with C
2016-05-06 08:19:01 +08:00
f32 float 32-bit floating point
f64 double 64-bit floating point
2016-01-20 16:27:53 +08:00
```
### Boolean Type
2016-01-20 16:27:53 +08:00
The boolean type has the name `bool` and represents either true or false.
### Function Type
2016-01-20 16:27:53 +08:00
TODO
### Fixed-Size Array Type
Example: The string `"aoeu"` has type `[4]u8`.
The size is known at compile time and is part of the type.
### Slice Type
A slice can be obtained with the slicing syntax: `array[start...end]`
Example: `"aoeu"[0...2]` has type `[]u8`.
2016-01-20 16:27:53 +08:00
2016-01-23 07:05:29 +08:00
### Struct Type
2016-01-20 16:27:53 +08:00
TODO
2016-01-23 07:05:29 +08:00
### Enum Type
TODO
### Maybe Type
TODO
### Pure Error Type
TODO
### Error Union Type
2016-01-23 07:05:29 +08:00
TODO
### Pointer Type
2016-01-20 16:27:53 +08:00
TODO
2015-12-10 06:20:31 +08:00
2016-01-20 16:27:53 +08:00
### Unreachable Type
2016-01-20 16:27:53 +08:00
The unreachable type has the name `unreachable`. TODO explanation
2015-12-10 06:20:31 +08:00
2016-01-20 16:27:53 +08:00
### Void Type
The void type has the name `void`. void types are zero bits and are omitted
from codegen.
2015-12-10 06:20:31 +08:00
2016-01-20 16:27:53 +08:00
## Expressions
### Literals
#### Character and String Literals
2016-01-20 16:27:53 +08:00
```
Literal Example Characters Escapes Null Term Type
2016-01-20 16:27:53 +08:00
Byte 'H' All ASCII Byte No u8
UTF-8 Bytes "hello" All Unicode Byte & Unicode No [5]u8
UTF-8 C string c"hello" All Unicode Byte & Unicode Yes &const u8
2016-01-20 16:27:53 +08:00
```
2016-05-02 05:53:48 +08:00
### Escapes
Escape | Name
----------|-------------------------------------------------------------------
\n | Newline
\r | Carriage Return
\t | Tab
\\ | Backslash
\' | Single Quote
\" | Double Quote
\xNN | hexadecimal 8-bit character code (2 digits)
\uNNNN | hexadecimal 16-bit Unicode character code UTF-8 encoded (4 digits)
\UNNNNNN | hexadecimal 24-bit Unicode character code UTF-8 encoded (6 digits)
Note that the maximum valid Unicode point is 0x10ffff.
##### Multiline String Literals
Multiline string literals have no escapes and can span across multiple lines.
To start a multiline string literal, use the `\\` token. Just like a comment,
the string literal goes until the end of the line. The end of the line is not
included in the string literal.
However, if the next line begins with `\\` then a newline is appended and
the string literal continues.
Example:
2016-01-20 16:27:53 +08:00
```zig
const hello_world_in_c =
\\#include <stdio.h>
\\
\\int main(int argc, char **argv) {
\\ printf("hello world\n");
\\ return 0;
\\}
;
2016-01-20 16:27:53 +08:00
```
For a multiline C string literal, prepend `c` to each `\\`. Example:
```zig
const c_string_literal =
c\\#include <stdio.h>
c\\
c\\int main(int argc, char **argv) {
c\\ printf("hello world\n");
c\\ return 0;
c\\}
;
2016-01-20 16:27:53 +08:00
```
In this example the variable `c_string_literal` has type `&const char` and
has a terminating null byte.
#### Number Literals
Number literals | Example | Exponentiation
--------------------|-------------|--------------
Decimal integer | 98222 | N/A
Hex integer | 0xff | N/A
Octal integer | 0o77 | N/A
Binary integer | 0b11110000 | N/A
Floating point | 123.0E+77 | Optional
Hex floating point | 0x103.70p-5 | Optional
2016-01-20 16:27:53 +08:00
### Identifiers
2016-01-20 16:27:53 +08:00
TODO
### Declarations
2016-01-20 16:27:53 +08:00
Declarations have type `void`.
#### Function Declarations
2016-01-20 16:27:53 +08:00
TODO
#### Variable Declarations
2016-01-20 16:27:53 +08:00
TODO
#### Struct Declarations
2016-01-20 16:27:53 +08:00
TODO
#### Enum Declarations
2016-01-20 16:27:53 +08:00
TODO
## Built-in Functions
2016-05-19 07:59:55 +08:00
Built-in functions are prefixed with `@`. Remember that the `inline` keyword on
a parameter means that the parameter must be known at compile time.
2016-01-20 16:27:53 +08:00
2016-05-19 07:59:55 +08:00
### @typeof(expression) -> type
2016-05-19 07:59:55 +08:00
This function returns a compile-time constant, which is the type of the
expression passed as an argument. The expression is *not evaluated*.
2016-01-20 16:27:53 +08:00
2016-05-19 07:59:55 +08:00
### @sizeof(inline T: type) -> (number literal)
2016-05-19 07:59:55 +08:00
This function returns the number of bytes it takes to store T in memory.
The result is a target-specific compile time constant.
### @alignof(inline T: type) -> (number literal)
This function returns the number of bytes that this type should be aligned to
for the current target.
The result is a target-specific compile time constant.
2016-01-20 16:27:53 +08:00
### Overflow Arithmetic
2016-05-19 07:59:55 +08:00
These functions take an integer type, two variables of the specified type,
and a pointer to memory of the specified type where the result is stored.
2016-01-20 16:27:53 +08:00
2016-05-19 07:59:55 +08:00
The functions return a boolean value: true if overflow or underflow occurred,
false otherwise.
2016-01-20 16:27:53 +08:00
```
2016-05-19 07:59:55 +08:00
Function Operation
@addWithOverflow(inline T: type, a: T, b: T, result: &T) -> bool *x = a + b
@subWithOverflow(inline T: type, a: T, b: T, result: &T) -> bool *x = a - b
@mulWithOverflow(inline T: type, a: T, b: T, result: &T) -> bool *x = a * b
@shlWithOverflow(inline T: type, a: T, b: T, result: &T) -> bool *x = a << b
2016-05-19 07:59:55 +08:00
```
### @memset(dest: &T, c: u8, byte_count: usize)
2016-05-19 07:59:55 +08:00
This function sets a region of memory to `c`. `dest` is a pointer.
This function is a low level intrinsic with no safety mechanisms. Most higher
level code will not use this function, instead using something like this:
```zig
for (destSlice) |*b| *b = c;
2016-05-19 07:59:55 +08:00
```
### @memcpy(noalias dest: &T, noalias source: &const T, byte_count: usize)
2016-05-19 07:59:55 +08:00
This function copies bytes from one region of memory to another. `dest` and
`source` are both pointers and must not overlap.
This function is a low level intrinsic with no safety mechanisms. Most higher
level code will not use this function, instead using something like this:
```zig
const mem = @import("std").mem;
mem.copy(destSlice, sourceSlice);
2016-05-19 07:59:55 +08:00
```
### @breakpoint()
This function inserts a platform-specific debug trap instruction which causes
debuggers to break there.
This function is only valid within function scope.
### @returnAddress()
2016-05-19 07:59:55 +08:00
This function returns a pointer to the return address of the current stack
frame.
The implications of this are target specific and not consistent across
all platforms.
This function is only valid within function scope.
### @frameAddress()
2016-05-19 07:59:55 +08:00
This function returns the base pointer of the current stack frame.
The implications of this are target specific and not consistent across all
platforms. The frame address may not be available in release mode due to
aggressive optimizations.
This function is only valid within function scope.
### @maxValue(inline T: type) -> (number literal)
2016-05-19 07:59:55 +08:00
This function returns the maximum integer value of the integer type T.
The result is a compile time constant. For some types such as `c_long`, the
result is marked as depending on a compile variable.
### @minValue(inline T: type) -> (number literal)
2016-05-19 07:59:55 +08:00
This function returns the minimum integer value of the integer type T.
The result is a compile time constant. For some types such as `c_long`, the
result is marked as depending on a compile variable.
### @memberCount(inline T: type) -> (number literal)
2016-05-19 07:59:55 +08:00
This function returns the number of enum values in an enum type.
The result is a compile time constant.
### @import(inline path: []u8) -> (namespace)
This function finds a zig file corresponding to `path` and imports all the
public top level declarations into the resulting namespace.
`path` can be a relative or absolute path, or it can be the name of a package,
such as "std".
This function is only valid at top level scope.
### @cImport(expression) -> (namespace)
2016-05-19 07:59:55 +08:00
This function parses C code and imports the functions, types, variables, and
compatible macro definitions into the result namespace.
`expression` is interpreted at compile time. The builtin functions
`@c_include`, `@c_define`, and `@c_undef` work within this expression,
appending to a temporary buffer which is then parsed as C code.
This function is only valid at top level scope.
### @cInclude(inline path: []u8)
2016-05-19 07:59:55 +08:00
This function can only occur inside `@c_import`.
This appends `#include <$path>\n` to the `c_import` temporary buffer.
### @cDefine(inline name: []u8, value)
2016-05-19 07:59:55 +08:00
This function can only occur inside `@c_import`.
This appends `#define $name $value` to the `c_import` temporary buffer.
### @cUndef(inline name: []u8)
2016-05-19 07:59:55 +08:00
This function can only occur inside `@c_import`.
This appends `#undef $name` to the `c_import` temporary buffer.
### @compileVar(inline name: []u8) -> (varying type)
2016-05-19 07:59:55 +08:00
This function returns a compile-time variable. There are built in compile
variables:
* "is_big_endian" `bool` - either `true` for big endian or `false` for little endian.
* "is_release" `bool`- either `true` for release mode builds or `false` for debug mode builds.
* "is_test" `bool`- either `true` for test builds or `false` otherwise.
* "os" `@OS` - use `zig targets` to see what enum values are possible here.
* "arch" `@Arch` - use `zig targets` to see what enum values are possible here.
* "environ" `@Environ` - use `zig targets` to see what enum values are possible here.
Build scripts can set additional compile variables of any name and type.
The result of this function is a compile time constant that is marked as
depending on a compile variable.
### @constEval(expression) -> @typeof(expression)
2016-05-19 07:59:55 +08:00
This function wraps an expression and generates a compile error if the
expression is not known at compile time.
The result of the function is the result of the expression.
2016-11-22 02:27:44 +08:00
### @ctz(x: T) -> T
2016-05-19 07:59:55 +08:00
This function counts the number of trailing zeroes in x which is an integer
type T.
2016-11-22 02:27:44 +08:00
### @clz(x: T) -> T
2016-05-19 07:59:55 +08:00
This function counts the number of leading zeroes in x which is an integer
type T.
### @errorName(err: error) -> []u8
2016-05-19 07:59:55 +08:00
This function returns the string representation of an error. If an error
declaration is:
```zig
error OutOfMem;
2016-01-20 16:27:53 +08:00
```
2016-05-19 07:59:55 +08:00
Then the string representation is "OutOfMem".
If there are no calls to `@err_name` in an entire application, then no error
name table will be generated.
### @embedFile(inline path: []u8) -> [X]u8
2016-05-19 07:59:55 +08:00
This function returns a compile time constant fixed-size array with length
equal to the byte count of the file given by `path`. The contents of the array
are the contents of the file.
### @cmpxchg(ptr: &T, cmp: T, new: T, success_order: MemoryOrder, fail_order: MemoryOrder) -> bool
This function performs an atomic compare exchange operation.
### @fence(order: MemoryOrder)
The `fence` function is used to introduce happens-before edges between operations.
### @divExact(a: T, b: T) -> T
2015-12-10 06:20:31 +08:00
2016-05-19 07:59:55 +08:00
This function performs integer division `a / b` and returns the result.
The caller guarantees that this operation will have no remainder.
In debug mode, a remainder causes a panic. In release mode, a remainder is
undefined behavior.
### @truncate(inline T: type, integer) -> T
This function truncates bits from an integer type, resulting in a smaller
integer type.
The following produces a crash in debug mode and undefined behavior in
release mode:
```zig
const a: u16 = 0xabcd;
const b: u8 = u8(a);
```
However this is well defined and working code:
```zig
const a: u16 = 0xabcd;
const b: u8 = @truncate(u8, a);
// b is now 0xcd
```
### @compileError(inline msg: []u8)
2016-05-19 07:59:55 +08:00
This function, when semantically analyzed, causes a compile error with the message `msg`.
2016-05-19 07:59:55 +08:00
There are several ways that code avoids being semantically checked, such as using `if`
or `switch` with compile time constants, and inline functions.
2015-12-10 06:20:31 +08:00
### @intType(inline is_signed: bool, inline bit_count: u8) -> type
This function returns an integer type with the given signness and bit count.