-
Notifications
You must be signed in to change notification settings - Fork 2
/
cl.lsp
204 lines (185 loc) · 6.33 KB
/
cl.lsp
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
;;; cl.lsp --- Common Lisp like functions
;;; NOTE:
;;
;; see "Differences to Other LISPs"
;; - http://www.newlisp.org/index.cgi?page=Differences_to_Other_LISPs
;; * Case-sensitive
;; * 関数部分は事前に評価される
;; * LISP-1
;; * ダイナミックスコープ
;; * ドット対が存在しない
;; * 関数引数はデフォルトでオプショナル
;; * 存在しないシンボルは生成時にnilに束縛される
;; * GCの代わりにORO
;; * Fexprマクロは引数を評価しない
;; * パッケージの代わりにコンテキスト
;; * Implicit Indexing
;; (constant (global 't) true)
;; (define t true)
(define (null x) (not (true? x)))
;;(define car first)
(define (car x)
(if (member x '(nil ())) nil (first x)))
(define cdr rest)
(define defconstant
(lambda-macro ()
(constant (args 0) (eval (args 1)))))
(define export global)
(define progn begin)
(define (funcall f) (apply f (args)))
(define (atom obj)
(or (atom? obj)
(= obj '())))
(define eq =)
(define eql =)
(define equal =)
(define let* letn)
(define intern sym) ; or make-symbol
(define symbol-name term)
(define symbol-package prefix)
(define char-code char) ; (char "A") => 65
(define code-char char) ; (char 65) => "A"
(define rplaca ; (rplaca x y)
(lambda-macro ()
(setf (first (eval (args 0))) (eval (args 1)))
(eval (args 0))))
(define rotatef swap) ; swap accept only two variables
(define complement
(lambda-macro ()
(letex ((f (args 0)))
(lambda ()
(not (apply f (args)))))))
(define identity
;; 引数のコピーを避けるためマクロを利用している
(lambda-macro () (eval (args 0))))
;; FIXME: short `uuid' name is safe to use?
(define (gensym) (sym (append "g-" (slice (uuid) 0 8))))
(define (find-symbol str (ctx (context)))
;; or (context ctx str)
(sym str ctx nil))
(define read-from-string read-expr)
;;; @@number
(constant 'most-positive-fixnum 0x7fffffffffffffff)
(constant 'most-negative-fixnum 0x8000000000000000)
(defconstant pi (mul (atan 1) 4)) ; 3.141592654 (mul (acos 0) 2)
(define incf inc) ; or ++
(define decf dec) ; or --
(define (plusp number) (< 0 number)) ; or (> number) , (sgn number nil nil true)
(define (minusp number) (< number 0)) ; or (< number) , (sgn number true nil nil)
(define (evenp i) (= (& i 1) 0))
(define (oddp i) (= (& i 1) 1))
(define (ash i cnt) (sgn cnt (>> i (abs cnt)) i (<< i cnt)))
(define logand &)
(define logxor ^)
(define logior |)
(define lognot ~)
(define expt pow)
(define (/= number)
"true if NUMBER and rest numbers are different all. otherwise nil."
(for-all (lambda (x) (not (= x number))) (args)))
;; (/= 1 2 3 1) ; nil
;; (!= 1 2 3 1) ; true ?
;;; @@list
(define intersection intersect)
(define set-difference difference)
(define butlast chop)
(define (nthcdr n lst) (slice lst n))
(define (common-lisp:last lst (n 1))
((- n) lst))
(define every for-all)
(define (some f lst)
(if (symbol? f) (setq f (eval f)))
(dolist (obj lst (f obj))))
(define (notany f lst)
(setq f (eval f))
(not (apply exists (list f lst $args))))
(define position find)
(define find-if exists)
(define remove-duplicates unique)
;(define (remove item seq) (clean (fn (x) (= x item)) seq))
(define (remove item seq)
(if (string? seq)
(replace item seq "")
(replace item seq)))
(define remove-if clean)
(define remove-if-not filter)
(define common-lisp:delete ; 破壊的 (destructive)
(lambda-macro ()
(if (string? (eval (args 1)))
(replace (eval (args 0)) (eval (args 1)) "")
(replace (eval (args 0)) (eval (args 1))))))
(define (count-if f seq)
(length (filter f seq)))
(define (mapcar f lst)
"syntax: (mapcar function list &rest more-lists)"
(letn ((lists (cons lst (args)))
(minlength (apply min (map length lists))))
(apply map (cons f (map (lambda (x)
(slice x 0 minlength))
lists)))))
;; (mapcar list '(1 2 3 4) '(10 nil 30) '(100 200 300 400 500 600))
;; => ((1 10 100) (2 nil 200) (3 30 300))
;; (map list '(1 2 3 4) '(10 nil 30) '(100 200 300 400 500 600))
;; => ((1 10 100) (2 nil 200) (3 30 300) (4 nil 400))
(define (list* )
(cond ((empty? (rest (args)))
(first (args)))
(true
(cons (first (args))
(apply list* (rest (args)))))))
;;; @@sequence
;(define concat string)
(define (concat) (join (args)))
(define copy-seq copy)
(define string-upcase upper-case)
(define string-downcase lower-case)
(define string-capitalize title-case)
(define (subseq seq start end)
(cond (end (slice seq start (- end start)))
(true (slice seq start))))
(define (string-equal str1 str2)
(= (upper-case str1) (upper-case str2)))
(define (string-left-trim char-bag str)
(if (string? char-bag)
(setq char-bag (map char (explode char-bag))))
(catch
(dostring (c str)
(unless (member c char-bag)
(throw (slice str $idx))))))
(define (string-right-trim char-bag str)
(if (string? char-bag)
(setq char-bag (map char (explode char-bag))))
(catch
(dostring (c (reverse (copy str)))
(unless (member c char-bag)
(throw (slice str 0 (- (length str) $idx)))))))
(define (string-trim char-bag str)
(string-right-trim char-bag (string-left-trim char-bag str)))
(define-macro (ignore-errors form)
(eval-string (prin1-to-string form) (context) nil))
;; @syntax (unwind-protect protected-form cleanup-form*) => result
;; (context 'unwind-protect)
(letex ((result (gensym)))
(define-macro (unwind-protect )
(local (result)
(if (catch (eval (args 0)) 'result)
(begin (map eval (1 (args))) result)
(begin (map eval (1 (args))) (throw-error (5 result))))))
)
(define (prin1-to-string obj)
(cond ((string? obj) (format {"%s"} (replace "\\" obj "\\\\")))
("else" (string obj))))
;; parallel setq
;; @syntax (psetq var form ...)
(define psetq
(letex ((v (gensym))
(s (gensym)))
(lambda-macro ()
(unless (= (& (length $args) 1) 0)
(throw-error "missing argument"))
(dolist (v (map (lambda (s) (list (s 0) (eval (s 1))))
;; ((var1 val1) (var2 val2) ...)
(explode $args 2)))
(set (v 0) (v 1))))))
(context MAIN)
;;; EOF