69 comments

[ 3.6 ms ] story [ 138 ms ] thread
Wow, really cool. You should ban.
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:

https://github.com/avleen/bashttpd

I once encountered an actual real live business application that included a web server written in VB6....
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.
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 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"

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.
1991 - the year punk broke.
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.

Besides the framework itself the website is glorious. Kudos!
Why hasn't someone made a Go and Forth combination yet?
What makes you think Go and Forth go well together?
(comment deleted)
Everyone knows you Go Forth and multiply.
ForthGo?

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

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
This is not getting enough up votes.
Not exactly Forth, but I implemented a small branchless Forth-like language in Go for audio synthesis and music:

https://github.com/boomlinde/acidforth

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 love postmodern software
To stay true to this claim it should’ve been written in Perl.
Even people who love Perl don't love 1991 Perl.
> 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.

Deep

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 }
        begin
            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.
And I thought I was horrible at choosing domain names lol
It would have been cool to serve this from the raw ip like https://1.9.9.1 :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.
Love the note at the end, rings true with me.
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?

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

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

Never used Forth much, but did use NeWS which had a multi-threaded PostScript environment - which was fun.
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:

https://bitbucket.org/yiyus/ngaro/src

Hmm, sadly Factor is single-threaded I think (so you are stuck with coroutines), but you can make use of multiple cores using channels.
Can this recreate trying to figure out a way to host a web server in 1991?