Let’s write a Chip8 emulator in Kotlin [Part 2: The first refactoring]

Disclaimer

This series is a means for me to learn Kotlin. As such i might misuse some features of Kotlin, not follow best practices or simply to silly things. Please always check the comment section for feedback from more knowledgable people. I’ll also have follow up articles where i refactor the code to be more idiomatic. So, make sure to check back.

Refactoring

Part of learning a new language is to get to know the idioms. Thanks to feedback on the last articles, i have a pretty good idea how to reorganize the code to make it more maintainable and concise. Let’s get going.

Moving things around

In the previous article we created a few top-level methods, loadRom, decode, and disassemble. I put them in different files. Let’s clean that up. We want a single file that contains the top-level methods that make up the functionality of the emulator. (Chip8.kt).

That cleans up the files Disassembler.kt, main.kt. I think i’ll make it a habit to put top-level functions of a package into a file named after the package itself.

Extension properties instead of extension methods

We added a few extension methods to Int and Byte in the previous article. Ioannis Tsakpinis of LWJGL fame and avid Kotlin user pointed out a better way to handle these extensions. We’ll make them extension properties instead of extension methods (Extensions.kt):

I renamed the properties to shower names and fixed up any code relying on the old extension methods accordingly. This makes our decode function a lot more concise, e.g.

turns into

It also cleans up our Disassembler, which is our next refactoring victim.

Shorter single line methods

Disassembler is composed of single line methods for the most part. We can omit all the curly braces and new lines, turning

into

As per the definition of Decoder implemented by Disassembler, all of these methods need to return Unit. For Disassembler#before and Disassembler#unknown we can’t just apply the single line style. Remember, the return type of a single line style function is the type of the expression of that single line. In case of these two methods, we call StringBuilder#append, which returns the StringBuilder. That is obviously not of type Unit.

We can apply a trick pointed out by Andrey Breslav of Kotlin fame: create an Extension method called unit that returns, you guessed it, Unit. Let’s modify Disassembler.kt:

Note the fun Any?.unit() {} extension method. It’s attached to any object (!= null) within the scope of Disassembler (i think). We can then rewrite the before and unknown methods to single line style, calling unit() to make the expression’s type Unit in accordance to our Decoder trait.

You can see the entire refactoring diff on Github.

Up Next

Next time we are going to write our first iteration of a simple interpreter.

Previously

Let’s write a Chip8 emulator in Kotlin [Part 0: Motivation & Setup]
Let’s write a Chip8 emulator in Kotlin [Part 1: A simple Disassembler]

Following Along

  1. Install the required tools (JDK, IDEA, IDEA Kotlin plugin, Git)
  2. Clone the repo: git clone https://github.com/badlogic/chip8.git
  3. Checkout the tag for the article you want to work with: git checkout part2
  4. Import the project into IDEA (Open Project, select build.gradle file, select "Use customizable gradle wrapper"

2 thoughts on “Let’s write a Chip8 emulator in Kotlin [Part 2: The first refactoring]

  1. Indeed, unit() will only be available inside Disassembler’s scope. This way each class can have its own internal “DSL” without polluting any external scope.

    Another useful detail to keep in mind is that it’ll also be available in extension functions and extension function literals with a Disassembler receiver type.

Leave a Reply

Your email address will not be published.