, we took our first step into the world of GHC, the Glasgow Haskell Compiler. We summarized the packages and tools we needed to install to get it building. We did this even in the rather hostile environment of a windows laptop. But, at the end of the day, we can now build the project with and create our local version of GHC. Last week make This week, we’ll establish our development cycle by looking at a very simple change we can make to the compiler. We’ll also discuss the architecture of the repository so we’ll can make some cooler changes next week. GHC is truly a testament to some of the awesome benefits of open source software. Haskell would not be the same language without it. But to understand GHC, you first have to have a decent grasp of Haskell itself! If you’ve never written a line of Haskell before, take a look at our for some tips on how to get going. You can also download our . Liftoff Series Beginners Checklist You may have also heard that while Haskell is a neat language, it’s useless from an industry perspective. But if you take a look at our , you’ll find tons of tools to write more interesting Haskell programs! Production Checklist Getting Started Let’s start off by writing a very simple program in . Main.hs module Main where main :: IO ()main = do putStrLn "Using GHC!" We can compile this program into an executable using the command. We start by running: ghc ghc -o prog Main.hs This creates our executable (or just if you’re not using Windows). Then we can run it like we can run any kind of program: prog.exe prog ./prog.exeUsing GHC! However, this is using the system level GHC we had to install while building it locally! which ghc/mingw/bin/ghc When we build GHC, it creates executables for each stage of the compilation process. It produces these in a directory called . So we can create an alias that will simplify things for us. We’ll write to be a "local GHC" command: ghc/inplace/bin lghc alias lghc="~/ghc/inplace/bin/ghc-stage2.exe -o prog" This will enable us to compile our single module program with . lghc Main.hs Hacking Level 0 Ultimately, we want to be able to verify our changes. So we should be able to modify the compiler, build it again, use it on our program, and then see our changes reflected in the code. One simple way to test the compiler’s behavior is to change the error messages. For example, we could try to import a module that doesn’t exist: module Main where import OtherModule (otherModuleString) main :: IO ()main = do putStrLn otherModuleString Of course, we’ll get an error message: [1 of 1] Compiling Main (Main.hs, Main.o) Main.hs:3:1: error: Could not find module 'OtherModule' Use -v to see a list of the files search for. |3 |import OtherModule (otherModuleString) |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Let’s try now changing the text of this error message. We can do a quick search for this message in the section of the codebase and find where it’s defined: compiler cd ~/ghc/compilergrep -r "Could not find module" ../main/Finder.hs:cannotFindModule = cantFindErr (sLit "Could not find module") Let’s go ahead and update that string to something a little different: cannotFindModule :: DynFlags -> ModuleName -> FindResult -> SDoccannotFindModule = cantFindErr (sLit "We were unable to locate the module") (sLit "Ambiguous module name") Now let’s go ahead and rebuild, except let’s use some of the techniques from last week to make the process go a bit faster. First, we’ll copy to . We’ll uncomment the following line, as per the recommendation from the setup guide: mk/build.mk.sample mk/build.mk BuildFlavour=devel2 We’ll also uncomment the line that says . This will restrict the compiler to only building the final stage of the compiler. It will skip past stage 0 and stage 1, which we’ve already build. stage=2 We’ll also build from the directory instead of the root directory. Note though that since we’ve changed our build file, we’ll have to boot and configure once again. But after we’ve re-compiled, we’ll now find that we have our new error message! compiler ghc [1 of 1] Compiling Main (Main.hs, Main.o) Main.hs:3:1: error: We were unable to locate the module 'OtherModule' Use -v to see a list of the files search for. |3 |import OtherModule (otherModuleString) |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ General Architecture Next week, we’ll look into making a more sophisticated change to the compiler. But at least now we’ve validated that we can develop properly. We can make a change, compile in a short amount of time, and then determine that the change has made a difference. But now let’s consider the organization of the GHC repository. This will help us think some more about the types of changes we’ll make. I’ll be drawing on written by Simon Peyton Jones and Simon Marlow. this description There are three main parts to the GHC codebase. The first of these is the compiler itself. The job of the compiler is to take our Haskell source code and convert it into machine executable code. Here is a very non-exhaustive list of some of the compiler’s tasks Determining the location of referenced modules Reading a single source file Breaking that source into its simplest syntactic representation Then there is the boot section. This section deals with the libraries that the compiler itself depends on. They include things such as low level types like or else . This section is somewhat more stable, so we won’t look at it too much. Int Data.Map The last major section is the Runtime System (RTS). This takes the code generated by the compiler above and determines how to run it. A lot of magic happens in this part that makes Haskell particularly strong at tasks like concurrency and parallelism. It’s also where we handle mechanics like garbage collection. We’ll try to spend most of our time in the section. The compilation pipeline has many stages, like type checking and de-sugaring. This will let us zero in on a particular stage and make a small change. Also the Runtime System is mostly C code, while much of the compiler is in Haskell itself! compiler Conclusion Next week we’ll take a look at a couple more ways to modify the compiler. After that, we’ll start looking at taking real issues from GHC and see what we can do to try and fix them! We’ll eventually take a peak at the submission process both with Github and Phabricator. If you want to start out your Haskell journey, you should read our ! It will help you learn the basics of this awesome language. For more updates, you can also to our monthly newsletter! Liftoff Series subscribe