Skip to content

Macros (@)

The @ sigil represents a parse-time dependency. It is not an execution-time "include" statement, but a macro expansion that happens before the script is fully parsed.

Syntax

hank
@ "utils"
@ "path/to/script.hank"

The @ macro strictly requires a String literal path. Passing an unquoted identifier is not allowed.

Expansion Mechanism

When the Parser encounters a @ macro, it performs the following steps:

  1. Request: It requests the raw string content for the path from the Runner.
  2. Parse: It parses the content. The resource must follow the same Universal Task structure as a script.
  3. Inject: It creates an assignment in the current scope, binding the resulting Task value to an identifier derived from the file name.

File Resolution

The Runner is responsible for resolving macro paths. By convention:

  • Relative paths are resolved against the directory of the file currently being processed.
  • If a path has no extension, the Runner should check for .hank.

Recursive Expansion

Macros can include other macros. The Runner's pre-processor resolves these dependencies recursively before parsing.

Circular Dependencies

Compliant Runners must detect circular dependencies (e.g., Task A requires Task B, which requires Task A) and throw a fatal error during the pre-processing phase.

Hoisting Compatibility

Because macro expansion results in assignments, the imported tasks are available for hoisting. You can call an imported task before its @ sigil appears in the file.

hank
() {
  log_print(math_utils.sum(1, 2)) // Valid due to hoisting
  @ "math_utils"
}

Released under the MIT License. Core Specification: Igazine/hank