Browse code
Adding various things
- Of particular note is zipfile.lisp which is a working streaming
zipfile decoder
Showing 19 changed files
- .gitignore
- asm.lisp
- bintree.lisp
- cells-html-scraper.dm.lisp
- cells-html-scraper.lisp
- changelog-filter.lisp
- code-lookup.lisp
- dotimes-to-for.lisp
- garagiste.lisp
- infer-type.lisp
- labels-parser.lisp
- lisp-sandbox.zip
- paip/gps.lisp
- patmatch-paip.lisp
- qtools-demo.lisp
- tools/Makefile
- tools/git-pick-patch.lisp
- typecheck.lisp
- zipfile.lisp
6 | 9 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
1 |
+;;; How to make the popcnt instruction available |
|
2 |
+(defpackage "POPCNT" |
|
3 |
+ (:use "CL") |
|
4 |
+ (:export "POPCNT")) |
|
5 |
+ |
|
6 |
+(in-package "POPCNT") |
|
7 |
+ |
|
8 |
+(sb-c:defknown popcnt ((unsigned-byte 64)) (integer 0 64) |
|
9 |
+ (sb-c:foldable sb-c:flushable sb-c:movable) |
|
10 |
+ :overwrite-fndb-silently t) |
|
11 |
+ |
|
12 |
+(in-package "SB-VM") |
|
13 |
+ |
|
14 |
+(define-vop (popcnt:popcnt) |
|
15 |
+ (:policy :fast-safe) |
|
16 |
+ (:translate popcnt:popcnt) |
|
17 |
+ (:args (x :scs (unsigned-reg) :target r)) |
|
18 |
+ (:arg-types unsigned-num) |
|
19 |
+ (:results (r :scs (unsigned-reg))) |
|
20 |
+ (:result-types unsigned-num) |
|
21 |
+ (:generator 3 |
|
22 |
+ (unless (location= r x) ; only break the spurious dep. chain |
|
23 |
+ (inst xor r r)) ; if r isn't the same register as x. |
|
24 |
+ (inst popcnt r x))) |
|
25 |
+ |
|
26 |
+(in-package "POPCNT") |
|
27 |
+ |
|
28 |
+(defun popcnt (x) |
|
29 |
+ (declare (inline)) |
|
30 |
+ (popcnt x)) |
0 | 31 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,69 @@ |
1 |
+(defpackage :bintree |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :bintree) |
|
5 |
+ |
|
6 |
+(defclass bintree () |
|
7 |
+ ((value :initarg :value :accessor node-value) |
|
8 |
+ (%left :initarg :left :accessor tree-left :initform nil) |
|
9 |
+ (%right :initarg :right :accessor tree-right :initform nil))) |
|
10 |
+ |
|
11 |
+(define-condition constraint-violated (serious-condition) |
|
12 |
+ ()) |
|
13 |
+ |
|
14 |
+(defmethod (setf tree-left) :before ((new-value bintree) (object bintree)) |
|
15 |
+ (unless (<= (node-value new-value) |
|
16 |
+ (node-value object)) |
|
17 |
+ (error 'constraint-violated))) |
|
18 |
+ |
|
19 |
+(defmethod (setf tree-left) ((new-value integer) (object bintree)) |
|
20 |
+ (setf (tree-left object) (make-instance 'bintree :value new-value))) |
|
21 |
+ |
|
22 |
+(defmethod (setf tree-right) :before ((new-value bintree) (object bintree)) |
|
23 |
+ (unless (> (node-value new-value) |
|
24 |
+ (node-value object)) |
|
25 |
+ (error 'constraint-violated))) |
|
26 |
+ |
|
27 |
+(defmethod (setf tree-right) ((new-value integer) (object bintree)) |
|
28 |
+ (setf (tree-right object) (make-instance 'bintree :value new-value))) |
|
29 |
+ |
|
30 |
+(defun insert (tree value) |
|
31 |
+ (if (<= value (node-value tree)) |
|
32 |
+ (if (null (tree-left tree)) |
|
33 |
+ (setf (tree-left tree) value) |
|
34 |
+ (insert (tree-left tree) value)) |
|
35 |
+ (if (null (tree-right tree)) |
|
36 |
+ (setf (tree-right tree) value) |
|
37 |
+ (insert (tree-right tree) value)))) |
|
38 |
+ |
|
39 |
+(defun rotate (tree direction) |
|
40 |
+ (ecase direction |
|
41 |
+ (:right (let* ((right-child (tree-right tree)) |
|
42 |
+ (left-of-right (tree-left right-child))) |
|
43 |
+ (setf (tree-left right-child) tree |
|
44 |
+ (tree-right tree) left-of-right) |
|
45 |
+ right-child)) |
|
46 |
+ (:left (let* ((left-child (tree-left tree)) |
|
47 |
+ (right-of-left (tree-right left-child))) |
|
48 |
+ (setf (tree-right left-child) tree |
|
49 |
+ (tree-left tree) right-of-left) |
|
50 |
+ left-child)))) |
|
51 |
+ |
|
52 |
+(defun list->tree (list) |
|
53 |
+ (declare (optimize (debug 3))) |
|
54 |
+ (destructuring-bind (root . rest) list |
|
55 |
+ (let ((result (make-instance 'bintree :value root))) |
|
56 |
+ (mapcar (lambda (v) (insert result v)) |
|
57 |
+ rest) |
|
58 |
+ result))) |
|
59 |
+ |
|
60 |
+(defmethod print-object ((object bintree) stream) |
|
61 |
+ (labels ((print-node (node stream) |
|
62 |
+ (if node |
|
63 |
+ (format stream "~a (~a) (~a)" |
|
64 |
+ (node-value node) |
|
65 |
+ (print-node (tree-left node) nil) |
|
66 |
+ (print-node (tree-right node) nil)) |
|
67 |
+ (format stream "~a" node)))) |
|
68 |
+ (print-unreadable-object (object stream :type t :identity t) |
|
69 |
+ (format stream "(~a)" (print-node object nil))))) |
0 | 70 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,104 @@ |
1 |
+ |
|
2 |
+(:DARKMATTER |
|
3 |
+ ((:ID . "1499699102316") (:NEXT . "1499699077360") (:PREV . "") (:COUNT . 0) |
|
4 |
+ (:LANG . "lisp") |
|
5 |
+ (:LISP . "(eval-when (:compile-toplevel :load-toplevel :execute) |
|
6 |
+ (let ((*standard-output* (make-broadcast-stream))) |
|
7 |
+ (push (truename \"~/git_repos/fwoar.lisputils\") asdf:*central-registry*) |
|
8 |
+ (ql:quickload '(:alexandria :serapeum :lquery :cells :fwoar.lisputils :drakma :puri)))) |
|
9 |
+(defpackage :cells-html-scraper |
|
10 |
+ (:use :cl :alexandria :serapeum :fw.lu :cells)) |
|
11 |
+(in-package :cells-html-scraper)") |
|
12 |
+ (:MD . "") |
|
13 |
+ (:OUTPUT |
|
14 |
+ . "<div id=\"result\">#<PACKAGE \"CELLS-HTML-SCRAPER\"></div>")) |
|
15 |
+ ((:ID . "1499699077360") (:NEXT . "1499699569637") (:PREV . "1499699102316") |
|
16 |
+ (:COUNT . 0) (:LANG . "lisp") |
|
17 |
+ (:LISP . "(lquery:define-lquery-macro progn (nodes &rest args) |
|
18 |
+ `(lquery:$ |
|
19 |
+ (inline ,nodes) |
|
20 |
+ ,@args)) |
|
21 |
+ |
|
22 |
+(lquery:define-lquery-function hn-score (item) |
|
23 |
+ (lquery:$1 (inline item) |
|
24 |
+ (next) |
|
25 |
+ \".score\" |
|
26 |
+ (text))) |
|
27 |
+ |
|
28 |
+(lquery:define-lquery-function hn-age (item) |
|
29 |
+ (lquery:$1 (inline item) |
|
30 |
+ (next) |
|
31 |
+ \".age\" |
|
32 |
+ (text))) |
|
33 |
+ |
|
34 |
+(lquery:define-lquery-function hn-comments (item) |
|
35 |
+ (lquery:$1 (inline item) |
|
36 |
+ (next) |
|
37 |
+ \".age\" |
|
38 |
+ (lquery-funcs:next) |
|
39 |
+ (next) |
|
40 |
+ (next) |
|
41 |
+ (text)))") |
|
42 |
+ (:MD . "") (:OUTPUT . "<div id=\"result\">HN-COMMENTS</div>")) |
|
43 |
+ ((:ID . "1499699569637") (:NEXT . "1499699613496") (:PREV . "1499699077360") |
|
44 |
+ (:COUNT . 0) (:LANG . "lisp") |
|
45 |
+ (:LISP . "(defclass hn-item () |
|
46 |
+ ((%url :initarg :url :reader url) |
|
47 |
+ (%title :initarg :title :reader title) |
|
48 |
+ (%score :initarg :score :reader score) |
|
49 |
+ (%age :initarg :age :reader age) |
|
50 |
+ (%comments :initarg :comments :reader comments))) |
|
51 |
+ |
|
52 |
+(defun make-hn-item (url title score age comments) |
|
53 |
+ (make-instance 'hn-item |
|
54 |
+ :url (puri:parse-uri url) |
|
55 |
+ :title title |
|
56 |
+ :score (when score (parse-integer score :junk-allowed t)) |
|
57 |
+ :age age |
|
58 |
+ :comments (when comments (parse-integer comments :junk-allowed t))))") |
|
59 |
+ (:MD . "") (:OUTPUT . "<div id=\"result\">MAKE-HN-ITEM</div>")) |
|
60 |
+ ((:ID . "1499699613496") (:NEXT . "1499699601303") (:PREV . "1499699569637") |
|
61 |
+ (:COUNT . 0) (:LANG . "lisp") |
|
62 |
+ (:LISP . "(defmodel url-getter () |
|
63 |
+ ((%url :initarg :url |
|
64 |
+ :accessor url |
|
65 |
+ :initform (c-in nil)) |
|
66 |
+ (%text :initform (c? (if (^url) |
|
67 |
+ (^url) |
|
68 |
+ \"\")) |
|
69 |
+ :reader text)))") |
|
70 |
+ (:MD . "") (:OUTPUT . "<div id=\"result\">NIL</div>")) |
|
71 |
+ ((:ID . "1499699601303") (:NEXT . "1499699627294") (:PREV . "1499699613496") |
|
72 |
+ (:COUNT . 0) (:LANG . "lisp") |
|
73 |
+ (:LISP . "(defmodel hn-scraper () |
|
74 |
+ ((%html :initarg :html |
|
75 |
+ :accessor html |
|
76 |
+ :initform (c-in \"\")) |
|
77 |
+ (%doc :reader %doc :initform (c? (plump:parse (^html)))) |
|
78 |
+ (%hnmain :reader %hnmain |
|
79 |
+ :initform (c? (lquery:$1 |
|
80 |
+ (inline (^%doc)) |
|
81 |
+ \"#hnmain\"))) |
|
82 |
+ (%body :reader %body |
|
83 |
+ :initform (c? (lquery:$ |
|
84 |
+ (inline (^%hnmain)) |
|
85 |
+ \".itemlist tr.athing\"))) |
|
86 |
+ (%titles :reader titles |
|
87 |
+ :initform (c? (lquery:$ |
|
88 |
+ (inline (^%body)) |
|
89 |
+ (combine (progn \".title .storylink\" (attr \"href\") |
|
90 |
+ (node)) |
|
91 |
+ (progn \".title .storylink\" (text) |
|
92 |
+ (node)) |
|
93 |
+ (hn-score) |
|
94 |
+ (hn-age) |
|
95 |
+ (hn-comments))))) |
|
96 |
+ (%items :reader items :initform (c? (map 'vector |
|
97 |
+ (op (apply 'make-hn-item _*)) |
|
98 |
+ (^titles))))))") |
|
99 |
+ (:MD . "") (:OUTPUT . "<div id=\"result\">NIL</div>")) |
|
100 |
+ ((:ID . "1499699627294") (:NEXT . "") (:PREV . "1499699601303") (:COUNT . 0) |
|
101 |
+ (:LANG . "lisp") |
|
102 |
+ (:LISP . "(defparameter *url-getter* (make-instance 'url-getter)) |
|
103 |
+(defparameter *parser* (make-instance 'hn-scraper :html (^text *url-getter*)))") |
|
104 |
+ (:MD . "") (:OUTPUT . ""))) |
|
0 | 105 |
\ No newline at end of file |
1 | 106 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,94 @@ |
1 |
+(defpackage :cells-html-scraper |
|
2 |
+ (:use :cl :alexandria :serapeum :fw.lu :cells)) |
|
3 |
+ |
|
4 |
+(in-package :cells-html-scraper) |
|
5 |
+ |
|
6 |
+(lquery:define-lquery-macro progn (nodes &rest args) |
|
7 |
+ `(lquery:$ |
|
8 |
+ (inline ,nodes) |
|
9 |
+ ,@args)) |
|
10 |
+ |
|
11 |
+(lquery:define-lquery-function hn-score (item) |
|
12 |
+ (lquery:$1 (inline item) |
|
13 |
+ (next) |
|
14 |
+ ".score" |
|
15 |
+ (text))) |
|
16 |
+ |
|
17 |
+(lquery:define-lquery-function hn-age (item) |
|
18 |
+ (lquery:$1 (inline item) |
|
19 |
+ (next) |
|
20 |
+ ".age" |
|
21 |
+ (text))) |
|
22 |
+ |
|
23 |
+(lquery:define-lquery-function hn-comments (item) |
|
24 |
+ (lquery:$1 (inline item) |
|
25 |
+ (next) |
|
26 |
+ ".age" |
|
27 |
+ (lquery-funcs:next) |
|
28 |
+ (next) |
|
29 |
+ (next) |
|
30 |
+ (text))) |
|
31 |
+ |
|
32 |
+(defclass hn-item () |
|
33 |
+ ((%url :initarg :url :reader url) |
|
34 |
+ (%title :initarg :title :reader title) |
|
35 |
+ (%score :initarg :score :reader score) |
|
36 |
+ (%age :initarg :age :reader age) |
|
37 |
+ (%comments :initarg :comments :reader comments))) |
|
38 |
+ |
|
39 |
+(defun make-hn-item (url title score age comments) |
|
40 |
+ (make-instance 'hn-item |
|
41 |
+ :url (puri:parse-uri url) |
|
42 |
+ :title title |
|
43 |
+ :score (when score (parse-integer score :junk-allowed t)) |
|
44 |
+ :age age |
|
45 |
+ :comments (when comments (parse-integer comments :junk-allowed t)))) |
|
46 |
+ |
|
47 |
+(defmodel hn-scraped () |
|
48 |
+ ((%html :initarg :html |
|
49 |
+ :accessor html |
|
50 |
+ :initform (c-in "")) |
|
51 |
+ (%doc :reader %doc :initform (c? (plump:parse (^html)))) |
|
52 |
+ (%hnmain :reader %hnmain |
|
53 |
+ :initform (c? (lquery:$1 |
|
54 |
+ (inline (^%doc)) |
|
55 |
+ "#hnmain"))) |
|
56 |
+ (%body :reader %body |
|
57 |
+ :initform (c? (lquery:$ |
|
58 |
+ (inline (^%hnmain)) |
|
59 |
+ ".itemlist tr.athing"))) |
|
60 |
+ (%titles :reader titles |
|
61 |
+ :initform (c? (lquery:$ |
|
62 |
+ (inline (^%body)) |
|
63 |
+ (combine (progn ".title .storylink" (attr "href") |
|
64 |
+ (node)) |
|
65 |
+ (progn ".title .storylink" (text) |
|
66 |
+ (node)) |
|
67 |
+ (hn-score) |
|
68 |
+ (hn-age) |
|
69 |
+ (hn-comments))))) |
|
70 |
+ (%items :reader items :initform (c? (map 'vector |
|
71 |
+ (op (apply 'make-hn-item _*)) |
|
72 |
+ (^titles)))))) |
|
73 |
+ |
|
74 |
+(defmodel url-getter () |
|
75 |
+ ((%url :initarg :url |
|
76 |
+ :accessor url |
|
77 |
+ :initform (c-in '())) |
|
78 |
+ (%text :reader text |
|
79 |
+ :initform (c? (let ((drakma:*text-content-types* (acons "application" "json" drakma:*text-content-types*))) |
|
80 |
+ (drakma:http-request (^url))))))) |
|
81 |
+ |
|
82 |
+(defun get-links (url) |
|
83 |
+ (restart-case (values (map 'list (compose (op (list* url _)) |
|
84 |
+ #'cdr) |
|
85 |
+ (remove-if-not (op (string= _ "alternate")) |
|
86 |
+ (lquery:$ |
|
87 |
+ (initialize (drakma:http-request url)) |
|
88 |
+ "link" |
|
89 |
+ (combine (attr "rel") (attr "href") (attr "type"))) |
|
90 |
+ :key #'car)) |
|
91 |
+ "") |
|
92 |
+ (continue nil |
|
93 |
+ :report (lambda (stream) (format stream "skip url ~a" url)) |
|
94 |
+ (values nil url)))) |
0 | 95 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,28 @@ |
1 |
+(defpackage :changelog-filter |
|
2 |
+ (:use :cl :alexandria :serapeum :fw.lu) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :changelog-filter) |
|
5 |
+ |
|
6 |
+(defparameter *changelog-path* "/Users/elangley/WebKit/Source/WebCore/ChangeLog") |
|
7 |
+ |
|
8 |
+(defun get-block (stream) |
|
9 |
+ (let ((header (read-line stream))) |
|
10 |
+ (loop for next = (peek-char nil stream nil) |
|
11 |
+ while (and next (whitespacep next)) |
|
12 |
+ collect (read-line stream) into lines |
|
13 |
+ finally |
|
14 |
+ (return (trim-whitespace |
|
15 |
+ (string-join (cons header lines) |
|
16 |
+ #\newline)))))) |
|
17 |
+ |
|
18 |
+(defun main () |
|
19 |
+ (let ((*changelog-path* (or (caddr sb-ext:*posix-argv*) |
|
20 |
+ *changelog-path*)) |
|
21 |
+ (search-string (cadr sb-ext:*posix-argv*))) |
|
22 |
+ (handler-case (with-input-from-file (s *changelog-path*) |
|
23 |
+ (loop for next-block = (get-block s) |
|
24 |
+ when (search search-string next-block :test #'char-equal) do |
|
25 |
+ (format t "~&~a~%" next-block))) |
|
26 |
+ (end-of-file (c) c)))) |
|
27 |
+ |
|
28 |
+;;; sbcl --disable-debugger --no-userinit --load $HOME/quicklisp/setup.lisp --eval '(ql:quickload (list :alexandria :serapeum :fwoar.lisputils))' --load /Users/elangley/git_repos/lisp-sandbox/changelog-filter.lisp --eval "(save-lisp-and-die "'"'"changelog-filter"'"'" :executable t :toplevel #'changelog-filter::main :compression t)" |
0 | 29 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,13 @@ |
1 |
+(defpackage :code-lookup |
|
2 |
+ (:use :cl :serapeum :alexandria :fw.lu) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :code-lookup) |
|
5 |
+ |
|
6 |
+ |
|
7 |
+(defun call-with-auto-coercions (coercions cb) |
|
8 |
+ (handler-bind ((type-error (lambda (c) |
|
9 |
+ (loop for ((from-type to-type) . coercion) in coercions |
|
10 |
+ when (and (subtypep to-type (type-error-expected-type c)) |
|
11 |
+ (subtypep (type-of (type-error-datum c)) from-type)) |
|
12 |
+ do (store-value (funcall coercion (type-error-datum c))))))) |
|
13 |
+ (funcall cb))) |
0 | 14 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,15 @@ |
1 |
+(defpackage :dotimes-printer |
|
2 |
+ (:use :cl)) |
|
3 |
+(in-package :dotimes-printer) |
|
4 |
+ |
|
5 |
+(dotimes (var count &optional result) |
|
6 |
+ &body body) |
|
7 |
+ |
|
8 |
+(defmacro destructure-dotimes ((var count &optional result) &body body) |
|
9 |
+ `(translate |
|
10 |
+ (produce-initializer ',var 0) |
|
11 |
+ (produce-check ',var '< ',count) |
|
12 |
+ (produce-increment ',))) |
|
13 |
+ |
|
14 |
+(defun translate-dotimes (form) |
|
15 |
+ ()) |
0 | 16 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,19 @@ |
1 |
+(defpackage :garagiste-app |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :garagiste-app) |
|
5 |
+ |
|
6 |
+(defun get-signin-page () |
|
7 |
+ (let ((c-j (make-instance 'drakma:cookie-jar))) |
|
8 |
+ (values (plump:parse |
|
9 |
+ (drakma:http-request "https://app.garagiste.com/users/sign_in" |
|
10 |
+ :cookie-jar c-j)) |
|
11 |
+ c-j))) |
|
12 |
+ |
|
13 |
+(defun extract-auth-token (doc) |
|
14 |
+ (lquery:$1 (inline doc) |
|
15 |
+ "form input[type=hidden][name=authenticity_token]" |
|
16 |
+ (attr "value"))) |
|
17 |
+ |
|
18 |
+(defun login-garagiste (user pass auth-token) |
|
19 |
+ ) |
0 | 20 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,119 @@ |
1 |
+(defpackage :infer-type |
|
2 |
+ (:use :cl :serapeum) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :infer-type) |
|
5 |
+ |
|
6 |
+(defclass type-env () |
|
7 |
+ ((%typedefs :initform (make-hash-table) |
|
8 |
+ :initarg :typedefs |
|
9 |
+ :reader typedefs) |
|
10 |
+ (%typebindings :initform (make-hash-table) |
|
11 |
+ :initarg :type-bindings |
|
12 |
+ :reader typebindings) |
|
13 |
+ (%values :initform (make-hash-table) |
|
14 |
+ :reader values-))) |
|
15 |
+ |
|
16 |
+(defparameter *type-env* (make-instance 'type-env)) |
|
17 |
+ |
|
18 |
+(defmacro with-types ((&rest types) (&rest defs) &body body) |
|
19 |
+ `(let ((*type-env* (make-instance 'type-env |
|
20 |
+ :typedefs |
|
21 |
+ (alexandria:alist-hash-table ',(loop for (type def) in types |
|
22 |
+ collect (cons type def))) |
|
23 |
+ :type-bindings |
|
24 |
+ (alexandria:alist-hash-table ',defs)))) |
|
25 |
+ ,@body)) |
|
26 |
+ |
|
27 |
+(defun lookup-type (type) |
|
28 |
+ (gethash type (typedefs *type-env*))) |
|
29 |
+ |
|
30 |
+(defun get-function-type (expr) |
|
31 |
+ (gethash (car expr) |
|
32 |
+ (typebindings *type-env*))) |
|
33 |
+ |
|
34 |
+(defun is-type-variable (tyvar) |
|
35 |
+ (and (symbolp tyvar) |
|
36 |
+ (char= (elt (symbol-name tyvar) |
|
37 |
+ 0) |
|
38 |
+ #\?))) |
|
39 |
+ |
|
40 |
+(defun is-bound-type-variable (tyvar) |
|
41 |
+ (nth-value 1 (gethash tyvar (typebindings *type-env*)))) |
|
42 |
+ |
|
43 |
+(defun lookup-type-variable (tyvar) |
|
44 |
+ (gethash tyvar (typebindings *type-env*))) |
|
45 |
+ |
|
46 |
+(defun infer-simple-type (expr) |
|
47 |
+ (loop for k being the hash-keys of (typebindings *type-env*) |
|
48 |
+ using (hash-value v) |
|
49 |
+ when (subtypep (type-of expr) v) do |
|
50 |
+ (return k))) |
|
51 |
+ |
|
52 |
+(defun infer-complex-type (expr) |
|
53 |
+ (destructuring-bind (ret-type arg-types) (get-function-type expr) |
|
54 |
+ )) |
|
55 |
+ |
|
56 |
+(defun infer-type (expr) |
|
57 |
+ (if (is-simple-expression expr) |
|
58 |
+ (infer-simple-type expr) |
|
59 |
+ (infer-complex-type expr))) |
|
60 |
+ |
|
61 |
+(defun bind-type-variable (expr tyvar) |
|
62 |
+ (setf (gethash tyvar (typebindings *type-env*)) |
|
63 |
+ (infer-type expr))) |
|
64 |
+ |
|
65 |
+(defun check-type- (expr type) |
|
66 |
+ (if (is-type-variable type) |
|
67 |
+ (if (is-bound-type-variable type) |
|
68 |
+ (check-type- expr |
|
69 |
+ (lookup-type-variable type)) |
|
70 |
+ (bind-type-variable expr type)) |
|
71 |
+ (if (is-simple-expression expr) |
|
72 |
+ (check-simple-type expr type) |
|
73 |
+ (check-complex-type expr type)))) |
|
74 |
+ |
|
75 |
+(defun is-simple-expression (expr) |
|
76 |
+ (or (not (listp expr)) |
|
77 |
+ (eql (car expr) |
|
78 |
+ 'quote))) |
|
79 |
+ |
|
80 |
+(defun check-simple-type (expr type) |
|
81 |
+ (values (subtypep (type-of expr) |
|
82 |
+ (lookup-type type)) |
|
83 |
+ type)) |
|
84 |
+ |
|
85 |
+(defun check-complex-type (expr type) |
|
86 |
+ (destructuring-bind (return-type arg-types) (get-function-type expr) |
|
87 |
+ (values (and (lookup-type return-type) |
|
88 |
+ (subtypep (lookup-type return-type) |
|
89 |
+ (lookup-type type)) |
|
90 |
+ (= (1- (length expr)) |
|
91 |
+ (length arg-types)) |
|
92 |
+ (every (lambda (arg-expr arg-type) |
|
93 |
+ (and (lookup-type arg-type) |
|
94 |
+ (check-type- arg-expr arg-type))) |
|
95 |
+ (cdr expr) |
|
96 |
+ arg-types)) |
|
97 |
+ return-type))) |
|
98 |
+ |
|
99 |
+ |
|
100 |
+(defun foo (a b) |
|
101 |
+ (check-type a number) |
|
102 |
+ (check-type b number) |
|
103 |
+ (+ a b)) |
|
104 |
+ |
|
105 |
+#+null |
|
106 |
+(defmacro with-implicit-conversions ((&rest conversions) &body body) |
|
107 |
+ `(let ((num-coercions 0) |
|
108 |
+ (coercion-limit 10)) |
|
109 |
+ (handler-bind ((type-error (lambda (c) |
|
110 |
+ (incf num-coercions) |
|
111 |
+ (when (< num-coercions |
|
112 |
+ coercion-limit) |
|
113 |
+ (let ((datum (type-error-datum c)) |
|
114 |
+ (expected-type (type-error-expected-type c))) |
|
115 |
+ (store-value |
|
116 |
+ (cond ,@(loop for (type handler) in conversions |
|
117 |
+ collect `((subtypep ',type expected-type) |
|
118 |
+ (,handler datum)))))))))) |
|
119 |
+ ,@body))) |
0 | 120 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,80 @@ |
1 |
+(defpackage :labels-parser |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :labels-parser) |
|
5 |
+ |
|
6 |
+(defmacro cond-switch* ((&rest bindings) &body clauses) |
|
7 |
+ `(let* (,@bindings) |
|
8 |
+ (cond ,@clauses))) |
|
9 |
+ |
|
10 |
+(defun read-group (s) |
|
11 |
+ (labels ((is-terminal-p (char) |
|
12 |
+ (or (null char) |
|
13 |
+ (member char '(#\space #\) #\,)))) |
|
14 |
+ (peek () |
|
15 |
+ (peek-char nil *standard-input* nil)) |
|
16 |
+ (discard () |
|
17 |
+ (read-char *standard-input*)) |
|
18 |
+ (getch () |
|
19 |
+ (read-char *standard-input*)) |
|
20 |
+ |
|
21 |
+ (consume-whitespace (next) |
|
22 |
+ (if (eql #\space (peek)) |
|
23 |
+ (progn (read-char) |
|
24 |
+ (consume-whitespace next)) |
|
25 |
+ (funcall next))) |
|
26 |
+ (consume-matching (pred) |
|
27 |
+ (if (funcall pred (peek)) |
|
28 |
+ (getch) |
|
29 |
+ (error 'parse-fail))) |
|
30 |
+ (consume-until (term-pred pred &optional accum) |
|
31 |
+ (cond-switch* ((nc (peek))) |
|
32 |
+ ((funcall term-pred nc) |
|
33 |
+ (consume-whitespace |
|
34 |
+ (lambda () (reverse accum)))) |
|
35 |
+ (t |
|
36 |
+ (consume-until term-pred pred |
|
37 |
+ (cons (consume-matching pred) |
|
38 |
+ accum))))) |
|
39 |
+ (consume-nonterminal (pred) |
|
40 |
+ (consume-until #'is-terminal-p pred)) |
|
41 |
+ |
|
42 |
+ (read-symbol () |
|
43 |
+ (coerce (consume-nonterminal #'alphanumericp) |
|
44 |
+ 'string)) |
|
45 |
+ (read-number () |
|
46 |
+ (parse-integer |
|
47 |
+ (coerce (consume-nonterminal #'digit-char-p) |
|
48 |
+ 'string))) |
|
49 |
+ (read-primitive () |
|
50 |
+ (cond-switch* ((c (peek))) |
|
51 |
+ ((null c) nil) |
|
52 |
+ ((digit-char-p c) (read-number)) |
|
53 |
+ ((alpha-char-p c) (read-symbol)))) |
|
54 |
+ (read-list (&optional accum) |
|
55 |
+ (cond-switch* ((next (read-primitive)) |
|
56 |
+ (nc (peek))) |
|
57 |
+ ((null next) |
|
58 |
+ (if (eql #\) nc) |
|
59 |
+ (reverse accum) |
|
60 |
+ (error 'parse-fail))) |
|
61 |
+ ((eql #\) nc) |
|
62 |
+ (discard) |
|
63 |
+ (reverse (cons next accum))) |
|
64 |
+ (t |
|
65 |
+ (read-list (cons next accum))))) |
|
66 |
+ |
|
67 |
+ (read-main () |
|
68 |
+ (cond-switch* ((nc (peek))) |
|
69 |
+ ((null nc) nil) |
|
70 |
+ ((eql #\space nc) (read-char) (read-main)) |
|
71 |
+ ((eql nc #\() |
|
72 |
+ (read-char) |
|
73 |
+ (consume-whitespace |
|
74 |
+ (lambda () (read-list)))) |
|
75 |
+ (t (prog1 (read-primitive) |
|
76 |
+ (when (listen *standard-input*) |
|
77 |
+ (error 'parse-fail))))))) |
|
78 |
+ (let ((*standard-input* s)) |
|
79 |
+ (read-main)))) |
|
80 |
+ |
0 | 6 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,17 @@ |
1 |
+(defpackage :qtools-demo |
|
2 |
+ (:use :cl)) |
|
3 |
+ |
|
4 |
+(in-package :qtools-demo) |
|
5 |
+ |
|
6 |
+(defun make-slider () |
|
7 |
+ (prog1-bind (the-widget (make-instance 'qui:slider)) |
|
8 |
+ )) |
|
9 |
+ |
|
10 |
+(defun main () |
|
11 |
+ (cl+qt:with-main-window (w (make-instance 'qui:panel-container)) |
|
12 |
+ (qui:add-widget (make-instance 'qui:panel :title "An empty panel :(") w) |
|
13 |
+ (qui:add-widget (make-instance 'qui:panel :title "A slider, whoa!" |
|
14 |
+ :center (make-slider)) w) |
|
15 |
+ (qui:add-widget (make-instance 'qui:listing :title "A slider, whoa!" |
|
16 |
+ :center (make-instance 'qui:slider)) w)) |
|
17 |
+) |
0 | 2 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,73 @@ |
1 |
+(defpackage :git-pick-patch |
|
2 |
+ (:use :cl :alexandria :serapeum) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :git-pick-patch) |
|
5 |
+ |
|
6 |
+(defun read-header (inp) |
|
7 |
+ (string-join (loop for line = (read-line inp nil) |
|
8 |
+ while line |
|
9 |
+ collect line |
|
10 |
+ until (eql #\@ (peek-char nil inp nil))) |
|
11 |
+ #\newline)) |
|
12 |
+ |
|
13 |
+(defun read-hunk (inp) |
|
14 |
+ (when (eql #\@ |
|
15 |
+ (peek-char nil inp nil)) |
|
16 |
+ (string-join (loop for line = (read-line inp nil) |
|
17 |
+ while line |
|
18 |
+ collect line |
|
19 |
+ until (member (peek-char nil inp nil) '(#\@ #\d))) |
|
20 |
+ #\newline))) |
|
21 |
+ |
|
22 |
+(defun read-hunks (inp) |
|
23 |
+ (loop for hunk = (read-hunk inp) |
|
24 |
+ while hunk |
|
25 |
+ collect hunk)) |
|
26 |
+ |
|
27 |
+(defun get-file-patch (inp) |
|
28 |
+ (list (read-header inp) |
|
29 |
+ (read-hunks inp))) |
|
30 |
+ |
|
31 |
+(defun get-all-patches (inp) |
|
32 |
+ (loop for patch = (get-file-patch inp) |
|
33 |
+ for (header data) = patch |
|
34 |
+ while (and (string/= header "") |
|
35 |
+ (not (null data))) |
|
36 |
+ collect patch)) |
|
37 |
+ |
|
38 |
+(defun filter-hunks (hunks predicate) |
|
39 |
+ (remove-if-not predicate hunks)) |
|
40 |
+ |
|
41 |
+(defun filter-file-hunks (file-data predicate) |
|
42 |
+ (let ((results (filter-hunks (cadr file-data) |
|
43 |
+ predicate))) |
|
44 |
+ (when results |
|
45 |
+ (list (car file-data) |
|
46 |
+ results)))) |
|
47 |
+ |
|
48 |
+(defun filter-patch (patch-data predicate) |
|
49 |
+ (remove-if #'null (mapcar (lambda (x) |
|
50 |
+ (filter-file-hunks x predicate)) |
|
51 |
+ patch-data))) |
|
52 |
+ |
|
53 |
+(defun combine-hunks (hunks) |
|
54 |
+ (string-join hunks #\newline)) |
|
55 |
+ |
|
56 |
+(defun rebuild-file-patch (file-data) |
|
57 |
+ (destructuring-bind (header hunks) file-data |
|
58 |
+ (format nil "~a~%~a" header (combine-hunks hunks)))) |
|
59 |
+ |
|
60 |
+(defun rebuild-patch (patch-data) |
|
61 |
+ (string-join (mapcar #'rebuild-file-patch patch-data) |
|
62 |
+ #\newline)) |
|
63 |
+ |
|
64 |
+(defun main () |
|
65 |
+ (if (null (cadr sb-ext:*posix-argv*)) |
|
66 |
+ (format t "~&Must provide a pattern!") |
|
67 |
+ (let* ((pattern (cadr sb-ext:*posix-argv*))) |
|
68 |
+ (loop for patch = (get-file-patch *standard-input*) |
|
69 |
+ for filtered = (when patch (filter-file-hunks patch |
|
70 |
+ (op (cl-ppcre:scan pattern _)))) |
|
71 |
+ until (equal patch '("" nil)) |
|
72 |
+ when filtered do |
|
73 |
+ (format t "~&~a~&" (rebuild-file-patch filtered)))))) |
0 | 6 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,123 @@ |
1 |
+(uiop:define-package :fwoar.zipfile |
|
2 |
+ (:mix :cl :fwoar.lisputils) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :fwoar.zipfile) |
|
5 |
+ |
|
6 |
+(defun read-bytes (n s) |
|
7 |
+ (with (seq (make-array n :element-type 'serapeum:octet)) |
|
8 |
+ (values seq |
|
9 |
+ (read-sequence seq s)))) |
|
10 |
+ |
|
11 |
+(defun calculate-sizes (desc) |
|
12 |
+ (reduce #'+ desc |
|
13 |
+ :key #'cadr |
|
14 |
+ :initial-value 0)) |
|
15 |
+ |
|
16 |
+(defun le->int (bytes) |
|
17 |
+ (cadr |
|
18 |
+ (reduce (op (destructuring-bind (count val) _1 |
|
19 |
+ (list (1+ count) |
|
20 |
+ (+ val |
|
21 |
+ (ash _2 |
|
22 |
+ (* count 8)))))) |
|
23 |
+ bytes |
|
24 |
+ :initial-value (list 0 0)))) |
|
25 |
+ |
|
26 |
+(defun get-extractable-bytes (desc &optional (bindings ())) |
|
27 |
+ (loop for ((name size . other) . rest) on (resolve-sizes desc bindings) |
|
28 |
+ until (symbolp size) |
|
29 |
+ collect (list* name size other) into extractable |
|
30 |
+ finally (return (values extractable |
|
31 |
+ (append (serapeum:unsplice |
|
32 |
+ (when (symbolp size) |
|
33 |
+ (list* name size other))) |
|
34 |
+ rest))))) |
|
35 |
+ |
|
36 |
+(defun resolve-sizes (desc extant-bindings) |
|
37 |
+ (declare (optimize (debug 3))) |
|
38 |
+ (loop with bindings = (copy-seq extant-bindings) |
|
39 |
+ for (name size . rest) in desc |
|
40 |
+ for resolved = (when (symbolp size) |
|
41 |
+ (cdr (assoc size bindings))) |
|
42 |
+ when resolved do (push (cons name resolved) |
|
43 |
+ bindings) |
|
44 |
+ if resolved collect (list* name resolved rest) into new-desc |
|
45 |
+ else collect (list* name size rest) into new-desc |
|
46 |
+ finally (return (values new-desc |
|
47 |
+ (remove-duplicates (append (mapcar (op (apply #'cons (subseq _ 0 2))) |
|
48 |
+ new-desc) |
|
49 |
+ bindings) |
|
50 |
+ :key 'car |
|
51 |
+ :from-end t))))) |
|
52 |
+ |
|
53 |
+(defun extract-bytes (desc bytes) |
|
54 |
+ (loop |
|
55 |
+ with cur-idx = 0 |
|
56 |
+ for (name size . rest) in desc |
|
57 |
+ for next-seq = (subseq bytes cur-idx |
|
58 |
+ (+ cur-idx size)) |
|
59 |
+ collect (cons name (if rest |
|
60 |
+ (funcall (car rest) next-seq) |
|
61 |
+ next-seq)) |
|
62 |
+ do (incf cur-idx size))) |
|
63 |
+ |
|
64 |
+(defun parse-struct (desc s) |
|
65 |
+ (let* ((struct-size (calculate-sizes desc)) |
|
66 |
+ (bytes (read-bytes struct-size s))) |
|
67 |
+ (extract-bytes desc bytes))) |
|
68 |
+ |
|
69 |
+(defun make-zipfile-stream (fn) |
|
70 |
+ (open fn :element-type '(unsigned-byte 8))) |
|
71 |
+ |
|
72 |
+ |
|
73 |
+(defun extract (raw-desc s &optional bindings) |
|
74 |
+ (multiple-value-bind (desc remainder) (get-extractable-bytes raw-desc bindings) |
|
75 |
+ (let ((next-segment (parse-struct desc s))) |
|
76 |
+ (if remainder |
|
77 |
+ (append next-segment |
|
78 |
+ (extract remainder s (append next-segment bindings))) |
|
79 |
+ next-segment)))) |
|
80 |
+ |
|
81 |
+(defparameter *zip-local-file-header* |
|
82 |
+ '((signature 4) |
|
83 |
+ (version 2) |
|
84 |
+ (flags 2) |
|
85 |
+ (compression 2 le->int) |
|
86 |
+ (mod-time 2) |
|
87 |
+ (mod-date 2) |
|
88 |
+ (crc-32 4) |
|
89 |
+ (compressed-size 4 le->int) |
|
90 |
+ (uncompressed-size 4 le->int) |
|
91 |
+ (file-name-length 2 le->int) |
|
92 |
+ (extra-field-length 2 le->int) |
|
93 |
+ (file-name file-name-length babel:octets-to-string) |
|
94 |
+ (extra-field extra-field-length))) |
|
95 |
+ |
|
96 |
+(defun decode-file-data (metadata s) |
|
97 |
+ (let ((crc-32 (le->int (cdr (assoc 'crc-32 metadata)))) |
|
98 |
+ (compressed-size (cdr (assoc 'compressed-size metadata))) |
|
99 |
+ (uncompressed-size (cdr (assoc 'uncompressed-size metadata)))) |
|
100 |
+ (when (= 0 (+ crc-32 compressed-size uncompressed-size)) |
|
101 |
+ (error "bad zipfile: I don't support data descriptors yet...")) |
|
102 |
+ (format t "~&COMPRESSED-SIZE: ~a~%" compressed-size) |
|
103 |
+ (let ((compressed-data (read-bytes compressed-size s))) |
|
104 |
+ (format t "~&...~%") |
|
105 |
+ (values (serapeum:ecase-let (compression (cdr (assoc 'compression metadata))) |
|
106 |
+ (0 compressed-data) |
|
107 |
+ (8 (princ "decompress") |
|
108 |
+ (chipz:decompress nil (chipz:make-dstate 'chipz:deflate) compressed-data)) |
|
109 |
+ (t (error "unsupported compression ~a" compression))) |
|
110 |
+ metadata)))) |
|
111 |
+ |
|
112 |
+(defun decode-a-file-if-name (pred s) |
|
113 |
+ (let ((metadata (extract *zip-local-file-header* s))) |
|
114 |
+ (values (if (funcall pred (cdr (assoc 'file-name metadata))) |
|
115 |
+ (decode-file-data metadata s) |
|
116 |
+ (progn (file-position s (+ (file-position s) |
|
117 |
+ (cdr (assoc 'compressed-size metadata)))) |
|
118 |
+ nil)) |
|
119 |
+ metadata))) |
|
120 |
+ |
|
121 |
+(defun decode-a-file (s) |
|
122 |
+ (let ((metadata (extract *zip-local-file-header* s))) |
|
123 |
+ (decode-file-data metadata s))) |