;copywr:bobak@computer.org
;--------------------------------------------------------------EOF
(deffunction ptag (?n)  (printout t t "a stub for ptag" ?n))
;start of pvm clips task code, Mike B.  ;-needs:util.clp
(defglobal ?*my-tid* = 0)
(defglobal ?*parent-tid* = 0)
(defglobal ?*model* = 0)  ;compiled w/ the model, or talking to it
(defglobal ?*inst-tids* = (create$ ))  ;tids of all the task instances
(defglobal ?*start-time* = 0)
(defglobal ?*recv-d-time* = 10)
;------------------------------------------------util
;(deffunction elapse-time () (- (time) ?*start-time*)) in misc-fnc.clp
(deffunction elapse-time () (- (time) ?*start-time*)) ;in misc-fnc.clp
(deffunction upk1int () (upkint))

;holds the information on how to contact another unix process on the 
;virtual machine  (note: pvm's virtual machine can include many machines)
(defclass TASK
  (is-a INITIAL-OBJECT)
  (role concrete) (pattern-match reactive)
  (slot init-time (create-accessor read-write))
  (slot active (create-accessor read-write))
  (slot tid  (create-accessor read-write))
  (slot tpid (create-accessor read-write))
  (slot host (create-accessor read-write))
  (slot flag (create-accessor read-write))
  ;(multislot msgtags (create-accessor read-write)) ;tags of possible interest
 (slot global-name ;(type INSTANCE) 
        (create-accessor read-write) (visibility public))
  (slot Name (create-accessor read-write)))

;a type of task which will be a clips process which controls a model
(defclass CNTRL-TASK
  (is-a TASK)
  (role concrete) (pattern-match reactive)
  (slot init-time (create-accessor read-write)))

;a type of task which will be the actual FORTRAN/C(++) model
(defclass MODEL-TASK
  (is-a TASK)
  (role concrete) (pattern-match reactive)
  (slot init-time (create-accessor read-write)))

;send-str (implode$  (local-slotnames ?inst))
;send-str (implode$  (slot-local-values ?inst))
;can use to-str & to-pstr=quote now for any list of args

;-------------------------------------------------------send_to_tasks
;so can send whatever is packed up to many different tasks
;can use mcast too, or bcast & a group name
(deffunction send_to_tasks ($?tasks)
   ;(map2 send_ (map1 get-tid ?tasks) 0)
   ;(map2 send_0 ?tasks) ;in my orig file
   (map2 send_0 ?tasks 0) ;a guess at a fix, mb
)

;-------------------------------------------------------GET-TID
(deffunction get-tid (?task)
  (if (numberp ?task) then ?task
   else (if (instancep ?task) then (send ?task get-tid)
         else (printout t "[get-tid:bad-arg " ?task "]"))))
;(if (numberp ?task) then ?task else (send ?task get-tid))
; else  if (stringp ?task) then return all the tids

;-------------------TASK msg handlers-----------------
;-------------------send/recv  handlers

;(deffunction send-str-to (?str $?tasks) 
;   (printout t "[send-str to defined below]"))
(deffunction send-str-to (?str $?tasks)
   (printout t "[send-str to defined below]"))
;------------------------------------------------------task EVAL
;take the args make into a parened string, and send to task for evaluation
;(defmessage-handler TASK eval primary ($?args)
;  (send-str-to (quotes ?args) ?self))

;-------------------TASK init handler  -------------
;makes sure that a newly created task has many of its slots filled in.
(defmessage-handler TASK init after ()
  (send ?self put-init-time (elapse-time))
;if active slot isn't set, the task is waiting (by default)
;if spawned or gotton from tasks it should be set to active (if it is)
;flag has some of that status info
  (if (not (symbolp ?self:active)) then (send ?self put-active waiting))
;set host if not set
    (if (and (numberp ?self:tid) (not (numberp ?self:host)))  then
                    (send ?self put-host (tidtohost ?self:tid)))
  (insert$ ?*inst-tids* 1 ?self:tid)

  ;if there is a global-name for the task make that inst w/ the same tid
  (if (or (and (instancep ?self:global-name) (neq ?self:global-name [nil]))
          (stringp ?self:global-name)) then
    (make-instance ?self:global-name of TASK (tid ?self:tid)))
)

(defmessage-handler TASK get-tid before ()
  (if (null ?self:tid) then (printout t "[" ?self " has no tid, so put-tid]")))


;--ADD-TASK    (takes 2 strings & and int right now)
;makes an instance of a task
(deffunction add-process (?name ?where ?tid)
  (make-instance (sym-cat task- ?name - ?tid) of TASK
    (tid ?tid)
    (host ?where)
    (Name ?name)))

;--MAKE-TASK    (takes 2 strings right now)
;makes an instance of a task
(deffunction make-process (?name ?where)
  (bind ?tid
   (spawn ?name "(load pvm-agt)" 1 ?where (if (stringp ?where) then 1 else 0)) )
   (add-process ?name ?where ?tid))
;latter will just incr the #, and use the tid slot for sends

;might still want something like above, so when you have a task/spawn it
;that the rest of the (tasks tid) info can be parsed into the new instance

;------------------------------------------------------task EVAL
;take the args make into a parened string, and send to task for evaluation
(defmessage-handler TASK eval primary ($?args)
  (send-str-to (quotes ?args) ?self))
;------------------------------------------------------
;------------------------------------------------------OID
(defclass OID                                   ;obj  id   (~= cORB-NAME)
  (is-a INITIAL-OBJECT)
  (role concrete) (pattern-match reactive)
  (slot tid  (create-accessor read-write))      ;task id ([inst] or int id)
  (slot iid  (create-accessor read-write))      ;inst id ([inst] or str id)
  (slot orb-name  (create-accessor read-write))) ;name given by naming service
;to have a globally seperate name, need 1 naming service
;either inst-name or orb-name slot should be unique
;-----------------------------------------------------new:
;(defclass TID                                  ;task obj  id  ;mirror globals for now
;  (is-a INITIAL-OBJECT)
;  (role concrete) (pattern-match reactive)
;  (slot tid  (type INTEGER) (create-accessor read-write))      ;task id ([inst] or int id)
;  (slot pid  (type INTEGER) (create-accessor read-write))      ;parent task id ([inst] or int id)
;  (slot start-time  (type INTEGER) (create-accessor read-write)) ;also was a global
;  (slot recv-d-time  (type INTEGER) (create-accessor read-write)) ;also was a global
;  (slot model  (type INTEGER) (create-accessor read-write)) ;also was a global
;  (multislot inst-tids  (create-accessor read-write)) ;also was a global
;)
;-----------------------------------------------------EOF
;start of pvm clips  code, Mike B.  ;-needs:util.clp

;-------------------send/recv  functions
;----------------------------------------send-str
;general send a string to a task w/ tid (takes an int||task & string, w/opt int)
(deffunction send-str (?task ?str $?msgtag)
    (initsend 0)
    (if (and (integerp (bind ?tid (get-tid ?task))) (lexemep ?str)) then
        (pkstr ?str)                     ;might use stringp
        (send_ ?tid (first-dflt ?msgtag 0))
    else (printout t "[bad send-str " ?task ", " ?str "]")))
;----------------------------------------send-str-to
;(deffunction send-str-to (?str ?task)
;    (initsend 1)
;    (if (and (integerp (bind ?tid (get-tid ?task))) (stringp ?str)) then 
;       (pkstr ?str)    (send_ ?tid 0)
;    else (printout t "[bad send-str-to " ?task ", " ?str "]")))

;----------------------------------------send_0
;(deffunction send_0 (?task)
;  (if (integerp (bind ?tid (get-tid ?task))) then (send_ ?tid 0)
;   else (printout t "[bad send_0 " ?tid "]")))
;task can be a task-inst a tid or a group-string,   msgtag will=0
(deffunction send_0 (?task)
  (if (integerp (bind ?tid (get-tid ?task))) then (send_ ?tid 0)
   else (if (stringp ?task) then (bcast ?task 0)
         else (printout t "[bad send_0 " ?tid "]"))))

;----------------------------------------SEND-STR-TO
(deffunction send-str-to (?str $?tasks)
    (initsend 1)
    (if (stringp ?str) then (pkstr ?str) (map1 send_0 ?tasks)
    else (printout t "[bad send-str-to " ?tasks ", " ?str "]")))


;----------------------------------------send-str-to-deem
;(deffunction send-str-to-deem (?str)
;    (initsend 1) (pkstr ?str)  (bcast "deem" 0))
;----------------------------------------send-str-to-models
;(deffunction send-str-to-models (?str)
;    (initsend 1) (pkstr ?str)  (bcast "models" 0))

;---------------------------------------------------(u)pk strings by bytes
(deffunction pkstrb (?str)
  (bind ?l (+ (str-length ?str) 1))
  (printout t "[pkstrb of len=" ?l "]")
  ;(free (pkbyte (deref b (imalloc ?l) ?str) ?l))
  (pkbyte (deref b (imalloc ?l) ?str) ?l))
;-------------------
;(deffunction upkstrb (?l)  (deref b (upkbyte (imalloc ?l) ?l)))
(deffunction upkstrb (?l)
   (bind ?p (imalloc ?l))
   (printout t "[upkstrb of len=" ?l "into " ?p "]")
   (bind ?p2 (upkbyte ?p ?l))
   (printout t "final ptr=" ?p2)
   (deref b ?p2))
;-------------------
;----------------------------------------send-cl
;general send a string to a task w/ tid  (takes an int & string)
;pkbyte for sends to fortran, probably won't be used
(deffunction send-cl (?tid ?str ?len)
    (initsend 0)
    (pkbyte ?str ?len)
    (send_ ?tid 1))

(deffunction send-c (?tid ?str)
    (send-cl ?tid ?str (str-length ?str)))

;----------------------------------------TRECV_EVAL
;timed receive, which expects a string, and will evaluate it.
(deffunction trecv_eval ($?time)
    (bind ?t (first-dflt ?time 10))
    (if (<> (trecv -1 0 ?t) 0) then ;(eval (upkstr))
        (bind ?str (upkstr))
        (if (lexemep ?str) then (eval ?str)
        else (printout t "[bad trecv_eval:" ?str "]"))
    ))
;----------------------------------------recv-eval
;general receive any string and eval it (run this periodically)
(deffunction recv-eval ($?tid)
  (recv_ (first-dflt ?tid -1) 0)
  (eval (upkstr)))
;-------------------------------------------------EOF
;misc-fnc.clp  has various misc functions     MTB
;----------------------------------------time etc
(deffunction elapse-time () (- (time) ?*start-time*))

(deffunction rt () (round (time)))
(deffunction rt1 () (round (/ (time) 10)))
(deffunction rt2 () (round (/ (time) 100)))

(deffunction debug (?level) (setopt 2 ?level))          ;sets it up for debugs
(deffunction rr ()  (reset) (run 1) (agenda) (debug 1)) ;to start it up
(deffunction e ()  (agenda) (exit_pvm) (exit))          ;exit in a clean way

(deffunction ri (?file)  (load-instances ?file))
(deffunction sleep (?t) (system (format nil "sleep %d" ?t)))

(deffunction is () (initsend 1))  ;1=no encodeing,0=xdr (avoid 2 for strs)
(deffunction bi () (bufinfo))
(deffunction rbi () (progn (recv_ -1) (bufinfo)))
(deffunction lrbi (?i) (loop-for-count ?i (printout t (rbi) crlf)))

;----------------------------------------------------------------DEBUG FNCS
;these below are already in utils.clp apr2005
;(deffunction wa () (watch all))
;(deffunction wmsg () (watch messages))
;(deffunction whnd () (watch message-handlers))
;(deffunction uwa () (unwatch all))
;(deffunction wdf ($?fncs) (funcall watch deffunctions ?fncs))
;(deffunction uwdf ($?fncs) (funcall unwatch deffunctions ?fncs))
;(deffunction wmh ($?fncs) (funcall watch message-handlers ?fncs))
;(deffunction uwmh ($?fncs) (funcall unwatch message-handlers ?fncs))
;(deffunction insm (?class) (instances MAIN ?class))
;(deffunction list-insts (?class) (instances MAIN ?class))
;(deffunction list-insts-from (?class) (instances MAIN ?class))
;might make a (wa) that takes extra args that would be fncs to (uwdf)
;----------------------------------------------------------------
;(deffunction list ($?stuff) (create$ ?stuff))
;;(deffunction let* ($?l2)    (map-skip 2 bind ?l2))
;add from this utils:
(deffunction union- (?l1 ?l2)          (create$ ?l1 ?l2)) ;for rul.clp -mb
;--------------------------------------------------------EOF
;-------------------util fncs
(deffunction s-atoi (?str)
  (if (or (null ?str) (eq ?str "")) then 0 else (atoi ?str)))
;(deffunction gn (?ins) (instance-name-to-symbol ?ins))
;(deffunction gn (?ins) (sub-string 11 55 (str-cat (sym-cat ?ins))))
(deffunction gn (?ins) ?ins)  ;just use instance-name
;=================================================================UPDATEABLE
;anything which is updated/ has a time-stamp /needs an explanation
(defclass UPDATEABLE
 (is-a INITIAL-OBJECT)
 (role concrete)
 (pattern-match reactive)
                                        ;set these in advance
 (slot expl (type STRING)               ;short description
        (create-accessor read-write) (visibility public))
 (slot time (type INTEGER)              ;time of last update
        (create-accessor read-write) (visibility public))
 ;get/put deamons will update, so can be used for 'freshness'/matching
 (slot get-time (type INTEGER)          ;time of last put bind
        (create-accessor read-write) (visibility public))
 (slot put-time (type INTEGER)          ;time of last get request
        (create-accessor read-write) (visibility public))
(slot fresh   (default FALSE)           ;if the proj is newly filled          
        (create-accessor read-write))
)
;-----------------------------------make-fresh
(deffunction make-fresh (?p)
  (send ?p put-fresh TRUE)
  (if (slot-existp (class ?p) params) then
        (map1 make-fresh (send ?p get-params))))
  ;will be done during an unpack & by running appropriate subs ?

;-------------------------------------------updateable INIT after
(defmessage-handler UPDATEABLE init after ()
  (bind ?self:time (round (elapse-time))))
;-------------------
;=================================================================ACCESSIBLE
;-------------------
;used for any instance that will be transmitted between unix processes
(defclass ACCESSIBLE
 (is-a UPDATEABLE) ; (is-a INITIAL-OBJECT)
 (role concrete)
 (pattern-match reactive)

 ;this will be even more of a numeric (rather than str) id, (no necc. msgtag)
 (slot msgtag (type INTEGER)            ;the flag used in the model (vid,fid)
        (create-accessor read-write) (visibility public))
                                        ;set at runtime
 (slot in-task                          ;task it is in   
        (create-accessor read-write) (visibility public))
 (slot in-tid (type INTEGER)            ;task-id it is in                     ??
        (create-accessor read-write) (visibility public))
 (slot count (type INTEGER)             ;number of this type of instance made
        (create-accessor read-write) (storage shared))
)
;-------------------------------------------accessible INIT after
(defmessage-handler ACCESSIBLE init after ()
  (bind ?self:put-time (round (elapse-time)))
  (if (instance-existp ?self:in-task) then
    (printout t "[filling in-tid slot]")
    (bind ?self:in-tid (get-tid ?self:in-task))))
;--------------------------------------------------------GET-TAG(s)
(deffunction get-tag (?acc)      ;send in and accessible|| tag get out a tag
  (if (numberp ?acc) then ?acc else (send ?acc get-msgtag)))

(deffunction get-tags ($?accs)   (map1 get-tag ?accs))        ;outputs the tags

;--------------------------------------------------------
;keep simulated real time/ real clock time ratio   -to see how its doing
;--------------------------------------------------------EOF
;class lib and msg handlers for arrays=(values of params)       M.Bobak,ANL
;--------------------------
;-needs: util.clp 
;--------------------------
;might have some array stuff accessible through PARAM handlers?
;lambda-fncs would still be nice (maybe tcl or scheme)-(has array,vect too)
;output to hdf format for viewing, trans this way?,can do quick mat.calcs

;==============================================================ARRAY
(defclass ARRAY
 (is-a ACCESSIBLE)
 (role concrete)
 (pattern-match reactive)
 (slot count (type INTEGER)             ;number of this type of instance made
        (create-accessor read-write) (storage shared))
 (slot fresh   (default FALSE)          ;if the array is newly filled
        (create-accessor read-write))
;----------------------stuff for the array 0 to 3 dim
 (slot type (default f)                 ;type of the array value (i/f/d/s)
        (create-accessor read-write) (visibility public))
; (multislot index (type INTEGER) (create-accessor read-write)) ;max array index
  (slot lang (type SYMBOL) (create-accessor read-write))        ;FORTRAN or C
 (slot x (type INTEGER) (default 1)     ;1st dimension index
        (create-accessor read-write) (visibility public))
 (slot y (type INTEGER) (default 1)     ;2nd dimension index
        (create-accessor read-write) (visibility public))
 (slot z (type INTEGER) (default 1)     ;3rd dimension index
        (create-accessor read-write) (visibility public))
 (slot num (type INTEGER) (default 1)   ;num of elts
        (create-accessor read-write) (visibility public))
 (slot size (type INTEGER) (default 1)  ;num of elements * #bytes/element
        (create-accessor read-write) (visibility public)) ;can just calc
 (slot val_ptr (type INTEGER)           ;long_int to point to value
        (create-accessor read-write) (visibility public))
;----------------------if array a seperate class fill these
;for viewing & matching, which can be done with (param)arrays
;w/deamons can get and set val_ptr ed space, and update get/put-time
 (slot value                            ;first value (usually only if 111)
        (create-accessor read-write) (visibility public))
 (multislot values                      ;first values (usually only if n11)
        (create-accessor read-write) (visibility public))
)
;-----------------------------------------------------------GET-VALUE
(defmessage-handler ARRAY get-value after ()  ;for debugging
  (printout t "[" (instance-name ?self) " v=" ?self:value "]"))

(deffunction get-value (?p)      ;or (slot-value ?p value)
  (if (slot-existp (class ?p) value) then (send ?p get-value)
   else (printout t "[WARNING:" ?p " does not have a value slot]")) )
(deffunction gv (?p)     (slot-value ?p value))
(deffunction pv (?p ?v)  (send ?p put-value ?v))
;if get rid of value slot have these fncs, then hndlrs too
;(deffunction get-value (?p)      (first (slot-value ?p values)))
;(deffunction put-value (?p ?val) (replace$ (slot-value ?p values) 1 1 ?val))

;-------------------------------------------array INIT after
(defmessage-handler ARRAY init after ()
  (printout t ?self ",")
  (send ?self incr count)
  (bind ?self:num (* ?self:x ?self:y ?self:z))
  (bind ?self:size (* ?self:num (typelen ?self:type)))
  (if (< ?self:val_ptr 999) then (bind ?self:val_ptr (imalloc ?self:size)))
; (if (or (and (instancep ?self:global-name) (neq ?self:global-name [nil])) 
;  (stringp ?self:global-name)) then
;   (make-instance ?self:global-name of ARRAY
;    (x ?self:x) (y ?self:y) (z ?self:z) 
;    (msgtag ?self:msgtag) (val_ptr ?self:val_ptr)))
)

;in the end it might not have the same val_ptr/msgtag-for printing

;-------------------------------------------(array)MPRINT
(defmessage-handler ARRAY mprint primary ()  ;for debugging
  (ptag (nnn ?self:msgtag)))

;-------------------------------------------(array)PUT-INDEX
(defmessage-handler ARRAY put-index ($?indx)  ;sets indecies
  (bind ?self:x (first-dflt ?indx 1))
  (bind ?self:y (second-dflt ?indx 1))
  (bind ?self:z (third-dflt ?indx 1)))

;=======================================================ARRAY STUFF
;'arrays' can be from 0 to 3 dimensions, (single= 1 1 1)
;-------------------------------------------------------Deref Handlers
(defmessage-handler ARRAY deref primary ($?nums)
 (if (<> (length$ ?nums) 0) then (funcall deref ?self:type ?self:val_ptr ?nums)
                            else         (deref ?self:type ?self:val_ptr)))
;-------------------
(defmessage-handler ARRAY deref-off primary (?offset $?nums)
  (if (> ?offset ?self:size) then
    (printout t "WARNING:offset too large " ?offset crlf) (return nil))
  (printout t "[deref-off " ?offset " makes " ?self:val_ptr " into " (+ ?self:val_ptr (* ?offset 4)) "," ?nums "]" crlf)
  (if (<> (length$ ?nums) 0)
     then (funcall deref ?self:type (+ ?self:val_ptr (* ?offset 4)) ?nums)
     else         (deref ?self:type (+ ?self:val_ptr (* ?offset 4)))))
;right now type-size is hard-coded to 4
;-------------------
(defmessage-handler ARRAY zero-to primary (?n)
  (loop-for-count (?i 0 ?self:num) do  (send ?self deref-off ?i ?n)))
;-------------------
(defmessage-handler ARRAY deref-off-n primary (?offset ?n)
  (bind ?top (+ ?offset ?n))
  (bind ?l (create$ ))
  (loop-for-count (?i 0 ?n) do
    (printout t "[" (send ?self deref-off (- ?top ?i)) "]")
    (insert$ ?l 1 (send ?self deref-off (- ?top ?i))))
?l)
;-------------------
(deffunction add2 (?x ?y) (+ ?x ?y))
(deffunction sub2 (?x ?y) (- ?x ?y))
(deffunction div2 (?x ?y) (/ ?x ?y))
(deffunction mul2 (?x ?y) (* ?x ?y))

;maybe ?fnc ?outarray $?array where they could be nums or array
;so array becomes a new wilder m.f.
(defmessage-handler ARRAY deref-fnc2 primary (?fnc ?warray ?outarray $?off-n)
  (bind ?offset (first-dflt ?off-n 0))
  (bind ?n (second-dflt ?off-n ?self:num))
  (bind ?top (+ ?offset ?n))
  (loop-for-count (?i ?offset ?top) do
    (send ?outarray deref-off ?i
      (funcall ?fnc (send ?self deref-off ?i) (send ?warray deref-off ?i)))))

;(get-nprcpk of SUBROUTINE 
; (sub "(send [rainc] deref-fnc2 add2 [rainnc] [nprcpk])"))
;then (call [get-nprcpk]) to calculate it  (do this in bats) rain(n)c state-vars
;-------------------
(defmessage-handler ARRAY check-ptr primary ()
  (if (< (nn ?self:val_ptr) 99) then
    (printout t crlf "[WARNING val_ptr=" ?self:val_ptr "]") (return TRUE)
   else (return FALSE)))

;============================-----------------GET/PUT VALUE DEAMONS
;have a GET-value that does a get-value but gets it from the model 1st
;have a PUT-value that does a put-value then puts it into the model too
;--not needed in the same executable, as you are accessing the same space
;---------------------------------------------
;could just make value a multislot, or just have/use value, for now
;if just have values, can have get/put-value just access the 1st one <-*

;-------------------------PUT       after
(defmessage-handler ARRAY put-value after ($?val)
  (if (< (nn ?self:val_ptr) 99) then
    (printout t crlf "[WARNING val_ptr=" ?self:val_ptr "]") (return nil))
  (if (> ?self:num 1) then
    (printout t crlf "[WARNING you are overwriting the 1st array element"))
  (bind ?self:put-time (elapse-time))
  (printout t "[" (instance-name ?self) " put-v " (send ?self deref) "]")
  (send ?self deref ?val))  ;what put in value slot, goes in val_ptr space 

(defmessage-handler ARRAY put-values after ($?vals)
  (if (< (nn ?self:val_ptr) 99) then
    (printout t crlf "[WARNING val_ptr=" ?self:val_ptr "]") (return nil))
  (bind ?self:put-time (elapse-time))
  (send ?self deref ?vals))  ;what put in values slot, goes in val_ptr space 

;-------------------------GET       before
(defmessage-handler ARRAY get-value before ()
  (if (< (nn ?self:val_ptr) 99) then
    (printout t crlf "[WARNING val_ptr=" ?self:val_ptr "]") (return nil))
  (bind ?self:value (send ?self deref))  ;get value from val_ptr space, &cache 
  (printout t "[" (instance-name ?self) " get-v " ?self:value "]")
  (bind ?self:get-time (elapse-time)))

(defmessage-handler ARRAY get-values before ($?n)
  (if (< (nn ?self:val_ptr) 99) then
    (printout t crlf "[WARNING val_ptr=" ?self:val_ptr "]") (return nil))
  (bind ?self:values (send ?self deref-n (first-dflt ?n 1)))
  (bind ?self:get-time (elapse-time)))
  ;get values from val_ptr space, &cache 
;;;;-------------------------------------------------------------
;remeber the C deref fnc only takes a ptr & if it gets a number it sets it
;so to pick another array loc a handler has to recompute the ptr
;;;;-------------------------------------------------------------
;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-array com code (might change)
;--------------------------
;-needs: util.clp & pvm.clp
;--------------------------
;=======================================array COMMUNICATION (pvm) packing
;can send stride to pk_tpn too
;--------------------------------------------(un)packing using the tpn C fnc
;write a tpn fnc that takes an offset---------actually just alter the old 1 
(defmessage-handler ARRAY pack-it primary ($?n-off)  ;then stride & binary-flag
  (bind ?n (first-dflt ?n-off ?self:num))
  (bind ?off (second-dflt ?n-off 0))
  (bind ?stride (third-dflt ?n-off 1))
  (pk_tpn ?self:type ?self:val_ptr ?n ?off ?stride)
  (send ?self get-value))

(defmessage-handler ARRAY upack-it primary ($?n-off)
  (bind ?n (first-dflt ?n-off ?self:num))
  (bind ?off (second-dflt ?n-off 0))
  (bind ?stride (third-dflt ?n-off 1))
  (pk_tpn (upcase ?self:type) ?self:val_ptr ?n ?off ?stride)
  ;(send ?self mprint)  ;to have the FORTRAN model print out the arrays
  (make-fresh ?self)
  (send ?self get-value))
;--------------------------------------------(un)packing using the pvm_(u)pkbyte
(defmessage-handler ARRAY pack-byte primary ($?s)
  (bind ?s (first-dflt ?s ?self:size))
  (printout t "[pack-byte " ?self:val_ptr ", " ?s "]")
  (pkbyte ?self:val_ptr ?s)
  (send ?self get-value))

(defmessage-handler ARRAY upack-byte primary ($?s)
  (bind ?s (first-dflt ?s ?self:size))
  ;a version of unpkbyte that takes a ptr rather than returning 1
  (printout t "[upkbyte " ?self:val_ptr " " ?s " " ?self:size "]")
  (upkbyte ?self:val_ptr ?s)
  (make-fresh ?self)
  (send ?self get-value))
;--------------------------------------------------------------------
;think about making array's xyz write-once  (unless want to realloc)
; but would be better to just make a new one and transfer the data
;;;;-------------------------------------------------------------EOF
;-------fnc/hndlers to eval stuff on the other side  MTB
;will need util.clp & pvm.clp (a send-str-to fnc)
;=====================
;----------------------------------------EVAL-SEND-TO
(deffunction eval-send-to (?str ?task)
 (send-str-to (str-cat (eval ?str)) ?task))

;will evaluate the string and turn the result into a strin & send it to ?task
;often called remotely to get a result back from an eval
;-more in eval.clp -all use send-str-to

;----------------------------------------SEND-BACK-TO
(deffunction send-back-to (?str ?task $?to-opt)
 (bind ?to-task (first-dflt ?to-opt (mytid)))
 (send-str-to (quotes eval-send-to ?str ?to-task) ?task))

;send a str ready for evaluation to task, it is eval-ed and the result is
; sent back in string form to your task (or optionally to another task).
;--make a send-back-to-param & eval-send-to-param (which sticks it in the value)

;=====================
;----------------------------------------------------EVAL-SEND-TO-ARRAY
(deffunction eval-send-to-array (?str ?task ?array)
 (send-str-to (quotes send ?array put-value (eval ?str)) ?task))

;(send-str-to (quote send ?array put-value (str-cat (eval ?str))) ?task)
;don't want string, but the real value now, make sure it's the right type

;will evaluate the string and turn the result into a strin & send it to ?task
; (& this version puts it in the value slot of the given array)
;often called remotely to get a result back from an eval

;----------------------------------------------------SEND-BACK-TO-ARRAY
(deffunction send-back-to-array (?str ?task ?array)
 (send-str-to (quotes eval-send-to-array ?str (mytid) ?array) ?task))

;?task could default to (mytid) so would always get sent back
;or the other side could do a bufinfo to see what the source is

;send a str ready for evaluation to task, it is eval-ed and the result is
; sent back in string form to your task.
; (& this version puts it in the value slot of the given array)
;---want to make sure that it puts in the correct type

;-might have a version that can send a mf back to the values slot
;-might have a version that lets you pick the slot to put it into -better

;=====================
;a version that 
;lets you return the ?str eval-ed at ?task and put it in the  ?slot of your ?ins

;----------------------------------------------------EVAL-SEND-TO-INS
(deffunction eval-send-to-ins (?str ?task ?ins ?slot)
 (send-str-to (quotes send ?ins (sym-cat put- ?slot) (eval ?str)) ?task))

;----------------------------------------------------SEND-BACK-TO-INS
(deffunction send-back-to-ins (?str ?task ?ins ?slot)
 (send-str-to (quotes eval-send-to-ins ?str (mytid) ?ins ?slot) ?task))

;=================================================================COPY routines=
;----------------------turn slot & value into a parened symbol
(deffunction sv-sym (?ins ?sn)  (quote ?sn (slot-value ?ins ?sn)))
;----------------------------------------------------COPY-NEW-INS-TO
(deffunction copy-new-ins-to (?task ?ins $?sn-s)
 (if (not (instance-existp ?ins)) then
   (printout t "[WARNING: No " ?ins " in copy-ins-to]") (return nil))
 (bind ?sns (if (eq (length ?sn-s) 0) then (slotnames ?ins) else ?sn-s))
 (send-str-to
        (quotes make-instance ?ins of (class ?ins) (map2 sv-sym ?ins ?sns))
        ?task))
;----------------------------------------------------COPY-OLD-INS-TO
(deffunction copy-old-ins-to (?task ?ins $?sn-s)
 (if (not (instance-existp ?ins)) then
   (printout t "[WARNING: No " ?ins " in copy-ins-to]") (return nil))
 (bind ?sns (if (eq (length ?sn-s) 0) then (slotnames ?ins) else ?sn-s))
 (send-str-to
        (quotes modify-instance ?ins of (class ?ins) (map2 sv-sym ?ins ?sns))
        ?task))
;later give another name to copy it too
;;;;-------------------------------------------------------------
;;;;-------------------------------------------------------------EOF

(defclass ConsCell
 (is-a INITIAL-OBJECT)
 (role concrete)
 (pattern-match reactive)

 (slot first (create-accessor read-write))
 (slot rest (create-accessor read-write))
)

;=================================================================SUBROUTINE
;-------can be similar to Lambda Fncs (but no args as of yet)<-(objs for now)*
;used to hold the information on how to run a subroutine in a model
;can include the variables that need to be current to run, and the ones wich
;will be updated/or returned when the subroutine is finished
(defclass SUBROUTINE
 (is-a ACCESSIBLE)
 (role concrete)
 (pattern-match reactive)
 (slot sub                                      ;subroutine code to eval
        (create-accessor read-write))

 (slot busy   (default FALSE)                   ;wether the subroutine is busy
        (create-accessor read-write))

 (slot val_ptr (type INTEGER)                   ;LOC(sub-name) 
        (create-accessor read-write))          ;to be used by DF2
 (multislot args (type INSTANCE)                ;instances it will be called w/
        (create-accessor read-write))          ; used to get arg typ/ptrs &#?

;might not use these-----------------get more data dict
 (multislot vars-needed (type INSTANCE)         ;vars used /needed
        (create-accessor read-write))                  ;can check if updated
 (multislot proj-needed (type INSTANCE)         ;vars used /needed
        (create-accessor read-write))                  ;can check if updated
 (multislot sub-needed (type INSTANCE)          ;vars used /needed
        (create-accessor read-write))                  ;can check if updated
 (slot count (type INTEGER)             ;number of this type of instance made
        (create-accessor read-write) (storage shared))
) ;even id/fid/msgtag because nothing is returned
;-------------------------------------------subroutine INIT after
(defmessage-handler SUBROUTINE init after ()
; (if (and (stringp ?self:expl) (neq ?self:expl "")) then
;     (printout t "[ " ?self:expl " ]"))
  (printout t ?self ","))

;------------------------------------make-busy
(deffunction make-busy (?sub)
  (send ?sub put-busy TRUE))

;------------------------------------------------------CALL
(defmessage-handler SUBROUTINE call primary ()
 (if (stringp ?self:sub) then
  (if (and (stringp ?self:expl) (neq ?self:expl "")) then
      (printout t "[ " ?self:expl " ]"))
  (eval ?self:sub)
  else
     (printout t "[call->ptag " ?self:msgtag "]")
     (ptag ?self:msgtag)
 ))

(deffunction call-a-sub (?sub)
  (if (not (instance-existp ?sub)) then
    (printout t "[WARNING: sub:" ?sub " not there]")
    (return nil)
   else
    (printout t "[sub:" ?sub "]")
    (send ?sub call)))

;takes a list of subs and send the call msg to them
(deffunction call ($?subs)
  (apply-1 call-a-sub ?subs))


;------------------------------------rcall
(deffunction rcall (?task $?subs)
  (send-str-to (quotes call ?subs) ?task)
  (map1 make-busy ?subs))

;=====================================================FUNCTION
;similar to a subroutine instance, but has a specific return value to look at
(defclass FUNCTION
 (is-a SUBROUTINE)
 (role concrete)
 (pattern-match reactive)
 (multislot ret-value           ;a 'future'   to be filled latter
        (create-accessor read-write))
)
;-------------------a handler should construct the ret val send
;(quote send-str ?self:sub ?*my-tid*)
;will use: (send-back-to-param ?str ?task ?param)
;where the string gets eval-ed on the other side and
; the resulting value (not str) is put into the param's value slot

;------------------------------------------------------------------
;------------------------------------------------------------------EOF
;defn & msg-handlers for some of the PARAM class (has-a classes)        MTB
;-sometimes what was a glob-pram will be made of a few of what where loc-params
; should references to them be sent along, or by transfering the 'glob-param'
; does it calc it from the locals, if they have been updated
;=========================================================projection_PARAMeter
;defclass PARAM in param.clp
;=================================================================GRID
(defclass GRID
     (is-a ACCESSIBLE)
     (role concrete)
     (pattern-match reactive)
 (slot units (type SYMBOL)              ;actuall units (eg: ft,mi,m,km,deg) 
        (create-accessor read-write) (visibility public))
 ;could take any 2 opposite corners, but this is easier for now
 (multislot corner-sw (type FLOAT)      ;location of SW-lower corner
        (create-accessor read-write) (visibility public))
 (multislot corner-ne (type FLOAT)      ;location of NE-upper corner
        (create-accessor read-write) (visibility public))
 (multislot delta (type FLOAT)           ;length of delta-x-y-z segments
        (create-accessor read-write) (visibility public))
 (multislot nseg (type INTEGER)          ;# of segments (should=array's xyz)
        (create-accessor read-write) (visibility public))
)
;deg would be in deg-min-sec, but can't do z this way
;will be able to have relation like subgrid-p & eq-sp-subgrid-p
;& fncs like grid-intersection & grid-union
;-----------------------------------------------------------------
;=================================================================UNITS
;SI base-units: meter, kilogram, second, ampere, Kelvin, mole, and candela
;               length, mass, time, current, temprature, mole, illum
;               l(m)    m(kg) t(s)  c(A)     t(K)        (M)   Cnd
;force=newton=kg m / s s
;--might not need an instance for this?  (more just standardization of names)
(defclass UNITS         ;name the instance w/ the basic-unit types (above order)
     (is-a ACCESSIBLE)
     (role concrete)
     (pattern-match reactive)
 (multislot units (type SYMBOL)         ;actuall units (eg: ft / sec sec) orStr?
        (create-accessor read-write) (visibility public))
 (multislot units-type (type SYMBOL)    ;type equiv (eg: length / time time)
        (create-accessor read-write) (visibility public))
 (multislot units-si (type SYMBOL)      ;SI equiv (eg: m / sec sec) [7 types]
        (create-accessor read-write) (visibility public))
 (multislot syn (type SYMBOL)           ;list of eqv unit defns (use member$)
        (create-accessor read-write) (visibility public)))
;have all numerator terms a / then all the denominator terms
;-----------------------------------------------------------------
;=================================================================DESCRIPT
;(defclass DESCRIPT   ;describe         maybe hold constraints -ref?
;    (is-a ACCESSIBLE)
;    (role concrete) 
;    (pattern-match reactive)
;(slot journal (type INSTANCE)        ;list of proceedures applied to the param
;(create-accessor read-write) (visibility public))      
;(slot constr (type INSTANCE)           ;list of constraint instances
;(create-accessor read-write) (visibility public))      
;;maybe put these in contraint objs:
;(multislot range                       ;min & max of the values
;       (create-accessor read-write) (visibility public))       
;(slot default                          ;default value for the array value(s)
;       (create-accessor read-write) (visibility public)))
;for units ft/(sec sec), ft/sec  sec, ft/sec/sec  or num= ft den= sec sec
;range/default values could be another param-inst
; which could mean use its range/default slots or the sep vals of the array
;could have get-actual-min get-actual-max get-mean get-median <-for arrays
;dumping the normed values or histogram of val bins to a fuz-fact ?
;would be nice to make arrays a base clips obj -or not
;------------------------------------------------------------------
;=================================================================CONSTR
(defclass CONSTR   ;constraints 
     (is-a SUBROUTINE)
     (role concrete)
     (pattern-match reactive)
 )
;use the constraint obj that updates slots/params/etc
;make it general, maybe like a subroutine, have good backup fncs
;---------------------------------------------------------------------------
;---still want to have params which are composed of other params,so need map-fnc
;-------------------
;instead of mapping, just have full description which can be mapped between
; (multislot from-var (type SYMBOL)     ;variable(s) mapped from (usually 1)
;       (create-accessor read-write) (visibility public))       
; (slot to-var (type SYMBOL)            ;variable mapped to
;       (create-accessor read-write) (visibility public))       
;;;have to list the model separtely, if no proxy around
;;(multislot from-mod (type SYMBOL)     ;model(s) mapped from (almost always 1)
;       (create-accessor read-write) (visibility public))       
;;(slot to-mod (type SYMBOL)            ;model mapped to
;       (create-accessor read-write) (visibility public))       
; (slot map-fnc (type SYMBOL)           ;fnc to map between them
;       (create-accessor read-write) (visibility public))       ) 
;-------------------
;Linda-like fncs/hndlers should be written around the param-
;------------------------------------------------------------------EOF
;defn & msg-handlers for the PARAM class                        MTB
;-sometimes what was a glob-pram will be made of a few of what where loc-params
; should references to them be sent along, or by transfering the 'glob-param'
; does it calc it from the locals, if they have been updated

