-
Notifications
You must be signed in to change notification settings - Fork 0
/
interface.lisp
182 lines (168 loc) · 7.68 KB
/
interface.lisp
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
;; -*- lisp -*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;**************************************************************************************************
;; FOMUS
;; interface.lisp
;;**************************************************************************************************
(in-package :fomus)
(compile-settings)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INTERFACE SINGLE FUNCTION CALL
(defparameter *fomus-args* nil)
(defun run-fomus (&rest args &key allow-other-keys &allow-other-keys)
(macrolet ((fma () (let ((n (mapcar (lambda (x) (declare (type cons x)) (intern (symbol-name (first x)) :fomus)) +settings+))
(v (mapcar (lambda (k) (declare (type cons k)) (find-symbol (conc-strings "*" (symbol-name (first k)) "*") :fomus)) +settings+)))
#+debug (when (position nil v) (error "Error in FOMUS"))
`(destructuring-bind (&key ,@(mapcar (lambda (x y) (list x y)) n v) &allow-other-keys) args
(progv (quote ,v) (list ,@n)
(fomus-main)))))
(fm () (let ((n (mapcar (lambda (x) (declare (type cons x)) (intern (symbol-name (first x)) :fomus)) +settings+))
(v (mapcar (lambda (k) (declare (type cons k)) (find-symbol (conc-strings "*" (symbol-name (first k)) "*") :fomus)) +settings+)))
#+debug (when (position nil v) (error "Error in FOMUS"))
`(destructuring-bind (&key ,@(mapcar (lambda (x y) (list x y)) n v) other-keys) args
(declare (ignore other-keys))
(progv (quote ,v) (list ,@n)
(fomus-main))))))
(if allow-other-keys
#+(or cmu sbcl) (muffwarn (fma)) #-(or cmu sbcl) (fma)
#+(or cmu sbcl) (muffwarn (fm)) #-(or cmu sbcl) (fm))))
(defun fomus (&rest args)
"Interface function/main entry point:
Runs FOMUS's algorithms on input data or file"
(typecase (first args)
((or string pathname) (fomus-text (first args) (rest args) #'fomus-textexec))
(list (let ((z (mapcar (lambda (x)
(typecase x
(fomuschunk x)
((or string pathname) (fomus-text x (rest args) #'fomus-textexec))
(otherwise (error "Expected LIST of STRING or FOMUSCHUNK"))))
(first args))))
(apply #'run-fomus :chunks z (append (rest args) (loop for e of-type fomuschunk in z append (fomuschunk-settings e))))))
(t (apply #'run-fomus args))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INTERFACE MULTIPLE FUNCTION CALL
(declaim (type list *fomus-global* *fomus-parts* *fomus-events*))
(defparameter *fomus-global* nil)
(defparameter *fomus-parts* nil)
(defparameter *fomus-events* nil)
(defun fomus-init (&rest args)
"Interface function:
Erases stored data and initializes FOMUS for FOMUS-EXEC, FOMUS-NEWTIMESIG,
FOMUS-NEWPART, FOMUS-NEWNOTE, FOMUS-NEWREST and FOMUS-NEWMARK functions"
(progn (setf *fomus-args* args *fomus-global* nil *fomus-parts* nil *fomus-events* nil) t))
(defun fomus-newtimesig (&rest args)
"Interface function:
Creates and stores a TIMESIG object"
(let ((ts (apply #'make-instance 'timesig args)))
(push ts *fomus-global*)
t))
(defun fomus-newpart (partid &rest args)
"Interface function:
Creates and stores a PART object"
(declare (type (or symbol real) partid))
(let ((pa (apply #'make-instance 'part :partid partid args)))
(push pa *fomus-parts*)
t))
(defun fomus-newnote (partid &rest args)
"Interface function:
Creates and stores a NOTE object"
(declare (type (or symbol real) partid))
(let ((no (apply #'make-instance 'note :partid partid args)))
(push no *fomus-events*)
t))
(defun fomus-newrest (partid &rest args)
"Interface function:
Creates and stores a REST object"
(declare (type (or symbol real) partid))
(let ((re (apply #'make-instance 'rest :partid partid args)))
(push re *fomus-events*)
t))
(defun fomus-newmark (partid &rest args)
"Interface function:
Creates and stores a MARK object"
(declare (type (or symbol real) partid))
(let ((re (apply #'make-instance 'mark :partid partid args)))
(push re *fomus-events*)
t))
;;(declaim (inline fomus-part))
(defun fomus-part (sym)
"Utility function:
Returns a PART object given an ID value"
(declare (type (or symbol real) sym))
(find sym *fomus-parts* :key #'part-partid))
;; should this function save additional objects for future calls?
(defun fomus-exec (&rest args)
"Interface function/main entry point:
Runs FOMUS's algorithms on data specified previously with FOMUS-INIT,
FOMUS-NEWTIMESIG, FOMUS-NEWPART, FOMUS-NEWNOTE, FOMUS-NEWREST and FOMUS-NEWMARK"
(unwind-protect
(apply #'run-fomus
:global (append *global* *fomus-global*)
:parts (append *parts* (nreverse *fomus-parts*))
:events (append *events* *fomus-events*)
(append args *fomus-args*))
(fomus-init)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TEXT INTERFACE
(defun fomus-textexec (args)
(apply #'run-fomus
:global (append *global* *fomus-global*)
:parts (append *parts* (nreverse *fomus-parts*))
:events (append *events* *fomus-events*)
(nconc *fomus-args* args)))
(defun fomus-textret (args)
(values
(append *parts* (nreverse *fomus-parts*))
(append *events* *fomus-events*)
(append *global* *fomus-global*)
(nconc *fomus-args* args)))
(defun fomus-text (filename args exe)
(let ((*fomus-args* args)
(*fomus-global* nil)
(*fomus-parts* nil)
(*fomus-events* nil))
(destructuring-bind (&key (verbose *verbose*) &allow-other-keys) args
(when (and (numberp verbose) (>= verbose 1)) (out ";; Loading input file ~S...~%" filename)))
(funcall exe
(let ((li 0) (lin "") (of nil))
(with-open-file (f filename :direction :input)
(handler-case
(flet ((git (rs rrs)
(unless (symbolp rs) (error "Invalid tag ~S" rs))
(when (numberp of)
(let ((m (member :off rrs)))
(when (and m (numberp (second m))) (setf (second m) (+ of (second m))))))
(case (intern (symbol-name rs) :keyword)
(:init (if (find (first rrs) +settings+ :key #'first) rrs (progn (format t ";; WARNING: Unknown setting ~A~%" (first rrs)) nil)))
(:timesig (apply #'fomus-newtimesig rrs) nil)
(:part (apply #'fomus-newpart rrs) nil)
((:note :notes) (destructuring-bind (pa &rest args &key notes &allow-other-keys) rrs
(if notes
(let ((as (member :notes args )))
(setf (first as) :note)
(map nil (lambda (no) (setf (second as) no) (apply #'fomus-newnote pa args)) notes))
(apply #'fomus-newnote pa args)))
nil)
(:rest (apply #'fomus-newrest rrs) nil)
(:mark (apply #'fomus-newmark rrs) nil)
(:off (setf of (first rrs)) nil)
(otherwise (error "Invalid tag ~S" rs)))))
(loop
with *package* = #.(find-package :fomus)
for re = (progn (incf li) (setf lin "") (read f nil 'eof)) until (eq re 'eof)
do (setf lin (format nil "~S ..." re))
if (listp re) nconc (git (first re) (uglify (rest re)))
else nconc (with-input-from-string (st (loop
with st = (read-line f nil "")
for s = (string-right-trim " " st)
while (and (> (length s) 1) (char= (aref s (1- (length s))) #\\))
do (setf st (conc-strings (subseq s 0 (1- (length s))) " " (read-line f))
lin (format nil "~S ~A ..." re st))
finally (setf lin (format nil "~S ~A" re st)) (return st)))
(git re (loop for e = (read st nil 'eof) until (eq e 'eof) collect (uglify e))))))
(error (err)
(error "Entry ~D, ~S: ~A" li (remove-newlines lin) err))))))))
(defun fomus-file (filename &optional args)
"Utility/file IO function:
Loads a \".fms\" file and returns (values parts events global args)"
(fomus-text filename args #'fomus-textret))