
Hi, I am not sure if I'm using DSL in the right context here but I am referring to those solutions that allow us to write code in Haskell and generate a target code source code of another language or even object code for that matter. I am aware of two ways of achieving this - 1. Implement functions that emit the target code - that is, when the Haskell code is compiled and run, the target code is emitted 2. Modify the Haskell compiler's back end to emit the code - that is when the Haskell code is compiled the target code is emitted I am not sure if there are more ways (hybrid perhaps) ... My question is, when would I chose one approach over the other? Regards, Kashyap

Hello,
I see no real reason to use the second approach, unless you're doing
something tremendously new and big. Besides, the first solution is much
easier and will be easier to maintain (in case the back end changes).
Kind regards,
Jasper Van der Jeugt
On Mon, Jan 4, 2010 at 6:14 PM, CK Kashyap
Hi, I am not sure if I'm using DSL in the right context here but I am referring to those solutions that allow us to write code in Haskell and generate a target code source code of another language or even object code for that matter. I am aware of two ways of achieving this - 1. Implement functions that emit the target code - that is, when the Haskell code is compiled and run, the target code is emitted 2. Modify the Haskell compiler's back end to emit the code - that is when the Haskell code is compiled the target code is emitted
I am not sure if there are more ways (hybrid perhaps) ...
My question is, when would I chose one approach over the other?
Regards, Kashyap
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

