summaryrefslogtreecommitdiff
path: root/src/GF/Source/CompileM.hs
blob: 3d97a029ed5b9772f63c076a524908ead016bf7e (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
module CompileM where

import Grammar
import Ident
import Option
import PrGrammar
import Update
import Lookup
import Modules
---import Rename

import Operations
import UseIO

import Monad

compileMGrammar :: Options -> SourceGrammar -> IOE SourceGrammar
compileMGrammar opts sgr = do

  ioeErr $ checkUniqueModuleNames sgr

  deps <- ioeErr $ moduleDeps sgr

  deplist <- either return 
                 (\ms -> ioeBad $ "circular modules" +++ unwords (map show ms)) $ 
                 topoTest deps

  let deps' = closureDeps deps

  foldM (compileModule opts deps' sgr) emptyMGrammar deplist

checkUniqueModuleNames :: MGrammar i f a r c -> Err ()
checkUniqueModuleNames gr = do
  let ms = map fst $ tree2list $ modules gr
      msg = checkUnique ms
  if null msg then return () else Bad $ unlines msg

-- to decide what modules immediately depend on what, and check if the
-- dependencies are appropriate

moduleDeps :: MGrammar i f a c r -> Err Dependencies
moduleDeps gr = mapM deps $ tree2list $ modules gr where
  deps (c,mi) = errIn ("checking dependencies of module" +++ prt c) $ case mi of
    ModAbs m -> chDep (IdentM c MTAbstract) 
                      (extends m) MTAbstract (opens m) MTAbstract
    ModRes m -> chDep (IdentM c MTResource) 
                      (extends m) MTResource (opens m) MTResource
    ModCnc m -> do
      a:ops <- case opens m of
        os@(_:_) -> return os
        _ -> Bad "no abstract indicated for concrete module"
      aty <- lookupModuleType gr a
      testErr (aty == MTAbstract) "the for-module is not an abstract syntax" 
      chDep (IdentM c (MTConcrete a)) (extends m) MTResource ops MTResource

  chDep it es ety os oty = do
    ests <- mapM (lookupModuleType gr) es
    testErr (all (==ety) ests) "inappropriate extension module type" 
    osts <- mapM (lookupModuleType gr) os
    testErr (all (==oty) osts) "inappropriate open module type" 
    return (it, [IdentM e ety | e <- es] ++ [IdentM o oty | o <- os])

type Dependencies = [(IdentM Ident,[IdentM Ident])]

---compileModule :: Options -> Dependencies -> SourceGrammar -> 
---                 CanonGrammar -> IdentM -> IOE CanonGrammar
compileModule opts deps sgr cgr i = do
  
   let name = identM i 

   testIfCompiled deps name

   mi <- ioeErr $ lookupModule sgr name

   mi' <- case typeM i of
     -- previously compiled cgr used as symbol table
     MTAbstract   -> compileAbstract cgr mi
     MTResource   -> compileResource cgr mi
     MTConcrete a -> compileConcrete a cgr mi 

   ifIsOpt doOutput $ writeCanonFile name mi'

   return $ addModule cgr name mi'

 where

   ifIsOpt o f = if (oElem o opts) then f else return ()
   doOutput    = iOpt "o"


testIfCompiled :: Dependencies -> Ident -> IOE Bool
testIfCompiled _ _ = return False ----

---writeCanonFile :: Ident -> CanonModInfo -> IOE ()
writeCanonFile name mi' = ioeIO $ writeFile (canonFileName name) [] ----

canonFileName n = n ++ ".gfc" ---- elsewhere!

---compileAbstract :: CanonGrammar -> SourceModInfo -> IOE CanonModInfo
compileAbstract can (ModAbs m0) = do
  let m1 = renameMAbstract m0
{-
  checkUnique
  typeCheck
  generateCode
  addToCanon
-}
  ioeBad "compile abs not yet"

---compileResource :: CanonGrammar -> SourceModInfo -> IOE CanonModInfo
compileResource can md = do
{-
  checkUnique
  typeCheck
  topoSort
  compileOpers -- conservative, since more powerful than lin
  generateCode
  addToCanon
-}
  ioeBad "compile res not yet"

---compileConcrete :: Ident -> CanonGrammar -> SourceModInfo -> IOE CanonModInfo
compileConcrete ab can md = do
{-
  checkUnique
  checkComplete ab
  typeCheck
  topoSort
  compileOpers
  optimize
  createPreservedOpers
  generateCode
  addToCanon
-}
  ioeBad "compile cnc not yet"


-- to be imported

closureDeps :: [(a,[a])] -> [(a,[a])]
closureDeps ds = ds ---- fix-point iteration