Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MetaForth: A Forth extension to create Forth?

955 views
Skip to first unread message

Liang Ng

unread,
Dec 5, 2018, 4:14:53 AM12/5/18
to
I was referred to eForth by Peter M and found that it might have the facilities to call C functions (just browsing source code, not tested).

While I was trying to do the same with jonesforth, I was wondering if anyone has recompiled eforth.img using modern assemblers?

Theoretically, it should not be "too difficult" to compare the primitive code in jonesforth and eforth, as the Reverse Polish Notation is well suited for tree and graph analysis.

I suppose LISP folks do that all the time.

Has anyone attempted this before?

Paul Rubin

unread,
Dec 5, 2018, 5:04:53 AM12/5/18
to
Liang Ng <lsn...@gmail.com> writes:
> I was referred to eForth by Peter M and found that it might have the
> facilities to call C functions (just browsing source code, not
> tested).

The traditional version almost certainly can't do that. Someone might
have added an extension.

There is an interpreter in C based on eforth:

http://chiselapp.com/user/tehologist/repository/compc/home

It is minimal but clever.

foxaudio...@gmail.com

unread,
Dec 5, 2018, 8:38:20 AM12/5/18
to
I may be wrong but I have the sense that you might be operating under a false assumption
about Forth implementations. Is it possible that you think that eForth and Jonesforth
work the same way internally?

I mean no offence, only to remove misunderstanding.

Forth has no "standard" way to implement the two stack virtual machine on a CPU.
This is in direct contrast to other languages which specify "HOW" things are implemented.

So in the case of Forth's written in Assembler a large number of decisions are made about:
-which registers will be used for which purpose in VM,
-will the top of stack be cached in a register or not
-how the dictionary is organized i.e. the word header data structure
- how the system calls its functions (indirect, direct, sub-routine)
and many more.

You can assume nothing about the internal details of a Forth system.

There are some best practices for different CPUs but there are no hard and fast rules that
implementors follow in creating a Forth system.

My apologies if this is already understood. The nature of the question gave me reason to
ask.

That being said, perhaps your first order of business is to specify an existing implementation
as your "Forth" for this C to Forth project.

An alternative that is less "sexy" but might provide a test platform would be to use a text
interface and use Forth like Postscript, leaving a binary interface for the next iteration.
The Forth interpreter in modern systems is very fast.
This eliminates the internal variations problem but lets you build a working system to demonstrate your ideas.

Just a thought.

Dmitry Ponyatov

unread,
Dec 5, 2018, 8:56:50 AM12/5/18
to
Maybe you should look to bytecode compiling? You can allocate a static buffer in vocabulary, compile bytecode in the format you want (platform-independent by design), and interpret compiler bytecode with an interpreter you also write in FORTH.

As it was said above, there is no generic way to manipulate compiled code in a portable way, and the second problem with the generic FORTH there is no standard ways to do any dynamic data structures.

Dmitry Ponyatov

unread,
Dec 5, 2018, 10:57:59 AM12/5/18
to
If anybody interested in, I can continue this implementation development:

https://github.com/ponyatov/nuFORTH/tree/dev/gforth

There are a lot of manuals on making target compiler in FORTH.

What you need for metaprogramming is some implementation works as a guest system in other ready to use system, say gforth.

The key is having predefined executable code structure, you can compile and modify in a predefined way. I like bytecode approach for this as it is totally portable. As an example, it can simultaneously on STM32/Cortex-M microcontroller boards, Linux, Windows and gforth port on Android phone.

We can write bytecode interpreter in gforth, combine it with a compiler in dedicated vocabulary, and get interactive debugger/compiler for free. In case you want to run your system standalone, you can write a tiny interpreter in C or any other language has effective byte addressing in raw arrays. As example, the same system can run in Linux, and in WebAssembly instance in browser.

Dmitry Ponyatov

unread,
Dec 5, 2018, 10:44:55 PM12/5/18
to
The other approach is code synthesis but to do this we need the FORTH Standard in the form suitable not for humans but for computer processing. It must include sound semantics for every element of a generic FORTH system, maybe someday I'll make it myself here.

https://github.com/ponyatov/kb/tree/dev/db/lang

But nowadays I'm totally not interested in classical FORTH, lack of principal features not in language but in its core runtime makes it dead decades ago: there are no
- dynamic memory
- generic data structures
- GUI/web and a thousand of other libraries must have now in a standard library of any programming language

Dmitry Ponyatov

unread,
Dec 6, 2018, 2:50:14 AM12/6/18
to
If anybody still interested in, first
let's define Target Compiler proposal to Forth Standard _right here_,
with two things critically required to continue:

1. target compiler proposal words and data structures (vocabulary, directives,..)

2. optional FORTH machine bytecode commands opcodes and format to make portable implementations to be run on microcontroller devices (Cortex-M, maybe Arduino, and mainstream OSes including Android)

3. ANS-compliant reference implementation combines target compiler and bytecode interpreter able to run in gforth (and any other like SPF)

4. ANSI'C reference implementation of bytecode interpreter contains a fixed set of data structures and minimal/optional commands optimized for MCU systems

Elizabeth D. Rather

unread,
Dec 6, 2018, 3:31:06 AM12/6/18
to
An effort in the direction of standardizing target compilers was started
some time ago, by FORTH, Inc. and MPE (both of whom have written and
maintained target compilers for many years).

This article covers some basic concepts:
http://www.forth.com/downloads/ANS/XCpaper.pdf

Normative (required behavior) text is here:
http://www.forth.com/downloads/ANS/XCpaper.pdf

Explanatory appendices are here:
http://www.forth.com/downloads/ANS/XCapp5.pdf

Both companies have moved on since then, but many of the concepts are
still valid and in use. For an illustrationn, you might want to take a
look at one of the free trial versions of SwiftX:
https://www.forth.com/embedded/

Cheers,
Elizabeth


--
Elizabeth D. Rather
FORTH, Inc.
6080 Center Drive, Suite 600
Los Angeles, CA 90045
USA

Alex McDonald

unread,
Dec 6, 2018, 4:13:10 AM12/6/18
to
On 06-Dec-18 07:50, Dmitry Ponyatov wrote:

Please don't delete all the message you are responding to. It was here.
--
Alex

john

unread,
Dec 6, 2018, 6:19:57 AM12/6/18
to
In article <a88e336d-21a8-44ea...@googlegroups.com>,
dpon...@gmail.com says...
> 1. target compiler proposal words and data structures (vocabulary, directives,..)
>
> 2. optional FORTH machine bytecode commands opcodes and format to make portable implementations to be run on microcontroller devices (Cortex-M, maybe Arduino, and mainstream OSes including Android)
>
> ...

I would humbly suggest such a task is only viable for commercial enterprises to
complete with any success. And then only with huge investment.

The list above only names one microcontroler as far as I'm aware which is
perhaps just do-able as open source. A full list of microcontrolers is quite lengthy.
To produce some sort of standard cross compiler for microcontrolers is a pretty
daunting task (and I thought my own project rather audacious)

The most popular microcontroler would be the microchip PIC family (I believe)
and having worked with it myself would not consider it suitable for any form of
universal cross compilation - in spite of the great efforts microchip go to to
standardise the hardware. PICforth exists of course - and it's a great idea
but it isnt universal.

Everyone is talking about the ARM's but they have had their day and will be
slowly retiring as better solutions arise for the mobile tasks they are currently
famous for. (longer term comment of course) Other microcontrolers are better
suited to forthcoming tasks and as such require far more diverse functionality.
I do see a window of opportunity there but the field will eventualy be more like
the PIC family than the cortex one. Embedding ARMS into FPGA's is simply a
stop gap solution and not a very efficient one at that. I'd go so far as to call it
a marketing ploy.

Register locations, functionality, and other variations are far too wide to make
generalised software for microcontrolers without large teams working on it.
And as someone mentioned - Forth is way out of date with its toolchain making
the task pretty much impossible.
It could be done - but only by the chip designers.

If you want to do something useful with forth - as I've said elsewhere previously -
you need to sort out the toolchain first before you can even see what it might be
suitable for these days.

You've all been talking about that here for weeks - why not just do it?

--

john

=========================
http://johntech.co.uk

=========================

Paul Rubin

unread,
Dec 6, 2018, 6:37:01 AM12/6/18
to
john <jo...@example.com> writes:
> A full list of microcontrolers is quite lengthy. To produce some sort
> of standard cross compiler for microcontrolers is a pretty daunting
> task (and I thought my own project rather audacious)

The idea is just to specify the bytecode format. Then someone wanting
to run the portable Forth on a particular device would implement a
bytecode interpreter for that device. That is how Retroforth and the C
version of eForth both work. Pascal P-code was another example of this
approach. It's very doable. The main drawback is that a
straightforward bytecode interpreter will run quite a bit slower than a
traditional threaded-code interpreter.

a...@littlepinkcloud.invalid

unread,
Dec 6, 2018, 7:08:03 AM12/6/18
to
Paul Rubin <no.e...@nospam.invalid> wrote:

