h3rald / min

A small but practical concatenative programming language and shell
https://min-lang.org
MIT License
310 stars 23 forks source link

IDEA: Eliminate stack-popping versions of functions #104

Closed drkameleon closed 3 years ago

drkameleon commented 3 years ago

I have noticed that many functions have an alternative version with a ! suffix, e.g. print just prints (and leaves the argument on the stack), while print! pops the item from the stack and prints it.

Wouldn't it be cleaner to just eliminate all these functions (since they are quite a lot + you have to create one all the time) and simply "alias" ! to pop?

Let me explain what I mean...

For me, "Hello" print! is the same - or 99% the same (given your implementation) - as "Hello" print pop.

So, my point is: instead of having a print and a print!, a notice and a notice! and so on... wouldn't it make more sense to just set ! to a single stack-pop?

In that case, a print! would be interpreted as print pop, provided that the ! is not considered (not permitted) as part of an identifier and parsed as a different token.

drkameleon commented 3 years ago

As a sidenote to how I do it in Arturo:

Basically, it's the reverse. Functions do pop the stack by default. (I prefer it all neat and clean + it's easier to avoid stack overflows or maintaining an enormous stack). For example, when you call a print, you're 100% sure that nothing's left on the stack after the call.

So... I was thinking how would I go about having an assignment that also returns (and have chained assignment statements)?

Here's the idea:

a: 3     ; that worked and works fine

a: b: 3  ; this did not and does *not* work:
         ; basically, this would pop 3 from the stack, assign it to `b`, 
         ; and then we'd have to pop something from the stack 
         ; so that we assign it to `a` - but what if there is nothing left?

a: b: push 3  ; `push` in this case re-pushes its argument (like a `dup`)
              ; - after that, instead of 3, the stack has two 3's -
              ; so that `b:` pops the first one, and `a:` pops the next

a: b:& 3  ; and since Arturo supports symbol aliases - that is:
          ; identifiers are one thing, symbols are a different case
          ; and symbols are just the "short" version of an identifier
          ; we assign `&` to `push`. And the whole thing works quite elegantly. :)

; To make it clearer, lexer- & parser-wise, the tokenization of the expression above is:
; "a:" -> label, "b:" -> label, "&" -> symbol, "3" -> integer
; so spacing of course does not matter. 
; `a:b:&3` would work fine as well ;-)
h3rald commented 3 years ago

Ahhhh I wish Github re-added the possibility to convert issues into discussions and vice versa... 😛

Anyhow, yes, indeed. That makes sense and yes, I've been trying to establish a convention of destructive symbols ending with a !.

It would actually make a lot of sense to add "autopopping" in this way. Not sure if I'd build it in the parser itself, for a few reasons:

The main problem that I have with this is that it would have to be a "one-off", while for sigils they are (more or less) first-class citizens and they operate at the start of a symbol.

I wonder if we could generalize this concept without making the language heavier and weirder than it actually it.

drkameleon commented 3 years ago

You have some interesting points here. I guess I'll have to take some time and dive into the internals of the interpreter and then perhaps I'll be able to form a more... complete opinion. :)

h3rald commented 3 years ago

Ehhh well, it's actually pretty cool and saves me from implementing loads of stupid symbols.

Two lines for the implementation basically made me remove dozens of lines of essentially duplicated code... autopopping it is! Will be available in the next version.

drkameleon commented 3 years ago

Ehhh well, it's actually pretty cool and saves me from implementing loads of stupid symbols.

Two lines for the implementation basically made me remove dozens of lines of essentially duplicated code... autopopping it is! Will be available in the next version.

It's called exchange of ideas haha.

Me, after playing with Min's code and seeing how you've structured the libraries, I've decided to proceed to a major overhaul of Arturo's system libraries (Basically, make it all a bit more independent, template-free, more flexible and not as tightly linked to bytecode instructions which would also permit re-definition of everything, builtin functions included).

The result is rewritting or reformatting tons of stuff from scratch: https://github.com/arturo-lang/arturo/tree/add-builtin-function-type. Whenever I manage to make it bug-free (and provided the earthquakes leave us alone - it's been 6 days that we've been practically shaking all the time here in Granada), I'll merge it to Master.

h3rald commented 3 years ago

Implemented in v0.31.0.

h3rald commented 3 years ago

About your rewrite... what do you mean? What did you change exactly? I actually really like your builtin template! I should rewrite all min to use something like that! 😅

I particularly like the embedded documentation... I cobbled together an integrated doc system recently but your way of managing it looks great, and easier to keep up-to-date!