JFuncMachine

JFuncMachine is a library providing an intermediate language for code generation, with the idea that it could be used as a back-end for a compiler. Although it was designed with functional languages in mind, it should support imperative ones, although it currently lacks some features like a looping construct that might be more suitable for imperative languages.

The JFuncMachine github repo is at: https://github.com/JFuncMachine/JFuncMachine.git

Why does JFuncMachine exist?

There are many levels to creating a compiler for a language, and over time there are more and more tools to help at various levels. There are a wide variety of parsing tools, for example. On the back-end, the Java Virtual Machine could be considered such a tool, since it abstracts the hardware details away into a simple stack-based byte-code machine. Similarly, LLVM provides an abstract machine that can target many different hardware architectures with finer-grained access than is possible with the JVM.

Compilers often use intermediate languages for code generation. For example, Haskell has several intermediate languages, the final two being STG (the spineless, tagless G-machine) and then CMM (C–). Idris and Racket use Chez Scheme as an intermediate language, and Chez Scheme does the native code generation. Racket itself is designed to be used as an intermediate language and contains many features that make it easier to develop languages.

There are already intermediate language options for the JVM. Clojure, for example, generates and loads JVM byte code on-the-fly, but also provides a :gen-class construct to generate .class files. It is also possible to use Java itself as an intermediate language, and just have the compiler generate Java code and use the JDK to compile it.

JFuncMachine is not a programming language on its own. Instead, it provides many of the kinds of code structures you need (if statements, variable bindings, functions, lambdas, try-catch blocks, method calls). The idea is to allow you to mix and match these to implement your own language, potentially doing things that another intermediate language might not support. You can also extend JFuncMachine with your own classes to create new constructs. The layers of your compiler might be:

  • Parse the input file and create an abstract syntax tree (AST)
  • Perform type checking and other validations on the AST
  • Convert the AST into JFuncMachine structures
  • Use the JFuncMachine class generator to create a .class file

Additional Tools

While JFuncMachine focuses on generating Java byte code, it includes a few utilities for upper levels of a compiler.

S-expressions

JFuncMachine contins a simple S-expression parser in org.jfuncmachine.sexprlang. An S-expression (symbolic expression, sexp or sexpr) is way of representing an expression that is fairly easy to parse. If you have seen Lisp or Scheme code, those are S-expressions. Normally, when you write an algebraic expression like 3 * 4 + 5, there are precedence rules so you know to do the multiplication first, then the addition. That kind of expression is referred to as “infix”, the operation is in-between its operands. S-expressions use a prefix notation, where the operation always comes first, that removes the requirement to specify precedence rules.

The S-expression version of that expression is (+ (* 3 4) 5) - that is, call the plus function with two arguments, the first of which is the result of calling the multiply function with 3 and 4, and the second of which is 5. A language that uses infix notation usually ends up converting the expression into something similar to an S-expression.

For completeness, there are languages where expressions use a postfix notation where the operation comes last (FORTH, Postscript). The FORTH version of the expression would be 3 4 * 5 +.

There is a parser in the parser package that returns S-expressions, and also a mapper that allows you to automatically map S-expressions to Java classes using a @ModelItem annotation. These may be useful in prototyping your language.

Unification

If your language is using something like Hindley-Milner type unification, the org.jfuncmachine.util.unification package contains some utilities to help with the unification process, although you still need to decide which types need to be unified. The example Minilang language in org.jfuncmachine.examples.minilang uses type unification. There will be documentation available for it on this site.

On this site you will find an overview, some examples, and Javadocs for the library.