Built-in Compilation Flags
The Cangjie language provides predefined compilation flags that can be used to control the behavior of the Cangjie compiler during compilation.
Source Code Location
Cangjie offers several built-in compilation flags to obtain the location of the source code during compilation.
- After
@sourcePackage()is expanded, it becomes a literal of theStringtype, which records the name of the package containing the source code where the flag is located. - After
@sourceFile()is expanded, it becomes a literal of theStringtype, which records the name of the file containing the source code where the flag is located. - After
@sourceLine()is expanded, it becomes a literal of theInt64type, which records the source code line where the flag is located.
These compilation flags can be used in any expressions, as long as they meet the type check rules. An example is provided below:
func test1() {
let s: String = @sourceFile() // The value of `s` is the current source file name
}
func test2(n!: Int64 = @sourceLine()) { /* at line 5 */
// The default value of `n` is the source file line number of the definition of `test2`
println(n) // print 5
}
Conditional Compilation
Conditional compilation uses the @When tag. It is a technology that selectively compiles different code snippets in program code based on specific conditions. The main uses of conditional compilation include:
- Platform adaptation: Enables selective code compilation based on the current compilation environment, facilitating cross-platform compatibility.
- Functionality selection: Code can be compiled selectively based on different requirements to implement flexible functionality configuration.
- Debugging support: Supports compiling code in debug mode to improve program performance and security. For example, compiling debug information or logging code in debug mode, while excluding them in release versions.
- Performance optimization: Enables selective compilation based on predefined conditions to improve program performance.
For details about conditional compilation, see Conditional Compilation.
@FastNative
To enhance performance when interoperating with the C language, Cangjie provides the @FastNative tag to optimize C function calls. Note that @FastNative can be used only for functions declared by foreign.
An example usage is provided below:
@FastNative
foreign func strlen(str: CPointer<UInt8>): UIntNative
When using @FastNative to modify the foreign function, ensure that the corresponding C function meets the following requirements:
- The overall execution time of the function should not be too long. For example, the function should not contain large loops or produce blocking, such as calling functions like
sleepandwait. - The Cangjie method cannot be called in the function.
@Frozen
The @Frozen flag can be used to modify functions and properties. If you are sure that the internal implementation of a function or property will not be modified in later versions, you can use @Frozen to mark it. This flag represents the developer's commitment to the evolution of the function or property in later versions. If a function or property is marked with @Frozen, its signature and function body cannot be changed in later versions. This means that with the same compiler and compilation options, the function or property will generate the same products in source and target code versions.
@Frozen can be used to modify:
- Global functions
- Functions in classes, structures, interfaces, extensions, and enums
- Properties in classes, interfaces, and extensions
@Frozen cannot be used to modify:
- Other types of declarations except functions and properties
- Nested functions
- Expressions
Examples:
@Frozen
public func test(): Unit {}
public class testClass {
@Frozen
public func testFunc(): Unit {}
@Frozen
public prop testProp: Unit {
get() {}
}
}
@Attribute
Cangjie provides the built-in @Attribute tag, which allows you to mark a declaration by setting an attribute value for it. The attribute value can be an identifier or string. In the following example, the State attribute of the identifier type is added to the cnt variable, and the "Binding" attribute of the string type is added to the bcnt variable.
@Attribute[State] var cnt = 0 // identifier
@Attribute["Binding"] var bcnt = 0 // string
In addition, the std.ast package in the standard library provides the getAttrs() method for obtaining node attributes and the hasAttr(attrs: String) method for determining whether the current node has an attribute. The following is an example:
The macro is defined as follows:
public macro Component(input: Tokens): Tokens {
var varDecl = parseDecl(input)
if (varDecl.hasAttr("State")) { //: If the node is marked with an attribute and the value is "State", true is returned. Otherwise, false is returned.
var attrs = varDecl.getAttrs() // A group of tokens is returned.
println(attrs[0].value)
}
return input
}
The macro is called as follows:
@Component(
@Attribute[State] var cnt = 0
)
@Deprecated
@Deprecated indicates that the API is deprecated. Although it is available for the time being, it will be removed or modified in the future. Developers are advised not to call this API. For example:
@Deprecated["Replaced by boo", since: "1.3.4"]
func foo() {}
main() {
foo()
}
The compiler provides the following warning information:
warning: The 'foo' function is deprecated since 1.3.4 and replaced by boo.
==> file.cj:5:5:
|
5 | foo()
| ^^^ deprecated
|
# note: this warning can be suppressed by setting the compiler option `-Woff deprecated`
1 warning generated, 1 warning printed.
@Deprecated user-defined macros can be applied to the following declarations:
- Classes, interfaces, structures, enums, and enum constructors
- Top-level (global) functions or variables
- Static or non-static member functions, member variables, properties, and property setters
- Operator functions
- Extended member functions, static functions, properties, or property setters
- Functions declared in the foreign block or foreign functions
- Constructors and primary constructors
- Abstract functions and properties
- Type aliases (including associated types)
- Named parameters of functions with default parameters
- const variables and functions
- Macro definitions
- Annotation class
@Deprecated Parameters
message: String- Describes why a declaration is deprecated and how to migrate it.since!:?String- Version since which it is deprecated.strict!: Bool- Default value:false. If an API is modified by this flag, a warning will be triggered where the API is called. If this parameter is set totrue, a compilation error is triggered.
@Deprecated["Use Macro2", since: "1990", strict: true]
public macro Macro(input: Tokens): Tokens {
return input
}