-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.hs
210 lines (175 loc) · 7.05 KB
/
Parser.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
module Parser where
import Control.Applicative ((<**>))
import Data.List (elemIndex)
import Term (Level(LevelN, LevelW, LevelAfterW))
import TypedTerm
import Text.Parsec
data SourceTerm =
SLam String SourceTerm
| SApp SourceTerm SourceTerm
| SVar String
| SNatLit Int
| SNatRec String SourceTerm SourceTerm String String SourceTerm SourceTerm
| SAddProof SourceTerm SourceTerm SourceTerm
| SUseProof SourceTerm SourceTerm SourceTerm SourceTerm String SourceTerm
| SPair SourceTerm SourceTerm
| SProj1 SourceTerm
| SProj2 SourceTerm
| SGetProof SourceTerm SourceTerm
| SUseSquash SourceTerm SourceTerm String SourceTerm
| SPi String SourceTerm SourceTerm
| SRefine SourceTerm String SourceTerm
| SSigma String SourceTerm SourceTerm
| SSort Level
| SLet String SourceTerm SourceTerm
| STyped SourceTerm SourceTerm
deriving Show
lexeme :: Parsec String st r -> Parsec String st r
lexeme = (<* spaces)
lchar :: Char -> Parsec String st Char
lchar = lexeme . char
lkeyword :: String -> Parsec String st String
lkeyword = lexeme . try . string
ident :: Parsec String st String
ident = lexeme $
(:) <$> (alphaNum <|> char '_') <*> many (alphaNum <|> oneOf "_'")
expr :: Parsec String st SourceTerm
expr = do
x <- subexpr
(lchar ':' *> (STyped x <$> subexpr)) <|> return x
subexpr :: Parsec String st SourceTerm
subexpr = lexeme $ pi' <|> sigma <|> soit <|> lam <|> superfactor
superfactor :: Parsec String st SourceTerm
superfactor = do
x <- factor
(lkeyword "->" *> (SPi "_" x <$> subexpr)) <|> return x
factor :: Parsec String st SourceTerm
factor = lexeme $ subfactor <**> postfixes
postfixes :: Parsec String st (SourceTerm -> SourceTerm)
postfixes = (flip (.) <$> postfix <*> postfixes) <|> return id
postfix :: Parsec String st (SourceTerm -> SourceTerm)
postfix = lexeme $ app <|> addproof <|> refine
app :: Parsec String st (SourceTerm -> SourceTerm)
app = lexeme $ flip SApp <$> subfactor
addproof :: Parsec String st (SourceTerm -> SourceTerm)
addproof = lexeme $ (\p t x->SAddProof x t p) <$ lchar '{'
<*> subexpr <* lchar ':' <*> expr <* lchar '}'
refine :: Parsec String st (SourceTerm -> SourceTerm)
refine = lexeme $ (\n p x->SRefine x n p) <$ lchar '['
<*> ident <* lchar '.' <*> expr <* lchar ']'
subfactor :: Parsec String st SourceTerm
subfactor =
sort <|> nat <|> natrec <|> useproof <|> pair
<|> proj <|> getproof <|> usesquash
<|> var <|> (lchar '(' *> expr <* lchar ')')
pi' :: Parsec String st SourceTerm
pi' = lexeme $ SPi <$ lchar '^' <*> (try (ident <* lchar ':') <|> return "_")
<*> expr <* lchar '.' <*> subexpr
sigma :: Parsec String st SourceTerm
sigma = lexeme $ SSigma <$ lchar '&' <*> (try (ident <* lchar ':') <|> return "_")
<*> expr <* lchar '.' <*> subexpr
soit :: Parsec String st SourceTerm
soit = lexeme $ SLet <$ lchar '|' <*> ident <* lchar '='
<*> expr <* lchar '.' <*> subexpr
lam :: Parsec String st SourceTerm
lam = lexeme $ lexeme (oneOf "\\!") *> sublam
sublam :: Parsec String st SourceTerm
sublam = lexeme $ (lchar '.' *> subexpr) <|> SLam <$> ident <*> sublam
sort :: Parsec String st SourceTerm
sort = lexeme $
try (SSort . LevelN <$ char '*' <*> (read <$> many1 digit)) <|>
try (SSort LevelW <$ string "*w") <|>
try (SSort LevelAfterW <$ string "*x") <|>
(SSort (LevelN 0) <$ char '*') <|>
(SSort (LevelN 1) <$ char '?')
nat :: Parsec String st SourceTerm
nat = lexeme $ try $ (SNatLit . read) <$> many1 digit
natrec :: Parsec String st SourceTerm
natrec = lexeme $
SNatRec <$ lkeyword "natrec" <* lchar '{'
<*> (try (ident <* lchar '.') <|> return "_") <*> expr <* lchar ';'
<*> expr <* lchar ';'
<*> ident <*> ident <* lchar '.' <*> expr <* lchar ';'
<*> expr <* optional (lchar ';')
<* lchar '}'
useproof :: Parsec String st SourceTerm
useproof = lexeme $
SUseProof <$ lkeyword "useproof" <* lchar '{'
<*> expr <* lchar ';'
<*> expr <* lchar ';'
<*> expr <* lchar ';'
<*> expr <* lchar ';'
<*> (try (ident <* lchar '.') <|> return "_")
<*> expr <* optional (lchar ';')
<* lchar '}'
pair :: Parsec String st SourceTerm
pair = lexeme $
SPair <$ lkeyword "pair" <* lchar '{'
<*> expr <* lchar ';'
<*> expr <* optional (lchar ';')
<* lchar '}'
proj :: Parsec String st SourceTerm
proj = lexeme $
((SProj1 <$ lkeyword "left") <|> (SProj2 <$ lkeyword "right"))
<* lchar '{' <*> expr <* lchar '}'
var :: Parsec String st SourceTerm
var = lexeme $ SVar <$> ident
getproof :: Parsec String st SourceTerm
getproof = lexeme $
SGetProof <$ lkeyword "getproof" <* lchar '{'
<*> expr <* lchar ';'
<*> expr <* optional (lchar ';')
<* lchar '}'
usesquash :: Parsec String st SourceTerm
usesquash = lexeme $
SUseSquash <$ lkeyword "usesquash" <* lchar '{'
<*> expr <* lchar ';'
<*> expr <* lchar ';'
<*> (try (ident <* lchar '.') <|> return "_")
<*> expr <* optional (lchar ';')
<* lchar '}'
data CodeLine =
ExprLine SourceTerm
| DefLine String SourceTerm
line :: Parsec String st CodeLine
line = (try (DefLine <$> ident <* lchar '=') <*> expr) <|> (ExprLine <$> expr)
lookupVar :: String -> [String] -> Either String Int
lookupVar s ss = case elemIndex s ss of
Just n -> return n
Nothing -> Left $ "Cannot find var " ++ s ++ " in " ++ show ss
indexifyC :: [String] -> SourceTerm -> Either String CheckedTerm
indexifyC ss (SLam s x) = TLam <$> indexifyC (s:ss) x
indexifyC ss (SAddProof x t p) =
TAddProof <$> indexifyC ss x <*> indexifyC ss t <*> indexifyC ss p
indexifyC ss (SPair a b) =
TPair <$> indexifyC ss a <*> indexifyC ss b
indexifyC ss (SLet s x y) = TLetC <$> indexifyS ss x <*> indexifyC (s:ss) y
indexifyC ss x = Synthed <$> indexifyS ss x
indexifyS :: [String] -> SourceTerm -> Either String SynthedTerm
indexifyS ss (SVar s) = TVar <$> lookupVar s ss
indexifyS ss (SNatLit n) =
TApp <$> (indexifyS ss $ SVar "fromNat") <*> return (fromNat n)
where
fromNat 0 = Synthed $ TZero
fromNat n = Synthed $ TSucc $ fromNat $ n - 1
indexifyS ss (SNatRec n1 t z n2 p s n) =
TNatRec <$> indexifyC (n1:ss) t <*> indexifyC ss z
<*> indexifyC (p:n2:ss) s <*> indexifyC ss n
-- the stubbed-out binders are technically unnecessary,
-- and I'll remove them someday probably
indexifyS ss (SUseProof tx tp x ty n1 y) =
TUseProof <$> indexifyC ss tx <*> indexifyC ss tp <*> indexifyC ss x
<*> indexifyC ("":ss) ty <*> indexifyC (n1:"":ss) y
indexifyS ss (SProj1 p) = TProj1 <$> indexifyS ss p
indexifyS ss (SProj2 p) = TProj2 <$> indexifyS ss p
indexifyS ss (SGetProof tp x) = TGetProof <$> indexifyC ss tp <*> indexifyS ss x
indexifyS ss (SUseSquash p ty n y) =
TUseSquash <$> indexifyS ss p <*> indexifyC ss ty <*> indexifyC (n:ss) y
indexifyS ss (SPi s t x) = TPi <$> indexifyS ss t <*> indexifyS (s:ss) x
indexifyS ss (SRefine x s p) = TRefine <$> indexifyS ss x <*> indexifyS (s:ss) p
indexifyS ss (SSigma s t x) = TSigma <$> indexifyS ss t <*> indexifyS (s:ss) x
indexifyS ss (SSort k) = return $ TSort k
indexifyS ss (SApp x y) = TApp <$> (indexifyS ss x) <*> (indexifyC ss y)
indexifyS ss (SLet s x y) = TLetS <$> indexifyS ss x <*> indexifyS (s:ss) y
indexifyS ss (STyped x t) = (:::) <$> indexifyC ss x <*> indexifyC ss t
indexifyS _ x = Left $ "Can't synth for " ++ show x