Hacker News new | past | comments | ask | show | jobs | submit login
PilOS โ€“ A Stand-Alone Operating System (picolisp.com)
110 points by daveloyall on June 19, 2015 | hide | past | web | favorite | 54 comments

Oddly enough I've been looking for a REPL that I can stick on a microcontroller. MicroPython is a candidate, and in fact I have one of the boards from the original Kickstarter. I looked into PicoLisp but see that it doesn't support floating point numbers. In fact I don't even know if floating point is "supposed" to be part of Lisp at all, and have read some comments to the effect that it might be frowned on by some. But my intended use would really benefit from it.

I tried adding floating point support to a small Lisp or Scheme interpreter (can't remember which one), and quickly got lost, as I'm not a great programmer.

This definitely looks cool, and I will play around with it. Maybe it's nostalgia, but I grew up with computers that booted into the BASIC prompt, so it brings back the fun of exploring computers for me.

It's not just Lisp, but it includes pilog, a built-in Prolog, a database and coroutines. PicoLisp is an amazing piece of work by essentially one man, and has been used in real-world database applications since the late 1980s. They were trying to build hardware to run it, hence PilMCU, but too much inertia has lead now to PilOS. Yeah, PilOS!

Now to get Shen running on PicoLisp after Alex adds networking!

> Now to get Shen running on PicoLisp after Alex adds networking!

That shouldn't be an issue :)

If you want to have a REPL on something like a microcontroller, there's a tool designed especially for that: Forth. You're going to find an implementation for any chip and platform you can think of (Forth is 40 years old and simple enough to be trivially portable to almost anything). Forth is strange and feels archaic at first, but I'd say it's roughly on par with Lisp in terms of expressivity and much better suited for systems with constrained resources than Python.

Interesting. Which microcontrollers are you considering? I didn't know about MicroPython but it's kind of blowing my mind; I mean, it feels weird to dynamically allocate anything in a microcontroller.

MicroPython was originally written for an ARM chip. Since then it's been ported to a number of other systems. What I do know is that it requires a fairly "big" micro. I have a particular interest in PIC chips, but would be happy with any version where I could compile and load the program on a circuit that I'm capable of building myself.

I have tried downloading and compiling large C programs in the past, and it's one of those things where if it works, great, but if the basic "make" comes back with an error for some reason, then I'm kinda lost. My experience with C programming has tended to be with programs numbering no more than a few hundred lines, that all fit in one file and didn't need any kind of "interesting" build process.

Wow, talk about a weird set of customer requirements. ;-)

These micro's have a fair amount of RAM, and the C compilers support memory management, e.g., basics such as malloc() and free(). I suppose somebody could even implement garbage collection.

In case you aren't aware of them, eLua [1] or PIC32Lua [2] may fit your needs.

  1. http://www.eluaproject.net/overview/status
  2. https://github.com/FMMT666/PIC32Lua

Also picobit for scheme goodness: https://github.com/stamourv/picobit

Doesn't support full numeric tower (no floats), but does implement 'unbound precision integers'. See ยง5.1 of this paper: http://www.iro.umontreal.ca/~feeley/papers/StAmourFeeleyIFL0...

That looks quite interesting. Thanks! I've actually got some PIC32 chips left over from another project.

I think MicroPython would be the best fit for your requirements, both because of the REPL, which really simplifies programming, and because the simplicity of python(i heard of quite a few guys that couldn't manage c , but we're fine with python).

On the other hand, why not the arduino ? there's no build process , plenty of documentation and libraries, and a reasonable chance you'll find some design close to yours.

So far I'm leaning towards the MicroPython. In fact, Python is my language of choice du jour, but I enjoy keeping my eye out for other possibilities.

At the same time, I've been using Arduino, and also have a fair amount of experience programming Microchip's MCU's in C. I'm actually fine with C, but not so good at wrapping my head around large programs that other people have written. This is probably because I've always been a lone wolf programmer.

The reasons why I want an interpreter on a micro is for some strictly hobby projects that require programmability on board. I started planning an absurd DIY pocket calculator, and actually ggot as far as writing my own parser and expression evaluator in C. But a programmable calculator that uses Python or even Lisp would be a fun novelty.

