-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhelpers.scm
65 lines (59 loc) · 2.32 KB
/
helpers.scm
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
;;; -*- Mode: Scheme; scheme48-package: soosy-helpers -*-
;; '((name class-record) ...)
(define *all-classes* (make-hash-table))
(define (name->class name)
(hash-table-ref/default *all-classes* name #f))
(define (add-class! name class)
(hash-table-set! *all-classes* name class))
(define (false? x) (eq? x #f))
(define (generate-ivar-bindings ->name ->body ivars)
(map (lambda (ivar)
`(,(->name ivar)
,(->body ivar)))
ivars))
;;;
;;; This procedure provides the expansion for the WITH-INSTANCE-VARIABLES macro
;;;
;;; The expansion contains two parts:
;;;
;;; (1) the LET part generates local bindings for each of the ivars using OBJECT-VARIABLE
;;; (2) the LET-SYNTAX part generates 'syntax-rules' macros for SET! and SET-IVAR!
;;; * SET! on an ivar will expand into a warning, otherwise it falls back to the normal SET!
;;; * SET-IVAR! on an ivar will expand into SET-OBJECT-VARIABLE, otherwise it will expand into a warning.
;;;
(define (with-instance-variables* expression rename compare)
(if (< (length expression) 5)
(syntax-error "(with-instance-variables class instance (ivars ...) code)"))
(let ((instance (list-ref expression 2))
(ivars (list-ref expression 3))
(code (drop expression 4))
(%let (rename 'let))
(%let-syntax (rename 'let-syntax))
(%ref (rename 'object-variable))
(%set-ivar! (rename 'set-object-variable!))
(%syntax-rules (rename 'syntax-rules))
(%warn (rename 'warn)))
`(,%let
(,@(generate-ivar-bindings
(lambda (ivar) ivar)
(lambda (ivar) `(,%ref ,instance ',ivar))
ivars))
(,%let-syntax
((set-ivar!
(,%syntax-rules
,ivars
,@(generate-ivar-bindings
(lambda (ivar) `(set-ivar! ,ivar value))
(lambda (ivar) `(,%set-ivar! ,instance ',ivar value))
ivars)
((set-ivar! var value) (,%warn "this is not an ivar" 'var))))
(set!
(,%syntax-rules
,ivars
,@(generate-ivar-bindings
(lambda (ivar) `(set! ,ivar value))
(lambda (ivar)
`(,%warn "this is an ivar, use SET-IVAR! instead" ',ivar))
ivars)
((set! var value) (set! var value)))))
,@code))))