Nocaml is a compiled, nearly pure, functional programming language
with a lightweight runtime that includes a precise compacting garbage
collector. Nocaml is well-suited to use in embedded systems by
virtue of having a very small and space-efficient runtime.
Nocaml’s reference compiler is implemented in Ruby, and it can
convert a Nocaml program into C code for efficient
execution. Nocaml also supports strong static type checking by
conversion to OCaml.
Since it compiles to C, Nocaml achieves superior performance to
typical interpreted runtimes for embedded systems. Granted, Nocaml
is currently somewhat slower than OCaml (when both are compiled to
native code). Below is a comparison of the performance relative to
OCaml on a basic non-mutating list-based quicksort program:

The OCaml code was run with OCAMLRUNPARAM=h=201326592,o=4000 to
completely remove GC memory pressure during the
computation. Instead, a GC cycle was forced at the end of the
quicksort calculation to mimic Nocaml’s behavior of GCing before
returning to native code. For some reason, Nocaml exceeds OCaml
performance on two data points. While the rest of the data points are
all slower than OCaml, Nocaml manages to stay above 75% of
OCaml performance in all cases.
Future work to improve garbage collector performance in Nocaml is
planned.
Nocaml supports:
ML-like data-types with constructors (currently defined via Ruby
code).
a slight generalization of ML in which objects may be of any constructor of any type. If this is used, strong static type checking is no longer possible.
Nocaml doesn’t support:
partial function application (the absence of partial function
applications is enforceable in the OCaml-based static type
check). Naturally, it is possible to define functions that
essentially perform partial function application, but they must be
used explicitly not implicitly.
fancy multi-level match as in OCaml. Instead one can switch over
the possible constructors for one expression via a case statement.
macros (but there are plans to allow macros implemented in Ruby as
AST transformations).
Nocaml supports x86_64 (SYSV calling convention) and 32-bit
MIPS (O32 with ABICALLS). Support for additional platforms is
relatively easy to add – there are just two simple functions that
need to be written in assembly.
You may be wondering, how is Nocaml able to do precise garbage
collection on a C program? The trick is that the C code output by
Nocaml manipulates only pointers, not arbitrary integer values. Thus
a stack location that has a value that appears to point into the heap
can be assumed to actually be a pointer and subject to adjustment if
the heap object it points to is relocated. Actually, “small” integer
values and pointers into static memory are also manipulated but these
are thankfully not problematic. The drawback to this approach is that
it is only possible to manipulate integers through builtins via
function calls that cannot be inlined.
Nocaml is made available under the terms of the MIT license. The
source code for the project is hosted on Github, click
here to access it.
Check out the FAQ and the QuickStart pages.