If you want a real trip check out leJOS - a JVM for the Hitachi H8 based Lego RCX (and now the much less esoteric ARM-based NXT bricks).

Older still is BrickOS.

Back in 2003, in grade 11, I built a LEGO robot that played the game Connect 4, compiling a mixed C/asm minimax implementation for the RCX via a cygwin toolchain. I can't find pictures of the actual competition, but there's a single pic from a hobby show where it was exhibited:


Sometimes not knowing what's impossible is a really good thing.

Microcontrollers haven't really become 64-bit yet.

Also this project looks very PC-oriented in other ways (virtual memory management, VGA screen output, keyboard - all of them are PC and no microcontroller devices)

You might be better off starting with a different, more portable, project. As klibertp said, Forth is a possibility. I remember one guy writing a 'Forth bootstrapping framework' called BootForth [1] sometime in 2008, which unfortunately since disappeared off the net, but you may have luck inquiring for the sources.

[1] http://compgroups.net/comp.lang.forth/forth-bootstrapping-fr...

There's several Scheme implementations now built for microcontroller/embedded use, Picobit for example: https://github.com/stamourv/picobit

Check out OSkit [1]. It was designed for people experimenting in OS's who might not want to reimplement all the low-level crap like memory management. It's been used in high-level language OS's from LISP to ML.

[1] http://www.cs.utah.edu/flux/oskit/

Do you know how this deals with drivers? Those seem to be the main impediment to making any useful new OS.

You can use the NetBSD drivers for other operating systems pretty easily - see http://rumpkernel.org/ - you can get filesystems, IP stack, network card drivers, etc. Several new OSs are using them.

Thanks, that site was really interesting! I hadn't heard of rump kernels before.

I have no idea. I discovered this researching secure OS work such as Flask. It does have plenty of documentation [1]. Maybe that will help you.

[1] http://www.cs.utah.edu/flux/oskit/html/oskit-www.html

I'm filled with joy to see that PicoLisp runs on OpenWRT. I would love to see PilOS itself running on a wireless router, if only to be able to brag: "My router runs Lisp!" :-)

Might want to implement networking for PilOS first, before putting it on your router ;-)

I have yet to understand the Lisp craze, no matter how many blog articles I read about it's beauty.

Although I will admit Lisp machines were pretty neat.

Some of Lisp appreciation is like appreciating the Pixies: it's hard to see what's so amazing about it when so many of its good points have been expropriated by later projects. It's easy to see what's so powerful about Lisp when your only comparison is C, but it's not 1998 anymore, and most new code is written in high-level garbage collected languages.

The rest of Lisp you appreciate by learning to appreciate real macros.

I've read a few books about lisp tininess, beauty etc. I don't know it was late 70s research bias or not. But it seems that no matter how many lisp genes are picked up by other language. Its symbolic/recursive nature can't be matched, and everything else is secondary.

It's the syntax. The elementary nature of s-expressions makes it fairly trivial to mangle them freely, and define all kinds of clever tree structures and so on, all in an easy and consistent way. It also means you never have to remember much symbolic weirdness, you just have to remember (operator atom atoms ...), and that's it.

I think only the functional languages like Haskell and F# come close to the same expressiveness, just from very different angles; auto-currying and lazy evaluation save a lot of boilerplate, and the former is tricky to do in Lisp for precisely one of the reasons it's so flexible (easy variable arguments).

It's a little more than syntax to me, even though it's part of it. Maybe a ~rapprochement between syntax semantics evaluation of recursive domains/categories. The fact that the construction of data through sexps belongs to that same philosophy as valuation between any domains. That the same recursive idea permeates through the whole system.

