1use bhc_ast::{Constraint, ModuleName, TyVar, Type};
4use bhc_intern::Ident;
5use bhc_lexer::TokenKind;
6
7use crate::{ParseError, ParseResult, Parser};
8
9impl<'src> Parser<'src> {
10 pub fn parse_type(&mut self) -> ParseResult<Type> {
12 self.enter_recursion()?;
13 let result = self.parse_type_guarded();
14 self.exit_recursion();
15 result
16 }
17
18 fn parse_type_guarded(&mut self) -> ParseResult<Type> {
19 let start = self.current_span();
20
21 if self.check(&TokenKind::Forall) {
23 return self.parse_forall_type();
24 }
25
26 if let Some(constraints) = self.try_parse_context()? {
30 let ty = self.parse_fun_type()?;
31 let span = start.to(ty.span());
32 return Ok(Type::Constrained(constraints, Box::new(ty), span));
33 }
34
35 self.parse_fun_type()
36 }
37
38 pub(crate) fn try_parse_context(&mut self) -> ParseResult<Option<Vec<Constraint>>> {
41 let saved_pos = self.pos;
43
44 let constraints = if self.check(&TokenKind::LParen) {
46 self.advance(); if self.check(&TokenKind::RParen) {
50 self.advance();
52 if self.eat(&TokenKind::FatArrow) {
53 return Ok(Some(vec![]));
54 }
55 self.pos = saved_pos;
57 return Ok(None);
58 }
59
60 let mut constraints = vec![];
61 match self.try_parse_constraint() {
62 Ok(Some(c)) => constraints.push(c),
63 _ => {
64 self.pos = saved_pos;
65 return Ok(None);
66 }
67 }
68
69 while self.eat(&TokenKind::Comma) {
70 match self.try_parse_constraint() {
71 Ok(Some(c)) => constraints.push(c),
72 _ => {
73 self.pos = saved_pos;
74 return Ok(None);
75 }
76 }
77 }
78
79 if !self.eat(&TokenKind::RParen) {
80 self.pos = saved_pos;
81 return Ok(None);
82 }
83
84 constraints
85 } else {
86 match self.try_parse_constraint() {
88 Ok(Some(c)) => vec![c],
89 _ => {
90 self.pos = saved_pos;
91 return Ok(None);
92 }
93 }
94 };
95
96 if self.eat(&TokenKind::FatArrow) {
98 Ok(Some(constraints))
99 } else {
100 self.pos = saved_pos;
102 Ok(None)
103 }
104 }
105
106 fn try_parse_constraint(&mut self) -> ParseResult<Option<Constraint>> {
108 let start = self.current_span();
109
110 let class = match self.current_kind() {
112 Some(TokenKind::ConId(sym)) => {
113 let ident = Ident::new(*sym);
114 self.advance();
115 ident
116 }
117 _ => return Ok(None),
118 };
119
120 let mut args = vec![];
122 while self.is_atype_start() {
123 args.push(self.parse_atype()?);
124 }
125
126 let end_span = args.last().map(|t| t.span()).unwrap_or(start);
127 let span = start.to(end_span);
128
129 Ok(Some(Constraint { class, args, span }))
130 }
131
132 fn parse_fun_type(&mut self) -> ParseResult<Type> {
134 let lhs = self.parse_infix_type()?;
135
136 self.skip_doc_comments();
139
140 if self.eat(&TokenKind::Arrow) {
141 let rhs = self.parse_fun_type()?;
142 let span = lhs.span().to(rhs.span());
143 Ok(Type::Fun(Box::new(lhs), Box::new(rhs), span))
144 } else {
145 Ok(lhs)
146 }
147 }
148
149 fn parse_infix_type(&mut self) -> ParseResult<Type> {
151 let lhs = self.parse_app_type()?;
152
153 if let Some(TokenKind::ConOperator(sym)) = self.current_kind().cloned() {
155 let op = Ident::new(sym);
156 self.advance();
157 let rhs = self.parse_infix_type()?;
159 let span = lhs.span().to(rhs.span());
160 Ok(Type::InfixOp(Box::new(lhs), op, Box::new(rhs), span))
161 } else {
162 Ok(lhs)
163 }
164 }
165
166 fn parse_app_type(&mut self) -> ParseResult<Type> {
168 let mut ty = self.parse_atype()?;
169
170 while self.is_atype_start() {
171 let arg = self.parse_atype()?;
172 let span = ty.span().to(arg.span());
173 ty = Type::App(Box::new(ty), Box::new(arg), span);
174 }
175
176 Ok(ty)
177 }
178
179 pub fn is_atype_start(&self) -> bool {
181 match self.current_kind() {
182 Some(kind) => matches!(
183 kind,
184 TokenKind::Ident(_)
185 | TokenKind::ConId(_)
186 | TokenKind::QualConId(_, _)
187 | TokenKind::LParen
188 | TokenKind::LBracket
189 | TokenKind::IntLit(_)
191 | TokenKind::TickLBracket
192 | TokenKind::Bang
194 | TokenKind::Tilde
195 ),
196 None => false,
197 }
198 }
199
200 pub fn parse_atype(&mut self) -> ParseResult<Type> {
202 let tok = self.current().ok_or(ParseError::UnexpectedEof {
203 expected: "type".to_string(),
204 })?;
205
206 match &tok.node.kind.clone() {
207 TokenKind::Ident(sym) => {
208 let ident = Ident::new(*sym);
209 let span = tok.span;
210 self.advance();
211 Ok(Type::Var(TyVar { name: ident, span }, span))
212 }
213
214 TokenKind::ConId(sym) => {
215 let ident = Ident::new(*sym);
216 let span = tok.span;
217 self.advance();
218 Ok(Type::Con(ident, span))
219 }
220
221 TokenKind::QualConId(qualifier, name) => {
222 let module_name = ModuleName {
223 parts: vec![*qualifier],
224 span: tok.span,
225 };
226 let ident = Ident::new(*name);
227 let span = tok.span;
228 self.advance();
229 Ok(Type::QualCon(module_name, ident, span))
230 }
231
232 TokenKind::LParen => self.parse_paren_type(),
233
234 TokenKind::LBracket => self.parse_list_type(),
235
236 TokenKind::IntLit(lit) => {
238 let span = tok.span;
239 let value = lit.parse().ok_or_else(|| ParseError::Unexpected {
240 found: "invalid integer".to_string(),
241 expected: "type-level natural".to_string(),
242 span,
243 })?;
244 if value < 0 {
246 return Err(ParseError::Unexpected {
247 found: "negative integer".to_string(),
248 expected: "type-level natural (non-negative)".to_string(),
249 span,
250 });
251 }
252 self.advance();
253 Ok(Type::NatLit(value as u64, span))
254 }
255
256 TokenKind::TickLBracket => self.parse_promoted_list(),
258
259 TokenKind::Bang => {
261 let start = tok.span;
262 self.advance();
263 let inner = self.parse_atype()?;
264 let span = start.to(inner.span());
265 Ok(Type::Bang(Box::new(inner), span))
266 }
267
268 TokenKind::Tilde => {
270 let start = tok.span;
271 self.advance();
272 let inner = self.parse_atype()?;
273 let span = start.to(inner.span());
274 Ok(Type::Lazy(Box::new(inner), span))
275 }
276
277 _ => Err(ParseError::Unexpected {
278 found: tok.node.kind.description().to_string(),
279 expected: "type".to_string(),
280 span: tok.span,
281 }),
282 }
283 }
284
285 fn parse_promoted_list(&mut self) -> ParseResult<Type> {
287 let start = self.current_span();
288 self.expect(&TokenKind::TickLBracket)?;
289
290 if self.eat(&TokenKind::RBracket) {
291 let span = start.to(self.tokens[self.pos - 1].span);
293 return Ok(Type::PromotedList(vec![], span));
294 }
295
296 let mut elems = vec![self.parse_type()?];
297 while self.eat(&TokenKind::Comma) {
298 elems.push(self.parse_type()?);
299 }
300
301 let end = self.expect(&TokenKind::RBracket)?;
302 let span = start.to(end.span);
303
304 Ok(Type::PromotedList(elems, span))
305 }
306
307 fn parse_paren_type(&mut self) -> ParseResult<Type> {
309 let start = self.current_span();
310 self.expect(&TokenKind::LParen)?;
311
312 if self.eat(&TokenKind::RParen) {
313 let span = start.to(self.tokens[self.pos - 1].span);
315 return Ok(Type::Tuple(vec![], span));
316 }
317
318 if self.eat(&TokenKind::Arrow) {
320 let end = self.expect(&TokenKind::RParen)?;
321 let span = start.to(end.span);
322 return Ok(Type::Con(Ident::from_str("->"), span));
323 }
324
325 if let Some(TokenKind::ConOperator(sym)) = self.current_kind().cloned() {
327 let saved = self.pos;
328 let ident = Ident::new(sym);
329 self.advance();
330 if self.check(&TokenKind::RParen) {
331 let end = self.expect(&TokenKind::RParen)?;
332 let span = start.to(end.span);
333 return Ok(Type::Con(ident, span));
334 }
335 self.pos = saved;
337 }
338
339 let first = self.parse_type()?;
340
341 if self.eat(&TokenKind::Comma) {
342 let mut types = vec![first];
344 loop {
345 types.push(self.parse_type()?);
346 if !self.eat(&TokenKind::Comma) {
347 break;
348 }
349 }
350 let end = self.expect(&TokenKind::RParen)?;
351 let span = start.to(end.span);
352 Ok(Type::Tuple(types, span))
353 } else {
354 let end = self.expect(&TokenKind::RParen)?;
356 let span = start.to(end.span);
357 Ok(Type::Paren(Box::new(first), span))
358 }
359 }
360
361 fn parse_list_type(&mut self) -> ParseResult<Type> {
363 let start = self.current_span();
364 self.expect(&TokenKind::LBracket)?;
365
366 if self.eat(&TokenKind::RBracket) {
367 let span = start.to(self.tokens[self.pos - 1].span);
369 return Ok(Type::Con(Ident::from_str("[]"), span));
370 }
371
372 let elem = self.parse_type()?;
373 let end = self.expect(&TokenKind::RBracket)?;
374 let span = start.to(end.span);
375
376 Ok(Type::List(Box::new(elem), span))
377 }
378
379 fn parse_forall_type(&mut self) -> ParseResult<Type> {
381 let start = self.current_span();
382 self.expect(&TokenKind::Forall)?;
383
384 let mut vars = Vec::new();
385 while let Some(tok) = self.current() {
386 match &tok.node.kind {
387 TokenKind::Ident(sym) => {
388 let name = Ident::new(*sym);
389 let span = tok.span;
390 self.advance();
391 vars.push(TyVar { name, span });
392 }
393 TokenKind::Dot => {
395 self.advance();
396 break;
397 }
398 _ => break,
399 }
400 }
401
402 let ty = self.parse_type()?;
403 let span = start.to(ty.span());
404
405 Ok(Type::Forall(vars, Box::new(ty), span))
406 }
407}