;be able to mark if the array is in a model or malloced
;& if that array is in fortran or C format

;=========================================================projection_PARAMeter
(defclass PARAM
 (is-a ACCESSIBLE)
 (role concrete)
 (pattern-match reactive)
 (slot count (type INTEGER)             ;number of this type of instance made
        (create-accessor read-write) (storage shared))
;---------------------------------------------------------------has-a instances
;---------------------description of gridding of data
 (slot grid (type INSTANCE)             ;inst w/gridding info
        (create-accessor read-write) (visibility public))
;---------------------description of gridding of data
 (slot units (type INSTANCE)            ;inst w/units info
        (create-accessor read-write) (visibility public))
;---------------------holds the array (is in array.clp) 
 (slot array (type INSTANCE)            ;inst w/memory &assoc descript
        (create-accessor read-write) (visibility public))
;---------------------holds the constraint instances
 (multislot cnstrs (type INSTANCE)
        (create-accessor read-write) (visibility public))
;---------------------holds the process/sub instances which act of the inst
;=have the lists only be for the current & last simulation timesteps 
;(finest grain or diferrent in each model- except for reasoning)
;-can use something like journal to show the goal state params
; or state at the begin/end of any process  (as the annotation)
;This annotation will have to use the abstract process name  (eg. [srfx])
 (multislot journal (type INSTANCE)   ;would be nice to also add the time
        (create-accessor read-write) (visibility public))
 (multislot journal-time (type INTEGER)   ;time of the journal entry
        (create-accessor read-write) (visibility public))
 (multislot journal-use (type INTEGER)   ;used as in out in-out
        (create-accessor read-write) (visibility public)) ;assume only 'out'?
;-journal might get really long quickly with looping
; easier to keep a journal of calls, & then reconstruct the params-touched ?
;;---------------------description of type of data (meaning??)
; (slot descript (type INSTANCE)        ;might hold constraints
;       (create-accessor read-write) (visibility public))
;----------------------------------------------------------------extra val rep??
;for viewing & matching, which can be done with (param)arrays
;w/deamons can get and set val_ptr ed space, and update get/put-time
 (slot value                            ;first value (usually only if xyz=111)??
        (create-accessor read-write) (visibility public))
 (multislot values                      ;first values(usually only if xyz=n11)??
        (create-accessor read-write) (visibility public)))
