home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 116.lha / SmallTalk / Manual / TOP.MS < prev    next >
Text File  |  1986-11-20  |  6KB  |  145 lines

  1. .SH
  2. Who's On Top?
  3. .PP
  4. One of the most important decisions to be made in designing a new user
  5. interface (or front end) for the Little Smalltalk system is whether the user
  6. interface management code should sit on top of the Smalltalk bytecode 
  7. interpreter, setting up commands and invoking the interpreter to execute them,
  8. or underneith the bytecode interpreter, being invoked by Smalltalk, via the
  9. mechanism of primitive methods.  Both schemes have advantages and disadvantages
  10. which we will discuss in this essay.
  11. .PP
  12. In a simple interface, placing Smalltalk on top is often easier.  The main
  13. driver need only set up one initial call to the Smalltalk bytecode interpreter,
  14. and thereafter everything is done in Smalltalk.  For example, we might put
  15. initialization code in a method in class \fBSmalltalk\fP, as follows:
  16. .DS L
  17. Class Smalltalk
  18.     getString
  19.         \(ua <1>
  20. |
  21.     run        | string |
  22.         [ '>    ' printNoReturn.
  23.            string <- smalltalk getString. 
  24.            string notNil ]
  25.             whileTrue: [ (string size > 0)
  26.                     ifTrue: [ smalltalk doIt: string ] ]
  27. ]
  28. .DE
  29. .PP
  30. Once the bytecode interpreter is started on the method \fBrun\fP, it will
  31. loop continuously, reading commands from the user (via the method 
  32. \fBgetString\fP) and executing them (via the method \fBdoIt:\fP).
  33. Presumably the user has some way of indicating end of input, such as the
  34. unix control-D convention, which causes \fBgetString\fP to return the
  35. value nil.  The \fIif\fP statement inside the while loop
  36. insures that if the user simply hits the return key execution will quickly 
  37. loop back to the prompt.
  38. .PP
  39. Besides making the initialization for the Little Smalltalk system easy,
  40. this approach also has the advantage of putting more code into Smalltalk
  41. itself, where the user can see it and (presumably) modify it if they wish.
  42. A general guideline is that it is better to put as much into Smalltalk
  43. as possible, since Smalltalk is easier to write and the bytecode representation
  44. usually smaller than the equivalent code in C.
  45. Never the less, there are valid reasons why an implementor might choose
  46. a different technique.
  47. .PP
  48. For example, if there are many other activities which should command the 
  49. attention of the controlling program (window updates, mouse motions) the 
  50. Smalltalk code may not be able to respond fast enough, or might become too 
  51. large and complex to be workable.
  52. In this case the only alternative is to have the front end respond directly
  53. to events, and only invoke the Smalltalk interpreter as time permits.
  54. In basic terms, the front end would perform the loop written in the method
  55. \fBinit\fP shown above (along with handling various other tasks), and then 
  56. call upon the method in class \fBSmalltalk\fP
  57. to execute the message \fBdoIt:\fP.
  58. .SH
  59. How to Do It
  60. .PP
  61. In either of the two schemes described above, an important message is 
  62. \fBdoIt:\fP, which takes a string (presumably representing a Smalltalk
  63. expression) and performs it.  An easy way to perform this message is to
  64. make a method out of the expression, by appending a message pattern
  65. on front, and then pass the string to the method parser.  If the method
  66. parser is successful, the method can then be executed.
  67. .DS L
  68. doIt: aString        | method |
  69.     method <- Method new.
  70.     method text: ( 'proceed ', aString ).
  71.     (method compileWithClass: Smalltalk)
  72.         ifTrue: [ method executeWith: #( 0 ) ]
  73. .DE
  74. .PP
  75. The message \fBcompileWithClass:\fP compiles the method as if it was
  76. appearing as part of class Smalltalk.  If compilation is successful,
  77. the message \fBexecuteWith:\fP executes the message, using as arguments
  78. the array #(0).  The array that accompanies this message must have at
  79. least one element, as the first value is used as the receiver for
  80. the method.
  81. Similar techniques can be used for the message \fBprintIt:\fP, if desired.
  82. .SH
  83. The Other End
  84. .PP
  85. The opposite extreme from the front end are those messages that originate
  86. within the bytecode interpreter and must be communicated to the user.
  87. We can divide these values into four categories:
  88. .IP 1.
  89. System errors.  These are all funnelled through the routine sysError(), found
  90. in memory.c.  System errors are caused by dramatically wrong conditions,
  91. and should generally cause the system to abort after printing the message
  92. passed as argument to sysError().
  93. .IP 2.
  94. Compiler errors.  As we noted above, the method compiler is used to
  95. parse expressions typed directly at the keyboard, so these message can
  96. also arise in that manner.  These are all funnelled through the routine
  97. compilError(), found in parse.c.  These should print their arguments 
  98. (two strings), in an appropriate location on the users screen.
  99. Execution continues normally after call.
  100. .IP 3.
  101. Various primitives, found in primitive.c, are also used to print strings
  102. on the users terminal.  In particular, an appropriate meaning should be
  103. given to the message \fBprint\fP in class \fBString\fP.  What appropriate
  104. means is undoubtedly implementation specific.
  105. .IP 4.
  106. Finally, and perhaps most importantly, there must be some means provided
  107. to allow users to enter and edit methods.  The interface for this task
  108. is standard; instances of class \fBClass\fP must respond to the messages
  109. \fBaddMethod\fP and \fBeditMethod:\fP, the latter taking as argument a
  110. symbol representing the name of a method.  How they achieve their two
  111. tasks is, however, implementation specific.
  112. Under Unix, a simple implementation adds a new primitive for Strings;
  113. this primitive copies the string into a temporary file, starts up the
  114. editor on the file, and returns the contents of the file when the user
  115. exits the editor.  Having this capability, the method editing code
  116. can be given as follows.  In class \fBClass\fP:
  117. .DS L
  118.     addMethod
  119.         self doEdit: ''
  120. |
  121.     editMethod: name        | theMethod |
  122.         theMethod <- methods at: name
  123.                 ifAbsent: [ 'no such method ' print. \(ua nil ].
  124.         self doEdit: theMethod text
  125. |
  126.     doEdit: startingText        | theMethod |
  127.         theMethod <- Method new;
  128.             text: startingText edit.
  129.         (theMethod compileWithClass: self)
  130.             ifTrue: [ methods at: theMethod name put: theMethod ]
  131. .DE
  132. .LP
  133. And in class \fBString\fP:
  134. .DS L
  135.     edit
  136.         \(ua <19 self>
  137. .DE
  138. .LP
  139. Here primitive 19 performs all the tasks of creating the temporary file,
  140. starting the editor, and creating the string representing the file
  141. contents when the editor is exited.
  142. .PP
  143. Alternative techniques, for example using windowing, would undoubtedly
  144. be more complicated.
  145.