forked from dharmatech/clos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
user.ss
111 lines (95 loc) · 3.28 KB
/
user.ss
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
(library (clos user)
(export
;; classes
<top>
<object>
;; procedures
slot-ref
slot-set!
get-arg
print-object-with-slots
initialize-direct-slots
;; base level generics
make
initialize
print-object
;; syntax
define-class
define-generic
define-method
)
;; mosh. We need minimum import for serialize library
(import (only (rnrs) define-syntax syntax-rules syntax-case define ...
lambda call-with-values datum->syntax quote cons values
reverse list unsyntax unsyntax-splicing if null? apply
error car cdr not syntax let with-syntax quasisyntax)
(only (clos core) <class> print-object initialize make
initialize-direct-slots print-object-with-slots
get-arg slot-set! slot-ref <object> <top> add-method
<method> <generic>))
(define-syntax define-class
(syntax-rules ()
((define-class ?name () ?slot-def ...)
(define-class ?name (<object>) ?slot-def ...))
((define-class ?name (?super ...) ?slot-def ...)
(define ?name
(make <class>
'definition-name '?name
'direct-supers (list ?super ...)
'direct-slots '(?slot-def ...))))))
(define-syntax define-generic
(syntax-rules ()
((define-generic ?name)
(define ?name
(make <generic>
'definition-name '?name)))))
(define-syntax define-method
(lambda (x)
(define (analyse args)
(let loop ((args args) (qargs '()) (types '()))
(syntax-case args ()
(((?qarg ?type) . ?args)
(loop #'?args (cons #'?qarg qargs) (cons #'?type types)))
(?tail
(values (reverse qargs) (reverse types) #'?tail)))))
(define (build kw qualifier generic qargs types tail body)
(let ((call-next-method (datum->syntax kw 'call-next-method))
(next-method? (datum->syntax kw 'next-method?)))
(with-syntax (((?arg ... . ?rest) tail))
(let ((rest-args (syntax-case #'?rest ()
(() #''())
(_ #'?rest))))
#`(define no-op
(add-method #,generic
(make <method>
'specializers (list #,@types)
'qualifier '#,qualifier
'procedure
(lambda (%generic %next-methods #,@qargs ?arg ... . ?rest)
(let ((#,call-next-method
(lambda ()
(if (null? %next-methods)
(apply error
'apply
"no next method"
%generic
#,@qargs ?arg ... #,rest-args)
(apply (car %next-methods)
%generic
(cdr %next-methods)
#,@qargs ?arg ... #,rest-args))))
(next-method?
(not (null? %next-methods))))
. #,body)))))))))
(syntax-case x (quote)
((?kw '?qualifier ?generic ?args . ?body)
(call-with-values
(lambda ()
(analyse #'?args))
(lambda (qargs types tail)
(build #'?kw #'?qualifier #'?generic qargs types tail #'?body))))
((?kw ?generic '?qualifier ?args . ?body)
#'(?kw '?qualifier ?generic ?args . ?body))
((?kw ?generic ?args . ?body)
#'(?kw 'primary ?generic ?args . ?body)))))
)