;if copy over all the slots, then the refered to instances latter, they can
; be chekced with a sim-time stamp,  and the value(s) slot too
;-----------------------------------------------------------------
;constraints checked when the value is updated  (maybe for get/put  seperately)
; might have w/>1 param  so put in each to be 2way
;-----------------------------------------------------------------
;use descriptive/(standard) names (so could even do defaults from the name)
;defclass GRID   in param-lib.clp
;defclass UNITS  in param-lib.clp
;defclass CONSTR in param-lib.clp
;defclass ARRAY  in array.clp
;if copy param to another task,refer to has-a as needed,use in-task slot to find
;------------------------------------------------------------------
(defmessage-handler PARAM  pack-it primary ($?n-off)
        (send ?self:array  pack-it ?n-off))
(defmessage-handler PARAM upack-it primary ($?n-off)
        (send ?self:array upack-it ?n-off))
;-------------------
;Linda-like fncs/hndlers should be written around the param-
;------------------------------------------------------------------EOF
;defn & msg-handlers for the PROJ class                 MTB
;=================================================================PROJection
(defclass PROJ
 (is-a ACCESSIBLE)
 (role concrete)
 (pattern-match reactive)
 (slot from   (type INSTANCE)           ;where is comes from                  ??
        (create-accessor read-write))
 (slot to   (type INSTANCE)             ;where is goes to                     ??
        (create-accessor read-write))
 (slot for   (type INSTANCE)            ;what subroutine gets called after    ?? 
        (create-accessor read-write))  ;it gets this data (redo so data-driven) 
 (multislot params ;(default (create$)) ;param instances which hold values
    (create-accessor read-write) (visibility public))
)
;-----------------------------------------------------

