- creating an array w/ create-array is possible, however I could not find how to take its address and pass it around
- one cannot get the address of an invalid position of the array, so one cannot construct bounded ranges (STL style) using a begin/end pair of addresses
- the interpreter strongly suggests to use refcounted pointers (address:shared) instead of addresses even when one does not borrow the memory
- could not figure out how to write a test scenario that uses checks named memory addresses rather than ordinal memory addresses (memory-should-contain instruction)
That's great!! Yes, create-array was just a version I created so I could teach arrays separate from new and addresses. But it creates an array on the 'stack' (default space) so there's no way to take an address of it. I quickly take my students past it to new.
memory-should-contain doesn't currently support named locations, sorry. Part of the problem is that with spaces a name can have many different addresses in different functions. So my tests write stuff I want to check in raw numbered locations, and the first 1000 addresses are reserved for tests so that names can never be clobbered.
I looked at Rust's borrow checker for a bit but wasn't smart enough to understand how it works or transplant it easily. I also noticed that it wasn't smart enough to deal with things like doubly-linked lists without reaching for ref-counting. So I figured I'd keep things simple and just use ref-counting for everything. That way I punt on all the complicated static checks in favor of a simple runtime one.
The rule is: new returns shared:address, and get-address and index-address (and maybe-convert) return address. Use shared:address to pass things around between functions, and reserve non-shared addresses only for short-term operations, usually mutations. Since non-shared addresses are not dynamically allocated, there's no possibility of use-after-free so they don't need to be refcounted, and you can copy them around as much as you like.
Use-after-free and related memory corruption is really the only thing I'm concerned about protecting my users from. Memory leaks I plan to have tools for, so that programmers can identify and break them down when memory becomes a concern, but not worry about until then. I call this "zero-developer-cost abstractions" :) It feels less restrictive and more dynamic than Rust.
Edit: I just took a look at your code, and it feels perfectly idiomatic. Nice job. Only issue I found was that you forgot to specify the outputs of find in its header. So its calls end up doing some runtime type-checking. I should probably raise a warning in this situation. Thanks again.
Indeed, I missed the output for find! A warning would definitely be helpful.
I like that you have users and thus will be able to test things out and get some genuine feedback.
This might however introduce a bias guiding your language and standard library in a certain direction (I think it's inevitable and what's happening in all languages anyway) .. Therefore I would add some of your peers into the mix.
Otherwise I really like the directions you are exploring, as I've come to very similar conclusions at this point in my career:
- being able to modify a system through safe additions
- not focusing too much on local details of a system
Yeah, the reactions here have been invaluable. It's interesting: I actually got into teaching because I had trouble getting programmers to try Mu out. Most people tend to unconsciously filter out what seems gratuitously new and different. But I'll keep trying.
https://gist.github.com/uucidl/df81b6ab0fe65713f5ba
My notes:
- creating an array w/ create-array is possible, however I could not find how to take its address and pass it around
- one cannot get the address of an invalid position of the array, so one cannot construct bounded ranges (STL style) using a begin/end pair of addresses
- the interpreter strongly suggests to use refcounted pointers (address:shared) instead of addresses even when one does not borrow the memory
- could not figure out how to write a test scenario that uses checks named memory addresses rather than ordinal memory addresses (memory-should-contain instruction)