
Hello Guys, While I was playing with YHC, I tried to rebuild Prelude.hs. I saw that there is a prebuilt version of the entire base package, which is copied when I do: $ Makefile.bat lib I wonder how this bootstrapping version of base was built. When I tried to do this manually the compiler died with stack overflow. Is it because the compiler is tring to import Prelude while compiling Prelude? Krasimir

I wonder how this bootstrapping version of base was built. When I tried to do this manually the compiler died with stack overflow. Is it because the compiler is tring to import Prelude while compiling Prelude?
Yes, its something like that. There are also problems with recursive dependancies I believe - things like IO require the Prelude, and the Prelude requires IO. If you look at the Unix makefile, that really does try and build them - it also requires the special flag --unifyhack or something. I believe it also requires modifying the .hi file by hand as well. The hope is in future that compiling the Prelude will be as simple as "yhc Prelude.hs" - but this requires quite a few changes before thats ready. Thanks Neil

Ok. I tried to replace the bytecode generator in YHC with my own which
is generating .NET code instead of the usual bytecode. I managed to
run my first application for .NET but with some hand written code that
replaces a small part of the base package. What I want is to generate
the right code for base with the compiler. Any advice about how to do
that?
Cheers,
Krasimir
2006/1/16, Neil Mitchell
I wonder how this bootstrapping version of base was built. When I tried to do this manually the compiler died with stack overflow. Is it because the compiler is tring to import Prelude while compiling Prelude?
Yes, its something like that. There are also problems with recursive dependancies I believe - things like IO require the Prelude, and the Prelude requires IO. If you look at the Unix makefile, that really does try and build them - it also requires the special flag --unifyhack or something. I believe it also requires modifying the .hi file by hand as well.
The hope is in future that compiling the Prelude will be as simple as "yhc Prelude.hs" - but this requires quite a few changes before thats ready.
Thanks
Neil

Wow, way cool. I hope the .NET back end can end up in the main repo as soon as its done! The secret to compiling the prelude is using the flags "-c -redefine -prelude" - if you omit -c it tries to compile in make mode, which notices that it requires the prelude, which requires the prelude ... and leads to stack overflow. Thanks Neil

Thanks! It works. I will be happy if the required changes would be
incorporated in the main repo when they are stable.
2006/1/16, Neil Mitchell
Wow, way cool. I hope the .NET back end can end up in the main repo as soon as its done!
The secret to compiling the prelude is using the flags "-c -redefine -prelude" - if you omit -c it tries to compile in make mode, which notices that it requires the prelude, which requires the prelude ... and leads to stack overflow.
Thanks
Neil

I found that there are two instances for: Show Char and Enum Char, and
there are two declarations for Bounded class. Is it intentional?
2006/1/17, Krasimir Angelov
Thanks! It works. I will be happy if the required changes would be incorporated in the main repo when they are stable.
2006/1/16, Neil Mitchell
: Wow, way cool. I hope the .NET back end can end up in the main repo as soon as its done!
The secret to compiling the prelude is using the flags "-c -redefine -prelude" - if you omit -c it tries to compile in make mode, which notices that it requires the prelude, which requires the prelude ... and leads to stack overflow.
Thanks
Neil

On 16/01/06, Krasimir Angelov
I found that there are two instances for: Show Char and Enum Char, and there are two declarations for Bounded class. Is it intentional?
My guess is no, and thats why -redefine is required. However, I know a lot of bizare internal hackery goes on in the prelude so maybe it is required... It doesn't seem to break with it removed, and it shouldn't propagate through to the back end, so I'll check with Tom and if possible remove all these bad bits. Thanks Neil

It doesn't seem to break with it removed, and it shouldn't propagate through to the back end, so I'll check with Tom and if possible remove all these bad bits.
All removed, I also changed the -redefine flag so it doesn't ignore the error that the bounded class was raising. Defining instance Show Char twice in one file should be an error, but it doesn't get raised. This is a bug outstanding. Thanks Neil

The error isn't raised when the usual byte code compiler is used but
it happens when the .NET backend is used. The problem is that I am
generating IL assembly code which after that is compiled with the
ilasm tool. The tool complains about the duplicated declarations. With
the byte code compiler you will end up with a little bit more byte
code. Is it possible to remove the duplicated instances as well?
Cheers,
Krasimir
2006/1/17, Neil Mitchell
It doesn't seem to break with it removed, and it shouldn't propagate through to the back end, so I'll check with Tom and if possible remove all these bad bits.
All removed, I also changed the -redefine flag so it doesn't ignore the error that the bounded class was raising.
Defining instance Show Char twice in one file should be an error, but it doesn't get raised. This is a bug outstanding.
Thanks
Neil

