
Statically typed functional programming language implementation with Go and LLVM - kristianp
https://github.com/rhysd/gocaml
======
knocte
From the description in the README file:

"GoCaml is subset of OCaml in Go based on MinCaml using LLVM. GoCaml adds many
features to original MinCaml. MinCaml is a minimal subset of OCaml for
educational purpose. It is statically-typed and compiled into a binary."

What do they mean with "GoCaml is subset of OCaml in Go"? Do they mean the
compiler is written in Go?

~~~
bitwalker
Yes, the compiler is written in Go, and implements a subset of OCaml, the
language.

------
bitwalker
This is well timed! I've been starting work on my own strongly-typed
functional programming language using Go + LLVM, and this looks like a great
reference for implementing some of the parts I hadn't yet thought out. Though
I'm not going the OCaml/MinCaml route, it's still extremely useful to see some
of the key compiler stages implemented, since it helps give me a guideline for
what has worked for others. Thanks for posting!

~~~
unboxed_type
What is your motivation behind that activity?

~~~
bitwalker
Mostly for my own edification/enjoyment. It's something I've wanted to do for
a long time, and once you have that itch, it's just a matter of time. I've
built some toy compilers before, but this project I'm aiming a lot higher to
see if I can combine some recent research in type theory (algebraic subtyping
as an extension of ML-style type inference, effects) and the bits of languages
that I would really love to see meshed together (rich pattern matching,
including pattern matching on binary data, macros, zero/low-cost abstractions,
Erlang-style concurrency with actors/supervision/transparent distribution) and
see if I can still find a sweet spot where the language is still approachable,
has good tooling, etc. I've accumulated a lot of research and notes, but only
recently started working on an actual implementation. At this point nothing is
set in stone, since I'm not certain all of those things are actually
compatible in a single language, but those are the goals I have in mind for
now, so we'll see where it takes me.

As for why I chose Go, I wanted something which was pretty portable, with
decent performance, easy to build command line tooling in, but at a slightly
higher level of abstraction than C; that way I could conceivably port it to C
or C++ relatively easily if I felt like that was a better way to go down the
road, but could mostly focus on getting things done in the short term. I'm not
a huge fan of the OCaml toolchain, even though I like the language, and it's
not very approachable for other people if they wanted to pitch in. Go isn't an
ideal language to build a compiler in, but it's not bad either. I'm
comfortable with it though, and that's all that really matters for a project
like this.

~~~
iagooar
Are you the same bitwalker, responsible for all those great Elixir libraries
and Docker images? Wanted to say thank you :)

~~~
bitwalker
I am! Thanks for the kind words! I don't hear from people using my stuff too
often, so it's always good to get some positive feedback :)

~~~
iagooar
You're most welcome :) Thank you again for doing a great job, offering your
time and brain to improve the Elixir community! I certainly benefit a lot from
Distillery and the Docker images that you always keep up-to-date.

------
amelius
Does anybody have a good reference on how to implement inlining and beta
reductions efficiently (efficient at both compile time and run-time)?

I've found SPJ's paper but I find it a bit of a grab-bag of ideas (difficult
to see how to implement it step by step instead of all at once).

~~~
Ono-Sendai
I don't have a reference, what in particular are you unsure about? In my code,
for inlining, I do something like

* Replace function application (function call) expression with body of inlined function

* Now replace all variables in the target function body with the argument values from the func expr

* Re-bind all variables.

(Some details elided :) )

The trickiest aspect of inlining is deciding what to inline.

~~~
amelius
Well, I have a deeply nested tree of let blocks intermixed with lambda
abstractions (my front-end, which uses a continuation passing style, generates
very inefficient code). If I alternate between beta-reductions and inlining,
then I need to do many passes to end up with something small and sensible (and
this takes a lot of time). So, I guess I have to do both types of steps in a
single depth-first pass. I'm about to rewrite my optimizer this way, so I
thought perhaps I'd better read up on it first to prevent unnecessary work :)

Yes, checking what to inline is tricky, but I'm not there yet; my code is
still very simple and everything can be inlined in principle (unless of course
intermediate results would cause problems, which I'm not sure about).

~~~
Ono-Sendai
Ok, I think I see the problem. What about traversing down to as deep as
possible, then walking up the AST inlining as you go? This should allow
processing in a linear time in the number of nodes, with a single pass.

~~~
amelius
Hey, thanks for the reply. I'm already doing something like that. The problem
is that I also have to do the beta-reductions (i.e. reduction of function
applications), and I'm not sure what order is best.

------
agumonkey
not to be confused with JoCaml
[https://en.wikipedia.org/wiki/JoCaml](https://en.wikipedia.org/wiki/JoCaml)
;)

~~~
mapletree
which is not to be confused with
[https://en.wikipedia.org/wiki/Joe_Camel](https://en.wikipedia.org/wiki/Joe_Camel)

------
ElectronShak
This is nice.