Lisps do a fantastic job following the principle of least astonishment ( https://en.wikipedia.org/wiki/Principle_of_least_astonishmen... ). I work with Clojure professionally and I find there's a huge advantage to Lisp syntax compared to other languages that I've used. The syntax is very minimal and consistent while also extremely expressive.

Practically all other languages tend provide expressiveness by having tons of syntax sugar. This introduces a lot of special cases, quirks, and rules that you have to keep in your head to work with the language. It's constant mental overhead that distracts me from the problem I'm working on.

A language like Clojure just gets out of your way and lets you focus on your work without having to worry about its quirks all the time. The code tends to work as expected and does what it looks like it's doing on the first try.

The other big advantage is that s-expressions make it much easier to write structural editors like paredit. With Clojure I'm always thinking in terms of manipulating expressions as opposed to lines of code. I think of taking this block of logic and putting it in there and so on.

Finally, the syntax provides additional visual information about the flow of the program. You can tell what parts of code are interacting with one another simply by looking at the nesting. This makes the code much more easily scannable than other languages.

You are confusing Clojure syntax with its s-expression syntax.

Clojure syntax is s-expressions, your own private definition notwithstanding.

> Clojure syntax is s-expressions

That can't be the case. Clojure provides 'special forms' and has macros. All those add syntax to the language.

The syntax of Clojure s-expressions is just that: the syntax of Clojure s-expressions - but not the syntax of the Clojure language.

The Clojure site says:


    The syntax for function definitions becomes the following:

    (fn name? [params* ] condition-map? exprs*)
    (fn name? ([params* ] condition-map? exprs*)+)
Read the word syntax? See the EBNF like syntax descriptions with star, question mark and plus syntax operators? See parentheses structure with [] and () in the second example?

star -> zero or more expressions

plus -> one or more expressions

question mark -> one optional expression

That's syntax. It describes the structure of s-expressions which form valid Clojure code.

Not all Clojure s-expressions are valid Clojure code. There are lots of syntactic restrictions. See the syntax for 'fn' above for an example.

> your own private definition notwithstanding.

You may want to take over the Clojure.org site to follow your own, private, definition of Clojure syntax. Personally I prefer the usual definition of Clojure syntax, as for example shown on Clojure.org .

Claiming that Clojure only has s-expressions as syntax is thus wrong and misleading.

well I guess CL doesn't have s-exps either then who knew! https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node59.html

Of course Common Liep has s-expressions. Everybody knows that.

But s-expression syntax is not the complete syntax of Lisp programs. Lisp programs are written using s-expressions. But not every s-expression is a valid Lisp program. There is syntax for lambda expressions, various special forms and syntax implemented by macros.

S-expression syntax OTOH is only the syntax for, wait, s-expressions.

A Lisp compiler will check the syntax of Lisp code at compile time:

    * (defun foo () (let a ((b 10)) 3))
    ; in: DEFUN FOO
    ;     (LET A
    ;       ((B 10))
    ;       3)
    ; caught ERROR:
    ;   Malformed LET bindings: A.
Here the syntax for LET is violated.

The syntax for LET is defined as:

    let ({var | (var [init-form])}*) declaration* form* => result*
Thus the compiler expects a list of bindings and not a symbol, as in my example above.

Every Lisp programmer will need to learn this syntax. Not just ATOM plus (S-EXPRESSION*).

I'm not really sure what your point here. These are implementation details of how CL works. Has nothing at all to do with what s-expressions are in principle.

I'm not sure why it's so difficult to understand for you.

S-expressions give us a textual syntax for data. But not for Lisp. Lisp syntax is built on top of s-expressions and has to be learned. That's true for Scheme, too. See chapter 7.1 of the Scheme R7RS specification: "Formal syntax". That's not s-expressions.

> I'm not really sure what your point here.

That seems to be a common theme for you. I'll help you out: Your original points were this:

> Clojure syntax is s-expressions, your own private definition notwithstanding.

Which I showed you by pointing to Clojure.org to be wrong. Clojure syntax is more than s-expressions.

> The syntax is very minimal and consistent while also extremely expressive.

This also is wrong, since the syntax consists of all kinds special forms and macros, too. The user can even introduce lots of new syntax by implementing it as macros. Every library with macros is likely introducing new syntax and semantics.

now explain how reader macros in CL fit into your argument :)

Isn't it obvious? Reader macros are in the first place there to implement and extend the s-expression reader. It implements parsing of the data structures: conses, lists, arrays, vectors, strings, symbols, various number types, bit vectors, ...

Lisp is more like the Velvet Underground than the Pixies ;-)