code. Is it possible to remove the duplicated instances as well? Yep, I removed them already - they were certainly a bug. It should be in the repo already.
The compiler detects duplicate class declarations (good), but supresses rename errors with the -redefine flag (bad, fixed now), and doesn't detect duplicate instance declarations (bad, unfixed). Thanks Neil

Cool! Now I am able to compile the entire base package to IL code but
there is still one problem. The byte code backend is using a special
instruction for all primitives. I would like to try an another
approach that will allow to call the primitives directly. For this
purpose I need to now whether a given Id is an Id of a primitive. Is
it currently possible? It is enough if there was any flag in the Info
datatype. Any suggestions?
Krasimir
2006/1/17, Neil Mitchell
code. Is it possible to remove the duplicated instances as well? Yep, I removed them already - they were certainly a bug. It should be in the repo already.
The compiler detects duplicate class declarations (good), but supresses rename errors with the -redefine flag (bad, fixed now), and doesn't detect duplicate instance declarations (bad, unfixed).
Thanks
Neil

Hi Krasimir, Great work with the .NET backend! It wouldn't be easy. Knowing whether a function internal to this module is primitive is relatively easy. However knowing whether a function in another module is primitive is harder because the program gets it's information about external functions from the .hi file and the .hi file doesn't store whether a function was primitive or not. It would be possible to add it, but messing about with the hi files isn't fun (trust me ;-)). Hope that helps Tom Krasimir Angelov wrote:
Cool! Now I am able to compile the entire base package to IL code but there is still one problem. The byte code backend is using a special instruction for all primitives. I would like to try an another approach that will allow to call the primitives directly. For this purpose I need to now whether a given Id is an Id of a primitive. Is it currently possible? It is enough if there was any flag in the Info datatype. Any suggestions?
Krasimir
2006/1/17, Neil Mitchell
: code. Is it possible to remove the duplicated instances as well?
Yep, I removed them already - they were certainly a bug. It should be in the repo already.
The compiler detects duplicate class declarations (good), but supresses rename errors with the -redefine flag (bad, fixed now), and doesn't detect duplicate instance declarations (bad, unfixed).
Thanks
Neil
_______________________________________________ Yhc mailing list Yhc@haskell.org http://haskell.org/mailman/listinfo/yhc

Ok. Then I will follow the same way used in the bytecode backend.
2006/1/18, Thomas Shackell
Hi Krasimir,
Great work with the .NET backend!
It wouldn't be easy. Knowing whether a function internal to this module is primitive is relatively easy. However knowing whether a function in another module is primitive is harder because the program gets it's information about external functions from the .hi file and the .hi file doesn't store whether a function was primitive or not.
It would be possible to add it, but messing about with the hi files isn't fun (trust me ;-)).
Hope that helps
Tom
Krasimir Angelov wrote:
Cool! Now I am able to compile the entire base package to IL code but there is still one problem. The byte code backend is using a special instruction for all primitives. I would like to try an another approach that will allow to call the primitives directly. For this purpose I need to now whether a given Id is an Id of a primitive. Is it currently possible? It is enough if there was any flag in the Info datatype. Any suggestions?
Krasimir
2006/1/17, Neil Mitchell
: code. Is it possible to remove the duplicated instances as well?
Yep, I removed them already - they were certainly a bug. It should be in the repo already.
The compiler detects duplicate class declarations (good), but supresses rename errors with the -redefine flag (bad, fixed now), and doesn't detect duplicate instance declarations (bad, unfixed).
Thanks
Neil
_______________________________________________ Yhc mailing list Yhc@haskell.org http://haskell.org/mailman/listinfo/yhc

