Lykos
Lykos

Reputation: 1029

Compiler Integration Tests in Haskell

I am planning to write a little toy compiler in Haskell for a very simple language in order to reinforce my Haskell skills and have fun designing a new language. I am still thinking about some general decisions and one of the biggest open points is how I would do integration tests. I have the following requirements:

I also have the following optional requirements:

I have tried to find something that fulfills my needs, but I wasn't successful so far. The alternatives I considered are the following:

I am not sure yet which option I should choose and I still hope that I am missing a good solution. Do you have any idea on how I could create an integration test that fulfills all my requirements?

Upvotes: 10

Views: 347

Answers (1)

Erik Kaplun
Erik Kaplun

Reputation: 38227

I'm thinking unsafePerformIO should be quite safe here considering the programs should never interact with anything the testing environment/logic depends on, or, in other words, the compilation and execution should be viewable as a pure function in the context of testing in a controlled, isolated environment. And I reckon it's indeed useful to test your compiler in such conditions. And QuickCheck should then become an option even for blackbox testing. But some clearer minds could prove me mistaken.

So assuming your compiler is smth like:

type Source = String

compile :: Source -> Program

and your program execution is

data Report = Report Output TimeTaken OtherStats ...

execute :: Program -> IO Report

you could quite safely use unsafePerformIO to convert that into

execute' :: Program -> Report -- or perhaps 'executeUnsafe'
execute' = unsafePerformIO . execute

and then

compileAndExec :: Source -> Report
compileAndExec = compile . execute'

and use that with QuickCheck.


Whether execute invokes a subprocess, obtains an actual binary, executes that, etc, — or interprets the binary (or bytecode) in-memory, is up to you.

But I'd recommend separating byte code and binary generation: this way you can test the compiler separately from the linker/whatnot, which is easier, and also get an interpreter in the process.

Upvotes: 4

Related Questions