;-----------------------------------------------------proj SEND-TO
;pack the upk cmd in a string then pack all the params
;(map1 pack-byte ?self:params ?tid) ;then one send

;-----------------------------------------------------(U)PK-(G)-PARAM
(deffunction  pk-param (?param) (send (send ?param get-array) pack-byte))
(deffunction upk-param (?param) (send (send ?param get-array) upack-byte))

;----------------------------------------------------send-to
;(defmessage-handler PROJ send-to primary (?task)
; (if (< (length ?self:params) 1) then 
;       (printout t "[WARNING: PROJ send-to has no params " ?self:params "]"))
; (initsend 1)
;;need to have params stay a mf, but can't (quote (quote)) w/out messed up ""
; (pkstr (quotes map1 upk-param (quote create$ ?self:params))) 
; (map1 pk-param ?self:params)
; (send_0 ?task))
;
;(defmessage-handler PROJ send_to_n primary (?task)
; (initsend 1)
; (pkstr (quotes apply-2 send (quote create$ ?self:params) upack-n)) 
; (apply-2 send ?self:params pack-n)
;;this is more like mark's proj-param-array send
;;(pkstr (quotes apply-2 send (quote create$ ?self:params) upack-byte)) 
;;(apply-2 send ?self:params pack-byte)
; (send_0 ?task))
;then the trecv-eval loop on the other side will get the string & upk the params
;assumes the glob params are set up the same on the other side
;the string that is sent along, runs upk-param which can updates/touchs the inst
;this is more efficient than the presend deem++send, so it should be reworked

