Directives - IS4Code/Sona GitHub Wiki

Directives are pieces of extra syntax placed either alone or attached to other elements, which affect the interpretation of the code in a specific way, depending on the kind of the directive used.

The syntax of a directive consists of the # character, followed immediately by the name of the directive and whitespace. If this collides with the usage of the # operator, using whitespace or parentheses after it fixes it.

Inside a directive, the normal parsing rules do not apply:

  • Whitespace is significant and may affect the result of the directive.
  • The directive is terminated by a newline or another #. To prevent it from terminating by a line end, it can be escaped with \.
  • Some directives allow arbitrary expressions, in which case parser rules may also extend them across multiple lines.
  • Some standard keywords may not be recognized, or other directive-specific keywords may be introduced.

Note that while the directive syntax resembles that used by the preprocessor in other languages, there is no separate preprocessing phase ‒ some information is expressible only through a directive, and the parser reacts to it directly.

Attributes

Attributes offer means to attach information to code existing code elements. They come in two forms: local, starting with #:, #item, #type, #method, #property, #return, #param, #field, #event, or #constructor, followed immediately by a code element, and global, using #program, #entry, #assembly, or #module, usable as a top-level statement.

Inside the attribute syntax, using any sorts of parentheses ((…), […], {…}) reverts back to the usual parsing rules within the parentheses, allowing newlines and insignificant whitespace as if outside the attribute. Additionally, a line ending with a comma (,) extends the directive to the next line.

Inline source

Inline F# source can be embedded using #inline. It can be used as a stand-alone statement, expression, type, or pattern, to insert a piece of F# code in its place, up until #endinline.

Pragmas

Pragmas serve to configure the compiler to output slightly different code from parts of its syntax. A pragma directive starts with #pragma, followed by name of the specific pragma and its parameters. Other than affecting the code that follows it, a pragma has no effect on the point of code where it is used itself, basically equivalent to whitespace.

pragma:
  '#pragma' pragma_name pragma_args;

Each individual pragma type has its own state stack, with the top state being the one that currently affects the code. This stack can be manipulated using #pragma push and #pragma pop; using the pragma without these directives always affects the top state.

push

push_pragma:
  '#pragma push' name args;

#pragma push is used to push a new state on top of the stack of the pragma identified by name. Its effect is the same as using #pragma name args, but can be reverted using #pragma pop name.

Example:

#pragma push echo printf
echo "Test"
#pragma pop echo
echo "Test"

This configures the echo pragma to use printf for the next line, and restores it afterwards to the default (printfn).

pop

push_pragma:
  '#pragma pop' name;

#pragma pop is used to remove the last pushed state of name and restore the previous state. It is an error if used without the corresponding prior #pragma push.

echo

echo_fragma:
  '#pragma echo' name;

#pragma echo configures the name of the function used by the subsequent echo statements, such as printf, printfn, eprintf, eprintfn.

newline

newline_pragma:
  '#pragma newline' string;

#pragma newline sets the newline sequence used when outputting non-verbatim strings spanning multiple lines. It takes a string argument, such as "\n" or "\r\n".

tuple, record, option

type_kind_pragma:
  '#pragma' ('tuple' | 'record' | 'option') ('class' | 'struct');

These three pragmas are used to affect what kind of type is used by default for tuples, records, and options, taking a struct or class argument to indicate whether these types should have value or reference semantics.

⚠️ **GitHub.com Fallback** ⚠️