Complete Documentation
SLIPS (Swift Language Implementation of Production Systems) is a faithful semantic translation of CLIPS 6.4.2 to Swift 6.2. The project maintains the original philosophy, algorithms, and architecture of CLIPS while adapting them to Swift's modern type safety features.
CLIPS (C Language Integrated Production System) is an expert system shell developed by NASA. It uses a rule-based engine built on the RETE algorithm for efficient pattern matching and supports procedural, object-oriented, and rule-driven programming paradigms.
Add SLIPS to your Package.swift:
dependencies: [
.package(url: "https://github.com/gpicchiarelli/SLIPS.git", from: "0.1.0")
]
import SLIPS
// Create an environment
let env = CLIPS.createEnvironment()
// Define a template
CLIPS.eval(expr: """
(deftemplate person
(slot name)
(slot age (type INTEGER)))
""")
// Define a rule
CLIPS.eval(expr: """
(defrule greet-adult
(person (name ?n) (age ?a&:(>= ?a 18)))
=>
(printout t "Hello " ?n ", you are an adult!" crlf))
""")
// Assert facts
CLIPS.eval(expr: "(assert (person (name \"John\") (age 25)))")
CLIPS.eval(expr: "(assert (person (name \"Jane\") (age 16)))")
// Run rules
let fired = CLIPS.run(limit: nil)
print("Rules fired: \(fired)")
swift run slips-cli
SLIPS> (facts)
SLIPS> (rules)
SLIPS> (run)
| C (CLIPS) | Swift (SLIPS) |
|---|---|
struct |
struct |
union + type tag |
enum with associated values |
#define macros |
static let or computed properties |
malloc/free |
Array, Dictionary, ARC |
| Pointers | Reference types, Unsafe* when needed |
Sources/SLIPS/
โโโ Core/ (32 files, ~11,500 LOC)
โ โโโ envrnmnt.swift (environment.c)
โ โโโ evaluator.swift (evaluatn.c)
โ โโโ ruleengine.swift (engine.c + factmngr.c)
โ โโโ expressn.swift (expressn.c)
โ โโโ scanner.swift (scanner.c)
โ โโโ router.swift (router.c)
โ โโโ Modules.swift (moduldef.c) โ
โ โโโ MultifieldFunctions.swift (multifun.c) โ
โ โโโ StringFunctions.swift (strngfun.c) โ
โ โโโ MathFunctions.swift (emathfun.c) โ
โ โโโ TemplateFunctions.swift (tmpltfun.c) โ
NEW!
โ โโโ IOFunctions.swift (iofun.c) โ
โ โโโ FactQueryFunctions.swift (factqpsr.c) โ
โ โโโ UtilityFunctions.swift (miscfun.c) โ
โ โโโ PrettyPrintFunctions.swift โ
โ โโโ functions.swift (160+ built-in)
โโโ Rete/ (12 files, ~2,800 LOC)
โ โโโ AlphaNetwork.swift (alpha memory)
โ โโโ BetaEngine.swift (beta network)
โ โโโ DriveEngine.swift (drive.c)
โ โโโ NetworkBuilder.swift(rulebld.c)
โ โโโ Propagation.swift (incremental updates)
โ โโโ Nodes.swift (explicit RETE nodes)
โโโ Agenda/ (1 file, ~150 LOC)
โ โโโ Agenda.swift (agenda.c + focus stack)
โโโ CLIPS.swift (public facade)
Total: 46 files, 15,200+ LOC
SLIPS now includes the complete set of functions for manipulating and querying templates,
faithfully translated from tmpltfun.c of CLIPS 6.4.2.
;; Modify existing fact
(assert (person (name "John") (age 30))) ; f-1
(modify 1 (age 31)) ; Update age
;; Duplicate with modifications
(duplicate 1 (name "Jane")) ; f-2: Jane, 31 years
(duplicate 1 (name "Bob") (age 25)) ; f-3: Bob, 25 years
;; List slots of a template
(deftemplate-slot-names person)
; โ (create$ name age)
;; Default value of a slot
(deftemplate-slot-default-value person age)
; โ 0 (or specified default)
;; Check slot type
(deftemplate-slot-multip project team-members)
; โ TRUE (is multifield)
(deftemplate-slot-singlep person name)
; โ TRUE (is single-field)
;; Check slot existence
(deftemplate-slot-existp person salary)
; โ FALSE (slot doesn't exist)
tmpltfun.c
have been implemented and tested (24 tests, 100% pass rate).
SLIPS now supports the complete CLIPS module system for organizing rules and facts in separate namespaces.
;; Create module with export
(defmodule UTILITIES
(export deftemplate data-record)
(export defrule process-data))
;; Create module with import
(defmodule MAIN
(import UTILITIES deftemplate data-record))
;; Set focus on module (LIFO stack)
(focus UTILITIES)
;; Focus on multiple modules
(focus MODULE-A MODULE-B MODULE-C)
;; Get current module
(get-current-module) ; Returns MAIN
;; Set current module
(set-current-module UTILITIES)
;; List all modules
(list-defmodules)
; Output:
; MAIN
; UTILITIES
; MODULE-A
;; Get list as multifield
(get-defmodule-list)
; Returns: (MAIN UTILITIES MODULE-A)
;; Agenda for specific module
(agenda UTILITIES)
// Create environment
static func createEnvironment() -> Environment
// Load file
static func load(_ path: String) -> Bool
// Reset environment
static func reset()
// Run rules
static func run(limit: Int?) -> Int
// Assert facts
static func assert(fact: String) -> Int
// Retract facts
static func retract(id: Int) -> Bool
// Evaluate expressions
static func eval(expr: String) -> Value
// Interactive command loop
static func commandLoop()
struct Environment {
var facts: [Int: FactRec] // Fact base
var rules: [Rule] // Defined rules
var templates: [String: Template] // Deftemplate templates
var agendaQueue: AgendaQueue // Activation queue
var rete: ReteNetwork // RETE network
var watchFacts: Bool // Watch facts
var watchRules: Bool // Watch rules
var experimentalJoinCheck: Bool // Experimental beta engine
}
enum Value: Codable, Equatable {
case none
case int(Int64)
case float(Double)
case string(String)
case symbol(String)
case boolean(Bool)
case multifield([Value])
case factAddress(Int)
case instanceAddress(String)
case externalAddress(String)
}
(deftemplate problem
(slot type)
(slot description))
(deftemplate symptom
(slot name)
(slot severity (type INTEGER)))
(defrule diagnose-battery
(symptom (name "engine-wont-start"))
(symptom (name "dim-lights"))
=>
(assert (problem
(type "dead-battery")
(description "Battery needs recharge or replacement")))
(printout t "Diagnosis: Dead battery" crlf))
(defrule diagnose-alternator
(problem (type "dead-battery"))
(symptom (name "battery-drains-quickly"))
=>
(printout t "Possible alternator failure" crlf))
(deftemplate order
(slot id)
(slot customer)
(slot amount (type FLOAT))
(slot urgent (type SYMBOL)))
(defrule high-priority-order
(order (id ?id)
(customer ?c)
(amount ?amt&:(> ?amt 1000.0))
(urgent YES))
=>
(printout t "HIGH PRIORITY: Order " ?id
" from " ?c " for $" ?amt crlf))
(defrule loyal-customer-discount
(order (id ?id) (customer ?c) (amount ?amt))
(premium-customer (name ?c) (years ?y&:(>= ?y 5)))
=>
(bind ?discount (* ?amt 0.15))
(printout t "15% discount for " ?c ": $" ?discount crlf))
(defrule customer-without-orders
(customer (id ?id) (name ?n))
(not (order (customer-id ?id)))
=>
(printout t "Customer " ?n " has never ordered" crlf))
(defrule out-of-stock
(product (code ?c) (name ?n))
(not (inventory (product ?c) (quantity ?q&:(> ?q 0))))
=>
(printout t "ALERT: " ?n " is out of stock!" crlf))
RETE is a pattern matching algorithm developed by Charles Forgy in 1979. It optimizes rule matching by avoiding rechecking unchanged conditions in each cycle.
// Enable comparison between classic backtracking and beta engine
CLIPS.eval(expr: "(set-join-check on)")
// Check status
let status = CLIPS.eval(expr: "(get-join-check)")
// Returns: boolean(true)
When join-check is active, SLIPS runs both algorithms
and logs any divergences to STDERR. This helps validate the incremental implementation.
See AGENTS.md in the repository root for complete rules. In summary:
.c/.h โ corresponding .swiftguard let and pattern matchinggit clone https://github.com/gpicchiarelli/SLIPS.git
cd SLIPS
swift build
swift test
# All tests (275+)
swift test
# Specific test
swift test --filter TemplateFunctionsTests
swift test --filter ModuleAwareAgendaTests
# With verbose output
swift test --verbose
# Results: 274/275 pass (99.6%) โ
Reference to original CLIPS sources:
clips_core_source_642/core/
โโโ agenda.c/h โ Agenda/Agenda.swift โ
โโโ drive.c/h โ Rete/BetaEngine.swift ๐ง
โโโ pattern.c/h โ (to be translated)
โโโ reteutil.c/h โ (to be translated)
โโโ network.c/h โ (to be translated)
โโโ ...
See ROADMAP_TO_1.0_UPDATED.md for detailed planning:
Current status: 96% coverage, production-ready! Only final documentation pending.