;----------------------------------------------------proj SEND_TO
(defmessage-handler PROJ send_to primary (?task $?opt)
 (initsend 1)
 (pkstr (quotes apply-2 send (quote create$ ?self:params) upack-it ?opt))
 (apply-2 send ?self:params pack-it ?opt)
 (send_0 ?task))

;then the trecv-eval loop on the other side will get the string & upk the params
;----------------------
;----------------------------------------------------GET_FROM
;(defmessage-handler PROJ get_from primary (?task $?to-opt)
; (bind ?to-task (first-dflt ?to-opt (mytid))) (initsend 1)
; (pkstr (quotes send  ?self  send_to  ?to-task ?to-opt)) 
; (send_0 ?task)) ;this only works if that proj is on the other side
;could do (send [clim-to-bats-init-proj] get_from [clim] [bats])
;if could assume the proper proj was there (could copy it)

;do by using a send_to for PARAM
(defmessage-handler PROJ get_from primary (?task $?opt)
 (initsend 1)
 (pkstr (quotes apply-2 send (quote create$ ?self:params) send_to (mytid) ?opt))
 (send_0 ?task)) ;this only works if params are on the other side 

 ;(pkstr (quotes apply-2 send (quote create$ ?self:params) pack-it ?opt)) 
 ;(apply-2 send ?self:params pack-it ?opt)

