-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathOMDocImport.hs
402 lines (321 loc) · 14.2 KB
/
OMDocImport.hs
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
{- |
Module : $Header$
Description : OMDoc-to-CASL conversion
Copyright : (c) Ewaryst Schulz, DFKI Bremen 2009
License : GPLv2 or higher, see LICENSE.txt
Maintainer : ewaryst.schulz@dfki.de
Stability : provisional
Portability : portable
CASL implementation of the interface functions omdocToSym, omdocToSen
, addOMadtToTheory, addOmdocToTheory from class Logic. The actual
instantiation can be found in module "CASL.Logic_CASL".
-}
module CASL.OMDocImport
( omdocToSym
, omdocToSen
, addOMadtToTheory
, addOmdocToTheory
) where
import OMDoc.DataTypes
import Common.Id
import Common.Result
import Common.AS_Annotation
import qualified Common.Lib.Rel as Rel
import CASL.AS_Basic_CASL
import CASL.Sign
import CASL.OMDoc
import Control.Monad
import qualified Data.Map as Map
import Data.List
-- * Environment Interface
type Env = SigMapI Symbol
symbolToSort :: Symbol -> SORT
symbolToSort (Symbol n SortAsItemType) = n
symbolToSort s = error $ "symbolToSort: Nonsort encountered: " ++ show s
symbolToOp :: Symbol -> (Id, OpType)
symbolToOp (Symbol n (OpAsItemType ot)) = (n, ot)
symbolToOp s = error $ "symbolToOp: Nonop encountered: " ++ show s
symbolToPred :: Symbol -> (Id, PredType)
symbolToPred (Symbol n (PredAsItemType pt)) = (n, pt)
symbolToPred s = error $ "symbolToPred: Nonpred encountered: " ++ show s
lookupSymbol :: Env -> OMName -> Symbol
lookupSymbol e omn =
Map.findWithDefault
(error $ concat [ "lookupSymbol failed for: "
, show omn, "\nmap: ", show $ sigMapISymbs e])
omn $ sigMapISymbs e
lookupSort :: Env -> OMName -> SORT
lookupSort e = symbolToSort . lookupSymbol e
lookupSortOMS :: String -> Env -> OMElement -> SORT
lookupSortOMS msg = lookupOMS lookupSort $ msg ++ "(SORT)"
lookupPred :: Env -> OMName -> (Id, PredType)
lookupPred e = symbolToPred . lookupSymbol e
lookupPredOMS :: String -> Env -> OMElement -> (Id, PredType)
lookupPredOMS msg = lookupOMS lookupPred $ msg ++ "(PRED)"
lookupOp :: Env -> OMName -> (Id, OpType)
lookupOp e = symbolToOp . lookupSymbol e
lookupOpOMS :: String -> Env -> OMElement -> (Id, OpType)
lookupOpOMS msg = lookupOMS lookupOp $ msg ++ "(Op)"
lookupOMS :: (Env -> OMName -> a) -> String -> Env -> OMElement -> a
lookupOMS f msg e oms@(OMS (cd, omn)) =
if cdIsEmpty cd then f e omn
else error $ concat [ msg, ": lookupOMS: Nonempty cd in const: "
, show oms]
lookupOMS _ msg _ ome =
error $ concat [msg, ": lookupOMS: Nonsymbol: ", show ome]
toOpSymb :: (Id, OpType) -> OP_SYMB
toOpSymb (i, t) = Qual_op_name i (toOP_TYPE t) nullRange
toPredSymb :: (Id, PredType) -> PRED_SYMB
toPredSymb (i, t) = Qual_pred_name i (toPRED_TYPE t) nullRange
-- * TOPLEVEL Interface
-- | A TCSymbols is transformed to a CASL symbol with given name.
omdocToSym :: Env -> TCElement -> String -> Result Symbol
omdocToSym e sym@(TCSymbol _ ctp srole _) n =
case srole of
Typ | ctp == const_sort -> return $ idToSortSymbol $ nameToId n
| otherwise -> fail $ "omdocToSym: No sorttype for " ++ show sym
Obj -> return $
case omdocToType e ctp of
Left ot -> idToOpSymbol (nameToId n) ot
Right pt -> idToPredSymbol (nameToId n) pt
_ -> fail $ concat [ "omdocToSym: only type or object are allowed as"
, " symbol roles, but found: ", show srole ]
omdocToSym _ sym _ = fail $ concat [ "omdocToSym: only TCSymbol is allowed,"
, " but found: ", show sym ]
omdocToSen :: Env -> TCElement -> String
-> Result (Maybe (Named (FORMULA f)))
omdocToSen e (TCSymbol _ t sr _) n =
case nameDecode n of
Just _ ->
return Nothing -- don't translate encoded names here
Nothing ->
let ns = makeNamed n $ omdocToFormula e t
res b = return $ Just $ ns { isAxiom = b }
in case sr of
Axiom -> res True
Theorem -> res False
_ -> return Nothing
omdocToSen _ sym _ = fail $ concat [ "omdocToSen: only TCSymbol is allowed,"
, " but found: ", show sym ]
-- | Sort generation constraints are added as named formulas.
addOMadtToTheory :: Env
-> (Sign f e, [Named (FORMULA f)]) -> [[OmdADT]]
-> Result (Sign f e, [Named (FORMULA f)])
addOMadtToTheory e (sig, nsens) adts = do
sgcs <- mapR (omdocToSortGenConstraint e) adts
return (sig, nsens ++ sgcs)
-- | The subsort relation is recovered from exported sentences.
addOmdocToTheory :: Env -> (Sign f e, [Named (FORMULA f)]) -> [TCElement]
-> Result (Sign f e, [Named (FORMULA f)])
addOmdocToTheory e (sig, nsens) tcs = do
srel <- omdocToSortRel e tcs
return (sig { sortRel = Rel.transClosure srel }, nsens)
-- * Algebraic Data Types
omdocToSortGenConstraint :: Env -> [OmdADT] -> Result (Named (FORMULA f))
omdocToSortGenConstraint e sortdefs = do
-- take the last type as the type of all constraints
let (t, cs) = mapAccumL (const $ mkConstraint e) Generated sortdefs
-- TODO: do we take newSort or origSort?
return $ toSortGenNamed (Sort_gen_ax cs $ t == Free) $ map newSort cs
mkConstraint :: Env -> OmdADT -> (ADTType, Constraint)
mkConstraint e (ADTSortDef nm t constrs) =
let s = lookupSort e $ mkSimpleName nm
l = map (mkConstructor e s) constrs
in (t, Constraint s l s)
mkConstraint _ _ = error "mkConstraint: Malformed ADT expression"
mkConstructor :: Env -> SORT -> OmdADT -> (OP_SYMB, [Int])
mkConstructor e s (ADTConstr nm args) =
let opn = nameToId $ lookupNotation e $ mkSimpleName nm
l = map (mkArg e) args
in (Qual_op_name opn (Op_type Total l s nullRange) nullRange, [0])
{- we have to create the name of this injection because we throw it away
during the export -}
mkConstructor e s (ADTInsort (_, omn)) =
let argsort = lookupSort e omn
opn = mkUniqueInjName argsort s
in (Qual_op_name opn (Op_type Total [argsort] s nullRange) nullRange, [0])
mkConstructor _ _ _ = error "mkConstructor: Malformed ADT expression"
mkArg :: Env -> OmdADT -> SORT
mkArg e (ADTArg oms _) = lookupSortOMS "mkArg" e oms
mkArg _ _ = error "mkArg: Malformed ADT expression"
-- * Subsort Relation
omdocToSortRel :: Env -> [TCElement] -> Result (Rel.Rel SORT)
omdocToSortRel e = foldM (addMaybeToSortRel e) Rel.empty
addMaybeToSortRel :: Env -> Rel.Rel SORT -> TCElement -> Result (Rel.Rel SORT)
addMaybeToSortRel e r (TCSymbol n (OMA [sof, oms1, oms2]) Axiom _) =
case nameDecode n of
Just ("ST", _)
| sof == const_subsortof ->
let s1 = lookupSortOMS "addMaybeToSortRel: s1" e oms1
s2 = lookupSortOMS "addMaybeToSortRel: s2" e oms2
in return $ Rel.insertKeyOrPair s1 s2 r
| otherwise ->
do
warning () ("Use of subsortof in a non ST Statement: " ++ n)
nullRange
return r
_ -> return r
addMaybeToSortRel _ r _ = return r
-- * Types
omdocToType :: Env -> OMElement -> Either OpType PredType
omdocToType e (OMA (c : args)) =
let sorts = map (lookupSortOMS "omdocToType" e) args
opargs = init sorts
oprange = last sorts
res | c == const_predtype = Right $ PredType sorts
| c == const_partialfuntype = Left $ OpType Partial opargs oprange
| c == const_funtype = Left $ OpType Total opargs oprange
| otherwise = error $ "omdocToType: unknown type constructor: "
++ show c
in res
omdocToType e oms@(OMS _)
| oms == const_predtype = Right $ PredType []
| otherwise = Left $ OpType Total [] $ lookupSortOMS "omdocToType" e oms
omdocToType _ ome = error $ "omdocToType: Non-supported element: " ++ show ome
-- * Terms and Formulas
type VarMap = Map.Map VAR SORT
type TermEnv = (Env, VarMap)
mkImplication, mkImplied, mkEquivalence
, mkNegation :: [FORMULA f] -> FORMULA f
mkImplication [x, y] = mkImpl x y
mkImplication _ = error "Malformed implication"
mkImplied [x, y] = mkRel RevImpl x y
mkImplied _ = error "Malformed if"
mkEquivalence [x, y] = mkEqv x y
mkEquivalence _ = error "Malformed equivalence"
mkNegation [x] = mkNeg x
mkNegation _ = error "Malformed negation"
mkDefinedness, mkExistl_equation, mkStrong_equation
:: [TERM f] -> FORMULA f
mkDefinedness [x] = Definedness x nullRange
mkDefinedness _ = error "Malformed definedness"
mkExistl_equation [x, y] = mkExEq x y
mkExistl_equation _ = error "Malformed existl equation"
mkStrong_equation [x, y] = mkStEq x y
mkStrong_equation _ = error "Malformed strong equation"
-- Quantification, Predication and Membership are handled inside omdocToFormula
-- Term construction functions
mkT2 :: (OMElement -> a) -> (OMElement -> b) -> (a -> b -> Range -> TERM f)
-> [OMElement] -> TERM f
mkT2 f g c l = case l of
[x, y] -> c (f x) (g y) nullRange
_ -> error "mkT2: 2 arguments expected"
mkT3 :: (OMElement -> a) -> (OMElement -> b) -> (OMElement -> c)
-> (a -> b -> c -> Range -> TERM f) -> [OMElement] -> TERM f
mkT3 f g h c l = case l of
[x, y, z] -> c (f x) (g y) (h z) nullRange
_ -> error "mkT3: 3 arguments expected"
-- Formula construction functions
mkFF :: TermEnv -> ([FORMULA f] -> FORMULA f) -> [OMElement] -> FORMULA f
mkFF e f l = f $ map (omdocToFormula' e) l
mkTF :: TermEnv -> ([TERM f] -> FORMULA f) -> [OMElement] -> FORMULA f
mkTF e f l = f $ map (omdocToTerm' e) l
getQuantifier :: OMElement -> QUANTIFIER
getQuantifier oms
| oms == const_forall = Universal
| oms == const_exists = Existential
| oms == const_existsunique = Unique_existential
| otherwise = error $ "getQuantifier: unrecognized quantifier " ++ show oms
mkBinder :: TermEnv -> QUANTIFIER -> [OMElement] -> OMElement -> FORMULA f
mkBinder te@(e, _) q vars body =
let (vm', vardecls) = toVarDecls te vars
bd = omdocToFormula' (e, vm') body
in Quantification q vardecls bd nullRange
toVarDecls :: TermEnv -> [OMElement] -> (VarMap, [VAR_DECL])
toVarDecls (e, vm) l =
let f acc x = let (v, s) = toVarDecl e x
acc' = Map.insert v s acc
in (acc', (v, s))
(vm', l') = mapAccumL f vm l
-- group by same sort
l'' = groupBy (\ x y -> snd x == snd y) l'
-- the lists returned by groupBy are never empty, so head will succeed
g vsl = Var_decl (map fst vsl) (snd $ head vsl) nullRange
in (vm', map g l'')
-- in CASL we expect all bound vars to be attributed (typed)
toVarDecl :: Env -> OMElement -> (VAR, SORT)
toVarDecl e (OMATTT (OMV v) (OMAttr ct t))
| ct == const_type = (nameToToken $ name v, lookupSortOMS "toVarDecl" e t)
| otherwise = error $ "toVarDecl: unrecognized attribution " ++ show ct
toVarDecl _ _ = error "toVarDecl: bound variables should be attributed."
-- Toplevel entry point
omdocToFormula :: Env -> OMElement -> FORMULA f
omdocToFormula e = omdocToFormula' (e, Map.empty)
-- Functions with given VarMap
-- omdocToTerm has no toplevel entry point
omdocToTerm' :: TermEnv -> OMElement -> TERM f
omdocToTerm' e@(ie, vm) f =
case f of
OMA (h : args)
| h == const_cast ->
mkT2 (omdocToTerm' e) (lookupSortOMS "omdocToTerm: Cast" ie)
Cast args
| h == const_if ->
mkT3 (omdocToTerm' e) (omdocToFormula' e) (omdocToTerm' e)
Conditional args
-- all other heads mean application
| otherwise ->
let os = toOpSymb $ lookupOpOMS "omdocToTerm" ie h
args' = map (omdocToTerm' e) args
in Application os args' nullRange
OMS _ -> let os = toOpSymb $ lookupOpOMS "omdocToTerm-OMS:" ie f
in Application os [] nullRange
OMV omn -> let var = nameToToken $ name omn
-- lookup the type of the variable in the varmap
s = Map.findWithDefault
(error $ concat [ "omdocToTerm': Variable not in "
, "varmap: ", show var ]) var vm
in Qual_var var s nullRange
OMATTT ome (OMAttr ct t)
| ct == const_type ->
-- same as cast
mkT2 (omdocToTerm' e) (lookupSortOMS "omdocToTerm: Sorted" ie)
Sorted_term [ome, t]
| otherwise -> error $ "omdocToTerm: unrecognized attribution "
++ show ct
_ -> error $ "omdocToTerm: no valid term " ++ show f
omdocToFormula' :: TermEnv -> OMElement -> FORMULA f
omdocToFormula' e@(ie, _) f =
case f of
OMA (h : args)
| h == const_in ->
case args of
[x, s] ->
Membership (omdocToTerm' e x) (lookupSortOMS
"omdocToFormula"
ie s) nullRange
_ -> error "Malformed membership"
| h == const_and ->
mkFF e conjunct args
| h == const_or ->
mkFF e disjunct args
| h == const_implies ->
mkFF e mkImplication args
| h == const_implied ->
mkFF e mkImplied args
| h == const_equivalent ->
mkFF e mkEquivalence args
| h == const_not ->
mkFF e mkNegation args
| h == const_def ->
mkTF e mkDefinedness args
| h == const_eeq ->
mkTF e mkExistl_equation args
| h == const_eq ->
mkTF e mkStrong_equation args
-- all other heads mean predication
| otherwise ->
let ps = toPredSymb $ lookupPredOMS "omdocToFormula" ie h
g l = Predication ps l nullRange in
mkTF e g args
OMBIND binder args body ->
mkBinder e (getQuantifier binder) args body
OMS _ | f == const_true -> trueForm
| f == const_false -> falseForm
-- Propositional Constants (0-ary predicates):
| otherwise ->
Predication (toPredSymb
$ lookupPredOMS
("omdocToFormula: can't handle constant "
++ show f) ie f) [] nullRange
_ -> error $ "omdocToFormula: no valid formula " ++ show f