Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines
(3 edits)

So…. here’s something really interesting. I don’t yet know exactly how useful this would end up being, but I thought I would share anyway.

There’s an open source project over at https://github.com/shinh/elvm which aims to be a C11 compiler for various esoteric languages, but what caught my eye was that it had JS and Lua backends in the source code. After some skimming, I realized it might be possible to make a Wren backend. It turns out not only was it possible, it was actually incredibly easy. So over the span of today, I got a simple C program compiling and running right inside of TM-16. It took some extra modification but I even got it to be able to call into external code (it’s kind of a huge hack, but it works).

Effectively it produces code that looks very similar to asm.js. It’s all pure Wren, but it takes a stdlib interface, a foreign function interface, and an array of numbers representing the “heap” as input, and performs a variety of low-level operations entirely on that heap array. The way I’ve implemented the backend, it even exposes all defined C functions and lets you call them with an arbitrary argument array, get a return value, that code can call into yours via the foreign function interface, etc.

Interfacing with it looks something like this:

import "kernel" for Shell
import "stdlib.wren" for Stdlib
import "test.asm.wren" for Module

class Program {
	construct new() {
	}
	
	main(args) {
		_heap = List.filled(1 << 24, 0)
		_module_test = Module.new(Stdlib, Stdlib, _heap) // at the moment, the first object is expected to define "putchar" and "getchar", and the second object is expected to define all of the external functions the C code is allowed to invoke
		
		Shell.printLn("Native module initialized!")
		
		var retVal = _module_test.main([]) // all functions return a single number. This can either be a simple atomic value such as a number, or it could be a pointer in which case it is an index into the heap array
		
		Shell.printLn("Result: %(retVal)") // in my simple test case it simply returned 100.
	}
}

What I’m debating on is whether it would be worth the effort to define a full enough stdlib interface that I could compile this compiler itself, and perhaps ship it with TM-16 as an optional C compiler. Is that something people might want?

EDIT: FWIW, C code compiled to Wren seems to run faster for reasons that are currently beyond my comprehension. A 1000 iteration C fibonnaci sequence runs about twice as fast as a hand-written Wren equivalent. I have no idea why that is, but it’s pretty cool nonetheless.