IlluLang Logo

IlluLang

Intent-Oriented Programming in IlluLang

Intent-oriented programming models behavior around goals (intents) rather than direct control flow. Instead of calling a function by name, you declare an intent and register one or more handlers that can satisfy it. The runtime chooses which handler(s) to run based on priority and optional guard conditions. For the rest of the language (types, functions, control flow), see SYNTAX.

Core Concepts

  • Intent: A named goal such as greet, fetch_data, or validate_input.
  • Handler: A block of code that can fulfill an intent. Multiple handlers can exist for the same intent.
  • Achieve: The act of requesting an intent to be fulfilled.

IlluLang keeps handlers decoupled from call sites, which makes it easier to add new behavior or override existing behavior without changing the callers.

Declaring Handlers

Use the intent keyword to register a handler. Handlers can specify:

  • priority: higher values run first
  • when: a condition that must be truthy for the handler to run
  • Typed parameters: optional base-type annotations (int, float, bool, string, array, dict, matrix, function)

Example:

intent greet(who) priority 10 {
  display("High priority hello " + who)
  return true
}

intent greet(who) priority 5 {
  display("Fallback hello " + who)
  return true
}

intent greet_typed(who: string) priority 12 {
  display("Typed hello " + who)
  return true
}

Achieving Intents

There are two ways to achieve an intent:

  • Statement form (prints the return value):
achieve greet("Alice")
  • Expression form (returns the handler result):
var ok = achieve("greet", "Alice")

Execution Rules

When achieve is called:

  1. All handlers for the intent are collected and sorted by descending priority.
  2. Each handler is evaluated in order: - If it has a when clause, the condition is evaluated first. - If when is falsy, the handler is skipped. - Otherwise, the handler runs.
  3. If a handler returns a truthy value, execution stops.
  4. The expression form returns the last truthy handler result, or 0 if none were truthy.

If a handler parameter is annotated, that handler is skipped when the runtime argument type does not match.

Truthiness rules are the same as the rest of the language: non-zero numbers, true, and non-empty strings are truthy.

Handler Chaining Control

Handlers can explicitly control chaining with halt or continue:

intent route(msg) priority 10 {
  if (len(msg) > 100) { halt }
  continue
}
  • halt stops handler evaluation immediately.
  • continue skips to the next handler, ignoring the current handler's return value.

Fallback Handler (otherwise)

Use an otherwise block to define a fallback when no handler matches or all are falsy:

otherwise route(msg) {
  display("No handler matched")
  return true
}

Weighted Scoring

Handlers can add a dynamic score to the base priority:

intent route(msg) priority 5 score (len(msg) * 0.1) {
  return true
}

The effective ordering is priority + score.

Introspection

Two built-ins provide runtime visibility:

var names = intents()
var hs = handlers("route")
  • intents() returns an array of intent names.
  • handlers(name) returns an array of handler metadata dicts.

Timeouts

You can bound handler evaluation time with within:

achieve route(msg) within 200ms
var ok = achieve("route", msg) within 1s

Guarding with when

when lets a handler opt out based on runtime conditions:

intent process(data) when (starts_with(type(data), "array")) {
  display("Processing array")
  return true
}

intent process(data) {
  display("Fallback processor")
  return true
}

Why Use Intents?

  • Decoupling: Callers do not need to know which handler will run.
  • Extensibility: Add new handlers without changing existing code.
  • Policy control: Priorities let you override behavior cleanly.
  • Conditional routing: when expressions can choose specialized logic.

Practical Patterns

  • Feature overrides: Add a high-priority handler to replace behavior.
  • Fallbacks: Keep a low-priority handler as a default path.
  • Validation pipelines: Use multiple handlers where each one can stop the chain.

Notes and Limitations

  • Handlers execute in their own lexical frame.
  • The statement form prints the result; use the expression form when you need the value.
  • Handlers should return truthy values to stop further processing.
  • Internal handler control values (return, halt, continue) are frame-local and do not leak into caller frames.

Generator Intent Handlers

Intent handlers can use yield to produce multiple values. When a handler body contains yield, the yielded values are collected and returned as an array:

intent range_squares(n) priority 10 {
  var i = 0
  while i < n {
    yield i * i
    i = i + 1
  }
}

var squares = achieve("range_squares", 5)
display(squares)  ## [0, 1, 4, 9, 16]

Generator support works in both regular intent handlers and otherwise fallback handlers.

Async Intents

Use achieve_async to schedule intent dispatch for deferred execution:

intent compute(x) priority 10 { return x * x + 1 }

var t1 = achieve_async("compute", 5)
var t2 = achieve_async("compute", 10)

## Execute when needed:
var r1 = await(t1)      ## 26
var r2 = await(t2)      ## 101

## Or batch with await_all:
var t3 = achieve_async("compute", 3)
var t4 = achieve_async("compute", 7)
var all = await_all(t3, t4)  ## [10, 50]

achieve_async returns a task ID (int) that is compatible with await() and await_all(), just like async() tasks.

1.0 Intent Compatibility Contract

The following intent semantics are part of the stable contract (as of the current VERSION):

  • Handler ordering is deterministic: handlers are sorted by effective score (priority + score) descending.
  • Equal effective score preserves registration order (earlier registered handler runs first).
  • when is evaluated per handler before execution; falsy when skips that handler.
  • Typed handler parameters are enforced at runtime; non-matching arguments skip that handler.
  • halt stops further handler evaluation immediately.
  • continue skips to the next handler, regardless of current handler return value.
  • otherwise runs only when no prior handler produced a truthy result and no timeout occurred.
  • within enforces a hard execution deadline for intent evaluation; timeout returns 0.

If you want a deep dive into the language surface, see SYNTAX.html.