Preprocessor

KonsolScript's preprocessor runs before tokenisation: it performs text substitution (#define) and file/plugin inclusion (#include).


#define

Plain word-boundary text substitution before tokenisation:

#define MAX 100
#define PI 3.14159

Var:Number limit = MAX;

#include

Two forms:

Syntax Behaviour
#include "name.ks" Always loads a KonsolScript file
#include "name" Plugin-first: searches for name.dll / .so / .dylib, then libname.dll / .so / .dylib, falls back to name.ks

KonsolScript file includes

#include "lib/utils.ks"
#include "helpers.ks"

Plugin includes

#include "kse_sample"     // loads kse_sample.dll / .so from plugin search paths

Plugin search order for #include "name":

  1. <directory of including file>/plugins/name.dll
  2. <main script root>/plugins/name.dll
  3. Dirs added via engine.addPluginPath() or the --plugin-path CLI flag
  4. MINKS_PLUGIN_PATH env var (colon-separated on Linux/macOS; semicolon on Windows)
  5. ~/.minks/plugins/ (Linux/macOS) — %APPDATA%\minks\plugins\ (Windows)
  6. ./plugins/

If the library is not found, minks falls back to searching for name.ks. If that also fails, a runtime error is raised. Each plugin name is include-guarded — including the same name twice is a no-op.

See Plugin system for the full plugin loading and authoring guide.


Examples

// 26_include.ks — #include multi-file support + include-guard diagnostics
//
// Notes printed to stderr by the include guard (not errors):
//   minks: note: 'math_utils.ks' already included (first included from '26_include.ks'), skipping
//   minks: note: 'math_utils.ks' already included (first included from '26_include.ks'), skipping
//   minks: note: 'lib/math_utils.ks' already included (first included from '26_include.ks'), skipping

// ── 1. Direct include ──────────────────────────────────────────────────────────
#include "lib/math_utils.ks"

Konsol:Print("=== clamp ===");
Var:Number r = clamp(5, 1, 10);
Konsol:Print(r);        // 5
r = clamp(-3, 0, 100);
Konsol:Print(r);        // 0
r = clamp(200, 0, 100);
Konsol:Print(r);        // 100

Konsol:Print("=== max2 ===");
r = max2(7, 3);
Konsol:Print(r);        // 7
r = max2(2, 9);
Konsol:Print(r);        // 9

Konsol:Print("=== sum_range ===");
r = sum_range(1, 5);
Konsol:Print(r);        // 15
r = sum_range(10, 10);
Konsol:Print(r);        // 10

// ── 2. Transitive include (greetings.ks → math_utils.ks) ──────────────────────
// greetings.ks internally includes math_utils.ks.
// Guard fires → note printed to stderr. greet() is still available.

Konsol:Print("=== transitive: greetings -> math_utils ===");
#include "lib/greetings.ks"
Var:String g = greet("world");
Konsol:Print(g);        // Hello, world!
r = max2(100, 200);
Konsol:Print(r);        // 200

// ── 3. Diamond include (stringtools.ks → math_utils.ks, already loaded) ───────
// stringtools.ks also includes math_utils.ks.
// Guard fires again → second note to stderr. All functions remain usable.

Konsol:Print("=== diamond: stringtools -> math_utils ===");
#include "lib/stringtools.ks"
Var:String s = repeat_char("*", 5);
Konsol:Print(s);        // *****
s = repeat_char("-", 0);
Konsol:Print(s);        // (empty string)
s = pad_left("42", 6, "0");
Konsol:Print(s);        // 000042

// ── 4. Direct re-include guard ─────────────────────────────────────────────────
// Same file re-included explicitly. Guard fires → third note to stderr.

Konsol:Print("=== direct re-include guard ===");
#include "lib/math_utils.ks"
r = clamp(50, 0, 100);
Konsol:Print(r);        // 50
r = sum_range(1, 10);
Konsol:Print(r);        // 55

Konsol:Print("done");