;param version of eval-send-to & send-back-to (in eval.clp)
;----------------------------------------------------
;probably have to reconfigure to synch w/ st
;----------------------------------------------------EOF
;-----------------------------------------------------new:
(defclass TID                                   ;task obj  id  ;mirror globals for now
  (is-a INITIAL-OBJECT)
  (role concrete) (pattern-match reactive)
  (slot tid  (type INTEGER) (create-accessor read-write))       ;task id ([inst] or int id)
  (slot pid  (type INTEGER) (create-accessor read-write))       ;parent task id ([inst] or int id)
  (slot start-time  (type FLOAT) (create-accessor read-write)) ;also was a global ;try diff type
  (slot recv-d-time  (type INTEGER) (create-accessor read-write)) ;also was a global ;does it change w/time?
  (slot elapse-time  (type FLOAT) (create-accessor read-write)) ;was a fact
  (slot model  (type INTEGER) (create-accessor read-write)) ;also was a global
  (multislot inst-tids  (create-accessor read-write)) ;also was a global
)
;------------------------------------------------RULES
;the first rule to run (goes only once/reset), 
;sets globals & some other stuff. 
(defrule startup-TIME
   (initial-fact)
 =>
    ;(add_nrcv_route)
   ;(assert (TIME (rt2)))
   (assert (TIME 0.0))
   (bind ?*my-tid* (mytid))
   (bind ?*parent-tid* (parent))
   (printout t " mytid= " ?*my-tid* crlf)
   (bind ?*start-time* (time))
;-new
  (make-instance mytid of TID ;new
   (start-time ?*start-time*)
   (tid ?*my-tid*)
   (pid ?*parent-tid*)
  )
  ;(send [mytid] put-start-time ?*start-time*)
  ;(send [mytid] put-tid ?*my-tid*)
  ;(send [mytid] put-pid ?*parent-tid*)
;
   ;(make-tasks)                        ;set up the TASK instances
   ;(bcast-str (tasks ?*my-tid*))       ;make sure others get this new 1
   (initsend)
   (agenda)
)

