Idk if this is already a thing or not but the string code passing around a pointer and an integer makes me think that porth really needs some sort of structured data type or at least a simple product type like a tuple that enables you to move coupled data around the stack as one unit.
@eyemotif2 жыл бұрын
even if its not very programming language-y i think even just hardcoding pairs (and maybe triples too) would help a lot
@minamagdy41262 жыл бұрын
That's the plan. He said he will add it at some point as syntactic sugar
@nexovec2 жыл бұрын
@@eyemotif That would kind of cripple the language, but it is needed :D
@WilcoVerhoef2 жыл бұрын
a b tup2 // or (a,b) // syntactic sugar for the same thing This operation `tup2` changes NOTHING on the stack, it just changes how the type system interprets the values. print, dup, swap, compare etc will need to be implemented for tuples polymorphically. print = let a b in b print a print end dup = let a b in a b a b etc. Meaning that depending on the type of the element on the stack, the correct function implementation is chosen. The type does not need to be stored at runtime, since types are known in advance the correct implementation can just be compiled in.
@minamagdy41262 жыл бұрын
When I said "That's the plan", I meant structs are well on their way to being fully conceptualized. I have no idea as to the likelihood of tuples, just what I see on structs in the vods.
@itallstartedwhen2 жыл бұрын
Freaking crazy, this is an extremely good idea 🔥🔥🔥🔥🔥🔥🔥
@StefanNoack2 жыл бұрын
Thanks. I'll be stealing that idea for my forth-inspired system :) This is further awesome, because the compiler could translate let binding into stack->register moves, and perform some primitives directly on the registers.
@ZephyrRz2 жыл бұрын
Absolutely brilliant! I had assumed porth's rot was like dc's R, which pops a number from the top of the stack (n) and rotates the top n elements from the remainder of the stack (when n < 0 it rotates in the opposite direction): 1 2 3 3 R ⇒ 2 3 1 1 2 3 _3 R ⇒ 3 1 2 1 2 3 4 5 4 R ⇒ 1 3 4 5 2 Although this "nrot" type operation would solve some of the issues you were having, your let bindings are much more powerful and result in more readable code. The way the let bindings consume input reminds me of n-ary lambda expressions, and I like how your implementation uses a separate stack instead of allocating local memory, allowing you to use let bindings in inlined procedures and ensure immutability.
@OCPyrit2 жыл бұрын
Beginner: Creating my dream game Expert: Creating my dream engine Legend: Crating my dream programming language
@wChris_2 жыл бұрын
i feel like it would be better to to have the 'ret_stack_rsp' in rbp and then just swap it with rsp (you can use 'xchg rbp, rsp' for that). This also allows you to use indexed addressing with rbp instead of double loading from memory.
@foxoninetails_2 жыл бұрын
Very nice! The next step I'd probably take personally is to remove the older stack operations as intrinsics, and reimplement them as inline procs in the standard library via let. Full backwards compatibility, but fewer core language features to maintain.
@SirFloIII2 жыл бұрын
i thought of that too, but programs not using the std lib would now require it, so its not quite full backwards compatibility.
@kitlith2 жыл бұрын
This idea was brought up at 8:29 , and is apparently blocked on type system features.
@berndeckenfels4 күн бұрын
It would help to also specify such bindings for arguments
@foidii2 жыл бұрын
isnt this that kinda non stack language usage with extra steps?
@yramagicman6752 жыл бұрын
Have you considered short-circuiting your streq procedure a little bit by comparing the sized before entering the loop and returning false immediately if the sizes are not equal?
@MichelHermier2 жыл бұрын
It is quite an interesting feature, basically, it is what regular functions do in C, but it blends inside of the function block. An interesting side effect is that you can push extra data, to bind them as named local variables. Though it may have the *undesirable* effect (if this a real problem) that users might be tempted to always bind proc parameters to names as the first instruction (even if it has its advantages, like conveying meaning to the required input stack layout).
@MichelHermier2 жыл бұрын
Thinking at it again, and after looking on the web, I think you should be able to do FFI using the CDECL call convention using a similar trick...
@wChris_2 жыл бұрын
it would be cool if procs worked the same way as let, so that you have access to the named parameter. Since most of the time you store them away to do some calculation first until you use them.
@danielschmitt57502 жыл бұрын
Let bindings look amazing!
@danielschmitt57502 жыл бұрын
Thank you for introducing me to concatenative programming languages and giving me the confidence that me to can write a compiler for my own language 😅
@hotlinkster1232 жыл бұрын
An alternative to `peek` and `take` would be to have a special word like `stkdup` or `[]` which expands into the elements in the `let` block. If you want to do the functionality of `peek` just begin the block with that word. let a b c in [] // do stuff end also if you want to dup the top n elements it is easy and it simplifies other operations let a1 a2 a3 ... an in [] [] end
@ricardo.mazeto2 жыл бұрын
That's not a good idea. You can implement everything you need to manipulate stacks with only three operations. "nth n", which copies the nth element from the stack to the top, "add-nth x n", which adds x to the nth position on the stack, and "del-nth n", which deletes the nth element on the stack. I use these operations with lists on lisp. That's all you need.
@lolcat69 Жыл бұрын
Porth inspired me to make a simple programming language called Proto, it haves inline assembly, an stack and "ram", stack is usted for functions, like this: entry main proc print { ; "Strings" are used for inline assembly ; Pops from the stack, and saves value onto memory 0 "pop 0" ; Prints number at memory 0 "put 0" } proc main { a = 20 $a ; push the value of A onto the stack #print ; calls print $30 ; also you can push numbers #print }
@lolcat69 Жыл бұрын
It has its own bytecode, that is why the "assembly" looks like that
@angelcaru9 ай бұрын
@@lolcat69 What's the point of inline assembly if the assembly isn't actual assembly?
@monsieuralexandergulbu36782 жыл бұрын
Have you considered something like proc let so we won't wdd let inside of the proc but use names instantly when we entered proc
@chromosundrift2 жыл бұрын
Very cool. What about let (doesn’t pop) and get (does pop them)?
@alurma2 жыл бұрын
Genius!
@hkhademian2 жыл бұрын
a simple way to make str memory immutable is to move them in code segment sometimes I even write them inplace (near usage) and jump over them. I think it's a way to obfuscate code to prevent inverse engineering and ...
@protowalker2 жыл бұрын
0:59 style points
@rogo73302 жыл бұрын
Nice feature to 'let' and its relatives will be: instead of taking all trash that we don't want from stack one by one just put the number of how many positions we want to skip from top of stack / from current position of 'let' / both, but with another word or something. Also instead of 'peek' I think more appropriate word will be 'map' or 'with', but as you wish :)
@NotMarkKnopfler2 жыл бұрын
Turboforth implementation is more powerful. Locals do not have be loaded from the stack. A local can receive the result of a computation that is computed locally within the procedure.
@pabloduran2032 жыл бұрын
What happens if a 64 bit integer is bound in the `let` block. It seems like you always allocate 8 bits in assembly no matter the size of the data you are storing
@computationaltrinitarianism2 жыл бұрын
The let binding looks a bit like compiling cartesian closed categories if you squint.
@AmCanTech2 жыл бұрын
why does the C++ STL use PUSH and POP for QUEUES and why do they let you access the last element?
@norude2 жыл бұрын
if you implement something like set, that will update value of let-ed item, and transform let ... in ... end syntax, so 'end' is always at the end of the current proc, this will become usable language
@frechjo2 жыл бұрын
It's curious I don't see "let" blocks used that much in Factor. Locals are used, but most of the time in a special word definition that binds the arguments (there's something like "proc+let", which binds the names of the arguments for the body of the definition). /bikeshed on I'd keep "let", and use "let*" for bindings that don't get removed from the stack (or try to find some kid of convention in general, for variants that keep more stuff on the stack in general.)
@frechjo2 жыл бұрын
Upon further thought, I think it's because in Factor you can introduce bindings anywhere in the body, with ":> varname". That probably makes the implementation more complex?
@YoghurtBuns2 жыл бұрын
10 print 20 print 30 print
@pabloduran2032 жыл бұрын
how about `with` instead of `peek`
@Dilpikl22 жыл бұрын
What, you didn't want to manually solve the Towers of Hanoi problem every time you write a function?
@tonysofla2 жыл бұрын
Is the stack just software, or is it's a real hardware stack that only has push and pop?, but if you used the stack pointer address as indirect access instead you could make whatever stack operation you want, but make it volatile or turn off IRQ's while manipulated it.
@telnobynoyator_61832 жыл бұрын
This is big
@everything-narrative2 жыл бұрын
you could take inspiration from ruby and make the words be "let?" and "let!" or something similar?
Very cool, and is funny how simple and powerful this feature is. Maybe in the future with take and peek we could have a syntactic sugar to proc, something like this, `proc foo a: int b: int -- int in ... end` translate to `proc foo int int -- int in take a b in ... end end`
@d3vn1co2 жыл бұрын
Very good video
@qwerty123443wifi2 жыл бұрын
Haven't finished the video yet so perhaps this is answered already, but are you going to add variable argument support?
@thecodingfoundation2 жыл бұрын
Are some parts of Porth going to be rewritten with let?
@xeenypl2 жыл бұрын
Actually forth has something similar. For example `: swap { a b } b a ;` and `proc a b -- b a in let a b in b a end end` but in forth there is not scoping also it is not standard. Also i write `proc a b -- b a in` but there is some way to express a polymorphism in porth?
@MCLooyverse2 жыл бұрын
I'm about 5 minutes in, so IDK what your solutions will be, but my first thought is that I'd want some `rot'`, which takes a natural `n` off the stack, and rotates `n` elements, as opposed to 3. So, that would mean that `3 rot'` is exactly the same as `rot`, and `2 rot'` is exactly the same as `swap`, and `1 rot'` and `0 rot'` are identities.
@NotMarkKnopfler2 жыл бұрын
In forth, what you are describing is called ROLL
@lhpl2 жыл бұрын
@@NotMarkKnopfler it would seem that the entire point of this project is to reinvent Forth somehow. Possibly blindfolded and with one hand tied behind the back or something, or just badly in general. It might have been a good idea to look at - and understand - some other stack languages. Besides Forth (which I believe comes in hundreds of various dialects), I can think of two right away: PostScript and POP-11.
@5omebody2 жыл бұрын
@@lhpl or _cough_ actually usable stack languages like factor :p
@lhpl2 жыл бұрын
@@5omebody you don't consider PS usable? ;-)
@5omebody2 жыл бұрын
@@lhpl sure. but is it not a DSL? so for anything outside its narrow scope i'd imagine it wouldn't be very usable
@theairaccumulator71442 жыл бұрын
cursed named variables
@hkhademian2 жыл бұрын
zozin can you check this for streq? while let n1 s1 n2 s2 in n1 1 - s1 1 ptr+ n2 1 - s2 1 ptr+ n1 0 > n2 0 > land if s1 @8 s2 @8 = else false end do end
@barterjke2 жыл бұрын
I really wander why it is so late to appear honestly. I am creating my own language rn and variables is one of the first things i build. i though it was just some weird style of programming and you enjoying writing like this. But yes, variables are much better then bare stack operations in the most cases :)
@marusdod36852 жыл бұрын
any plans to port porth to WebAssembly?
@Mrqwertar2 жыл бұрын
imagine random access stack amirite
@NateROCKS1122 жыл бұрын
I haven't finished the whole video yet, but I think "with" is a better name than "peek." "take" is a good name, I think. Also, in general, I think it'd be nice to have commands that, respectively, rotate N elements and duplicate the Nth element.
@pb-vj1qs2 жыл бұрын
Cool
@MrHminer2 жыл бұрын
let bindings are super cool, the peek bindings though should be called 'label'.
@agreencat34842 жыл бұрын
Your title is misleading. You new operation is really a Random Access Machine operation, like accessing an arbitrary element of an array and thus have nothing to do with Stacks.
@5omebody2 жыл бұрын
not quite, it's syntactic sugar. otherwise you'd consider any kind of stack manipulation as "random access" to since you can access arbitrary elements with those too...
@5omebody2 жыл бұрын
also note that forth also has this in the form of `pick`. but i guess it's fair to say it's definitely not "better stack operations"
@agreencat34842 жыл бұрын
@@5omebody "syntactic sugar" yeah that was the other option. I don't know anything about Forth. But either way, I was right. This is syntactic sugar so this is still not new operations and the title is still clickbait.
@VioletGiraffe2 жыл бұрын
Forth is a terrible programming language, exactly for the reasons you've highlighted. Why does it even exist, other than for the puzzle factor?
@trungthanhbp2 жыл бұрын
i dont like Porth, it look kind of weird
@protowalker2 жыл бұрын
It's weird as hell, but sometimes that's okay! It's more about playing with the paradigm than creating the Next Big Thing. I thought it was super gross at first but after a little while I started to genuinely like a lot of its quirks
@0x1EGEN2 жыл бұрын
It's a stack-based language. Based on a much older language from the 1970's called FORTH. It's actually very intuitive because everything in the language is just either "words" or numbers. And you can use words to create new words, essentially extending the compiler within the language itself. It's very meta but powerful.