forked from LispMechanics/cl-data-structures
/
expression-wrapper.lisp
106 lines (86 loc) · 3.58 KB
/
expression-wrapper.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
(in-package #:cl-data-structures)
(defclass expression (c2mop:funcallable-standard-object
fundamental-forward-range)
((%construct-function :initarg :construct-function
:type function
:reader read-body)
(%arguments :initarg :arguments
:initform nil
:reader read-arguments)
(%arguments-closure :accessor access-arguments-closure
:initarg :arguments-closure)
(%closure :accessor access-closure
:initarg :closure))
(:metaclass c2mop:funcallable-standard-class))
(defmethod clone ((obj expression))
(bind (((:slots %construct-function %arguments %closure %arguments-closure)
obj)
((:values result-closure arguments-closure)
(apply %construct-function
(funcall %arguments-closure)))
(result (make 'expression
:construct-function %construct-function
:arguments-closure arguments-closure
:arguments %arguments
:closure result-closure)))
result))
(defmethod initialize-instance :after ((obj expression) &rest all
&key &allow-other-keys)
(declare (ignore all))
(if (slot-boundp obj '%closure)
(c2mop:set-funcallable-instance-function obj (access-closure obj))
(reset! obj)))
(defmacro xpr (arguments &body body)
(let ((keys (plist-keys arguments)))
(with-gensyms (!fn)
`(cl-ds.utils:let-generator
((,!fn ,(mapcar (lambda (x) (intern (symbol-name x))) keys)
,@body))
(make 'cl-ds:expression
:construct-function (function ,!fn)
:arguments (list ,@arguments))))))
(defmethod traverse (function (obj expression))
(declare (optimize (speed 3) (debug 0) (space 0)))
(let ((fn (access-closure obj))
(function (ensure-function function)))
(declare (type (-> (t) t) function)
(type (-> (&optional boolean) t) fn))
(iterate
(for (values value not-finished) = (funcall fn))
(while not-finished)
(funcall function value)))
obj)
(defmethod across (function (obj expression))
(declare (optimize (speed 3) (debug 0) (space 0)))
(let ((function (ensure-function function)))
(declare (type (-> (t) t) function))
(bind (((:slots %construct-function %closure %arguments-closure) obj)
(fn (apply %construct-function (funcall %arguments-closure))))
(declare (type (-> (&optional boolean) t) fn))
(iterate
(for (values value not-finished) = (funcall fn))
(while not-finished)
(funcall function value))
obj)))
(defmethod consume-front ((obj expression))
(funcall obj))
(defmethod peek-front ((obj expression))
(bind (((:slots %closure %construct-function %arguments-closure) obj)
(fn (apply %construct-function (funcall %arguments-closure))))
(funcall fn)))
(defmethod reset! ((obj expression))
(bind (((:slots %construct-function %arguments %closure %arguments-closure) obj)
((:values function arguments-closure) (apply %construct-function %arguments)))
(setf %closure function
%arguments-closure arguments-closure)
(c2mop:set-funcallable-instance-function obj (lambda () (funcall function))))
obj)
(defmethod drop-front ((obj expression) count)
(check-type count non-negative-fixnum)
(iterate
(with function = (access-closure obj))
(repeat count)
(for i from 0)
(for (values value more) = (funcall function))
(while more)
(finally (return i))))