186 lines
4.8 KiB
TypeScript
186 lines
4.8 KiB
TypeScript
/**
|
|
* Pure first-order logic AST types for Imhotep V1.1.
|
|
*
|
|
* These nodes represent the deterministic scene logic layer:
|
|
* quantifiers, boolean connectives, predicate calls, and terms.
|
|
*
|
|
* All nodes follow the unist-style shape with source spans.
|
|
*/
|
|
|
|
import type { AstNode } from './ast.js'
|
|
import type { Position } from './types.js'
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Formula Union
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type FormulaNode =
|
|
| ForAllFormula
|
|
| ExistsFormula
|
|
| AndFormula
|
|
| OrFormula
|
|
| NotFormula
|
|
| ImpliesFormula
|
|
| PredicateCall
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Quantifier Formulas
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface ForAllFormula extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'forall'
|
|
bindings: TupleBinding[]
|
|
body: FormulaNode
|
|
}
|
|
|
|
export interface ExistsFormula extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'exists'
|
|
bindings: TupleBinding[]
|
|
body: FormulaNode
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Boolean Connective Formulas
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface AndFormula extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'and'
|
|
left: FormulaNode
|
|
right: FormulaNode
|
|
}
|
|
|
|
export interface OrFormula extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'or'
|
|
left: FormulaNode
|
|
right: FormulaNode
|
|
}
|
|
|
|
export interface NotFormula extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'not'
|
|
operand: FormulaNode
|
|
}
|
|
|
|
export interface ImpliesFormula extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'implies'
|
|
antecedent: FormulaNode
|
|
consequent: FormulaNode
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Atomic Formula: Predicate Call
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface PredicateCall extends AstNode {
|
|
type: 'FormulaNode'
|
|
kind: 'predicate'
|
|
predicate: string
|
|
args: TermNode[]
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Terms
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type TermNode = VariableRef | DomainRef | AccessorTerm
|
|
|
|
export interface VariableRef extends AstNode {
|
|
type: 'VariableRef'
|
|
name: string
|
|
}
|
|
|
|
export interface DomainRef extends AstNode {
|
|
type: 'DomainRef'
|
|
domain: string
|
|
selector?: string
|
|
parentVar?: string
|
|
}
|
|
|
|
export interface AccessorTerm extends AstNode {
|
|
type: 'AccessorTerm'
|
|
variable: string
|
|
property: string
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tuple Binding (for multi-variable quantification)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface TupleBinding extends AstNode {
|
|
type: 'TupleBinding'
|
|
variables: string[]
|
|
domain: DomainRef
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Property Run Blocks
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface PropertyRunBlock extends AstNode {
|
|
type: 'PropertyRunBlock'
|
|
mode: 'sampled' | 'enumerated'
|
|
inputDomain: unknown
|
|
body: AstNode[]
|
|
}
|
|
|
|
export interface SampledRunBlock extends AstNode {
|
|
type: 'SampledRunBlock'
|
|
arbitrary: unknown
|
|
numRuns?: number
|
|
seed?: number
|
|
body: AstNode[]
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Type Guards
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export function isForAllFormula(node: FormulaNode): node is ForAllFormula {
|
|
return node.kind === 'forall'
|
|
}
|
|
|
|
export function isExistsFormula(node: FormulaNode): node is ExistsFormula {
|
|
return node.kind === 'exists'
|
|
}
|
|
|
|
export function isAndFormula(node: FormulaNode): node is AndFormula {
|
|
return node.kind === 'and'
|
|
}
|
|
|
|
export function isOrFormula(node: FormulaNode): node is OrFormula {
|
|
return node.kind === 'or'
|
|
}
|
|
|
|
export function isNotFormula(node: FormulaNode): node is NotFormula {
|
|
return node.kind === 'not'
|
|
}
|
|
|
|
export function isImpliesFormula(node: FormulaNode): node is ImpliesFormula {
|
|
return node.kind === 'implies'
|
|
}
|
|
|
|
export function isPredicateCall(node: FormulaNode): node is PredicateCall {
|
|
return node.kind === 'predicate'
|
|
}
|
|
|
|
export function isVariableRef(node: AstNode): node is VariableRef {
|
|
return node.type === 'VariableRef'
|
|
}
|
|
|
|
export function isDomainRef(node: AstNode): node is DomainRef {
|
|
return node.type === 'DomainRef'
|
|
}
|
|
|
|
export function isAccessorTerm(node: AstNode): node is AccessorTerm {
|
|
return node.type === 'AccessorTerm'
|
|
}
|
|
|
|
export function isTupleBinding(node: AstNode): node is TupleBinding {
|
|
return node.type === 'TupleBinding'
|
|
}
|