I have been writing a tutorial on how to implement structures in poslin.
I am now at the point where structures and their types are almost completely done. Next up are mutable slots for structs (currently any setting operation called on a struct creates a new one).
A little thing about organization.
I plan to have poslin coming in different versions.
The first only contains primary operations, or rather the operations defined in this document:
https://bitbucket.org/thomas_bartscher/poslin-specification/src/0f7c09ad5da7a9044cf9df51735049ad92ba9451/spec/prims.txt?at=defaultWell, a few operations are missing from this (for example one that returns the length of an array). The basic idea is that this version doesn't load anything externally but is completely bare bones.
That version I call "poslin0". Yeah, it's not very creative.
The second version comes with the standard library, which contains the basic necessities for comfortable working with stacks, defining operations, working with variables, loops…
What it doesn't contain is stuff like packages, a way to define your own data types, modules, type checking, poslin level optimization or anything like that.
It implements the operations in this document:
https://bitbucket.org/thomas_bartscher/poslin-specification/src/0f7c09ad5da7a9044cf9df51735049ad92ba9451/spec/base.txt?at=default and would be called "poslin1".
(I think I should get rid of the `fibonacci` and `factorial` operations here.)
If you download the binary distribution, you'll find that it contains a binary file "poslin-dyn" and two scripts, "poslin0" and "poslin1". These two scripts are for starting up the previously described versions.
The third version should contain all the stuff which helps organizing code: Packages, modules and the ability to define your own data types.
Also of interest would be static type checking (if I can come up with something), generic operations and stuff like that.
This would be "poslin2", as you can probably imagine. As the extent of this version isn't quite clear to me there also is no corresponding document right now.
You might wonder why the last two versions are distinct. Well, "poslin1" is relatively small and, more importantly, it is easy to come up with how to do stuff. The stuff in "poslin1" should be uncontroversial. There's no big discussion about how operations should be defined (or at least I am not aware of anything like that) and the same goes for variables, mathematical functions or loops.
The stuff in "poslin2" is not so clear cut. My ideas on how to do object orientation and packages are heavily inspired by Common Lisp which does those things very differently from, say, C++, Java or Haskell for example.
So, everyone who isn't fine with my choice on how to do these things should be encouraged to use poslin1 and implement his own ideas instead of using my implementation of my ideas.
A better idea might be to move all those systems into their own libraries… Hrm…
Poslin0 is distinct from poslin1 for the people who really want to experiment. I don't really know what kind of language you could come up with based on poslin0.
Also poslin0 is kind of a necessity if I ever make that tutorial on how to implement the standard library.
A short while ago I was able to do a slight optimization in the standard library. The optimized operation is `~:`, which duplicates the element on top of the current stack, like this:
[ 1 ]
> ~: !
[ 1 1 ]
>
This operation is essential and often used, as it is necessary to duplicate a binding when I want to set its value first and then save the binding in an environment.
Previously it was implemented like this (without the comments and also not with `[` and `]o`, as neither comments nor these operations are available at that moment):
~:
[ e~ & STACK e-> & ;[ … x b<> ];
e~ & STACK e-> & b-> & _ & ;[ … x b<> [ … x ] ];
e~ & STACK e-> & b-> & _ & _ & ;[ … x b<> [ … x ] [ … x ] ];
: &
<- & b<- &
]o
It works like this: It puts the binding of the current stack onto the current stack, then gets the binding again and extracts it's value, which is a stack. This stack is equivalent to the stack we had after we popped off that last binding and before we put back that new value again, so it contains the binding of the current stack on top, which we don't want to have there after duplication, so we drop it from there.
Now we get the value of the current stack again, only that now it contains the binding of the current stack and the stack we made previously, which both need to be dropped so we can take the value we actually want to duplicate from the top of that stack, put it onto the stack before it and finally set the binding of the current stack to the newly constructed stack.
That's a lot of work for just duplicating one value. It's also a lot of unnecessary work.
Take a look at this new version:
~:
[ e~ & STACK e-> & b-> & ;[ … x [ … x ] ];
: & ;[ … x x ];
]o
I don't think this requires much explanation.
Everything runs quite a bit faster now.
Unfortunately swapping the top two elements on the current stack still requires the long route.