Descriptors

A descriptor is a short text attached to any value. Descriptors never
affect behavior — they only explain what a value or member is for. They show
up in info() and help() so you can explore a value’s contents without
guessing.

Attaching a descriptor

In Scrii, the -> operator attaches a description to any value:

var version = "0.1.0"
version -> "the language version"

-> works at statement level: on its own line (or chained onto a
declaration, below). It is not an expression operator — it cannot appear
inside calls, parentheses, return, or literals (info(7 -> "seven") and
return 5 -> "five" are parse errors). The value keeps its identity; only
the description is added.

Chaining onto declarations

The descriptor can be chained directly onto a declaration, so the value and
its documentation are introduced together:

var num = 4 -> "It's a four"
const limit = 10 -> "max retries"
var bare -> "nil with docs"

This declares the variable exactly as usual, then attaches the description —
var num = 4 -> "..." behaves like var num = 4 followed by
num -> "...". It works with var, const, local, and ref (which
describes the aliased storage), and the description can be any expression:

var n = 1 -> "n=" + "1"

The description is the whole trailing expression — operators on the right
belong to the text ("n=" + "1" above describes n as n=1).

Destructured declarations (var a, b = ...) have no single binding to
describe, so chaining onto them is an error — describe each name separately
instead.

From C++, descriptions are supplied when the value is registered:

  • Embedding — engine.insert(name, var, description) (and the path-based
    insert/insert_path variants) takes an optional description string that is
    attached to the inserted value. scrii::Var::with_description(value, "…")
    produces a value carrying a description in one step (see
    Embedding — Exchanging values).
  • Plugins — the description argument of Registry::add_function /
    add_module.

Either way the text ends up on the same value, retrievable the same way as a
description attached with ->.

Reading a descriptor

Two builtins surface descriptors:

  • info(value) — returns a string with the value’s type and description
    (see Info & inspection).
  • help(value) / help() — lists builtins, modules, and their members with
    one name - description line each (see help).

Two-tier help return from objects

help() on an object or module returns two tiers in a single string:

  1. The object’s own description (the line attached to the object itself).
  2. One name - description line for each member, telling you exactly what
    is at that layer.
hello - string - helper module
   upper - string - converts to uppercase

Because every member carries a description line, you can drill into the next
layer: help(module) shows its function names and what they do, and you can
call help() on any nested member to keep descending. The interface is
self-describing — you never have to guess at a module’s contents.

The LSP surfaces the same text on hover, so descriptors describe values in the
editor too.

What describes what

  • Module / object members come with a description line (from their
    registration, e.g. add_function("name", fn, "name(x) - does y")).
  • Anything else carries a descriptor only if you attached one with ->
    (scalars, arrays, and plain values are otherwise empty).

See Builtins — info & help for the full reference.