1
+ import Data.List
2
+
3
+ data Command = Nop | Loop [(Int , Command )]
4
+
5
+ isLoop :: Command -> Bool
6
+ isLoop (Loop _) = True
7
+ isLoop _ = False
8
+
9
+ type Program = ([(Int , Structure )], [(Int , Command )])
10
+
11
+ data Structure = BoundedTape | Register | InfBoundedTapes | Tape
12
+ deriving (Ord , Enum , Eq )
13
+
14
+ reduce :: Structure -> [Structure ]
15
+ reduce Register = [BoundedTape ]
16
+ reduce InfBoundedTapes = [BoundedTape , BoundedTape , BoundedTape , BoundedTape , Register ]
17
+ reduce Tape = [InfBoundedTapes ]
18
+
19
+ freshTapes :: Program -> Int -> [Structure ] -> (Program , [Int ])
20
+ freshTapes p _ [] = (p, [] )
21
+ freshTapes (structs, cmds) oldIdx (s: ss) = (p, oldIdx: is)
22
+ where (p, is) = freshTapes (structs', cmds) idx ss
23
+ structIndexes = sort $ (map fst structs)
24
+ structs' = (oldIdx, s) : (case oldIdx `elem` structIndexes of
25
+ True -> filter ( (/= oldIdx) . fst ) structs
26
+ False -> structs )
27
+ idx = head $ [1 .. ] \\ structIndexes
28
+
29
+ compileSingle :: Structure -> Command -> [Int ] -> [(Int , Command )]
30
+ compileSingle = undefined -- TODO: Specify
31
+
32
+ mapSingle :: Structure -> Int -> Program -> Program
33
+ mapSingle struct idx p@ (structs, cmds) = (structs', cmds')
34
+ where newStructs = reduce struct
35
+ ((structs', _), idxs) = freshTapes p idx newStructs
36
+ cmds' = concat $ map (\ (i, c) ->
37
+ case i == idx of
38
+ True -> compileSingle struct c idxs
39
+ False -> [(i, c)] ) cmds
40
+
41
+ reorderStep :: Program -> Program
42
+ reorderStep (structs, cmds) = (structs, untangledInit ++ ( case restCommands of
43
+ [] -> []
44
+ ((i, Loop l): rs) -> (i, Loop (snd $ reorderStep (structs, l))) : (snd $ reorderStep (structs, rs))
45
+ _ -> [] ) )
46
+ where initCommands = takeWhile (not . isLoop . snd ) cmds
47
+ restCommands = dropWhile (not . isLoop . snd ) cmds
48
+ struct idx = snd $ head $ filter ( (== idx) . fst ) structs
49
+ reorderedInit = sortBy (\ (ix, cmd) (ix', cmd') ->
50
+ case (compare (struct ix) (struct ix'), compare ix ix') of
51
+ (GT , _) -> LT
52
+ (LT , _) -> GT
53
+ (EQ , x) -> x) initCommands
54
+ zippedInit = map ( \ (i,c) -> (i, (struct i), c) ) reorderedInit
55
+ partitionedInit = partitioned' [] zippedInit
56
+ partitioned' acc [] = [acc]
57
+ partitioned' [] (x: xs) = partitioned' [x] xs
58
+ partitioned' (y@ (_, s, _): ys) (x@ (_, s', _): xs) = case s == s' of
59
+ True -> partitioned' (y: ys ++ [x]) xs
60
+ False -> (y: ys) : partitioned' [x] xs
61
+ optimizedInit = concat $ map optimize partitionedInit
62
+ untangledInit = map ( \ (i, _, c) -> (i, c) ) optimizedInit
63
+
64
+ compileStep :: Program -> Program
65
+ compileStep p@ (structs, cmds) = case maxLevelStructs of
66
+ (x: xs) -> mapSingle (snd x) (fst x) p
67
+ [] -> p
68
+ where maxLevelStructs = filter ( (== maxLevel) . snd ) structs
69
+ maxLevelCommands = filter ( (flip elem ) (map fst maxLevelStructs) . fst ) $ cmds
70
+ maxLevel = maximum $ map snd structs
71
+ struct idx = snd $ head $ filter ( (== idx) . fst ) structs
72
+ -- computedInit = map (\(idx, cmd) -> (idx, struct idx, cmd) ) initCommands
73
+
74
+
75
+ optimize :: [(Int , Structure , Command )] -> [(Int , Structure , Command )]
76
+ optimize = id
0 commit comments