-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathe2_states.metta
99 lines (85 loc) · 3.31 KB
/
e2_states.metta
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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; State atoms
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; `new-state` creates a new state atom wrapping the initial value (A B).
; Then it binds this state atom to the token `&state-token`,
; which is replaced by the corresponding atom at parse-time.
!(bind! &state-token (new-state (A B)))
; &state-token is replaced by the state atom in the code below its creation
; we wrap it into a function to show that it's not the token that changes, but
; the content of the state atom
(= (get-token) &state-token)
; `new-state $x` creates a `(State $x)` structure,
; and `get-token` will show its content
!(assertEqual
(get-state (get-token))
(A B))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; States can be equal even if they are wrapped into different state atoms
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!(assertEqual
(get-token)
(new-state (A B)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; State atoms are of StateMonad type
; These are inferred types based on new-state and change-state! signatures
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!(assertEqual
(get-type (new-state 2))
(StateMonad Number))
!(assertEqual
(get-type (change-state! (new-state "S") "V"))
(StateMonad String))
; These are the types of State grounded atom
!(assertEqual
(let $v (new-state 1) (get-type $v))
(StateMonad Number))
; atm, meta-types for states of non-grounded types are used
!(assertEqual
(get-type &state-token)
(StateMonad Expression))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; State atoms have a defined type based on initial state
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; &state-token was initialized with state of type (A B), so
; it cannot be changed to int
;!(rtrace!
!(assertEqual
(change-state! &state-token 1)
(Error 1 BadType))
;)
; the new state here is int, so it cannot be changed to string
!(assertEqual
(change-state! (new-state 1) "S")
(Error "S" BadType))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Changing the content of the state atom
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; nop is used to ignore the result and return unit
; as expected by unit tests
!(nop (change-state! &state-token (C D)))
; The same state atom has different content now
!(assertEqual
(get-state (get-token))
(C D))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MeTTa provides proper encapsulated state manipulation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; scoping doesn't conflict between let bound variables and state atom types.
!(assertEqual
(let $x (new-state 1)
(change-state! $x (+ (get-state $x) 1)))
(new-state 2))
; Checking that there is no conflict between variable names in
; let-expression and type definition of new-state
!(assertEqual
(let $tnso (new-state 1) $tnso)
(new-state 1))
; FIXME: doesn't work as for 25 May 2023
; !(get-state (let $x (new-state 1) $x))