There were three things that really did it for me: powerful macro's + language designed to be easily macro'd; incremental compilation; updating live code. The macro's let me extend it however I liked. OOP was invented? Add a library. Aspects? Add a library. Type-checking? Add a library. In each case, the language itself transforms to more effectively use the approach with much zero-overhead potential given the transforms are usually at compile-time. I had DSL's for common things such as GUI's, state-machines, and databases. Let me do so much with so little work while having consistency across the whole thing.

The second was incremental compilation. I was an imperative programmer and mostly used that style. Languages such as C++ interrupt one's mental flow with long compile cycles. Interactive languages, especially scripting, tended to be too slow in production. LISP let me compile individual functions in a fraction of a second after writing them. Think, type, hit button, examine results, and repeat. The flow stays there and you just keep pumping out more of your solution. That my main DSL was compatible with a C++ subset meant I could just autogenerate that at the end to benefit from its compilers or portability. Otherwise, I stayed in LISP.

The third thing was something that I tried with C/C++. Self-modifying code for AI and security applications was one use. Another was updating apps live. LISP made both pretty easy. The program ran as an instance while you made it in certain development environments. You were in a way always working with a live program. Also, you could drop a member variable in a class definition and all running instances of that class would loose it. Just like that. So easy to change while being able to compile to fast code with type & safety level declarations.

So, it was a language that could do anything I want it to do, allow rapid iterations at max flow, and even change running systems if they weren't good enough. Still haven't felt this full effect in other languages. The old LISP machines went further [1] in that they could take you to any problem in the app or OS right at the source code without crashing. Like LISP apps, you can inspect the issue, modify the code of the running system, optionally modify the instance, and proceed how you wanted to. Still waiting for that feature in Windows or Linux development. ;)

[1] http://www.symbolics-dks.com/Genera-why-1.htm

You'd have to sit down and learn it and try it out for yourself. At least that's the case for me.

True, I have Scheme, Racket, and Clojure installed on my machine. I tried to get started, but I couldn't think of any simple projects that would accentuate the "uniqueness" of Lisp dialects.

Maybe I'll pick it up again after my love affair with Go dries up.

maybe take the https://www.coursera.org/course/proglang MOOC

at one point you write a small evaluator, then extend it through macros. Shows you how to get the linguistic trait you'd like in a few lines. One thing lisp has been used to demonstrate since its birth.

(the course uses ruby and sml for other subjects)

Not sure if games interest you, but "Realm of Racket" is a fun read to get into Racket with. I mostly got into the rest of Lisp because I liked Racket.

I'll second that, it's a great book. Sort of a cousin to Land of Lisp, simultaneously a bit more academic and a bit more gentle to newcomers.

Does it have to be unique? A small project that you use now and then that needs an upgrade would probably benefit from being written in lisp (in some manner).

I thought about having a shell that is lisp based for Linux, as a way of forcing myself to use lisp more often, since I'm on and off with it. Though running things like apt-get and such would be interesting (sudo (apt-get (install racket chromium-browser))) or so

One of the (many) lisp-like shells is Scsh (http://scsh.net/), which incidentally also has the best acknowledgments page by an open source project: http://scsh.net/docu/html/man.html

Though I believe your example would just be written as

  (sudo apt-get install racket chromium-browser)

It would be great to have Scsh as an installable package for the major Linux distributions? For example, on Ubuntu 14.04 LTS it exists but is not installable, says something about "unresolvable dependencies". Don't know about other distributions.

Then, there was an effort to port Scsh to the GNU Scheme, but the work was lost or abandoned somehow if I understood it correctly.

For people spending a lot of time on with Unix shell(s), a great Lisp/Scheme shell might have been the entering point. But somehow the great work that has been done at the beginning cannot be brought to masses.

It's a pitty.

14.10+ checking in here, it's very much installable.

Thanks for the link to the acknowledgements.

You can use eshell in emacs. It allows you run elisp commands.

Good work but the name is rather unfortunate; it is just too much like piles.

I first read the name as "Pile of %&!#". Definitely consider a rename. It looks like a fascinating project, and the use of Lisp/Prolog is really interesting.

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