Kevo(ID:1691/kev001)Stack and prototype-based object-oriented languagename for northern Finland natural area (basically Finnish Lapland) A. Taivalsaari Helsinki Finland and U Victoria, June 1992. Prototype-based object-oriented system built around a threaded code interpreter. Semantically resembles Self and Omega. Syntacically resembles Forth. "Experimental prototype-based object-oriented system. Although the Kevo system has been built to experiment with ideas which are somewhat irrelevant from the viewpoint of Forth, the system does bear some resemblance to Forth; in particular, the system executes indirect threaded code, and a great deal of the primitives are similar to those of Forth's." Structures: Related languages
References: Some operations have been marked with an asterisk (*). This indicates that the operation is intended primarily for internal use by the system, and isn't normally supposed to be executed directly by the user. Some operations have been marked with a carat (^). This indicates that the operation is seemingly similar to that in ANSI Forth, but the actual behavior is different. Note that Kevo is a case-sensitive system, and all words must be typed using correct capitalization. In many cases, the same word obeys a different calling convention when written using different key case. For instance, the word 'SEE' takes its parameter from the input stream (e.g., SEE hello), whereas 'see' receives its parameter in the stack (e.g., " hello" see). By convention, a word written in all caps is immediate, i.e., executed at compile time, whereas lower case words are typically intended for runtime execution. For a more detailed description of the primitives, including their stack effects, refer to the source code and the standard image file 'kevo.img'. /* Data loading primitives */ (=sharedVar) (*) load address of a shared variable (=taskVar) (*) load address of a task-specific var (=sharedConst) (*) load shared constant (=taskConst) (*) load task-specific constant (=sharedVector) (*) shared vectored execution (=taskVector) (*) task-specific vectored execution (=context) (*) denotes an object-oriented object (=REF) (*) load a shared to-variable (=VAR) (*) load an object-specific to-variable (lit) (*) load a literal ("lit) (*) load a string literal /* Execution primitives */ noop no operation execute execute an operation exit exit a routine freeExit (*) exit a routine, deallocating memory killExit (*) exit a routine, killing the task debugExit (*) exit a routine in debug mode reboot (*) reboot the system using given operation /* Data stack primitives */ top no operation dup duplicate topmost item in data stack 2dup duplicate two topmost items ?dup duplicate if non-zero drop drop topmost 2drop drop two topmost items swap swap two topmost 2swap swap two cells at a time over copy second topmost to top 2over 'over' two cells at a time rot rotate third topmost onto top -rot rotate topmost to third topmost nip = swap drop ; tuck = swap over ; pick (^) copy n'th item to the top (1 = top) roll (^) rotate stack left or right (+/-n items) depth return current stack depth .s print stack contents sp# return current maximum data stack size resizeDataStack (*) change data stack size resetSp empty data stack /* Return stack primitives */ >r (*) push to return stack r@ (*) copy topmost to data stack r> (*) pop from return stack i innermost loop index j second innermost loop index dup>r (*) = dup >r ; r>drop (*) = r> drop ; rdepth return current return stack depth .rs print return stack contents rp# return current max return stack size resizeReturnStack (*) change return stack size /* Temporary variable primitives (frames) */ temp: (*) access a local variable (runtime) ({) (*) open a local variable frame (runtime) { open a local variable frame (compile) (}) (*) close a local variable frame (runtime) } close a local variable frame (compile) (=template) (*) denote a temporary variable forgetTemp (*) delete a compile-time temp variable forgetTemps (*) delete all temp variables in a frame TEMP define a local to-variable (compile) /* Context stack primitives */ self return receiver of current message & return receiver of previous message >self (*) push to context stack self> (*) pop context stack self>drop (*) = self> drop ; >area (*) return beginning of object's data area area0 (*) return beginning of self's data area area# (*) size of self object's data area >send (*) send a message (internal) >resend (*) resend a message (internal) send (*) send a message to an object resend resend a message ("super") cdepth return current context stack depth .cs print context stack contents cp# return current max context stack size resizeContextStack (*) change context stack size resetCp (*) reset the context stack pointer resetContext (*) reinitialize context stack pointer /* Memory access primitives */ @ fetch from a memory address (32 bit) ! store to a memory address +! increment to a memory address w@ fetch from a memory address (16 bit) w! store to a memory address w+! increment to a memory address b@ fetch from a memory address (8 bit) b! store to a memory address b+! increment to a memory address on store -1 to an address (32 bit) off store zero to an address woff store zero to an address (16 bit) boff store zero to an address (8 bit) ++ increment an address by one cell++ increment an address by four -- decrement an address by one cell-- decrement an address by four toggle set bits in a memory location (32 bit) untoggle unset bits in a memory location btoggle set bits in a memory location (8 bit) buntoggle unset bits in a memory location align align given address to next even cell move (^) move memory (src lenInBytes dest move) fill fill an area of memory with given byte (->) (*) to-variable assignment (internal op) -> to-variable assignment room return amount of free memory lowMem give lowest addressable memory address highMem give highest addressable memory address /* Integer arithmetic primitives */ + add - subtract * multiply / divide mod return modulus /mod return both quotient and remainder u/ unsigned division umod unsigned modulus u/mod unsigned /mod 1+ 1 + ; 2+ 2 + ; cell+ 4 + ; 1- 1 - ; 2- 2 - ; cell- 4 - ; 2* multiply by two 2/ divide by two cell* multiply by four cell/ divide by four abs absolute value negate negate (two's complement) +/- synonym of 'negate' /* Comparison primitives */ 0= test if zero 0<> test if nonzero 0< test if less than zero 0> test if greater than zero = test if equal <> test if not equal < test if less <= test if less or equal > test if greater >= test if greater or equal u< unsigned test if less u> unsigned test if greater min return smaller of two topmost max return larger of two topmost between check if a value is within given range /* Logical primitives */ and logical and or logical or xor logical exclusive or not logical not (one's complement) << left shift >> right shift /* Literal primitives */ zero load zero to stack one load one to stack cell load four to stack false load false (0) true load true (-1) "bs" load ASCII value of backspace "tab" load ASCII value of tab "lf" load ASCII value of linefeed "cr" load ASCII value of carriage return "bl" load ASCII value of space "del" load ASCII value of delete ASCII compile a character literal (ASCII x) /* Control structure primitives */ (branch) (*) unconditional branch (if) (*) branch if zero (do) (*^) begin loop (conditionally) (-do) (*) begin loop (executed at least once) (loop) (*^) end loop (increment by one) (+loop) (*^) end loop (increment by n) (msecsDo) (*) begin loop (execute for n milliseconds) (msecsLoop) (*) end loop (execute for n milliseconds) leave exit loop immediately mark> (*) create a forward reference resolve> (*) resolve a forward reference mark< (*) mark a backward reference resolve< (*) resolve a backward reference ensureStruct (*) ensure validity of control structures "if" (*) literal for syntax checking (IF-THEN) "begin" (*) literal for syntax checking (BEGIN) "while" (*) literal for syntax checking (WHILE) "do" (*) literal for syntax checking (DO-LOOP) "of" (*) literal for syntax checking (CASE) ":" (*) literal for syntax checking (: ;) "{}" (*) literal for syntax checking (frames) /* Internal structure primitives */ checkSystemValidity perform system integrity checks /* Internal structure maneuvering primitives */ name>object (*) go from the name part to the object name'object (*) return the object field of the name name'name (*) return the name field of the name name'flags (*) return the flag field of the name name'prev (*) return the previous name in a link name'succ (*) return the successor name in a link name'context (*) return the context field of the name object>name (*) find a name given an object object>typename (*) find a type name given an object object>store (*) go from the object to its store part object'store (*) return the store field of the object object'size (*) return the size field of the object object>context (*) go from object to its context (if any) context'thread (*) return the n'th thread of the context context'first (*) return the first name in the context context'latest (*) return the latest name in the context context'family (*) return the clone family of the context context'parents (*) return the parents of the context context'children (*) return the children of the context #threads (*) return number of threads in hash table default# (*) default size of objects (in cells) "immediate" (*) return the immediate bit as a literal "hidden" (*) return the hidden bit as a literal "smudge" (*) return the smudge bit as a literal "thisOnly" (*) return "this only" mode as a literal "wholeFamily" (*) return "whole family" mode as a literal "derivatives" (*) return "derivatives" mode as a literal /* Dictionary (context) search primitives */ searchThis (*) search for a name in this context only search search for a name using default path find search for a name (" name" find) FIND search for a name (FIND name) tick search for an object ("name" tick) ' search for an object (' name) immediate? check if a name is marked immediate DEFINED check if a name exists (DEFINED name) respondsTo check if object responds to certain msg /* String manipulation primitives */ /* Note: Kevo uses zero-terminated (ASCIZ) strings */ count (^) count the length of an ASCIZ string match compare two ASCIZ strings scan scan for a character scanWhite scan for a whitespace character skip skip requested characters skipWhite skip all whitespaces enclose extract a word separated by whitespace number convert a string to a number " create a string literal (" string") ." print a string literal (." string") ^ synonym of '"' .^ synonym of '."' /* Multitasker primitives */ up pointer to current task multitasking true if multitasking is on running check if a certain task is running #tasks return the total number of tasks #running return the number of running tasks basePriority base priority of tasks taskingMode multitasking mode (0=preemptive) preemptive set preemptive multitasking mode cooperative set cooperative multitasking mode yield force a task switch <| begin a critical region |> end a critical region (wait) (*) semaphore p operation (internal) WAIT semaphore p operation (REF x WAIT x) (signal) (*) semaphore v operation (internal) SIGNAL semaphore v operation (SIGNAL x) activate activate a certain task suspend suspend a certain task stop stop the current task does set the behavior of a task raisePriority multiply task priority by two lowerPriority divide task priority by two resetPriorities reset priorities of all tasks to basepr >taskData (*) push a value to data stack of a task >taskReturn (*) push a value to return stack of a task >taskContext (*) push a value to context stack of a task /* Decompilation primitives */ isPrintable check if a character is printable dump (^) dump memory in ascii and hex format see decompile a definition (" name" see) SEE decompile a definition (SEE name) mirror decompile all definitions in a context allnames print all names in given context allwords print all names in current context succWords (*) print all successive names words print public names in given context names print public names in current context .threads print each name thread separately /* Debugging and tracing primitives */ trace set trace mode on fullTrace set full trace mode on endTrace disable trace mode debug set a breakpoint unbug remove a breakpoint resume resume execution after breakpoint r synonym for 'resume' /* Input/output primitives */ emit output a single character type (^) output an ASCIZ string ltype output an ASCIZ string left-justified rtype output an ASCIZ string right-justified page blank the screen (form feed) . output a number u. output a number unsigned h. output a number in hexadecimal bell sound the bell cr output a carriage return tab output a tab space output a space spaces output n spaces key? check if any key is pressed key wait for a keypress expect input a string query input a string to text buffer /* File primitives */ pushInfile (*) open a file and push it to infile stack popInfile (*) pop and close the input file resetInfiles (*) reset the input file stack pushOutfile (*) open a file and push it to outfile stak popOutfile (*) pop and close the output file resetOutfiles (*) reset the output file stack resetFiles (*) close all input and output files errorTo redirect output to error device consoleTo redirect output to console device from load a file by redirecting input endFrom end file loading by popping infile to redirect output to a file >>to append output to a file endTo pop output file stack stdInput? (*) is input currently from keyboard? raiseEof (*) force end of file fileShell (*) shell for loading files "write" (*) return file "write" mode as a literal "append" (*) return file "append" mode as a literal /* Block file (virtual memory) primitives */ open-blockfile open a block file (" file" open-bl...) close-blockfile close a block file block load a block into memory update mark the current block to be updated discard discard changes in current block save-buffers save all changed buffers empty-buffers empty and release all buffers flush save and empty all buffers b/buf return buffer size more add a new block to block file capacity return size of block file (in blocks) /* Host system specific primitives */ eventDelay tells how often event loop is called eventSlice tells how much time is given to Mac clock return the value of system clock ticks>msecs convert system clock ticks to millisecs msecs>ticks convert millisecs to system clock ticks msecs pause for n milliseconds system execute host system commands $ execute host system commands ($ cmd) bye exit Kevo and return to host system /* Task-specific variables and constants */ /* Each task has copy of this structure (represented as object) */ nextInRobin (*) next task in the round robin chain nextTask (*) next defined task in the system rpStore (*) temporary return stack pointer storage fp (*) current frame pointer priority task priority returnStack (*) return stack dataStack (*) data stack contextStack (*) context stack trampoline (*) interactive execution area textBuffer (*) text buffer textHead (*) pointer to next character to be read textTail (*) pointer to the end of the text buffer eof (*) end of file flag infiles (*) input file stack outfiles (*) output file stack infile' (*) input file stack pointer outfile' (*) output file stack pointer infile (*) current input file outfile (*) current output file errfile (*) current error file window current window of the task path (*) search path (obsolete) assigning (*) assignment counter error error vector user' (*) number of task-specific variables compilation (*) current definition under compilation target (*) latest compiled definition latest (*) latest defined name frameSize (*) compile-time temporary variable count whoToModify (*) current module operation mode controls (*) number of open control structures warnings are compilation warnings on? tram' (*) ptr to latest compiled thread (exec) comp' (*) ptr to latest compiled thread (comp) text' (*) text buffer pointer input (*) latest encoded name (for error msgs) /* Pseudovariables */ user0 (*) beginning of task data area user# (*) size of task data area text0 (*) beginning of text buffer text# (*) size of text buffer infile0 (*) beginning of input file stack infile# (*) size of input file stack outfile0 (*) beginning of output file stack outfile# (*) size of output file stack tram0 (*) beginning of execution trampoline tram# (*) size of execution trampoline comp0 (*) beginning of current definition comp# (*) size of current definition area here0 (*) either tram0 or comp0 here' (*) either tram' or comp' here# (*) either tram# or comp# here return current memory location /* Execution state manipulation */ >compile (*) set compilation mode >execute (*) set execution mode executing return true if executing compiling return true if compiling mustCompile (*) ensure we are currently compiling mustExecute (*) ensure we are currently executing /* Compilation primitives */ allot (^) allocate space in either tram or comp , (^) compile a cell to either tram or comp compile, compile a call to given routine override, (*) override previous compilation literal, (*) compile a literal "literal, (*) compile a string literal (compile) (*) compile a call to next operation tramAllot (*) allocate space in trampoline tram, (*) compile a cell to trampoline recurse compile a recursive call to itself myself compile a recursive jump to itself COMPILE compile a call (COMPILE xxx) NOW execute right away (NOW xxx) LATER postpone execution (LATER xxx) /* Task data area primitives */ userAllot (*) allocate cells in task data area user, (*) compile a cell into task data area my (*) access this task's data area MY (*) access this task's data area (MY input) his (*) access another task's data area HIS (*) access another task's data area /* Interactive execution primitives */ cycle (*) recycle trampoline memory go (*) execute trampoline code (|) (*) run the compiled command line | treat command line as 2 separate lines (BG|) (*) background execution internal (runBG) (*) background execution internal BG run a command line on background (cmd1 cmd2 ... cmdN BG) /* Command input stream primitives */ textAvailable check if there is text in input buffer eraseText (*) erase text input buffer prepareText (*) prepare input buffer for interpretation (word) (*) parse text delimited by a character WORD parse text delimited by a character (parse) (*) parse text delimited by whitespace PARSE (^) parse text delimited by whitespace ( begin comment ( this is a comment) \ treat rest of the line as comment /* Message expression parser */ noDotsAtAll (*) ensure a string does not contain dots dotInBeginning (*) ensure a string does not begin with '.' dotInEnd (*) ensure a string does not end with '.' dotExpression (*) check if a string is a dot expression message, (*) compile a message send skipDot (*) skip a dot in a string innerMessages (*) process inner messages in a dot expr lastMessage (*) process last message in a dot expr encodeMessages (*) encode and compile a dot expression assignment? (*) compile assignment if needed ooEncode (*) encode and compile a dot expression encode (*) vectored encoding (encode) (*) process a word in command line /* Command shell */ interpret (*) interpret a line in the text buffer "interpret interpret the given string checkStacks check the validity of all stacks .ok (*) print prompt string prompt (*) prompt if necessary shell the command shell /* Error handling */ abort abort execution and return to shell (error) (*) low-level error handler oopError (*) higher-level error handler brError (*) internal error handler for browsers /* High-level structure definition */ warn (*) warn about overridden definitions rewarn (*) warn about redefined definitions (create) (*) low-level object creation create (^) create a definition (" xxx" create) CREATE (^) create a definition (CREATE xxx) does, (*) store to execution field with, (*) store to parameter field (replace) (*) low-level general redefinition replace (*) redefine the behavior of definition (recreate) (*) low-level redefinition for clone fams recreate (*) redefine definition in a clone family (:) (*) low-level colon definition bredef (*) internal op needed by the browser (REF) (*) define a shared variable REF define a shared variable (VAR) (*) define a local variable VAR define a local variable CONST define a constant SHAREDVAR synonym of 'REF' METHOD synonym of ':' : begin a colon definition (method) ; end a colon definition immediate make the latest definition immediate hidden make the latest definition hidden smudge (*) make the latest definition invisible unsmudge (*) make the latest definition visible (ADDS) (*) start adding properties to an object ADDS start adding properties to an object (ADDS*) (*) start adding ... to all in clone family ADDS* start adding ... to all in clone family ADDS** start adding ... to a larger group (ENDADDS) (*) end property addition ENDADDS; end property addition REDEFINE redefine a method in an object REDEFINE* redefine a method in a clone family REDEFINE** redefine a method in a larger group rename rename a property in single object RENAME rename a property in single object rename* rename a property in clone family RENAME* rename a property in clone family RENAME** rename in a larger group remove remove a property from single object REMOVE remove a property from single object remove* remove from all in a clone family REMOVE* remove from all in a clone family REMOVE** remove from a larger group hide make a property hidden (i.e., private) HIDE make a property hidden (i.e., private) hide* make hidden in a clone family HIDE* make hidden in a clone family HIDE** make hidden in a larger group show make a property visible (i.e., public) SHOW make a property visible (i.e., public) show* make visible in a clone family SHOW* make visible in a clone family SHOW** make visible in a larger group /* Context management */ SystemRoot return address of system root context Root return address of user root context MKDIR build an empty object (MKDIR Test) hasContext check if the given object has a context mustBeObject ensure that given value is an object cd set the "current working directory" CD set the "current working directory" pwd display the "current working directory" home go back to 'Root' context /* Control structures */ /* Unlike other primitives, these are described with examples */ IF ELSE THEN BEGIN BEGIN xxx AGAIN AGAIN UNTIL BEGIN xxx WHILE REPEAT BEGIN xxx DO (^) 10 1 DO i . LOOP (goes from 1 to 10) TIMES 1000 TIMES LOOP (TIMES = 1 DO) MSECS 200 MSECS LOOP (loop for 2 seconds) LOOP +LOOP (^) 100 1 DO i . 10 +LOOP (increment by 10) CASE (^) n CASE OF (^) 10 < OF ." Less than 10" ENDOF ENDOF (^) 20 > OF ." More than 20" ENDOF ELSEOF (^) ELSEOF ." Something else" ENDOF ENDCASE (^) ENDCASE /* Random number generator */ seed (*) random number seed randomize randomize the random number seed random return a random integer rnd return a random number in certain range /* GUI window primitives */ showWindow display a window hideWindow hide a window selectWindow select a window (make it topmost) frontWindow return the frontmost window nextWindow return next topmost window getWindowTitle get window title setWindowTitle set window title getWindowSize get window size setWindowSize set window size getWindowLoc get window location setWindowLoc set window location getWindowKind get window kind TEDeactivate deactivate a Mac TextEdit TEActivate activate a Mac TextEdit /* GUI mouse & graphics primitives */ getMouse get current mouse coordinates button true if mouse button pressed setPort set graphics port getPort get graphics port hidePen hide pen showPen show pen getPen get pen location setPenSize set pen size setPenMode set pen mode penNormalize reinitialize pen moveTo move graphics cursor to (x,y) moveDelta increment graphics cursor with (dx, dy) lineTo draw a line to (x,y) lineDelta draw a line to (dx, dy) setTextFont set text font setTextFace set text face setTextMode set text mode setTextSize set text size drawChar draw a character drawString draw a text string wipeScreen wipe the graphics off the screen browse open a browser for an object unbrowse close a browser for an object (if any) cfBrowse (*) open a browser for a clone family /* System startup */ hello greet the user demo load the default demo programs demoInfo display info about loading demos SystemInit initialize the system boot reinitialize the system /* Error messages */ msg$dEmpty (*) data stack empty msg$dFull (*) data stack full msg$rEmpty (*) return stack empty msg$rFull (*) return stack full msg$cEmpty (*) context stack empty msg$cFull (*) context stack full msg$control (*) illegal control structure msg$what (*) name not found msg$"what (*) name 'x' not found msg$execOnly (*) for execution only msg$compOnly (*) for compilation only msg$notCtxt (*) not a context object msg$noDot (*) message syntax error msg$notImpl (*) not implemented msg$notAvail (*) not available notImplemented raise 'msg$notImpl' notAvailable raise 'msg$notAvail' inRange ensure that a number is in range /* The following operations are redundant and will */ /* probably be removed from later versions of Kevo */ (=>) (*) alternative to-var assignment (unused) => alternative to-var assignment (unused) (tick&) (*) access the parameter field (obsolete) '& access the parameter field (obsolete) forget forget a certain name (" name" forget) FORGET forget a certain name (FORGET name) forgetRest forget rest of the names empty forget all after 'boot' (obsolete) context define a context object CONTEXT define a context object bgtask build a background task (" xxx" bgtask) BGTASK build a background task (BGTASK xxx) grtask build a graphics task (" xxx" grtask) GRTASK build a graphics task (GRTASK xxx) task build a full task (" xxx" task) TASK build a full task (TASK xxx) sharedVar build a shared variable taskVar build a task-specific variable sharedConst build a shared constant taskConst build a task-specific constant sharedVector build a shared execution vector taskVector build a task-specific exec vector VARIABLE define a Forth-style variable CONSTANT define a Forth-style constant DEFER define a Forth-style exec vector About Kevo Kevo is a prototype-based object-oriented system build around a very simple object model. Unlike most object-oriented systems, Kevo does not have classes. And unlike the few other prototype-based object-oriented systems (such as Self), Kevo does not feature delegation. Instead of classes and delegation, Kevo is based on concatenation: unrestricted composition of object interfaces. In concatenation, objects are derived from each other simply by cloning (copying) and subsequently modifying them so as to differentiate them from each other. The Kevo system automatically maintains information about clone families (groups of similar objects) and their derivation relationships. The overall organization of the Kevo system differs considerably from most other object-oriented systems. Instead of building the system around inheritance hierarchies, in Kevo the basic skeleton for the system is the part-whole hierarchy. This hierarchy organizes the system into an intuitive Unix-like hierarchical structure in which the individual "directories" are objects rather than files. The user can freely move about in this hierarchy, and change the "current working directory" in a Unix-like manner. The commands given from the command shell will be implicitly interpreted in the "current working directory" so that the user can manipulate objects easily without having to use long message paths to reach a certain object. In Kevo, there are several basic ways to create new kinds of objects. Besides that it is possible to define objects using text files (see the demo programs and the papers to get the idea), all the object creation facilities have been integrated into Kevo's user interface. In fact, some of the most interesting functions (such as cut-copy-paste editing of objects) of the Kevo system necessitate the presence of the user interface and cannot necessarily be done textually. Even in the user interface, there are two basic ways to "inherit" existing objects: Either you can copy an existing object using the Tools menu, and subsequently make changes to the copy using the Edit facilities (traditional concatenation). Alternatively, you can start with an empty object using MKDIR in Edit menu, use copy and paste to "inherit" possibly several existing objects (or just parts of them), and subsequently make changes to the new object (cut-copy-paste concatenation). Kevo system also features explicitly selectable early or late binding, regardless of whether the properties to be bound are variables or operations. When using the cut-copy-paste features, Kevo will automatically recompile all the needed properties if they contain early-bound references. For instance, when the user removes a property from an object, the system will recompile all the properties which refer to the removed property (using the name of the removed property), and report all the inconsistencies to the console window. Similarly, when pasting properties in the middle of an object, all the early-bound references will be checked, causing some methods to be possibly recompiled. If only late binding is used, then no recompilations will be made. One curious feature of Kevo is propagation. All the basic object editing functions, such as the addition, removal, renaming, method redefinition, and cut-copy-paste features can be targeted to individual objects or to whole clone families, depending on the propagation settings in the Edit menu. When modifying individual objects, the system will automatically start a new clone family around the modified object. After the modifications have been completed, the system will automatically compare the modified object to other related objects, and possibly move the object upwards or downwards in the clone family hierarchy to some other clone family with matching properties. In other words, Kevo allows objects to automatically migrate in the inheritance hierarchy. In the current version of Kevo, the implementation of propagation is still somewhat limited. The idea is to allow the user to easily modify very large groups of objects with only a minimum effort. At the present time the use of the derivatives mode in the Edit menu is however limited to the redefinition of methods only. Note that the effect of large-scale propagation can however be achieved manually quite simply by following the clone family relationships and using cut or paste to do the same modification to each clone family. In general, Kevo is an experimental combination of several previously little investigated ideas. All these ideas still offer many interesting lines of research to pursue: ? self-sufficient objects, ? use of part-whole hierarchy as the basis for system organization, ? automatic management of inheritance hierarchies, ? inheritance by copying and subsequent modification (concatenation), ? cut-copy-paste editing of objects, ? flexible early and late binding, and ? runtime modification of the system by change propagation. Introduction to Kevo Kevo is a prototype-based language designed around self-sufficient and concrete objects, By self-sufficient, it is meant that each Kevo object contains all the properties needed for implementing a certain abstraction, and that these properties are logically independent of the other objects? properties. This is different from Self which relies heavily on sharing, and requires the programmer to divide objects into separate traits and prototype structures. By concrete, it is meant that Kevo allows the programmer to manipulate each object directly, either on a per-object or per-group basis. Kevo does not support inheritance in the traditional sense. And unlike many prototype-based object-oriented systems, Kevo does not support delegation. Instead of inheritance and delegation, the essence of inheritance - incremental modification - is captured using concatenation, i.e., by duplicating existing objects and by allowing flexible editing and combination of objects. In practice, concatenation is supported by providing two user-redefinable copying operations, new and clone, and a set of module operations that allow different kinds of modifications to be performed on objects. For instance, to create a ColoredPoint object, one would simply copy an existing Point object, and then add the desired new properties to the copy using the module operation ADDS. Late binding of methods and variables ensures that earlier defined (?inherited?) properties can adapt to later modifications in an incremental fashion. As a result of the above mentioned arrangements, Kevo objects look quite different from Self objects. Extract: Benefits/Issues of Prototypes vs. Classes Benefits/Issues of Prototypes vs. Classes Prototypes have many benefits especially when exploratory programming is concerned. They are cognitively more lightweight than classes, support direct manipulation more naturally, avoid many modularity problems of class-based systems, and result in simpler and conceptually more elegant language implementations. Considering these benefits, it is appropriate to ask why haven't prototype-based systems received more widespread acceptance thus far. Besides the easy explanation - lack of maturity - the best answer to this question seems to be that there has been an over-emphasis on technical issues. The advocates of prototype-based systems have failed to advertise the conceptual benefits of prototypes, and emphasized technical curiosities instead. While features such as unanticipated sharing of data slots, dynamic inheritance, and prioritized parents are often useful, they are questionable and even dangerous in serious, large-scale software development. Compared to other issues, these features have received considerable attention in the literature, diverting the focus away from the real benefits of prototypes, and may have increased resistance against adopting prototype- based techniques more widely. In summary, prototypes are beneficial, but a more concept-oriented view of prototypes is still lacking, and this is exactly what we should be aiming at in the future. Delegation-free languages serve as a promising alternative in this respect. in Smith, Randall B (moderator) "Prototype-based languages (panel): object lessons from class-free programming" OOPSLA 94 pp102-112 view details in Smith, Randall B (moderator) "Prototype-based languages (panel): object lessons from class-free programming" OOPSLA 94 pp102-112 view details in SIGPLAN Notices 31(04) April 1996 view details Antero then presented several consequences of this philosophical background. Because classifications cannot be determined in advance, there can be no optimum class hierarchies, and class library designs need to evolve over time. Class hierarchies evolve from the ``middle out'', in particular, classes high in the hierarchy will be very general and discovered after the more basic classes. Unfortunately, class based languages require that class hierarchies are defined top down, with the most abstract classes being written first. Prototype based languages which use family resemblances rather than class hierarchies (such as Kevo) can avoid these problems. in Cointe, P. editor, Proceedings of the Ninth European Conference on Object-Oriented Programming (ECOOP), July 1996. LNCS 1098, Springer-Verlag view details Introduction "Objects in the real world have only one thing in common -- they are all different." In the recent years an alternative to the traditional class-based object-orientedlanguage model has emerged. In this prototype-based paradigm [Bor86, Lie86, LTP86, Ste87, UnS87, SLU88, DMC92, Bla94] there are no classes. Rather, newkinds of objects are formed more directly by composing concrete, full-fledged objects, which are often referred to as prototypes. When compared to class-basedlanguages, prototype-based languages are conceptually simpler, and have many other characteristics that make them suitable especially to the development of evolving,exploratory and distributed software systems. The distinction between class-based and prototype-based systems reflects a long-lasting philosophical dispute concerning the representation of abstractions. Plato viewed forms -- stable, abstract, "ideal" descriptions of things -- as having anexistence more real than instances of those things in the real world. Class-based languages such as Smalltalk, C++ or Simula are Platonic in their explicit use ofclasses to represent similarity among collections of objects. Prototype-based systems such as Self [UnS87], Omega [Bla91, Bla94], Kevo [Tai92, Tai93], GlyphicScript[Gly94] and NewtonScript [SLS94] represent another view of the world, in which one does not rely so much on advance categorization and classification, but rather tries tomake the concepts in the problem domain as tangible and intuitive as possible. A typical argument in favor of prototypes is that people seem to be a lot better at dealingwith specific examples first, then generalizing from them, than they are at absorbing general abstract principles first and later applying them in particular cases. Prototypes give rise to a broad spectrum of interesting technical, conceptual andphilosophical issues. In this paper we take a rather unusual, non-technical approach and investigate object-oriented programming and the prototype-based programmingfield from a purely philosophical viewpoint. Some historical facts and observations pertaining to objects and prototypes are presented, and conclusions based on thoseobservations are derived. in Cointe, P. editor, Proceedings of the Ninth European Conference on Object-Oriented Programming (ECOOP), July 1996. LNCS 1098, Springer-Verlag view details in Cointe, P. editor, Proceedings of the Ninth European Conference on Object-Oriented Programming (ECOOP), July 1996. LNCS 1098, Springer-Verlag view details in Cointe, P. editor, Proceedings of the Ninth European Conference on Object-Oriented Programming (ECOOP), July 1996. LNCS 1098, Springer-Verlag view details Resources
|