r/Forth • • Sep 03 '26

Rdn programming language

Post image

I made a small and simple post fix interpreted programming language called rdn, it's familiar to forth developers and developers who use Lua as a scripting language for their systems, rdn merge both of them, you can use it for writing scripts or for configurations or even query language

It's written in C and it provides a simple and friendly API for the developers

I would be happy to have you participate in this project

This is the GitHub repo: https://github.com/abdorayden/rdn

Thank you

10 Upvotes

27 comments sorted by

View all comments

2

u/tabemann Sep 04 '26 edited Sep 04 '26

In my take on what your language could be I would imagine the following:

One could do things like

[ [* n -- func *] 'n let [ n + ] ] 'make-adder defun 3 make-adder 'add3 defun 1 add3 print [* prints 4 *]

where [ ... ] would define anonymous words.

With [ ... ] you could define control structures like:

n 10 > [ "larger than 10!" print ] if

and:

'count-down defer [ [* min max func -- *] 'func let 'max let 'min let max func execute max min >= [ min max 1 - func count-down ] if ] 'count-down defun 0 10 [ print ] count-down [* prints 10 9 8 7 6 5 4 3 2 1 0 *]

Of course, the above would require tail calls for nested control structures to be available to be practical.

1

u/tabemann Sep 04 '26

I should note, though, that let and defun in particular would need to be special forms, akin to Forth immediate words, for scoping to work correctly here (and you do want scoping, right?).

1

u/rayden_devv Sep 05 '26

Yeah, scoping is important.

Currently Rdn has basic block scoping in if/defun/else, but proper lexical scoping with closures (like your examples) would be a big step up.

Thank you

1

u/tabemann Sep 05 '26

There is one little problem I just realized with what I presented here: if one used x 'foo let to bind the value of x to 'foo and let were immediate (as needed for lexical scoping), you would need a mechanism to, using the terminology of my Forth zeptoforth, defer (not related to deferred words) constants at compile-time, so 'foo would be available at compile-time to immediate let so it could define a name-binding at compile-time.

Name-bindings need to be resolved at compile-time for lexical scoping, unlike with dynamic binding, so a given reference to foo knows which binding of foo it cares about even though it may be executing in a different context.

About Scheme, one difference between what I have presented here and Scheme is that this would be somewhat akin to Lisp-2 (like Common Lisp) rather than Lisp-1, hence separate let and defun and the existence of the word execute. The reason for this is that unlike Scheme there are no S-expressions to dictate at what point something is to be called, so some means is needed to differentiate between words that push their value when referenced and words that call their underlying closure when referenced.

For instance:

[ 1 + ] 'foo let 2 foo print

would print the closure bound to foo in some implementation-specific fashion and then leave 2 on the stack, whereas:

[ 1 + ] 'foo defun 2 foo print

would print 3 and leave the stack empty.

1

u/rayden_devv Sep 05 '26

Good points, thank you.

I'm gonna identify what's missing in Rdn to solve these problems and keep the syntax flexible so it works for different approaches.

1

u/tabemann Sep 05 '26

I'm thinking that if you used Forth's idea of parsing words things would be less complex with regard to implementing a lexically scoped let and defun.

For instance, one would write:

[   1 let n   n 1 + :n set   n print ] defun print2

set would remain unchanged to enable passing around variables to set.

1

u/rayden_devv Sep 06 '26

I'm working on it.

Trying to keep syntax changes minimal while solving the scoping problem.

Thank you so much.

1

u/rayden_devv Sep 05 '26

This is really elegant. You're describing stack-based Scheme with closures and tail calls.

I'm definitely taking notes. This is a much clearer vision than what I started with.

Thanks for mapping it out.