Factor out.
Chris Pressey
11 months ago
0 | module Language.ZOWIE.Machine where | |
1 | ||
2 | import Language.ZOWIE.Registers | |
3 | import Language.ZOWIE.State | |
4 | ||
5 | ||
6 | run s = s |
0 | module Language.ZOWIE.Registers where | |
1 | ||
2 | import Language.ZOWIE.State | |
3 | ||
4 | data Register = TtyRegister | |
5 | | BeginTransactionRegister | |
6 | | CommitRegister | |
7 | | CommitAndRepeatRegister | |
8 | | AdditionRegister | |
9 | | SubtractionRegister | |
10 | | MultiplicationRegister | |
11 | | NegationRegister | |
12 | | RegularRegister Addr | |
13 | ||
14 | ||
15 | mapRegister 0 = TtyRegister | |
16 | mapRegister 1 = BeginTransactionRegister | |
17 | mapRegister 2 = CommitRegister | |
18 | mapRegister 3 = CommitAndRepeatRegister | |
19 | mapRegister 4 = AdditionRegister | |
20 | mapRegister 5 = SubtractionRegister | |
21 | mapRegister 6 = MultiplicationRegister | |
22 | mapRegister 7 = NegationRegister | |
23 | mapRegister x = RegularRegister x | |
24 | ||
25 | readAddr :: State -> Addr -> IO Value | |
26 | readAddr state@State{ mem=mem } addr = | |
27 | case mapRegister addr of | |
28 | TtyRegister -> do | |
29 | i <- readLn | |
30 | return i | |
31 | BeginTransactionRegister -> return 1 | |
32 | CommitRegister -> return 2 | |
33 | CommitAndRepeatRegister -> return 3 | |
34 | AdditionRegister -> return 4 | |
35 | SubtractionRegister -> return 5 | |
36 | MultiplicationRegister -> return 6 | |
37 | NegationRegister -> return 7 | |
38 | RegularRegister x -> return (readMem mem x) | |
39 | ||
40 | writeAddr :: State -> Addr -> Value -> IO State | |
41 | writeAddr state@State{ mem=mem } addr payload = | |
42 | case mapRegister addr of | |
43 | TtyRegister -> do | |
44 | print payload | |
45 | return state | |
46 | BeginTransactionRegister -> | |
47 | return $ beginTransaction state | |
48 | CommitRegister -> | |
49 | return $ if payload > 0 then commit state else rollback state | |
50 | CommitAndRepeatRegister -> | |
51 | return $ if payload > 0 then commitAndRepeat state else commit state | |
52 | AdditionRegister -> | |
53 | return state{ mem=(writeMem mem 8 ((readMem mem 8) + payload)) } | |
54 | SubtractionRegister -> | |
55 | return state{ mem=(writeMem mem 8 ((readMem mem 8) - payload)) } | |
56 | MultiplicationRegister -> | |
57 | return state{ mem=(writeMem mem 8 ((readMem mem 8) * payload)) } | |
58 | NegationRegister -> | |
59 | return state{ mem=(writeMem mem 8 (if payload == 0 then 1 else 0)) } | |
60 | RegularRegister x -> | |
61 | return state{ mem=(writeMem mem x payload) } |
0 | module Language.ZOWIE.State where | |
1 | ||
2 | import qualified Data.Map.Strict as Map | |
3 | ||
4 | ||
5 | type Addr = Integer | |
6 | type Value = Integer | |
7 | ||
8 | type Memory = Map.Map Addr Value | |
9 | ||
10 | data Instruction = Immediate Addr Value | |
11 | | Direct Addr Addr | |
12 | | Indirect Addr Addr Value | |
13 | deriving (Show, Ord, Eq) | |
14 | ||
15 | data State = State { | |
16 | pc :: Addr, | |
17 | mem :: Memory, | |
18 | prog :: [Instruction], | |
19 | saved :: Maybe State | |
20 | } deriving (Show, Ord, Eq) | |
21 | ||
22 | ||
23 | readMem mem addr = Map.findWithDefault 0 addr mem | |
24 | writeMem mem addr value = Map.insert addr value mem | |
25 | ||
26 | ||
27 | beginTransaction :: State -> State | |
28 | beginTransaction state@State{} = | |
29 | state{ saved=(Just state) } | |
30 | ||
31 | rollback :: State -> State | |
32 | rollback state@State{ pc=pc, saved=(Just previous) } = | |
33 | previous{ pc=pc } | |
34 | ||
35 | commit :: State -> State | |
36 | commit state@State{ saved=(Just previous) } = | |
37 | state{ saved=(saved previous) } | |
38 | ||
39 | commitAndRepeat :: State -> State | |
40 | commitAndRepeat state@State{ saved=(Just previous) } = | |
41 | state{ pc=((pc previous) - 1) } |
0 | module Language.ZOWIE where | |
1 | ||
2 | import qualified Data.Map.Strict as Map | |
3 | ||
4 | ||
5 | type Addr = Integer | |
6 | type Value = Integer | |
7 | type Memory = Map.Map Addr Value | |
8 | ||
9 | readMem mem addr = Map.findWithDefault 0 addr mem | |
10 | writeMem mem addr value = Map.insert addr value mem | |
11 | ||
12 | data Instruction = Immediate Addr Value | |
13 | | Direct Addr Addr | |
14 | | Indirect Addr Addr Value | |
15 | deriving (Show, Ord, Eq) | |
16 | ||
17 | data State = State { | |
18 | pc :: Addr, | |
19 | mem :: Memory, | |
20 | prog :: [Instruction], | |
21 | saved :: Maybe State | |
22 | } deriving (Show, Ord, Eq) | |
23 | ||
24 | data Register = TtyRegister | |
25 | | BeginTransactionRegister | |
26 | | CommitRegister | |
27 | | CommitAndRepeatRegister | |
28 | | AdditionRegister | |
29 | | SubtractionRegister | |
30 | | MultiplicationRegister | |
31 | | NegationRegister | |
32 | | RegularRegister Addr | |
33 | ||
34 | ||
35 | mapRegister 0 = TtyRegister | |
36 | mapRegister 1 = BeginTransactionRegister | |
37 | mapRegister 2 = CommitRegister | |
38 | mapRegister 3 = CommitAndRepeatRegister | |
39 | mapRegister 4 = AdditionRegister | |
40 | mapRegister 5 = SubtractionRegister | |
41 | mapRegister 6 = MultiplicationRegister | |
42 | mapRegister 7 = NegationRegister | |
43 | mapRegister x = RegularRegister x | |
44 | ||
45 | ||
46 | readAddr :: State -> Addr -> IO Value | |
47 | readAddr state@State{ mem=mem } addr = | |
48 | case mapRegister addr of | |
49 | TtyRegister -> do | |
50 | i <- readLn | |
51 | return i | |
52 | BeginTransactionRegister -> return 1 | |
53 | CommitRegister -> return 2 | |
54 | CommitAndRepeatRegister -> return 3 | |
55 | AdditionRegister -> return 4 | |
56 | SubtractionRegister -> return 5 | |
57 | MultiplicationRegister -> return 6 | |
58 | NegationRegister -> return 7 | |
59 | RegularRegister x -> return (readMem mem x) | |
60 | ||
61 | ||
62 | writeAddr :: State -> Addr -> Value -> IO State | |
63 | writeAddr state@State{ mem=mem } addr payload = | |
64 | case mapRegister addr of | |
65 | TtyRegister -> do | |
66 | print payload | |
67 | return state | |
68 | BeginTransactionRegister -> | |
69 | return $ beginTransaction state | |
70 | CommitRegister -> | |
71 | return $ if payload > 0 then commit state else rollback state | |
72 | CommitAndRepeatRegister -> | |
73 | return $ if payload > 0 then commitAndRepeat state else commit state | |
74 | AdditionRegister -> | |
75 | return state{ mem=(writeMem mem 8 ((readMem mem 8) + payload)) } | |
76 | SubtractionRegister -> | |
77 | return state{ mem=(writeMem mem 8 ((readMem mem 8) - payload)) } | |
78 | MultiplicationRegister -> | |
79 | return state{ mem=(writeMem mem 8 ((readMem mem 8) * payload)) } | |
80 | NegationRegister -> | |
81 | return state{ mem=(writeMem mem 8 (if payload == 0 then 1 else 0)) } | |
82 | RegularRegister x -> | |
83 | return state{ mem=(writeMem mem x payload) } | |
84 | ||
85 | ||
86 | beginTransaction :: State -> State | |
87 | beginTransaction state@State{} = | |
88 | state{ saved=(Just state) } | |
89 | ||
90 | ||
91 | rollback :: State -> State | |
92 | rollback state@State{ pc=pc, saved=(Just previous) } = | |
93 | previous{ pc=pc } | |
94 | ||
95 | ||
96 | commit :: State -> State | |
97 | commit state@State{ saved=(Just previous) } = | |
98 | state{ saved=(saved previous) } | |
99 | ||
100 | ||
101 | commitAndRepeat :: State -> State | |
102 | commitAndRepeat state@State{ saved=(Just previous) } = | |
103 | state{ pc=((pc previous) - 1) } | |
104 | ||
105 | ||
106 | run s = s |
3 | 3 | import System.Exit |
4 | 4 | import System.IO |
5 | 5 | |
6 | import Language.ZOWIE | |
6 | import qualified Language.ZOWIE.Machine as Machine | |
7 | 7 | |
8 | 8 | |
9 | 9 | main = do |
11 | 11 | case args of |
12 | 12 | ["run", fileName] -> do |
13 | 13 | text <- readFile fileName |
14 | putStrLn $ show $ reverse $ run text | |
14 | putStrLn $ show $ reverse $ Machine.run text | |
15 | 15 | return () |
16 | 16 | _ -> do |
17 | 17 | abortWith "Usage: zowie run <carriage-program-text-filename>" |