;the problem is after the 1st time test fails, it is never checked again
;until the fact chages,   (could try tick tock w/ nrecv_rout)

;updates the time, and does receives of command-strings
(defrule UPDATE-TIME
   (declare (salience -50))   ;could go up w/time
   ?t <- (TIME ?old-time)
;   (test (neq (rt2) ?old-time))
 =>
   (printout t "UT=" (rt2) " ")
   ;(if (not (nrecv_route)) then (system "sleep 1"))
   (trecv_eval ?*recv-d-time*)
  (send [mytid] put-recv-d-time ?*recv-d-time*)  ;new
  (send [mytid] put-elapse-time (elapse-time))  ;new
   (retract ?t)
   ;(assert (TIME (rt2)))
   ;(assert (TIME (- (time) ?*start-time*)))
   (assert (TIME (elapse-time)))
   (agenda)
)
;-------------------------------------------------context rules
;;;;;;--this is out of date, latest work is in the tmp rul files
;(deffunction find-pp (?ppname)
;   (find-instance (?pp PROVIDED-PARAM)
;      (eq ?pp:gname ?ppname)))
;fix for all.clp -mb  ;no class or gname elsewhere, glenda, howto-fix? ;also not called
(defclass PROVIDED-PARAM  ;add this, as this file was probably lost.
  (is-a PARAM) ;(is-a ACCESSIBLE)
  (role concrete)
  (pattern-match reactive)
   (slot gname (create-accessor read-write))  ;maybe w/glenda? 
)        ;it is used in 'inputs' slot below, so there was even a produced|similar subclass?
(defclass PROCESS  ;add this, as this file was probably lost, which really sucks. -mb
  (is-a ACCESSIBLE)
  (role concrete)
  (pattern-match reactive)
   (multislot inputs (create-accessor read-write))  ;
   (multislot outputs (create-accessor read-write))  ;
   (multislot comp-proc (create-accessor read-write))  ;
)
(deffunction find-pp (?ppname)
   (find-instance ((?pp PROVIDED-PARAM))
      (eq ?pp:gname ?ppname)))
