Hacker News new | past | comments | ask | show | jobs | submit login
Ferret: a Lisp implementation for real time embedded control systems (github.com/nakkaya)
135 points by tosh on July 31, 2018 | hide | past | favorite | 36 comments



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.


ALL of the code seems to be stored inside the org-mode file, https://github.com/nakkaya/ferret/blob/master/ferret.org - which is the most unusual form of source code organization that I have ever seen.


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.


So you're doing literate programming with org-mode. That's pretty nifty.

I'm on the opposite side of the planet but I'd be interested, if you did an article or video on whatever you would teach in the workshop.


I know the rather spiffy project http://thi.ng uses org mode for literate programming and web site generation all from the source code. It doesn't seem to be all one big file, but I think each component may be a file.


Been doing emacs config in org for a long time. I think it's more common than you think, at least for that purpose.


Quite possibly, outside of a post every two weeks or so on HN I have never met anyone else who uses it.

Though I have met a few people who use org mode as an organizer/planner.


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.


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.


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.


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


That it's not different is kind of a good point?

Some people use several Emacs windows (or frames or whatever) but all of them peeking into the same file, but in to different locations of it.


If it's all the same, why use separate files?


When your IDE (or Emacs in this case) offers go jumping/searching functionality, it doesn't really matter how many files your code is in. When I used bare vim, I cared a lot more about code organization than I do with an IDE that makes jumping around the codebase easy.


That's called literate programming. Maybe the most famous example is the source code for TeX, a single ~25,000 line file (http://tug.org/texlive/devsrc/Build/source/texk/web2c/tex.we...) that can be used to make a TeX compiler, or produce a book explaining the implementation.


I actually just started dong this a few days ago and I’m loving it so far. I have it configured so that every time I save, emacs runs org-tangle and all my code ends up in the proper directories but I never have to touch it there, I can just stay in org mode and keep different ‘files’ of code in different collapsible sections making moving around much easier!


Look at org-babel-detangle and have your mind blown[0].

[0] Mostly, the current implementation works only with source blocks that are linearly added one after the other and don't use the <<noweb reference>> in code blocks.


I had a similar setup, but ended up coding a toggle for it, as it can get rather long as your source grows. In case you find it useful:

        ;; Tangle Org files when we save them
    (defun toggle-org-tangle-on-save()
      (interactive)
      (if (bound-and-true-p org-tangle-on-save)
          (setq-local org-tangle-on-save nil)
        (setq-local org-tangle-on-save t))
      (message (if org-tangle-on-save "Enabled tangling on save" "Disabled tangling on save")))


Using org-mode for literate programming isn't entirely unheard of.


I guess I had never seen literate programming taken to such an extreme before. This was an actual surprise for me.


This has been my go-to way of programming anything where I'm the primary person responsible for it.

With pandoc you get a system that can export to any format under the sun. The highlight so far was exporting a problematic code portion with the literate explanation around it and a pretty basic asymptotic analysis in latex to docx, code highlighting, math formulas, tables all worked without human intervention. It ended up in a power point that I'm told was very well received.


Just curious, how does github manages to render org files so flawlessly, including embedded code snippets. I thought emacs was the only popular environment supporting org files.


Github seems to play quite well with Org. Little known fact: If you give your repo a README.org instead of a README.md, github will show that file just like how it shows a regular README.md.


Unfortunately, the same can't be said of Bitbucket. At one point I voted for or commented on a feature request for it, and I pretty routinely get notified when someone else discovers the lack of org-mode support on Bitbucket.

At this point, I'm convinced Atlassian hates happiness, or there is some shameful architectural reason why they cannot support more than Markdown for their READMEs. Given the number of vociferous responses to that feature request, there would appear to demand.


> I thought emacs was the only popular environment supporting org files.

Pandoc has a pretty decent Org Mode parser and writer.


There's a "building from sources" section on https://ferret-lang.org/, but I could not easily detect where the source is on github.

Update: It needs to be extracted from an org file, and by default Github renders the org file so that the source is not visible.


Or click the "raw" button on the github source page.

https://raw.githubusercontent.com/nakkaya/ferret/master/ferr...


Do you not see all the source code in https://github.com/nakkaya/ferret/blob/master/ferret.org?


It's in ferret.org, apparently.


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?


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


You are right. It is due to limitation of writing for embedded systems. I try to keep everything as close to Clojure as possible but some stuff is just not possible on embedded systems or behave a little bit different.


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?


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.)


Maybe that's a solved problem so that was outside the scope/focus? https://isocpp.org/wiki/faq/compiler-dependencies#convert-to...





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: