... | ... | @@ -24,8 +24,11 @@ We assume that open extension typefamily instances for GHC-specific decorations |
|
|
|
|
|
There are a couple of ways to implement such a solution:
|
|
|
|
|
|
1. We put the source locations in the new field extensions and use a typeclass to set/get the locations.
|
|
|
1. We put the source locations in the new constructor extension, similar in spirit to the current `Located`.
|
|
|
1. We put the source locations in the new field extensions and use a typeclass to set/get the locations.
|
|
|
|
|
|
|
|
|
In the implementation, we have settled on the solution A, as it avoids the clutter.
|
|
|
|
|
|
|
|
|
Notes:
|
... | ... | @@ -130,6 +133,22 @@ typeinstanceXId(GHC p)=XIdGHC p |
|
|
### Solution A - Example Code
|
|
|
|
|
|
|
|
|
In the code below, as compared to the ping-pong style above, we have the following key changes:
|
|
|
|
|
|
- `LExp` is replaced with `Exp`
|
|
|
- a new constructor extension is introduced to wrap `Exp` with a `SrcSpan`
|
|
|
- a pattern synonym `LL` is introduced using the new constructor
|
|
|
|
|
|
```
|
|
|
{-# OPTIONS_GHC -Wall #-}{-# LANGUAGE TypeFamilies, PatternSynonyms #-}moduleSolutionBwhereimportBasicGHCTypesimportTTG-- ------------------------------------------------ GHC-Specific Decorations-- ----------------------------------------------typeinstanceXVar(GHC_)=()typeinstanceXAbs(GHC_)=()typeinstanceXApp(GHC p)=XAppGHC p
|
|
|
typeinstanceXPar(GHC_)=()typeinstanceXNew(GHC p)=Either(Located(Exp(GHC p)))(XNewGHC p)typeinstanceXId(GHC p)=XIdGHC p
|
|
|
|
|
|
-- NB: if GHC later wants to add extension fields to (say)-- XAbs, we can just redefine XAbs (GHC p) to be more like-- the XApp case-- ------------------------------------------------ LL Pattern Synonym-- ----------------------------------------------patternLL::SrcSpan->Exp(GHC p)->Exp(GHC p)patternLL sp m =New(Left(L sp m))-- ------------------------------------------------ Example Function-- ----------------------------------------------par::Exp(GHC p)->Exp(GHC p)par l@(LL sp (App{}))=LL sp (Par() l)par l = l
|
|
|
```
|
|
|
|
|
|
### Solution B - Example Code
|
|
|
|
|
|
|
|
|
In the code below, as compared to the ping-pong style above, we have the following key changes:
|
|
|
|
|
|
- `LExp` is replaced with `Exp`
|
... | ... | @@ -183,42 +202,11 @@ patternLL s m <-(getSpan' ->L s m)whereLL s m = setSpan m s |
|
|
-- ------------------------------------------------ Example Function-- ----------------------------------------------par::Exp(GHC p)->Exp(GHC p)par l@(LL sp (App{}))=LL sp (Par(L noLoc ()) l)par l = l
|
|
|
```
|
|
|
|
|
|
### Solution B - Example Code
|
|
|
|
|
|
|
|
|
In the code below, as compared to the ping-pong style above, we have the following key changes:
|
|
|
|
|
|
- `LExp` is replaced with `Exp`
|
|
|
- a new constructor extension is introduced to wrap `Exp` with a `SrcSpan`
|
|
|
- a pattern synonym `LL` is introduced using the new constructor
|
|
|
|
|
|
```
|
|
|
{-# OPTIONS_GHC -Wall #-}{-# LANGUAGE TypeFamilies, PatternSynonyms #-}moduleSolutionBwhereimportBasicGHCTypesimportTTG-- ------------------------------------------------ GHC-Specific Decorations-- ----------------------------------------------typeinstanceXVar(GHC_)=()typeinstanceXAbs(GHC_)=()typeinstanceXApp(GHC p)=XAppGHC p
|
|
|
typeinstanceXPar(GHC_)=()typeinstanceXNew(GHC p)=Either(Located(Exp(GHC p)))(XNewGHC p)typeinstanceXId(GHC p)=XIdGHC p
|
|
|
|
|
|
-- NB: if GHC later wants to add extension fields to (say)-- XAbs, we can just redefine XAbs (GHC p) to be more like-- the XApp case-- ------------------------------------------------ LL Pattern Synonym-- ----------------------------------------------patternLL::SrcSpan->Exp(GHC p)->Exp(GHC p)patternLL sp m =New(Left(L sp m))-- ------------------------------------------------ Example Function-- ----------------------------------------------par::Exp(GHC p)->Exp(GHC p)par l@(LL sp (App{}))=LL sp (Par() l)par l = l
|
|
|
```
|
|
|
|
|
|
## Pros & Cons
|
|
|
|
|
|
### Solution A
|
|
|
|
|
|
|
|
|
Pros:
|
|
|
|
|
|
- TODO
|
|
|
|
|
|
|
|
|
Cons:
|
|
|
|
|
|
- An instance of `HasSpan` should be defined per datatype
|
|
|
- Handling of the source locations should be done once per constructor
|
|
|
- When constructing/generating terms the first field of the constructors should explicitly mention the source location
|
|
|
(see the `par` function in the Solution A's code, where the first field of `Par` should have a `SrcSpan`, even though a dummy one.)
|
|
|
|
|
|
### Solution B
|
|
|
|
|
|
|
|
|
Pros:
|
|
|
|
|
|
- It makes it easy to omit locations altogether (see the notes about "Generated" code).
|
... | ... | @@ -237,3 +225,18 @@ Cons: |
|
|
|
|
|
- At the binding site of a variable we know that we \*always\* have a location, and we can put that in its Name.
|
|
|
If locations were more optional, that would not be so true.
|
|
|
|
|
|
### Solution B
|
|
|
|
|
|
|
|
|
Pros:
|
|
|
|
|
|
- TODO
|
|
|
|
|
|
|
|
|
Cons:
|
|
|
|
|
|
- An instance of `HasSpan` should be defined per datatype
|
|
|
- Handling of the source locations should be done once per constructor
|
|
|
- When constructing/generating terms the first field of the constructors should explicitly mention the source location
|
|
|
(see the `par` function in the Solution A's code, where the first field of `Par` should have a `SrcSpan`, even though a dummy one.) |