SLIPS API

Reference Completo

Indice

CLIPS (Facciata Pubblica)

La classe principale per interagire con SLIPS.

createEnvironment()

static func createEnvironment() -> Environment

Crea e inizializza un nuovo environment SLIPS.

let env = CLIPS.createEnvironment()

load(_:)

static func load(_ path: String) -> Bool

Carica ed esegue un file CLIPS.

let success = CLIPS.load("rules.clp")

eval(expr:)

static func eval(expr: String) -> Value

Valuta un'espressione CLIPS e ritorna il risultato.

let result = CLIPS.eval(expr: "(+ 2 3)")
// result: .int(5)

reset()

static func reset()

Resetta l'environment corrente, rimuovendo fatti ma mantenendo regole e template.

run(limit:)

static func run(limit: Int?) -> Int

Esegue le regole nell'agenda. Ritorna il numero di regole eseguite.

let fired = CLIPS.run(limit: nil)  // Esegue tutte
let fired = CLIPS.run(limit: 10)   // Esegue max 10

assert(fact:)

static func assert(fact: String) -> Int

Asserisce un fatto, ritorna l'ID.

let id = CLIPS.assert(fact: "(persona (nome \"Mario\") (età 30))")

retract(id:)

static func retract(id: Int) -> Bool

Rimuove un fatto dall'environment.

CLIPS.retract(id: 1)

commandLoop()

static func commandLoop()

Avvia un REPL interattivo.

CLIPS.commandLoop()
// SLIPS> (facts)
// SLIPS> (run)

Environment

Contesto di esecuzione che mantiene lo stato del sistema.

Struttura

public struct Environment {
    var facts: [Int: FactRec]
    var rules: [Rule]
    var templates: [String: Template]
    var agendaQueue: AgendaQueue
    var rete: ReteNetwork
    var localBindings: [String: Value]
    var globalBindings: [String: Value]
    var functionTable: [String: FunctionDefinitionSwift]
    var watchFacts: Bool
    var watchRules: Bool
    var experimentalJoinCheck: Bool
}

FactRec

public struct FactRec {
    let id: Int
    let name: String
    var slots: [String: Value]
}

Template

public struct Template {
    let name: String
    var slots: [String: SlotDefinition]
}

public struct SlotDefinition {
    let name: String
    let isMultifield: Bool
    let defaultType: DefaultType
    var defaultStatic: Value?
    var defaultDynamicExpr: ExpressionNode?
    var constraints: SlotConstraints?
}

Value

Rappresenta i tipi di dato in SLIPS.

Enum

public 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)
}

Esempi

let v1 = Value.int(42)
let v2 = Value.string("hello")
let v3 = Value.symbol("ok")
let v4 = Value.boolean(true)
let v5 = Value.multifield([.int(1), .int(2), .int(3)])

Conversioni

// Da Swift a Value
func toValue(_ x: Int) -> Value { .int(Int64(x)) }
func toValue(_ x: Double) -> Value { .float(x) }
func toValue(_ x: String) -> Value { .string(x) }
func toValue(_ x: Bool) -> Value { .boolean(x) }

// Da Value a Swift
if case .int(let i) = value { print(i) }
if case .string(let s) = value { print(s) }

Rule & Pattern

Rule

public struct Rule {
    let name: String
    let patterns: [Pattern]
    let rhs: [ExpressionNode]
    let salience: Int
    let tests: [ExpressionNode]
}

Pattern

public struct Pattern {
    let name: String
    let slots: [String: PatternTest]
    let negated: Bool
}

public struct PatternTest {
    public enum Kind {
        case constant(Value)
        case variable(String)
        case predicate(ExpressionNode)
    }
    let kind: Kind
}

Agenda

Gestisce la coda di attivazioni delle regole.

AgendaQueue

public struct AgendaQueue {
    var strategy: Strategy = .depth
    
    mutating func add(_ activation: Activation)
    mutating func next() -> Activation?
    mutating func clear()
    func contains(_ act: Activation) -> Bool
    mutating func setStrategy(_ s: Strategy)
}

Strategy

public enum Strategy: String {
    case depth      // Nuove attivazioni in testa
    case breadth    // Nuove attivazioni in coda
    case lex        // Per salience, poi recency
    case mea        // Per salience, poi età
}

Activation

public struct Activation {
    let priority: Int            // salience
    let ruleName: String
    var bindings: [String: Value]?
    var factIDs: Set = []
    var timestamp: Int = 0
}

Uso

// Imposta strategia
CLIPS.eval(expr: "(set-strategy lex)")

// Verifica strategia corrente
let strategy = CLIPS.eval(expr: "(get-strategy)")
// Returns: .symbol("lex")

Router

Sistema I/O flessibile con callback personalizzabili.

Costanti

public enum Router {
    public static let STDOUT = "stdout"
    public static let STDERR = "stderr"
    public static let STDIN = "stdin"
}

Funzioni

// Scrive su un router
public static func WriteString(
    _ env: inout Environment,
    _ logicalName: String,
    _ str: String
)

// Scrive con newline
public static func Writeln(
    _ env: inout Environment,
    _ str: String
)

// Aggiunge callback
public static func AddCallback(
    _ env: inout Environment,
    name: String,
    priority: Int,
    callback: @escaping (inout Environment, String, String) -> Bool
)

Esempio Custom Router

var buffer: [String] = []

Router.AddCallback(&env, name: "buffer", priority: 20) { _, _, text in
    buffer.append(text)
    return true
}

CLIPS.eval(expr: "(printout buffer \"Test\" crlf)")
print(buffer)  // ["Test\n"]

