|
1 | | --- Copyright (c) 2020 Vorotynsky Maxim |
| 1 | +-- Copyright (c) 2020 - 2021 Vorotynsky Maxim |
| 2 | + |
| 3 | +{-# LANGUAGE DeriveTraversable #-} |
| 4 | +{-# LANGUAGE RankNTypes #-} |
2 | 5 |
|
3 | 6 | module Kroha.Ast where |
4 | 7 |
|
| 8 | +import Control.Comonad |
5 | 9 | import Data.Tree |
6 | 10 | import Data.List (mapAccumR) |
| 11 | +import Control.Monad.Zip (mzipWith) |
7 | 12 |
|
8 | 13 | type VariableName = String |
9 | 14 | type RegisterName = String |
@@ -35,65 +40,115 @@ data LocalVariable |
35 | 40 | deriving (Show, Eq) |
36 | 41 |
|
37 | 42 | data Comparator |
38 | | - = Equals | NotEquals |
39 | | - | Greater | Less |
| 43 | + = Equals | NotEquals |
| 44 | + | Greater | Less |
40 | 45 | deriving (Show, Eq) |
41 | 46 |
|
42 | 47 | newtype Condition = Condition (RValue, Comparator, RValue) |
43 | 48 | deriving (Show, Eq) |
44 | 49 |
|
45 | | -data FrameElement |
46 | | - = Instructions [FrameElement] |
47 | | - | VariableDeclaration LocalVariable |
48 | | - | If Label Condition FrameElement FrameElement |
49 | | - | Loop Label FrameElement |
50 | | - | Break Label |
51 | | - | Call Label [RValue] |
52 | | - | Assignment LValue RValue |
53 | | - | Inline InlinedCode |
54 | | - deriving (Show, Eq) |
55 | | - |
56 | | - |
57 | | -data Declaration |
58 | | - = Frame Label FrameElement |
59 | | - | GlobalVariable VariableName TypeName Literal |
60 | | - | ConstantVariable VariableName TypeName Literal |
61 | | - | ManualFrame Label InlinedCode |
62 | | - | ManualVariable VariableName TypeName InlinedCode |
63 | | - deriving (Show, Eq) |
64 | | - |
65 | | -newtype Program = Program [Declaration] |
66 | | - deriving (Show, Eq) |
67 | | - |
68 | | -type Selector a = FrameElement -> a |
69 | | - |
70 | | -childs :: FrameElement -> [FrameElement] |
71 | | -childs (Instructions xs) = xs |
72 | | -childs (VariableDeclaration x) = [] |
73 | | -childs (If _ _ b e) = [b, e] |
74 | | -childs (Loop _ b) = [b] |
75 | | -childs (Break _) = [] |
76 | | -childs (Call _ _) = [] |
77 | | -childs (Assignment _ _) = [] |
78 | | -childs (Inline _) = [] |
79 | | - |
80 | | -selector :: Selector a -> FrameElement -> Tree a |
| 50 | +data FrameElement d |
| 51 | + = Instructions [FrameElement d] d |
| 52 | + | VariableDeclaration LocalVariable d |
| 53 | + | If Label Condition (FrameElement d) (FrameElement d) d |
| 54 | + | Loop Label (FrameElement d) d |
| 55 | + | Break Label d |
| 56 | + | Call Label [RValue] d |
| 57 | + | Assignment LValue RValue d |
| 58 | + | Inline InlinedCode d |
| 59 | + deriving (Show, Eq, Functor, Foldable, Traversable) |
| 60 | + |
| 61 | + |
| 62 | +data Declaration d |
| 63 | + = Frame Label (FrameElement d) d |
| 64 | + | GlobalVariable VariableName TypeName Literal d |
| 65 | + | ConstantVariable VariableName TypeName Literal d |
| 66 | + | ManualFrame Label InlinedCode d |
| 67 | + | ManualVariable VariableName TypeName InlinedCode d |
| 68 | + deriving (Show, Eq, Functor, Foldable, Traversable) |
| 69 | + |
| 70 | +data Program d = Program [Declaration d] d |
| 71 | + deriving (Show, Eq, Functor, Foldable, Traversable) |
| 72 | + |
| 73 | +childs :: FrameElement d -> [FrameElement d] |
| 74 | +childs (Instructions xs _) = xs |
| 75 | +childs (VariableDeclaration x _) = [] |
| 76 | +childs (If _ _ b e _) = [b, e] |
| 77 | +childs (Loop _ b _) = [b] |
| 78 | +childs (Break _ _) = [] |
| 79 | +childs (Call _ _ _) = [] |
| 80 | +childs (Assignment _ _ _) = [] |
| 81 | +childs (Inline _ _) = [] |
| 82 | + |
| 83 | +getDeclData :: Declaration d -> d |
| 84 | +getDeclData (Frame _ _ d) = d |
| 85 | +getDeclData (GlobalVariable _ _ _ d) = d |
| 86 | +getDeclData (ConstantVariable _ _ _ d) = d |
| 87 | +getDeclData (ManualFrame _ _ d) = d |
| 88 | +getDeclData (ManualVariable _ _ _ d) = d |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | +selector :: (FrameElement d -> a) -> FrameElement d -> Tree a |
81 | 93 | selector s = unfoldTree (\e -> (s e, childs e)) |
82 | 94 |
|
83 | | -selectorM :: Monad m => Selector (m a) -> FrameElement -> m (Tree a) |
84 | | -selectorM s = unfoldTreeM (\e -> s e >>= (\x -> return (x, childs e))) |
85 | | - |
86 | | - |
87 | | -selectorProg :: (Declaration -> a) -> Selector a -> Program -> Forest a |
88 | | -selectorProg df sf (Program declarations) = fmap mapper declarations |
89 | | - where mapper d@(Frame _ frame) = Node (df d) [selector sf frame] |
90 | | - mapper declaration = Node (df declaration) [] |
| 95 | +selectorProg :: (Declaration d -> a) -> (FrameElement d -> a) -> Program d -> Forest a |
| 96 | +selectorProg df sf (Program declarations _) = fmap mapper declarations |
| 97 | + where mapper d@(Frame _ frame _) = Node (df d) [selector sf frame] |
| 98 | + mapper declaration = Node (df declaration) [] |
91 | 99 |
|
92 | 100 |
|
93 | 101 | type NodeId = Int |
94 | 102 |
|
95 | | -genId :: Tree a -> Tree NodeId |
96 | | -genId = snd . mapAccumR (\ac b -> (ac + 1, ac)) 0 |
97 | | - |
98 | | -progId :: Program -> Tree NodeId |
99 | | -progId program = genId $ Node () (selectorProg (const ()) (const ()) program) |
| 103 | +genId :: Program d -> Program NodeId |
| 104 | +genId (Program decls _) = Program (snd $ mapAccumR declId 1 decls) 0 |
| 105 | + where genId'' = mapAccumR (\ac b -> (ac + 1, ac)) |
| 106 | + declId begin (Frame l fe _) = let (acc, fe') = genId'' (begin + 1) fe in (acc, Frame l fe' begin) |
| 107 | + declId begin d = (begin + 1, d $> begin) |
| 108 | + |
| 109 | +progId :: Program d -> Tree NodeId |
| 110 | +progId program = Node 0 $ selectorProg getDeclData extract (genId program) |
| 111 | + |
| 112 | +instance Comonad FrameElement where |
| 113 | + duplicate node@(Instructions c _) = Instructions (map duplicate c) node |
| 114 | + duplicate node@(VariableDeclaration v _) = VariableDeclaration v node |
| 115 | + duplicate node@(If l c i e _) = If l c (duplicate i) (duplicate e) node |
| 116 | + duplicate node@(Loop l b _) = Loop l (duplicate b) node |
| 117 | + duplicate node@(Break l _) = Break l node |
| 118 | + duplicate node@(Call l a _) = Call l a node |
| 119 | + duplicate node@(Assignment l r _) = Assignment l r node |
| 120 | + duplicate node@(Inline c _) = Inline c node |
| 121 | + |
| 122 | + extract (Instructions _ d) = d |
| 123 | + extract (VariableDeclaration _ d) = d |
| 124 | + extract (If _ _ _ _ d) = d |
| 125 | + extract (Loop _ _ d) = d |
| 126 | + extract (Break _ d) = d |
| 127 | + extract (Call _ _ d) = d |
| 128 | + extract (Assignment _ _ d) = d |
| 129 | + extract (Inline _ d) = d |
| 130 | + |
| 131 | +tzip :: FrameElement a -> FrameElement b -> FrameElement (a, b) |
| 132 | +tzip (Instructions ca _a) (Instructions cb _b) = Instructions (uncurry tzip <$> zip ca cb) (_a, _b) |
| 133 | +tzip (VariableDeclaration va _a) (VariableDeclaration vb _b) | va == vb = VariableDeclaration va (_a, _b) |
| 134 | +tzip (If la ca ia ea _a) (If lb cb ib eb _b) | (la, ca) == (lb, cb) = If la ca (tzip ia ib) (tzip ea eb) (_a, _b) |
| 135 | +tzip (Loop la ba _a) (Loop lb bb _b) | la == lb = Loop la (tzip ba bb) (_a, _b) |
| 136 | +tzip (Break la _a) (Break lb _b) | la == lb = Break la (_a, _b) |
| 137 | +tzip (Call la aa _a) (Call lb ab _b) | (la, aa) == (lb, ab) = Call la aa (_a, _b) |
| 138 | +tzip (Assignment la ra _a) (Assignment lb rb _b) | (la, ra) == (lb, rb) = Assignment la ra (_a, _b) |
| 139 | +tzip (Inline ca _a) (Inline cb _b) | ca == cb = Inline ca (_a, _b) |
| 140 | +tzip _ _ = error "can't zip different frame elements" |
| 141 | + |
| 142 | +dzip :: Declaration a -> Declaration b -> Declaration (a, b) |
| 143 | +dzip (Frame la fea _a) (Frame lb feb _b) | la == lb = Frame la (tzip fea feb) (_a, _b) |
| 144 | +dzip (GlobalVariable va ta la _a) (GlobalVariable vb tb lb _b) | (va, ta, la) == (vb, tb, lb) = GlobalVariable va ta la (_a, _b) |
| 145 | +dzip (ConstantVariable va ta la _a) (ConstantVariable vb tb lb _b) | (va, ta, la) == (vb, tb, lb) = ConstantVariable va ta la (_a, _b) |
| 146 | +dzip (ManualFrame la ca _a) (ManualFrame lb cb _b) | (la, ca) == (lb, cb) = ManualFrame la ca (_a, _b) |
| 147 | +dzip (ManualVariable va ta ca _a) (ManualVariable vb tb cb _b) | (va, ta, ca) == (vb, tb, cb) = ManualVariable va ta ca (_a, _b) |
| 148 | +dzip _ _ = error "can't zip different declarations" |
| 149 | + |
| 150 | +pzip :: Program a -> Program b -> Program (a, b) |
| 151 | +pzip (Program da _a) (Program db _b) = Program (mzipWith dzip da db) (_a, _b) |
| 152 | + |
| 153 | +pzip3 :: Program a -> Program b -> Program c -> Program (a, b, c) |
| 154 | +pzip3 a b c = fmap (\((a, b), c) -> (a, b, c)) (pzip (pzip a b) c) |
0 commit comments