File: bank-example.oak

package info (click to toggle)
oaklisp 1.3.7-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 5,776 kB
  • sloc: ansic: 4,014; makefile: 149
file content (187 lines) | stat: -rw-r--r-- 6,482 bytes parent folder | download | duplicates (5)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
;; FILE		"bank-example.oak"
;; IMPLEMNETS	Bank account example from YASOS article
;; AUTHOR	Ken Dickey
;; DATE		5 aUGUST 2004


;; (define-predicate foo?)
;;-> (define-instance foo? operation)
;;   (add-method (foo? (object) self) #f)

(define-local-syntax (define-predicate name)
  `(block
    (define-instance ,name operation)
    (add-method (,name (object) self) #f)))

;; (add-predicate-true foo? type)
;;-> (add-method (foo? (type) self) #t)

(define-local-syntax (add-predicate-true name type)
  `(add-method (,name (,type) self) #t))

;; (define-type name slots supers)
;; -> (define-instance name TYPE slots (list super...))

(define-local-syntax (define-object-type name slots . supers)
  `(define-instance ,name type ',slots (list ,@supers)))

(define-local-syntax (define-operation name)
  `(define-instance ,name operation))

(define-local-syntax (define-settable-operation name)
  `(define-instance ,name settable-operation))

;; @@DEBUG
;; (define trace-expansion #t)

;; Test 'em out

;; <PERSON>

(define-predicate person?)

(define-object-type <person> (name age SSN password) object)

(add-predicate-true person? <person>)

(add-method (initialize (<person> name age SSN password)
                        self the-name the-age the-ssn the-password)
            (set! name the-name)
            (set! age  the-age)
            (set! SSN  the-ssn)
            (set! password the-password)
            self)


(define-operation name)
(define-settable-operation age)
(define-operation SSN)
(define-operation bad-password)
(define-operation change-password)

(add-method (name (<person> name) self) name)
(add-method (age  (<person> age)  self) age)
(add-method ((setter age) (<person> age)  self new-age)
            (set! age new-age))
(add-method (SSN (<person> SSN password) self a-password)
            (if (equal? password a-password)
                SSN
                (bad-password self a-password)))

(add-method (bad-password (<person>) self bogus-password)
            (let ( (message
                    (format #f
                            "bad password \"~a\""
                            bogus-password))
                 )
              (format #t "~%~a" message)
              message))

(add-method (change-password (<person> password) self old-passwd new-passwd)
            (if (equal? old-passwd password)
                (block (set! password new-passwd) self)
                (bad-password self old-passwd)))


;; <BANK-ACCOUNT-TRANSACTION-HISTORY>
;; Just a reverse list of balances (i.e. newest 1st, oldest last)

(define-object-type <bank-account-transaction-history> (reverse-history) object)

(add-method (initialize (<bank-account-transaction-history> reverse-history)
                        self initial-balance)
            (set! reverse-history (list initial-balance))
            self)

(define-instance history operation)
(define-instance add     operation)
(add-method (history (<bank-account-transaction-history> reverse-history) self)
            (reverse reverse-history))

(add-method (add (<bank-account-transaction-history> reverse-history) self new-balance)
            (set! reverse-history (cons new-balance reverse-history))
            new-balance)


;; <BANK-ACCOUNT>

(define-predicate bank-account?)

(define-object-type <bank-account> (master-password p-i-n balance)
                                 <person> <bank-account-transaction-history>)

(add-predicate-true bank-account? <bank-account>)

(add-method (initialize (<bank-account> master-password p-i-n balance)
                        self master-passwd initial-balance name age SSN PIN)
            (set! master-password master-passwd)
            (set! p-i-n           PIN)
            (set! balance         initial-balance)
            (^super <bank-account-transaction-history> initialize self initial-balance)
            (^super <person> initialize self name age SSN p-i-n)
            self)


(define-operation current-balance)
;;(define-operation add      operation)  @@@ defined above
(define-operation withdraw)
(define-settable-operation PIN)

(add-method (current-balance (<bank-account> balance  p-i-n master-password) self passwd)
            (if (or (equal? passwd p-i-n)
                    (equal? passwd master-password))
                balance
                (bad-password self passwd)))

(add-method (pin (<bank-account> master-password p-i-n) self passwd)
            (if (equal? passwd master-password)
                p-i-n
                (bad-password self passwd)))

(add-method ((setter pin) (<bank-account> master-password p-i-n) self passwd new-pin)
            (if (equal? passwd master-password)
                (block
                 (^super <person> change-password self p-i-n new-pin)
                 (set! p-i-n new-pin)
                 self)
                (bad-password self passwd)))

(add-method (change-password (<bank-account> master-password p-i-n)
                             self old-passwd new-passwd)
            (if (equal? old-passwd p-i-n)
                ((setter pin) self master-password new-passwd)
                (bad-password self old-passwd)))

(add-method (bad-password (<bank-account>) self bogus-pssword)
            (format #t "~%!!! CALL THE POLICE !!!")
            (error "!!! CALL THE POLICE !!!"))

(add-method (history (<bank-account> master-password p-i-n) self passwd)
            (if (or (equal? passwd p-i-n)
                    (equal? passwd master-password))
                (^super <bank-account-transaction-history> self history)
                (bad-password self passwd)))

(add-method (add (<bank-account> balance) self amount)
            ;; dumb checks elided (e.g. amount > 0)
            (set! balance (+ balance amount))
            (^super <bank-account-transaction-history> add self balance)
            (format #t "~%new balance is ~a" balance)
            self)

(add-method (withdraw (<bank-account> balance p-i-n) self amount passwd)
            (cond
             ((not (equal? passwd p-i-n))
              (bad-password self passwd))
             ((> amount balance)
              (format #t "~%Error: can't withdraw more than you have!"))
             (else
              (set! balance (- balance amount))
              (^super <bank-account-transaction-history> add self balance)
              (format #t "~%new balance is ~a" balance))))

(add-method (SSN (<bank-account>) self passwd)
            (^super <person> SSN self passwd))


;; --- E O F --- ;;