Hacker News new | past | comments | ask | show | jobs | submit login
1991 – a server-side web framework written in Forth (1-9-9-1.com)
409 points by ChrisArchitect 5 months ago | hide | past | web | favorite | 67 comments

That is a masterpiece of Forth programming!

I particularly enjoyed this section from the template renderer which made me think... Return stack manipulation - that's playing with fire. And also - wow Forth is not much higher level than assembly, and gosh, I don't think I could have written that without writing some stack diagrams!

            2dup s" $>" search if               \ Check to see if there's a closing tag $>.
                2 -                             \ Add the close tag to the search result.
                nip                             \ Save the end position of $>.
                dup >r
                -                               \ Reduce the string to <$ ... $>.
                evaluate                        \ Run user's code (maybe a bad idea?).
                r>                              \ Retrieve our saved end position of $>.
                r> r>                           \ Retrive the addr u from start of loop iter.
                rot                             \ Bring end $> to stack top.
                over >r                         \ Store the real string's length.
                -                               \ Subtract end $> from u to get the pos from top
                r> swap                         \ that we'd like to strip away. Restore saved u.
                /string                         \ Drop top of the string until the end of $>.
                0                               \ Keep looping.
Thanks for the trip down memory lane!

The beauty of Forth is that you can write at as low or as high a level as you'd like. I think most Forth programmers would factor out some of these operations into their own words rather than writing such a low-level definition, but there's nothing preventing you from writing your web server like it's assembly code.

The rstack is just a temporary second stack with the caveat that you have to be a bit careful about cleaning it up after you're finished with it. (Unless you intend to do something fun and exotic like : goto r> drop >r ;)

Usually I'm more tense about code that uses rot/-rot; a little harder to keep track of in my head.

I like the (maybe a bad idea?) comment.

Its the only distracting comment, the rest tels me what it does, this one tells me how he feels.

Documenting potential security issues with your code is rarely a bad idea.

This is charming. A microframework in a scant 480 lines of code, plus a postmodern manifesto on historisity -- what's not to love!

I can't wait to read the slew of "Why we switched from <web-framework> to 1991" blog posts.

Maybe migrating from bashttpd:


I can see that happening: "the deployment was a piece of cake".

What says the project about security? "Only rudimentary input handling. We would not be running this on a public machine."

What will the hipsters say? "time to market"

Do you know what runs HN?

I once encountered an actual real live business application that included a web server written in VB6....

The only sucky things about VB6 was threading wasn't a regular language feature. You could get to it through the WinAPI but that's not organic enough for most VB programmers. One thing I do miss about VB6 is that you didn't need an entire runtime to build a GUI.

I wouldn’t say that was the only thing...error handling was a mess and I don’t even want to remember what I had to do to make a hash table - there were definitely low level calls to RtlMoveMemory and such.

I can see how that would go; I mean "how to serve static files" is one of the first things that you can learn when doing e.g. NodeJS.

I never did find out the real reason - I suspect (as it was a relatively small business that had been acquired) that it was because they were too cheap to pay for a server edition of Windows.

Looks like there are a few people actually running it :)


As someone with a similarly retro web framework ( https://fortran.io ), as far as I know, no one has switched to it. I have gotten a few serious inquiries from coders in the sciences or who are making use of their old Fortran skills... but only a very few in two years.

I really like the commitment to retro aesthetics. Last weekend I made an "imaginary astronomy" web app with nearly pixel-perfect Windows 95 theming. :-) http://steveasleep.com/keplverse/

Forth still seems like a language worth learning, not for practical reasons, but for technohistorical context. Maybe my first project should be a sqlite library?

That's a nice one, but why not use MS Sans Serif as a font where available, for maximum effect?

Because I'm on a Mac and wouldn't be able to test it. :-D

Patches accepted here: https://github.com/irskep/keplverse

I also blogged about the algorithm, if that's of interest: https://blog.steveasleep.com/using-data-from-the-kepler-miss...

Think you can make it into a CSS framework or Bootstrap theme?

That's really nice. I have a stupid amount of nostalgia for the Win95/NT theme.

> Hence developers working on new projects while still coding in decades-old text editors. They write the future in the past and are made present in so doing.


Postmodern. Just like Perl.

Besides the framework itself the website is glorious. Kudos!

Cool. Any decent implementation for client side forth in the browser so I can do some good old Asynchronous Forth And staX?

I wrote a Forth interpreter for WASM some time ago: https://github.com/stefano/wasm-forth

It's not production ready and it's missing a good JS interface, but you can use it to run Forth code in the browser with a basic console interface.