> The idea is just to specify the bytecode format. Then someone
> wanting to run the portable Forth on a particular device would
> implement a bytecode interpreter for that device. That is how
> Retroforth and the C version of eForth both work. Pascal P-code was
> another example of this approach. It's very doable. The main
> drawback is that a straightforward bytecode interpreter will run
> quite a bit slower than a traditional threaded-code interpreter.

Not to mention more complicated. And it gets worse, because literal
formats have to be fixed with alignment rules, endianness, and so on.

Andrew.

Albert van der Horst

unread,
Dec 6, 2018, 7:50:03 AM12/6/18
to
In article <T9-dnSIxXK-BjJTB...@supernews.com>,
However, there may be already a quite capable byte-code interpreter
present. I mean Python. I'm not aware of a Forth compiling to
Python byte-code and relying on the Python engine to run it.
Like Forth compiling to Java-code it would have its restrictions
but basic operations should be quite doable.

>
>Andrew.

Groetjes Albert
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Dmitry Ponyatov

unread,
Dec 6, 2018, 7:50:39 AM12/6/18
to
> Not to mention more complicated. And it gets worse, because literal
> formats have to be fixed with alignment rules, endianness, and so on.

We have this with any compiler, nobody cares.
We have only 6 variants (2 byte orders times 3 cell width) and extra primitive language.
We just need to make target compiler and host interpreter be configurable in an explicit manner.

Dmitry Ponyatov

unread,
Dec 6, 2018, 7:53:42 AM12/6/18
to
> However, there may be already a quite capable byte-code interpreter
> present. I mean Python.

Python in a 20K (!) of RAM. Are you kidding?

a...@littlepinkcloud.invalid

unread,
Dec 6, 2018, 8:25:25 AM12/6/18
to
Dmitry Ponyatov <dpon...@gmail.com> wrote:
>> Not to mention more complicated. And it gets worse, because literal
>> formats have to be fixed with alignment rules, endianness, and so on.
>
> We have this with any compiler, nobody cares.

What? Do we?

> We have only 6 variants (2 byte orders times 3 cell width) and extra
> primitive language.

Indeed.

> We just need to make target compiler and host interpreter be
> configurable in an explicit manner.

Why would you need the host interpreter to be configurable? If the
bytecode is to be portable, then there's no configuration needed.
I must be missing something.

Andrew.

c...@forthworks.com

unread,
Dec 6, 2018, 8:37:11 AM12/6/18
to
https://micropython.org/ claims to run in as little 16K of RAM.

john

unread,
Dec 6, 2018, 8:44:53 AM12/6/18
to
In article <87sgzae...@nightsong.com>, no.e...@nospam.invalid says...
>

> The idea is just to specify the bytecode format. Then someone wanting
> to run the portable Forth on a particular device would implement a
> bytecode interpreter for that device. That is how Retroforth and the C
> version of eForth both work. Pascal P-code was another example of this
> approach. It's very doable. The main drawback is that a
> straightforward bytecode interpreter will run quite a bit slower than a
> traditional threaded-code interpreter.

I suspect such an approach would make the use of forth a serious drawback
not a benefit Paul.

Bytecode is never a good idea. There's no real excuse for it.
It's generally proposed when someone wants to offload the real task
of doing a job onto someone else. And when it still looks complicated
they generally start trying to involve other languages their bytecode
can "compile to" as JIT in order to solve the new issues they've created.

You ultimately end up with application code that cripples your hardware
instead of using it.
And you don't want that in a microcontroler.

foxaudio...@gmail.com

unread,
Dec 6, 2018, 9:46:41 AM12/6/18
to
For reference this benchmark indicates microPython runs between 87 to 241
times slower than a C++. (assume that is native code)
ITC Forth would typically be 4 to 10 times slower vs native code.

https://github.com/micropython/micropython/wiki/Performance

Albert van der Horst

unread,
Dec 6, 2018, 10:02:41 AM12/6/18
to
In article <6b0eb04e-6c62-46e8...@googlegroups.com>,
Who cares? These days one accesses a built in file on a webserver
to switch a led on and a different file to switch it off.

Anton Ertl

unread,
Dec 6, 2018, 10:21:37 AM12/6/18
to
Paul Rubin <no.e...@nospam.invalid> writes:
>The idea is just to specify the bytecode format. Then someone wanting
>to run the portable Forth on a particular device would implement a
>bytecode interpreter for that device. That is how Retroforth and the C
>version of eForth both work. Pascal P-code was another example of this
>approach. It's very doable. The main drawback is that a
>straightforward bytecode interpreter will run quite a bit slower than a
>traditional threaded-code interpreter.

Getting from bytecode to threaded code is also doable, even with
optimizations, see
<http://www.complang.tuwien.ac.at/papers/ertl+06dotnet.ps.gz>.

The bigger problem is that compiled Forth code contains literals whose
value depends on cell and float size and alignment, and contains
memory areas that depend on cell and float size and alignment, and the
computations can require a symbolic representation of the values
and/or sizes. E.g., consider:

create x 3 allot align 5 , 5 chars allot falign 1 floats allot 9 allot
sfalign 1 sfloats allot align here x - ,

If we are not prepared to go to this symbolic level, we need one file
format for every combination of cell size, float size, and possibly
alignment variations, plus (to avoid having to mark types beyond
addresses) byte order. That's what we do in Gforth. We have only one
float size, and we are using natural alignment (alignment=size), so we
have 6 variants: {16,32,64}bit x {little,big}endian.

And once you are there, you can eliminate much of the complexity of
the bytecode->threaded-code translation by storing the intermediate
code as cell code rather than byte code. We do that in Gforth, too.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2018: http://www.euroforth.org/ef18/

Albert van der Horst

unread,
Dec 6, 2018, 10:21:52 AM12/6/18
to
In article <MPG.367337c91...@news.aioe.org>,
Where the mainstream in Iot seems to be micropython, I wonder where
you can be so sure. No doubt, you swim against the tide.
Willem Ouwerkerk and I agree on one thing, with Forth and microprocessor
you don't spend your time designing or programming, you are busy
deciphering data sheets. Most people can't even understand a datasheet
if there life depended on it, but they are happily doing Iot with Python
(or 1G+ c++ development environments, which is an other way to
offload the real task onto someone else. Which is fine by me.)

>
>
>john

Dmitry Ponyatov

unread,
Dec 6, 2018, 10:56:36 AM12/6/18
to

> The bigger problem is that compiled Forth code contains literals whose
> value depends on cell and float size and alignment, and contains
> memory areas that depend on cell and float size and alignment, and the
> computations can require a symbolic representation of the values
> and/or sizes.

Exactly, and every FORTH system has its own memory organization, vocabulary structure, machine code, direct memory bumping... all the hell.

Let's return to the original question. How can we do metaprogramming if we must dive to the machine code level to do anything even in the single FORTH system?

