CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

mps-aspect-typesystem

Use when authoring or debugging MPS typesystem — inference rules (`typeof :==: / :<=: / :>=:`), `SubtypingRule`, `ComparisonRule`, `InequationReplacementRule`, `SubstituteTypeRule`, `WhenConcreteStatement` blocks, `NonTypesystemRule` checking rules, `TypesystemQuickFix`, error/warning/info reports with `messageTarget` highlighting and quick-fix wiring (`helginsIntention`), and shared BaseLanguage helpers in the typesystem model. For questions to the compiled typesystem (`IS_SUBTYPE`, `EXPLAIN_TYPE`, `GET_EXPECTED_TYPE`), use the query tools when debugging “type stays undefined” or “operator cannot be applied.” Reach for this skill whenever the task involves editing `<lang>/languageModels/typesystem.mps`.

Quality

98%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

—

The risk profile of this skill

SKILL.md
Quality
Evals
Security

MPS Typesystem and Checking Aspect

Loading companion skills

Companion names in this skill are lazy dependencies: load only those relevant to the current task. If this skill came from an MCP server, use the host's skill loader to resolve the companion's unique discovered entry URI on the same host-assigned originating server. If the host has no server-backed skill loader, stop and report that limitation; do not silently fall back to a filesystem copy. If this skill came from a filesystem catalog, load the named sibling from that same catalog at <skills-root>/<skill-name>/SKILL.md, even if remote skill loaders are also available. Do not invent a tool name or server endpoint.

The typesystem aspect gives nodes types and reports semantic errors. It combines two related sub-aspects:

  • Typesystem rules — compute types and constraints on them (InferenceRule, SubtypingRule, InequationReplacementRule, ComparisonRule, SubstituteTypeRule).
  • Non-typesystem checking rules — produce errors/warnings/messages without contributing to type inference (NonTypesystemRule, a.k.a. "checking rule").

Lives in <lang>/languageModels/typesystem.mps, language jetbrains.mps.lang.typesystem. Rule bodies are BaseLanguage + smodel + collections + closures.

Critical Directives

  • One InferenceRule (or other root rule) per concept whose type/check you compute. Multiple rules collectively constrain a node — keep each rule focused.
  • The infer prefix makes an inequation soft (the solver tries to satisfy it, will not immediately error). Without infer, violating the inequation reports an error. Choose deliberately.
  • In equation/inequation JSON, both leftExpression and rightExpression are TypeClause slots — always wrap the real Expression in a NormalTypeClause (normalType child holds the actual Expression). Do not put the Expression directly under leftExpression/rightExpression.
  • TextGen-style dispatch caveat does not apply here; typesystem rules are inherited via concept hierarchy, but the overrides property on a rule suppresses inherited rules from superconcepts.
  • TextGen / typesystem error messages: wrap smodel expressions that render types with <...> presentation: error "Expected " + <expectedType> + " but got " + <actualType> -> node;. Avoid raw toString.
  • when concrete (typeof(expr) as v) { ... } defers a block until the type is fully resolved — use it before deciding whether to report an error or assign a result type.
  • Quick fixes (TypesystemQuickFix) are roots, not executed automatically — the user triggers them via the UI. Wire them into a report through the helginsIntention slot (TypesystemIntention wrapper with quickFix ref + actualArguments). See references/quick-fixes.md.
  • Reusable helper code (utility classes, shared algorithms) can live as a plain BaseLanguage ClassConcept root directly in the typesystem model. No separate utility module is required.
  • For MPS-typed return types (sequence<node<X>>, list<node<X>>) the Java parser gives back List<SNode> — fix per references/variable-declarations.md in the mps-model-manipulation skill root after loading that companion skill from the same origin.
  • Edit typesystem models through MPS MCP tools (mps_mcp_insert_root_node_from_json, mps_mcp_update_node, mps_mcp_parse_java_and_insert). Do not hand-edit .mps files.
  • After edits run mps_mcp_check_root_node_problems, compile the language, and test on sample models.

