fare / xcvb

eXtensible Component Verifier and Builder for Common-Lisp

This URL has Read+Write access

xcvb / computations.lisp
100644 141 lines (113 sloc) 4.761 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#+xcvb (module (:depends-on ("grains" "registry")))
 
(in-package :xcvb)
 
(defclass computation () ())
(defclass computation-type () ())
 
;;(defparameter *computations-inputing-grain*
;; (make-hash-table :test 'equal)
;; "hash mapping each grain to a list of computations that take said grain as input")
 
(defclass concrete-computation (computation)
  ((inputs
    :initarg :inputs
    :accessor computation-inputs)
   (outputs
    :initarg :outputs
    :accessor computation-outputs)
   ;; (side-effects) ; for additional files being side-effected
   (command
    :initarg :command
    :accessor computation-command)))
 
#|
(defgeneric computation-command (type computation &key))
 
(defclass lisp-command ()
((implementation
:initarg :implementation
:initform *lisp-implementation-type*
:accessor lisp-implementation)
(executable
:initarg :executable
:initform *lisp-executable-pathname*
:accessor lisp-executable)
(image
:initarg :image
:initform *lisp-image-pathname*
:accessor lisp-image)
(flags
:initarg :flags
:initform *lisp-flags*
:accessor lisp-flags)))
 
(defun make-lisp-command (&rest r)
(apply #'make-the 'lisp-command r))
 
(defvar *lisp-command* (make-lisp-command))
 
(defun lisp-command-using-image (lisp-command image)
(make-the 'lisp-command
:implementation (lisp-implementation lisp-command)
:executable (lisp-executable lisp-command)
:image image
:flags (lisp-flags lisp-command)))
 
(defclass shell-command (computation-type) ())
 
(defvar *shell-command* (make-the 'shell-command))
 
(defclass concrete-shell-computation (concrete-computation)
())
 
(defclass concrete-lisp-computation (concrete-computation)
())
 
(defmethod computation-command ((s shell-command) (c concrete-shell-computation))
(slot-value c 'command))
 
(defmethod computation-command ((l lisp-command) (c concrete-lisp-computation))
(slot-value c 'command))
 
(defmethod computation-command ((s shell-command) (c concrete-lisp-computation)
&key (lisp-command (make-lisp-command)))
(let* ((a (lisp-invocation-arglist
:implementation-type (lisp-implementation lisp-command)
:lisp-path (lisp-executable lisp-command)
:image-path (lisp-image lisp-command)
:lisp-flags (lisp-flags lisp-command)
:eval (strcat (computation-command l c)
(quit-form 0 (lisp-implementation lisp-command))))))
(shell-tokens-to-string a)))
|#
 
(defgeneric make-computation (env &key))
 
(defmethod make-computation ((env null) &rest keys &key &allow-other-keys)
  (apply #'make-computation 'concrete-computation keys))
 
(defmethod make-computation ((class symbol) &rest keys &key &allow-other-keys)
  (apply #'make-computation (find-class class) keys))
 
(defmethod make-computation ((class standard-class) &rest keys &key &allow-other-keys)
  (let ((computation (apply #'make-instance class keys)))
    (link-computation-outputs computation)
    (push computation *computations*)
    computation))
 
(defun link-computation-outputs (computation)
  (loop :for target :in (computation-outputs computation)
    :for n :from 0 :do
    (when (slot-boundp target 'computation)
      (error "Grain ~S already is the output of an existing computation!" target))
    (setf (grain-computation target) computation
          (grain-computation-index target) n)))
 
(defun make-nop-computation (dependencies &optional targets)
  (make-computation ()
                    :inputs dependencies
                    :outputs targets
                    :command nil))
 
(defun make-phony-grain (&key name dependencies)
  (let* ((grain (make-grain 'phony-grain :fullname name)))
    (make-nop-computation dependencies (list grain))
    grain))
 
(defmethod print-object ((x computation) stream)
  (print-unreadable-object (x stream :type t :identity nil)
    (with-slots (inputs outputs command) x
    (format stream ":inputs ~S :outputs ~S :command ~S"
            (mapcar #'fullname inputs)
            (mapcar #'fullname outputs)
            command))))
 
(defun computation-target (computation)
  (first (computation-outputs computation)))
 
(defun grain-computation-target (grain)
  (let ((computation (grain-computation grain)))
    (if computation
      (computation-target computation)
      grain)))
 
;;; TODO: use a more declarative model to describe the various types of objects
;;; and the types of relations between them within a given first-class context,
;;; so that there can be pure functions from context to context,
;;; mapping sets of facts (atoms and relationships) to sets of facts.
;;; make good use of linear relationships for in-place modification,
;;; automatically create indices, etc.