That's why when I've decided to do the meta to be my own main programming arts, I completely refused classical FORTH and leave only CLI, stack machine and vocabulary lookup principle (atop of homoiconic structures very close to Minsky's frames).

When we speak about embedded, it's my professional area, and I want to be productive here using tools I'm glad to use including FORTH. I think meta in a mixed form of concept programming (not Stepanov's but Tyugu) and automated code generation to native C/LLV1M has some perspectives here, but it's a long curved road dissolves in a fog.

foxaudio...@gmail.com

unread,
Dec 6, 2018, 11:41:43 AM12/6/18
to
Lol. I guess the answer today is very few people care.

a...@littlepinkcloud.invalid

unread,
Dec 6, 2018, 1:03:01 PM12/6/18
to
Dmitry Ponyatov <dpon...@gmail.com> wrote:
>
>> The bigger problem is that compiled Forth code contains literals whose
>> value depends on cell and float size and alignment, and contains
>> memory areas that depend on cell and float size and alignment, and the
>> computations can require a symbolic representation of the values
>> and/or sizes.
>
> Exactly, and every FORTH system has its own memory organization,
> vocabulary structure, machine code, direct memory bumping... all the
> hell.
>
> Let's return to the original question. How can we do metaprogramming
> if we must dive to the machine code level to do anything even in the
> single FORTH system?

But we do not have to dive down to machine level to do anything.

> That's why when I've decided to do the meta to be my own main
> programming arts, I completely refused classical FORTH and leave
> only CLI, stack machine and vocabulary lookup principle (atop of
> homoiconic structures very close to Minsky's frames).
>
> When we speak about embedded, it's my professional area, and I want
> to be productive here using tools I'm glad to use including FORTH. I
> think meta in a mixed form of concept programming (not Stepanov's
> but Tyugu) and automated code generation to native C/LLV1M has some
> perspectives here, but it's a long curved road dissolves in a fog.

But what makes such a thing better? It sounds like you'd either have
to implement some kind of language runtime many times or lean on some
non-Forth tools.

Andrew.

Paul Rubin

unread,
Dec 6, 2018, 4:20:41 PM12/6/18
to
a...@littlepinkcloud.invalid writes:
>> We have only 6 variants (2 byte orders times 3 cell width) and extra
>> primitive language.
> Indeed.

Certainly the bytecode should use fixed byte ordering and at least for
literals, not care about cell size (just have different opcodes for
different sizes of literals).

> Why would you need the host interpreter to be configurable? If the
> bytecode is to be portable, then there's no configuration needed.
> I must be missing something.

The host interpreter probably has to know the target cell size, since
you can calculate stuff with it and put the results into the bytecode.
The host has to simulate the target if you want to have code that does
the same thing on both.

Example: 1 20 LSHIFT 20 RSHIFT generates 0 if the cell size is
16 bits, but 1 with larger cells.

Paul Rubin

unread,
Dec 6, 2018, 4:49:26 PM12/6/18
to
foxaudio...@gmail.com writes:
> For reference this benchmark indicates microPython runs between 87 to
> 241 times slower than a C++. (assume that is native code)

I wonder if that's using bignum arithmetic, and if that C++ loop on ARM
is actually spending most of its time in the millis() function, since
it's doing just 10M counts/sec on a 96 mhz cpu.

> ITC Forth would typically be 4 to 10 times slower vs native code.
> https://github.com/micropython/micropython/wiki/Performance

Ok, C++ on an Arduino is doing 5M counts in 10 sec, so ITC Forth would
do between .5M and ~1M, similar to Micropython on the Teensy (the AVR to
ARM cpu speedup is about equal to the interpreter slowdown). You end up
being able to do about the same things on both. Of course Forth on the
ARM would be far faster still, but the AVR is closer to the traditional
Forth platforms.

FWIW, the BBC Micro is about half the speed of the Teensy and
Micropython really struggles to run with 16k of ram (and that's just
ram; it also needs ~ 100K of program flash). It's much happier with
32k. So you're right that Micropython doesn't compete with Forth on
either speed or size. You can have a pretty nice Forth with 16k of
flash and 1k of ram.

I think the old school counterpart of Micropython would have been BASIC
rather than Forth. Quite a bit slower, but less assembler-like.

I have an Adafruit Trinket M0 and have played with Circuitpython (their
fork of Micropython) and it's really nice. The board is tiny and its
MCU has 256k of flash and 32k of ram. You can plug it into a USB port
where it presents as a flash drive that you can drag and drop files to.
They make bigger versions with SPI flash and faster/bigger MCU's too.

Liang Ng

unread,
Dec 6, 2018, 9:11:04 PM12/6/18
to
On Friday, 7 December 2018 05:49:26 UTC+8, Paul Rubin wrote:
> f....@gmail.com writes:
> > For reference this benchmark indicates microPython runs between 87 to
> > 241 times slower than a C++. (assume that is native code)
>
> I wonder if that's using bignum arithmetic, and if that C++ loop on ARM
> is actually spending most of its time in the millis() function, since
> it's doing just 10M counts/sec on a 96 mhz cpu.
.....
.....
> I have an Adafruit Trinket M0 and have played with Circuitpython (their
> fork of Micropython) and it's really nice. The board is tiny and its
> MCU has 256k of flash and 32k of ram. You can plug it into a USB port
> where it presents as a flash drive that you can drag and drop files to.
> They make bigger versions with SPI flash and faster/bigger MCU's too.

Haven't had time to respond to all. Since you are the first to respond to my thread, so I will summarize my response here:

(1) Forth ITC being slower than "native code" can be addressed by making a Forth just-in-time compiler -- to compile Forth words to native code.

Is there commercial implementation for this, or someone's pet project?

(2) By my own survey, the interpreters of Python, Java, JavaScript, Ruby, PHP are all stack machines. This pretty much cover the majority of popular programming languages today.

If we are to standardize Forth bytecode, why not create a mechanism to standardizing opcodes amongst stack machines of these high level languages -- a Universal Stack Machine (USM)???

In that way, we can attract more young talents to the project. We need to have a bigger goal to attract more followers, c.f. Karl Marx.

(3) As part the demonstration of the "universal stack machine", I am trying to create a "C stack machine" -- using Forth-like words to call C functions, without returning to C, eliminate assignment operation, use EAX as top of stack.

For this, I found that eforth http://home.iae.nl/users/mhx/eforth.html has a prototype of Forth calling C function. However, since the eforthl.asm was written for MASM, it might be easier to mirror the mechanism in jonesforth or bigforth (another Forth with C loader), instead of modifying it. (Microsoft hater alert!!)

If we have a C stack machine (CSM) prototype, then I believe we are half way towards a "universal stack machine".

The big question is not how many man months it would take, the only question is how many men (women) can we get to join the revolution. Again, c.f. Marx, Lenin, Mao, Stallman, Torvalds. And that, depends on how well we can tell the story!

Liang Ng

unread,
Dec 6, 2018, 9:21:54 PM12/6/18
to
On Friday, 7 December 2018 10:11:04 UTC+8, Liang Ng wrote:
> If we have a C stack machine (CSM) prototype, then I believe we are half way towards a "universal stack machine".
>
> The big question is not how many man months it would take, the only question is how many men (women) can we get to join the revolution. Again, c.f. Marx, Lenin, Mao, Stallman, Torvalds. And that, depends on how well we can tell the story!

Initial sketch and implementation of "Universal Stack Machine":

Multitiered Stack Machine (nSM) using 5GL (Fifth Generation Graph Language)

https://www.linkedin.com/pulse/multitiered-stack-machine-nsm-using-5gl-fifth-graph-ng-ph-d-/

http://5gl.epizy.com/nsm/fgl.html?i=1

Paul Rubin

unread,
Dec 6, 2018, 10:01:53 PM12/6/18
to
Liang Ng <lsn...@gmail.com> writes:
> compile Forth words to native code... Is there commercial
> implementation for this, or someone's pet project?

Sure there are tons of Forth compilers.

> (2) By my own survey, the interpreters of Python, Java, JavaScript,
> Ruby, PHP are all stack machines. This pretty much cover the majority
> of popular programming languages today.

But it's an implementation detail. Lua uses a register VM which shows
that approach works as well.

> If we are to standardize Forth bytecode, why not create a mechanism to
> standardizing opcodes amongst stack machines of these high level
> languages -- a Universal Stack Machine (USM)???

To some extent the Java VM (JVM) is used as the backend for a lot of
different languages like Scala, Clojure, Jython, and even some Forths.
The Microsoft CLR is another example.

These are all relatively heavyweight, not anything like traditional
Forth, which is close to the machine and minimalistic.

Forth historically brought a lot of powerful features together
(interactive development, integrated editing, multitasking, etc.) on
very limited hardware, by sacrificing various conveniences like files
(use blocks instead), automatic memory management (your hardware control
program won't need it), and infix notation (use explicit stacks).

Today though, Forth's explicit stack is like Lisp's parentheses, a
historically grounded implementation hack that people can learn to love,
but it isn't something to get excited about in its own right. With
fewer hardware constraints you can make the programmer's life easier by
getting rid of those sacrifices. Once you start using the
implementation techniques of Python or Javascript, you might as well
also use their syntax.

So I think Forth is still most interesting in something like its
original context: simple, low-level, mostly-traditional-style
implementations. It's amazing how cleverly the parts all fit together.

Liang Ng

unread,
Dec 6, 2018, 10:24:50 PM12/6/18
to
On Friday, 7 December 2018 11:01:53 UTC+8, Paul Rubin wrote:

> > compile Forth words to native code... Is there commercial
> > implementation for this, or someone's pet project?

> Sure there are tons of Forth compilers.

Examples please?


> Forth historically brought a lot of powerful features together
> (interactive development, integrated editing, multitasking, etc.) on
> very limited hardware, by sacrificing various conveniences like files
> (use blocks instead), automatic memory management (your hardware control
> program won't need it), and infix notation (use explicit stacks).
>
> Today though, Forth's explicit stack is like Lisp's parentheses, a
> historically grounded implementation hack that people can learn to love,
> but it isn't something to get excited about in its own right. With
> fewer hardware constraints you can make the programmer's life easier by
> getting rid of those sacrifices. Once you start using the
> implementation techniques of Python or Javascript, you might as well
> also use their syntax.
>
> So I think Forth is still most interesting in something like its
> original context: simple, low-level, mostly-traditional-style
> implementations. It's amazing how cleverly the parts all fit together.

Survey question (which I will ask others in long term):

(1) If there is a Universal Stack Machine Language (USML) that allows you to translate USML code to any of your favourite programming languages (e.g. PHP, JavaScript, C), would you use it, much like a shell script (a better shell, shell is a stack machine with a stack height of 1, not more)?

(2) If the USML helps you to optimize execution speed -- instead of interpreting PHP code to PHP-SM opcode, it translates directly from USML to JIT-Forth, would you use it?

(3) For (1) and (2), you may continue to use your favourite programming languages, only use USML as and when and where you like it. Will you use it?

Paul Rubin

unread,
Dec 6, 2018, 10:41:45 PM12/6/18
to
Liang Ng <lsn...@gmail.com> writes:
>> Sure there are tons of Forth compilers.
> Examples please?

If you have to ask that question after this long on clf, you're not
really following Forth. But BigForth (which you were just using),
Mecrisp, ciForth, amForth(?), and the usual commercial offerings all
compile to native code.

> (1) If there is a Universal Stack Machine Language (USML) that allows
> you to translate USML code to any of your favourite programming
> languages (e.g. PHP, JavaScript, C), would you use it...?

That sounds silly, do you mean for the translation to be in the other
direction? Anyway, it makes no sense for C. PHP and JavaScript already
have their own maintainers (and there are lots of highly tuned JS
implementations) so I'd leave such questions up to them for those
languages. But I doubt it would get much of a reception.

> (2) If the USML helps you to optimize execution speed -- instead of
> interpreting PHP code to PHP-SM opcode, it translates directly from
> USML to JIT-Forth, would you use it?

I don't really use PHP to begin with.

> (3) For (1) and (2), you may continue to use your favourite
> programming languages, only use USML as and when and where you like
> it. Will you use it?

If there were an efficient portable VM that could handle languages like
JavaScript then it could be of some interest as yet another compiler
backend. But that VM would have no resemblance at all to traditional
Forth. It would need closures, garbage collection, memory safety, OOP
and types at the lowest level probably, etc., and not just at the toy
level like we see in the small Lisps that everyone ends up writing. I
don't know if you understand how large a gap there is between that and
Forth. Forth is in a very limited niche, which is one of the things
that makes it interesting.

Liang Ng

unread,
Dec 6, 2018, 11:57:39 PM12/6/18
to
On Friday, 7 December 2018 11:41:45 UTC+8, Paul Rubin wrote:
> Liang Ng <....@gmail.com> writes:
> >> Sure there are tons of Forth compilers.
> > Examples please?
>
> If you have to ask that question after this long on clf, you're not
> really following Forth. But BigForth (which you were just using),
> Mecrisp, ciForth, amForth(?), and the usual commercial offerings all
> compile to native code.

Thanks for confirming. As usual, no much organized documentation is available. So I only start to think about it when I need to use it.


> > (1) If there is a Universal Stack Machine Language (USML) that allows
> > you to translate USML code to any of your favourite programming
> > languages (e.g. PHP, JavaScript, C), would you use it...?
>
> That sounds silly, do you mean for the translation to be in the other
> direction? Anyway, it makes no sense for C. PHP and JavaScript already
> have their own maintainers (and there are lots of highly tuned JS
> implementations) so I'd leave such questions up to them for those
> languages. But I doubt it would get much of a reception.

Please see comments after (3) below.


> > (2) If the USML helps you to optimize execution speed -- instead of
> > interpreting PHP code to PHP-SM opcode, it translates directly from
> > USML to JIT-Forth, would you use it?
>
> I don't really use PHP to begin with.

You may substitute PHP with any stack machine based programming language that you are using.


> > (3) For (1) and (2), you may continue to use your favourite
> > programming languages, only use USML as and when and where you like
> > it. Will you use it?
> If there were an efficient portable VM that could handle languages like
> JavaScript then it could be of some interest as yet another compiler
> backend. But that VM would have no resemblance at all to traditional
> Forth. It would need closures, garbage collection, memory safety, OOP
> and types at the lowest level probably, etc., and not just at the toy
> level like we see in the small Lisps that everyone ends up writing. I
> don't know if you understand how large a gap there is between that and
> Forth. Forth is in a very limited niche, which is one of the things
> that makes it interesting.

For a start we may describe a USML specification which can be use to specify any stack machine operations. That would make the internal operations of programming languages like PHP, JavaScript (insert equivalent) available to a wider audience, instead of the few hard core developers.

USML could be a superset of Forth -- unless you think there is another stack machine language which has more users?

The first phase goals should aim only to describe existing PHP/JavaScript (or equivalent) (High Level Programming Language / HLPL) using USML and execute the equivalent USML without loss of functionalities.

Thereafter, we may start looking at places where USML may improve the existing stack machine operations. Currently, developers of each HLPL work in silos. If we have USML, then perhaps there will be collective wisdom which can solve problems across languages.

I suspect there should not be that many differences between HLPL at the stack machine level. If there are, we can always define structures to characterise and abstract them.

Liang Ng

unread,
Dec 7, 2018, 12:18:23 AM12/7/18
to
On Friday, 7 December 2018 12:57:39 UTC+8, Liang Ng wrote:
> On Friday, 7 December 2018 11:41:45 UTC+8, Paul Rubin wrote:
> > Liang Ng <....@gmail.com> writes:
> > >> Sure there are tons of Forth compilers.
> > > Examples please?
> >
> > If you have to ask that question after this long on clf, you're not
> > really following Forth. But BigForth (which you were just using),
> > Mecrisp, ciForth, amForth(?), and the usual commercial offerings all
> > compile to native code.
>
> Thanks for confirming. As usual, no much organized documentation is available. So I only start to think about it when I need to use it.

Interestingly, I found one Dr Anton Ertl's doctorate thesis by googling "universal stack machine language":

Implementation of Stack-Based Languages on Register Machines (1996)

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.3.7444&rep=rep1&type=pdf

Dmitry Ponyatov

unread,
Dec 7, 2018, 12:27:07 AM12/7/18
to
I've had a bit of sleep last night and grok the Universe. The only unique invincible and truly effective metalanguage is the glorious Machine Code (*) runs on any von Neumann computer! There is nothing else, all other tools and languages just abstractions above it.
(*) forget about FPGA this time

So yes and no, you can't use FORTH as a metalanguage as this is a holey abstraction, but you will be happy to use FORTH as a powerful CLI frontend for doing the real metaprogramming in machine code. Factically FORTH was born this way, and it stays there last fifty years.

Don't throw out a C compiler, it will help you to build pointer tables of your core system, provides wrappers to any OS APIs and libraries you want, and hides the [dynamic] linker stage problems.

The same can be said about (GNU) toolchain if you want to play with the embedded device. The simplest way to start metaprogramming is the use of gdb in remote debug mode. If you have enough skills you can embed some host-side (g)forth as an extension to gdb (as it was done with Python) and combine mainstream hw.debugging interface with ready to use [dis]assembler, memory browser, symbol tables,.. and the power of FORTH.

PS:

Don't use PIC, AVR8 or any other computer with ungodly Harvard architecture. It is unsuitable specifically for metaprogramming, this hardware will be usable but you'll get a lot of superfluous problems for free.

The most suitable candidate for the embedded self-hosted metaprogramming is any Cortex-M microcontroller: almost any semiconductor vendor has more or less rich Cortex-M product line. There a lot of cheap ones lies everywhere in local radishacks and easy to start devboards with embedded hardware debugger on-board. Cortex-M is able to run code from RAM, that's the thing we must to have for meta. And if you ready to spend more, you'll get the Cortex-M7/H7 SoC beats old days Pentiums like a chickens with powerful RISC command set, multi-channel DMA, and rich periphery.

Liang Ng

unread,
Dec 7, 2018, 12:35:48 AM12/7/18
to
On Friday, 7 December 2018 13:27:07 UTC+8, Dmitry Ponyatov wrote:
> I've had a bit of sleep last night and grok the Universe. The only unique invincible and truly effective metalanguage is the glorious Machine Code (*) runs on any von Neumann computer! There is nothing else, all other tools and languages just abstractions above it.
> (*) forget about FPGA this time
>
> So yes and no, you can't use FORTH as a metalanguage as this is a holey abstraction, but you will be happy to use FORTH as a powerful CLI frontend for doing the real metaprogramming in machine code. Factically FORTH was born this way, and it stays there last fifty years.
>
> Don't throw out a C compiler, it will help you to build pointer tables of your core system, provides wrappers to any OS APIs and libraries you want, and hides the [dynamic] linker stage problems.

You reminded me to make an important point: there are 2 aspects of Forth -- the syntax and the implementation.

Most people on comp.lang.forth seem to be obsessed with the implementation aspect of Forth, whereas the syntax part -- the Reverse Polish Notation -- has a lot more interesting properties, mathematically and practically speaking.

Calling it RPN is not sexy -- even racist I think. Calling it USML (Universal Stack Machine Language) is funny -- United States Munition List if you google USML.

USML sounds close to UML. Or ?SML where ? could be [A-Z][a-z][0-9] or even Unicode!!

Dmitry Ponyatov

unread,
Dec 7, 2018, 12:48:42 AM12/7/18
to
> Calling it USML (Universal Stack Machine Language)
> is funny -- United States Munition List if you google USML.

There are a lot of programmers here and there whines about compiler speed, code optimization, and resource consumptions. No more stacks! Only old warm tubby machine registers, main control panel, and hardcore direct machine code modifications. No one can reproach me that my programming language implementation eats the efficiency!

Liang Ng

unread,
Dec 7, 2018, 12:49:45 AM12/7/18
to
Examples?

Ron Aaron

unread,
Dec 7, 2018, 1:32:58 AM12/7/18
to
Do you know how to use Google?

Liang Ng

unread,
Dec 7, 2018, 1:58:43 AM12/7/18
to
Good lord. I am asking a specific person about specific examples.

What are you intending to do with the recent unfriendly posts? I hope this does not escalate?

You do have a product to promote. So please don't destroy it. At least I know some marketing rules.

Thank you very much.

You are welcome for the caution.

Ron Aaron

unread,
Dec 7, 2018, 4:01:55 AM12/7/18
to
On 07/12/2018 8:58, Liang Ng wrote:
> On Friday, 7 December 2018 14:32:58 UTC+8, Ron Aaron wrote:
>> On 07/12/2018 7:49, Liang Ng wrote:
>>> On Friday, 7 December 2018 13:48:42 UTC+8, Dmitry Ponyatov wrote:
>>>>> Calling it USML (Universal Stack Machine Language)
>>>>> is funny -- United States Munition List if you google USML.
>>>>
>>>> There are a lot of programmers here and there whines about compiler speed, code optimization, and resource consumptions. No more stacks! Only old warm tubby machine registers, main control panel, and hardcore direct machine code modifications. No one can reproach me that my programming language implementation eats the efficiency!
>>>
>>> Examples?
>>
>> Do you know how to use Google?
>
> Good lord. I am asking a specific person about specific example
>
> What are you intending to do with the recent unfriendly posts? I hope this does not escalate?

You continually post requests for others to do your research for you.
You're posting here, you're posting on Facebook. Same stuff, same long
discussions.

> You do have a product to promote. So please don't destroy it. At least I know some marketing rules.

Not sure where you're going with that.

My point is your questions are requests for research; the answers are
literally a Google-search away, if you would dedicate 15 minutes to that.

Dmitry Ponyatov

unread,
Dec 7, 2018, 4:27:03 AM12/7/18
to
> You continually post requests for others to do your research for you.
> My point is your questions are requests for research; the answers are
> literally a Google-search away, if you would dedicate 15 minutes to that.

It is not a problem. That's why I rejected StackOverflow, and moved to Quora: to understand something your first need to intro the topic, and _to google you must know the right keywords_. Asking even dumb questions on the new area, you have a good chance that somebody gives you a few links points you to the right way.

Ron Aaron

unread,
Dec 7, 2018, 5:06:23 AM12/7/18
to
Em, perhaps; but someone purporting to write a whole new language, and
who makes claims like the term "RPN" is maybe "racist", should be
someone who already knows more about the topic than a newbie who just is
getting his hands wet.

Google isn't restricted to StackOverflow results.

a...@littlepinkcloud.invalid

unread,
Dec 7, 2018, 7:45:01 AM12/7/18
to
Paul Rubin <no.e...@nospam.invalid> wrote:

> Today though, Forth's explicit stack is like Lisp's parentheses, a
> historically grounded implementation hack that people can learn to
> love, but it isn't something to get excited about in its own right.

I think that's a bit ahistorical. LISP 1.5 was supposed to have had
its M-expressions but they didn't get used (and AFAIK the M-expression
compiler was never finished) because people didn't see the point of
them. Steve Russell preferred S-expressions and he won, right?

> With fewer hardware constraints you can make the programmer's life
> easier by getting rid of those sacrifices. Once you start using the
> implementation techniques of Python or Javascript, you might as well
> also use their syntax.
>
> So I think Forth is still most interesting in something like its
> original context: simple, low-level, mostly-traditional-style
> implementations. It's amazing how cleverly the parts all fit
> together.

I agree with you. Forth written simply in Forth is the real thing:
anything else is a step on the road to that ideal state.

Andrew.

Anton Ertl

unread,
Dec 7, 2018, 8:02:12 AM12/7/18
to
a...@littlepinkcloud.invalid writes:
>Paul Rubin <no.e...@nospam.invalid> wrote:
>
>> Today though, Forth's explicit stack is like Lisp's parentheses, a
>> historically grounded implementation hack that people can learn to
>> love, but it isn't something to get excited about in its own right.
>
>I think that's a bit ahistorical. LISP 1.5 was supposed to have had
>its M-expressions but they didn't get used (and AFAIK the M-expression
>compiler was never finished)

It was Lisp 2 and the project was never finished. However, when I
recently <2018Jul1...@mips.complang.tuwien.ac.at> cross-posted to
c.l.lisp that M-expressions were never implemented, there were
responses that they were implemented several times. They just did not
catch on.

Lisp 1.5 was the first widely-distributed version of Lisp, apparently
a revision of the original implementation, rather than the big
revolution that Lisp 2 was supposed to be.

Lars Brinkhoff

unread,
Dec 7, 2018, 10:11:28 AM12/7/18
to
Anton Ertl wrote:
> when I recently <2018Jul1...@mips.complang.tuwien.ac.at>
> cross-posted to c.l.lisp that M-expressions were never implemented,
> there were responses that they were implemented several times. They
> just did not catch on.

The first of those alternatiev syntaxes was called M-expressions, the
other weren't. Though they were more or less similar in intent: to have
a more mainstream syntax for Lisp.

One of them actually did catch on somewhat: the original Macsyma was
written in a mix of Lisp and the more Algol-like CGOL.

Here's a small sample, and a manual:
https://github.com/PDP-10/its/blob/02d9eb9851105ab2f83244a2aae177ba9e77e44e/src/libdoc/utils.ejs2
https://github.com/PDP-10/its/blob/4e2ea8e4d851a0ea1f910c3001e5c2ddb9ff528c/doc/_info_/cgol.doc

Paul Rubin

unread,
Dec 7, 2018, 5:23:24 PM12/7/18
to
a...@littlepinkcloud.invalid writes:
>> like Lisp's parentheses, a historically grounded implementation hack
>> that people can learn to love, but it isn't something to get excited
>> about in its own right.
>
> I think that's a bit ahistorical. LISP 1.5 was supposed to have had
> its M-expressions but they didn't get used (and AFAIK the M-expression
> compiler was never finished) because people didn't see the point of
> them. Steve Russell preferred S-expressions and he won, right?

LISP 1.5 was before my time, but are we not saying the same thing?
Today's popular languages (Python, Javascript etc.) are basically Lisp
under the hood, but without S-expressions.

Elizabeth D. Rather

unread,
Dec 7, 2018, 7:47:38 PM12/7/18
to
On 12/6/18 5:41 PM, Paul Rubin wrote:
> Liang Ng <lsn...@gmail.com> writes:
>>> Sure there are tons of Forth compilers.
>> Examples please?
>
> If you have to ask that question after this long on clf, you're not
> really following Forth. But BigForth (which you were just using),
> Mecrisp, ciForth, amForth(?), and the usual commercial offerings all
> compile to native code.

In case you don't already know this, the "usual commercial offerings"
he's referring to include systems from FORTH, Inc. and MPE, which have
been compiling native code on a variety of processors since the late 1990's.

Cheers,
Elizabeth

--
Elizabeth D. Rather
FORTH, Inc.
6080 Center Drive, Suite 600
Los Angeles, CA 90045
USA

Elizabeth D. Rather

unread,
Dec 7, 2018, 7:53:36 PM12/7/18
to
On 12/6/18 6:57 PM, Liang Ng wrote:
> On Friday, 7 December 2018 11:41:45 UTC+8, Paul Rubin wrote:
>> Liang Ng <....@gmail.com> writes:
>>>> Sure there are tons of Forth compilers.
>>> Examples please?
>>
>> If you have to ask that question after this long on clf, you're not
>> really following Forth. But BigForth (which you were just using),
>> Mecrisp, ciForth, amForth(?), and the usual commercial offerings all
>> compile to native code.
>
> Thanks for confirming. As usual, no much organized documentation is available. So I only start to think about it when I need to use it.
>

Get a free evaluation version of SwiftForth (for Windows, MacOS, or
Linux) or SwiftX (interactive cross-compiler for 11 different targets)
here: https://www.forth.com/download/

All come with source and are extensively documented.

a...@littlepinkcloud.invalid

unread,
Dec 8, 2018, 3:38:19 AM12/8/18
to
That's true in a way, but only really because LISP is a really
fundamental model of computation. IMO LISP's S-expressions are
something to love because code and data are the same thing. Sure,
that's also true of a Turing machine, but LISP is (to say the very
least!) easier to reason about.

Andrew.

luser droog

unread,
Dec 11, 2018, 1:27:50 AM12/11/18
to
Lisp is not alone in this regard. Languages with the homoiconic
property include PostScript and, bizarrely, APL. M-expressions'
failure to catch on may in part be due to their disturbance of
this transparency.

--
Re-wrote that last sentence several times. Still not sure about it. :(

Albert van der Horst

unread,
Dec 14, 2018, 8:52:58 AM12/14/18
to
In article <1a5c7868-1dcc-4c67...@googlegroups.com>,
Are you the luser-dr00g from sexp.c in github?
I share your fascination with the original definition of McCarthy
of lisp and was equally scorned by Kaz.
I tried to base a forth lisp on that definition and never managed.
Apparently you managed through the use of c-macro's to stay close
to the original definitions. Wow!
Sadly, I have problems:

~/PROJECT2/ciforthcvs/lisp/lispdroog/sexp.c-master$ sexp<test
>Segmentation fault

Can this be caused by trying to compile sexp.c as 64 bits?
(My gcc may not be kosher, I can't compile gforth 0.7.3 either.)

Groetjes Albert
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

luser droog

unread,
Dec 17, 2018, 2:16:00 AM12/17/18
to
On Friday, December 14, 2018 at 7:52:58 AM UTC-6, Albert van der Horst wrote:
> In article <1a5c7868-1dcc-4c67...@googlegroups.com>,
> luser droog <mij...@yahoo.com> wrote:
> >On Saturday, December 8, 2018 at 2:38:19 AM UTC-6, a...@littlepinkcloud.invalid wrote:
> >> That's true in a way, but only really because LISP is a really
> >> fundamental model of computation. IMO LISP's S-expressions are
> >> something to love because code and data are the same thing. Sure,
> >> that's also true of a Turing machine, but LISP is (to say the very
> >> least!) easier to reason about.
> >>
> >
> >Lisp is not alone in this regard. Languages with the homoiconic
> >property include PostScript and, bizarrely, APL. M-expressions'
> >failure to catch on may in part be due to their disturbance of
> >this transparency.
> >
> >--
> >Re-wrote that last sentence several times. Still not sure about it. :(
>
> Are you the luser-dr00g from sexp.c in github?
> I share your fascination with the original definition of McCarthy
> of lisp and was equally scorned by Kaz.
> I tried to base a forth lisp on that definition and never managed.
> Apparently you managed through the use of c-macro's to stay close
> to the original definitions. Wow!
> Sadly, I have problems:

Yes, that's me. Oddly, the macro idea came from Kaz. He doesn't shy
away from expressing negative opinions, but he sure does have some
good ideas.

> ~/PROJECT2/ciforthcvs/lisp/lispdroog/sexp.c-master$ sexp<test
> >Segmentation fault
>
> Can this be caused by trying to compile sexp.c as 64 bits?
> (My gcc may not be kosher, I can't compile gforth 0.7.3 either.)
>
> Groetjes Albert

64 bit shouldn't matter I think. It doesn't do any weird pointer
tricks. It compiles for me on cygwin.

sh-4.4$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: /cygdrive/i/szsz/tmpp/gcc/gcc-6.4.0-5.x86_64/src/gcc-6.4.0/configure --srcdir=/cygdrive/i/szsz/tmpp/gcc/gcc-6.4.0-5.x86_64/src/gcc-6.4.0 --prefix=/usr --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc\
--docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target=x86_64-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --libexecdir=/usr/lib --enable-sh\
ared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --enable-__cxa_atexit --with-dwarf2 --with-tune=generic --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-grap\
hite --enable-threads=posix --enable-libatomic --enable-libcilkrts --enable-libgomp --enable-libitm --enable-libquadmath --enable-libquadmath-support --disable-libssp --enable-libada --disable-symvers --with-gnu-ld --with-gnu\
-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --enable-linker-build-id --with-default-libstdcxx-abi=gcc4-compatible
Thread model: posix
gcc version 6.4.0 (GCC)
sh-4.4$ rm sexp
sh-4.4$ CFLAGS='-Wno-implicit-int -Wno-implicit-function-declaration' make sexp
cc -Wno-implicit-int -Wno-implicit-function-declaration sexp.c -o sexp
sh-4.4$ ./sexp
>(QUOTE (A B))
(A B )
>sh-4.4$

I plan to revisit the code at some point and remove the weird character
emcoding.

Doug Hoffman

unread,
Dec 17, 2018, 7:55:30 AM12/17/18
to
On 12/6/18 10:41 PM, Paul Rubin wrote:

> If there were an efficient portable VM that could handle languages like
> JavaScript then it could be of some interest as yet another compiler
> backend. But that VM would have no resemblance at all to traditional
> Forth. It would need closures, garbage collection, memory safety, OOP
> and types at the lowest level probably, etc., and not just at the toy
> level like we see in the small Lisps that everyone ends up writing. I
> don't know if you understand how large a gap there is between that and
> Forth.

You make good points. Have you looked at Oforth? It
seems to nicely bridge the gap between classic Forth and something
into which Forth could evolve in the future. As I think you know Oforth
has closures, GC, OOP, and types at the lowest level. None of
this is add-on, rather it is all built into the lowest levels.

Oforth is pretty easy to learn, especially if one already knows classic
Forth. There are some very straightforward carry-overs ( if else then
begin again until ) and some things not so much ( while loops ). Do loop
is thankfully replaced by a less restrictive finite loop. All in all
worth a look.

-Doug

Albert van der Horst

unread,
Dec 17, 2018, 12:26:27 PM12/17/18
to

Paul Rubin

unread,
Dec 20, 2018, 10:35:37 PM12/20/18
to
Doug Hoffman <glid...@gmail.com> writes:
> Have you looked at Oforth? It seems to nicely bridge the gap between
> classic Forth and something into which Forth could evolve in the
> future. As I think you know Oforth has closures, GC, OOP, and types at
> the lowest level.

I'm aware of Oforth and it's interesting but I haven't tried it or
looked at it very closely. There are also 8th, Factor, and probably
some others. But, I've personally never been terribly enamored of
Forth's RPN syntax as a user feature. It's just something that makes
the VM and text interpreter implementation very simple, thus making
Forth itself very simple. Once you add the complexity of closures,
types, GC, and all that to Forth, you're most of the way to Lisp, so why
not get rid of the RPN as well? You can even add infix syntax (Python,
Javascript), static types (ML, Haskell), concurrency (Erlang), etc., if
you're into those sorts of things.

hughag...@gmail.com

unread,
Dec 20, 2018, 10:40:39 PM12/20/18
to
I agree with this.

Doug Hoffman

unread,
Dec 21, 2018, 7:45:55 AM12/21/18
to
On 12/20/18 10:35 PM, Paul Rubin wrote:
> Doug Hoffman <glid...@gmail.com> writes:
>> Have you looked at Oforth? It seems to nicely bridge the gap between
>> classic Forth and something into which Forth could evolve in the
>> future. As I think you know Oforth has closures, GC, OOP, and types at
>> the lowest level.
>
> I'm aware of Oforth and it's interesting but I haven't tried it or
> looked at it very closely. There are also 8th, Factor, and probably
> some others. But, I've personally never been terribly enamored of
> Forth's RPN syntax as a user feature. It's just something that makes
> the VM and text interpreter implementation very simple, thus making
> Forth itself very simple.

The stack offers more than just that, IMO. It's a dead simple way to
pass parameters between functions and enables nameless parameters, among
other things. Passing parameters interactively to individual functions
and inspecting what is returned is also trivial using the interpreter
and stack.


> Once you add the complexity of closures,
> types, GC, and all that to Forth, you're most of the way to Lisp, so why
> not get rid of the RPN as well?

I wasn't clear about what I meant about types at the lowest level. Forth
already has this with integers, doubles, and floats. Oforth adds to
these with big integers, strings, and arrays. As with classic Forth
there is no type checking.

The GC is transparent to the programmer. It removes complexity.


Many classic Forth definitions are written essentially the same
in Oforth. For example:

Forth:
: fact \ n -- n!
dup if dup 1- recurse * else drop 1 exit then ;

Oforth:
: fact \ n -- n!
dup if dup 1- fact * else drop 1 exit then ;

50 fact .
30414093201713378043612608166064768844377641568960512000000000000 ok

The OOP is built-in to Oforth (duck typing, no current object stack)
so one isn't faced with choosing which (of many) object extension to
use.

Today Oforth is only for desktop computers.
Not sure what the future holds.
I'm not saying that Oforth is better than classic Forth
for every problem. But Oforth contains some very interesting
ideas that may illustrate an evolutional path for future Forths.

-Doug

Paul Rubin

unread,
Dec 23, 2018, 6:48:27 PM12/23/18
to
Doug Hoffman <glid...@gmail.com> writes:
> The stack offers more than just that, IMO. It's a dead simple way to
> pass parameters between functions and enables nameless parameters

There's a related concept in Haskell called "point-free style" and it's
convenient sometimes, but other times leads to confusion. In the
absence of something like that, named parameters are ok. Using postfix
everywhere means it's not always easy to tell where the parameters begin
and end. Lisp (prefix) and everything else (infix) avoid that issue.

> Oforth adds to these [types] with big integers, strings, and
> arrays. As with classic Forth there is no type checking.

Do you really mean you can crash Oforth by interpreting integers as
pointers and that sort of thing? Or do you just mean that there is no
compile-time checking, i.e. there is runtime checking instead? I'm not
sure how the GC can know what the stuff in memory is, if there are no
runtime tags.

> The GC is transparent to the programmer. It removes complexity.

Sure, I just meant GC is another chunk of code in the runtime, that
complicates the implementation compared to traditional Forth.

> But Oforth contains some very interesting ideas that may illustrate an
> evolutional path for future Forths.

I guess that's possible. My Forth instincts aren't good enough to see
where I'd want to use it instead of something like MicroPython, once the
underlying computer is big enough. I'm used to thinking of Forth in
terms of very minimal target systems. Your sense of it is better than
mine though.

minf...@arcor.de

unread,
Dec 23, 2018, 8:30:21 PM12/23/18
to
Am Montag, 24. Dezember 2018 00:48:27 UTC+1 schrieb Paul Rubin:
> > But Oforth contains some very interesting ideas that may illustrate an
> > evolutional path for future Forths.
>
> I guess that's possible. My Forth instincts aren't good enough to see
> where I'd want to use it instead of something like MicroPython, once the
> underlying computer is big enough. I'm used to thinking of Forth in
> terms of very minimal target systems.

I am also in that camp but I wave also the DSL banner. The capability to build
simple DSLs with minimal effort is one of Forth's big advantages.

For many other programming disciplines standard Forth is obviously not the best
tool in the belt. But who cares, the toolstack is determined by other factors.

IMO the evolutionary path for Forth lies still in the realm of small target
systems, f.ex. small sensors or controllers (certainly not smartphones).
IOT is the buzzword.

But unfortunately parallelism/concurrency and communication are not discussed
(to my limited knowledge) in combination with Forth.

Doug Hoffman

unread,
Dec 26, 2018, 5:15:49 AM12/26/18
to
On 12/23/18 6:48 PM, Paul Rubin wrote:
> Doug Hoffman <glid...@gmail.com> writes:
>> The stack offers more than just that, IMO. It's a dead simple way to
>> pass parameters between functions and enables nameless parameters
>
> There's a related concept in Haskell called "point-free style" and it's
> convenient sometimes, but other times leads to confusion. In the
> absence of something like that, named parameters are ok. Using postfix
> everywhere means it's not always easy to tell where the parameters begin
> and end. Lisp (prefix) and everything else (infix) avoid that issue.

This is true. Reading a non-trivial postfix computation long after it
was written can be a challenge. OTOH, the lack of parentheses, not
having to remember operator precedence, and the ability to simply step
through any computation while seeing each atomic interim result can
have significant benefits.


>> Oforth adds to these [types] with big integers, strings, and
>> arrays. As with classic Forth there is no type checking.
>
> Do you really mean you can crash Oforth by interpreting integers as
> pointers and that sort of thing? Or do you just mean that there is no
> compile-time checking, i.e. there is runtime checking instead?

Sorry. Yes, you are right. Runtime checking/exceptions.


>> The GC is transparent to the programmer. It removes complexity.
>
> Sure, I just meant GC is another chunk of code in the runtime, that
> complicates the implementation compared to traditional Forth.

But that is just the implementer's complication.


>> But Oforth contains some very interesting ideas that may illustrate an
>> evolutional path for future Forths.
>
> I guess that's possible. My Forth instincts aren't good enough to see
> where I'd want to use it instead of something like MicroPython, once the
> underlying computer is big enough.

I see that MicroPython has GC and OOP.


> I'm used to thinking of Forth in
> terms of very minimal target systems.

The Forth I normally use occupies 4MB on disk and is comprised of about
200 text source files on top of the kernel. It's designed for
programming on the desktop Mac OS. MacFOrthOnVFX, an IDE.


> Your sense of it is better than
> mine though.

I don't think so. I've never gone near embedded work. Just desktop. I do
know that I disliked Fortran enough to switch to Forth and haven't
looked back.

-Doug

Paul Rubin

unread,
Dec 29, 2018, 2:31:16 PM12/29/18
to
Doug Hoffman <glid...@gmail.com> writes:
>> Sure, I just meant GC is another chunk of code in the runtime, that
>> complicates the implementation compared to traditional Forth.
> But that is just the implementer's complication.

Sure, though a traditional characteristic of Forth is that the line
between the user program and the language implementation is blurred or
erased, so you can redefine system words and so on. That means that the
implementer's complication is now also the user's complication. I don't
claim that's a good idea, but it makes Forth unique and interesting.

> I see that MicroPython has GC and OOP.

Yes, and the memory and cpu costs are considerable. MicroPython is only
practical on processors that would have been unaffordable in Forth's
heyday. MicroPython barely works on the BBC Microbit which has 256k of
program flash and 16k of ram, while eForth works on those super cheap
STM8 boards that have 8k of flash and 1k of ram. Plus, you may face
issues of unpredictable GC delays if you're doing something realtime.
But, these days 16k of ram is tiny by many standards.

>> Your sense of it is better than mine though.
> I don't think so. I've never gone near embedded work. Just desktop.

Well, I've never done any actual embedded Forth programming, and I'm
sure you've written a lot more desktop Forth code than I have.

I'd agree that a desktop application is less likely to care about small
GC delays, so unless it's memory constrained, GC is frequently a big win.

Doug Hoffman

unread,
Dec 31, 2018, 4:18:14 AM12/31/18
to
On 12/29/18 2:31 PM, Paul Rubin wrote:
> Doug Hoffman <glid...@gmail.com> writes:
>>> Sure, I just meant GC is another chunk of code in the runtime, that
>>> complicates the implementation compared to traditional Forth.
>> But that is just the implementer's complication.
>
> Sure, though a traditional characteristic of Forth is that the line
> between the user program and the language implementation is blurred or
> erased, so you can redefine system words and so on. That means that the
> implementer's complication is now also the user's complication.

I've recently been learning Oforth. While there are a few user-settable
options for the GC such as how often the GC runs and the minimum
allocated memory for the GC to run, I've not felt the need to touch the
defaults. So there has been zero added complication for me.


>> I see that MicroPython has GC and OOP.
>
> Yes, and the memory and cpu costs are considerable. MicroPython is only
> practical on processors that would have been unaffordable in Forth's
> heyday. MicroPython barely works on the BBC Microbit which has 256k of
> program flash and 16k of ram, while eForth works on those super cheap
> STM8 boards that have 8k of flash and 1k of ram. Plus, you may face
> issues of unpredictable GC delays if you're doing something realtime.
> But, these days 16k of ram is tiny by many standards.

On Ebay there's a pyboard with 1024k flash and 192k of ram. Surely in
the future larger memory boards will be available.

My first PC, a Macintosh, had 64k of rom and 512k of ram. It could run
Excel in a full GUI in 1985.

>>> Your sense of it is better than mine though.
>> I don't think so. I've never gone near embedded work. Just desktop.
>
> Well, I've never done any actual embedded Forth programming, and I'm
> sure you've written a lot more desktop Forth code than I have.
>
> I'd agree that a desktop application is less likely to care about small
> GC delays, so unless it's memory constrained, GC is frequently a big win.

After using Oforth I'd say that GC is a very big win. I've lost track
of the time I've spent fixing memory leaks in Forth. I find
dynamically sized objects for strings, arrays, etc. to be the most
useful because I never know in advance how large the object needs to be
or how many of them I'll need.

-Doug


Paul Rubin

unread,
Dec 31, 2018, 5:04:27 AM12/31/18
to
Doug Hoffman <glid...@gmail.com> writes:
> I've recently been learning Oforth....there has been zero added
> complication for me.

Right, so I'd claim that Oforth is not really Forth (which is fine).
It's Forth-inspired, but rather different in how it works underneath and
conceptually.

> On Ebay there's a pyboard with 1024k flash and 192k of ram. Surely in
> the future larger memory boards will be available.

Even further, for $5 you can get a Raspberry Pi Zero with 512MB of ram
and a MicroSD socket (add a few more bucks for a multi-GB flash card) so
memory is really not an issue for lots of things now. CPUs are also
many orders of magnitude faster than before. That enables a lot of
programming approaches that wouldn't have been practical in the old
days.

> After using Oforth I'd say that GC is a very big win. I've lost track
> of the time I've spent fixing memory leaks in Forth.

Yep! Welcome to enlightenment ;-).

minf...@arcor.de

unread,
Dec 31, 2018, 7:47:39 AM12/31/18
to
Am Montag, 31. Dezember 2018 10:18:14 UTC+1 schrieb Doug Hoffman:
> After using Oforth I'd say that GC is a very big win. I've lost track
> of the time I've spent fixing memory leaks in Forth. I find
> dynamically sized objects for strings, arrays, etc. to be the most
> useful because I never know in advance how large the object needs to be
> or how many of them I'll need.

+1 as one says today ;-)

Enhance Forth with dynamic arrays of nested structs, and it'll be prepared
for the 21st century.

franck....@gmail.com

unread,
Jan 2, 2019, 12:37:52 AM1/2/19
to
Le lundi 31 décembre 2018 11:04:27 UTC+1, Paul Rubin a écrit :
> Doug Hoffman <glid...@gmail.com> writes:
> > I've recently been learning Oforth....there has been zero added
> > complication for me.
>
> Right, so I'd claim that Oforth is not really Forth (which is fine).
> It's Forth-inspired, but rather different in how it works underneath and
> conceptually.
>

Hello and happy new year to all,

Hello Paul,

Sorry for the late answer (I'am on holiday with almost no access to Internet.
Yes it is still possible :) )

I don't understand your point. What is conceptually different between Forth
and Oforth ?

I know only one principle : a Forth is basically an outer interpreter that
read tokens (one at a time), find words and run corresponding code.
(This naturally leads to RPN notation, imo).

And with a mechanism to execute words during compilation (immediate words or
dual words) that allow to generate new definitions into a dictionary.

That's all. And that's exactly what Oforth is...

You can think as GC and OOP as extensions (and such extensions exist in Forth
too). Having them as built-in features does not make Oforth "conceptually"
different.

Regards,
Franck

Paul Rubin

unread,
Jan 2, 2019, 8:15:04 PM1/2/19
to
franck....@gmail.com writes:
> I don't understand your point. What is conceptually different between Forth
> and Oforth ?
>
> I know only one principle : a Forth is basically an outer interpreter that
> read tokens (one at a time), find words and run corresponding code.
> (This naturally leads to RPN notation, imo).

Hmm, well, Forth is in the eye of the beholder so I don't claim this is
objective truth, but I think of Forth as being minimalistic, with
one-pass compilation, no typechecking of any sort, preference for linear
sequencing over tree structure, very direct mapping of Forth words to
machine operations, and the general flavor of programming in assembly
language. Oforth with runtime types and garbage collection seems to me
more in the Lisp tradition (and I like Lisp) than Forth. But, I haven't
tried Oforth yet. One of these days!

franck....@gmail.com

unread,
Jan 3, 2019, 1:03:53 AM1/3/19
to
I don't see how Oforth could be comparable to Lisp, but I don't know Lisp
very well.

Oforth is minimalist imo if you compare it with :
Forth + OOP extension + GC extension + big integer extension.
( + multi-threading extension if built with multi-threading support)
( + Float extension if built with float support)
( + TCP extension if build with TCP support).
( + FFI extension if build with FFI support).

The executable is about 90 ko with a built that supports all this
(it uses OS libraries for TCP, threads, floats and ffi).

And memory allocated (by Oforth) at startup is 128 Ko, with 45 Ko free.

Btw, you have runtime checking only for method dispatch and it is 10 lines in
assembler. If you write words, you have no runtime checking.

But I let you try it ... one of these days :) !

