Newton Script(ID:1278/new008)Prototyped scripting language for the Apple NewtonWalter Smith, Newton development group, Apple Computers Related languages
References: Don't forget everything you know about class-based programming, though. It is possible, and even desirable, to simulate classes in NewtonScript. Even though the language contains no explicit features to support classes, you can use a simple set of stylistic conventions to gain the familiar advantages of classes when you need them, without losing the flexibility of prototypes. External link: Online copy at Walter Smith's site in PIE Developers magazine, January 1994 view details This is an introduction to the paper "Self: the power of simplicity", by Ungar and Smith. When I joined the Newton group--then called the Special Projects Group--in 1988, it was still a research organization. The product, whatever it might be, was a long-term goal, and we had the now-incredible luxury of thinking about abstract problems and filling our file cabinets with papers ordered from the Apple Library document service. One of the problems that interested us in those days was choosing a language for Newton. We knew it would be a big influence on the feel of the system, and it would have to be powerful and productive if we were going to do all the things we wanted. Object-oriented languages were just starting to enter the mainstream (even C++ was not yet the industry darling it is today), and there were a lot of interesting new languages to learn about and evaluate. In hindsight, actually, we became a little too distracted by choosing a language; this period of Newton history is not-so-fondly remembered as the "language thrash". SELF stood out among the languages we saw during that period. Although it was clearly impractical as a system language (it took several years for the SELF compiler to reach its present impressive state), its audacious simplicity made an impression that the more "serious" languages did not. During the language thrash, as we conducted a series of objective evaluations that showed we should really be using Smalltalk, or Eiffel, or Trellis-Owl, or even C++, the conversation would often wishfully turn to SELF. I had no idea I would end up designing a language for Newton. In fact, at that time we consciously avoided the temptation to design a Newton-specific language. Leave language design to the experts, we thought, and we'll just choose one. To make a very long story short, it didn't happen that way. Reality set in, and during the development effort that brought you the MessagePad, a new language--now called NewtonScript--evolved in parallel with the view system and object store. The language thrash made it possible: all those languages we looked at provided a wealth of ideas that found their way into NewtonScript. SELF was one of the primary influences. Extract: SELF and NewtonScript SELF and NewtonScript As a NewtonScript user (which I assume you are or will be shortly), you may not immediately recognize SELF. NewtonScript is not a direct derivative. However, SELF inspired some of the most important aspects of NewtonScript. The prototype-based inheritance system of NewtonScript is adapted from SELF's "parent slots"; it's more complex than the version of SELF described here, but simpler than some later versions. Newton's view system evolved in parallel with NewtonScript, and the idea of combining container inheritance defined by the view hierarchy with refinement in the form of view templates was naturally reflected in the language as "double inheritance". Later versions of SELF allowed any number of prioritized parent slots, but NewtonScript fixed the number and priority in the form of _parent and _proto slots. The advantages of prototype-based inheritance are described somewhat abstractly in this paper. As a user of Newton Toolkit, you experience them frequently. When you draw a view in NTK and attach slots to it, you're not specifying parameters that will be read out of a resource file at runtime to generate an instance of a class that you specified somewhere else; you're constructing an actual object that will be embedded in your application and used directly at runtime. Eliminating that layer of abstraction gives Newton programming an unusually direct feel. "One-of-a-kind" objects are painful to create in a class-based system, as Ungar and Smith point out, and graphical user interfaces are full of them. SELF combines variables, slots, and messages into one mechanism, but NewtonScript doesn't go quite so far. In SELF, you can't tell if referencing a variable will execute a method or just get a value from a slot. In NewtonScript, variable accesses are always simple slot accesses. If you want to execute a method, you have to send a message. There's no fancy theoretical explanation for this decision; I was just being conservative with space, time, and implementation complexity. The feature is sufficiently useful that it found its way into the system anyway, in the form of the SetValue function. SELF's use of regular objects as activation records is a powerful idea. The NewtonScript documentation avoids such a direct description of the calling mechanism because we find very few people are interested in such details, and in fact the demands of speed draw the implementation away from such a direct approach, but here you can see the elegance of the original concept. Its original implementation in the NewtonScript interpreter may well have been smaller than its explanation. It will be obvious that none of SELF's syntax was used in NewtonScript. Smalltalk syntax is elegant, but unfamiliar to most programmers. NewtonScript's Pascal-like (or, to give credit where due, Algol-like) syntax is easier to learn for many, with little loss of expressiveness and power. External link: Online copy at Walter Smith's site in PIE Developers magazine, July 1994 view details Goals and audience NewtonScript was created specifically for developing applications for the Newton platform. It is a general-purpose language (in fact, Newton- Script compilers have been written in NewtonScript), but particularly well suited to Newton programming. Newton's language, view system, and persistent object store were designed in parallel to work well together. The language and its development environment, the Newton Toolkit, are being used by several thousand Newton developers. Many of them have no previous experience with dynamic object-oriented languages. Newton Toolkit has generated surprisingly positive feedback; the adjustment to prototype-based programming appears to be relatively easy and pleasant for most of our developers. (Of course, this group is self-selected by the decision to adopt a brand-new platform in the first place!) Thus, NewtonScript's most important contribution to the field may simply be a demonstration that a prototype- based language can be practical-currently, it is the only language publicly available for Newton and that it can be acceptable to "real" programmers. in Smith, Randall B (moderator) "Prototype-based languages (panel): object lessons from class-free programming" OOPSLA 94 pp102-112 view details NewtonScript All Newton applications are written in a dynamic object-oriented language called NewtonScript. The syntax of NewtonScript is similar to Pascal. It uses infix notation for built-in math and comparison operators, begin and end for compound statements, and has the standard Pascal control structures (such as if/then, while, repeat, and for). (See Fig. 2.) However, it is a dynamic language whose semantics are similar to Scheme [7]: functions are first-class objects, all statements have a return value, variables are untyped, and it has upward closures (but not continuations). In addition, it has features for object-oriented programming. --------------------- Figure 2. A tiny NewtonScript example. This function finds the highest value from the price slots of all the entries in the given soup. Func (soup) begin local max := nil; local cursor := Query(soup, '{type: index}); while cursor:Entry() do begin local e := cursor:Entry(); if not max or e.price > max then max := e.price; cursor:Next() end; max end --------------------- The language is strongly tied to the Newton object system. It includes operators and syntax features that make it easy to create and manipulate Newton objects. More significantly, frames are the basis for inheritance and message passing. NewtonScript's object-oriented features are in some ways a simplified version of Self [2], with frames taking the role of Self objects. A frame is the only kind of object that can respond to messages and serve as the context of a method execution. Like Self, inheritance is prototype-based: there are no classes, and objects inherit directly from other objects. However, variable references are distinct from message sends, and inheritance is limited to two paths with fixed priority. The inheritance system looks for two slot tags, _proto and _parent, which define the inheritance relationship between frames. The names are chosen to reflect the convention that _parent frames are containers, frames holding shared data, while _proto frames are prototypes, frames to be refined by other frames. When a message is sent to a frame, or a variable reference is resolved, the interpreter looks for a matching tag in the receiver frame. If it is not found, the lookup tries the frames in the receiver's _proto chain, then goes up to the _parent frame and tries its _proto chain, and so on. A slightly different rule applies to variable assignment. The same lookup occurs to locate the frame containing the variable, but the assignment always occurs in the _parent chain, not in a _proto chain, creating a new slot if necessary. This assignment rule makes it difficult to accidentally modify a prototype frame, which might be shared by many frames. More importantly, it provides a form of "copy-on-write": the prototypes may provide an initial value for a slot, which is overridden in a particular frame by the first assignment. This delays the allocation of the slot as long as possible, saving space. (See Fig. 3.) NewtonScript is compiled into bytecodes, which are interpreted at runtime. This has two advantages: the byte-codes are significantly smaller than native code, and they make Newton applications inherently portable to any processor. Because the Newton technology is widely licensed, and expected to migrate to a variety of devices, these are important properties. However, some applications cannot tolerate the speed penalty of bytecode interpretation. We are working on a native-code compiler for NewtonScript that will allow the programmer to selectively pay the space penalty for the parts of an application for which speed is critical. Bytecodes will still be generated, so the code will retain portability. External link: Online copy at Walter Smith's site in Proceedings of the 39th IEEE Computer Society International Conference, San Francisco, 1994 view details in Proceedings of the 39th IEEE Computer Society International Conference, San Francisco, 1994 view details in ACM SIGCHI Bulletin 27(3) (July 1995) view details in SIGPLAN Notices 30(10) ACM Press, October 1995 (Proceedings of the 10th Annual Conference on Object-Oriented Programming: Systems, Languages and Applications (OOPSLA'95)) view details |