-
-
Notifications
You must be signed in to change notification settings - Fork 613
Attributes and Directives
Michael Kutowski edited this page Nov 1, 2021
·
12 revisions
-
@(link_name = <string>)
This attribute can be attached to variable and procedure declarations inside aforeign
block. This specifies what the variable/proc is called in the library.
Example:
foreign foo {
@(link_name = "bar")
testbar :: proc(baz: int) ---
}
-
@(link_prefix = <string>)
This attribute can be attached to aforeign
block to specify a prefix to all names. So if functions are prefixed withltb_
in the library is you can attach this and not specify that on the procedure on the odin side. Example:
@(link_prefix = "ltb_")
foreign foo {
testbar :: proc(baz: int) --- // This now refers to ltb_testbar
}
-
@export or @(export=true/false)
-
@(default_calling_convention = <string>)
This attribute can be attached to aforeign
block to specify the default calling convention for all procedures in the block. Example:
@(default_calling_convention = "std")
foreign kernel32 {
@(link_name="LoadLibraryA") load_library_a :: proc(c_str: ^u8) -> Hmodule ---
}
- @(deferred_in=<proc>)
- @(deferred_out=<proc>)
- @(deferred_in_out=<proc>)
-
@(deferred_none=<proc>)
These attributes can be attached to a procedureX
which will be called at the end of the calling scope forX
s caller.
deferred_in
will receive the same parameters as the called proc.deferred_out
will receive the result of the called proc.deferred_in_out
will receive both.deferred_none
will receive no parameters.
baz :: proc() {
fmt.println("In baz")
}
@(deferred_none=baz)
bar :: proc() {
fmt.println("In bar")
}
foo :: proc() {
fmt.println("Entered foo")
bar()
fmt.println("Leaving foo")
}
// Prints:
// Entered foo
// In bar
// Leaving foo
// In baz
-
@(static)
Can be applied to a variable to have it keep its' state even when going out of scope. Same as a static local variable in C.
test :: proc() -> int {
@(static) foo := 0
foo += 1
return foo
}
main :: proc() {
fmt.println(test()) // prints 1
fmt.println(test()) // prints 2
fmt.println(test()) // prints 3
}
-
@(thread_local)
Can be applied to a variable at file scope
@(thread_local) foo: int
-
@(private)
Prevents a top level element from being exported with the package. In Odin elements beginning with '_' will not be exported. This attribute allows you to explicitly prevent something from being exported without naming it with an '_'.
package foo
_this_is_private :: 0
this_is_not :: 1
@private
this_is_also_private :: 2
-
@(deprecated=<string>)
Mark a procedure as deprecated. Runningodin build/run/check
will print out the message for each usage of the deprecated proc.
@(deprecated="'foo' deprecated, use 'bar' instead")
foo :: proc() {
...
}
-
@(builtin)
Marks builtin procs in Odin's "core:runtime" package. Cannot be used in user code. -
@(require_results)
Ensures procedure return values are acknowledged.
@(require_results)
foo :: proc() -> bool {
return true
}
main :: proc() {
foo() // won't compile
_ = foo() // Ok
}
-
#packed
This tag can be applied to struct. By doing so, the Odin compiler will omit padding and preserve the order of fields in a struct. -
#raw_union
This tag can be applied to a struct. Struct's fields will share the same memory space which serves the same functionality asunion
s in C language. Useful when writing bindings especially. -
#align
This tag can be applied to a struct or union. This tag in form#align N
specifies the struct's alignment to N bytes.
Foo :: struct #align 4 {
b: bool,
}
Bar :: union #align 4 {
i32,
u8,
}
-
#no_nil
This tag can be applied to a union to not allow nil values.
A :: union {int, bool}
B :: union #no_nil {int, bool}
Possible states of A:
{} // nil
{int}
{bool}
Possible states of B:
{int} // default state
{bool}
-
#partial
By default allcase
s in anenum
have to be covered. This tag allows to use wantedcase
s
Foo :: enum {
A,
B,
C,
}
test :: proc() {
bar := Foo.A
// All cases required, removing any would result in an error
switch bar {
case .A:
case .B:
case .C:
}
// Partially state wanted cases
#partial switch bar {
case .A:
case .B:
}
}
-
#no_alias
This tag can be applied to a procedure parameter that is a pointer. This is a hint to the compiler that this parameter will not alias other parameters. This is equivalent to C's
__restrict
.
foo :: proc(#no_alias a, b: ^int) {}
-
#caller_location
This tag is used as a function's parameter value. In the following function signature,
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr
loc
is a variable of type Source_Code_Location
(see core/runtime/core.odin
) that is automatically filled with the location of the line of code calling the function (in this case, the line of code calling alloc
).
-
#c_vararg
Used to interface with vararg functions in foreign procedures.
foreign foo {
bar :: proc(n: int, #c_vararg args: ..any) ---
}
-
#optional_ok
Allows skipping the last return parameter, which needs to be a
bool
import "core:fmt"
foo :: proc(x: int) -> (value: int, ok: bool) #optional_ok {
return x + 1, true
}
main :: proc() {
for x := 0; x < 11; x = foo(x) {
fmt.printf("v: %v\n", x)
}
}
-
#type
This tag doesn't serve a functional purpose in the compiler, this is for telling someone reading the code that the expression is a type. The main case is for showing that a procedure signature without a body is a type and not just missing its body, for example:
foo :: #type proc(foo: string)
bar :: struct {
gin: foo,
}
- #bounds_check
-
#no_bounds_check
#bounds_check
and#no_bounds_check
are flags that control Odin's built-in bounds checking of arrays and slices. Any statement, block, or function with one of these flags will have their bounds checking turned on or off, depending on the flag provided. Valid uses of these flags include:
proc_without_bounds_check :: proc() #no_bounds_check {
#bounds_check {
#no_bounds_check fmt.println(os.args[1])
}
}
-
#assert
Assert ran at compile time. -
#defined
Checks if an identifier is defined.
n: int
when #defined(n) { fmt.println("true") }
if #defined(int) { fmt.println("true") }
when #defined(nonexistent_proc) == false { fmt.println("proc was not defined") }
-
#file #line #procedure
Return the current file path, line number, or procedure name, respectively. Used like a constant value.
file_name :: #file
-
#location
Returns aruntime.Source_Code_Location
(seecore/runtime/core.odin
). Can be called with no parameters for current location, or with a parameter for the location of the variable/proc declaration
foo :: proc() {}
main :: proc() {
n: int
fmt.println(#location())
fmt.println(#location(foo))
fmt.println(#location(n))
}
-
#load
Returns a[]u8
of file contents at compile time
foo := #load("path/to/file")
fmt.println(string(foo))
-
#load_or
Returns a[]u8
of file contents at compile time, otherwhise default content when the file wasn't found
foo := #load_or("path/to/file", []u8 { 104, 105 })
fmt.println(string(foo))