minf...@arcor.de

unread,
Jan 3, 2019, 3:42:03 AM1/3/19
to
What would Oforth offer better than Lua?
I mean with FreeBSD dropping Forth for Lua.

franck....@gmail.com

unread,
Jan 3, 2019, 6:12:23 AM1/3/19
to
I don't know well about Lua, but Oforth generates native code on the flow
(in a one pass compilation, using the outer interpreter).

The 128 Ko allocated at startup are 2 pages of 64 Ko, one for native code
( with 30 Ko free) and one for memory allocation (dictionary + heap,
with 15 Ko free).

This contains (among other things... ) an assembler + native code generator +
optimizer. The code generator is written in Oforth itself and loaded at startup.
This also contains all basic objects definition (collections, arrays, files,
...).

So, I would say speed, but as I don't know Lua, perhap's I'm wrong (I don't
know if Lua is interpreted or compiled on the flow).


minf...@arcor.de

unread,
Jan 3, 2019, 7:25:45 AM1/3/19
to
AFAIU the FreeBSD team is not so much concerned about speed for their
bootloader (although Lua has a JIT compiler) but about flexible interpretation
of parameter files, easy integration with C, and code maintainabilty.

Smaller memory footprint could be a bonus though. And Forth's typical ease
to create a DSL for parameter file interpretation. I don't know how well
Oforth interacts with C (Oforth being embedded, or Oforth calling C functions
and libraries).

