#lang racket/base
(provide forward-chain)
(define-syntax try-rule
(syntax-rules ()
((try-rule vfired ifired restart-chain (predicate consequence ...))
(cond
((vector-ref vfired ifired)null)
(predicate
(vector-set! vfired ifired #t)
consequence ...
(restart-chain))))))
(define-syntax expand-rule
(syntax-rules ()
((expand-rule vfired ifired restart-chain last-rule)
(try-rule vfired ifired restart-chain last-rule))
((expand-rule vfired ifired restart-chain this-rule next-rule ...)
(begin
(try-rule vfired ifired restart-chain this-rule)
(expand-rule vfired (add1 ifired) restart-chain next-rule ...)))))
(define-syntax-rule (forward-chain rule ...)
(let ((vfired (make-vector (length '(rule ...)) #f)))
(let/cc restart-chain
(expand-rule vfired 0 restart-chain rule ...))))