Common-Path Workflow

  1. Ask the compiled typesystem before authoring a rule. Check whether a type relation already holds or what produces a node's current type with mps_mcp_query_types (IS_SUBTYPE, SUPERTYPES, OPERATION_TYPE, EXPLAIN_TYPE) or mps_mcp_query_nodes (GET_TYPE, GET_EXPECTED_TYPE). Do not simulate the solver by reading rule roots: print a rule root only to change it or to pick a sibling to copy, and ask the engine (OPERATION_TYPE, COMMON_SUPERTYPE) what a change does to operators and joins. See mps-mcp-workflow/references/analysis-tools/type-queries.md for all operations and caveats.
  2. Create a typesystem model (mps_mcp_create_model with moduleName: "<lang>" and modelName: "<lang>.typesystem" — aspect ID typesystem, case-sensitive, no @ suffix; see aspect-model-stereotypes.md) if absent.
  3. Add used languages: jetbrains.mps.lang.typesystem, and any languages used in bodies (smodel, collections, closures, baseLanguage).
  4. Add InferenceRule roots for concepts whose types you compute (see references/inference-rules.md).
  5. Add SubtypingRule / ComparisonRule / InequationReplacementRule / SubstituteTypeRule roots for the type lattice (see references/lattice-rules.md).
  6. Add NonTypesystemRule roots for checks that are not about types (see references/non-typesystem-checking.md).
  7. Add TypesystemQuickFix roots for any fix you want to attach to reports; wire them via a helginsIntention/TypesystemIntention child of the warning/error/info statement (see references/quick-fixes.md).
  8. Write bodies with BaseLanguage + smodel. Use when concrete (references/when-concrete.md) when you need resolved types before checking. For helper code, place a ClassConcept root directly in the typesystem model and call it from rules.
  9. Validate: mps_mcp_check_root_node_problems plus compile the language and test on sample models. A helginsIntention-wired quick fix now surfaces in the check report's quickFixes array and can be applied with mps_mcp_apply_intention(nodeReference = <problem node>, intentionId = <fix id>); an auto-applicable fix runs under autoApplyQuickFixes=true.
  10. Verify the rules against a sandbox you own with the matching engine query; do not infer their behavior from what mps_mcp_check_root_node_problems does or does not report:
    1. mps_mcp_create_model a scratch model in the language's sandbox solution; mps_mcp_model_used_language ADD (kind: language) the language under test and whatever the copied root's own concept needs (e.g. jetbrains.mps.baseLanguage).
    2. mps_mcp_alter_nodes COPY_NODE a sample root (the copy lands in the sample's model), then MOVE_NODE_TO_PARENT it with only modelReference = the scratch model (node ids survive the move; swap the model part of references you harvested before it); or mps_mcp_insert_root_node_from_json. Add the construct whose typing you will change.
    3. Before the change: mps_mcp_check_root_node_problems + EXPLAIN_TYPE on it, so you have the baseline error and the rule behind it (a problem's rules[0].rule names it; print ruleReference only to change that rule). Commented-out code is not checked (uncheckedSubtrees), so a clean verdict over it proves nothing.
    4. Author the rule — copy-then-modify a sibling rule (COPY_NODE, then mps_mcp_update_node the name and references) — then MAKE with parameters = {"modules":["<lang>"],"rebuild":true}. One MAKE answering runtimeReady:true is the reload; no mps_mcp_reload_all.
    5. After: ask again — IS_SUBTYPE, mps_mcp_query_nodes GET_TYPE, EXPLAIN_TYPE (the subtype_checked entry's via names the rule that made it fit), and OPERATION_TYPE / COMMON_SUPERTYPE for side effects of a lattice change.
    6. mps_mcp_update_model DELETE the scratch model when you no longer need it (keep it if the task asks for it). MPS's VCS integration may stage files the MAKE writes; an entry git status then shows as AD (staged, since deleted) needs git rm --cached.

Related Skills

  • mps-aspect-behavior — behavior methods called from rule bodies via node.method(); common host for getType / isAssignableFrom-style helpers callable from typesystem.
  • mps-aspect-constraints — non-type validation often lives in constraints; consider whether a check belongs there before adding a NonTypesystemRule.
  • mps-aspect-intentions — distinct from TypesystemQuickFix (intentions are user-invoked from caret; quick fixes attach to a report).
  • mps-collections-and-closures — .where / .select / .translate, foreach and closure literals inside rule bodies.
  • mps-model-manipulation — full BaseLanguage / smodel reference used inside rule bodies (StatementList, DotExpression, smodel operations, the List<SNode> → sequence<node<X>> return-type fix); for an inference or checking rule body open only references/dot-expression-basics.md in the mps-model-manipulation skill root after loading that companion skill from the same origin.
  • mps-quotations — <type> literals in rule bodies are heavy quotations; %(expr)% splices use the Antiquotation family. The typesystem model usually uses jetbrains.mps.lang.quotation as a used language.
  • mps-aspect-structure-concepts — when introducing the type concept(s) the rules target.

Reference Index

Start here — most common case: one InferenceRule that types a concept → read only references/inference-rules.md, plus references/json-blueprints.md when inserting it through MCP; a checking rule that reports an error → only references/non-typesystem-checking.md; a type that stays undefined → only references/common-failures.md.

  • Open references/inference-rules.md when writing or debugging an InferenceRule — the operator vocabulary (:==:, :<=:, :>=:, soft infer, strong :<<=: / :>>=:), free type variables (var elementType;), join(A | B), %(...)% anti-quotations in <...> literals, and the four worked examples (StringLiteral, ParenthesizedExpression, TernaryOperator, ForEachStatement).
  • Open references/when-concrete.md when a rule must wait for a resolved concrete type before deciding — WhenConcreteStatement shape, nested when concrete blocks, operation type(op, leftType, rightType), and the bound-variable plumbing (WhenConcreteVariableDeclaration / WhenConcreteVariableReference).
  • Open references/lattice-rules.md for the type-lattice rules — SubtypingRule (single supertype or nlist<> of supertypes), InequationReplacementRule (a.k.a. "replacement rule", structural subtyping with isApplicableClause, isWeak, equationInfo.getNodeWithError()), ComparisonRule (boolean body, weak), and SubstituteTypeRule (attributedNode, return-or-null pattern).
  • Open references/non-typesystem-checking.md when adding a NonTypesystemRule ("checking rule") — error / warning / info "msg" -> node;, isStrongSubtype(typeof(x) :<< t) for strict-subtype tests, and the CheckExcessTypeCasts example.
  • Open references/quick-fixes.md when authoring a TypesystemQuickFix and wiring it into a report — QuickFixArgument declarations, executeBlock / descriptionBlock, the three sample fixes (RemoveExcessTypeCast, RemoveMisplacedDash, HideCardinalityOne), and the full JSON for the helginsIntention / TypesystemIntention / TypesystemIntentionArgument plumbing.
  • Open references/messages-and-helpers.md when crafting messages — the <...> type-rendering convention, messageTarget to highlight just a property/reference/child cell, PropertyMessageTarget shape, and shared BaseLanguage helper roots (ElementSummary pattern).
  • Open references/json-blueprints.md when inserting nodes via MCP — body-level skeletons for each equation/inequation kind, ReportErrorStatement / WarningStatement / InfoStatement with optional helginsIntention / messageTarget, anti-quotation handling inside quotations, minimal rule-root skeletons, and the full validated concept reference with FQNs and concept refs.
  • Open references/common-failures.md when a type is undefined, subtyping isn't applied, error messages render badly, return types fight the Java parser, rules cycle, quick fixes aren't offered, when concrete bodies never run, or SubstituteTypeRule seems ignored.
Repository

JetBrains/MPS

Path

.agents/skills/mps-aspect-typesystem/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.