1;; Copyright (c) 2015-2016 Robert Virding
2;;
3;; Licensed under the Apache License, Version 2.0 (the "License");
4;; you may not use this file except in compliance with the License.
5;; You may obtain a copy of the License at
6;;
7;;     http://www.apache.org/licenses/LICENSE-2.0
8;;
9;; Unless required by applicable law or agreed to in writing, software
10;; distributed under the License is distributed on an "AS IS" BASIS,
11;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12;; See the License for the specific language governing permissions and
13;; limitations under the License.
14
15;; File    : cl.lfe
16;; Author  : Robert Virding, Duncan McGreggor
17;; Purpose : LFE Common Lisp interface library.
18
19(defmodule cl
20  "LFE Common Lisp interface library."
21  (export
22   ;; Boolean conversion functions.
23   (make-lfe-bool 1) (make-cl-bool 1)
24   ;; Control structure.
25   (mapcar 2) (maplist 2) (mapc 2) (mapl 2)
26   ;; Symbol functions.
27   (symbol-plist 1) (symbol-name 1)
28   (get 2) (get 3) (getl 2) (putprop 3) (remprop 2)
29   ;; Property list functions.
30   (getf 2) (getf 3) (putf 3) (remf 2) (get-properties 2)
31   ;; Sequences.
32   (elt 2) (length 1) (reverse 1) (some 2) (every 2) (notany 2) (notevery 2)
33   (reduce 2) (reduce 4) (reduce 6)
34   (remove 2) (remove-if 2) (remove-if-not 2) (remove-duplicates 1)
35   (substitute 3) (substitute-if 3) (substitute-if-not 3)
36   (find 2) (find-if 2) (find-if-not 2)
37   (position 2) (position-if 2) (position-if-not 2)
38   (count 2) (count-if 2) (count-if-not 2)
39   ;; Lists.
40   (car 1) (cdr 1) (first 1) (rest 1) (nth 2)
41   (nthcdr 2) (last 1) (butlast 1)
42   ;; Substitution of expressions.
43   (subst 3) (subst-if 3) (subst-if-not 3) (sublis 2)
44   ;; Lists as sets.
45   (member 2) (member-if 2) (member-if-not 2) (adjoin 2) (union 2)
46   (intersection 2) (set-difference 2) (set-exclusive-or 2) (subsetp 2)
47   ;; Association list functions.
48   (acons 3) (pairlis 2) (pairlis 3) (assoc 2) (assoc-if 2) (assoc-if-not 2)
49   (rassoc 2) (rassoc-if 2) (rassoc-if-not 2)
50   ;; Types.
51   (type-of 1) (coerce 2))
52  (export-macro
53   ;; Export control structure macros.
54   do
55  ;; Export CL-style if and cond, which we don't use internally.
56   if cond))
57
58;;; Boolean conversion functions.
59
60(defun make-lfe-bool                    ;Make an LFE bool from a CL value
61  "cl-boolean
62   Make an LFE bool from a CL value."
63  ([()] 'false)
64  ([_]  'true))                         ;Everything else is true
65
66(defun make-cl-bool                     ;Make a CL bool from an LFE value
67  "lfe-boolean
68   Make a CL bool from an LFE value."
69  (['false] ())
70  (['true] 'true))
71
72;; Control structure.
73
74(defmacro do args
75  "vars (end-test result) body"
76  (let* ((`(,pars (,test ,ret) . ,body) args)
77	 ((tuple vs is cs)
78	  (lists:foldr (match-lambda
79			 ([(list v i c) (tuple vs is cs)]
80			  (tuple (cons v vs) (cons i is) (cons c cs))))
81		       (tuple () () ()) pars)))
82    `(letrec-function ((|\|-do-func-\||
83			(lambda ,vs
84			  (if ,test ,ret
85			      (let ((do-state (progn . ,body)))
86				(|\|-do-func-\|| . ,cs))))))
87       (|\|-do-func-\|| . ,is))))
88
89(defun mapcar (func list)
90  "function list"
91  (lists:map func list))
92
93(defun maplist
94  "function list"
95  ([func (= (cons _ rest) list)]
96   (cons (funcall func list) (maplist func rest)))
97  ([func ()] ()))
98
99(defun mapc (func list)
100  "function list"
101  (lists:foreach func list)
102  list)
103
104(defun mapl (func list)
105  "function list"
106  (fletrec ((mapl-loop
107             ([(= (cons _ rest) list)]
108              (funcall func list)
109              (mapl-loop rest))
110             ([()] ())))
111    (mapl-loop list)
112    list))
113
114;; Symbol function functions.
115;;  get, getl, putprop and remprop should really only work on a
116;;  symbols plist not just a plist. This is coming. Hence including
117;;  getf, putf and remf.
118
119(defun ensure-plist-table ()
120  (case (ets:info 'lfe-symbol-plist 'type)
121    ('undefined
122     (let ((init-pid (erlang:whereis 'init)))
123       (ets:new 'lfe-symbol-plist
124        (list 'set 'public 'named_table (tuple 'heir init-pid ())))))
125    (_ 'ok)))
126
127(defun symbol-plist (symbol)
128  "symbol
129   Get the property list for symbol."
130  (ensure-plist-table)
131  (case (ets:lookup 'lfe-symbol-plist symbol)
132    (`(#(,_ ,plist)) plist)
133    (() ())))
134
135(defun symbol-name (symb)
136  "symbol
137   Get the name of symbol as a list."
138  (atom_to_list symb))
139
140(defun get (symbol pname)
141  "symbol pname
142   Get the property pname of symbol."
143  (get symbol pname ()))
144
145;;(defun get (plist pname def) (getf plist pname def))
146
147(defun get (symbol pname def)
148  "symbol pname default"
149  (ensure-plist-table)
150  (let ((plist (symbol-plist symbol)))
151    (getf plist pname def)))
152
153(defun getl (symbol pnames)
154  "symbol pnames"
155  (ensure-plist-table)
156  (let ((plist (symbol-plist symbol)))
157    (fletrec ((getl-loop
158               ([(= (list* p v plist-rest) plist) pnames]
159                (if (member p pnames)
160                  plist
161                  (getl-loop plist-rest pnames)))
162               ([() pnames] ())))
163      (getl-loop plist pnames))))
164
165;; (defun putprop (plist val pname) (putf plist val pname))
166
167(defun putprop (symbol val pname)
168  "symbol value pname"
169  (ensure-plist-table)
170  (let* ((plist (symbol-plist symbol))
171         (plist (putf plist val pname)))
172    (ets:insert 'lfe-symbol-plist (tuple symbol plist))))
173
174;; (defun getprop (plist pname) (remf plist pname))
175
176(defun remprop (symbol pname)
177  "symbol pname"
178  (ensure-plist-table)
179  (let* ((plist (symbol-plist symbol))
180         (plist (remf plist pname)))
181    ;; Delete element if plist empty
182    (if (=:= plist ())
183      (ets:delete 'lfe-symbol-plist symbol)
184      (ets:insert 'lfe-symbol-plist (tuple symbol plist)))))
185
186;; Property list functions.
187
188(defun getf (plist pname)
189  "plist pname"
190  (getf plist pname ()))
191
192(defun getf
193  "plist pname default"
194  ([(list* p v plist) p def]  v)
195  ([(list* _ _ plist) pname def] (getf plist pname def))
196  ([() _m def] def))
197
198(defun putf                             ;This doesn't exist in CL
199  "plist value pname"
200  ([(list* p _ plist) val p]
201   (list* p val plist))
202  ([(list* p v plist) val pname]
203   (list* p v (putf plist val pname)))
204  ([() val pname] (list pname val)))
205
206(defun remf
207  "plist pname"
208  ([(list* p _ plist) p] plist)
209  ([(list* p v plist) pname]
210   (list* p v (remf plist pname)))
211  ([() pname] ()))
212
213(defun get-properties
214  "plist pnames"
215  ([(= (list* p v plist-rest) plist) pnames]
216   (if (member p pnames)
217     (tuple p v plist)
218     (get-properties plist-rest pnames)))
219  ([() pnames] (tuple () () ())))
220
221;; Arrays.
222
223;; (defun aref (array i j)
224;;   (elt j (elt i array)))
225
226;; Sequences.
227;; Simple sequence functions.
228
229(defun elt
230  ((n seq) (when (is_list seq))
231   (nth n seq))
232  ((n seq) (when (is_tuple seq))
233   (tref seq (+ n 1))))
234
235(defun length
236  ([seq] (when (is_list seq))
237   (length seq))
238  ([seq] (when (is_tuple seq))
239   (tuple_size seq)))
240
241(defun reverse
242  ([seq] (when (is_list seq))
243   (lists:reverse seq))
244  ([seq] (when (is_tuple seq))
245   (list_to_tuple (lists:reverse (tuple_to_list seq)))))
246
247;; Concatanation, mapping and reducing sequences.
248
249(defun some
250  "pred list
251   Return true if pred is true for some element of list."
252  ([pred seq] (when (is_list seq))
253   (lists:any pred seq))
254  ([pred seq] (when (is_tuple seq))
255   (fletrec ((some-loop
256              ([i n] (when (>= i n)) 'false)
257              ([i n]
258               (orelse (funcall pred (tref seq i))
259                       (some-loop (+ i 1) n)))))
260     (some-loop 1 (tuple_size seq)))))
261
262(defun every
263  "pred list
264   Return true if pred is true for every element of list."
265  ([pred seq] (when (is_list seq))
266   (lists:all pred seq))
267  ([pred seq] (when (is_tuple seq))
268   (fletrec ((every-loop
269              ([i n] (when (>= i n)) 'false)
270              ([i n]
271               (andalso (not (funcall pred (tref seq i)))
272                        (every-loop (+ i 1) n)))))
273     (every-loop 1 (tuple_size seq)))))
274
275(defun notany (pred seq)
276  "pred list
277   Returns true if pred is false for every element of list."
278  (every (lambda (x) (not (funcall pred x))) seq))
279
280(defun notevery (pred seq)
281  "pred list
282   Returns true if pred is false for some element of list."
283  (some (lambda (x) (not (funcall pred x))) seq))
284
285(defun reduce (func seq)
286  (lists:foldl func '() seq))
287
288(defun reduce
289  ((func seq 'initial-value x)
290   (lists:foldl func x seq))
291  ((func seq 'from-end 'true)
292   (lists:foldr func '() seq)))
293
294(defun reduce
295  ((func seq 'from-end 'true 'initial-value x)
296   (lists:foldr func x seq))
297  ((func seq 'initial-value x 'from-end 'true)
298   (lists:foldr func x seq)))
299
300;; Modifying sequences.
301
302(defun remove
303  "item sequence
304   Remove all elements from sequence which are equal to item."
305  ([item seq] (when (is_list seq))
306   (lc ((<- x seq) (=/= x item)) x))
307  ([item seq] (when (is_tuple seq))
308   (list_to_tuple (remove item (tuple_to_list seq)))))
309
310(defun remove-if
311  "pred sequence
312   Remove all elements from sequence for which pred is true."
313  ([pred seq] (when (is_list seq))
314   (lc ((<- x seq) (not (funcall pred x))) x))
315  ([pred seq] (when (is_tuple seq))
316   (list_to_tuple (remove-if pred (tuple_to_list seq)))))
317
318(defun remove-if-not
319  "pred sequence
320   Remove all elements from sequence for which pred is false."
321  ([pred seq] (when (is_list seq))
322   (lc ((<- x seq) (funcall pred x)) x))
323  ([pred seq] (when (is_tuple seq))
324   (list_to_tuple (remove-if-not pred (tuple_to_list seq)))))
325
326(defun remove-duplicates
327  "sequence
328   Remove duplicates from sequence."
329  ([seq] (when (is_list seq))
330   (fletrec ((rm-loop
331              ([(cons x rest)]
332               (if (lists:member x rest)
333                 (rm-loop rest)
334                 (cons x (rm-loop rest))))
335              ([()] ())))
336     (rm-loop seq)))
337  ([seq] (when (is_tuple seq))
338   (list_to_tuple (remove-duplicates (tuple_to_list seq)))))
339
340(defun substitute
341  "new old sequence
342   Replace all elements in sequence which are equal to old with new."
343  ([new old seq] (when (is_list seq))
344   (fletrec ((sub-loop
345              ([n o (cons o xs)]
346               (cons n (sub-loop n o xs)))
347              ([n o (cons x xs)]
348               (cons x (sub-loop n o xs)))
349              ([_ _ ()] ())))
350     (sub-loop new old seq)))
351  ([new old seq] (when (is_tuple seq))
352   (list_to_tuple (substitute new old (tuple_to_list seq)))))
353
354(defun substitute-if
355  "new pred sequence
356   Replace all elements in sequence for which pred is true with new."
357  ([new pred seq] (when (is_list seq))
358   (fletrec ((sub-loop
359              ([n p (cons x xs)]
360               (cons (if (funcall p x) n x) (sub-loop n p xs)))
361              ([_ _ ()] ())))
362     (sub-loop new pred seq)))
363  ([new pred seq] (when (is_tuple seq))
364   (list_to_tuple (substitute-if new pred (tuple_to_list seq)))))
365
366(defun substitute-if-not
367  "new pred sequence
368   Replace all elements in sequence for which pred is false with new."
369  ([new pred seq] (when (is_list seq))
370   (fletrec ((sub-loop
371              ([n p (cons x xs)]
372               (cons (if (funcall p x) x n) (sub-loop n p xs)))
373              ([_ _ ()] ())))
374     (sub-loop new pred seq)))
375  ([new pred seq] (when (is_tuple seq))
376   (list_to_tuple (substitute-if-not new pred (tuple_to_list seq)))))
377
378;; Searching sequences.
379
380(defun find (item seq)
381  "item sequence
382   If sequence contains item then it is returned else ()."
383  (fletrec ((find-loop
384             ([x (cons x xs)] x)
385             ([x (cons _ xs)] (find-loop x xs))
386             ([x ()] ())))
387    (find-loop item seq)))
388
389(defun find-if (pred seq)
390  "pred sequence
391   Return element in sequnce for which pred is true else ()."
392  (fletrec ((find-if-loop
393             ([pred (cons x xs)]
394              (if (funcall pred x) x (find-if-loop pred xs)))
395             ([pred ()] ())))
396    (find-if-loop pred seq)))
397
398(defun find-if-not (pred seq)
399  "pred sequence
400   Return element in sequnce for which pred is true else ()."
401  (fletrec ((find-if-not-loop
402             ([pred (cons x xs)]
403              (if (funcall pred x) (find-if-not-loop pred xs) x))
404             ([pred ()] ())))
405    (find-if-not-loop pred seq)))
406
407(defun position (item seq)
408  "item sequence
409   Return index of item in sequence else ()."
410  (fletrec ((pos-loop
411             ([x n (cons x xs)] n)
412             ([x n (cons _ xs)] (pos-loop x (+ n 1) xs))
413             ([x n ()] ())))
414    (pos-loop item 0 seq)))
415
416(defun position-if (pred seq)
417  "item sequence
418   Return index of item in sequence for which pred is true else ()."
419  (fletrec ((pos-if-loop
420             ([pred n (cons x xs)]
421              (if (funcall pred x)
422                n
423                (pos-if-loop pred (+ n 1) xs)))
424             ([pred n ()] ())))
425    (pos-if-loop pred 0 seq)))
426
427(defun position-if-not (pred xs)
428  "item sequence
429   Return index of item in sequence for which pred is false else ()."
430  (fletrec ((pos-if-not-loop
431             ([pred n (cons x xs)]
432              (if (funcall pred x)
433                (pos-if-not-loop pred (+ n 1) xs)
434                n))
435             ([pred n ()] ())))
436    (pos-if-not-loop pred 0 xs)))
437
438(defun count (item seq)
439  "item sequence
440   Return the number of elements in sequence equal to item."
441  (fletrec ((count-loop
442             ([x n (cons x1 xs)]
443              (let ((n1 (if (=:= x x1) (+ n 1) n)))
444                (count-loop x n1 xs)))
445             ([x n ()] n)))
446    (count-loop item 0 seq)))
447
448(defun count-if (pred seq)
449  "pred sequence
450   Return the number of elements in sequence for which pred is true."
451  (fletrec ((count-if-loop
452             ([pred n (cons x xs)]
453              (let ((n1 (if (funcall pred x) (+ n 1) n)))
454                (count-if-loop pred n1 xs)))
455             ([pred n ()] n)))
456    (count-if-loop pred 0 seq)))
457
458(defun count-if-not (pred seq)
459  "pred sequence
460   Return the number of elements in sequence for which pred is false."
461  (fletrec ((count-if-not-loop
462             ([pred n (cons x xs)]
463              (let ((n1 (if (funcall pred x) n (+ n 1))))
464                (count-if-not-loop pred n1 xs)))
465             ([pred n ()] n)))
466    (count-if-not-loop pred 0 seq)))
467
468;;; Lists
469
470(defun car
471  ([()] ())
472  ([xs] (car xs)))
473
474(defun first (xs)
475  (cl:car xs))
476
477(defun cdr
478  ([()] ())
479  ([xs] (cdr xs)))
480
481(defun rest (xs)
482  (cl:cdr xs))
483
484(defun nth
485  ([n xs] (when (< n 0)) ())
486  ([n xs]
487   (fletrec ((nth-loop
488              ([n ()] ())               ;End of the list
489              ([0 xs] (car xs))         ;Found the one
490              ([n xs] (nth-loop (- n 1) (cdr xs)))))
491     (nth-loop n xs))))
492
493(defun nthcdr (n xs)
494  (lists:nthtail (+ n 1) xs))
495
496(defun last (list)
497  (lists:last list))
498
499(defun butlast (list)
500  (lists:droplast list))
501
502;; Substitution of expressions
503
504(defun subst
505  "new old tree
506   Substitute `new` for every subtree `old` in `tree`."
507  ([new old old] new)
508  ([new old (cons e rest)]
509   (cons (subst new old e) (subst new old rest)))
510  ([new old tree] tree))
511
512(defun subst-if (new test tree)
513  "new test tree
514   Substitute `new` for every subtree which satisfies `test` in `tree`."
515  (if (funcall test tree) new
516      (case tree
517        ((cons e rest)
518         (cons (subst-if new test e) (subst-if new test rest)))
519        (_ tree))))
520
521(defun subst-if-not (new test tree)
522  "new test tree
523   Substitute `new` for every subtree which does not satisfy `test` in `tree`."
524  (if (funcall test tree)
525    (case tree
526      ((cons e rest)
527       (cons (subst-if-not new test e) (subst-if-not new test rest)))
528      (_ tree))
529    new))
530
531(defun sublis (a-list tree)
532  "a-list tree
533   Subsitute the value of each key in `a-list` occurring in `tree`."
534  (case (assoc tree a-list)
535    ((cons _ new) new)                  ;Found it
536    (()                                 ;Not there
537     (case tree
538       ((cons e rest)
539        (cons (sublis a-list e) (sublis a-list rest)))
540       (_ tree)))))
541
542;; Lists as sets.
543
544(defun member (item list)
545  "item list
546   Return true if `item` is a member of `list`."
547  (lists:member item list))
548
549(defun member-if
550  "pred list
551   Return true if `pred` is satisfied for a member of `list`."
552  ([pred (cons e list)]
553   (orelse (funcall pred e)
554           (member-if pred list)))
555  ([pred ()] 'false))
556
557(defun member-if-not
558  "pred list
559   Return true if `pred` is not satisfied for a member of `list`."
560  ([pred (cons e list)]
561   (orelse (not (funcall pred e)) (member-if-not pred list)))
562  ([pred ()] 'false))
563
564(defun adjoin (item list)
565  "item list
566   Add `item` to `list` if it is not already a member."
567  (if (member item list)
568    list
569    (cons item list)))
570
571(defun union
572  "list-1 list-2
573   Returns the elements which are members of lists `list-1` or `list-2`."
574  ([(cons e l1) l2]
575   (if (member e l2)
576     (union l1 l2)
577     (cons e (union l1 l2))))
578  ([() l2] l2))
579
580(defun intersection (l1 l2)
581  "list-1 list-2
582   Returns the elements which are members of both lists `list-1` and `list-2`."
583  (lc ((<- e l1) (member e l2)) e))
584
585(defun set-difference (l1 l2)
586  "list-1 list-2
587   Returns the elements of `list-1` which are not elements in `list-2`."
588  (lc ((<- e l1) (not (member e l2))) e))
589
590(defun set-exclusive-or (l1 l2)
591  "list-1 list-2
592   Return the elements which are elements of one of `list-1` or `list-2`."
593  (++ (set-difference l1 l2) (set-difference l2 l1)))
594
595(defun subsetp
596  "list-1 list-2
597   Return true if every element in `list-1` is also in `list-2`."
598  ([(cons e l1) l2] (andalso (member e l2) (subsetp l1 l2)))
599  ([()          l2] 'true))
600
601;; Association list functions.
602
603(defun acons (k v a-list)
604  "key value a-list
605   Add `(key . value)` to the front of the `a-list`."
606  (cons (cons k v) a-list))
607
608(defun pairlis (ks vs)
609  "keys values
610   Make an alist from pairs of keys values."
611  (pairlis ks vs ()))
612
613(defun pairlis
614  "keys values a-list
615   Make an alist from pairs of keys values prepending them to a-list."
616  ([(cons k ks) (cons v vs) a-list]
617   (cons (cons k v) (pairlis ks vs a-list)))
618  ([() () a-list] a-list))
619
620(defun assoc
621  "key a-list
622   Searches a-list returning the first pair whose car is key."
623  ([k (cons (= (cons k v) pair) _)] pair)
624  ([k (cons _ a-list)] (assoc k a-list))
625  ([k ()] ()))
626
627(defun assoc-if
628  "pred a-list
629   Searches a-list returning the first pair for which pred is true."
630  ([pred (cons (= (cons k _) pair) a-list)]
631   (if (funcall pred k) pair
632       (assoc-if pred a-list)))
633  ([pred ()] ()))
634
635(defun assoc-if-not
636  "pred a-list
637   Searches a-list returning the first pair for which pred is false."
638  ([pred (cons (= (cons k _) pair) a-list)]
639   (if (funcall pred k)
640     (assoc-if-not pred a-list)
641     pair))
642  ([pred ()] ()))
643
644(defun rassoc
645  "value a-list
646   Searches a-list returning the first pair whose cdr is value."
647  ([v (cons (= (cons _ v) pair) _)] pair)
648  ([v (cons _ a-list)] (rassoc v a-list))
649  ([v ()] ()))
650
651(defun rassoc-if
652  "pred a-list
653   Searches a-list returning the first pair for which pred is true."
654  ([pred (cons (= (cons _ v) pair) a-list)]
655   (if (funcall pred v)
656     pair
657     (rassoc-if pred a-list)))
658  ([pred ()] ()))
659
660(defun rassoc-if-not
661  "pred a-list
662   Searches a-list returning the first pair for which pred is false."
663  ([pred (cons (= (cons _ v) pair) a-list)]
664   (if (funcall pred v)
665     (rassoc-if-not pred a-list)
666     pair))
667  ([pred ()] ()))
668
669;;; Types
670
671(defun type-of
672  ((x) (when (is_boolean x))
673   'boolean)
674  ((x) (when (is_atom x))
675   'atom)
676  ((x) (when (is_tuple x))
677   'tuple)
678  ((x) (when (is_integer x))
679   'integer)
680  ((x) (when (is_float x))
681   'float)
682  ((x) (when (is_list x))
683   (cond ((io_lib:printable_latin1_list x) 'string)
684         ((io_lib:printable_unicode_list x) 'unicode)
685         ((?= `(,a . ,b) (when (not (is_list b))) x) 'cons)
686         ('true 'list)))
687  ((x) (when (is_function x))
688   'function)
689  ((x) (when (is_binary x))
690   'binary)
691  ((x) (when (is_bitstring x))
692   'bitstring)
693  ((x) (when (is_pid x))
694   'pid)
695  ((x) (when (is_port x))
696   'port)
697  ((x) (when (is_reference x))
698   'reference)
699  ((x)
700   (andalso (call 'erlang 'is_map x) 'map)))
701
702(defun coerce
703  ((x 'vector) (when (is_list x))
704   (list_to_tuple x))
705  ((x 'tuple) (when (is_list x))
706   (list_to_tuple x))
707  ((x 'atom) (when (is_list x))
708   (list_to_atom x))
709  ((x 'list) (when (is_atom x))
710   (atom_to_list x))
711  ((x 'list) (when (is_tuple x))
712   (tuple_to_list x))
713  ((x 'list) (when (is_binary x))
714   (binary_to_list x))
715  ((x 'list) (when (is_bitstring x))
716   (bitstring_to_list x))
717  ((x 'character) (when (is_atom x))
718   (car (atom_to_list x)))
719  ((x 'character) (when (is_list x))
720   (car x))
721  ((x 'integer) (when (is_float x))
722   (trunc x))
723  ((x 'float) (when (is_integer x))
724   (list_to_float (integer_to_list x)))
725  ((x 'float) (when (is_list x))
726   (list_to_float x))
727  ((x 'float) (when (is_atom x))
728   (list_to_float (atom_to_list x)))
729  ((x 't)
730   x))
731
732;;; System
733
734(defun posix-argv ()
735  (init:get_arguments))
736
737;; Test defining CL if and cond. We need to put these last so they
738;; won't be used inside this module, but of course the if can't.
739
740(defmacro if args
741  "test true-case false-case
742   CL compatible if macro."
743  (flet ((exp-if (test if-true if-false)
744                 `(case ,test
745                    (() ,if-false)
746                    (_ ,if-true))))
747    (case args
748      ((list test if-true) (exp-if test if-true ()))
749      ((list test if-true if-false)
750       (exp-if test if-true if-false)))))
751
752(defmacro cond args
753  "args
754   CL compatible cond macro."
755  (fletrec ((exp-cond
756             ([(cons (list test) cond)]
757              `(case ,test
758                 (() ,(exp-cond cond))
759                 (|\|-cond-test-\|| |\|-cond-test-\||)))
760             ([(cons (cons test body) cond)]
761              `(case ,test
762                 (() ,(exp-cond cond))
763                 (_ (progn . ,body))))
764             ([()] ())))
765    (exp-cond args)))
766