Anyhow, the dice seems cast already.

a...@littlepinkcloud.invalid

unread,
Jan 3, 2019, 8:22:52 AM1/3/19
to
Paul Rubin <no.e...@nospam.invalid> wrote:
> franck....@gmail.com writes:
>> I don't understand your point. What is conceptually different between Forth
>> and Oforth ?
>>
>> I know only one principle : a Forth is basically an outer
>> interpreter that read tokens (one at a time), find words and run
>> corresponding code. (This naturally leads to RPN notation, imo).
>
> Hmm, well, Forth is in the eye of the beholder so I don't claim this
> is objective truth, but I think of Forth as being minimalistic, with
> one-pass compilation, no typechecking of any sort, preference for
> linear sequencing over tree structure, very direct mapping of Forth
> words to machine operations, and the general flavor of programming
> in assembly language.

I mostly agree with that. However, I think that Forth's stack (for
RPN) is really epiphenomenal rather than essential. The defining
characteristic of Forth is perhaps more of an attitude than a feature
set: that everything non-essential should be removed. Of course
"essential" is partly a matter of taste, and that's why it's important
that to begin with Forth was the product of a single mind. The design
of the language came not from any theoretical considerations but from
the combination of that attitude and the needs of the applications
that Forth Inc worked on.

Also, pre-FIG Forth was always multi-tasking, with the task the basic
unit of execution. This is in a natural and easy way of responding
promptly to real-time demands. It's essential that tasks be very small
because you want to be able to have many of them. That idea of a tiny
task context of just two stacks and a few user variables drove the
design of the whole system. Any decision which required the addition
of even a single byte to every task had to be considered extremely
carefully.

