Welcome to Ripen, a stack-based scripting engine with highly readable syntax, that can be implemented with little code and effort in a language like C++ or D. It's informed by RetroForth and PostScript, but diverges from either in important ways, not least due to its string-threaded nature. Surprisingly, Ripen only seems to be about 6 times slower than the host language on a quick test — much better than for other language families.

Ripen is based on the principles explained in this interpreter construction tutorial. The point is having a tiny engine, easily copy-pasted into any application, even hidden inside a bigger module. For this reason, the default vocabulary is kept small.

As of 2 December 2019, there are two implementations: the browser-based one embedded above, and the original Python prototype. They differ in some details, but should work largely the same.

Overview

At a basic level, Ripen works like most similar languages:


	? 3 2 + . cr
	5
	 
	ok
	? :squared dup * ;
	ok
	? 3 2 + squared . cr
	25
	 
	ok

Note the lack of a space after the colon: Ripen doesn't use parsing words, instead relying on sigils to achieve similar functionality. E.g. variables work like this:


	? 3 2 - >a
	ok
	? $a . cr
	1
	 
	ok

On the minus side, there are no proper quoted strings; words in parentheses are simply joined by a space. Note that the closing paren is a word too, so it must be space-separated itself, on both sides:


	? (  Hello,  world!  ) .
	Hello, world!
	ok

Speaking of which, comments are C-style instead. They're also executable, so you'll want to leave them on the outside of word definitions:


	? /* s -- */ :say . cr ;
	ok
	? ( Hello, world! ) say
	Hello, world!
	 
	ok

Last but not least, control structures are inspired by Logo, to make them a lot more readable than in other stack-based languages:


	? 3 2 + 3 2 * < [ ( Yes! ) . ] iftrue
	Yes!
	ok
	? [ $i . cr ] 3 times
	0
	 
	1
	 
	2
	 
	ok

In the above, square brackets delimit lists of words, that control structures treat as blocks of code. Curly braces are synonymous:


	? { dup * } /squared
	ok
	? 5 squared . cr
	25
	 
	ok

The reason both are provided is that lists of the same kind can't nest. And yes, that's another way to define words; beware that an older definition by the same name will be overwritten, and the entire script will see the new one right away.

More details to come; in the mean time, take a look at the source code. This page demonstrates how to embed and extend the JS version.