atproto_mlf/lower
Lower the parser’s mlf tree to atproto_lexicon/ast. This is where the
mlf-specific semantics live: inline types expand at use sites, the
prelude built-ins become string + format, tokens qualify to
id#name inside enum/knownValues, use names resolve to nsid#def
refs, T | null lowers to the object’s nullable list, and one def is
promoted to main (by @main, by NSID-suffix match, or as the single
xrpc/record item). Constructs the target AST cannot represent (inline
objects in property position, inline primitives in unions, per-item or
top-level @const/@reference extension fields) surface as a clear
Semantic error or are dropped, never silently mis-encoded.
A bare type name resolves in this order: inline types, then local defs
(both take priority over everything else, matching upstream mlf),
then explicit use imports, then use ... as namespace aliases, then
the built-in prelude formats, and finally an unmatched wildcard use
import as the last resort.
A dotted path (inline, or after namespace-alias expansion) mirrors
upstream’s workspace resolution against known_docs, the set of
document NSIDs being compiled together: when the path minus its last
segment names a known document, the last segment is a def of it
(a.b.c#d); otherwise the whole path is taken as a document NSID
referencing its main def, emitted as a bare NSID (a.b.c.d). The
bare form is also the fallback when nothing is known, so a lone
parse without tree context lowers dotted paths to bare NSIDs, and
use a.b.c; imports resolve the same way (bare a.b.c).
Values
pub fn lower(
items: List(mlf_ast.Item),
id: String,
) -> Result(ast.LexiconDoc, error.ParseError)
pub fn lower_in_tree(
items: List(mlf_ast.Item),
id: String,
known_docs: set.Set(String),
) -> Result(ast.LexiconDoc, error.ParseError)
Lower with workspace knowledge: known_docs holds the NSIDs of every
document compiled alongside this one, letting dotted reference paths
distinguish a.b.c#d (def d of known document a.b.c) from the
bare-NSID main reference a.b.c.d.