updated-parameters.scm 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2023 Sarthak Shah <shahsarthakw@gmail.com>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  7. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  8. ;;; under the terms of the GNU General Public License as published by
  9. ;;; the Free Software Foundation; either version 3 of the License, or (at
  10. ;;; your option) any later version.
  11. ;;;
  12. ;;; GNU Guix is distributed in the hope that it will be useful, but
  13. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;;; GNU General Public License for more details.
  16. ;;;
  17. ;;; You should have received a copy of the GNU General Public License
  18. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  19. (define-module (guix parameters)
  20. #:use-module (guix diagnostics)
  21. #:use-module (guix i18n)
  22. #:use-module (guix packages)
  23. #:use-module (guix profiles)
  24. #:use-module (guix records)
  25. #:use-module (guix transformations)
  26. #:use-module (srfi srfi-1)
  27. #:use-module (srfi srfi-13)
  28. #:use-module (srfi srfi-26)
  29. #:use-module (srfi srfi-34)
  30. #:use-module (srfi srfi-35)
  31. #:use-module (ice-9 hash-table)
  32. #:use-module (ice-9 match)
  33. #:use-module (ice-9 receive)
  34. #:export (package-parameter
  35. parameter-type
  36. parameter-spec
  37. boolean-parameter-type
  38. parameter-variant
  39. parameter-variant-match
  40. parameter-spec-property
  41. package-parameter-spec
  42. all-spec-parameters
  43. base-parameter-alist
  44. parameter-spec-override-plist
  45. parameter-spec-validate
  46. spec-resolve-list
  47. %global-parameters
  48. define-global-parameter
  49. package-with-parameters
  50. parameter-spec-parameter-alist
  51. parameter-if
  52. parameter-if-all
  53. parameter-match-any
  54. parameter-match-all
  55. parameter-match-case-any
  56. parameter-match
  57. parameter-match-case
  58. parameter-modify-inputs))
  59. ;;; Commentary:
  60. ;;;
  61. ;;; This module provides a way to express high-level "package parameters",
  62. ;;; which allow users to customize how packages are built. Parameters are an
  63. ;;; interface that package developers define, where each parameter has a name
  64. ;;; and type. The user interface then converts parameter values from string
  65. ;;; to Scheme values and records them in the package properties.
  66. ;;;
  67. ;;; Package parameters are discoverable; their description is
  68. ;;; internationalized. The possible values of a parameter can be enumerated,
  69. ;;; and thus the Cartesian product of all possible parameter values for a
  70. ;;; package can be enumerated as well.
  71. ;;;
  72. ;;; Code:
  73. (define (give-me-a-symbol ex)
  74. (cond ((symbol? ex) ex)
  75. ((string? ex) (string->symbol ex))
  76. (else (throw 'bad-give-me-a-sym ex))))
  77. (define-record-type* <parameter-type> parameter-type
  78. make-parameter-type
  79. parameter-type?
  80. this-parameter-type
  81. (name parameter-type-name
  82. (sanitize give-me-a-symbol))
  83. (accepted-values parameter-type-accepted-values)
  84. (negation parameter-type-negation
  85. (default (car (parameter-type-accepted-values this-parameter-type)))
  86. (thunked))
  87. (default parameter-type-default
  88. (default (if (not (parameter-type-negation this-parameter-type))
  89. (car (parameter-type-accepted-values this-parameter-type))
  90. (cadr (parameter-type-accepted-values this-parameter-type))))
  91. (thunked))
  92. (description parameter-type-description
  93. (default "")))
  94. (define boolean-parameter-type
  95. (parameter-type
  96. (name 'boolean)
  97. (accepted-values '(off on))
  98. (description "Boolean Parameter Type")))
  99. ;; Package parameter interface.
  100. (define-record-type* <package-parameter> package-parameter
  101. make-package-parameter
  102. package-parameter?
  103. (name package-parameter-name
  104. (sanitize give-me-a-symbol))
  105. (type package-parameter-type
  106. (default boolean-parameter-type))
  107. (variants package-parameter-variants
  108. (default '())
  109. (sanitize sanitize-parametric-variants))
  110. (dependencies package-parameter-dependencies ; 7/14
  111. (default '())
  112. (sanitize dependency-sanitizer)
  113. (thunked))
  114. (predicate package-parameter-predicate
  115. (default #f))
  116. (description package-parameter-description (default "")))
  117. ;; TODO: Find a cleaner way to manage global parameters
  118. (define %global-parameters
  119. (alist->hash-table '()))
  120. ;; SANITIZERS
  121. ;; (define (sanitize-package-parameter-name x)
  122. ;; (cond ((string? x)
  123. ;; (if (string= (string-take-right x 1) "!")
  124. ;; (throw "Negation in parameter name!" x) ; we cannot have negation in parameter name!
  125. ;; (string->symbol x)))
  126. ;; ((symbol? x)
  127. ;; (if (string= (string-take-right (symbol->string x) 1) "!")
  128. ;; (throw "Negation in parameter name!" x) ; we cannot have negation in parameter name!
  129. ;; x))
  130. ;; (else (throw 'bad! x))))
  131. ;; (sanitize-package-parameter-name 'x!)
  132. ;; (define (sanitize-build-system-transforms ls)
  133. (define (sanitize-parametric-variants ls)
  134. ;; ((a . t1 t2 ...) ((b c) t3 t4 ...))
  135. (cond ((list? ls) ls)
  136. (else (throw 'bad-variants ls))))
  137. ;; (define-syntax lots-of-cons->alist
  138. ;; (syntax-rules ()
  139. ;; ((_ (a . b))
  140. ;; (list (cons 'a b)))
  141. ;; ((_ (a . b) rest ...)
  142. ;; (cons (cons 'a b)
  143. ;; (lots-of-cons->alist rest ...)))))
  144. ;; (define-syntax build-system/transform
  145. ;; (syntax-rules (-> _)
  146. ;; ((build-system/transform (x ...) -> y ...)
  147. ;; (map (lambda (g)
  148. ;; (cons g (lots-of-cons->alist y ...)))
  149. ;; (list x ...)))
  150. ;; ((build-system/transform _ -> y ...) ; for local parameter definitions
  151. ;; (cons 'any ; matches any build system
  152. ;; (lots-of-cons->alist y ...)))
  153. ;; ((build-system/transform x -> y ...)
  154. ;; (cons x (lots-of-cons->alist y ...)))))
  155. ;; Parameter Variants:
  156. ;; (parameter-variant
  157. ;; (sym + build-system -> morphism-list))
  158. ;; alist->hash-table of the format
  159. ;; ((build-system . ((sym . ((transforms (a . b) ...) ...)) ...)) ...)
  160. ;; % USEFUL HELPER FUNCTIONS %
  161. (define (return-list lst)
  162. (if (list? lst)
  163. lst
  164. (list lst)))
  165. (define (append-everything . things)
  166. (apply append
  167. (map return-list things)))
  168. (define (get-parameter-sym psym)
  169. (match psym
  170. [(a . b) a]
  171. [a a]))
  172. (define* (merge-same-car lst #:optional (carry '()))
  173. ;; Takes an ALIST and merges entries with the same CAR
  174. (define (assq-append alist key cont)
  175. (if (equal? (caar alist) key)
  176. (cons (cons key (append (cdar alist) cont))
  177. (cdr alist))
  178. (cons (car alist) (assq-append (cdr alist) key cont))))
  179. (cond ((null? lst) carry)
  180. ((null? (filter (lambda (y) (equal? (caar lst)
  181. (car y)))
  182. carry))
  183. (merge-same-car (cdr lst) (cons (car lst) carry)))
  184. (else
  185. (merge-same-car (cdr lst)
  186. (assq-append carry (caar lst) (cdar lst))))))
  187. ;; (define-syntax parameter-variant
  188. ;; (syntax-rules (-> + _)
  189. ;; [(%) '()]
  190. ;; [(% _ -> variants ...)
  191. ;; (cons 'any (cons 'any (parameter/parse-variants '(variants ...))))]
  192. ;; [(% _ + _ -> variants ...)
  193. ;; (cons 'any (cons 'any (parameter/parse-variants '(variants ...))))]
  194. ;; [(% sym + _ -> variants ...)
  195. ;; (let ((parsed-variants (parameter/parse-variants '(variants ...))))
  196. ;; (cons 'any (map (lambda (g)
  197. ;; (cons g parsed-variants))
  198. ;; (return-list 'sym))))]
  199. ;; [(% _ + b-system -> variants ...)
  200. ;; (let ((parsed-variants (parameter/parse-variants '(variants ...))))
  201. ;; (map (lambda (g) (cons g (cons 'any parsed-variants)))
  202. ;; (return-list 'b-system)))]
  203. ;; [(% sym + b-system -> variants ...)
  204. ;; (let ((parsed-variants (parameter/parse-variants '(variants ...))))
  205. ;; (map (lambda (g) (cons g (map (lambda (h) (cons h parsed-variants))
  206. ;; (return-list 'sym))))
  207. ;; (return-list 'b-system)))]
  208. ;; [(% sym -> variants ...)
  209. ;; (let ((parsed-variants (parameter/parse-variants '(variants ...))))
  210. ;; (cons 'any (map (lambda (g)
  211. ;; (cons g parsed-variants))
  212. ;; (return-list 'sym))))]))
  213. ;; (parameter-variant (! _ 3) + (a b c) -> #:transform m1 #:rewrite m2 m3 #:modify c3)
  214. ;; NEW SYNTAX
  215. ;; (parameter-morphism (param ...) #:_ _ #:_ _ ...)
  216. ;; BUILD-SYSTEM is just a part of CDR now
  217. (define-syntax parameter-variant
  218. (syntax-rules ()
  219. [(%) '()]
  220. [(% psym variants ...)
  221. (let ((parsed-variants
  222. (parse-kw-list '(variants ...))))
  223. (map (cut cons <>
  224. parsed-variants)
  225. (return-list 'psym)))]))
  226. ;; if we want to use break, (use-modules (srfi srfi-1) (ice-9 receive))
  227. ;;
  228. ;; (define (list-till-kw lst)
  229. ;; (receive (a b)
  230. ;; (break keyword? lst)
  231. ;; (cons a b)))
  232. ;;
  233. ;; (list-till-kw '(a b #:c d e))
  234. ;; (define* (list-till-kw lst #:optional (carry '()))
  235. ;; (cond ((null? lst) (cons (reverse carry) '()))
  236. ;; ((and (not (null? (cdr lst)))
  237. ;; (keyword? (car lst)))
  238. ;; (cons (reverse carry) lst))
  239. ;; (else (list-till-kw (cdr lst) (cons (car lst) carry)))))
  240. (define* (parse-kw-list kw-lst)
  241. (define (list-till-kw lst)
  242. (receive (a b)
  243. (break keyword? lst)
  244. (cons a b)))
  245. (define* (break-keywords lst)
  246. (cond ((null? lst) '())
  247. ((null? (cdr lst)) '())
  248. ((keyword? (car lst))
  249. (let ((next-lst (list-till-kw (cdr lst))))
  250. (cons (cons (keyword->symbol (car lst))
  251. (car next-lst))
  252. (break-keywords (cdr next-lst)))))
  253. (else (throw 'bad-break-kw lst))))
  254. (merge-same-car (break-keywords kw-lst)))
  255. ;; (define-syntax build-system/transform-match
  256. ;; (syntax-rules ()
  257. ;; ((_ (x ...))
  258. ;; (list
  259. ;; (build-system/transform x ...)))
  260. ;; ((_ (x ...) rest ...)
  261. ;; (cons
  262. ;; (build-system/transform x ...)
  263. ;; (build-system/transform-match rest ...)))))
  264. ;; (parse-kw-list '(#:transform a (b c) #:rewrite d #:transform h))
  265. ;; The lock here is used to signal when merge-same-car is to be used
  266. ;; having a :lock means merge-same-car has been used further up the tree
  267. ;; note that :lock is not a keyword but a symbol, as we are using keywords elsewhere
  268. (define-syntax parameter-variant-match
  269. (syntax-rules (:lock)
  270. ((% :lock (x ...))
  271. (return-list
  272. (parameter-variant x ...)))
  273. ((% :lock (x ...) rest ...)
  274. (append
  275. (return-list (parameter-variant x ...))
  276. (parameter-variant-match :lock rest ...)))
  277. ((% rest ...)
  278. (map
  279. (lambda (ls) (cons (car ls)
  280. (merge-same-car (cdr ls))))
  281. (merge-same-car
  282. (parameter-variant-match :lock rest ...))))))
  283. ;; (use-modules (ice-9 pretty-print))
  284. ;; (pretty-print
  285. ;; (parameter-variant-match
  286. ;; ((a b c) #:build-system (d e f) #:transform (x _) y #:rewrite z)
  287. ;; (g #:transform u)))
  288. (define (local-sanitizer ls)
  289. (if (list? ls)
  290. (map (lambda (val)
  291. (cond ((package-parameter? val) val)
  292. ((symbol? val) (package-parameter (name val)))
  293. ((string? val) (package-parameter (name (string->symbol val))))
  294. (else (throw 'bad-local-val val))))
  295. ls)
  296. (throw 'bad-local-list ls)))
  297. ;; (use-modules (ice-9 match))
  298. ;; (define (morphism-sanitizer lv) ; ((a^ m) ((b sym) m2) c ((d sym1 sym2 ...) m3) ...)
  299. ;; (define (default-morphism? psym) ; check if parameter is given as parameter^
  300. ;; ;; TAKE SPECIAL CARE:
  301. ;; ;; As we are treating ^ as a special character,
  302. ;; ;; it will trim it away from the parameter symbol.
  303. ;; ;; DO NOT USE IT AT THE END OF THE PARAMETER!
  304. ;; (or (and (string=? (string-take-right (symbol->string psym) 1) "^")
  305. ;; (string->symbol (string-drop-right (symbol->string psym) 1)))
  306. ;; (and (string=? (string-take-right (symbol->string psym) 2) "^!")
  307. ;; (string->symbol (string-append (string-drop-right (symbol->string psym) 2)
  308. ;; "!")))))
  309. ;; (define (default-morphism-list psym)
  310. ;; (or (find (lambda (g) (eqv? psym
  311. ;; (package-parameter-name g)))
  312. ;; lv)
  313. ;; (hash-ref %global-parameters psym)
  314. ;; (throw 'bad! psym)))
  315. ;; (lambda (ls)
  316. ;; (map
  317. ;; (match-lambda
  318. ;; [psym
  319. ;; ;; default morphism for psym
  320. ;; (list
  321. ;; (cons psym
  322. ;; (default-morphism-list psym)))]
  323. ;; [((psym vals ...) m)
  324. ;; ;; assign morphism to psym at vals
  325. ;; (let ((variants (if (keyword? (car m))
  326. ;; (parameter/parse-variants m)
  327. ;; m)))
  328. ;; (map (lambda (x) (cons x variants))
  329. ;; (return-list vals)))]
  330. ;; [((? default-morphism? psym) sym)
  331. ;; ;; get default morphism at sym
  332. ;; (let ((csym (default-morphism? psym)))
  333. ;; (list
  334. ;; (cons (cons csym sym)
  335. ;; (default-morphism-list csym))))]
  336. ;; [(psym m)
  337. ;; ;; morphism for psym
  338. ;; (let ((variants (if (keyword? (car m))
  339. ;; (parameter/parse-variants m)
  340. ;; m)))
  341. ;; (list
  342. ;; (cons psym variants)))]
  343. ;; [x
  344. ;; (throw 'bad! x)])
  345. ;; ls)))
  346. ;; 8/18 USE VARIANTS PROBLEMS
  347. ;; p -> interpreted as p _
  348. ;; but users want to use it as a total override in #:no
  349. ;; XXX New USE VARIANTS:
  350. ;; #:yes, #:no only accepts parameter names and not values
  351. ;; #:special only accepts variants
  352. ;; if you wish to fine-tune something #:yes/#:no is not the way to go!
  353. ;; just override it in #:special!
  354. (define* (variant-sanitizer lv)
  355. ;; #:yes -> use default variant
  356. ;; #:no -> don't use variant
  357. ;; #:special -> use variant in cdr
  358. (define (sym->parameter psym)
  359. (display "SYM->PARAMETER: ") (display psym) (newline)
  360. (or (find (lambda (g) (eqv? psym
  361. (package-parameter-name g)))
  362. lv)
  363. (hash-ref %global-parameters psym)
  364. (throw 'bad-parameter psym)))
  365. (define-macro (assq-ov! asslst key val)
  366. `(set! ,asslst
  367. (assq-set! ,asslst ,key ,val)))
  368. (lambda (ls)
  369. (let ((triad (parse-kw-list ls)))
  370. (if (find (lambda (g) (not (or (eqv? (car g) 'yes)
  371. (eqv? (car g) 'no)
  372. (eqv? (car g) 'special))))
  373. triad)
  374. (error "invalid keyword in use-variant"))
  375. (let ((vars-lst '()))
  376. (map
  377. (match-lambda
  378. [('yes rest ...)
  379. (map
  380. (lambda (p)
  381. (if (not (symbol? p))
  382. (throw 'bad-symbol! p)
  383. (assq-ov! vars-lst p #:yes)))
  384. rest)]
  385. [('no rest ...)
  386. (map
  387. (lambda (p)
  388. (if (not (symbol? p))
  389. (throw 'bad-symbol! p)
  390. (assq-ov! vars-lst p #:no)))
  391. rest)]
  392. [('special rest ...)
  393. (map
  394. (lambda (x)
  395. (assq-ov! vars-lst
  396. (car x)
  397. (cdr x)))
  398. rest)]
  399. [_ (error "wrongly formatted use-variant!")])
  400. triad)
  401. (map
  402. (lambda (x)
  403. (match (assq-ref vars-lst (package-parameter-name x))
  404. [#f (assq-ov! vars-lst
  405. (package-parameter-name x)
  406. (package-parameter-variants x))]
  407. [#:yes (assq-ov! vars-lst
  408. (package-parameter-name x)
  409. (package-parameter-variants x))]
  410. [#:no #f] ; do nothing
  411. [varn (assq-ov! vars-lst
  412. (package-parameter-name x)
  413. varn)]))
  414. lv)
  415. (display "SANITIZED VARLST: ") (display vars-lst) (newline)
  416. vars-lst))))
  417. ;; (let ((local-no '())
  418. ;; (variant-lst '()))
  419. ;; (set! variant-lst
  420. ;; (apply append
  421. ;; (map
  422. ;; (match-lambda
  423. ;; [(yes rest ...)
  424. ;; (return-list
  425. ;; (map (lambda (y)
  426. ;; (cons (get-parameter-sym y) ; FIX the other thing
  427. ;; (package-parameter-variants
  428. ;; (sym->parameter
  429. ;; (get-parameter-sym y)))))
  430. ;; rest))]
  431. ;; [(no rest ...)
  432. ;; ;; XXX: set the entry in the variant list to empty..?
  433. ;; ;; BAD IDEA -> could lead to re-evaluation of existing pkgs
  434. ;; (and (set! local-no
  435. ;; (append
  436. ;; (return-list
  437. ;; (filter (lambda (g)
  438. ;; (member (package-parameter-name g)
  439. ;; rest))
  440. ;; lv))
  441. ;; local-no))
  442. ;; '())]
  443. ;; [(special rest ...)
  444. ;; (return-list
  445. ;; (map
  446. ;; (lambda (x)
  447. ;; (cons (car x)
  448. ;; (sanitize-parameteric-variants (cdr x))))
  449. ;; rest))]
  450. ;; [_ (error "wrongly formatted use-variant!")])
  451. ;; triad)))
  452. ;; (append variant-lst
  453. ;; (return-list
  454. ;; (map (lambda (z)
  455. ;; (cons (package-parameter-name z)
  456. ;; (package-parameter-variants z)))
  457. ;; (filter (lambda (g)
  458. ;; (not (member g
  459. ;; local-no)))
  460. ;; lv))))))))
  461. ;; parameter-dependency
  462. ;; now a sanitizer
  463. ;; '(#:parameter a b ... #:package c d ...)
  464. ;; '(a b c) -> parameter
  465. (define (dependency-sanitizer deps)
  466. (and (display "SANITIZING DEPS") (newline))
  467. (unless (eqv? deps '())
  468. (if (not (list? deps)) (throw 'bad! deps))
  469. (if (keyword? (car deps))
  470. (if (match (car deps)
  471. [#:package #t]
  472. [#:parameter #t]
  473. [_ #f])
  474. (and (display (assq-ref (parse-kw-list deps) 'parameter)) (newline)
  475. (parse-kw-list deps))
  476. (throw 'bad-keyword! (car deps)))
  477. (dependency-sanitizer (cons #:parameter deps)))))
  478. ;; (define-syntax parameter/dependency
  479. ;; (lambda (defn)
  480. ;; (syntax-case defn (->)
  481. ;; [(% p-lst -> rest ...)
  482. ;; (syntax
  483. ;; (let ((morphism-list (return-list '(rest ...))))
  484. ;; (map
  485. ;; (lambda (x)
  486. ;; (cons x
  487. ;; (parameter/parse-variants (if (keyword? (car morphism-list))
  488. ;; morphism-list
  489. ;; (cons #:parameters morphism-list)))))
  490. ;; (return-list 'p-lst))))])))
  491. ;;
  492. ;; ;; (parameter/dependency (a b) -> #:parameters a b #:packages d)
  493. ;; ;; (parameter/dependency (a (b yyy)) -> m n o)
  494. ;;
  495. ;; (define-syntax parameter/dependency-match
  496. ;; (syntax-rules (:lock _ ->)
  497. ;; ((% :lock (x ...))
  498. ;; (parameter/dependency x ...))
  499. ;; ((% :lock (x ...) rest ...)
  500. ;; (append
  501. ;; (parameter/dependency x ...)
  502. ;; (parameter/dependency-match :lock rest ...)))
  503. ;; ((% rest ...)
  504. ;; (merge-same-car
  505. ;; (parameter/dependency-match :lock rest ...)))))
  506. ;; (parameter/dependency-match
  507. ;; (a -> k)
  508. ;; ((a b) -> #:parameters a b #:packages d)
  509. ;; ((a (b yyy)) -> m n o))
  510. ;; thunked -> we can do stuff like (parameter-spec-optional-parameters ps) to get the optional parameters
  511. (define-record-type* <parameter-spec> parameter-spec
  512. make-parameter-spec
  513. parameter-spec?
  514. this-parameter-spec
  515. ;; local-parameters: parameters specific to the package
  516. (local parameter-spec-local
  517. ;; keeping it as an alist as it will be useful to retrieve them for the UI
  518. (default '())
  519. (sanitize local-sanitizer) ; morphism-update: all good!
  520. (thunked))
  521. ;; 6/15: Pjotr recommended using a global hash table instead.
  522. ;; See: (define-global-parameter), %global-parameters
  523. ;; Lines commented out due to this will have an 'x615' next to them
  524. ;; (global parameter-spec/global ;; global parameters used must be declared
  525. ;; (default '())
  526. ;; (sanitizer (lambda (ls)
  527. ;; (map (lambda (val) ; they must be package parameters
  528. ;; (if (package-parameter? val)
  529. ;; val
  530. ;; (throw 'bad! val)))
  531. ;; ls)))
  532. ;; (thunked))
  533. (defaults parameter-spec-defaults ; '(a b c d ...) -> '(a (b sym) (c sym2) e! ...)
  534. (default '())
  535. (thunked))
  536. (required parameter-spec-required
  537. (default '())
  538. (thunked))
  539. (optional parameter-spec-optional
  540. (default '()) ; 6/16: causing problems with all-spec-parameters
  541. ;; 6/13: removed the sanitizer as merging local and optional
  542. ;; should be handled by the parser instead.
  543. (thunked))
  544. (one-of parameter-spec-one-of
  545. (default '())
  546. (thunked))
  547. ;; add dependencies
  548. ;; (dependencies (parameter/dependencies
  549. ;; (a b -> d e f)
  550. ;; (c -> g h)))
  551. (dependencies parameter-spec-dependencies
  552. (default '())
  553. (sanitize dependency-sanitizer)
  554. (thunked))
  555. ;; 7/14 : Moved to the package-parameter record
  556. (combinations-with-substitutes
  557. parameter-spec-combinations-with-substitutes
  558. (default parameter-spec-defaults)
  559. (thunked))
  560. ;; (use-transforms parameter-spec/use-transforms ;; only use transforms for these
  561. ;; (default '())
  562. ;; (sanitize (transform-sanitizer (parameter-spec/local this-parameter-spec)))
  563. ;; (thunked))
  564. (use-variants parameter-spec-use-variants ;; only use variants for these
  565. (default '())
  566. (sanitize (variant-sanitizer
  567. (parameter-spec-local this-parameter-spec)))
  568. (thunked))
  569. (parameter-alist parameter-spec-parameter-alist ;; this is ultimately what will be transformed by --with-parameters
  570. ;; '((a . #t) (b . #f) ...)
  571. (default (base-parameter-alist this-parameter-spec)) ; if this doesn't work some tricks might be needed
  572. (thunked)))
  573. ;; g23: Most parameters should be boolean
  574. ;; Might make sense to add a recursive type
  575. ;; (define boolean-parameter-type
  576. ;; ;; The Boolean parameter type.
  577. ;; (parameter-type (name 'boolean)
  578. ;; (accepted-values '(#t #f))
  579. ;; (value->string
  580. ;; (match-lambda
  581. ;; (#f "off")
  582. ;; (#t "on")))
  583. ;; (string->value
  584. ;; (lambda (str)
  585. ;; (cond ((string-ci=? str "on")
  586. ;; #t)
  587. ;; ((string-ci=? str "off")
  588. ;; #f)
  589. ;; (else
  590. ;; (raise (condition
  591. ;; (&message (message "wrong value"))))))))))
  592. (define-syntax parameter-spec-property
  593. (syntax-rules ()
  594. [(parameter-spec-property body ...)
  595. (cons 'parameter-spec
  596. (parameter-spec body ...))]))
  597. ;; (define-syntax package-with-parameters
  598. ;; (syntax-rules ()
  599. ;; [(package-with-parameters body ...)
  600. ;; (let ((the-package (package body ...)))
  601. ;; ((options->transformation
  602. ;; (apply append
  603. ;; (let ((the-build-system (package-build-system the-package)))
  604. ;; (map (lambda (x)
  605. ;; (transform-for-build-system
  606. ;; (assq-ref (parameter-spec/use-transforms
  607. ;; (package-parameter-spec the-package))
  608. ;; (car x))
  609. ;; the-build-system))
  610. ;; (filter (lambda (x) (eqv? #t (cdr x)))
  611. ;; (parameter-spec/parameter-alist
  612. ;; (package-parameter-spec the-package)))))))
  613. ;; the-package))]))
  614. ;; Function for package-with-parameters
  615. ;; reason why it's outside its defn:
  616. ;; too huge, macroexpansion will become unhelpful in case of a bug
  617. ;; this fn will be applied to applicable variants
  618. ;; varlst -> [(<psym cons> . options) (<psym cons> . options) ...]
  619. ;; inner function
  620. ;; PKG: package record
  621. ;; VARS: [(psym val) (OPTION . (option args) ...) (OPTION-2 ...) ...]
  622. (define (apply-variants pkg vars)
  623. ;; sub keywords
  624. (define* (sub-kw-t in #:optional (ret '()))
  625. (if (null? in)
  626. (match (reverse ret)
  627. [(a . rest)
  628. (cons a (string-join rest "="))])
  629. (sub-kw-t
  630. (cdr in)
  631. (cons
  632. (match (car in)
  633. [#:package-name
  634. (package-name pkg)]
  635. [#:package
  636. pkg]
  637. [#:parameter-value
  638. (cdar vars)]
  639. [x x])
  640. ret))))
  641. (define* (sub-kw in #:optional (ret '()))
  642. (if (null? in)
  643. (reverse ret)
  644. (sub-kw
  645. (cdr in)
  646. (cons
  647. (match (car in)
  648. [#:package-name
  649. (package-name pkg)]
  650. [#:package
  651. pkg]
  652. [#:parameter-value
  653. (cdar vars)]
  654. [x x])
  655. ret))))
  656. (cond [(null? (cdr vars))
  657. (and (display "NULL CDR: ") (display vars) (newline)
  658. pkg)] ; ((psym val))
  659. [(null? (cdadr vars)) ; ((psym val) (option))
  660. (and (display "NULL CDADR: ") (display vars) (newline)
  661. (apply-variants pkg (cons (car vars) (cddr vars))))]
  662. [#t
  663. (and (display "VARS: ") (display vars) (newline)
  664. (match (caadr vars) ; ((psym . val) . (<option> optargs) ...)
  665. ('build-system
  666. ;; halt execution if it does not match
  667. (if
  668. (member (package-build-system the-package)
  669. (cdadr vars)) ; will be a list of build systems
  670. (apply-variants pkg (cons (car vars)
  671. (cddr vars)))
  672. pkg))
  673. ('transform
  674. (apply-variants
  675. ((options->transformation
  676. ;; multiple
  677. (map sub-kw-t (return-list (cdadr vars))))
  678. pkg)
  679. (cons (car vars)
  680. (cddr vars))))
  681. ;; modify-inputs is not a priority.
  682. ;; modify-inputs is a macro, and cannot be passed arguments
  683. ;; for now parameter-modify-inputs should be enough
  684. ('lambda
  685. (apply-variants
  686. ;; eval should normally be avoided
  687. ;; but `lambda` as is defined evaluates
  688. ;; code after substituting in keywords
  689. (primitive-eval (and (display "CADADR: ")
  690. (display (cadadr vars))
  691. (newline)
  692. (sub-kw (cadadr vars))))
  693. (cons (car vars)
  694. (cddr vars))))))]))
  695. (define-syntax package-with-parameters
  696. (syntax-rules ()
  697. [(% spec body ...)
  698. (let* [(the-package-0 (package body ...))
  699. (the-package (package
  700. (inherit the-package-0)
  701. (properties
  702. (cons (cons 'parameter-spec
  703. spec)
  704. (package-properties the-package-0)))))]
  705. (define-macro (assq-ov! asslst key val)
  706. `(set! ,asslst
  707. (assq-set! ,asslst ,key ,val)))
  708. (define smoothen
  709. (match-lambda
  710. [(a . #:off)
  711. (cons a
  712. (parameter-type-negation
  713. (package-parameter-type (parameter-spec-get-parameter spec a))))]
  714. [(a . #:default)
  715. (cons a
  716. (parameter-type-default
  717. (package-parameter-type (parameter-spec-get-parameter spec a))))]
  718. [cell cell]))
  719. ;; (define (p-eqv? psym absv relv)
  720. ;; (if
  721. ;; General Idea:
  722. ;; We Extract the Parametric-Variant List
  723. ;; Then we apply each operation in order
  724. ;; big recursive match statement
  725. ;; first get the variant list
  726. (let* [(the-spec ; this value gets called very often
  727. (package-parameter-spec the-package))
  728. (the-parameter-list
  729. (parameter-spec-parameter-alist
  730. the-spec))
  731. (the-variants
  732. ;; XXX rewrite: first get list of normal variants (local, etc)
  733. ;; then match over use-variants
  734. ;; if cdr #:yes, check the-parameter-list for val
  735. ;; if cdr #:no, purge from prev list
  736. ;; if cdr #:special, /replace/ value
  737. (let ((var-lst (parameter-spec-use-variants the-spec)))
  738. (map (lambda (x)
  739. (display "OVERRIDING ") (display var-lst)
  740. (display " WITH ") (display (car x)) (newline)
  741. (set! var-lst
  742. (assq-set! var-lst
  743. (car x)
  744. (package-parameter-variants
  745. (parameter-spec-get-parameter the-spec (car x))))))
  746. (filter (lambda (x)
  747. (display "CHECKING PARAMETER: ") (display x) (newline)
  748. (match (package-parameter-predicate
  749. (parameter-spec-get-parameter
  750. the-spec
  751. (car x)))
  752. [#f #f]
  753. [#t #t]
  754. [fn (fn the-package)]))
  755. (filter
  756. (lambda (x)
  757. (not (assq-ref var-lst (car x)))) ; not in the variant-lst?
  758. the-parameter-list)))
  759. (display "DONE OVERRIDING!") (newline)
  760. (map
  761. (lambda (x)
  762. (match (cdr x)
  763. [#:yes (assq-ov! var-lst
  764. (car x)
  765. (package-parameter-variants
  766. (parameter-spec-get-parameter the-spec (car x))))]
  767. [#:no (set! var-lst
  768. (assq-remove! var-lst
  769. (car x)))]
  770. [_ #f]))
  771. var-lst)
  772. var-lst))
  773. ;; (append-everything
  774. ;; ;; add GLOBAL variants from the-parameter-list
  775. ;; (map (lambda (x)
  776. ;; (let ((z (parameter-spec-get-parameter
  777. ;; the-spec (get-parameter-sym x))))
  778. ;; (cons (package-parameter-name z)
  779. ;; (package-parameter-variants z))))
  780. ;; (filter (lambda (x)
  781. ;; (display "CHECKING PARAMETER: ") (display x) (newline)
  782. ;; (match (package-parameter-predicate
  783. ;; (parameter-spec-get-parameter
  784. ;; the-spec
  785. ;; x))
  786. ;; [#f #f]
  787. ;; [#t #t]
  788. ;; [fn (fn the-package)]))
  789. ;; ;; XXX: merge with use-variants list
  790. ;; ;; give use-variants precedence
  791. ;; ;; check if #:no
  792. ;; ;; exceptions: #:BLOCK-ALL, #:EVERYTHING
  793. ;; (let ((local-plist
  794. ;; (map (cut package-parameter-name <>)
  795. ;; (parameter-spec-local the-spec))))
  796. ;; (filter (lambda (x)
  797. ;; (not (member (car x) local-plist)))
  798. ;; the-parameter-list))))
  799. ;; (parameter-spec-use-variants
  800. ;; the-spec)))
  801. (use-variant-printing (and (display "USE VARIANTS: ")
  802. (display (parameter-spec-use-variants the-spec)) (newline)))
  803. ;; applicable variants -> parameter cell matches the-variants
  804. ;; we must use a modified m+eqv? here (resolves #:off, #:default)
  805. (variant-printing (and (display "ALL VARIANTS: ")
  806. (display the-variants) (newline)))
  807. (applicable-variants
  808. (map (lambda (y)
  809. (cons (cons (car y)
  810. (assq-ref the-parameter-list (car y)))
  811. (apply append
  812. (map (lambda (x)
  813. (return-list (cdr x)))
  814. (cdr y)))))
  815. ;; does it have values?
  816. (filter (lambda (x) (not (null? (cdr x))))
  817. (filter ;; get list of applicable values
  818. (lambda (x)
  819. (display "TESTING FOR APPLICABILITY: ")
  820. (display x) (newline)
  821. ;;; XXX: check for cases like _, #:off etc
  822. ;; filter over values within psym's list
  823. (let* ((absv (assq-ref the-parameter-list (car x)))
  824. ;; if absv is -ve, only -ve values allowed
  825. ;; if absv is +ve, only +ve and _ allowed
  826. (negv (parameter-type-negation
  827. (package-parameter-type
  828. (parameter-spec-get-parameter the-spec (car x)))))
  829. (defv? (eqv? absv
  830. (parameter-type-default
  831. (package-parameter-type
  832. (parameter-spec-get-parameter the-spec (car x)))))))
  833. (if (eqv? absv negv) ; -ve?
  834. (filter
  835. (lambda (ls)
  836. (match (car ls)
  837. [#:off #t]
  838. [negv #t]
  839. [_ #f]))
  840. (cdr x))
  841. (filter
  842. (lambda (ls)
  843. (match (car ls)
  844. ['_ #t]
  845. [absv #t]
  846. [#:default defv?]
  847. [_ #f]))
  848. (cdr x)))))
  849. (filter (lambda (x) assq-ref the-parameter-list (car x))
  850. the-variants)))))]
  851. (display "APPLICABLE VARIANTS: ")
  852. (display applicable-variants) (newline)
  853. (fold (lambda (vlst pack)
  854. (apply-variants pack vlst))
  855. the-package
  856. applicable-variants)))]))
  857. (define (package-parameter-spec package)
  858. (or (assq-ref (package-properties package) 'parameter-spec)
  859. '()))
  860. ;;; PROCESSING PIPELINE
  861. ;; Convention:
  862. ;; Works on Parameters? -> parameter-spec/fun
  863. ;; Works on Parameter-Spec? -> parameter-spec/fun
  864. (define (parameter-spec-get-parameter pspec pcons)
  865. (let ((psym (get-parameter-sym pcons)))
  866. (or (find (lambda (x)
  867. (eqv? psym
  868. (package-parameter-name x)))
  869. (parameter-spec-local pspec))
  870. (hash-ref %global-parameters psym)
  871. (throw "Parameter not found: " psym))))
  872. (define (parameter-spec-negation-supported? pspec x)
  873. (let ((negv
  874. (parameter-type-negation (package-parameter-type (parameter-spec-get-parameter pspec x)))))
  875. (if negv
  876. negv
  877. '_)))
  878. ;; (define (get-spec-deps pspec lst)
  879. ;; (apply
  880. ;; append
  881. ;; (map
  882. ;; (lambda (x)
  883. ;; (cons x
  884. ;; (assq-ref
  885. ;; (assq-ref (parameter-spec-dependencies pspec) x)
  886. ;; 'parameters)))
  887. ;; lst)))
  888. (define (get-spec-deps pspec psym)
  889. (let ([p (parameter-spec-get-parameter pspec psym)])
  890. (return-list
  891. (assq-ref (package-parameter-dependencies p)
  892. 'parameter))))
  893. ;; 1. Fetching
  894. (define (base-parameter-alist pspec) ; returns base case
  895. ;; '((a . psym) (b . #f) ...)
  896. (let* ((v1 (parameter-process-list ; returns funneled list
  897. (append-everything
  898. (parameter-spec-defaults pspec)
  899. (parameter-spec-required pspec))))
  900. (v2 (parameter-process-list
  901. (append-everything
  902. (apply append
  903. ;; XXX: change to a filter-map
  904. (filter (cut car <>)
  905. (map (cut get-spec-deps pspec <>)
  906. (return-list v1))))
  907. v1))))
  908. ;; funnel will signal duplication err
  909. (display "V1: ") (display v1) (newline)
  910. (display "V2: ") (display v2) (newline)
  911. v2))
  912. ;; 2. Processing
  913. ;; IMPORTANT CHANGE: Symbolic Negation no longer supported (psym!)
  914. (define (parameter-process-list lst)
  915. ;; (define (unexclaim p) ; step 1
  916. ;; (define (negated-sym? p)
  917. ;; (string=? (string-take-right (symbol->string (car (return-list p))) 1) "!"))
  918. ;; (match p
  919. ;; ;; Signal error if p! is in a cell
  920. ;; [((? negated-sym? a) . b) (throw 'negation-in-cell! p)]
  921. ;; [(a . b) p] ; normal cells are OK
  922. ;; [(? negated-sym? a) (cons (string->symbol
  923. ;; (string-drop-right (symbol->string a) 1))
  924. ;; #:off)]
  925. ;; [_ p]))
  926. (define (return-cell p) ; step 2 + 3
  927. (match p
  928. [(a b) (cons a b)]
  929. [(a . b) p]
  930. [a (cons a '_)]))
  931. ;; (define (desugarize p) ; step 4
  932. ;; (match p
  933. ;; ;; [(a . '_) (cons a '_)]
  934. ;; ;; [(a . '!) (cons a #:off)]
  935. ;; [_ p]))
  936. (define (funnel plst) ; step 5
  937. ;; first we will get a list indexed by keys
  938. (define (group-val carry lst)
  939. (display "GROUPING: ") (display lst) (display " AND ") (display carry)
  940. (newline)
  941. (if (null-list? lst)
  942. carry
  943. (let ((v (assq-ref carry (caar lst))))
  944. (group-val
  945. (assq-set! carry (caar lst)
  946. (if v
  947. (cons (cdar lst) v)
  948. ;; We want a list in cdr
  949. (cons (cdar lst) '())))
  950. (cdr lst)))))
  951. (define (figure-out p)
  952. (display "FIGURING OUT: ") (display p) (newline)
  953. (or (and (< (length p) 3)
  954. (or (and (eq? (length p) 1) (car p))
  955. (and (member '_ p)
  956. (car (delq '_ p)))))
  957. (throw 'too-many-elements! p)))
  958. (display "FUNNELING: ") (display (group-val '() plst)) (newline)
  959. (map (lambda (x) (cons (car x)
  960. (figure-out
  961. (delete-duplicates (cdr x)))))
  962. (group-val '() plst)))
  963. (funnel (map ;; (lambda (x) (desugarize (return-cell (unexclaim x))))
  964. return-cell
  965. lst)))
  966. ;; 3. Overriding
  967. ;; This will get us all the parameters
  968. (define (all-spec-parameters pspec) ; for the UI
  969. ;; '(sym-a sym-b ...)
  970. (delete-duplicates
  971. (map get-parameter-sym ; we do not care about the values
  972. (append-everything ; works same as before
  973. (map package-parameter-name
  974. (parameter-spec-local pspec))
  975. (parameter-spec-defaults pspec)
  976. (parameter-spec-required pspec)
  977. ;; We are NOT pulling dependencies at this phase
  978. ;; They will not be influenced by the user parameter alist
  979. (filter (lambda (x) (not (eqv? x '_)))
  980. (apply append (parameter-spec-one-of pspec)))
  981. (parameter-spec-optional pspec)))))
  982. ;; Now we compare it against the PLIST
  983. ;; NOTE: This is the only instance where GLOBAL PARAMETERS may be used
  984. ;; Since referring to the package is not possible, we pass it instead of pspec
  985. (define (parameter-spec-override-plist pkg plist)
  986. (display "OVERRIDE")(newline)
  987. (let* ((pspec (package-parameter-spec pkg))
  988. (all-p (all-spec-parameters pspec))
  989. (filtered-plist (filter (lambda (x) (or (member (car x) all-p)
  990. (and (hash-ref %global-parameters (car x))
  991. ((package-parameter-predicate
  992. (hash-ref %global-parameters (car x)))
  993. ;; NOTE:
  994. ;; <this-package> might not work
  995. ;; might have to capture it in pspec
  996. pkg))))
  997. (parameter-process-list plist)))
  998. (filtered-car (map car filtered-plist))
  999. (remaining-p (filter (lambda (x) (not (member x filtered-car)))
  1000. all-p)))
  1001. (append-everything filtered-plist
  1002. (map (lambda (x) (if (parameter-spec-negation-supported? pspec x)
  1003. (cons x #:off)
  1004. (cons x '_)))
  1005. remaining-p))))
  1006. ;; 4. Funneling
  1007. (define (override-spec-multi-match pspec plst)
  1008. (display "MULTIMATCH")(newline)
  1009. (map
  1010. (match-lambda
  1011. [(a . '_) ;; TODO: iterate through these!
  1012. (cons a
  1013. (cadr (parameter-type-accepted-values (package-parameter-type (parameter-spec-get-parameter pspec a)))))]
  1014. [(a . #:off)
  1015. (cons a
  1016. (parameter-type-negation (package-parameter-type (parameter-spec-get-parameter pspec a))))]
  1017. [(a . #:default)
  1018. (cons a
  1019. (parameter-type-default (package-parameter-type (parameter-spec-get-parameter pspec a))))]
  1020. [cell cell])
  1021. plst))
  1022. ;; 5. Validation
  1023. (define (parameter-spec-validate pspec plst)
  1024. (display "VALIDATING: ") (display plst) (newline)
  1025. (define (process-multi-list lst)
  1026. (apply append
  1027. (map (lambda (x)
  1028. (display x) (display ": ")
  1029. (display (parameter-process-list (list x))) (newline)
  1030. (parameter-process-list (list x)))
  1031. (filter (lambda (x) ;; (display x) (newline)
  1032. (not (eqv? x '_)))
  1033. lst))))
  1034. ;; We want all tests to run
  1035. (let ((works? #t))
  1036. (define (m+eqv? new-val orig-val)
  1037. (display "VALS: ") (display new-val)
  1038. (display " ") (display orig-val) (newline)
  1039. (or (and (eqv? orig-val '_)
  1040. (not (eqv? new-val #:off)))
  1041. (eqv? orig-val new-val)))
  1042. (define (throw+f sym vals)
  1043. (display "Error: ")
  1044. (display sym)
  1045. (display " with values ")
  1046. (display vals)
  1047. (newline)
  1048. (set! works? #f))
  1049. ;; first we check duplication
  1050. ;; a bit unnecessary
  1051. (define (validate/duplication)
  1052. (let ((symlst (map car plst)))
  1053. (unless (eqv? symlst (delete-duplicates symlst))
  1054. (throw+f 'duplicates plst))))
  1055. ;; logic checking checks for:
  1056. ;; - presence of required parameters
  1057. ;; - 'one-of' conflicts
  1058. ;; - dependency satisfaction
  1059. (define (validate/logic)
  1060. (map ; required
  1061. (lambda (x)
  1062. (unless
  1063. (let ((new-val (assq-ref plst (car x))))
  1064. (m+eqv? (if (eqv?
  1065. new-val
  1066. (parameter-spec-negation-supported?
  1067. pspec
  1068. (car x)))
  1069. #:off new-val)
  1070. (cdr x)))
  1071. (throw+f 'unsatisfied-requirement x)))
  1072. (parameter-process-list ; cannot have duplicates here!
  1073. (parameter-spec-required pspec)))
  1074. (map ; one-of
  1075. (lambda (ls)
  1076. (unless
  1077. (let ((satisfied (count
  1078. (lambda (x)
  1079. (let ((new-val (assq-ref plst (car x))))
  1080. (m+eqv?
  1081. (if
  1082. (eqv? new-val
  1083. (parameter-spec-negation-supported?
  1084. pspec
  1085. (car x)))
  1086. #:off new-val)
  1087. (cdr x))))
  1088. (process-multi-list ls)))) ; duplicates could happen!
  1089. (or (= satisfied 1)
  1090. (and (= satisfied 0)
  1091. (eqv? (car ls) '_))))
  1092. (throw+f 'one-of-unsatisfied ls)))
  1093. (parameter-spec-one-of pspec))
  1094. (and (display "STARTING DEPLOOPS") #t)
  1095. (unless (not (member #f
  1096. (return-list
  1097. (map (lambda (x)
  1098. (let ((deps (package-parameter-dependencies
  1099. (parameter-spec-get-parameter pspec x))))
  1100. (display "DEPS: ") (display deps) (newline)
  1101. (if deps
  1102. (not
  1103. (member
  1104. #f
  1105. (map
  1106. (lambda (dep)
  1107. ;; 0. restructure d to a proper cell
  1108. (let ([ok (and (display "DEPLOOP: ")
  1109. (display dep) (newline)
  1110. 2)]
  1111. (d (car
  1112. (parameter-process-list
  1113. (return-list dep)))))
  1114. ;; 1. assq-ref
  1115. (m+eqv?
  1116. (assq-ref plst (car d))
  1117. (cdr d))))
  1118. (return-list
  1119. ;;; XXX: check for packages
  1120. ;; not doable in the current state as the validator
  1121. ;; does not take the entire package as an argument
  1122. ;; the validator will have to be heavily modified
  1123. (assq-ref deps 'parameter)))))
  1124. #t)))
  1125. ;; filter to check if parameter is not its negation
  1126. (filter (lambda (x)
  1127. (display "CHECKING: ") (display x) (newline)
  1128. (not (eqv? (cdr x)
  1129. (parameter-spec-negation-supported?
  1130. pspec
  1131. (car x)))))
  1132. plst)))))
  1133. (throw+f "Bad dependencies!"))
  1134. ;; XXX: Needs a per-parameter rewrite
  1135. ;; (map ; dependencies
  1136. ;; (lambda (x)
  1137. ;; (let ([deplst (parameter-process-list
  1138. ;; (assq-ref
  1139. ;; (assq-ref (parameter-spec-dependencies pspec) x)
  1140. ;; 'parameters))])
  1141. ;; (map
  1142. ;; (lambda (y)
  1143. ;; (unless (m+eqv? (assq-ref plst (car y))
  1144. ;; (cdr y))
  1145. ;; (throw+f 'dependency-unsatisfied y)))
  1146. ;; deplst)))
  1147. ;; plst)
  1148. )
  1149. (validate/duplication)
  1150. (validate/logic)
  1151. ;; (display "DOES IT WORK? ") (display works?) (newline)
  1152. works?))
  1153. ;; need pkg instead of pspec for override-spec
  1154. (define (spec-resolve-list pkg plst)
  1155. (let* ([pspec (package-parameter-spec pkg)]
  1156. [proper-plst (override-spec-multi-match
  1157. pspec
  1158. (parameter-spec-override-plist
  1159. pkg
  1160. (parameter-process-list plst)))])
  1161. ;; (display "TRIALS OVER?")(newline)
  1162. (if (parameter-spec-validate pspec proper-plst)
  1163. proper-plst
  1164. (base-parameter-alist pspec))))
  1165. ;; %global-parameters: hash table containing global parameters ref'd by syms
  1166. (define-syntax define-global-parameter
  1167. (syntax-rules ()
  1168. [(define-global-parameter parameter-definition)
  1169. (let ((gp-val parameter-definition))
  1170. (hash-set! %global-parameters
  1171. (package-parameter-name gp-val)
  1172. gp-val))]))
  1173. ;; (define-global-parameter (package-parameter
  1174. ;; (name "tests!")
  1175. ;; (description "no tests")))
  1176. ;; Works!
  1177. (define-syntax parameter-inside?
  1178. (syntax-rules ()
  1179. [(% p plst)
  1180. (not
  1181. (eqv? (or (assq-ref plst p)
  1182. (error "Parameter not found!"))
  1183. (parameter-type-negation
  1184. (package-parameter-type
  1185. (parameter-spec-get-parameter
  1186. (package-parameter-spec this-package)
  1187. p)))))]))
  1188. (define-syntax parameter-if
  1189. (syntax-rules ()
  1190. [(parameter-if property exp)
  1191. (let ((properties
  1192. (parameter-spec/parameter-alist
  1193. (package-parameter-spec this-package))))
  1194. (if (member
  1195. #t
  1196. (map (cut parameter-inside? <> properties)
  1197. (parameter-process-list (return-list property))))
  1198. exp
  1199. '()))]
  1200. [(parameter-if property exp exp-else)
  1201. (let ((properties
  1202. (parameter-spec/parameter-alist
  1203. (package-parameter-spec this-package))))
  1204. (if (member
  1205. #t
  1206. (map (cut parameter-inside? <> properties)
  1207. (parameter-process-list (return-list property))))
  1208. exp
  1209. exp-else))]))
  1210. (define-syntax parameter-if-all
  1211. (syntax-rules ()
  1212. [(parameter-if-all property exp)
  1213. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1214. (if (not (member
  1215. #f
  1216. (map (cut parameter-inside? <> properties)
  1217. (parameter-process-list (return-list property)))))
  1218. exp
  1219. '()))]
  1220. [(parameter-if-all property exp exp-else)
  1221. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1222. (if (not (member
  1223. #f
  1224. (map (cut parameter-inside? <> properties)
  1225. (parameter-process-list (return-list property)))))
  1226. exp
  1227. exp-else))]))
  1228. ;; Test these macros without using packages:
  1229. ;; (define (parameter-spec/parameter-alist _)
  1230. ;; (list (cons 'a 1)
  1231. ;; (cons 'b 2)
  1232. ;; (cons 'c 3)))
  1233. ;; (define (package-parameter-spec _) #t)
  1234. ;; (define this-package '())
  1235. ;; (parameter-if '(a (b 3))
  1236. ;; "YES"
  1237. ;; "NO")
  1238. ;; (parameter-if-all '(a (b 3))
  1239. ;; "NO"
  1240. ;; "YES)
  1241. ;; parameter-match-any:
  1242. ;; (parameter-match-any
  1243. ;; ((a b) e1 e2 ..)
  1244. ;; ((c) d1 d2 ..)
  1245. ;; (else c1 c2 ...))
  1246. (define-syntax parameter-match-any
  1247. (syntax-rules (_)
  1248. [(%) '()]
  1249. [(% (_ clauses ...)) (begin clauses ...)]
  1250. [(% ((parameters ...)) rest ...) (parameter-match-any rest ...)]
  1251. [(% ((parameters ...) clauses ...) rest ...)
  1252. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1253. (begin
  1254. (and (member #t (map (cut parameter-inside? <> properties)
  1255. (list parameters ...)))
  1256. (begin clauses ...))
  1257. (parameter-match-any rest ...)))]
  1258. [(% (parameter clauses ...) rest ...)
  1259. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1260. (begin
  1261. (and (parameter-inside? parameter properties)
  1262. (begin clauses ...))
  1263. (parameter-match-any rest ...)))]))
  1264. ;; (let ((SOME_ALIST_FOR_THIS_EXAMPLE '()))
  1265. ;; (parameter-match-any
  1266. ;; (('a 'd)
  1267. ;; (set! SOME_ALIST_FOR_THIS_EXAMPLE (append '(1) SOME_ALIST_FOR_THIS_EXAMPLE))
  1268. ;; (set! SOME_ALIST_FOR_THIS_EXAMPLE (append '(2) SOME_ALIST_FOR_THIS_EXAMPLE)))
  1269. ;; (('c))
  1270. ;; (('e)
  1271. ;; (set! SOME_ALIST_FOR_THIS_EXAMPLE (append '(3) SOME_ALIST_FOR_THIS_EXAMPLE)))
  1272. ;; (all
  1273. ;; (set! SOME_ALIST_FOR_THIS_EXAMPLE (append '(4) SOME_ALIST_FOR_THIS_EXAMPLE))))
  1274. ;; SOME_ALIST_FOR_THIS_EXAMPLE)
  1275. ;; The answer to this should be '(4 2 1)
  1276. ;; note that all is essentially useless, one can simply put the expression in all
  1277. ;; outside the macro and it will work the same
  1278. (define-syntax parameter-match-all
  1279. (syntax-rules (_)
  1280. [(%) '()]
  1281. [(% (_ clauses ...)) (begin clauses ...)]
  1282. [(% ((parameters ...)) rest ...) (parameter-match-all rest ...)]
  1283. [(% ((parameters ...) clauses ...) rest ...)
  1284. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1285. (begin
  1286. (and (not (member #f (map (cut parameter-inside? <> properties)
  1287. (list parameters ...))))
  1288. (begin clauses ...))
  1289. (parameter-match-all rest ...)))]
  1290. [(% (parameter clauses ...) rest ...)
  1291. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1292. (begin
  1293. (and (parameter-inside? parameter properties)
  1294. (begin clauses ...))
  1295. (parameter-match-all rest ...)))]))
  1296. ;; (parameter-match-all
  1297. ;; (('a 'b) (display "YES") (display "YES"))
  1298. ;; (('c 'd) (display "NO"))
  1299. ;; (all (display "ALL")))
  1300. (define-syntax parameter-match-case-all
  1301. (syntax-rules ()
  1302. [(%) '()]
  1303. [(% (_ clauses ...)) (begin clauses ...)]
  1304. [(% ((parameters ...)) rest ...) (parameter-match-case-any rest ...)]
  1305. [(% ((parameters ...) clauses ...) rest ...)
  1306. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1307. (and (not (member #f (map (cut parameter-inside? <> properties)
  1308. (list parameters ...))))
  1309. (begin clauses ...)
  1310. (parameter-match-case-any rest ...)))]
  1311. [(% (parameter clauses ...) rest ...)
  1312. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1313. (and (parameter-inside? parameter properties)
  1314. (begin clauses ...)
  1315. (parameter-match-case-any rest ...)))]))
  1316. ;; should short-circuit at YESYES
  1317. ;; (parameter-match-case
  1318. ;; (('a 'b 'e) (display "YES") (display "YES"))
  1319. ;; (('c 'd) (display "NO"))
  1320. ;; (all (display "ALL")))
  1321. ;; parameter-match:
  1322. ;; combine all and any into one
  1323. ;; (parameter-match
  1324. ;; ((any a b) ...)
  1325. ;; ((all a b c) ...)
  1326. ;; (all ...))
  1327. (define-syntax parameter-match
  1328. (syntax-rules (_ all)
  1329. [(%) '()]
  1330. [(% (_ clauses ...) rest ...) (begin (begin clauses ...) (parameter-match rest ...))]
  1331. [(% (parameters) rest ...) (parameter-match rest ...)]
  1332. [(% ((all parameters ...) clauses ...) rest ...)
  1333. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1334. (begin
  1335. (and (not (member #f (map (cut parameter-inside? <> properties)
  1336. (list parameters ...))))
  1337. (begin clauses ...))
  1338. (parameter-match rest ...)))]
  1339. [(% ((parameters ...) clauses ...) rest ...)
  1340. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1341. (begin
  1342. (and (member #t (map (cut parameter-inside? <> properties)
  1343. (list parameters ...)))
  1344. (begin clauses ...))
  1345. (parameter-match rest ...)))]
  1346. [(% (parameter clauses ...) rest ...)
  1347. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1348. (begin
  1349. (and (parameter-inside? parameter properties)
  1350. (begin clauses ...))
  1351. (parameter-match rest ...)))]))
  1352. ;; (parameter-match
  1353. ;; ((all 'a 'b) (display "YES"))
  1354. ;; (_ (display "YES"))
  1355. ;; (('c 'e) (display "YES"))
  1356. ;; ((all 'a 'o) (display "NO"))
  1357. ;; (_ (display "ALL")))
  1358. (define-syntax parameter-match-case
  1359. (syntax-rules (all _)
  1360. [(%) '()]
  1361. [(% (_ clauses ...) rest ...) (begin clauses ...)]
  1362. [(% (parameters) rest ...) (parameter-match-case rest ...)]
  1363. [(% ((all parameters ...) clauses ...) rest ...)
  1364. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1365. (if (not (member #f (map (cut parameter-inside? <> properties)
  1366. (list parameters ...))))
  1367. (begin clauses ...)
  1368. (parameter-match-case rest ...)))]
  1369. [(% ((parameters ...) clauses ...) rest ...)
  1370. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1371. (if (member #t (map (cut parameter-inside? <> properties)
  1372. (list parameters ...)))
  1373. (begin clauses ...)
  1374. (parameter-match-case rest ...)))]
  1375. [(% (parameter clauses ...) rest ...)
  1376. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1377. (if (parameter-inside? parameter properties)
  1378. (begin clauses ...)
  1379. (parameter-match-case rest ...)))]))
  1380. ;; (parameter-match-case
  1381. ;; ((all 'a 'f) (display "NO"))
  1382. ;; ;; (all (display "YES"))
  1383. ;; ;; ((any 'c 'e) (display "YES"))
  1384. ;; ;; ((all 'a 'b) (display "YES"))
  1385. ;; (all (display "ALL")))
  1386. (define-syntax parameter-modifier-if
  1387. (syntax-rules (_ all delete prepend append replace)
  1388. [(% _ exp exp2)
  1389. exp]
  1390. [(% (all parameters ...) exp exp2)
  1391. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1392. (if (member #t
  1393. (map (cut parameter-inside? <> properties)
  1394. (list parameters ...)))
  1395. exp
  1396. exp2))]
  1397. ;; [(% (all parameter) exp exp2) ; unnecessary
  1398. ;; (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1399. ;; (if (parameter-inside? parameter properties)
  1400. ;; exp
  1401. ;; exp-else))]
  1402. [(% parameter exp exp2)
  1403. (let ((properties (parameter-spec/parameter-alist (package-parameter-spec this-package))))
  1404. (if (member
  1405. #t
  1406. (map (cut parameter-inside? <> properties)
  1407. (return-list parameter)))
  1408. exp
  1409. exp2))]))
  1410. (define-syntax parameter-modify-inputs
  1411. (syntax-rules (_ all delete prepend append replace)
  1412. [(% inputs (parameter) clauses ...)
  1413. (parameter-modify-inputs inputs clauses ...)]
  1414. [(% inputs (parameter (delete name) rest ...) clauses ...)
  1415. (parameter-modify-inputs
  1416. (parameter-modifier-if
  1417. parameter
  1418. (alist-delete name inputs)
  1419. inputs)
  1420. (parameter rest ...)
  1421. clauses ...)]
  1422. [(% inputs (parameter (delete names ...) rest ...) clauses ...)
  1423. (parameter-modify-inputs
  1424. (parameter-modifier-if
  1425. parameter
  1426. (fold alist-delete inputs (list names ...))
  1427. inputs)
  1428. (parameter rest ...)
  1429. clauses ...)]
  1430. [(% inputs (parameter (prepend lst ...) rest ...) clauses ...)
  1431. (parameter-modify-inputs
  1432. (parameter-modifier-if
  1433. parameter
  1434. (append (map add-input-label (list lst ...)) inputs)
  1435. inputs)
  1436. (parameter rest ...)
  1437. clauses ...)]
  1438. [(% inputs (parameter (append lst ...) rest ...) clauses ...)
  1439. (parameter-modify-inputs
  1440. (parameter-modifier-if
  1441. parameter
  1442. (append inputs (map add-input-label (list lst ...)))
  1443. inputs)
  1444. (parameter rest ...)
  1445. clauses ...)]
  1446. [(% inputs (parameter (replace name replacement) rest ...) clauses ...)
  1447. (parameter-modify-inputs
  1448. (parameter-modifier-if
  1449. parameter
  1450. (replace-input name replacement inputs)
  1451. inputs)
  1452. (parameter rest ...)
  1453. clauses ...)]
  1454. [(% inputs)
  1455. inputs]))
  1456. ;; (parameter-type-negation
  1457. ;; (parameter-type
  1458. ;; (name "ok")
  1459. ;; (accepted-values '(not-ok ok))))
  1460. ;; (define-syntax parameter/type
  1461. ;; (syntax-rules (_)
  1462. ;; [(% _ rest ...)
  1463. ;; (parameter/type (string-append (or (package-parameter-name this-package-parameter)
  1464. ;; "%blank")
  1465. ;; "-type")
  1466. ;; rest ...)]
  1467. ;; [(% t-name t-accepted-values)
  1468. ;; (parameter-type
  1469. ;; (name t-name)
  1470. ;; (accepted-values t-accepted-values))]
  1471. ;; [(% t-name t-accepted-values t-negation)
  1472. ;; (parameter-type
  1473. ;; (name t-name)
  1474. ;; (accepted-values t-accepted-values)
  1475. ;; (negation t-negation))]
  1476. ;; [(% t-name t-accepted-values t-negation t-description)
  1477. ;; (parameter-type
  1478. ;; (name t-name)
  1479. ;; (accepted-values t-accepted-values)
  1480. ;; (negation t-negation)
  1481. ;; (description t-description))]))
  1482. ;; (parameter-type-negation (parameter/type _ '(1 2 3)))
  1483. ;;
  1484. ;; (define (package-parameter-name _) #f)
  1485. ;; (define this-package-parameter #f)