milliForth
github.com
github.com
The sectorlambda implementation of Binary Lambda Calculus is shorter yet at 383 bytes [1].
And the BLC self-interpreter is only 29 bytes [2].
> A FORTH in 422 bytes — the smallest real programming language ever, as of yet.
That may still be true, as BLC is an esoteric programming language.
I own a couple hard copies of this before it got popular. Most folks will only ever encounter the above PDF. It is absolutely wonderful book written in such a matter of fact style, the only thing comparable are the works of Nils Holm.
Lisps are given low-level hardware access primitives (peek/poke etc) when they are designed for bootstrapping an OS, and low-level OS primitives (such as system calls) when they are designed for bootstrapping a rich environment on a different OS. Basically the same primitives as Forth for the same purposes.
This is a very cool project, author, love it!
I think it was around 2000 lines of assembly code to implement most of the FORTH-83 standard although mine was unusual in that it did not support the block-based I/O that was common on “language system” FORTHs but instead it had handle-based API for accessing files similar to Unix, C and MS-DOS in version 2 and up.
The programming environment was a lot like Linux overall in that I’d use an ed or vi clone to edit files, then run something like an assembler or C compiler. I’d run my FORTH binary and it would present an interactive environment like most FORTHs.
Almost a zen like experience - you, the machine and your focus. No world.
pop ax
neg ax ;sets carry flag if nonzero
sbb ax,ax
push ax
And another two bytes in DOCOL: ;add ax,4
;mov si,ax
xchg ax,si
lodsw
lodsw
Maybe even free up a word register to always hold the address of DOCOL, then you only need two bytes at each colon definition. If it's possible without adding any extra instructions, this should save 4 bytes in total (one stosw in COLON, the DOCOL.addr variable, one lodsw in the above version of DOCOL)I'll futz around with making DOCOL's address as a register and see if I can make that work, though I don't know if that will work since I think some of the mechanisms in place have additional functions.
EDIT: So, I don't think this will work. I'd be using `dx` to store DOCOL's address, but this appears to get clobbered somewhere, fixing which would outweigh the 1 byte benefit you end up actually getting. I'll keep thinking about it though!
I've removed some primitives further from milliFORTH, but I haven't touched the arithmetic base. I hadn't seen those issues on sectorFORTH though, very interesting - I will look into it!
It's a good reason to at least try to implement your own sometimes, rather than just use libraries - even if you end up just using the supported external dep, you'll understand it a lot better.
(not saying that's the case here, just that you reminded me of that with your convergance...)
"GreenArrays is shipping its 144-core asynchronous chip that needs little energy (7 pJ/inst). Idle cores use no power (100 nW). Active ones (4 mW) run fast (666 Mips), then wait for communication (idle).
Tight coding to minimize instructions executed will minimize power. The programmer can also reduce instruction fetches, transistor switching and duty cycle."
It is like the elegance of Forth in low power, multi-core hardware.
I do have to note that the linked video is from 2013 so I assume they've moved on from that.
Forth is great, but colorForth takes it one step to far.
It is very difficult to know when to not add a seemingly cool feature. Specially when you where right against most odds before.
[0] https://en.wikipedia.org/wiki/ColorForth
[1] https://ratfactor.com/forth/the_programming_language_that_wr...
The Moore Microprocessor Patent Portfolio was very lucrative. Eventually it ended up with a patent marketer. Nearly everyone doing processors had to buy in.
And as the inventor Chuck got his share out of it...
https://web.archive.org/web/20071226155608/http://www.linuxe...
Guix bootstraps from a tiny audited binary, and milliForth could be used for the same purpose.
Imagine bootstrapping a full Linux distro from a milliForth binary and source code for everything. Everything would be fully auditable, no Trusting Trust problem, and a full Software Bill of Materials.
When designing a multi-party contract, the essential problem is that two people specify the terms they each want to apply to any case in which the funds must be spent, then these two sets of requirements must be merged into a single program. This is, in general, difficult to do securely. We can establish conventions that are relatively easy to follow, but it would be a lot nicer and more powerful if we could syntactically enforce that both sets of requirements are enforced in the combined program.
Concatenative languages like Forth meet this requirement nicely. If you represent the spend requirements as a program, then combining the two programs together in such a way that they both are equally enforce is as simple as literally concatenating the two programs together.
For example, suppose Alice's requirement is that Alice signs the transaction with her key, and Bob's requirement is that Bob signs with his key, and the spending transaction is after some specified time T. Expressed in bitcoin script:
Alice: <AlicePubkey> CHECKSIGVERIFY
Bob: <T> CHECKLOCKTIMEVERIFY DROP <BobPubkey> CHECKSIGVERIFY
The combined script that meets both these sets of requirements is as simple as putting Alice's script, then Bob's, unaltered:
Alice&Bob: <AlicePubkey> CHECKSIGVERIFY <T> CHECKLOCKTIMEVERIFY DROP <BobPubkey> CHECKSIGVERIFY 1
(The `1` at the end is a quirk of bitcoin that it has to finish with a non-zero value on the stack. This combined script could also be simplified in a couple of ways. Also there's a couple of ways in which this can fail in practice. Alice's script could contain OP_RETURN, for example, which causes the entire script to become unspendable. Or a mismatched IF/ELSE. A better designed and strongly typed Forth dialect would fix these issues.)
Bitcoin's Forth is not type checked, but suppose that it were. And furthermore, suppose that it had a powerful dependently typed system that captured various key signing and stack requirements at the type level. It could be used to track not just what a program does, but also the properties of a program. Alice could put a constraint in her program that says "lock time can be no later than April 2024," and this becomes part of both the input and output type requirements of her program. Then when Bob's program is specified with T=15 May 2024, then his program no longer type checks when concatenated to the end of Alice's.
No one has yet written a system like this, but it would be really powerful if it did exist. Alice writes here smart contract conditions all by lonesome self, and Bob writes his. Then they literally concatenate one program to the other, and if it type checks then Alice and Bob can be certain that both sets of conditions are satisfied.
I don't use or study anything crypto related, so I'm just guessing, but wouldn't something like Prolog work for describing contracts?
The actual spend condition language would be lower level, however, and Forth-like languages are a good fit for this part of the stack.
[1] https://github.com/BlockstreamResearch/scriptless-scripts
[2] https://tlu.tarilabs.com/cryptography/introduction-to-script...
That's a stretch. Replacing timelocks with hashcash (or equivalent) is hardly the same thing.
But generally speaking "scriptless scripts" suffer from the need for interactive construction. There's a long way to go until scriptless scripts is a full replacement for script, if it is even possible.
> suffer from the need for interactive construction.
Interactive construction is already widely in use in relative timelocks' prime application of payment channels.
Do you have a citation for a block-based relative timelock? The only such things I've seen are verifiable delay functions, which are a lot more like hashcash.
What about absolute lock times? Those are far more interesting in applications of business logic, like logistics contracts. Most of which require non-interactive state updates.
Don't you find 2nd layers like Lightning interesting, as a way to scale far beyond the limited L1 capacity?
> Do you have a citation for a block-based relative timelock?
See the thread starting with https://lists.launchpad.net/mimblewimble/msg00546.html
> What about absolute lock times?
Those are trivially supported in any Mimblewimble chain.
Your link to the mailing list thread describes essentially the same approach that bitcoin has for dealing with lock times. I would not normally describe this as “scriptless scripts,” which I have understood to me using the signing operation itself to achieve some goal that would otherwise be done in script. The locktime here is still enforced by special cased code of the consensus algorithm. If the number of things you want to do are fixed and enumerable then I suppose this is a valid approach. But it does not allow for general, arbitrary, future-defined constraints.
To give a concrete, simple example: show me how to do a return peg validation on scriptless scripts. If it can’t even do that, it is not a replacement for scripts.
Satoshi promised no such thing. That sounds more like an Ethereum promise (to which I don't subscribe).
> show me how to do a return peg validation on scriptless scripts
How does one do return peg validation in bitcoin script?
Re: bitcoin vs. ethereum, the bitcoin community pre-ethereum was very invested in the idea of decentralizing all the things. I remember: I was there and part of that history. But over time people interested in more than just payments or the bitcoin asset have left or switched to ethereum. Originally expressive smart contracting was very much in scope.
If you're talking about SPV inclusion on another chain, wouldn't one also need to verify cumulative diff on that other chain (if PoW based) ?
The point is that smart contracts actually do something other than “authorize payment”, and fancy Schnorr signing modes don’t come close to replicating those capabilities.
And so long as there is a need for a programmable verification architecture, Forth-like languages are prttty ideal.
If you include formal verification tools as part of the stack then you can verify the tools by eye, type them in, and use them to verify the function of the stack. Admittedly Forth is tricky to do here, but something like lisp/scheme/wat can actually be proven out with say microkanren.
From there we can trust the software stack.
: - sp@ @ nand 1 + + ;
or as it appears in the hello_world.FORTH file : dup sp@ @ ;
: invert dup nand ;
: negate invert 1 + ;
: - negate + ;
There is of course no benefit to this thing at all other than reclaiming the crown from those deviant lispers... well I suppose if you're making a your own computer from scratch like https://www.homebrewcpuring.org/ it might be a useful starting point.Disclaimer: I've never written forth, so this may not be valid for any particular forth implementation.
More seriously, a metacircular example to draw from would be: https://github.com/kragen/stoneknifeforth
The included py_autotype.py takes forever, but nothing outputs in the qemu vm as it is running.
WSL 2 does have an X server running (xeyes works).
Update: running the script against gedit doesn't work either... it's not a qemu issue
Keep in mind, nothing SHOULD output while it's running, until you get to the very end and there's a 'hello world' printed.
This being said, the autotype's lethargy severely irks me. But I couldn't make it go faster, as pyautogui kept tripping up. If someone finds a better way (i.e. a way that isn't my first random thought), it will be much appreciated.