One argument for option 2 is to carry forward datatypes to the target
language. For example, if you want to describe a state machine with
the state as a type:
data StopLightState = Red | Yellow | Green
With option 1, values of type StopLightState will be resolved at
compile-time, not run-time. (yes, there's tricks to get around this,
but they're ugly)
I experimented briefly with option 2 using YHC, but quickly threw in
the cards for option 1.
It would be nice if GHC's internals were more accessible for this type of work.
On Mon, Jan 4, 2010 at 6:20 PM, Jasper Van der Jeugt
Hello, I see no real reason to use the second approach, unless you're doing something tremendously new and big. Besides, the first solution is much easier and will be easier to maintain (in case the back end changes). Kind regards, Jasper Van der Jeugt
On Mon, Jan 4, 2010 at 6:14 PM, CK Kashyap
wrote: Hi, I am not sure if I'm using DSL in the right context here but I am referring to those solutions that allow us to write code in Haskell and generate a target code source code of another language or even object code for that matter. I am aware of two ways of achieving this - 1. Implement functions that emit the target code - that is, when the Haskell code is compiled and run, the target code is emitted 2. Modify the Haskell compiler's back end to emit the code - that is when the Haskell code is compiled the target code is emitted
I am not sure if there are more ways (hybrid perhaps) ...
My question is, when would I chose one approach over the other?
Regards, Kashyap
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Mon, Jan 4, 2010 at 12:16 PM, Tom Hawkins
One argument for option 2 is to carry forward datatypes to the target language. For example, if you want to describe a state machine with the state as a type:
What do you mean "carry forward". Can you elaborate on your simple example? What about it requires option 2?
data StopLightState = Red | Yellow | Green
With option 1, values of type StopLightState will be resolved at compile-time, not run-time. (yes, there's tricks to get around this, but they're ugly)
I experimented briefly with option 2 using YHC, but quickly threw in the cards for option 1.
It would be nice if GHC's internals were more accessible for this type of work.
On Mon, Jan 4, 2010 at 6:20 PM, Jasper Van der Jeugt
wrote: Hello, I see no real reason to use the second approach, unless you're doing something tremendously new and big. Besides, the first solution is much easier and will be easier to maintain (in case the back end changes). Kind regards, Jasper Van der Jeugt
On Mon, Jan 4, 2010 at 6:14 PM, CK Kashyap
wrote: Hi, I am not sure if I'm using DSL in the right context here but I am referring to those solutions that allow us to write code in Haskell and generate a target code source code of another language or even object code for that matter. I am aware of two ways of achieving this - 1. Implement functions that emit the target code - that is, when the Haskell code is compiled and run, the target code is emitted 2. Modify the Haskell compiler's back end to emit the code - that is when the Haskell code is compiled the target code is emitted
I am not sure if there are more ways (hybrid perhaps) ...
My question is, when would I chose one approach over the other?
Regards, Kashyap
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Mon, Jan 4, 2010 at 9:41 PM, Luke Palmer
On Mon, Jan 4, 2010 at 12:16 PM, Tom Hawkins
wrote: One argument for option 2 is to carry forward datatypes to the target language. For example, if you want to describe a state machine with the state as a type:
What do you mean "carry forward". Can you elaborate on your simple example? What about it requires option 2?
Well in the case of Atom, it would be very convenient to write code like this: data StopLight = Red | Yellow | Green changeLight :: V StopLight -> Atom () changeLight light = light <== light' where light' = case value light of Red -> Green Yellow -> Red Green -> Yellow The problem is the case expression is evaluated at compile-time, when what we really want is to "carry forward" the case expression to the run-time environment (aka. the generated code). This example illustrates the use of a simple enumerated type. But full-blown algebraic data types would also be useful in the run-time. For example, a Maybe type could be used to represent a valid signal: Just validValue or Nothing if the signal is invalid. Of course this is not a limitation if the run-time and compile-time is the same environment, i.e. Haskell. However, if the target is a different language, such as C in the case of Atom, then the full power of algebraic data types are lost with light embedded domain specific languages.

To start with, can you clarify that you are looking for an Embedded DSL
(sometimes called Light Weight DSL)?
A _proper_ DSL has its own interpreter/compiler where an EDSL/LwDSL
leverages the compiler of a host language (in this case, Haskell).
Assuming you're referring to an EDSL, I'll respond. :)
I don't think the second option is ever used. Modifying the compiler backend
doesn't seem to make a lot of sense to me. I'm not aware of any circumstance
where this has been done.
Your first option is closer. Generally, when emitting some sort of target
code from a large EDSL, you'll have two stages. Your first takes the
embedded syntax of your EDSL and converts it to an Abstract Syntax Tree.
Your second stage accepts the AST as input and emits target code.
Take Tom Hawkins' Atom EDSL as an example. When we write Atom code, we're
building up an AST. After the AST is built up, the "compile" function
converts the AST to C code.
For smaller EDSLs, it's more than possible to have the functions themselves
emit the code we're after (rather than relying on an AST and compile
function).
Is this what you're looking for?
/jve
On Mon, Jan 4, 2010 at 12:14 PM, CK Kashyap
Hi, I am not sure if I'm using DSL in the right context here but I am referring to those solutions that allow us to write code in Haskell and generate a target code source code of another language or even object code for that matter. I am aware of two ways of achieving this - 1. Implement functions that emit the target code - that is, when the Haskell code is compiled and run, the target code is emitted 2. Modify the Haskell compiler's back end to emit the code - that is when the Haskell code is compiled the target code is emitted
I am not sure if there are more ways (hybrid perhaps) ...
My question is, when would I chose one approach over the other?
Regards, Kashyap
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thanks Jasper ... Thanks John, While most of the use case I had in mind seems to fit the EDSL description, I had some in the proper DSL category as well... So, my prejudice had been towards option one - and I was unable to visualize a situation where option 1 would not work - or become too problematic or option 2 becomes too simple. I was just thinking of implementing an OS kernel (monolithic to start with) using Haskell - via option 1. Then again, if I understand right, House was done by modifying GHC ... So, I guess it'll help me if I can see some example situations where modifying GHC's back end would be a better/only option. The main reason I am asking this is to make sure I don't miss out some obvious pitfall in my OS implementation via option 1. Regards, Kashyap > >From: John Van Enk>To: CK Kashyap >Cc: haskell-cafe@haskell.org >Sent: Mon, January 4, 2010 10:51:06 PM >Subject: Re: [Haskell-cafe] A question on DSL's > > >To start with, can you clarify that you are looking for an Embedded DSL (sometimes called Light Weight DSL)? > > >A _proper_ DSL has its own interpreter/compiler where an EDSL/LwDSL leverages the compiler of a host language (in this case, Haskell). > > >Assuming you're referring to an EDSL, I'll respond. :) > >I don't think the second option is ever used. Modifying the compiler backend doesn't seem to make a lot of sense to me. I'm not aware of any circumstance where this has been done. > > >Your first option is closer. Generally, when emitting some sort of target code from a large EDSL, you'll have two stages. Your first takes the embedded syntax of your EDSL and converts it to an Abstract Syntax Tree. Your second stage accepts the AST as input and emits target code. > > >Take Tom Hawkins' Atom EDSL as an example. When we write Atom code, we're building up an AST. After the AST is built up, the "compile" function converts the AST to C code. > > >For smaller EDSLs, it's more than possible to have the functions themselves emit the code we're after (rather than relying on an AST and compile function). > > >Is this what you're looking for? > > >/jve > > >On Mon, Jan 4, 2010 at 12:14 PM, CK Kashyap wrote: > >>>Hi, >>>>I am not sure if I'm using DSL in the right context here but I am referring to those solutions that allow us to write code in Haskell and generate a target code source code of another language or even object code for that matter. I am aware of two ways of achieving this - >>>> >>1. Implement functions that emit the target code - that is, when the Haskell code is compiled and run, the target code is emitted >>>>2. Modify the Haskell compiler's back end to emit the code - that is when the Haskell code is compiled the target code is emitted >> >>>>I am not sure if there are more ways (hybrid perhaps) ... >> >>>>My question is, when would I chose one approach over the other? >> >>>>Regards, >>>>Kashyap >> >> >> >> >> >>>>_______________________________________________ >>>>Haskell-Cafe mailing list >>Haskell-Cafe@haskell.org >>http://www.haskell.org/mailman/listinfo/haskell-cafe >> >
participants (5)
-
CK Kashyap
-
Jasper Van der Jeugt
-
John Van Enk
-
Luke Palmer
-
Tom Hawkins