I know Karsten Schmidth made a browser REPL you can try. I don't know the address, but I think he mentions it in this talk: https://juxt.pro/blog/posts/XT16-karsten-schmidt.html

Forth must be lightning fast albeit single-threaded... has there been any work on a multithreaded Forth? Compiling to BEAM VM might be an option for (not fast) implementation...

Considering that some Forth implementations were custom hardware that directly implemented the language semantics, it was often quite fast, yes. Most of the bigger Forth systems (gForth, WinForth, BigForth) have some form of threading/task management. The smaller ones, which are often the ones expecting to run natively on microcontrollers with no operating system, expect you to write your own if you need it.

A naive (ie. threaded[1]) Forth implementation will be slow because the jump between each instruction is a very effective way to defeat branch prediction. Of course this doesn't apply to "real Forth" which is compiled into machine code or even less naive Forths which can do inlining, but there are many hobbyist Forth implementations (because they're so easy to write) where this will still be true.

If you're interested I wrote a naive literate Forth implementation which can do inlining: http://git.annexia.org/?p=jonesforth.git;a=blob;f=jonesforth... http://git.annexia.org/?p=jonesforth.git;a=blob;f=jonesforth...

[1] "Threaded" in this sense means https://en.wikipedia.org/wiki/Threaded_code not multithreading.

I've always meant to thank you for publishing jonesforth. I learned so much from it. (I can't believe it's been nearly ten years now!)

It's a beautiful example of literate programming. Knuth would be proud, I think!

It seems it's supported in some FORTHs: https://stackoverflow.com/questions/32736552/does-forth-supp...

Also of interest - Chuck Moore's* current work is on such a parallel architecture ASIC that uses FORTH: http://www.greenarraychips.com/

*Chuck Moore is the creator of FORTH

Some years ago, I ported ngaro (the retroForth vm) to Go, and made it possible to launch goroutines and use channels. It was very cool.

However, it was Go pre-1.0, so it won't work now. For a while, it was maintained by Charles Childers - the original retroForth author - but I do not think the Go version is still available.

If you want to give it a try (making it work with the latest Go version shouldn't be difficult), have a look at:


Hmm, sadly Factor is single-threaded I think (so you are stuck with coroutines), but you can make use of multiple cores using channels.

Never used Forth much, but did use NeWS which had a multi-threaded PostScript environment - which was fun.

And I thought I was horrible at choosing domain names lol

It would have been cool to serve this from the raw ip like :P It's actually responding to pings, seems to be in Malaysia.

certain target audiences don't in domain names anymore, they just follow links so it often doesn't really matter.

1991 - the year punk broke.

Nice. I wonder what the threading model is? Process per request? Thread per request? NodeJS style?

One process, one HTTP request at a time, buffering excess requests in a queue of up to 255 requests. Here's the main "event loop":

    : start-server { server client }
            server 255 listen
            server accept-socket to client
            client read-request prepare-response client send-response
        again ;
I think this word's definition should be fairly easy to follow even if you aren't familiar with Forth.

Why hasn't someone made a Go and Forth combination yet?

I made it in 2010: https://bitbucket.org/yiyus/ngaro/src

As I said in another comment, it won't work now because Go had not yet reached 1.0 at that time, but it should be easy to get it working again.

Not exactly Forth, but I implemented a small branchless Forth-like language in Go for audio synthesis and music:


I think entirely procedural languages are a nice fit for this domain since they make order of operations apparent. Going for something Forth-like was obvious, since it's terse, trivial to implement and makes factoring easy.

That said, I think the documentation of this project is a bit out of date, that the overall architecture is flawed and that stack juggling can be a bit distracting when working with more complex algorithms. I intend to rewrite it some day.

I've always thought Haskell and Forth would make an amazing combo.

That's more or less what kitten[1] is.

[1] http://kittenlang.org/

I've implemented forth a few times, most recently in perl.

I have a couple of forth-implementations in golang bookmarked. As a quick example take this one:

     $ go get github.com/unixdj/forego
     $ echo '3 4 + dup * . ' | forego 2>/dev/null
     49 ok

maybe it's just me, but that seems really neat


Sounds like it isn't that good if it took them four tries.

What makes you think Go and Forth go well together?

Everyone knows you Go Forth and multiply.

Strictly speaking, you're meant to GO FORTH AND MULTIPLY.



This is not getting enough up votes.

Can this recreate trying to figure out a way to host a web server in 1991?

Love the note at the end, rings true with me.

That's beautiful. Well done!

I love postmodern software

And postfix software!

To stay true to this claim it should’ve been written in Perl.

Even people who love Perl don't love 1991 Perl.


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