(deffunction maprm (?l1 ?l2) (set-difference ?l1 ?l2)) ;just a guess right now-mb
;-------------------------------------------------FIND-PROC-PROVIDES
(defrule FIND-PROC-PROVIDES
   (declare (salience 5))   ;doing before make-proc-chunks could save time?
   ?p1 <- (object (is-a PROCESS)  (inputs ?in1)  ;mved a paren back up-mb
                                 (outputs ?out1)
                                 (comp-proc ?cp1))
 =>
   ;(map1 find-pp ?in1)  ;gives a list of params that are provided for the proc
   ;this process's params should then be marked as being available
   ; and can be taken out of the active input list
   ;-would be good to save the old list or mark as not matchable
   (send ?p1 put-inputs (maprm (map1 find-pp ?in1) ?in1))
)
;-------------------------------------------------MAKE-PROC-CHUNKS
;make a process out of 2 processes  (refire till no more chunking/its usable)
(defrule MAKE-PROC-CHUNKS
   ?p1 <- (object (is-a PROCESS) (inputs $?in1)
                                 (outputs $?out1)
                                 (comp-proc $?cp1))
   ?p2 <- (object (is-a PROCESS) (inputs $?in2)
                                 (outputs $?out2)
                                 (comp-proc $?cp2))
   (test (and (neq ?p1 ?p2)             ;not combining the same process
              (not (member$ ?p1 ?cp2))  ;process not alread a component
              (not (member$ ?p2 ?cp1))  ;  of a (chunked) process
              (null-lv (intersection ?cp1 ?cp2))))
 =>
   (bind ?int1to2 (intersection ?in1 ?out2))  ;calc any out to input matches
   (bind ?int2to1 (intersection ?in2 ?out1))
   ;if there are any make a chunked process
   (if (full-lv ?int1to2) then (make-instance
                      (sym-cat (instance-name ?p1) -  (instance-name ?p2))
                       of PROCESS
                (inputs (union- ?in1 (set-difference ?in2 ?int1to2)))
                (outputs (union- ?out1 ?out2))
                (comp-proc (create$ ?p1 ?p2 ?cp1 ?cp2))))
   (if (full-lv ?int2to1) then (make-instance
                      (sym-cat (instance-name ?p2)  -  (instance-name ?p1))
                       of PROCESS
                (inputs (union- ?in2 (set-difference ?in1 ?int2to1)))
                (outputs (union- ?out2 ?out1))
                (comp-proc (create$ ?p2 ?p1 ?cp2 ?cp1))))
)
;inputs are all of the first ones and of of the 2nd except what the 1st provieds
;outputs are the combined outputs (even though used, still available-branch out)
;comprised proceedures are the 2 put together & all of there comp-proc s
;-------------------------------------------------
;(sym-cat (format nil "%s-%s" (instance-name ?p1) (instance-name ?p2)))
;-------------------------------------------------EOF