
Ferret: a Lisp implementation for real time embedded control systems - tosh
https://github.com/nakkaya/ferret
======
garganzol
Where is the source code of a compiler? It looks like it's written in Java but
there are no source code files in corresponding GitHub repo.

~~~
phoe-krk
_ALL_ of the code seems to be stored inside the org-mode file,
[https://github.com/nakkaya/ferret/blob/master/ferret.org](https://github.com/nakkaya/ferret/blob/master/ferret.org)
\- which is the most unusual form of source code organization that I have ever
seen.

~~~
antt
There's singles of us!

If you want to extract it run M-x org-babel-tangle and you will end up with
the usual source files and directories installed relative to the location of
the org file.

I doubt there's a dozen people in the world that do it. But it is surprisingly
useful and powerful when you get used to it. If anyone in Melbourne is
interested in learning about this I have been toying with the idea of running
a workshop on it.

I'm in the process of getting the detangle working for noweb mode. The current
implementation fakes it with regex which force you to write code linearly
instead of literately. But even if you can't detangle arbitrarily nested code
it's magic to see changes in a source file appear in the right source code
block.

~~~
Touche
How do you deal with having to scroll such a large file? That's the biggest
turn-off to literate programming for me. I don't like code files more than a
couple hundred lines of code. Search isn't enough for me.

~~~
Jtsummers
Org mode will let you collapse trees and source blocks. You can also narrow
the view to a sub tree. This makes navigation much easier.

~~~
heavenlyblue
So how is navigating the file tree any different from navigating the source
code tree?

Just don’t tell me “you can see the context” as any proper codebase would
probably not be linear in code flow anyway.

~~~
Jtsummers
I mean, it isn't, if you organize your file identically to the source tree.
But I break it out differently when I use this approach. I'll use the noweb
references and scatter my code across the document in a logical way that's not
reflective of the generated source tree.

For instance, I group all _include_ or equivalent statements in an appendix,
rather than within the primary code discussion. If a block of code can't be
directly reused, but for some reason needs to be in every (or several) source
files (think standard boilerplate), I'll write it once in a place that makes
sense, and reference it from all the places where it actually gets tangled
into the output.

Additionally, I include the Makefile (or whatever equivalent) and other
scripts within this same document. Learning docker? Make a dockerfile in here,
fully annotated, along with the shell commands to actually deploy it.

Mine will only mirror the original source tree if it's:

Very simple.

I've imported a bunch of code into it and don't, yet, know how to break it
down.

An example C project may look like:

    
    
      * Purpose Statement
      * README
      * Usage
      This program can be executed from the command line by calling:
      #+BEGIN_EXAMPLE
        $ ./foo
      #+END_EXAMPLE
      It accepts the following command line parameters:
      - =-c= :: something
      - =-d= :: something else
      ** Implementation
      To process the command line flags we use <some library>.
      it has the following API calls...
    
      Here's the code for processing our commands...
      * Business Logic
      We communicate with the server via some REST API described in <location>
      and <library> to make the calls.
      -- Here I'd intermingle the REST API I'm using and the C API I'm producing
      -- for my own consumption, or something similar.
      * Code that's not fully organized yet
      ** Main Function
      This is the entry point, blah, blah, blah:
      #+BEGIN_SRC c :noweb yes :tangle src/main.c
      #+END_SRC
      * Appendix: Includes

------
nanomonkey
The first time I came across this it was touted as Clojure that compiled down
to C++11. Now I'm seeing it listed as a generic lisp. I'm curious if that's
due to the limitations of writing for embedded systems (using d-list instead
of hash tables, memory management, etc.) or are there other deviations?

~~~
kimi
IIRC it used to be a fairly complete reimplementation of Clojure. I toyed with
the idea of using it to cross-compile to Golang.

------
bsder
Given that this seems to be a transpiler, why go to C++ instead of C?

What feature of C++ does this need that is so compelling as to cut it off from
use on straight C?

~~~
nakkaya
If I were to go with C I would have to reimplement OOP machinery required for
an object system. OOP also makes memory management a non issue. Functions are
first class citizens in Lisp so functors/lambdas makes it real easy to create
closures. std::atomic combined with Clojure semantics makes sure there no race
conditions. std::thread / std::future makes multi threaded programming much
easier. Templates help with picking and choosing which components to include
(i.e there are multiple memory managers to pick from.). etc. etc. Non of the
above is essential and can be done in C but why bother, GCC/LLVM people are
much better at this then I can be including platform specific tricks for
different architectures. Modern C++ is very close to Lisp after all it only
takes 6 passes over the Clojure code to generate C++ code. (Compiler makes
more than 6 passes but others are for optimization.)

------
BrendanD
[https://ferret.pmel.noaa.gov/Ferret/](https://ferret.pmel.noaa.gov/Ferret/)

