How CodeHS is Adding New Programming Languages
By Andy Bayer, CodeHS Engineer
CodeHS recently announced support for Python 3, C, C++, Node, Scheme, and more. In this technical article, my goal is to shed some light on the CodeHS infrastructure and changes we made to support these new languages. To learn how to sign up for the Python 3 beta, check out our latest blog here.
It’s not a coincidence that CodeHS is able to support a lot of new languages all at once: there were some major infrastructure changes that have allowed us to add new languages more quickly and robustly than before.
Where Code Is Run
To understand the changes we’ve made, it’s important to understand the distinction between the “client side” and the “server side.”
When you’re using CodeHS, you are the client, and your computer is on the client side. The server side is the other end of the connection, and includes all of our servers, which the client talks to over the internet.
When you run an exercise on CodeHS, it can either be run on the client side (your computer) or on the server side (our servers). Some languages, like JavaScript, are designed to be evaluated on the client side. All of our JavaScript exercises, including Karel, are evaluated on the client side.
Other languages, like Java, run on servers. When you hit the “Run Code” button on a Java exercise, we send your code to a server, run it there, then send the result back.
Out With The Old
When we started running code on the server side, Java was the only language we taught that made sense to run on servers. We made assumptions when sending and executing code that made it difficult to do anything except run Java. Here’s a very simplified version of how our old servers worked:
The only thing this server knows how to do is compile and run Java code.
That means that even Python, a language that arguably should be run on a server, couldn’t run on our servers. To run Python, we transformed the code into JavaScript, then that JavaScript was run on the client side.
While this works, client-side implementations of languages sometimes lack features and each require their own unique interpreter. Even though many languages can be transformed to JavaScript and run in browser, doing so requires a lot of time and work to make sure it meshes properly with our site. There are some advantages to running code on the client side, but it was limiting our ability to expand what languages we offered.
In With The New
Now, our servers are incredibly general. They aren’t specialized for any language. Instead of implementing a system to run specific languages, we’ve implemented a protocol for evaluating commands on a server and receiving their output. Rather than sending code and expecting the server to know how to evaluate it, the server simply receives code and the command for how to execute it.
Here’s what that looks like in practice:
The important difference here is on line 4. We’re calling child.spawn(cmd, args)
which creates a process running any command passed as cmd
.
This is like thinking of the server as the CLI on your computer. Since you can run Java, C, C++, Python, Elm, Scheme, Erlang, Haskell, whatever on your computer, you can run all of those languages on the server, as well.
With this change, we’re able to add new languages quickly and simply, just by sending different cmd
s to our server (assuming it has that language installed). That cmd
could be python3
, python2.7
, scheme
, or anything else you can run on your computer. No matter what language it is, the server understands how to run it.
You can see this in action right now on CodeHS. Visit codehs.com/run to run Python3, Scheme, C, and C++ using this protocol.