[cvs-nhc98] patch applied (hat): Correct bug in expansion of type
synonyms for worker type signatures.
Malcolm Wallace
Malcolm.Wallace at cs.york.ac.uk
Tue Oct 10 07:24:36 EDT 2006
Wed Apr 2 08:21:52 PST 2003 olaf
* Correct bug in expansion of type synonyms for worker type signatures.
Malcolm's following program failed transforming:
----A.hs----
module A where
type State d s u s' = d -> s -> (u,s')
----B.hs----
module B where
import A
data Down = Down
data Thread = Thread
type GcodeFixMonad a = State Down Thread a Thread
checkIfR :: Int -> GcodeFixMonad Bool
checkIfR i Down Thread = (i==0, Thread)
----end----
$ hmake -hat B.hs
hat-trans A.hs
Creating directories Hat
Wrote Hat/A.hs
nhc98 -c -package hat -o Hat/A.o Hat/A.hs
hat-trans B.hs
Fail: expandTypeSynonym: GcodeFixMonad___1 is not a type synonym
The problem was that when determining the upper part of a rhs of a type
synonym definition that may be expanded, it may (and in this example is)
necessary to expand a type synonym occuring on the rhs.
Modifying hat-trans to perform correct expansion showed up two bad design
properties of its implementation:
1. The upper part of the rhs of a type synonym needs to be written in the
.aux file and the helper type synonyms for the lower parts of the rhs
need to be added to the transformed program. Upper and lower parts are in
a natural way determined by a single splitSynonym function. However, the
generation of the environment that is later written to the .aux file and
the generation of the transformed program happen in two separate passes,
working on different data structures (e.g. TokenId vs TraceId). Hence the
code of splitSynonym is basically duplicated, and both variants have to
agree to make everything work.
Is there an architecture that avoids this duplication?
2. Originally, when generating the upper part of a rhs for the .aux file,
the information about the (upper part of) rhss of other type synonyms was
not available. The passes were:
1 Traverse top level ast to determine identifier map
2 Traverse top level ast to determine environment of locally defined exported identifiers.
3 Read imports to determine environment of all exported identifiers.
4 Write environment of all exported identifiers into aux file.
5 Traverse top level ast to determine identifier map
6 Traverse top level ast to determine environment of all locally defined identifiers.
7 Read imports to determine environment of all possibly used identifiers.
8 Traverse whole ast to annotate it with infos from environment.
Because the environment generated by step 7 is needed for type synonym splitting in step 2 and 6, I rearranged the passes:
1 Traverse top level ast to determine identifier map
2 Read imports to determine environment of all imported possibly used identifiers.
3 Traverse top level ast to determine environment of all used identifiers.
4 Traverse whole ast to annotate it with infos from environment.
5 Traverse top level ast to determine identifier map
6 Traverse top level ast to determine environment of locally defined exported identifiers.
7 Read imports to determine environment of all exported identifiers.
8 Write environment of all exported identifiers into aux file.
So now the environment for type splitting is generated in step 3 and used in steps 3 and 6. To enable generation and use in step 3 essential use of lazy evaluation is made in step 3. As long as there is no cyclic type synonym definition this does not cause a black hole.
The rearrangement has the disadvantage that orginal and attributed ast live at the same time.
It works, but certainly all this could be much simpler and more efficient?
M ./src/hattrans/AuxFile.hs -28 +77
M ./src/hattrans/AuxLabelAST.hs -28 +16
M ./src/hattrans/AuxTypes.hs +16
M ./src/hattrans/Flags.hs +3
M ./src/hattrans/HatTrans.hs -7 +13
M ./src/hattrans/Makefile -1 +1
M ./src/hattrans/TraceId.hs +5
M ./src/hattrans/TraceTrans.hs -9 +13
More information about the Cvs-nhc98
mailing list