Modules

Turn's module system provides code organization and reuse through a straightforward import mechanism. Modules are resolved at compile time, compiled once, and cached for the lifetime of the program.


Use Declarations

To import a module, use the use keyword with a string path. The imported module is bound to a local variable, giving you explicit control over naming and scope.

modules.tn
let print = use "std/print";
let http = use "std/http";

call("echo", "Modules loaded successfully");

Each use declaration loads the module's exports into a namespace bound to the specified variable. You access the module's functions and values through this binding — there is no implicit global pollution.


Standard Library

Turn ships with a small set of standard library modules that cover the most common operations. The standard library is intentionally minimal — it provides essential utilities without creating framework lock-in.

ModulePurpose
std/printFormatted output utilities for debugging and logging.
std/httpHTTP client tools for making GET and POST requests to external APIs.
std/jsonJSON serialization and deserialization. json_parse converts a string to a Turn value; json_stringify converts a value to a string.
std/mathMathematical functions including arithmetic helpers, rounding, and random number generation.
std/timeTimestamp retrieval and duration computation for scheduling and time-aware agent behavior.

Module Resolution

When the compiler encounters a use declaration, it searches for the module source file in the following order:

  1. Relative path. The compiler first checks relative to the directory containing the current source file. This allows project-local modules to be imported without any configuration.
  2. Standard library. If the path begins with std/, the compiler looks in the Turn standard library directory bundled with the Turn binary.
  3. Module path. The compiler checks each directory listed in the TURN_MODULE_PATH environment variable, separated by colons. This allows teams to share module libraries across projects.

NOTE

Modules are loaded and compiled exactly once. If two files import the same module, they share the compiled representation. Circular imports are detected during semantic analysis and rejected with a clear error message indicating the cycle.


Module Authoring

A module is simply a Turn source file (.tn) that evaluates to a value — typically a map or struct containing the module's public API. Any valid Turn expression can serve as a module's export value.

my_utils.tn
// A module that exports a map of utility functions
{
greet: turn(name: Str) -> Str {
  return "Hello, " + name;
},
double: turn(n: Num) -> Num {
  return n + n;
}
}

Consumers import this module with let utils = use "./my_utils"; and then call utils.greet("Turn") or utils.double(21).