Andrew.

Paul Rubin

unread,
Jan 3, 2019, 3:11:18 PM1/3/19
to
franck....@gmail.com writes:
> But I let you try it ... one of these days :) !

Ok, I downloaded the src.zip file from oforth.com.

1) ran "make" and it made a preproc file but no oforth. Checked
makefile and saw I have to run "make all", so did that, which built
oforth.

2) running oforth complained that OFORTH_PATH was not set, and left the
tty in raw mode (it shouldn't leave it that way). The error message
says "See INSTALL.TXT" file but that file is missing from the zip.
I fixed the tty settings and set OFORTH_PATH and tried again.

3) ./oforth then segfaults immediately. I haven't tried to debug it.

Suggestions/requests:

1) the distro file should include everything: sources, INSTALL.TXT,
documentation source and scripts for building the doc pdf, etc.

2) Exiting oforth abnormally should restore the tty modes

3) if possible, running oforth shouldn't require user to set
OFORTH_PATH: it should assume something reasonable.

4) There should be a "make install" target

5) "all" should be the default make target.

A quick look at the sources show it is nice and compact! Around 7 kloc
of C. The docs are also very good. I'm looking forward to getting it
working and trying it.

NN

unread,
Jan 3, 2019, 3:15:30 PM1/3/19
to
"""
However, I think that Forth's stack (for
RPN) is really epiphenomenal rather than essential.
"""

