# Metaprogramming Deft exposes its own metadata and reflection layer via `@`-decorators, the `meta` accessor, and the `info/*` namespace. Together they cover introspection (what does this value know about itself?) and annotations (what should tooling do with this?). Special forms — the compiler-reserved names that desugar to internal IR — are also documented here. ## Decorators: `@`-tags A function body may carry any number of `@key value` lines. The key becomes metadata; the value is attached. `@doc` is the most common; arbitrary tags work too.
 def greet {|name^string|
    @doc "Print a greeting."
    @since "1.2.0"
    @category :friendly
    echo "Hello, $name!"
} 
`@doc` accepts either a string (joined if multiple) or a structured map:
 def create-user {|name^string email^string|
    @doc {
        :description "Create a user record."
        :params %{
            :name "User's full name"
            :email "Contact email"
        }
        :returns %User
    }
    %User{ :name $name :email $email }
} 
### Retrieving metadata `meta` reads a single key; `info/props` returns the whole metadata map:
 echo [meta $greet "doc"]                       # => "Print a greeting."
echo [meta $greet "since"]                     # => "1.2.0"
echo [info/props $greet]
# => %{ :doc "Print a greeting." :since "1.2.0" :category :friendly } 
### Other places decorators are used | Tag | Used by | |---|---| | `@doc` | Editor hover, REPL help, `info/props`, MCP tool descriptions | | `@rpc true` | Runtime RpcRegistry — exposes fn to `rpc` | | `@command` | CLI subcommand registration | | `@private` / `@internal` | Documentation tools — marks non-public | | `@since` / `@deprecated` | Version tracking | | `@bench` | Marks benchmarks for the runner | ## The `info/*` Namespace `info/*` exposes the runtime's symbol and module tables. | Function | Returns | |---|---| | `info/modules` | List of loaded module names | | `info/defs` | Defs in the current namespace | | `info/vars` | Vars (module locals) in the current namespace | | `info/types` | Registered types | | `info/protocols` | Registered protocols | | `info/props` | Full metadata map for a value | | `info/sig` | Function signature | | `info/source` | Source code of a def (when available) | | `info/resolve` | Resolve a name to its source |
 [info/defs]                                    # => @{ greet create-user ... }
[info/types]                                   # => @{ User Point ... }
[info/protocols]                               # => @{ Drawable Keyable ... }
[info/sig $greet]                              # => function with 1 param
[info/source $greet]                           # => source text 
## Reflection on Values
 [type 42]                                      # => "number"
[type "hi"]                                    # => "string"
[type %User{...}]                              # => "User"
[type @{ 1 2 }]                                # => "list"
[type ^{:a :b}]                                # => "set"

[is? "number" 42]                              # => true
[is? "User" $alice]                            # => true
[satisfies? $p "Drawable"]                     # => true if $p's type impls Drawable
[nil? $x]                                      # => true if nil
[empty? $xs]                                   # => true if empty
[future? $f]                                   # => true if a Future
[keyword? :foo]                                # => true 
## Special Forms These are compiler-reserved names. They're not functions; they desugar to internal IR or trigger specific compiler behaviour. ### Variable binding | Form | Purpose | |---|---| | `def name value` | Module-scoped binding | | `set name value` | Local rebinding | | `set name^type value` | Typed rebinding (validates at runtime) | ### Collection constructors | Form | Purpose | |---|---| | `@{ ... }` | List literal | | `%{ ... }` | Map literal | | `^{ ... }` | Set literal | | `%Tag{ ... }` | Tagged map literal | ### Control flow | Form | Purpose | |---|---| | `if cond { ... } else { ... }` | Conditional | | `match expr { pat => result ... }` | Pattern dispatch | | `for x in $xs { ... }` | Collection iteration | | `while cond { ... }` | Condition loop | | `try { ... } catch e { ... }` | Error handling | | `defer { ... }` | Cleanup on exit | | `return expr` | Early return | | `break` / `continue` | Loop control | | `throw value` | Raise an error | ### Function definitions | Form | Purpose | |---|---| | `def name { \|params\| body }` | Function | | `def name { \|params\| body1 \|params\| body2 }` | Multi-arity function | | `defcoro name { ... }` | Coroutine | | `deftask { body }` | Async task (also a function-position form) | | `defworker "path.dft" ?n` | Persistent worker / pool (function-position form; see [defworker](defworker)) | | `defmacro name { \|params\| body }` | Macro | | `deftype Name %{ ... }` | Record type | | `defprotocol Name %{ ... }` | Protocol spec set | | `defimpl Type Protocol { ... }` | Attach behaviour | | `defmethod Type name { ... }` | Add one method | | `defsuite "name" { ... }` | Test suite | | `deftest "name" { ... }` | Test case | | `defbench "name" { ... }` | Benchmark case | > The following forms appear in some older docs but **do not exist** > in the current language: `defgen`, `defwait`, `defgroup`, `defasync`, > `chan`, `<-`, `select` (channel form), `receive`, `send`. See > [Concurrency](concurrency) for the supported primitives. ### Module system | Form | Purpose | |---|---| | `import "path" as alias` | Load and alias | | `from "path" import @{ names }` | Pull in specific names | | `implements Interface` | Module conformance (checked at load) | | `in-ns "name"` | Switch namespace | ### Operators (arity-locked) | Form | Purpose | |---|---| | `+ - * /` | Arithmetic | | `mod` | Modulo | | `== != < > <= >=` | Comparison | | `and or not` | Boolean | | `& \| ^ << >>` | Bitwise | | `..` | Range (inside patterns and infix) | ### Internal IR forms The compiler emits a few `__`-prefixed IR nodes that you may encounter when reading generated code or macro output: | Form | Purpose | |---|---| | `__make-tagged-map` | Construct a tagged map (used by HTML/SQL blocks) | | `__shell-exec` | Shell capture `[|cmd]` | | `__postfix-*` | Postfix sugar `$x(call)` | | `__capture` | Closure literal | | `__import-file` / `__import` / `__refer` | Module loader hooks | | `__implements` | `implements` desugaring | | `__source` | Source-tracking node | | `__defsuite` / `__deftest` / `__defbench` | Test scaffolding | You don't need to write these directly; they're documented here so macro output and error traces are decipherable. ## Using Metadata in Practice ### Editor / tooling Documentation tools walk `info/defs` and pull `@doc` strings to build API references. The MCP integration (see [MCP](../05-AI/mcp)) uses `@doc` to describe tools exposed to language models. ### Custom dispatch Tag a function with arbitrary metadata, then dispatch on it:
 def handler {|req|
    @route "/users/:id"
    @method :GET
    # ...
}

# Walk all defs, find handlers by their @route metadata
def routes []
for name [info/defs] {
    set fn [info/resolve $name]
    set route [meta $fn "route"]
    if $route { $routes << @{ $route $fn } }
} 
### Runtime versioning
 defn deprecated-op {|x|
    @deprecated "use new-op instead"
    @since "0.3.0"
    # ...
} 
A lint tool can walk `info/defs` and warn on any call to a function tagged `@deprecated`. ## Quick Reference | Form | Purpose | |---|---| | `@key value` (inside def body) | Attach metadata | | `[meta $fn "key"]` | Read one piece of metadata | | `[info/props $fn]` | Read all metadata | | `[info/defs]` / `[info/types]` / `[info/protocols]` | Namespace contents | | `[info/sig $fn]` / `[info/source $fn]` | Function info | | `[type x]` / `[is? "Type" x]` / `[satisfies? x "Protocol"]` | Type reflection |