-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInterp.hs
More file actions
179 lines (138 loc) · 5.59 KB
/
Interp.hs
File metadata and controls
179 lines (138 loc) · 5.59 KB
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
module Interp (Block(Function, name, args, sents, rets), Sentence(Return, Relation), Expr(Atom, Operation, Call, Pattern), Atom(Identifier, Literal), Literal(Nat, Real), DependencyType(Always, Partly), Dependency, leftHand, rightHand, interpret) where
import Data.List
import Data.Maybe
import Data.Graph.Inductive.Graph
import Data.Graph.Inductive.Tree
import Control.Applicative (pure, (<$>), (<*>), (<*), (*>))
import Control.Monad
import Control.Monad.Error
data Block = Function {
name :: String,
args :: [Expr],
sents :: [Sentence],
rets :: [Expr]
}
deriving Show
data Sentence = Return Expr
| Relation String Expr Expr
deriving Eq
data Expr = Atom Atom
| Operation String Expr Expr
| Call String [Expr]
| Pattern [(Expr, Sentence)]
deriving Eq
data Atom = Identifier String | Literal Literal
deriving Eq
data Literal = Nat Int | Real Double
deriving Eq
data Type = IntType | RealType
data Connection a = Unidir a | Bidir a
deriving (Eq, Show)
data DependencyType = Always | Partly Sentence
deriving (Eq, Show)
type Dependency = (Expr, DependencyType)
instance Show Sentence where
show (Return x) = foldl1 (++) ["return ", show x]
show (Relation r x y) = foldl1 (++) [show x, " ", r, " ", show y]
instance Show Expr where
show (Atom p) = show p
show (Operation o x y) = foldl1 (++) ["(", show x, " ", o, " ", show y, ")"]
show (Call f x) = foldl1 (++) [f, "(", intercalate ", " (map show x), ")"]
show (Pattern a) = foldl1 (++) $ intercalate [", "] $ map (\(e, s) -> [show e, " (", show s, ")"]) a
instance Show Atom where
show (Identifier s) = s
show (Literal l) = show l
instance Show Literal where
show (Nat n) = show n
show (Real r) = show r
(?) :: (Error e) => Maybe a -> String -> Either e a
(Just x) ? _ = Right x
Nothing ? er = throwError $ strMsg er
leftHand :: Sentence -> Expr
leftHand (Relation _ l _) = l
rightHand :: Sentence -> Expr
rightHand (Relation _ _ r) = r
interpret :: Block -> Either String (Gr Sentence Dependency)
interpret f = dependencyGraph f
-- dependency analyzer --
dependencyGraph :: Block -> Either String (Gr Sentence Dependency)
dependencyGraph (Function _ a s r) = constrDepGraph a s (mkGraph nodes []) init
where
nodes = zip [0..] $ map Return r
init = zip [0..] $ map (\x -> (x, Always)) r
constrDepGraph :: [Expr] -> [Sentence] -> Gr Sentence Dependency -> [(Node, Dependency)] -> Either String (Gr Sentence Dependency)
constrDepGraph _ _ gr [] = Right gr
constrDepGraph arg st gr xs
| elem x arg = constrDepGraph arg st gr (tail xs)
| isJust def = constrDepGraph arg st (insEdge (from, fst $ fromJust def, (x, dep)) gr) (tail xs)
| otherwise = do
eq <- find (\s -> any (== Bidir x) $ getVarSent s) st ? ("`" ++ show x ++ "` not defined")
expl <- solve x eq
constrDepGraph arg (delete eq st)
(insEdge (from, curr, (x, dep))
$ insNode (curr, expl) gr)
(tail xs ++ (zip (repeat curr) $ (getDep . rightHand) expl))
where
(from, (x, dep)) = head xs
curr = head $ newNodes 1 gr
def = find (\(n, l) -> isRel l && leftHand l == x) $ labNodes gr
isRel (Relation _ _ _) = True
isRel _ = False
undir (Bidir a) = a
undir (Unidir a) = a
getDepSent :: Sentence -> [Dependency]
getDepSent (Relation _ x y) = getDep x ++ getDep y
getDepSent (Return x) = getDep x
getDep :: Expr -> [Dependency]
getDep (Operation _ x y) = getDep x ++ getDep y
getDep (Call _ a) = concatMap getDep a
getDep (Pattern a) = concatMap (getDepSent . snd) a ++ concatMap (\(x, c) -> map (cond c) (getDep x)) a
where
cond s (x, _) = (x, Partly s)
getDep x | isIdent x = [(x, Always)]
| otherwise = []
direct :: Connection a -> Connection a
direct (Bidir x) = Unidir x
direct x = x
getVarSent :: Sentence -> [Connection Expr]
getVarSent (Relation "=" x y) = getVar x ++ getVar y
getVarSent (Relation _ x y) = map direct $ getVar x ++ getVar y
getVarSent (Return x) = getVar x
getVar :: Expr -> [Connection Expr]
getVar (Operation _ x y) = getVar x ++ getVar y
getVar (Call _ a) = map direct $ concatMap getVar a
getVar (Pattern a) = map direct $ concatMap (\(x, c) -> getVar x ++ getVarSent c) a
getVar x | isIdent x = [Bidir x]
| otherwise = []
isIdent :: Expr -> Bool
isIdent (Atom (Identifier _)) = True
isIdent _ = False
-- equation solver --
solve :: Expr -> Sentence -> Either String Sentence
solve x (Relation "=" y z) =
Relation "=" x <$> xor (solveExpr x y z) (solveExpr x z y)
solve _ _ = throwError $ noMsg
xor :: (Error e) => Either e b -> Either e b -> Either e b
xor (Right x) (Left _) = Right x
xor (Left _) (Right x) = Right x
xor _ _ = throwError $ strMsg "solving failed"
solveExpr :: Expr -> Expr -> Expr -> Either String Expr
solveExpr x y z | z == x = Right y
solveExpr x y (Atom a) = throwError noMsg
solveExpr x y (Operation o p q) =
xor (solveExpr x (invLeft o p y) q)
(solveExpr x (invRight o q y) p)
solveExpr x y _ = throwError noMsg
invLeft :: String -> Expr -> Expr -> Expr
invLeft "+" p y = Operation "-" y p
invLeft "-" p y = Operation "-" p y
invLeft "*" p y = Operation "/" y p
invLeft "/" p y = Operation "/" p y
invRight :: String -> Expr -> Expr -> Expr
invRight o p y = Operation i y p
where
i = case o of
"+" -> "-"
"-" -> "+"
"*" -> "/"
"/" -> "*"