A forth without stacks would not really be a forth.
Or at least one I cant imagine !

Doug Hoffman

unread,
Jan 3, 2019, 8:00:13 PM1/3/19
to
I had none of those problems because I just downloaded and used one of
the three pre-compiled distributions. Quick and easy. I did have to
set PATH. Simple. INSTALL.TXT is included.

Later if you want a custom build (leave out TCP or something?) you
could try the below again.

-Doug

Doug Hoffman

unread,
Jan 3, 2019, 8:02:33 PM1/3/19
to
+1

-Doug

franck....@gmail.com

unread,
Jan 3, 2019, 11:28:51 PM1/3/19
to
Thanks for those returns.

There is a distro with all those files and with a binary already built.
The sources are here only if you want to rebuilt the binary.
(I will update the source distro to include all the files).

If you run oforth without option, it should wait for input and not seg fault.
On what system are you running ?

To run oforth with the interpreter, run : oforth --i

But it will not work if you don't install the distro (with all the files) into
the OFORTH_PATH directory. After, if you want, you can update the binary with
the one you just built.


Paul Rubin

unread,
Jan 4, 2019, 2:00:10 AM1/4/19
to
franck....@gmail.com writes:
> If you run oforth without option, it should wait for input and not seg fault.
> On what system are you running ?

debian 9, x86-64.

> To run oforth with the interpreter, run : oforth --i
> But it will not work if you don't install the distro (with all the
> files) into the OFORTH_PATH directory. After, if you want, you can
> update the binary with the one you just built.

Ok, now I installed those files from the other zip, and oforth no longer
crashes, and oforth --i works. But it is confusing: can you make a
distro that includes sources and docs and everything in one zip or tgz?
Neither current zip file seems to include the docs.

franck....@gmail.com

unread,
Jan 8, 2019, 6:57:46 AM1/8/19
to
Yes, I will add this full distro (including the manual) for the next
release.

Franck

0 new messages