home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
aijournl
/
ai_nov86.arc
/
PFL.LSP
< prev
next >
Wrap
Text File
|
1986-10-04
|
15KB
|
424 lines
PFL Language
by Tim Finin
from:
November & December 1986 AI EXPERT article
"Understanding Frame Languages"
fdcl.lisp
;;; -*- Mode: LISP; Syntax: Zetalisp; Base: 10 -*-
;;; copyright (c) 1985 Tim Finin (tim@cis.upenn.edu)
;;; this file defines/loads the PFL system.
#+ symbolics
(defpackage pfl
(:export fput frame fslots ffacets fget fvalues fremove ferase
framep fsubsumes fdefineq fdefine ako instance subsumes-if
subsumed-if))
#+ symbolics
(defsystem pfl
(:name "Pedagogic Frame Representation Language")
(:package "pfl")
(:pathname-default "upenn:usr:[tim.frames]")è (:module pflvariables ("pflvariables"))
(:module pflmacros ("pflmacros"))
(:module pflbase ("pflbase"))
(:module pfldisplay ("pfldisplay"))
(:module pflthing ("thing"))
(:compile-load pflvariables)
(:compile-load pflmacros)
(:compile-load pflbase (:fasload pflmacros))
(:compile-load pfldisplay (:fasload pflmacros))
(:load pflthing))
#+vax
(progn
;; VAXLISP system file for PFL.
(require 'pflvariables "pflvariables.lisp")
(require 'pflmacros "pflmacros.lisp")
(require 'pflbase "pflbase.lisp")
(require 'pfldisplay "pfldisplay.lisp")
(require 'pflthing "pflthing.lisp")
(export '(fput frame fslots ffacets fget fvalues fremove ferase
framep fsubsumes fdefineq fdefine
ako instance subsumes-if subsumed-if))
(provide 'pfl))
fvariables.lisp
;;; -*- Mode: LISP; Syntax: Common-lisp; Package: USER; Base: 10 -*-
;;; copyright (c) 1985 Tim Finin (tim@cis.upenn.edu)
;;; This file binds and initializes the global variables used in PFL.
(defvar *frames* nil) ; a list of all frames in existence.
(defvar *fdemons* t) ; should demons be triggered by default?
(defvar *finherit* t) ; should inheritance be done by default?
(defvar *fdefault* t) ; should default-values be used by default?
(defvar *ftype* t) ; should type checking be done by default?
(defvar *fnumber* t) ; should :min and :max checking be done by default?
(provide 'pflvariables)
fmacros.lisp
;;; -*- Mode: LISP; Syntax: Common-lisp; Package: USER; Base: 10 -*-
;;; copyright (c) 1985 Tim Finin (tim@cis.upenn.edu)
;;; local macros and utilities used in PFL.è
;; syntactic sugar for a mapcar, some and every.
(defmacro foreach (V in L &rest body) `(mapcar #'(lambda (,V) ,@body) ,L))
(defmacro forsome (V in L &rest body) `(some #'(lambda (,V) ,@body) ,L))
(defmacro forall (V in L &rest body) `(every #'(lambda (,V) ,@body) ,L))
(defmacro fwarn (msg &rest fillers) `(progn (format t ,msg ,@fillers) nil))
;; applies a function to a list of things, then unions the results.
(defun collect (function sequence)(reduce #'onion (mapcar function sequence)))
;; like union, but works with 0 and 1 argument.
(defun onion (&optional arg1 arg2) (union arg1 arg2))
(provide 'pflmacros)
fbase.lisp
;; -*- Mode: LISP; Syntax: Common-lisp; Base: 10; Package: USER -*-
;;; copyright (c) 1985 Tim Finin (tim@cis.upenn.edu)
;;; this file provides the basic PFL functions.
;;; SETTING FUNCTIONS ...
(defun fput (frame slot facet datum
&key (demons *fdemons*) (type *ftype*)
(inherit *finherit*) (number *fnumber*))
;; adds a datum to a slot if its not their already.
(cond ((member datum (fget-local frame slot facet)) datum)
((equal facet :value)
(fput-value frame slot datum demons type inherit number))
(t (fput-add frame slot facet datum) datum)))
(defun fput-value (frame slot datum demons? type? inherit? number?)
;; adds a value to a slot if the types are ok and the
;; slot isn't full, then runs demons.
(unless (and type? (not (fcheck-types frame slot datum)))
(unless (and number? (not (fcheck-max frame slot)))
(fput-add frame slot :value datum)
(if demons?
(foreach demon in
(fget frame slot :if-added :inherit inherit?)
(funcall demon frame slot datum)))
datum)))
(defun fcheck-types (frame slot value)
;; true iff value is subsumed by all of the slot's types.
(forall type in (fget frame slot :type)è (or (fsubsumes type value)
(fwarn "~%;; ~S can't fit into ~S of ~S because it's
not subsumed by ~S" value slot frame type))))
(defun fcheck-max (frame slot)
;; true if there's room for another value.
(or (<= (length (fget-local frame slot :value))
(fget-slot-max frame slot))
(fwarn ";; Can't add another value to ~S of ~S" slot frame)))
(defun fcheck-min (frame slot)
;; true if it's ok to remove a value
(or (> (length (fget-local frame slot :value))
(fget-slot-min frame slot))
(fwarn ";; Can't remove a value from ~S of ~S " slot frame)))
(defun fget-slot-max (f s)
; returns the max-cardinality for slot S of frame F.
(let ((max (fget f s :max)))
(if max (car max) most-positive-fixnum)))
(defun fget-slot-min (f s)
; returns the min-cardinality for slot S of frame F.
(let ((min (fget f s :min)))
(if min (car min) 0)))
(defun fput-add (frame slot facet datum)
;; adds datum to specified (frame,slot,facet)
(rplacd (last (ffacet frame slot facet)) (list datum)))
(defun ffacet (frame slot facet)
;; returns the expression representing the given facet of
;; a particular frame and slot, creating it if neccessary.
(extend facet (extend slot (frame frame))))
(defun extend (key alist)
;; like assoc, but adds key KEY if its not in the alist alIST.
(or (assoc key (cdr alist)) (cadr (rplacd (last alist)(list (list key))))))
;;; ACCESSING FUNCTIONS ...
;; returns the structure which represents the frame named F.
(defun frame (f) (or (get f 'frame) (fcreate f)))
;; returns a list of all local and inherited slots.
(defun fslots (f &key (inherit *finherit*))
(if inherit
(collect 'fslots-local (flineage f))
(fslots-local f)))
(defun fslots-local (f)
"returns just the local slots of frame f"
(mapcar #'car (cdr (frame f))))
(defun ffacets (f s &key (inherit *finherit*))è "returns a list of local and inherited facets for slot of frame"
(if inherit
(collect #'(lambda (x) (ffacets-local x s)) (flineage f))
(ffacets-local f s)))
(defun ffacets-local (f s) (mapcar 'car (cdr (assoc s (cdr (frame f))))))
(defun fget (frame slot facet &key (inherit *finherit*)
(demons *fdemons*) (default *fdefault*))
(if (equal facet :value)
(fvalues frame slot :inherit inherit :demons demons :default default)
(fget1 frame slot facet inherit)))
(defun fget1 (frame slot facet inherit?)
;; returns list of data for the given frame, slot and facet
(or (fget-local frame slot facet)
(if inherit?
(forsome parent in (fparents frame)
(fget1 parent slot facet t)))))
(defun fget-local (frame slot facet)
;; returns the data in a facet w/o inheritance or demons.
(cdr (assoc facet (cdr (assoc slot (cdr (frame frame)))))))
(defun fvalues (f s &key (inherit *finherit*) (demons *fdemons*)
(default *fdefault*) (finitial f))
;; returns values from frame F slot S, local or inherited.
(or (fget-local f s :value)
(and default (fget-local f s :default))
(and demons (forsome demon in (fget-local f s :if-needed)
(listify (funcall demon finitial s))))
(and inherit
(forsome parent in (fparents f)
(fvalues parent s :inherit t
:demons demons
:default default
:finitial finitial)))))
(defun listify (l) (if (and l (atom l)) (list l) l))
(defun fvalue (frame slot &key (inherit *finherit*) (demons *fdemons*)
(default *fdefault*))
"returns the 1st value in the specified slot"
(car (fvalues frame slot :inherit inherit :demons demons :default default)))
;; returns the immediate parents of frame f.
(defun fparents (f) (fget-local f 'ako :value))
;; returns a list of F and all of F's ancestor frames.
(defun flineage (f) (cons f (collect #'flineage (fparents f))))
;;; FUNCTIONS TO REMOVE FRAMES, ETC. ...
(defun fremove (frame slot facet datum
&key (demons *fdemons*)è (inherit *finherit*)
(number *fnumber*))
;; removes datum from frame's slot's facet and runs if-removed demons.
(when (and (member datum (fget-local frame slot facet))
(or (not (eq facet :value)) (fcheck-min frame slot)))
(delete datum (ffacet frame slot facet))
(if (and (eq facet :value) demons)
(foreach demon in (fget frame slot :if-removed :inherit inherit)
(funcall demon frame slot datum)))))
(defun ferase (f &key (demons *fdemons*) (inherit *finherit*))
"erases a frame, piece by piece (so that demons can fire)"
(foreach slot in (append (delete 'ako (fslots-local f)) '(ako))
(foreach facet in (ffacets-local f slot)
(foreach datum in (fget-local f slot facet)
(fremove f s facet datum :demons demons :inherit inherit))))
(setq *frames* (delete f *frames*))
(setf (get f 'frame) nil))
;;; PREDICATES
(defun framep (f)
"returns T iff its argument is a frame"
(and (symbolp f) (get f 'frame) (member f *frames*)))
(defun fsubsumes (super sub)
"Does SUPER subsume SUB? One of {sub,super} must be a frame."
(or (ako-chain sub super)
(ako-subsumes-if sub super)
(ako-subsumed-if sub super)))
(defun ako-chain (sub super)
"is there a chain of AKO likes from frame SUB to frame SUPER?"
(and (framep sub) (framep super) (ako-chain1 sub super)))
(defun ako-chain1 (sub super)
(or (equal sub super)
(forsome parent in (fparents sub) (ako-chain parent super))))
(defun ako-subsumes-if (sub super)
"is there a method on SUPER that says SUB is below it?"
(and (framep super)
(forsome pred in (fvalues super 'subsumes-if) (funcall pred sub))))
(defun ako-subsumed-if (sub super)
"is there a method on SUB that says SUPER is above it?"
(and (framep sub)
(forsome pred in (fvalues sub 'subsumed-if) (funcall pred sub))))
;;; FUNCTIONS TO CREATE and DEFINE FRAMES
(defmacro fdefineq (frame parents &rest slots)
;; defines a frame named FRAME with parents PARENTS and slots SLOTS
`(fdefine ',frame ',parents ',slots))
è(defun fdefine (name parents slots)
;; (re)defines a frame, arguments are evaluated.
(fcreate name)
(foreach p in (if (listp parents) parents (list parents))
(fput name 'ako :value p))
(foreach slot in slots
(foreach facet in (cdr slot)
(foreach datum in (cdr facet)
(fput name (car slot) (car facet) datum))))
name)
(defun fcreate (f)
"creates a frame with name F"
(setq *frames* (adjoin f *frames*))
(setf (get f 'frame) (list f)))
(provide 'pflbase)
fdisplay.lisp
;;; -*- Mode: LISP; Syntax: Common-lisp; Package: USER; Base: 10 -*-
;;; copyright (c) 1985 Tim Finin (tim@cis.upenn.edu)
;;; This file defines functions to display frames, including:
;;; fshow - show all data in all facets of all slots of a frame.
;;; fshow-values - show just values of all slots of a frame.
(defun fshow (frame &key (inherit *finherit*))
;; displays a frame
(format t "~%frame ~S" frame)
(foreach slot in (fslots frame :inherit inherit)
(format t "~% slot ~S:" slot)
(foreach facet in (ffacets frame slot :inherit inherit)
(format t "~% ~S = " facet)
(foreach datum in (fget frame slot facet :inherit inherit)
(format t "~S " datum))))
frame)
(defun fshow-values (frame
&key (inherit *finherit*)
(demons *fdemons*)
(default *fdefault*))
;; displays values in a frame
(format t "~%frame ~S" frame)
(foreach slot in (fslots frame :inherit inherit)
(let ((values (fvalues frame slot
:inherit inherit :demons demons :default default)))
(WHEN values
(format t "~% ~S = " slot)
(foreach v in
(if (atom values) (list values) values)è (format t "~S " v)))))
frame)
(provide 'pfldisplay)
pflthing.lisp
;;; -*- Mode: LISP; Syntax: Common-lisp; Package: USER; Base: 10 -*-
;;; copyright (c) 1985 Tim Finin (tim@cis.upenn.edu)
;;; this is the default initialization file for the frame hierarchy.
;;; It sets up the hierarchy:
;;;
;;; thing
;;; frame - subsumes all PFL frames.
;;; slot - subsumes all PFL slots.
;;; ako - the PFL AKO slot.
;;; instance - The PFL instance slot.
;;; expression
;;; list
;;; number
(fdefineq thing nil ; in the beginning was THING ...
(ako (:type frame)
(:if-added add-inverse)
(:if-removed remove-inverse))
(instance (:type frame)
(:if-added add-inverse)
(:if-removed remove-inverse)))
(defun add-inverse (frame slot value)
;; add an inverse relation.
(fput value (fvalue slot 'inverse) ':value frame))
(defun remove-inverse (frame slot value)
;; remove an inverse relation
(fremove value (fvalue slot 'inverse) ':value frame))
(defun add-symmetric (frame slot value) (fput value slot :value frame))
(defun remove-symmetric (frame slot value) (fremove value slot :value frame))
;; these are PFL related concepts....
(fdefineq frame thing (subsumes-if (:value framep)))
(fdefineq slot thing
(inverse (if-added (lambda (f s d) (fput d 'inverse f)))
(if-removed (lambda (f s d) (fremove d 'inverse f)))))
(fdefineq ako slot (inverse (:value instance)))
è(fdefineq instance slot (inverse (:value ako)))
(fdefineq ILLEGAL nil
;; this is a frame that subsumes nothing.
(subsumes-if (lambda (x) nil)))
;; These are commonly useful concepts.
(fdefineq expression thing (subsumes-if (:value (lambda(x) t))))
(fdefineq list expression (subsumes-if (:value listp)))
(fdefineq number expression (subsumes-if (:value numberp)))
(provide 'pfl-thing)
))))
;;; FUNCTIONS TO CREATE and DEFINE FRAMES
(