Skip to content

Commit

Permalink
docs: describe @[c_extern], @[weak], and some usages of the condi…
Browse files Browse the repository at this point in the history
…tional compilation feature `@[if flag?]`
  • Loading branch information
spytheman committed Mar 26, 2024
1 parent 8173424 commit 7b92c7b
Showing 1 changed file with 76 additions and 22 deletions.
98 changes: 76 additions & 22 deletions doc/docs.md
Expand Up @@ -5492,7 +5492,7 @@ An attribute is a compiler instruction specified inside `[]` right before a
function/struct/enum declaration and applies only to the following declaration.

```v
// [flag] enables Enum types to be used as bitfields
// @[flag] enables Enum types to be used as bitfields
@[flag]
enum BitField {
Expand Down Expand Up @@ -5559,7 +5559,7 @@ fn legacy_function() {}
fn legacy_function2() {}
```
```v nofmt
```v globals
// This function's calls will be inlined.
@[inline]
fn inlined_function() {
Expand Down Expand Up @@ -5587,21 +5587,6 @@ fn forever() {
struct Window {
}
// V will not generate this function and all its calls if the provided flag is false.
// To use a flag, use `v -d flag`
@[if debug]
fn foo() {
}
fn bar() {
foo() // will not be called if `-d debug` is not passed
}
// The memory pointed to by the pointer arguments of this function will not be
// freed by the garbage collector (if in use) before the function returns
@[keep_args_alive]
fn C.my_external_function(voidptr, int, voidptr) int
// Calls to following function must be in unsafe{} blocks.
// Note that the code in the body of `risky_business()` will still be
// checked, unless you also wrap it in `unsafe {}` blocks.
Expand All @@ -5624,22 +5609,52 @@ fn risky_business() {
// V's autofree engine will not take care of memory management in this function.
// You will have the responsibility to free memory manually yourself in it.
// Note: it is NOT related to the garbage collector. It will only make the
// -autofree mechanism, ignore the body of that function.
@[manualfree]
fn custom_allocations() {
}
// For C interop only, tells V that the following struct is defined with `typedef struct` in C
@[typedef]
pub struct C.Foo {
// The memory pointed to by the pointer arguments of this function will not be
// freed by the garbage collector (if in use) before the function returns
// For C interop only.
@[keep_args_alive]
fn C.my_external_function(voidptr, int, voidptr) int
// A @[weak] tag tells the C compiler, that the next declaration will be weak, i.e. when linking,
// if there is another declaration of a symbol with the same name (a 'strong' one), it should be
// used instead, *without linker errors about duplicate symbols*.
// For C interop only.
@[weak]
__global abc = u64(1)
// Tell V, that the following global was defined on the C side,
// thus V will not initialise it, but will just give you access to it.
// For C interop only.
@[c_extern]
__global my_instance C.my_struct
struct C.my_struct {
a int
b f64
}
// Tell V that the following struct is defined with `typedef struct` in C.
// For C interop only.
@[typedef]
pub struct C.Foo {}
// Used to add a custom calling convention to a function, available calling convention: stdcall, fastcall and cdecl.
// This list also applies for type aliases (see below).
@[callconv: "stdcall"]
// For C interop only.
@[callconv: 'stdcall']
fn C.DefWindowProc(hwnd int, msg int, lparam int, wparam int)
// Used to add a custom calling convention to a function type aliases.
@[callconv: "fastcall"]
// For C interop only.
@[callconv: 'fastcall']
type FastFn = fn (int) bool
// Windows only:
Expand All @@ -5656,6 +5671,45 @@ fn main() {
## Conditional compilation
The goal of this feature, is to tell V to *not compile* a function, and all its calls, in the final
executable, if a provided custom flag is not passed.
V will still type check the function and all its calls, *even* if they will not be present in the
final executable, due to the passed -d flags.
In order to see it in action, run the following example with `v run example.v` once,
and then a second time with `v -d trace_logs example.v`:
```v
@[if trace_logs ?]
fn elog(s string) {
eprintln(s)
}
fn main() {
elog('some expression: ${2 + 2}') // such calls will not be done *at all*, if `-d trace_logs` is not passed
println('hi')
elog('finish')
}
```
Conditional compilation, based on custom flags, can also be used to produce slightly different
executables, which share the majority of the same code, but where some of the logic, is needed
only some of the time, for example a network server/client program can be written like so:
```v ignore
fn act_as_client() { ... }
fn act_as_server() { ... }
fn main() {
$if as_client ? {
act_as_client()
}
$if as_server ? {
act_as_server()
}
}
```
To generate a `client.exe` executable do: `v -d as_client -o client.exe .`
To generate a `server.exe` executable do: `v -d as_server -o server.exe .`
### Compile time pseudo variables
V also gives your code access to a set of pseudo string variables,
Expand Down

0 comments on commit 7b92c7b

Please sign in to comment.