Skip to content

Commit a592553

Browse files
committed
Add implementation of digital circuit
1 parent c41dc39 commit a592553

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

chapter3/digital_circuit.rkt

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#lang racket
2+
3+
;;; Helper procedure to call all procedures in a list
4+
(define (call-each procedures)
5+
(if (null? procedures)
6+
'done
7+
(begin ((car procedures))
8+
(call-each (cdr procedures)))))
9+
10+
(define (make-wire)
11+
(let ((signal-value 0)
12+
(action-procedures '()))
13+
(define (set-my-signal! new-value)
14+
(if (not (= signal-value new-value))
15+
(begin (set! signal-value new-value)
16+
(call-each action-procedures))
17+
'done))
18+
19+
(define (accept-action-procedure! proc)
20+
(set! action-procedures (cons proc action-procedures))
21+
;; Call the procedure immediately
22+
(proc))
23+
24+
(define (dispatch m)
25+
(cond ((eq? m 'get-signal) signal-value)
26+
((eq? m 'set-signal!) set-my-signal!)
27+
((eq? m 'add-action!) accept-action-procedure!)
28+
(else (error "Unknown operation -- WIRE" m))))
29+
dispatch)
30+
)
31+
32+
(define (get-signal wire)
33+
(wire 'get-signal))
34+
35+
(define (set-signal! wire new-value)
36+
((wire 'set-signal!) new-value))
37+
38+
(define (add-action! wire action-proc)
39+
((wire 'add-action!) action-proc))
40+
41+
(module+ test
42+
(require rackunit)
43+
44+
(test-case "Test for make-wire"
45+
(define a (make-wire))
46+
(define b (make-wire))
47+
(check-eq? (get-signal a) 0)
48+
(set-signal! a 1)
49+
(check-eq? (get-signal a) 1)
50+
)
51+
(test-case "Test for add-action!"
52+
(define w (make-wire))
53+
(define counter 0)
54+
(define last-signal #f)
55+
56+
; Add an action that increments counter and records the signal
57+
(add-action! w (lambda ()
58+
(set! counter (+ counter 1))
59+
(set! last-signal (get-signal w))))
60+
61+
; The action should be called immediately when added
62+
(check-eq? counter 1)
63+
(check-eq? last-signal 0)
64+
65+
; Change the signal - action should be called again
66+
(set-signal! w 1)
67+
(check-eq? counter 2)
68+
(check-eq? last-signal 1)
69+
70+
; Change signal back - action should be called again
71+
(set-signal! w 0)
72+
(check-eq? counter 3)
73+
(check-eq? last-signal 0)
74+
75+
; Setting same signal should NOT call action
76+
(set-signal! w 0)
77+
(check-eq? counter 3) ; Should remain 3
78+
(check-eq? last-signal 0)
79+
)
80+
)

0 commit comments

Comments
 (0)