Tuesday, May 27, 2014

Live objects vs. static types for code completion in Objective-Smalltalk

Objective-Smalltalk is now getting into a very nice virtuous cycle of being more useful, therefore being used more and therefore motivating changes to make it even more useful. One of the recent additions was autocomplete, for both the tty-based and the GUI based REPLs.

I modeled the autocomplete after the one in bash and other Unix shells: it will insert partial completions without asking up the point that they become ambiguous. If there is no unambiguous partial completion, it displays the alternatives. So a usual sequence is <TAB> -> something is inserted <TAB> again -> list is displayed, type one character to disambiguate, <TAB> again and so on. I find that I get to my desired result much quicker and with fewer backtracks than with the mechanism Xcode uses.

Fortunately, I was able to wrestle NSTextView's completion mechanism (in ShellView borrowed from the excellent FSCript) to provide these semantics rather than the built in ones.

Another cool thing about the autocomplete is that it is very precise, unlike for example FScript which as far as I can tell just offers all possible symbols. How can this be, when Objective-Smalltalk is (currently) dynamically typed and we all know that good autocomplete requires static types? The reason is simply that there is one thing that's even better than having the static types available: having the actual objects themselves available!

The two REPLs aren't just syntax-aware, they also evaluate the expression as much as needed and possible to figure out what a good completion might be. So instead of having to figure out the type of the object, we can just ask the object what messages it understands. This was very easy to implement, almost comically trivial compared to a full blown static type-system.

So while static types are good for this purpose, live objects are even better! The Self team made a similar discovery when they were working on their optimizing compiler, trying both static type inference and dynamic type feedback. Type feedback was both simpler and performed vastly better and is currently used even for optimizing statically typed languages such as Java.

Finally, autocomplete also works with Polymorphic Identifiers, for example file:./a<TAB> will autocomplete files in the current directory starting with the letter 'a' (and just fi<TAB> will autocomplete to the file: scheme). Completion is scheme-specific, so any schemes you add can provide their own completion logic.

Like all of Objective-Smalltalk, this is still a work in progress: not all syntactic constructs support completions, for example Polymorphic Identifiers don't support complex paths and there is no bracket matching. However, just like Objective-Smalltalk, what is there is quite useful and often already better what else is out there in small areas.


No comments: