import type { MemoModel, MemoElement } from '../model/semantic.js'; import type { Violation } from './types.js'; import type { ConstraintExpr } from '../language/generated/ast.js'; import type { KindRegistry } from '../model/kind-registry.js'; /** A constraint authored as a KerML-subset boolean expression over a subject element. */ export interface NativeConstraint { /** Stable rule id, e.g. "EE-ALLOC-001". */ id: string; /** Human-readable description (surfaced in the violation). */ description: string; /** The element kind this constraint quantifies over (the SysML `subject`). */ appliesToKind: string; /** KerML-subset boolean expression; the subject element is implicit. */ expression: string; /** Severity when the expression is false for a subject. */ severity: 'error' | 'warning' | 'info'; /** Named specialized evaluator selected by ontology metadata. */ evaluator?: string; /** * The `constraint def` name. A rule's stable ID is its audit identity; the * def name is what a `RulePolicy` references, so both travel together. */ typeName?: string; /** Tailoring class from the rule's own `tailoring` attribute. */ tailoring?: 'invariant' | 'assurance' | 'methodology'; /** File the rule is declared in. */ sourceFile?: string; } /** Constraint metadata without the expression body — used by the AST entry point. */ export type ConstraintMeta = Omit; /** A constraint whose boolean body has already been parsed to an evaluator AST. */ export interface CompiledConstraint extends ConstraintMeta { /** Parsed boolean body; the subject element is the implicit root. */ ast: ConstraintNode; } /** Evaluate one native constraint (expression as source string) against its subject kind. */ export declare function evaluateNativeConstraint(constraint: NativeConstraint, model: MemoModel, kindRegistry?: KindRegistry): Violation[]; /** * Evaluate a pre-parsed constraint body against every element of its subject kind. * This is the shared core used by both the string entry point (above) and the * ontology loader, which compiles `constraint def` bodies via {@link langiumExprToNode}. */ export declare function evaluateConstraintNode(meta: ConstraintMeta, ast: ConstraintNode, model: MemoModel, kindRegistry?: KindRegistry, inScope?: (element: MemoElement) => boolean): Violation[]; type CmpOp = '==' | '!=' | '>=' | '<=' | '>' | '<'; type ArithOp = '+' | '-' | '*' | '/'; type Node = { kind: 'bool'; value: boolean; } | { kind: 'int'; value: number; } | { kind: 'str'; value: string; } /** Feature chain resolved against the current element (or the root subject). */ | { kind: 'feature'; root: 'current' | 'subject'; segments: string[]; } /** All elements of a named kind (the kind extent). */ | { kind: 'allOfKind'; kindName: string; } | { kind: 'acyclic'; relationshipType: string; } /** Elements standing at one declared end of every link of a relation. */ | { kind: 'endsOf'; relationshipType: string; side: 'source' | 'target'; } /** The LINKS of a relation, as id-bearing values a quantifier can range over. */ | { kind: 'linksOf'; relationshipType: string; } /** True when the current element's kind is, or specializes, a named kind. */ | { kind: 'conformsTo'; kindName: string; } /** * Transitive DIRECTIONAL navigation from the current element. * * The bare relation-name segment is bidirectional on purpose (see * `navigate`), which is right for "is this hazard mitigated" but useless * for a chain: from a requirement, `derivesFrom` returns its drivers AND * everything derived from it in one undifferentiated collection, so no rule * can ask "what is upstream of this". * * These are the additive directional tokens `navigate`'s comment * prescribes. `upstream` walks incoming edges (this element as target), * `downstream` walks outgoing edges (this element as source); both are * transitive and both exclude the element itself, so a cycle terminates * rather than hanging. */ | { kind: 'reach'; relationshipType: string; direction: 'upstream' | 'downstream'; } /** True when two collections share at least one element, compared by id. */ | { kind: 'intersects'; target: Node; other: Node; } /** * A feature chain hanging off an arbitrary expression rather than off a * bare identifier root — `downstream(derivesFrom).satisfiedBy`. Without it * a directional walk is a dead end: you can reach the ancestors but not * navigate on from them, and the trace rules need exactly that second hop. */ | { kind: 'chain'; target: Node; segments: string[]; } | { kind: 'method'; target: Node; name: 'size' | 'notEmpty' | 'isEmpty'; } | { kind: 'quant'; target: Node; name: 'forAll' | 'exists' | 'select'; body: Node; } | { kind: 'arith'; op: ArithOp; left: Node; right: Node; } | { kind: 'cmp'; op: CmpOp; left: Node; right: Node; } | { kind: 'and'; left: Node; right: Node; } | { kind: 'or'; left: Node; right: Node; } | { kind: 'not'; operand: Node; }; /** Public alias for the evaluator AST node (the compiled form of a constraint body). */ export type ConstraintNode = Node; export declare function parseConstraintExpression(src: string): Node; /** Map a Langium-parsed constraint expression to the evaluator AST. */ export declare function langiumExprToNode(expr: ConstraintExpr): Node; export {}; //# sourceMappingURL=constraint-eval.d.ts.map