
Description
Use when writing or debugging MPS quotations and anti-quotations — "node literals" that create SNode trees inline in behavior, typesystem, intentions, generator, and other model code. Covers heavy quotations (`Quotation`, `<...>`), light quotations (`NodeBuilder`, constructor-style for bootstrapping), and the four anti-quotation varieties: child (`%(...)%`), list (`*(...)*`), reference (`^(...)^`), property (`$(...)$`). Reach for this skill whenever the task involves splicing runtime values into quoted node trees or choosing between heavy and light quotations.
SKILL.md
MPS Quotations and Anti-quotations
A quotation is a node literal — a concise expression that evaluates to an SNode (or tree of SNodes) at runtime. Instead of building nodes manually via the smodel API, you write the desired structure in the target language syntax and let MPS wrap it. Anti-quotations ("antiquotations") are escape holes inside a quotation where a runtime expression is spliced in.
Required used language: jetbrains.mps.lang.quotation (UUID 3a13115c-633c-4c5c-bbcc-75c4219e9555)
Critical Directives
- Quotations do not call behavior constructors. Using
<Car()>produces anSNodeof conceptCarwithout running its constructor. Usenew node<Car>()(smodel API) when you need the constructor to run. - Use the concept identifier inside a quotation, not an alias. Write
<IntegerType>, not<int>. - All four anti-quotation kinds attach via the inherited
smodelAttributerole on anyBaseConcept. The anti-quotation node is a sibling attribute of the host node, not a replacement child. The runtime substitution happens during materialisation. Seereferences/antiquotations.md. ListAntiquotationconstraint: the list role must contain at least one placeholder child before you can activate a list antiquotation. The placeholder is replaced at runtime with zero-or-more nodes.PropertyAntiquotation.propertyIdandReferenceAntiquotation.linkIdare filled in automatically by MPS when you type$/^in a property/reference cell. Do not construct these encoded ids manually unless you have already verified the exactlanguage-uuid/concept-id/property-or-link-idform against the running MPS. Seereferences/property-and-reference-ids.md.- Prefer heavy quotation (
<...>) for readability; switch to light quotation (NodeBuilder) only for bootstrapping (the target language can't be aused language), for generators-of-generators, or when nesting depth makes embedded syntax unreadable. Seereferences/heavy-vs-light.md. - The deprecated
NodeBuilderInitLink.expression(cardinality 0..1) was removed in 2019.2. UseinitValuewith aNodeBuilderExpressioninstead. - Edit quotation-bearing models through MPS MCP tools (
mps_mcp_insert_root_node_from_json,mps_mcp_update_node). Do not hand-edit.mpsfiles. - Validate with
mps_mcp_check_root_node_problems; quotations frequently expose missing used-languages on the host model (the quoted concept's language must be a used language, not just a dependency).
Common-Path Workflow
- Add
jetbrains.mps.lang.quotationto the host model's used languages, plus the language whose concepts will be quoted. - In the editor, type
<in an expression position to insert aQuotation, then type the desired surface syntax of the quoted node. The quoted concept must be available as a used language; otherwise switch toNodeBuilder. - To inject runtime values, place the caret inside the appropriate cell and type:
%— child antiquotation (replaces the child node)*— list antiquotation (replaces a list-position node; requires a placeholder child first)^— reference antiquotation (replaces a reference target)$— property antiquotation (replaces a property value)
- For bootstrapping or deep nesting, use the Convert Quotation to NodeBuilder intention (or insert
NodeBuilderdirectly). - Validate with
mps_mcp_check_root_node_problems; rebuild the host language if needed.
When To Use Which Form
| Situation | Recommended form |
|---|---|
| Short, readable node literal in behavior / typesystem / intentions code | Heavy quotation |
| One or more children computed at runtime | Heavy quotation + child/list antiquotation |
| A property computed at runtime | Heavy quotation + property antiquotation |
| A reference target resolved at runtime | Heavy quotation + reference antiquotation |
| Bootstrapping (generating language infrastructure) or concept not importable | Light quotation (NodeBuilder) |
| More than 3 levels of nesting where embedded syntax is confusing | Light quotation (NodeBuilder) |
Related Skills
mps-aspect-behavior— behavior bodies frequently use quotations to build sub-trees; remember constructors do not fire when materialising a quotation.mps-aspect-typesystem—<TypeConcept>literals inside rule bodies are heavy quotations; the typesystem model typically importsjetbrains.mps.lang.quotationas a used language. The:==:/:<=:body shapes are inmps-aspect-typesystemjson-blueprints.md.mps-aspect-generator— template macros are a different mechanism for building target trees; quotations are used in non-template code (filters, mapping scripts, conditions) within the generator model.mps-aspect-migrations—<NewConcept>plus^(oldNode.target)^is the canonical shape inside migration rewrite scripts (references/antiquotation-reference.mdincludes the verbatim example).mps-aspect-intentions— thereplace_invokeOperation_with_compactInvokeexample shipping with the closures language uses<%(...)%>+*(...)*to rebuild an expression tree.mps-aspect-structure-concepts— when the quoted concept's link/property metadata is needed;propertyId/linkIdencode the persistent form of those declarations.mps-model-manipulation— the smodel operations and BaseLanguage expressions used inside antiquotationexpressionslots.
Reference Index
- Open
references/heavy-vs-light.mdwhen deciding betweenQuotationandNodeBuilder— the surface trade-offs, the bootstrapping rationale, and the recommendation table for typical situations. - Open
references/heavy-quotation.mdwhen authoring a basicQuotation(<...>) — concept structure, thequotedNode/smodelAttribute/modelToCreateroles, JSON blueprint, and the verbatimMoneyTypeexample from the baseLanguage.money generator. - Open
references/antiquotations.mdfor the full antiquotation catalog — the four kinds at a glance, attachment mechanism viasmodelAttribute, syntax (%/*/^/$), theAbstractAntiquotationinterface, theAntiquotation(child) shape, and the closures-intention worked example combining child + list antiquotations. - Open
references/antiquotation-list.mdwhen working withListAntiquotation(*(...)*) — placeholder requirement, expression type (nlist<..>/Iterable), and how it cooperates with multi-cardinality list roles. - Open
references/antiquotation-property.mdwhen writing or debugging aPropertyAntiquotation($(...)$) — concept structure,propertyId/name_DebugInfo/stringValueMigratedproperties, and the full JSON printout from the quotation editor test. - Open
references/antiquotation-reference.mdwhen a runtime reference target must be spliced —ReferenceAntiquotation(^(...)^) shape,linkId/role_DebugInfoproperties, and the migration-script example creating aNewComponentRefwhose target is computed at runtime. - Open
references/property-and-reference-ids.mdfor the encoded id formats used byPropertyAntiquotation.propertyIdandReferenceAntiquotation.linkId—language-uuid/concept-id/property-or-link-id— and the rule "let MPS fill these in" when editing in the IDE. - Open
references/light-quotation.mdwhen usingNodeBuilder— the constructor-style notation,NodeBuilderNode/NodeBuilderInitLink/NodeBuilderInitProperty/NodeBuilderExpression(#) concept structure, deprecation note onNodeBuilderInitLink.expression, JSON blueprint, and the verbatim nested-NodeBuilder example fromjetbrains.mps.kotlin.smodel.behavior. - Open
references/model-and-node-id.mdwhen the quotation needs to land in a specific model or with a specific node id —ModelNodeInitializershape and JSON blueprint. - Open
references/concept-catalog.mdfor the quick lookup table — FQNs and aliases of everyjetbrains.mps.lang.quotation.structure.*concept, plus the key role names and cardinalities used in JSON blueprints. - Open
references/source-locations.mdfor paths inside the MPS repository — where to find structure/behavior/typesystem/editor of the quotation language, generation+editor test cases, and the source models behind every example used in this skill.
More skills from the MPS repository
View all 31 skillsmps-aspect-accessories
configure JetBrains MPS module dependencies
Jul 17ArchitectureConfigurationEngineeringmps-aspect-actions
define and edit MPS node factories
Jul 17ArchitectureEngineeringmps-aspect-behavior
define and edit MPS concept behavior
Jul 13ArchitectureEngineeringmps-aspect-constraints
define JetBrains MPS language constraints
Jul 17ArchitectureCode Analysismps-aspect-dataflow
define and debug MPS dataflow builders
Jul 13Data Analysismps-aspect-editor
define MPS editor layouts
Jul 13DesignUI Components
More from JetBrains
View publishermps-aspect-editor-menus-and-keymaps
author MPS editor menus and keymaps
MPS
Jul 13EngineeringUI Componentsmps-aspect-generation-plan
modify MPS generation plans
MPS
Jul 13ArchitectureEngineeringmps-aspect-generator
define JetBrains MPS generator rules
MPS
Jul 17ArchitectureCode AnalysisEngineeringmps-aspect-intentions
define and edit MPS intentions
MPS
Jul 17ArchitectureEngineeringmps-aspect-migrations
author and debug MPS migration scripts
MPS
Jul 13DebuggingMigrationmps-aspect-structure-concepts
define concepts in MPS structure aspect
MPS
Jul 17Data Modeling