One thing to consider (that I forgot to mention) is that the compiler generates wrappers for primitives. Thus if you have Haskell code like: aPrimitive primitive 1 :: Int -> Int The code that is generated is a wrapper FUN aPrimitive: PUSH_ARG 0 EVAL POP 1 PRIMITIVE [aPrimitive C code] RETURN_EVAL It *is* possible to get away without the wrapper but it makes life quite hard, because you need to make sure that the arguments are evaluated before calling the primitive function. You could of course do FUN aPrimitive: PUSH_ARG 0 EVAL MK_AP [aPrimitive C code] 1 RETURN_EVAL but this is both quite nasty and also less efficient. Tom Krasimir Angelov wrote:
Ok. Then I will follow the same way used in the bytecode backend.
2006/1/18, Thomas Shackell
: Hi Krasimir,
Great work with the .NET backend!
It wouldn't be easy. Knowing whether a function internal to this module is primitive is relatively easy. However knowing whether a function in another module is primitive is harder because the program gets it's information about external functions from the .hi file and the .hi file doesn't store whether a function was primitive or not.
It would be possible to add it, but messing about with the hi files isn't fun (trust me ;-)).
Hope that helps
Tom
Krasimir Angelov wrote:
Cool! Now I am able to compile the entire base package to IL code but there is still one problem. The byte code backend is using a special instruction for all primitives. I would like to try an another approach that will allow to call the primitives directly. For this purpose I need to now whether a given Id is an Id of a primitive. Is it currently possible? It is enough if there was any flag in the Info datatype. Any suggestions?
Krasimir
2006/1/17, Neil Mitchell
: code. Is it possible to remove the duplicated instances as well?
Yep, I removed them already - they were certainly a bug. It should be in the repo already.
The compiler detects duplicate class declarations (good), but supresses rename errors with the -redefine flag (bad, fixed now), and doesn't detect duplicate instance declarations (bad, unfixed).
Thanks
Neil
_______________________________________________ Yhc mailing list Yhc@haskell.org http://haskell.org/mailman/listinfo/yhc

Yes. I will do something similar. The PRIMITIVE instruction will be
replaced with a call to a specific static method. I thought, I can do
that each time when the primitive is called, since it isn't so
difficult (in .NET mode) to evaluate the arguments from the primitive
itself.
2006/1/18, Thomas Shackell
One thing to consider (that I forgot to mention) is that the compiler generates wrappers for primitives. Thus if you have Haskell code like:
aPrimitive primitive 1 :: Int -> Int
The code that is generated is a wrapper
FUN aPrimitive: PUSH_ARG 0 EVAL POP 1 PRIMITIVE [aPrimitive C code] RETURN_EVAL
It *is* possible to get away without the wrapper but it makes life quite hard, because you need to make sure that the arguments are evaluated before calling the primitive function.
You could of course do
FUN aPrimitive: PUSH_ARG 0 EVAL MK_AP [aPrimitive C code] 1 RETURN_EVAL
but this is both quite nasty and also less efficient.
Tom
Krasimir Angelov wrote:
Ok. Then I will follow the same way used in the bytecode backend.
2006/1/18, Thomas Shackell
: Hi Krasimir,
Great work with the .NET backend!
It wouldn't be easy. Knowing whether a function internal to this module is primitive is relatively easy. However knowing whether a function in another module is primitive is harder because the program gets it's information about external functions from the .hi file and the .hi file doesn't store whether a function was primitive or not.
It would be possible to add it, but messing about with the hi files isn't fun (trust me ;-)).
Hope that helps
Tom
Krasimir Angelov wrote:
Cool! Now I am able to compile the entire base package to IL code but there is still one problem. The byte code backend is using a special instruction for all primitives. I would like to try an another approach that will allow to call the primitives directly. For this purpose I need to now whether a given Id is an Id of a primitive. Is it currently possible? It is enough if there was any flag in the Info datatype. Any suggestions?
Krasimir
2006/1/17, Neil Mitchell
: code. Is it possible to remove the duplicated instances as well?
Yep, I removed them already - they were certainly a bug. It should be in the repo already.
The compiler detects duplicate class declarations (good), but supresses rename errors with the -redefine flag (bad, fixed now), and doesn't detect duplicate instance declarations (bad, unfixed).
Thanks
Neil
_______________________________________________ Yhc mailing list Yhc@haskell.org http://haskell.org/mailman/listinfo/yhc

I have to deal with another hack this time. See the comment from IExtract.hs: -- addPreludeTupleInstances is an efficiency hack. -- It takes a long time to parse the Prelude.hi file, and adding large -- numbers of tuple instances to the .hi file increases compile-times -- by 30% or more. -- Omitting them from the .hi file and adding them by hand here, therefore -- gives a big time saving. The problem is that all instances for tuples >3 aren't defined in the prelude but the required type declarations are injected explicitly in the IExtract.hs module. In this way no bytecode for them will be generated. In Data.Ix are defined Ix instances for all tuples with size up to 15. Since the Ix instance depends on Ord, when I am compiling these Ix instances the byte code will have references to the corresponding Ord instances but unfortunately they don't exist. This is reported as missing reference from the assembler. I have fixed that with some dummy instance declarations in Prelude.hs. Another problem is that sometimes the compiler is generating references to tuples with size 1. Of course this type of tuple doesn't exist and I again end up with unresolved references in the assembling phase. It seems like these tuples are generated from CaseLib.caseTuple but I still don't know how to avoid this. How are you dealing with these issues? Cheers, Krasimir

