After a period of slower progress I got reignited regarding Spry. So far I have written a lot of articles about Spry, and during this time things have evolved and changed.
So I am now trying to write down a summary on where Spry stands today, the changes I would like to make, and what I am doing next.
Let's go through the articles from the beginning, things wrong in article one:
funci
is now calledmethod
if
as been changed to the more Smalltalkishthen:else:
return
is now^
just like in Smalltalk
In article two:
- Context is now called Map. It's the same as a Smalltalk Dictionary.
- Get words use
$
-prefix, not^
(which is return) - The idea with a pluggable parser... I think I will skip that and replace with something else in pure Spry.
- The scoping prefixes
.
and..
have been removed. - I wrote "This means Ni maintains no call stack of its own." - no idea what I meant by that. Spry indeed has a stack of activation records.
In article three:
- There is no
ifelse
, instead we havethen:else:
,else:then:
,else:
,then:
. - The argwords design mistake is still here, but... can be avoided by not using argwords nested, so use
[:x :y ^[x + y]]
instead of[^[:x + :y]]
. So it will probably have to stay. - Single
?
is not used anymore, we can useset?
to check if an unevaluated word is bound, likex set?
- Meaning of scopes are now (but I am planning to cut out
.
and..
):x
- look in locals and then all the way out.@x
- look in closest surrounding Map (self).
- Optional arguments have not been added.
&
has been changed to Smalltalk style,
for concatenation, but leaning towards+
.undef
vsnil
is slightly different:nil
is a value that means "no value".undef
has been removed
?
-marks are used for funcs/methods that return booleans, convention.!
-mark is still unused.self
is as the receiver for methods. It can be anything.context
islocals
, returns the Map of the local scope.activation
returns the current activation, not yet explored much but it's there!
In article four:
- I later opted to call a Dictionary a Map, so it's Map now :)
- The
bindings
word is nowlocals
. - The description of
object
is partly the way it works, yes, it takes a Map as argument and returns an "object". But... this is done using tags that's not described in this article. - Also, the traits idea and thoughts around that is not what has been implemented later. The current Spry instead is exploring if methods can be defined for things with specific tags, and then if those methods can be automatically composed into "polymethods" so that two different modules can define methods with the same name - and they are "merged" into a polymethod that get's bound to that name. When invoked the polymethod should "internally" pick which method to execute.
In article five:
- Yes, renamed to Spry. But... it's sprylang.se, not .org
In article six:
- Yes, base idea of using compressed "Spry code" and store in a fast embedded database still stands! But I now have Rocksdb instead of Sophia, and a pure Nim implementation of Snappy instead of lz4 (it was too hard to get on various platforms)
- Yes, the current modules is implemented as described. Not tested much, but yes. I still think the base ideas stand.
- I did fix so that Foo::bar first finds Foo, and then looks in it. So it works for Maps in general, not just modules. And yes, you can then shadow a module with a global.
- To access "map members" I instead added
@x
syntax. Sinceself
is now bound to the receiver of methods, this resolves members also. One issue though, if you use blocks (and not funcs) then nested blocks in a method sent as parameters to other methods will obviously not resolve to the lexical self, but to the receiving self. Changing the block to a func solves this. - Lossless AST was something I did experiment with, but dropped it. A bit too crazy perhaps.
- So... otherwise it basically sounds like a good plan, but not used much (or implemented much) yet.
In article nine
- This article is mostly "fluff" but there is one important thing I need to improve - "Live within the prototype". In other words, Spry code should be edited, browsed and debugged in Spry tools. I need to try to get that going!
In article ten
- Nothing to note, except that yeah, Nim is fast :)
- Most of this article seems quite correct and according to plan.
And finally, in article twelve
- Most here seems fine too.
The following describes changes I wish to do to the language right now:
- I have added
:=
for reassignment. If no existing binding is found there is an error. - I have removed
undef
. It felt neat but get's confusing. Maps can still hold nil, it's a valid value - if you want to check for a missing binding you will have to use explicit calls to do it instead, just as in Smalltalk. - I have similarly removed
.
and..
scoping words. They can instead be implemented as direct access tolocals
oractivation parent lookup:
etc. - I would like to change concatenation to
+
, even Dart does it these days. It also frees,
for something else, see below. - I will remove pluggable literals and later do something else.