@@ -193,7 +193,11 @@ tokens :-
193
193
Happy
194
194
-----
195
195
196
- We'll parse into a small untyped lambda calculus for our frontend language.
196
+ Using Happy and our previosly defind lexer we'll write down the production rules
197
+ for our simple untyped lambda calculus.
198
+
199
+ We start by defining a `` Syntax `` module where we define the AST we'll generate
200
+ from running over the token stream to produce the program graph structure.
197
201
198
202
``` haskell
199
203
module Syntax where
@@ -243,7 +247,9 @@ production rules.
243
247
```
244
248
245
249
The parser itself will live inside of a custom monad of our choosing. In this
246
- simple case we'll just add error handling with the `` Except `` monad.
250
+ case we'll add error handling with the `` Except `` monad that will break out of
251
+ the parsing process if an invalid production or token is found and return a
252
+ `` Left `` value which we'll handle inside of our toplevel logic.
247
253
248
254
``` haskell
249
255
-- Parser monad
@@ -252,8 +258,15 @@ simple case we'll just add error handling with the ``Except`` monad.
252
258
```
253
259
254
260
And finally our production rules, the toplevel entry point for our parser will
255
- be the `` expr `` rule. Notice how naturally we can write a left recursive
256
- grammar for our infix operators.
261
+ be the `` expr `` rule. The left hand side of the production is a Happy production
262
+ rule which can be mutually recursive, while the right hand side is a Haskell
263
+ expression with several metavariable indicated by the dollar sign variables that
264
+ map to the nth expression on the left hand side.
265
+
266
+ ```
267
+ $0 $1 $2 $3 $4 $5
268
+ let VAR '=' Expr in Expr { App (Lam $2 $6) $4 }
269
+ ```
257
270
258
271
``` haskell
259
272
-- Entry point
@@ -283,6 +296,9 @@ Atom : '(' Expr ')' { $2 }
283
296
| false { Lit (LBool False ) }
284
297
```
285
298
299
+ Notice how naturally we can write a left recursive grammar for our binary infix
300
+ operators.
301
+
286
302
Syntax Errors
287
303
-------------
288
304
@@ -324,7 +340,7 @@ Type Error Provenance
324
340
325
341
Before our type inference engine would generate somewhat typical type inference
326
342
error messages. If two terms couldn't be unified it simply told us this and some
327
- information about the toplevel declaration where it occurred, leaving us with a
343
+ information about the top-level declaration where it occurred, leaving us with a
328
344
bit of a riddle about how exactly this error came to be.
329
345
330
346
``` haskell
@@ -337,14 +353,13 @@ in the definition of 'foo'
337
353
338
354
Effective error reporting in the presence of type inference is a difficult task,
339
355
effectively our typechecker takes our frontend AST and transforms it into a
340
- large constraint problem, destroying position
341
- information in the process. Even if the position information were tracked, the
342
- nature of unification is that a cascade of several unifications can lead to
343
- unsolvability and the immediate two syntactic constructs that gave rise to a
344
- unification failure are not necessarily the two that map back to human intuition
345
- about how the type error arose. Very little research has done on this topic and
346
- it remains an open topic with very immediate and applicable results to
347
- programming.
356
+ large constraint problem, destroying position information in the process. Even
357
+ if the position information were tracked, the nature of unification is that
358
+ a cascade of several unifications can lead to unsolvability and the immediate
359
+ two syntactic constructs that gave rise to a unification failure are not
360
+ necessarily the two that map back to human intuition about how the type error
361
+ arose. Very little research has done on this topic and it remains an open
362
+ topic with very immediate and applicable results to programming.
348
363
349
364
To do simple provenance tracking we will use a technique of tracking the "flow"
350
365
of type information through our typechecker and associate position information
@@ -473,10 +488,10 @@ with
473
488
let f x y = x y
474
489
```
475
490
476
- This is of course the simplest implementation of the tracking method and
477
- could be further extended by giving a weighted ordering to the constraints
478
- based on their likelihood of importance and proximity and then choosing which
479
- location to report based on this information. This remains an open area of work.
491
+ This is of course the simplest implementation of the tracking method and could
492
+ be further extended by giving a weighted ordering to the constraints based on
493
+ their likelihood of importance and proximity and then choosing which location to
494
+ report based on this information. This remains an open area of work.
480
495
481
496
Indentation
482
497
-----------
0 commit comments