refactor: convert DSL compiler relationCodes and unary check to spec table

Replace 19-entry relationCodes string-to-integer map with
getPredicateRelationCode() from PredicateSpec. Keep only
aspectRatioBetween (15) as local DSL-keyword override.

Replace string-based unary detection ('atLeast'||'atMost') in
compileSimpleAssertionToFormula with isUnaryPredicate() from spec.

595 SDK + 57 E2E tests pass.
This commit is contained in:
John Dvorak
2026-05-22 12:48:39 -07:00
parent 6f82849b4f
commit 2e27693278
+11 -24
View File
@@ -27,7 +27,7 @@ import type {
SelectorRef,
} from 'imhotep-core'
import { createEmptySemanticIr, getDefaultContext } from 'imhotep-core'
import { createEmptySemanticIr, getDefaultContext, getPredicateRelationCode, isUnaryPredicate } from 'imhotep-core'
import { parseTolerance, parseGap } from './validator.js'
// DSL grammar FOL types (distinct from solver FormulaNode imported above)
@@ -365,27 +365,15 @@ function toExecutionIr(semanticIr: SemanticIr): ExecutionIr {
idx = 0
for (const k of semanticIr.envGuards.keys()) guardIndex.set(k, idx++)
// Encode relation as small integer
const relationCodes: Record<string, number> = {
leftOf: 1,
rightOf: 2,
above: 3,
below: 4,
alignedWith: 5,
leftAlignedWith: 6,
rightAlignedWith: 7,
topAlignedWith: 8,
bottomAlignedWith: 9,
centeredWithin: 10,
inside: 11,
contains: 12,
overlaps: 13,
separatedFrom: 14,
// Encode relation as small integer (derived from predicate spec table).
// aspectRatioBetween is a DSL keyword, not a registered predicate.
const DSL_RELATION_CODES: Record<string, number> = {
aspectRatioBetween: 15,
between: 16,
intersects: 17,
touches: 18,
hasGap: 19,
}
function getRelationCode(relation: string): number {
const override = DSL_RELATION_CODES[relation]
if (override !== undefined) return override
return getPredicateRelationCode(relation) ?? 0
}
const clauseType = new Uint16Array(count)
@@ -403,7 +391,7 @@ function toExecutionIr(semanticIr: SemanticIr): ExecutionIr {
for (let i = 0; i < count; i++) {
const c = clauses[i]
clauseType[i] = relationCodes[c.relation] || 0
clauseType[i] = getRelationCode(c.relation)
clauseSubject[i] = subjectIndex.get(c.subjectRef) ?? 0
clauseReference[i] = c.referenceRef ? (subjectIndex.get(c.referenceRef) ?? 0) : 0
clauseFrame[i] = frameIndex.get(c.frameRef) ?? 0
@@ -527,8 +515,7 @@ function compileSimpleAssertionToFormula(
): FormulaNode {
const options = buildOptionsFromAssertion(assertion)
const isUnary = assertion.type === 'SizeAssertion'
|| (assertion.type === 'RelationAssertion'
&& (assertion.relation === 'atLeast' || assertion.relation === 'atMost'))
|| (assertion.type === 'RelationAssertion' && isUnaryPredicate(assertion.relation))
let predicateName: string
let args: VariableRef[]