MPS Typesystem and Checking Aspect
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
inferprefix makes an inequation soft (the solver tries to satisfy it, will not immediately error). Withoutinfer, violating the inequation reports an error. Choose deliberately. - In equation/inequation JSON, both
leftExpressionandrightExpressionareTypeClauseslots — always wrap the real Expression in aNormalTypeClause(normalTypechild holds the actual Expression). Do not put the Expression directly underleftExpression/rightExpression. - TextGen-style dispatch caveat does not apply here; typesystem rules are inherited via concept hierarchy, but the
overridesproperty 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 rawtoString. 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 thehelginsIntentionslot (TypesystemIntentionwrapper withquickFixref +actualArguments). Seereferences/quick-fixes.md. - Reusable helper code (utility classes, shared algorithms) can live as a plain BaseLanguage
ClassConceptroot 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 backList<SNode>— fix permps-model-manipulation/references/variable-declarations.md. - 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.mpsfiles. - After edits run
mps_mcp_check_root_node_problems, compile the language, and test on sample models.
Common-Path Workflow
- Create a
typesystemmodel (mps_mcp_create_modelwithmodelName: "<lang>.typesystem"— aspect IDtypesystem, case-sensitive, no@suffix; see aspect-model-stereotypes.md) if absent. - Add used languages:
jetbrains.mps.lang.typesystem, and any languages used in bodies (smodel,collections,closures,baseLanguage). - Add
InferenceRuleroots for concepts whose types you compute (seereferences/inference-rules.md). - Add
SubtypingRule/ComparisonRule/InequationReplacementRule/SubstituteTypeRuleroots for the type lattice (seereferences/lattice-rules.md). - Add
NonTypesystemRuleroots for checks that are not about types (seereferences/non-typesystem-checking.md). - Add
TypesystemQuickFixroots for any fix you want to attach to reports; wire them via ahelginsIntention/TypesystemIntentionchild of thewarning/error/infostatement (seereferences/quick-fixes.md). - Write bodies with BaseLanguage + smodel. Use
when concrete(references/when-concrete.md) when you need resolved types before checking. For helper code, place aClassConceptroot directly in the typesystem model and call it from rules. - Validate:
mps_mcp_check_root_node_problemsplus compile the language and test on sample models. AhelginsIntention-wired quick fix now surfaces in the check report'squickFixesarray and can be applied withmps_mcp_apply_intention(nodeReference = <problem node>, intentionId = <fix id>); an auto-applicable fix runs underautoApplyQuickFixes=true.
Related Skills
mps-aspect-behavior— behavior methods called from rule bodies vianode.method(); common host forgetType/isAssignableFrom-style helpers callable from typesystem.mps-aspect-constraints— non-type validation often lives in constraints; consider whether a check belongs there before adding aNonTypesystemRule.mps-aspect-intentions— distinct fromTypesystemQuickFix(intentions are user-invoked from caret; quick fixes attach to a report).mps-model-manipulation— full BaseLanguage / smodel / collections reference used inside rule bodies (StatementList,DotExpression, smodel operations, theList<SNode>→sequence<node<X>>return-type fix).mps-quotations—<type>literals in rule bodies are heavy quotations;%(expr)%splices use theAntiquotationfamily. The typesystem model usually usesjetbrains.mps.lang.quotationas a used language.mps-aspect-structure-concepts— when introducing the type concept(s) the rules target.
Reference Index
- Open
references/inference-rules.mdwhen writing or debugging anInferenceRule— the operator vocabulary (:==:,:<=:,:>=:, softinfer, 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.mdwhen a rule must wait for a resolved concrete type before deciding —WhenConcreteStatementshape, nestedwhen concreteblocks,operation type(op, leftType, rightType), and the bound-variable plumbing (WhenConcreteVariableDeclaration/WhenConcreteVariableReference). - Open
references/lattice-rules.mdfor the type-lattice rules —SubtypingRule(single supertype ornlist<>of supertypes),InequationReplacementRule(a.k.a. "replacement rule", structural subtyping withisApplicableClause,isWeak,equationInfo.getNodeWithError()),ComparisonRule(booleanbody,weak), andSubstituteTypeRule(attributedNode, return-or-null pattern). - Open
references/non-typesystem-checking.mdwhen adding aNonTypesystemRule("checking rule") —error / warning / info "msg" -> node;,isStrongSubtype(typeof(x) :<< t)for strict-subtype tests, and theCheckExcessTypeCastsexample. - Open
references/quick-fixes.mdwhen authoring aTypesystemQuickFixand wiring it into a report —QuickFixArgumentdeclarations,executeBlock/descriptionBlock, the three sample fixes (RemoveExcessTypeCast,RemoveMisplacedDash,HideCardinalityOne), and the full JSON for thehelginsIntention/TypesystemIntention/TypesystemIntentionArgumentplumbing. - Open
references/messages-and-helpers.mdwhen crafting messages — the<...>type-rendering convention,messageTargetto highlight just a property/reference/child cell,PropertyMessageTargetshape, and shared BaseLanguage helper roots (ElementSummarypattern). - Open
references/json-blueprints.mdwhen inserting nodes via MCP — body-level skeletons for each equation/inequation kind,ReportErrorStatement/WarningStatement/InfoStatementwith optionalhelginsIntention/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.mdwhen a type isundefined, subtyping isn't applied, error messages render badly, return types fight the Java parser, rules cycle, quick fixes aren't offered,when concretebodies never run, orSubstituteTypeRuleseems ignored.