Evaluator

Valuta espressioni ed esegue funzioni.

Funzioni Principali

public enum Evaluator {
    public static func EvaluateExpression(
        _ env: inout Environment,
        _ node: ExpressionNode
    ) -> Value
    
    public static func eval(
        _ env: inout Environment,
        _ node: ExpressionNode
    ) throws -> Value
}

ExpressionNode

public final class ExpressionNode {
    public enum NodeType {
        case fcall, integer, float, string
        case symbol, boolean
        case variable, mfVariable
        case gblVariable, mfGblVariable
        case instanceName
    }
    
    public var type: NodeType
    public var value: ValueHolder?
    public var argList: ExpressionNode?
    public var nextArg: ExpressionNode?
}

Funzioni Built-in (160 funzioni)

Operatori Matematici (15):

  • +, -, *, /
  • =, <>, <, <=, >, >=
  • and, or, not, eq, neq

Math Functions (36):

  • Trigonometriche: sin, cos, tan, sec, csc, cot
  • Inverse: asin, acos, atan, atan2, asec, acsc, acot
  • Iperboliche: sinh, cosh, tanh, sech, csch, coth
  • Iperboliche inverse: asinh, acosh, atanh, asech, acsch, acoth
  • Esponenziali: exp, log, log10, sqrt, **
  • Utilità: abs, mod, round, pi, deg-rad, rad-deg

String Functions (11):

  • str-cat, sym-cat - Concatenazione
  • str-length, str-byte-length - Lunghezza
  • upcase, lowcase - Conversione caso
  • sub-string, str-index - Manipolazione
  • str-replace, str-compare - Operazioni
  • string-to-field - Parsing

Multifield Functions (10):

  • nth$, length$, first$, rest$
  • subseq$, member$, insert$, delete$
  • explode$, implode$

Template Functions (14) 🆕:

  • modify, duplicate - Manipolazione fatti
  • deftemplate-slot-names - Lista slot
  • deftemplate-slot-default-value - Default value
  • deftemplate-slot-cardinality - Cardinalità
  • deftemplate-slot-types - Tipi consentiti
  • deftemplate-slot-range - Range valori
  • deftemplate-slot-multip - Test multifield
  • deftemplate-slot-singlep - Test single-field
  • deftemplate-slot-existp - Test esistenza

I/O Functions (13):

  • read, readline, read-number, get-char
  • printout, print, println, put-char
  • open, close, flush, remove, rename

Fact Query Functions (7):

  • find-fact, find-all-facts
  • do-for-fact, do-for-all-facts
  • any-factp, fact-existp, fact-index

Utility Functions (6):

  • gensym, gensym* - Generazione simboli
  • random, seed - Numeri casuali
  • time - Timestamp
  • funcall - Chiamata dinamica

Module Functions (6):

  • defmodule - Definisce modulo
  • focus - Imposta focus
  • get-current-module, set-current-module
  • list-defmodules, get-defmodule-list

Pretty Print Functions (4):

  • ppdefmodule, ppdeffacts
  • ppdefrule, ppdeftemplate

Costrutti Core:

  • deftemplate, deffacts, defrule
  • assert, retract
  • bind, printout, progn
  • facts, rules, agenda
  • watch, unwatch
  • reset, clear, run
  • set-strategy, get-strategy

Vedi FUNZIONI_REFERENCE.md per la documentazione completa di tutte le 160 funzioni.

Template Functions API 🆕

modify

(modify <fact-id> (<slot-name> <value>)*)

; Esempio
(modify 1 (age 31) (city "Rome"))

Modifica uno o più slot di un fatto esistente. Ritorna il nuovo fact-id.

duplicate

(duplicate <fact-id> (<slot-name> <value>)*)

; Esempio
(duplicate 1 (name "Copy") (age 25))

Duplica un fatto con modifiche opzionali agli slot. Ritorna il nuovo fact-id.

deftemplate-slot-names

(deftemplate-slot-names <template-name>)

; Esempio
(deftemplate-slot-names person)
; Ritorna: (create$ name age city)

Ritorna un multifield con i nomi di tutti gli slot del template.

deftemplate-slot-default-value

(deftemplate-slot-default-value <template-name> <slot-name>)

; Esempio
(deftemplate-slot-default-value person age)
; Ritorna: 0 (o il default specificato)

Ritorna il valore di default di uno slot.

deftemplate-slot-multip / deftemplate-slot-singlep

(deftemplate-slot-multip <template-name> <slot-name>)
(deftemplate-slot-singlep <template-name> <slot-name>)

; Esempio
(deftemplate-slot-multip project team-members)
; Ritorna: TRUE

(deftemplate-slot-singlep person name)
; Ritorna: TRUE

Verificano se uno slot è rispettivamente multifield o single-field.

deftemplate-slot-existp

(deftemplate-slot-existp <template-name> <slot-name>)

; Esempio
(deftemplate-slot-existp person salary)
; Ritorna: FALSE (se lo slot non esiste)

Verifica se uno slot esiste nel template.

Funzioni Personalizzate

FunctionDefinitionSwift

public final class FunctionDefinitionSwift {
    public let name: String
    public let impl: (inout Environment, [Value]) throws -> Value
}

Registrazione

var env = CLIPS.createEnvironment()

env.functionTable["square"] = FunctionDefinitionSwift(
    name: "square"
) { _, args in
    guard let arg = args.first,
          case .int(let i) = arg else {
        return .none
    }
    return .int(i * i)
}

// Uso
CLIPS.eval(expr: "(printout t (square 7) crlf)")
// Output: 49