Krasimir Angelov wrote:
I have to deal with another hack this time. See the comment from IExtract.hs:
-- addPreludeTupleInstances is an efficiency hack. -- It takes a long time to parse the Prelude.hi file, and adding large -- numbers of tuple instances to the .hi file increases compile-times -- by 30% or more. -- Omitting them from the .hi file and adding them by hand here, therefore -- gives a big time saving.
The problem is that all instances for tuples >3 aren't defined in the prelude but the required type declarations are injected explicitly in the IExtract.hs module. In this way no bytecode for them will be generated. In Data.Ix are defined Ix instances for all tuples with size up to 15. Since the Ix instance depends on Ord, when I am compiling these Ix instances the byte code will have references to the corresponding Ord instances but unfortunately they don't exist. This is reported as missing reference from the assembler. I have fixed that with some dummy instance declarations in Prelude.hs.
I don't think I had to do anything special to do this, I believe it worked as normal, though I haven't actually checked ...
Another problem is that sometimes the compiler is generating references to tuples with size 1. Of course this type of tuple doesn't exist and I again end up with unresolved references in the assembling phase. It seems like these tuples are generated from CaseLib.caseTuple but I still don't know how to avoid this.
Yes this is a problem, I had to add size 1 tuple directly into the runtime. Thus no Haskell programmer can write something with a size one tuple but the compiler can still generate code that uses it. This is done in src/runtime/BCKernel/builtin/Prelude.c prim_addCon("1", 1, 0, CI_NONE); which adds a data type called "1" directly into the prelude dictionary (which makes sense since (,) is called "2" and (,,) is called "3"). I'm not sure how'd you do this in your setup, since you're compiling directly to .NET IL. One option is to get the compiler to 'know' that the type "One_" should be renamed "1". Then you could write data One_ a = One_ a Hope that helps. Tom

2006/1/19, Thomas Shackell
Yes this is a problem, I had to add size 1 tuple directly into the runtime. Thus no Haskell programmer can write something with a size one tuple but the compiler can still generate code that uses it.
This is done in src/runtime/BCKernel/builtin/Prelude.c
prim_addCon("1", 1, 0, CI_NONE);
which adds a data type called "1" directly into the prelude dictionary (which makes sense since (,) is called "2" and (,,) is called "3").
I can write a manually implementation for tuple of size 1 but I wonder wheter the generation of such tuples can be avoided. If you have to pass the (x) tuple to somewhere then you can simply pass the value of x instead. In addition all pattern matchings for (x) should be removed. Cheers, Krasimir

Krasimir Angelov wrote:
I can write a manually implementation for tuple of size 1 but I wonder wheter the generation of such tuples can be avoided. If you have to pass the (x) tuple to somewhere then you can simply pass the value of x instead. In addition all pattern matchings for (x) should be removed.
Cheers, Krasimir
Yes, the 1 tuple is entirely redundant, however, given the compiler uses tuples for every other size of dictionary it would be a nuisance to add lots of special case code in the compiler to optimise away the one tuple. Thanks Tom

Krasimir Angelov
I have to deal with another hack this time. See the comment from IExtract.hs:
-- addPreludeTupleInstances is an efficiency hack. -- It takes a long time to parse the Prelude.hi file, and adding large -- numbers of tuple instances to the .hi file increases compile-times -- by 30% or more. -- Omitting them from the .hi file and adding them by hand here, therefore -- gives a big time saving.
I wrote that comment (and the code it refers to).
The problem is that all instances for tuples >3 aren't defined in the prelude but the required type declarations are injected explicitly in the IExtract.hs module. In this way no bytecode for them will be generated.
Actually, the code for the instances is supposed to be generated by a 'deriving' clause on each tuple data declaration. In nhc98, the relevant source files are src/prelude/D[2..15].hs These deriving clauses seem to have disappeared in the move to a single Prelude file in yhc. Regards, Malcolm
participants (4)
-
Krasimir Angelov
-
Malcolm Wallace
-
Neil Mitchell
-
Thomas Shackell