summaryrefslogtreecommitdiff
path: root/src/GF/Devel/Grammar/Construct.hs
blob: 5b4215843353ab3dd679eb59654419e019533d83 (plain)
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
module GF.Devel.Grammar.Construct where

import GF.Devel.Grammar.Grammar
import GF.Infra.Ident

import GF.Data.Operations

import Control.Monad
import Data.Map
import Debug.Trace (trace)

------------------
-- abstractions on Grammar, constructing objects
------------------

-- abstractions on GF

emptyGF :: GF
emptyGF = GF Nothing [] empty empty

type SourceModule = (Ident,Module)

listModules :: GF -> [SourceModule]
listModules = assocs.gfmodules

addModule :: Ident -> Module -> GF -> GF
addModule c m gf = gf {gfmodules = insert c m (gfmodules gf)}

gfModules :: [(Ident,Module)] -> GF
gfModules ms = emptyGF {gfmodules = fromList ms}

-- abstractions on Module

emptyModule :: Module
emptyModule = Module MTGrammar True [] [] [] [] empty empty

isCompleteModule :: Module -> Bool
isCompleteModule = miscomplete

isInterface :: Module -> Bool
isInterface m = case mtype m of
  MTInterface -> True
  MTAbstract -> True
  _ -> False

interfaceName :: Module -> Maybe Ident
interfaceName mo = case mtype mo of
  MTInstance i -> return i
  MTConcrete i -> return i
  _ -> Nothing

listJudgements :: Module -> [(Ident,Judgement)]
listJudgements = assocs . mjments

isInherited :: MInclude -> Ident -> Bool
isInherited mi i = case mi of
  MIExcept is -> notElem i is
  MIOnly is -> elem i is
  _ -> True

-- abstractions on Judgement

isConstructor :: Judgement -> Bool
isConstructor j = jdef j == EData

isLink :: Judgement -> Bool
isLink j = jform j == JLink

-- constructing judgements from parse tree

emptyJudgement :: JudgementForm -> Judgement
emptyJudgement form = Judgement form meta meta meta (identC "#") 0 where
  meta = Meta 0

addJType :: Type -> Judgement -> Judgement
addJType tr ju = ju {jtype = tr}

addJDef :: Term -> Judgement -> Judgement
addJDef tr ju = ju {jdef = tr}

addJPrintname :: Term -> Judgement -> Judgement
addJPrintname tr ju = ju {jprintname = tr}

linkInherited :: Bool -> Ident -> Judgement
linkInherited can mo = (emptyJudgement JLink){
  jlink = mo,
  jdef = if can then EData else Meta 0
  }

absCat :: Context -> Judgement
absCat co = addJType (mkProd co typeType) (emptyJudgement JCat)

absFun :: Type -> Judgement
absFun ty = addJType ty (emptyJudgement JFun)

cncCat :: Type -> Judgement
cncCat ty = addJType ty (emptyJudgement JLincat)

cncFun :: Term -> Judgement
cncFun tr = addJDef tr (emptyJudgement JLin)

resOperType :: Type -> Judgement
resOperType ty = addJType ty (emptyJudgement JOper)

resOperDef :: Term -> Judgement
resOperDef tr = addJDef tr (emptyJudgement JOper)

resOper :: Type -> Term -> Judgement
resOper ty tr = addJDef tr (resOperType ty)

resOverload :: [(Type,Term)] -> Judgement
resOverload tts = resOperDef (Overload tts)

-- param p = ci gi  is encoded as p : ((ci : gi) -> p) -> Type
-- we use EData instead of p to make circularity check easier  
resParam :: Ident -> [(Ident,Context)] -> Judgement
resParam p cos = addJDef (EParam (Con p) cos) (addJType typePType (emptyJudgement JParam))

-- to enable constructor type lookup:
-- create an oper for each constructor p = c g, as c : g -> p = EData
paramConstructors :: Ident -> [(Ident,Context)] -> [(Ident,Judgement)]
paramConstructors p cs = [(c,resOper (mkProd co (Con p)) EData) | (c,co) <- cs]

-- unifying contents of judgements

---- used in SourceToGF; make error-free and informative
unifyJudgements j k = case unifyJudgement j k of
  Ok l -> l
  Bad s -> error s

unifyJudgement :: Judgement -> Judgement -> Err Judgement
unifyJudgement old new = do
  testErr (jform old == jform new) "different judment forms"
  [jty,jde,jpri] <- mapM unifyField [jtype,jdef,jprintname]
  return $ old{jtype = jty, jdef = jde, jprintname = jpri}
 where
   unifyField field = unifyTerm (field old) (field new)
   unifyTerm oterm nterm = case (oterm,nterm) of
     (Meta _,t) -> return t
     (t,Meta _) -> return t
     _ -> do
       if (nterm /= oterm) 
          then (trace (unwords ["illegal update of",show oterm,"to",show nterm]) 
                (return ()))
          else return () ---- to recover from spurious qualification conflicts
----       testErr (nterm == oterm) 
----               (unwords ["illegal update of",prt oterm,"to",prt nterm])
       return nterm

updateJudgement :: Ident -> Ident -> Judgement -> GF -> Err GF
updateJudgement m c ju gf = do
  mo  <- maybe (Bad (show m)) return $ Data.Map.lookup m $ gfmodules gf
  let mo' = mo {mjments = insert c ju (mjments mo)}
  return $ gf {gfmodules = insert m mo' (gfmodules gf)}

-- abstractions on Term

type Cat  = QIdent
type Fun  = QIdent
type QIdent = (Ident,Ident)

-- | branches à la Alfa
newtype Branch = Branch (Con,([Ident],Term)) deriving (Eq, Ord,Show,Read)
type Con = Ident ---

varLabel :: Int -> Label
varLabel = LVar

wildPatt :: Patt
wildPatt = PW

type Trm = Term

mkProd :: Context -> Type -> Type
mkProd = flip (foldr (uncurry Prod))

-- type constants

typeType :: Type
typeType = Sort "Type"

typePType :: Type
typePType = Sort "PType"

typeStr :: Type
typeStr = Sort "Str"

typeTok :: Type      ---- deprecated
typeTok = Sort "Tok"  

cPredef :: Ident
cPredef = identC "Predef"

cPredefAbs :: Ident
cPredefAbs = identC "PredefAbs"

typeString, typeFloat, typeInt :: Term
typeInts :: Integer -> Term

typeString = constPredefRes "String"
typeInt = constPredefRes "Int"
typeFloat = constPredefRes "Float"
typeInts i = App (constPredefRes "Ints") (EInt i)

isTypeInts :: Term -> Bool
isTypeInts ty = case ty of
  App c _ -> c == constPredefRes "Ints"
  _ -> False

cnPredef = constPredefRes

constPredefRes :: String -> Term
constPredefRes s = Q (IC "Predef") (identC s)

isPredefConstant :: Term -> Bool
isPredefConstant t = case t of
  Q (IC "Predef") _ -> True
  Q (IC "PredefAbs") _ -> True
  _ -> False