MC logo

GNU Smalltalk User Manual


GNU Smalltalk Documentation


[ Next: | Previous:Top | Up:Top ]

GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

Copyright 1990, 91, 92, 94, 95, 99 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow.

  1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

    Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

  2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

    You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

  3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

    Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

    In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

  4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

    The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

    If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

  5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
  7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
  8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

    If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

    It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

    This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

  9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

    Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

one line to give the program's name and an idea of what it does.
Copyright (C) 19yy  name of author

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'.  This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than show w and show c; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.


[ Next: | Previous:Copying | Up:Top ]

Introduction

GNU Smalltalk is an implementation that closely follows the Smalltalk-80 language (tm ParcPlace Systems) as described in the book Smalltalk-80: the Language and its Implementation by Adele Goldberg and David Robson, which will hereinafter be referred to as "the Blue Book".

The Smalltalk programming language is an object oriented programming language. This means, for one thing, that when programming you are thinking of not only the data that an object contains, but also of the operations available on that object. The object's data representation capabilities and the operations available on the object are "inseparable"; the set of things that you can do with an object is defined precisely by the set of operations, which Smalltalk calls methods, that are available for that object. You cannot even examine the contents of an object from the outside. To an outsider, the object is a black box that has some state and some operations available, but that's all you know.

In the Smalltalk language, everything is an object. This includes variables, executable procedures (methods), stack frames (called method contexts or block contexts), etc. Each object is an instance of a class. A class can be thought of as a datatype and the set of functions that operate on that datatype. An instance is a particular variable of that datatype. When you want to perform an operation on an object, you send it a message, and the object performs an operation that corresponds to that message.

Unlike other Smalltalks (including Smalltalk-80), GNU Smalltalk emphasizes Smalltalk's rapid prototyping features rather than the graphical and easy-to-use nature of the programming environment (did you know that the first GUIs ran under Smalltalk?). The availability of a large body of system classes, once you master them, makes it pretty easy to write complex programs which are usually a task for the so called "scripting languages". Therefore, even though we have a nice GUI environment including a class browser (see Blox), the goal of the GNU Smalltalk project is currently to produce a complete system to be used to write your scripts in a clear, aesthetically pleasing, and philosophically appealing programming language.

An example of what can be obtained with Smalltalk in this novel way can be found in Class reference. That part of the manual is entirely generated by a Smalltalk program, starting from the source code for the system classes as distributed together with the system.


[ Next: | Previous:Overview | Up:Top ]

Installation


[ Next: | Previous:Installation | Up:Installation ]

Compiling GNU Smalltalk

The first thing to do to compile GNU Smalltalk is to configure the program, creating the makefiles and a gstconf.h, which contains guesses at the system's peculiarities. GST comes with a gstconf.h file which is valid for Cygnus' Win32 port of GCC and for Visual C++, an environment which makes harder to use the wonderful Unix tools under Windows 95/98/NT. For other systems, you can perform this configuration automatically by the `configure' shell script; to run it, merely type:

     configure

Options that you can pass to configure include --without-dld, which precludes Smalltalk programs from dynamically linking libraries at run-time, and --with-readline, which will look for the GNU readline library to allow for better command line editing.

After you've configured GNU Smalltalk, you can compile the system by typing:

make

Smalltalk should compile and link with no errors. If compiling goes wrong you'll want to examine the makefiles, and adjust them to suit the environment that you're running in. You may have to examine Makefile.defs.in and the first part of lib/Makefile.in, which define which compiler you will use, its options and more. For example, be sure to check if your compiler has extensions which, if not enabled, don't make it ANSI compatible. After having done this, re-run configure (this time it will be much faster) and try again.

After you have successfully built the GNU Smalltalk interpreter, you can test it by invoking it. You should be able to invoke Smalltalk, thus:

gst -V

You should see the various classes being loaded one by one. At the end you should see a message of the form:

Processing ValueAdaptors.st
"Major GC flip... done, used space = xy%"
Smalltalk Ready

st>

At this point, you have a working GNU Smalltalk. Congratulations!!!

If you want to use some of the wonderful GNU Smalltalk features, you should use the modules script. The modules script takes one or more directory names and creates new versions of cfuncs.c and Makefile which include that directory's contents. This is a major change with respect to previous versions of GST, which forced you to write special makefiles to include more than one feature. For example,

./modules blox
make
mv gst blox-gst
./modules blox tcp
make

will create two executables: one, blox-gst, only has support for the Blox GUI toolkit, and one, gst, has support for both the Blox GUI toolkit and the TCP toolkit (which does not work yet--it is only there for a taste of things to come).

You will also want to create the image file in the proper place (if you don't know what an image file is, see Save binary file). You could switch to the directory that you want the Smalltalk binary image to live in, and invoke Smalltalk. To do so, just move or copy the image file (gst.im) to its final home.


[ Next: | Previous:Compiling | Up:Installation ]

Including GNU Smalltalk in your programs (legal stuff)

Believe it or not, Smalltalk is (also) a very good scripting and macro language. For this reason, GNU Smalltalk is distributed as a library that you can link your programs to. It's very simple: just include gstpub.h, link to libgst.a, and you're done.

The GNU General Public License, under which GNU Smalltalk is distributed, clearly states that programs that link against GNU Smalltalk's library (libgst.a) must themselves be free software. So, if you develop a program whose run-time is different from that in the standard distribution (main.c), that run-time will have to be distributed as free software.

Using the system classes in an image can be considered to be a kind of `linking'. So, all the consequences of the GPL that apply to executable files do apply to Smalltalk images too. For example, GNU Smalltalk can only be used to create free Smalltalk programs. Be sure to read licenses for other class libraries that you use, to check whether they are compatible with the GNU General Public License.

If you distribute the program as an image file, you can remove the source code from it. However, you have to distribute the whole source code for your application and for the entire GNU Smalltalk system, in the version used to create your program, together with it.

Well, no more legal stuff now, and back to computers... For more information on what to do in your program so that it communicates well with Smalltalk, relate to C and Smalltalk.


[ Previous:More legal stuff | Up:Installation ]

Adding your own features to GNU Smalltalk.

Another nice thing you can do with GNU Smalltalk is sticking to the bare bones environment and enhance it with your own goodies. If they're written in Smalltalk only, no problem: you could get them to work as packages (see Packages), together with the GNU Smalltalk packaging system, but that is likely to be a five-minutes task.

You should, instead, do something much more interesting if you're goodie has C functions and you want it to work together with the modules shell script (see Compiling). This section explains what to do, taking the (yet experimental) TCP library as a guide.

First of all, create a cfuncs.h in your directory. The TCP library's cfuncs.h is simply

CALL(initTCP);

which means: to initialize the TCP layer, call the extern function initTCP, which in turn shall contain the required calls to defineCFunc (see C and Smalltalk). Most of the times, cfuncs.h will contain just a call to the CALL macro.

Instead, you might want to use the CFUNC macro, which defines C functions directly from cfuncs.h: in the automatically generated cfuncs.c, it will be defined as

#define CFUNC(smalltalk, c)     \
       { extern void c(); defineCFunc(smalltalk, c); }

Using CFUNC has an advantage and a disadvantage: the advantage is that you keep all the declarations in a single file, while CALL divides them between cfuncs.h and where you put the called function; the disadvantage is that you will not be able to declare your C functions as static. For this reason, all the packages supplied with GNU Smalltalk stick on CALL.


[ Next: | Previous:Installation | Up:Top ]

Using GNU Smalltalk


[ Next: | Up:Using GNU Smalltalk ]

Command line arguments

GNU Smalltalk may be invoked via the following command:

gst [ flags ... ] [ file ... ]

When you first invoke GNU Smalltalk, it will attempt to see if any of the kernel method definition files are newer than the last saved binary image in the current directory (if there is one). If there is a newer kernel method definition file, or if the binary image file (called gst.im) does not exist, a new binary image will be built by loading in all the kernel method definition files, performing a full garbage collection in order to compact the space in use, and then saving the resulting data in a position independent format. Your first invocation should look something like this:

"Minor GC flip... done, used space = 76.4%"
"Major GC flip... done, used space = 42.4%"
Smalltalk Ready

st>

If you specify file, that file will be read and executed and Smalltalk will exit when end of file is reached. If you specify more than one file, each will be read and processed in turn. If you don't specify file, standard input is read, and if the standard input is a terminal, a prompt is issued. You may specify - or -- for the name of a file to invoke an explicit read from standard input.

You can specify both short and long flags; for example, --version is exactly the same as -v, but is easier to remember. Short flags may be specified one at a time, or in a group. A short flag or a group of short flags always starts off with a single dash to indicate that what follows is a flag or set of flags instead of a file name; a long flag starts off with two consecutive dashes, without spaces between them.

In the current implementation the flags can be intermixed with file names, but their effect is as if they were all specified first. The various flags are interpreted as follows:

-a -smalltalk
Used to make arguments available to Smalltalk code. The C option parser discards everything after the parameter including -a, while Smalltalk code can get it sending the arguments message to the Smalltalk object.

Examples:

command line          what the C code gets    Smalltalk arguments
gst                   gst                     #()
gst -Via foo bar      gst -Vi                 #('foo' 'bar')
gst -Vai test         gst -Vi                 #('test')
gst -Vaq              gst -Vq                 #()
gst --verbose -aq -c  gst --verbose -q        #('-c')

That should be clear.


-c -core-dump
When this flag is set and a fatal signal occurs, a core dump is produced after an error message is printed. Normally, the backtrace is produced and the system terminates without dumping core.


-d -user-declaration-trace
Declaration tracing...prints the class name, the method name, and the byte codes that the compiler is generating as it compiles methods. Only for files that are named explicitly on the command line; kernel files that are loaded automatically as part of rebuilding the image file do not have their declarations traced.


-D -kernel-declaration-trace
Like the -d flag, but also includes declarations processed for the kernel files.


-e -user-execution-trace
Prints the byte codes being executed as the interpreter operates. Only works for those executions that occur after the kernel files have been loaded and the image file dumped.


-E -kernel-declaration-trace
Like the -e flag, but includes all byte codes executed, whether they occur during the loading of the kernel method definition files, or during the loading and execution of user files.


-g -no-gc-messages
Suppress garbage collection messages.


-h -H -? -help
Prints out a brief summary of the command line syntax of GNU Smalltalk, including the definitions of all of the option flags, and then exits.


-i -rebuild-image
Ignore the saved image file; always load from the kernel method definition files. Setting this flag bypasses the normal checks for kernel files newer than the image file, or the image file's version stamp out of date with respect to the Smalltalk version. After the kernel definitions have been loaded, a new image file will be saved.


-I file -image-file file
Use the image file named FILE as the image file to load. Completely bypasses checking the file dates on the kernel files and standard image file.


-l -log-changes
Produce a log of the compiled Smalltalk code to st-changes.st, in the current working directory.


-L file -log-file file
Produce a log of the compiled Smalltalk code to the file named file.


-q -quiet -silent
Suppress the printing of execution information while GNU Smalltalk runs. Messages about the beginning of execution or how many byte codes were executed are completely suppressed when this flag is set.


-Q -no-messages
Suppress the printing of execution information and any other informative message while GNU Smalltalk runs. Useful, for example, for CGI programs.


-r -regression-test
Disables certain informative I/O; this is used by the regression testing system and is probably not of interest to the general user.


-s -store-no-source
Usually, Smalltalk stores the methods' source code as FileSegments for files in the kernel directory, and as Strings for files outside it. This behavior minimizes problems on recompile, because FileSegments cannot be relied upon if the source file changes. However, storing source code for big libraries is not useful, since the file-in source is unlikely to change. There are two ways to override this behavior and make Smalltalk store everything loaded in a particular session as FileSegments: one is to specify a directory relative to the kernel directory, such as /usr/local/smalltalk/kernel/../blox/Blox.st; the other is to specify this option on the command line.


-S -snapshot
Save a snapshot after loading files from the command line. Of course the snapshot is not saved if you include - (stdin) on the command line and exit by typing Ctrl-C.


-v -version
Prints out the Smalltalk version number, then exits.


-V -verbose
Enables verbose mode. When verbose mode is on, various diagnostic messages are printed (currently, only the name of each file as it's loaded).


-y -yacc-debug
Turns on parser debugging. Not typically used.


[ Next: | Previous:Command line | Up:Using GNU Smalltalk ]

Startup sequence

When GNU Smalltalk is invoked, it tries to find the saved binary image file. If this is found, it compares the write dates of all of the kernel method definition files against the write date of the binary image file. If any of the kernel files are newer, or if the image file cannot be found, or if the -i flag is used, the image file is ignored, all of the kernel method definition files are loaded and then the binary image file is saved.

Smalltalk first looks for the saved image file, called gst.im in the path indicated by the SMALLTALK_IMAGE environment variable (if it is defined); if SMALLTALK_IMAGE is not defined, Smalltalk will try the current directory and then the path compiled in the binary (usually, under Unix systems, /usr/local/share/smalltalk or a similar data file path).

Smalltalk first looks for the saved image file, called gst.im in the current directory, to allow for overriding the system default image file. If that doesn't exist, it checks the SMALLTALK_IMAGE environment variable, and if that's defined, it tries to find the image file in the directory given by SMALLTALK_IMAGE, which again allows individual users to override the system default location for the image file. If SMALLTALK_IMAGE is not defined, Smalltalk will use a the path compiled in the binary (usually, under Unix systems, /usr/local/share/smalltalk or a similar data file path).

For the kernel files, the procedure is a bit more complicated. Smalltalk first similarly elects a default directory in which to look for each of the kernel method definition files. First it tries the directory pointed to by SMALLTALK_KERNEL if it is defined, then the current directory's kernel subdirectory, then in the system default location for kernel files, compiled in the binary (usually, under UNIX systems, in /usr/local/share/smalltalk/kernel or a similar data file path).

Each of the files, however, is first looked for in the current directory, then in its kernel subdirectory, then in the default path (which is chosen as just described).

Even if the image file is more recent than all the kernel definition files, if the version of Smalltalk that created the image file is different from the one that's trying to load it, or if the size of the OOP table is different between image save time and image load time, the image file will be ignored. GST is able to load an image created on a system with the same sizeof(long) but different endianness (for example, a 68k image on an x86), but not an image created on a system with different sizeof(long) like an Alpha image on an x86.

The set of files that make up the kernel method definitions can be found in lib/lib.c, in the standardFiles variable. Each file is loaded in turn. Once they have all been loaded, a full garbage collection is performed, and the entire contents of the object table and object memory are dumped to a file called gst.im in the current directory.

At this point, independent of whether the binary image file was loaded or created, any blocks that were marked as init blocks (see Init Blocks) are invoked (in the order of their declaration).

After the init blocks have been executed, the user initialization file (see Init file) (if any) is loaded.

Finally, if there were any files specified on the command line, they are loaded, otherwise standard input is read and executed until an EOF is detected.


[ Next: | Previous:Startup | Up:Using GNU Smalltalk ]

Syntax of GNU Smalltalk

The language that Smalltalk accepts is based on the file out syntax as shown in the Green Book, also known as Smalltalk-80: Bits of History, Words of Advice by Glenn Krasner. The entire grammar of GNU Smalltalk is described in the gst.y file, but a brief description may be in order:

<statements> !

Executes the given statements immediately. For example,

16rFFFF printNl !

prints out the decimal value of hex FFFF, followed by a newline.

Smalltalk quitPrimitive !

exits from the system. You can also type a C-d to exit from Smalltalk if it's reading statements from standard input.

! <class expression> methodsFor: <category name> !
<method definition 1> !
<method definition 2> !
...
<method definition n> ! !

This syntax is used to define new methods in a given class. The <class expression> is an expression that evaluates to a class object, which is typically just the name of a class, although it can be the name of a class followed by the word class, which causes the method definitions that follow to apply to the named class itself, rather than to its instances. Two consecutive bangs terminate the set of method definitions. <category name> should be a string object that describes what category to file the methods in.

!Float methodsFor: 'pi calculations'!

radiusToArea
    ^self squared * Float pi !

radiusToCircumference
    ^self * 2 * Float pi ! !

It also bears mentioning that there are two assignment operators: _ and :=. Both are usable interchangeably, provided that they are surrounded by spaces. The GNU Smalltalk kernel code uses the := form exclusively, but _ is supported a) for compatibility with previous versions of GNU Smalltalk b) because this is the correct mapping between the assignment operator mentioned in the Blue Book and the current ASCII definition. In the ancient days (like the middle 70's), the ASCII underscore character was also printed as a back-arrow, and many terminals would display it that way, thus its current usage. Anyway, using _ may lead to portability problems.

The return operator, which is represented in the Blue Book as an up-arrow, is mapped to the ASCII caret symbol ^.

A complete treatment of the syntax of the language is beyond the scope of this document. Please refer to the included tutorial or to the Blue Book for details of the syntax and semantics of the Smalltalk language. If that's the only Smalltalk-80 book available you can look at the "Purple Book" (Smalltalk-80, the language), which is basically a Blue Book without the part on the implementation. The latter part, in fact, is also available online (HTML) at <http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebook_imp_toc.html>: this, plus the Purple Book (which is still in print) essentially equals a Blue Book for those seeking further info.


[ Next: | Previous:Syntax | Up:Using GNU Smalltalk ]

Operating GNU Smalltalk

You operate GNU Smalltalk by typing in expressions to the st> prompt, and/or reading in files that contain Smalltalk code.

At some time, you may wish to abort what GNU Smalltalk is doing and return to the command prompt. You can use C-c to do this.


[ Next: | Previous:Operation | Up:Using GNU Smalltalk ]

Per-user init files

When GNU Smalltalk is invoked, it will examine your home directory for a file with the name .stinit. If this file exists, it is loaded as a normal Smalltalk file. This file can be used for per-user customizations (such as turning off garbage collection messages), and definitions.

This file is always loaded; to have some code loaded only before main binary image is created, put it in .stpre. This file is ignored when creating the default image (which resides, under Unix systems, in /usr/local/share/smalltalk or a similar data file path).

Under MS-DOS, the name of the files are, respectively, _stinit and _stpre. Under Atari ST, they are .gstinit and .gstpre.


[ Previous:Init file | Up:Using GNU Smalltalk ]

Running the test suite

GNU Smalltalk comes with a set of files that provides a simple regression test suite.

To run the test suite, you should be connected to the top-level Smalltalk directory. Type

make check

You should see the names of the test suite files as they are processed, but that's it. Any other output indicates some problem. The only system that I know of which currently fails the test suite is the NeXT, and this is apparently due to their non-standard C runtime libraries.

The test suite is by no means exhaustive. One good way to help the GNU Smalltalk project, and learn some Smalltalk in the process, is to add files and tests to the test suite directory. Ideally, the test suite would be used as the "go/nogo" gauge for whether a particular port of GNU Smalltalk is really working properly.


[ Next: | Previous:Using GNU Smalltalk | Up:Top ]

Features of GNU Smalltalk

In this section, the features which are specific to GNU Smalltalk are described. These features include support for calling C functions from within Smalltalk, accessing UNIX environment variables, and controlling various aspects of compilation and execution monitoring.

Note that, in general, GNU Smalltalk is much more powerful than the original Smalltalk-80, as it contains a lot of methods that are common in today's Smalltalk implementation but were absent in the Blue Book. Examples include Collection's contains: and conform: methods and many methods in SystemDictionary (the Smalltalk dictionary's class).


[ Next: | Previous:Features | Up:Features ]

Saving snapshots to binary files

GNU Smalltalk allows you to snapshot the current state of the virtual machine. This means that all objects are saved to a file that can be loaded rapidly at a later point in time. There are two messages that you can use:

SystemDictionary snapshot
This saves the current state of the GNU Smalltalk system to a file called gst.im. When you later invoke GNU Smalltalk, this file will be used for binary loading if none of the kernel files has a more recent file modification date, if the GNU Smalltalk version number is the same as the one that created the image file, and if the size of the object table has not changed between the time that the image file was dumped and the time that the image file is loaded. Note that the instance's class that you send this message to is SystemDictionary; in practice, you send this message to the sole instance of SystemDictionary, Smalltalk.


SystemDictionary snapshot: aString
This operates exactly like the snapshot message above, except that the string argument you supply is used as the name of the file to save the image to. However, since you currently cannot specify any other file name for the image file to load from other than gst.im, this capability is of limited utility (you could save several snapshots throughout a run, and move the one that you were happy with to gst.im).


[ Next: | Previous:Save binary file | Up:Features ]

The system message

SystemDictionary system: aString
This message invokes system(3), passing the string aString to it. It returns an integer which is whatever system(3) returns.


[ Next: | Previous:system | Up:Features ]

The getenv message

SystemDictionary getenv: aString
This message does a getenv(3) on string aString, and returns the result. The result is either a string, or nil if there was no environment variable with the name aString.


[ Next: | Previous:getenv | Up:Features ]

Initialization blocks

SystemDictionary addInit: aBlock
This message adds aBlock to the set of init blocks that the system has. Init blocks are invoked after loading binary image files or kernel files, but before loading any command line files or reading from standard input. aBlock should be a block that takes no arguments.


[ Next: | Previous:Init Blocks | Up:Features ]

Memory accessing methods

GNU Smalltalk provides methods for directly accessing real memory. You may access memory either as individual bytes, or as 32 bit words. You may read the contents of memory, or write to it. Due to the limitations of Integers in GNU Smalltalk, you can only deal with word memory as 31 bit quantities.

You may also determine the real memory address of an object or the real memory address of the OOP table that points to a given object, by using messages to the Memory class, described below.

There are two basic classes which provide methods to access memory: ByteMemory and WordMemory. The methods for these classes are as follows:

ByteMemory class at: address
Returns the byte at address as an Integer. address is also an Integer.


ByteMemory class at: address put: value
Sets the byte at address (an Integer) to be value (an Integer in the range of 0 to 255).


WordMemory class at: address
Returns an Integer that represents the contents of address, which should also be an Integer. Depending on the machine architecture, you'll probably want to ensure that address is a multiple of 4.


WordMemory class at: address put: value
Stores the Integer value into real memory at address. Same alignment cautions as above.


Bigendian
A global variable that is set to true on machine architectures where the most significant byte of a 32 bit integer has the lowest address (e.g. 68000 and Sparc), and false on architectures where the least significant byte occurs at the lowest address (e.g. Intel and VAX).


C*Size and C*Alignment
The CIntSize, CLongSize, CShortSize, CFloatSize, CDoubleSize, CPtrSize, CDoubleAlignment globals are provided by the VM as part of the Smalltalk dictionary, and are there for compatibility with previous versions of GST. However you should not use them and, instead, send messages like CInt sizeof or CDouble alignOf.

To find out the real memory address of an object or its OOP table entry, you may use one of the methods described below.

Memory class addressOfOOP: anObject
Returns the address of the OOP for anObject. The address is an Integer and will not change over time (i.e. is immune from garbage collector action).


Memory class addressOf: anObject
Returns the address of the actual object that anObject references. Note that this address is only valid until the next GC flip; thus it's pretty risky to count on the address returned by this method for very long.


Object asOop
Returns the index of the OOP for anObject. This index is immume from garbage collection and is the same value used by default as an hash value for anObject (it is returned by Object's implementation of hash and identityHash.


Integer asObject
Converts the given OOP index (not address) back to an object. Fails if no object is associated to the given index.


Integer asObjectNoFail
Converts the given OOP index (not address) back to an object. Returns nil if no object is associated to the given index.

Other methods in ByteArray and Memory allow to read various C types (doubleAt:, ucharAt:, etc.). For examples of using asOop and asObject, look at the Blox source code in blox/BloxEvents.st.


[ Next: | Previous:Memory access | Up:Features ]

Producing backtraces

SystemDictionary backtrace
When you send this message to a system dictionary (i.e. Smalltalk, the only system dictionary available), it produces a backtrace of the methods that are the ancestors of the currently executing method. This backtrace is exactly like the one that is printed when the interpreter encounters an error.


[ Next: | Previous:backtrace | Up:Features ]

Controlling tracing of bytecode execution

SystemDictionary executionTrace: aBoolean
This method controls whether byte codes are printed as the interpreter processes them or not. It has the exact same effect as the command line switch -e, but allows for very fine grain control of the tracing. Use true to enable tracing, and false to disable tracing.


[ Next: | Previous:executionTrace | Up:Features ]

Printing Smalltalk stack during execution

SystemDictionary verboseTrace: aBoolean
This method is used in conjunction with SystemDictionary executionTrace:. When given the argument true, and execution tracing is on, it causes the top element of the Smalltalk stack to be printed before each byte code is executed.


[ Next: | Previous:verboseTrace | Up:Features ]

Assistance using C debuggers

SystemDictionary debug
This primitive method calls a C routine which is called debug. This can be useful in the following way: you want to get access to dbx or gdb at a particular point in the execution of a Smalltalk method. There typically is no easy way to do this. In the GNU Smalltalk system, the C routine called debug exists solely so that you can put a breakpoint in it from a debugger such as dbx (it is an empty routine, and thus harmless). You put a call to the C debug routine in the C function that you want to debug.

So, if you put a breakpoint in the debug routine, and invoke the debug method just before the code which you want to debug, you gain control for detailed debugging.


[ Next: | Previous:debug | Up:Features ]

Control C profiling during execution of methods.

SystemDictionary monitor: aBoolean
This primitive method allows the user to enable or disable the generation of C profiling information during the operation of the interpreter. You must modify the Makefile to switch the compilation to profiling mode and recompile the entire system for this to take effect.

When you pass true to this method, you enable the collection of profiling data during the operation of the interpreter to be later analyzed by the gprof program. Passing false disables this collection. You can use this facility to closely monitor the operation of the interpreter over a given set of Smalltalk code to see where it's spending its time.


[ Next: | Previous:monitor | Up:Features ]

Controlling generation of GC flip messages

SystemDictionary gcMessage: aBoolean
This message allows the user to control whether a message is printed each time the garbage collector flips between old and new space. The default state is true, meaning that when the garbage collector performs a flip, a message will be printed. If you supply false as the argument of this message, the message generation is disabled until you turn it back on.


[ Next: | Previous:gcMessage | Up:Features ]

Explicit termination of GNU Smalltalk

SystemDictionary quitPrimitive
Invoking this method causes an immediate and unconditional exit from GNU Smalltalk.


[ Next: | Previous:quitPrimitive | Up:Features ]

UNIX file-IO primitive messages

Three classes (FileStream, File, Directory) allow you to create files and access the file system in a fully object-oriented way. FileStream objects also allow you to write raw binary data in a portable endian-neutral format.

For more information on these classes, look in the class reference.

In addition, the three files, stdin, stdout, and stderr are declared as global instances of FileStream that are bound to the proper values.

Finally, Object defines four other methods: print and printNl, store and storeNl. These do a printOn: or storeOn: to the "Transcript" object; this object, which is the sole instance of class TranscriptInterface, normally delegates write operations to stdout. If you load the Blox GUI, instead, the Transcript Window will be attached to the Transcript object (see Blox).


[ Next: | Previous:UNIX file-IO | Up:Features ]

The GNU Smalltalk ObjectDumper

Another GNU Smalltalk-specific class, the ObjectDumper class, allows you to dump objects in a portable, endian-neutral, binary format. Note that you can use the ObjectDumper on ByteArrays too, thanks to another GNU Smalltalk-specific class, ByteStream, which allows you to treat ByteArrays the same way you would treat disk files.

For more information on the usage of the ObjectDumper, look in the class reference.


[ Next: | Previous:Object dumping | Up:Features ]

Explicitly loading files

The fileIn: message sent to the FileStream class, with a file name as a string argument, will cause that file to be loaded into Smalltalk.

For example,

FileStream fileIn: 'foo.st' !

will cause foo.st to be loaded into GNU Smalltalk.


[ Next: | Previous:FileIn | Up:Features ]

Weak, finalizable, read-only objects

A few methods in Object support the creation of particular objects. This include:

  1. finalizable objects
  2. weak objects (i.e. objects whose contents are not considered, during garbage collection, when scanning the heap for live objects).
  3. read-only objects (like literals found in methods)

They are:

makeWeak
Marks the object so that it is considered weak in subsequent GC passes. The garbage collector will consider dead an object which has references only inside weak objects, and will replace references to such an "almost-dead" object with nils.


addToBeFinalized
Marks the object so that, as soon as it becomes unreferenced, its finalize method is called. Before finalize is called, the VM implicitly removes the objects from the list of finalizable ones. If necessary, the finalize method can mark again the object as finalizable, but by default finalization will only occur once. Note that a finalizable object is kept in memory even when it has no references, because tricky finalizers might "resuscitate" the object; automatic marking of the object as not to be finalized has the nice side effect that the VM can simply delay the releasing of the memory associated to the object, instead of being forced to waste memory even after finalization happens.


removeToBeFinalized
Removes the to-be-finalized mark from the object. As I noted above, the finalize code for the object does not have to do this explicitly.


finalize
This method is called by the VM when there are no more references to the object (or, of course, if it only has references inside weak objects).


isReadOnly
This method answers whether the VM will refuse to make changes to the objects when methods like become:, basicAt:put:, and possibly at:put: too (depending on the implementation of the method). Note that GNU Smalltalk won't try to intercept assignments to fixed instance variables, nor assignments via instVarAt:put:. Many objects (Characters, nil, true, false, method literals) are read-only by default.


makeReadOnly: aBoolean
Changes the read-only or read-write status of the receiver to that indicated by aBoolean.


[ Next: | Previous:Special objects | Up:Features ]

The context unwinding system

When the C code files in something, the doits in the file-in are evaluated in a different execution environment so that the file-in is protected from errors signalled in the doit; the same also happens, for example, when you do a C callin to Smalltalk.

Now, suppose that you want to evaluate something using Behavior's evaluate: method. Instead of using complex exception handling code, the unwinding system can be used to obtain that behavior with code as simple as this:

    [ lastResult := evalFor perform: selector ] valueWithUnwind.

In fact, using valueWithUnwind arranges things so that an exception will resume execution after the block, instead of stopping it.

This system is quite low-level, so it should not be used in most cases: as a rule of thumb, use it only when the corresponding C code uses the prepareExecutionEnvironment, stopExecuting and finishExecutionEnvironment functions. The places where I'm using it obey this rule. They include the exception handling system, the ST parser, Behavior>>#evalString:to: and Behavior>>#evalString:to:ifError:.

The valueWithUnwind method is defined in BlkClosure.st, but it mostly relies on code in the ContextPart.st file. Here are the methods involved in the unwinding mechanism: you can find descriptions in the Smalltalk source code. Note that all these methods are internal, this reference is provided just for sake of completeness.


[ Previous:Context unwinding | Up:Features ]

Packages

Thanks to Andreas Klimas' insight, GNU Smalltalk now includes a powerful packaging system which allows one to file in components (goodies in Smalltalk's very folkloristic terminology) without caring of whether they need other goodies to be loaded.

The packaging system is implemented by a Smalltalk class, PackageLoader, which looks for information about packages in the file named (guess what) packages, in the current image directory. There are two ways to load something using the packaging system. The first way is to use the PackageLoader's fileInPackage: and fileInPackages: methods. For example:

    PackageLoader fileInPackages: #('BloxTestSuite' 'Browser').
    PackageLoader fileInPackage: 'Compiler'.

The second way is to use the Load.st file in the main GST directory. For example, start GNU Smalltalk with this command line:

    gst Load.st -aq BloxTestSuite Browser Blox Compiler

and GST will automatically file in:

Then it will save the Smalltalk image, and finally exit!

To provide support for this system, you have to give away with your GST goodies a small file (say you call it mypkg) which looks like this:

# This is a bogus comment for the package file
# for the absolutely WONDERFUL package MyPackage

MyPackage
    MyPrereq1 MyPrereq2 C:MyCallout1 C:MyCallout2
    MyFilein1.st MyFilein2.st
    ../yourDirectoryName      # absolute or relative to kernel path

then people who install your package will only have to do

    ./install-pkg mypkg

which is a small shell script which will execute these two commands

    cat packages mypkg > packages
    gst Load.st -aq MyPackage

Simple, isn't it? Here is a list of the packages supplied with GNU Smalltalk 1.6.2: Blox (see Blox), BloxTestSuite, Browser, CInt, Compiler (see Compiler), DLD (see Dynamic loading), GDBM, Parser, Tokenizer. For examples of package declarations, have a look at the file packages as distributed.


[ Next: | Previous:Packages | Up:Packages ]

Blox

Blox is a GUI building block tool kit. It is an abstraction on top of the a platform's native GUI toolkit that is common across all platforms. Writing to the Blox interface means your GUI based application will be portable to any platform where Blox is supported.

Blox is based on Tcl/Tk, which constitutes the required portability layer: instead of having to rewrite widgets and support for each platform, Blox simply hands valid Tcl code to a standard Tcl 8.0 environment; the abstraction from the operating system being used is then provided by Tk, which does quite a good job of providing a user interface which is both portable and has a native look and feel.

An alternative version of Blox, based on Gtk+, is in the works.


[ Next: | Previous:Blox | Up:Packages ]

The Smalltalk-in-Smalltalk compiler

The Smalltalk-in-Smalltalk compiler is a nice compiler for Smalltalk code which is written in Smalltalk itself. Ideally, the C compiler would only serve to bootstrap the system, then a fully working Smalltalk compiler would start compiling methods.

The current status of the Smalltalk-in-Smalltalk compiler can be summarized thus: it does work, but it does not work well. This for many reasons: first of all it is slow (10-15 times slower than the C compiler), and it does not produce very optimized code. Anyway it has very few bugs (it does have some), it is a good example of programming the GNU Smalltalk system, and its source code (found in the compiler directory) provides good insights into the Smalltalk virtual machine: so, after all, it is not that bad.

The compiler is built on a recursive descent parser which creates parse nodes in the form of instances of subclasses of STParseNode. Then the parser instantiates a compiler object which creates the actual method; more information on the inner workings of the compiler can be found in the comment for the STCompiler class.

If want to give it a try, just file in the Compiler package.


[ Previous:Compiler | Up:Packages ]

Dynamic loading through the DLD package

DLD is the Dynamic LoaDer package. This is a peculiar package in that it is always loaded if your system supports it; currently supported architectures include shlib (that is the dlopen function as used in Linux, BSD and Solaris), Win32, HPUX, GNU DLD (Linux ELF) and GNU libtool (which includes a portable dlopen for a lot of systems).

The DLD package enhances the C callout mechanism to automatically look for unresolved functions in a series of program-specified libraries. To add a library to the list, evaluate code like the following:

     DLD addLibrary: '/usr/lib/libc.a'

You will then be able to use #defineCFunc:... (see C callout) to define all the functions in the C run-time library. Note that this is a potential security problem (especially if your program is SUID root under Unix), so you might want to disable DLD when using GNU Smalltalk as an extension language. To disable DLD, configure GNU Smalltalk passing the --without-dld switch.

Note that a DLD class will be present even if DLD is disabled (either because your system is not supported, or by the --without-dld configure switch) but any attempt to perform dynamic linking will result in an error.


[ Next: | Previous:Features | Up:Top ]

Interoperability between C and GNU Smalltalk

GNU Smalltalk provides powerful ways to incorporate its engine and virtual machine through a C and Smalltalk interoperability layer which allows Smalltalk to call C subroutines and C to call back Smalltalk methods.


[ Next: | Previous:C and Smalltalk | Up:C and Smalltalk ]

Using the C callout mechanism

To use the C callout mechanism, you first need to inform Smalltalk about the C functions that you wish to call. You currently need to do this in two places: 1) you need to establish the mapping between your C function's address and the name that you wish to refer to it by, and 2) define that function along with how the argument objects should be mapped to C data types to the Smalltalk interpreter. As an example, let us use the pre-defined (to GNU Smalltalk) functions of system and getenv.

First, the mapping between these functions and string names for the functions needed to be established in cint.c. In the function initCFuncs, the following code appears:

extern int system();
extern char *getenv();

defineCFunc("system", system);
defineCFunc("getenv", getenv);

Any functions that you will call from Smalltalk must be similarly defined.

Second, we need to define a method that will invoke these C functions and describe its arguments to the Smalltalk runtime system. Such a method is automatically generated by calling a method which is available to every class, defineCFunc:withSelectorArgs:returning:args:. The method that was used in previous versions of GNU Smalltalk, defineCFunc:withSelectorArgs:forClass:returning:args:, is still present for backward compatibility, but its use is deprecated and should be avoided.

Here are the definitions for the two functions system and getenv (taken from CFuncs.st)

SystemDictionary defineCFunc: 'system'
    withSelectorArgs: 'system: aString'
    returning: #int
    args: #(string)!

SystemDictionary defineCFunc: 'getenv'
    withSelectorArgs: 'getenv: aString'
    returning: #string
    args: #(string)!

The various keyword arguments are described below.

The arguments are as follows:

SystemDictionary
This specifies where the new method should be stored. In our case, the method will be installed in the SystemDictionary, so that we would invoke it thus:
   Smalltalk system: 'lpr README' !

Again, there is no special significance to which class receives the method; it could have just as well been Float, but it might look kind of strange to see:

   1701.0 system: 'mail sbb@gnu.org' !

defineCFunc: 'system'
This says that we are defining the C function system. This name must be EXACTLY the same as the string passed to defineCFunc.


withSelectorArgs: 'system: aString'
This defines how this method will be invoked from Smalltalk. The name of the method does not have to match the name of the C function; we could have just as easily defined the selector to be 'rambo: fooFoo'; it's just good practice to define the method with a similar name and the argument names to reflect the data types that should be passed.
returning: #int
This defines the C data type that will be returned. It is converted to the corresponding Smalltalk data type. The set of legal return types is:
   char        Single C character value
   string      A C char * value, converted to a Smalltalk string
   stringOut   A C char * value, converted to a Smalltalk string
               and then freed.
   symbol      A C char * value, converted to a Smalltalk symbol
   int         A C int value
   long        A C long value
   double      A C double value, converted to an instance of Float
   void        No returned value
   cObject     An anonymous C pointer value; useful to pass back to
               some C function later
   smalltalk   An anonymous (to C) Smalltalk data value; should have
               been passed to C at some point in the past or created
               by the program by calling other public GNU Smalltalk
               functions (see Smalltalk types).
   <ctype>     You can pass an instance of CType or one of its
               subclasses (see C data types)

args: #(string)
This is an array of symbols that describes the types of the arguments in order. For example, to specify a to call open(2), the arguments might look something like:
   args: #(string int)

The following argument types are supported; see above for details.

   unknown     Smalltalk will make the best conversion that it can
               for this object; see the mapping table below
   boolean     passed as "char", which is promoted to "int"
   char        passed as "char", which is promoted to "int"
   string      passed as "char *"
   stringOut   passed as "char *", the contents are expected to be
               overwritten with a new C string, and the object that
               was passed becomes the new string on return
   symbol      passed as "char *"
   byteArray   passed as "char *", even though may contain NUL's
   int         passed as "int"
   long        passed as "long"
   double      passed as "double"
   variadic    an Array is expected, each of the elements of the
               array will be converted
   cObject     C object value passed as "long" or "void *"
   smalltalk   Pass the object pointer to C.  The C routine should
               treat the value as a pointer to anonymous storage.
               This pointer can be returned to Smalltalk at some
               later point in time.
   self        Pass the receiver, converting it to C like an 'unknown'
               parameter.  Parameters passed as self don't map to
               the message's arguments, instead they map to the
               message's receiver.

Table of parameter conversions:

Declared param type     Object type             C parameter type used

smalltalk               anything                OOP
long                    Integer                 long
unknown/self            Integer                 long
int                     Integer                 int
char                    Integer                 int
int                     Boolean (True, False)   int
boolean                 Boolean (True, False)   int
char                    Boolean (True, False)   int
unknown/self            Boolean (True, False)   int
long                    Boolean (True, False)   long
char                    Character               int (C promotion rule)
unknown/self            Character               int
string                  String                  char *
stringOut               String                  char *
unknown/self            String                  char *
symbol                  Symbol                  char *
string                  Symbol                  char *
unknown/self            Symbol                  char *
byteArray               ByteArray               char *
unknown/self            ByteArray               char *
double                  Float                   double (C promotion)
unknown/self            Float                   double
cObject                 CObject                 void *
unknown/self            CObject                 void *
unknown/self            anything else           OOP
variadic                Array                   each element is passed
                                                according to "unknown"


[ Next: | Previous:C callout | Up:C and Smalltalk ]

The C data type manipulation system

CType is a class used to represent C data types themselves (no storage, just the type). There are subclasses called things like C<mumble>CType. The instances can answer their size and alignment. Their valueType is the underlying type of data. It's either an integer, which is interpreted by the interpreter as the scalar type, or the underlying element type, which is another CType subclass instance.

To make life easier, there are global variables which hold onto instances of CScalarCType: they are called C<mumble>Type (like CIntType, not like CIntCType), and can be used wherever a C datatype is used. If you had an array of strings, the elements would be CStringType's (a specific instance of CScalarCType).

CObject is the base class of the instances of C data. It has a subclass called CScalar, which has subclasses called C<mumble>. These subclasses can answer size and alignment information.

Instances of CObject holds a pointer to a C type variable. The variable have been allocated from Smalltalk by doing <type> new, where <type> is a CType subclass instance, or it may have been returned through the C callout mechanism as a return value. Thinking about this facet of the implementation (that CObject point to C objects) tends to confuse me when I'm thinking about having CObjects which are of type (say) long*... so I try to think of CObject as just representing a C data object and not thinking about the implementation. To talk about the type long*, you'd create an instance of CPtrCType (because all CType instances represent C types, not C objects), via

CPtrCType elementType: CLongType.  "use the existing CLongCType instance"

To allocate one of these C objects, you'd do:

longPtr := (CPtrCType elementType: CLongType) new.

Now you have a C variable of type "long *" accessible from longPtr.

Scalars fetch their value when sent the value message, and change their value when sent the value: message.

CStrings can be indexed using at: with a zero based index, which returns a Smalltalk Character instance corresponding to the indexed element of the string. To change the value at a given index, use at:put:.

To produce a pointer to a character, use addressAt:. To dereference the string, like *(char *)foo, use deref: this returns an object of type CChar, not a Character instance). To replace the first character in the string, use deref: and pass in a CChar instance. These operations aren't real useful for CStrings, but they are present for completeness and for symmetry with pointers: after all, you can say *string in C and get the first character of the string, just like you can say *string = 'f'.

Also for symmetry (but this is useful in fact) + anInteger returns a CString object pointing to integer bytes from the start of the string. - acts like + if it is given an integer as its parameter. If a pointer is given, it returns the difference between the two pointers.

incr, decr, incrBy:, decrBy: adjust the string either forward or backward, by either 1 or n characters. Only the pointer to the string is changed; the actual characters in the string remain untouched.

replaceWith: aString replaces the string the instance points to with the new string. Actually, it copies the bytes from the Smalltalk String instance aString into the C string object, and null terminates. Be sure that the C string has enough room! You can also use a Smalltalk ByteArray as the data source.

Instances of CArray represent an array of some C data. The underlying element type is provided by a CType subclass instance which is associated with the CPtr instance. They have at: and at:put: operations just like Strings. at: returns a Smalltalk datatype for the given element of the array (if the element type is a scalar, otherwise it returns a CObject subclass instance whose type is that of the element type); at:put: works similarly. addressAt: returns a CObject subclass instance no matter what, which you then can send value or or value: to get or set its value. CArray's also support deref, deref:, + and - with equivalent semantics to CString.

CPtrs are similar to CArrays (as you might expect given the similarity between pointers and arrays in C) and even more similar to CStrings (as you might again expect since strings are pointers in C). In fact both CPtrs and CArrays are subclasses of a common subclass, CAggregate. Just like CArrays, the underlying element type is provided by a CType subclass instance which is associated with the CPtr instance.

CPtr's also have value and value: which get or change the underlying value that's pointed to. Like CStrings, they have #incr, #decr, #incrBy: and #decrBy:. They also have #+ and #- which do what you'd expect.

Finally, there is CStruct, an abstract subclass of CObject (it makes sense, because its subclasses provide a way to access actual C data objects).

They provide direct access to C data structures including

Here is an example struct decl in C:

struct audio_prinfo {
    unsigned    channels;
    unsigned    precision;
    unsigned    encoding;
    unsigned    gain;
    unsigned    port;
    unsigned    _xxx[4];
    unsigned    samples;
    unsigned    eof;
    unsigned char       pause;
    unsigned char       error;
    unsigned char       waiting;
    unsigned char       _ccc[3];
    unsigned char       open;
    unsigned char       active;
};

struct audio_info {
    audio_prinfo_t      play;
    audio_prinfo_t      record;
    unsigned    monitor_gain;
    unsigned    _yyy[4];
};

And here is a Smalltalk equivalent decision:

CStruct newStruct: #AudioPrinfo
        declaration: #( (sampleRate uLong)
                        (channels uLong)
                        (precision uLong)
                        (encoding uLong)
                        (gain uLong)
                        (port uLong)
                        (xxx (array uLong 4))
                        (samples uLong)
                        (eof uLong)
                        (pause uChar)
                        (error uChar)
                        (waiting uChar)
                        (ccc (array uChar 3))
                        (open uChar)
                        (active uChar))
!

CStruct newStruct: #AudioInfo
        declaration: #( (play AudioPrinfo)
                        (record AudioPrinfo)
                        (monitorGain uLong)
                        (yyy (array uLong 4)))
!

This creates two new subclasses of CStruct called AudioPrinfo and AudioInfo, with the given fields. You can make C functions return CObjects pointing to these instances by passing AudioPrinfo type as the parameter to the returning: keyword.

AudioPrinfo has methods defined on it like:

    #sampleRate
    #sampleRate:
    #channels
    #channels:

etc. These access the various data members. The array element accessors (xxx, ccc) just return a pointer to the array itself.

For simple scalar types, just list the type name after the variable. Here's the set of scalars names, as defined in CStruct.st:

TypeMap at: #long put: #CLongType;
        at: #uLong put: #CULongType;
        at: #ulong put: #CULongType;
        at: #char put: #CCharType;
        at: #uChar put: #CUCharType;
        at: #uchar put: #CUCharType;
        at: #short put: #CShortType;
        at: #uShort put: #CUShortType;
        at: #ushort put: #CUShortType;
        at: #float put: #CFloatType;
        at: #double put: #CDoubleType;
        at: #string put: #CStringType.

To have a pointer to a type, use something like:

        (example (ptr long))

To have an array pointer of size <size, use:

        (example (array string <size>))

Note that this maps to char *example[<size>] in C.

The objects returned by using the fields are CObjects; there is no implicit value fetching currently. For example, suppose you somehow got ahold of an instance of class AudioPrinfo as described above (the instance is a CObject subclass and points to a real C structure somewhere). Let's say you stored this object in variable "audioInfo". To get the current gain value, do

    audioInfo gain value

to change the gain value in the structure, do

    audioInfo gain value: 255

The structure member message just answers a CObject instance, so you can hang onto it to directly refer to that structure member, or you can use the value or value: methods to access or change the value of the member.

Note that this is the same kind of access you get if you use the addressAt: method on CStrings or CArrays or CPtrs: they return a CObject which points to a C object of the right type and you need to use value and value: to access and modify the actual C variable.


[ Next: | Previous:C data types | Up:C and Smalltalk ]

Manipulating Smalltalk data from C

GNU Smalltalk internally maps every object except Integers to a data structure named an OOP (which is not an acronym for anything, as far as I know). An OOP is a pointer to an internal data structure; this data structure basically adds a level of indirection in the representation of objects, since it contains

This additional level of indirection makes garbage collection very efficient, since the collector is free to move an object in memory without updating every reference to that object in the heap, thereby keeping the heap fully compact and allowing very fast allocation of new objects. However, it makes C code that wants to deal with objects even more messy than it would be without; if you want some examples, look at the hairy code in GNU Smalltalk that deals with processes.

To shield you as much as possible from the complications of doing object-oriented programming in a non-object-oriented environment like C, GNU Smalltalk provides friendly functions to map between common Smalltalk objects and C types. This way you can simply declare OOP variables and then use these functions to treat their contents like C data.

These functions are declared in gstpub.h and can be divided in two groups, those that map from Smalltalk objects to C data types and those that map from C data types to Smalltalk objects.

Here are those in the former group (Smalltalk to C); you can see that they all begin with OOPTo:

extern long OOPToInt(OOP)
This function assumes that the passed OOP is an Integer and returns the C signed long for that integer.


extern double OOPToFloat(OOP)
This function assumes that the passed OOP is an Float and returns the C double for that integer.


extern int OOPToBool(OOP)
This function returns a C integer which is true (i.e. != 0) if the given OOP is the true object, false (i.e. == 0) otherwise.


extern char OOPToChar(OOP)
This function assumes that the passed OOP is a Character and returns the C char for that integer.


extern char *OOPToString(OOP)
This function assumes that the passed OOP is a String or ByteArray and returns a C null-terminated char * with the same contents. It is the caller's responsibility to free the pointer and to handle possible NUL characters inside the Smalltalk object.


extern voidPtr OOPToCObject(OOP)
This functions assumes that the passed OOP is a kind of CObject and returns a C voidPtr to the C data pointed to by the object. The caller should not free the pointer, nor assume anything about its size and contents, unless it exactly knows what it's doing. A voidPtr is a void * if supported, or otherwise a char *.


extern long OOPToC(OOP)
This functions assumes that the passed OOP is a String, a ByteArray, a CObject, or a built-in object (nil, true, false, character, integer). If the OOP is nil, it answers 0; else the mapping for each object is exactly the same as for the above functions. Note that, even though the function is declared as returning a long, you might need to cast it to either a char * or voidPtr.

While special care is needed to use the functions above (you will probably want to know at least the type of the Smalltalk object you're converting), the functions below, which convert C data to Smalltalk objects, are easier to use and also register objects for you so that they are not swept by a garbage collection. These functions all end with ToOOP, except cObjectToTypedOOP:

OOP intToOOP(long)
This object returns a Smalltalk Integer which contains the same value as the passed C long. Note that Smalltalk Integers are always signed and have a bit less of precision with respect to C longs. On 32 bit machines, their precision is 30 bits (if unsigned) or 31 bits (if signed); on 64 bit machines, their precision is 62 bits (if unsigned) or 63 bits (if signed).


OOP floatToOOP(double)
This object returns a Smalltalk Float which contains the same value as the passed double. Unlike Integers, Floats have exactly the same precision as C doubles.


OOP boolToOOP(int)
This object returns a Smalltalk Boolean which contains the same boolean value as the passed C int. That is, the returned OOP is the sole instance of either False or True, depending on where the parameter is zero or not.


OOP charToOOP(char)
This object returns a Smalltalk Character which represents the same char as the passed C char.


OOP classNameToOOP(char *)
This method returns the Smalltalk class (i.e. an instance of a subclass of Class) whose name is the given parameter. This method is slow; you can safely cache its result.


OOP stringToOOP(char *)
This method returns a String which maps to the given null-terminated C string, or the builtin object nil if the parameter points to address 0 (zero).


OOP symbolToOOP(char *)
This method returns a String which maps to the given null-terminated C string, or the builtin object nil if the parameter points to address 0 (zero). Note that symbols cannot be garbage collected (they are always in the root set), so they're not registered: calling unregisterOOP with a symbol as a parameter has no effect.


OOP cObjectToOOP(voidPtr)
This method returns a CObject which maps to the given C pointer, or the builtin object nil if the parameter points to address 0 (zero). The returned value has no precise CType assigned. To assign one, use cObjectToTypedOOP.


OOP cObjectToTypedOOP(voidPtr, OOP),
This method returns a CObject which maps to the given C pointer, or the builtin object nil if the parameter points to address 0 (zero). The returned value has the second parameter as its type; to get possible types you can use typeNameToOOP.


OOP typeNameToOOP(char *)
All this method actually does is evaluating its parameter as Smalltalk code; so you can, for example, use it in any of these ways:
    cIntType = typeNameToOOP("CIntType");
    myOwnCStructType = typeNameToOOP("MyOwnCStruct type");

This method is primarily used by msgSendf (see Smalltalk callin), but it can be useful if you use lower level call-in methods. This method is slow too; you can safely cache its result.

As said above, the C to Smalltalk layer automatically puts the objects it creates in a special registry (different from the incubator) which prevents objects from being collected as garbage. Here are the functions you may want to use to have more control on this registry:

void registerOOP(OOP)
Puts the given OOP in the registry. If you register an object multiple times, you will need to unregister it the same number of times. You may want to register objects returned by Smalltalk call-ins.


void unregisterOOP(OOP)
Remove an occurrence of the given OOP from the registry.

Usually, you should use the registry to protect the main object, and the incubator to protect objects which are part of the object before they become parts of the root set; this because the incubator is designed to unregister multiple objects at a time, while the registry works better for objects that should be kept registered for a relatively long time, and whose lives in the registry typically overlap.


[ Next: | Previous:Smalltalk types | Up:C and Smalltalk ]

Calls from C to Smalltalk

GNU Smalltalk provides seven different function calls that allow you to call Smalltalk methods in a different execution context than the current one. The priority in which the method will execute will be the same as the one of Smalltalk process which is currently active.

Four of these functions are more low level and are more suited when the Smalltalk program itself gave a receiver, a selector and maybe some parameters; the others, instead, are more versatile. One of them (msgSendf) automatically handles most conversions from C data types to Smalltalk objects, while the others takes care of compiling full snippets of Smalltalk code.

OOP msgSend (OOP receiver, OOP selector, ...)
This function sends the given selector (should be a Symbol, otherwise a Smalltalk exception is quite likely) to the given receiver. The message arguments should also be OOPs (otherwise, an access violation exception is even more likely) and are passed in a NULL-terminated list after the selector. The value returned from the method is passed back to the C program as the result of msgSend. Example (same as 1 + 2):
    OOP shouldBeThreeOOP = msgSend(
        intToOOP(1),
        symbolToOOP("+"),
        intToOOP(2),
        nil);

OOP strMsgSend (OOP receiver, char *selector, ...)
This function is the same as above, but the selector is passed as a C string and is automatically converted to a Smalltalk symbol.

Theoretically, this function is a bit slower than msgSend if your program has some way to cache the selector and avoiding a call to symbolToOOP on every call-in. However, this is not so apparent in "real" code because the time spent in the Smalltalk interpreter will usually be much higher than the time spent converting the selector to a Symbol object. Example:

    OOP shouldBeThreeOOP = strMsgSend(
        intToOOP(1),
        "+",
        intToOOP(2),
        nil);

OOP vmsgSend (OOP receiver, OOP selector, OOP *args)
This function is the same as msgSend, but accepts a pointer to the NULL-terminated list of arguments, instead of being a variable-arguments functions. Example:
    OOP arguments[2], shouldBeThreeOOP;
    arguments[0] = intToOOP(2);
    arguments[1] = nil;
    /* ... some more code here ... */

    shouldBeThreeOOP = vmsgSend(
        intToOOP(1),
        symbolToOOP("+"),
        arguments);

OOP nvmsgSend (OOP receiver, OOP selector, OOP *args, int nargs)
This function is the same as msgSend, but accepts an additional parameter containing the number of arguments to be passed to the Smalltalk method, instead of relying on the NULL-termination of args. Example:
    OOP argument, shouldBeThreeOOP;
    argument = intToOOP(2);
    /* ... some more code here ... */

    shouldBeThreeOOP = nvmsgSend(
        intToOOP(1),
        symbolToOOP("+"),
        &argument,
        1);

The two functions that directly accept Smalltalk code are named evalCode and evalExpr, and they're basically the same. They both accept a single parameter, a pointer to the code to be submitted to the parser. The main difference is that evalCode discards the result, while evalExpr returns it to the caller as an OOP.

msgSendf, instead, has a radically different syntax. Let's first look at some examples.

    /* 1 + 2 */
    int shouldBeThree;
    msgSend(&shouldBeThree, "%i %i + %i", 1, 2)

    /* aCollection includes: 'abc' */
    OOP aCollection;
    int aBoolean;
    msgSend(&aBoolean, "%b %o includes: %s", aCollection, "abc")

    /* 'This is a test' printNl -- in two different ways */
    msgSendf(nil, "%v %s printNl", "This is a test");
    msgSendf(nil, "%s %s printNl", "This is a test");

    /* 'This is a test', ' ok?' */
    char *str;
    msgSendf(&str, "%s %s , %s", "This is a test", " ok?");

As you can see, the parameters to msgSendf are, in order:

Note that the receiver and parameters are NOT registered in the object registry (see Smalltalk types). receiver_type and paramX_type can be any of these characters, with these meanings:

      Specifier        C data type        equivalent Smalltalk class
          i                long           Integer (see intToOOP)
          f               double          Float (see floatToOOP)
          b                int            True or False (see boolToOOP)
          c                char           Character (see charToOOP)
          C               voidPtr         CObject (see cObjToOOP)
          s               char *          String (see stringToOOP)
          S               char *          Symbol (see symbolToOOP)
          o                OOP            any
          t            char *, voidPtr    CObject (see below)
          T              OOP, voidPtr     CObject (see below)

%t and %T are particular in the sense that you need to pass two additional arguments to msgSendf, not one. The first will be a description of the type of the CObject to be created, the second instead will be the CObject's address. If you specify %t, the first of the two arguments will be converted to a Smalltalk CType via typeNameToOOP (see Smalltalk types); instead, if you specify %T, you will have to directly pass an OOP for the new CObject's type.

The type specifiers you can pass for return_type are a bit different:

      Specifier        C data type        expected class of the result
          i                long           Integer (see OOPToInt)
          f               double          Float (see OOPToFloat)
          b                int            True or False (see OOPToBool)
          c                char           Character (see OOPToChar)
          C               voidPtr         CObject (see OOPToCObj)
          s               char *          String/Symbol (see OOPToString)
          o                OOP            any
          ?            char *, voidPtr    See oopToC
          v                 /             Discard the result.

Note that, if resultPtr is nil, the return_type is always treated as %v.


[ Next: | Previous:Smalltalk callin | Up:C and Smalltalk ]

Other functions in libgst.a

In addition to the functions above, gstpub.h exports many other functions and macros that aid in developing GNU Smalltalk extensions in C. This node documents these functions.

You should always assume that they are implemented as macros, and thus only pass arguments without side effects.

void asyncSignal(OOP)
This functions accepts an OOP for a Semaphore object and signals that object so that one of the processes waiting on that semaphore is waken up. Since a Smalltalk call-in is not an atomic operation, the correct way to signal a semaphore is not to send the signal method to the object but, rather, to use:
    asyncSignal(semaphoreOOP)

The signal request will be processed as soon as the next bytecode is executed.


OOP objectAlloc(OOP)
OOP objectAlloc(OOP, int)
The objectAlloc function allocates an OOP for a newly created instance of the class whose OOP is passed as the first parameter; if that parameter is not a class the results are undefined (for now, read as "the program will most likely core dump", but that could change in a future version).

The second parameter is used only if the class is an indexable one, otherwise it is discarded; the same warning above holds if you don't pass the second argument but the class is indexable. Simple uses of objectAlloc include:

     OOP myClassOOP;
     OOP myNewObject;
     myNewObjectData obj;
     ...
     myNewObject = objectAlloc(myClassOOP);
     incAddOOP(myNewObject);
     obj = (myNewObjectData) oopToObj(myNewObject);
     obj->arguments = objectAlloc(classNameToOOP("Array"), 10);
     incAddOOP(obj->arguments);
     ...

mst_Object oopToObj(OOP)
Dereference a pointer to an OOP into a pointer to the actual object data (see Object representation). The result of oopToObj is not valid anymore if a garbage-collection happens; for this reason, you should assume that a pointer to object data is not valid after doing a call-in, calling objectAlloc, and caling any of the "C to Smalltalk" functions (see Smalltalk types).


mst_Boolean oopIsReadOnly(OOP)
Answer whether or not the given OOP is read-only (see Special objects). Note that being read-only only limits access to indexed instance variables from Smalltalk code. Fixed instance variables, usage of instVarAt:put: and C accesses cannot be write-protected.


makeOOPReadOnly(OOP, mst_Boolean)
Set whether or not the given OOP is read-only.


markOOPToFinalize(OOP, mst_Boolean)
Set whether or not the given OOP is a `finalizable' oop. (see Special objects).


makeOOPWeak(OOP, mst_Boolean)
Set whether or not the given OOP is a `weak' oop (see Special objects).


OOP oopClass(OOP)
Return the OOP for the class of the given object. For example, oopClass(stringToOOP("Wonderful GNU Smalltalk")) is the String class, as returned by classNameToOOP("String").


mst_Boolean isClass(OOP, OOP)
Return whether the class of the OOP passed as the first parameter is the OOP passed as the second parameter.
mst_Boolean isInt(OOP)
Return a Boolean indicating whether or not the OOP is an Integer object; the value of Integer objects is encoded directly in the OOP, not separately in a mst_Object structure. It is not safe to use oopToObj and oopClass if isInt returns false.


mst_Boolean isOOP(OOP)
Return a Boolean indicating whether or not the OOP is a `real' object (and not an Integer). It is safe to use oopToObj and oopClass only if isOOP returns true.


mst_Boolean isNil(OOP)
Return a Boolean indicating whether or not the OOP points to nil, the undefined object.


mst_Boolean arrayOOPAt(mst_Object, int)
Access the character given in the second parameter of the given Array object. Note that this is necessary because of the way mst_Object is defined, which prevents indexedOOP from working.


mst_Boolean stringOOPAt(mst_Object, int)
Access the character given in the second parameter of the given String or ByteArray object. Note that this is necessary because of the way mst_Object is defined, which prevents indexedByte from working.


mst_Boolean indexedWord(<some object type>, int)
Access the given indexed instance variable in a variableWordSubclass. The first parameter must be a structure declared as described in Object representation).


mst_Boolean indexedByte(<some object type>, int)
Access the given indexed instance variable in a variableByteSubclass. The first parameter must be a structure declared as described in Object representation).


mst_Boolean indexedOOP(<some object type>, int)
Access the given indexed instance variable in a variableSubclass. The first parameter must be a structure declared as described in Object representation).


[ Next: | Previous:Other C functions | Up:C and Smalltalk ]

Manipulating instances of your own Smalltalk classes from C

Although GNU Smalltalk's library exposes functions to deal with instances of the most common base class, it's likely that, sooner or later, you'll want your C code to directly deal with instances of classes defined by your program. There are three steps in doing so:

In this chapter you will be taken through these steps considering the hypotetical task of defining a Smalltalk interface to an SQL server.

The first part is also the simplest, since defining the Smalltalk class can be done in a single way which is also easy and very practical; just evaluate the standard Smalltalk code that does that:

    Object subclass: #SQLAction
	   instanceVariableNames: 'database request'
	   classVariableNames: ''
	   poolDictionaries: ''
	   category: 'SQL-C interface'

    SQLAction subclass: #SQLRequest
	   instanceVariableNames: 'returnedRows'
	   classVariableNames: ''
	   poolDictionaries: ''
	   category: 'SQL-C interface'

To define the C struct for a class derived from Object, GNU Smalltalk's gstpub.h include file defines an OBJ_HEADER macro which defines the fields that constitute the header of every object. Defining a struct for SQLAction results then in the following code:

    struct st_SQLAction {
        OBJ_HEADER;
        OOP database;
        OOP request;
    }

The representation of SQLRequest in memory is this:

    .------------------------------.
    |     common object header     |	2 longs
    |------------------------------|
    | SQLAction instance variables |
    |           database           |	2 longs
    |           request            |
    |------------------------------|
    | SQLRequest instance variable |
    |         returnedRows         |    1 long
    '------------------------------'

A first way to define the struct would then be:

    typedef struct st_SQLAction {
        OBJ_HEADER;
        OOP database;
        OOP request;
        OOP returnedRows;
    } *SQLAction;

but this results in a lot of duplicated code. Think of what would happen if you had other subclasses of SQLAction such as SQLObjectCreation, SQLUpdateQuery, and so on! The solution, which is also the one used in GNU Smalltalk's source code is to define a macro for each superclass, in this way:

    /* SQLAction
        |-- SQLRequest
        |     `-- SQLUpdateQuery
        `-- SQLObjectCreation       */

    #define ST_SQLACTION_HEADER		\
        OBJ_HEADER;			\
        OOP database;			\
        OOP request			/* no semicolon */

    #define ST_SQLREQUEST_HEADER	\
        ST_SQLACTION_HEADER;		\
        OOP returnedRows		/* no semicolon */

    typedef struct st_SQLAction {
        ST_SQLACTION_HEADER;
    } *SQLAction;

    typedef struct st_SQLRequest {
        ST_SQLREQUEST_HEADER;
    } *SQLRequest;

    typedef struct st_SQLObjectCreation {
        ST_SQLACTION_HEADER;
        OOP newDBObject;
    } *SQLObjectCreation;

    typedef struct st_SQLUpdateQuery {
        ST_SQLREQUEST_HEADER;
        OOP numUpdatedRows;
    } *SQLUpdateQuery;

Note that the macro you declare is used instead of OBJ_HEADER in the declaration of both the superclass and the subclasses.

Although this example does not show that, please note that you should not declare anything if the class has indexed instance variables.

The first step in actually using your structs is obtaining a pointer to an OOP which is an instance of your class. Ways to do so include doing a call-in, receiving the object from a call-out (using #smalltalk, #unknown or #self as the type specifier).

Let's assume that the oop variable contains such an object. Then, you have to dereference the OOP (which, as you might recall from Smalltalk types, point to the actual object only indirectly) and get a pointer to the actual data. You do that with the oopToObj macro (note the type casting):

    SQLAction action = (SQLAction) oopToObj(oop);

Now you can use the fields in the object like in this pseudo-code:

    /* These are retrieved via classNameToOOP and then cached in global
       variables */
    OOP sqlUpdateQueryClass, sqlActionClass, sqlObjectCreationClass;
    ...
    invokeSQLQuery(
        oopToCObject(action->database),
        oopToString(action->request);
        sqlQueryCompletedCallback,	/* Callback function */
        oop);				/* Passed to the callback */

    ...
    /* Imagine that invokeSQLQuery runs asynchronously and calls this
       when the job is done. */
    void
    sqlQueryCompletedCallback(result, database, request, clientData)
    QueryResult *result;
    DB *database;
    char *request;
    OOP clientData;
    {
        SQLUpdateQuery query;
        OOP rows;
        OOP cObject;

        /* Free the memory allocated by oopToString */
        free(request);

        if (isClass(oop, sqlActionClass))
            return;

        if (isClass(oop, sqlObjectCreationClass)) {
            SQLObjectCreation oc;
            oc = (SQLObjectCreation) oopToObj(clientData);
            cObject = cObjectToOOP(result->dbObject)
            oc->newDBObject = cObject;
        } else {
            /* SQLRequest or SQLUpdateQuery */
            cObject = cObjectToOOP(result->rows);
            query = (SQLUpdateQuery) oopToObj(clientData);
            query->returnedRows = cObject;
            if (isClass(oop, sqlUpdateQueryClass)) {
                query->numReturnedRows = intToOOP(result->count);   <<<
            }
        }
        unregisterOOP(cObject);		/* no need to force it alive */
    }

Note that the result of oopToObj is not valid anymore if a garbage-collection happens; for this reason, you should assume that a pointer to object data is not valid after doing a call-in, calling objectAlloc, and using any of the "C to Smalltalk" functions except intToOOP (see Smalltalk types). That's why I passed the OOP to the callback, not the object pointer itself.

Note that in the line marked <<< I did not have to reload the query variable because I used intToOOP. If I used any other function, I would have had to create all the required objects (using, if needed, the incubator described in Incubator), dereference the pointer, and store the data in the object.

Also, you should remember to unregister every object created with the "C to Smalltalk" fnctions (again, with the exception of intToOOP).

If your class has indexed instance variables, you can use the indexedWord, indexedOOP and indexedByte macros declared in gstpub.h, which return an lvalue for the given indexed instance variable--for more information, see Other C functions.


[ Next: | Previous:Object representation | Up:C and Smalltalk ]

Incubator support

The incubator concept provides a mechanism to protect newly created objects from being accidentally garbage collected before they can be attached to some object which is reachable from the root set.

If you are creating some set of objects which will not be immediately (that means, before the next object is allocated from the Smalltalk memory system) be attached to an object which is still "live" (reachable from the root set of objects), you'll need to use this interface.

The interface provides the following operations:

void incAddOOP(OOP anOOP)
Adds a new object to the protected set.


IncPtr incSavePointer()
Retrieves the current incubator pointer. Think of the incubator as a stack, and this operation returns the current stack pointer for later use (restoration) with the incRestorePointer function.


void incRestorePointer(IncPtr ptr)
Sets (restores) the incubator pointer to the given pointer value.

Typically, when you are within a function which allocates more than one object at a time, either directly or indirectly, you'd want to use the incubator mechanism. First you'd save a copy of the current pointer in a local variable. Then, for each object you allocate (except the last, if you want to be optimal), after you create the object you add it to the incubator's list. When you return, you need to restore the incubator's pointer to the value you got with incSavePointer using the incRestorePointer function.

Here's an example from cint.c:

The old code was (the comments are added for this example):

  desc = (CFuncDescriptor)newInstanceWith(cFuncDescriptorClass, numArgs);
  desc->cFunction = cObjectNew(funcAddr);    // 1
  desc->cFunctionName = stringNew(funcName); // 2
  desc->numFixedArgs = fromInt(numArgs);
  desc->returnType = classifyTypeSymbol(returnTypeOOP, true);
  for (i = 1; i <= numArgs; i++) {
    desc->argTypes[i - 1] = classifyTypeSymbol(arrayAt(argsOOP, i), false);
  }

  return (allocOOP(desc));

desc is originally allocated via newInstanceWith and allocOOP, two private routines which are encapsulated by the public routine objectAlloc. At "1", more storage is allocated, and the garbage collector has the potential to run and free (since no live object is referring to it) desc's storage. At "2" another object is allocated, and again the potential for losing both desc and desc->cFunction is there if the GC runs (this actually happened!).

To fix this code to use the incubator, modify it like this:

  OOP     descOOP;
  IncPtr  ptr;

  incPtr = incSavePointer();
  desc = (CFuncDescriptor)newInstanceWith(cFuncDescriptorClass, numArgs);
  descOOP = allocOOP(desc);
  incAddOOP(descOOP);

  desc->cFunction = cObjectNew(funcAddr);
  incAddOOP(desc->cFunction);

  desc->cFunctionName = stringNew(funcName);
  /* since none of the rest of the function (or the functions it calls)
   * allocates any storage, we don't have to add desc->cFunctionName
   * to the incubator's set of objects, although we could if we wanted
   * to be completely safe against changes to the implementations of
   * the functions called from this function.
   */

  desc->numFixedArgs = fromInt(numArgs);
  desc->returnType = classifyTypeSymbol(returnTypeOOP, true);
  for (i = 1; i <= numArgs; i++) {
    desc->argTypes[i - 1] = classifyTypeSymbol(arrayAt(argsOOP, i), false);
  }

  incRestorePointer(ptr);
  return (descOOP);

Note that it is permissible for a couple of functions to cooperate with their use of the incubator. For example, say function A allocates some objects, then calls function B which allocates some more objects, and then control returns to A where it does some more execution with the allocated objects. If B is only called by A, B can leave the management of the incubator pointer up to A, and just register the objects it allocates with the incubator. When A does a incRestorePointer, it automatically clears out the objects that B has registered from the incubator's set of objects as well; the incubator doesn't know about functions A & B, so as far as it is concerned, all of the registered objects were registered from the same function.


[ Previous:Incubator | Up:C and Smalltalk ]

Using the Smalltalk environment as an extension library

If you are reading this chapter because you are going to write extensions to GNU Smalltalk, this section won't probably interest you. But if you intend to use GNU Smalltalk as a scripting language or an extension language for your future marvellous software projects, you might be interest.

How to initialize GNU Smalltalk is most briefly and easily explained by looking at GNU Smalltalk's own source code. For this reason, here are two snippets from main.c and lib/lib.c.

/* From main.c */
int main(argc, argv)
int     argc;
char    **argv;
{
  smalltalkArgs(argc, argv);
  initSmalltalk();
  topLevelLoop();

  exit(0);
}

/* From cint.c */
void initUserCFuncs()
{
}

void initCFuncs()
{
  /* Access to command line args */
  defineCFunc("getArgc", getArgc);
  defineCFunc("getArgv", getArgv);

  /* Test functions */
  defineCFunc("testCallin", testCallin);
  defineCFunc("testCString", testCString);
  defineCFunc("testCStringArray", testCStringArray);

  /* ... */

  /* Initialize any user C function definitions. initUserCFuncs,
     defined in cfuncs.c, is overridden by explicit definition
     before linking with the Smalltalk library. */
  initUserCFuncs();
}

/* From the automatically generated cfuncs.c, after preprocessing */
void
initUserCFuncs()
{
  initBlox();
  initTCP();
}

Your initialization code will be almost the same as that in GNU Smalltalk's main(), with the exception of the code to topLevelLoop. All you'll have to do is to pass some arguments to the GNU Smalltalk library via smalltalkArgs, and then call initSmalltalk.

Note that initSmalltalk will likely take some time (from a second to 30-40 seconds), because it has to check if the image file must be be rebuilt and, if so, it reloads and recompiles the 27000 lines of Smalltalk code in a basic image. To avoid this check, pass to GNU Smalltalk a -I flag:

char myArgv[][] = { "-I", "myprog.im", nil };
int myArgc;
/* ... */
myArgc = sizeof(myArgv) / sizeof (char *) - 1;
smalltalkArgs(myArgc, myArgv);

If you're using GNU Smalltalk as an extension library, you might also want to disable the Smalltalk dictionary's quitPrimitive and quitPrimitive: method. I advice you not to change the Smalltalk kernel code. Instead, in the script that loads your extension classes add these two lines:

Smalltalk class compile: 'quitPrimitive        self shouldNotImplement'!
Smalltalk class compile: 'quitPrimitive: n     self shouldNotImplement'!

which will effectively disable the two offending methods. Other possibilities include using atexit (from the C library) to exit your program in a less traumatic way, or redefining these two methods to exit through a call out to a C routine in your program.

Another important thing is the initUserCFuncs, which as you can see for the source code above is an hook from which anybody can declare his/her own C call-outs. The default implementation of initUserCFuncs, as the library exports it, does nothing, but you can redefine it to place your calls to defineCFunc there.

Also, note that it is not a problem if you develop the class libraries for your programs within GNU Smalltalk's environment without defineCFunc-ing your own C call-outs, since GNU Smalltalk recalculates the addresses of the C call-outs every time it is started.


[ Next: | Previous:C and Smalltalk | Up:Top ]

Tutorial


What this manual presents
This document provides a tutorial introduction to the Smalltalk language in general, and the GNU Smalltalk implementation in particular. It does not provide exhaustive coverage of every feature of the language and its libraries; instead, it attempts to introduce a critical mass of ideas and techniques to get the Smalltalk novice moving in the right direction.


Who this manual is written for
This manual assumes that the reader is acquainted with the basics of computer science, and has reasonable proficiency with a procedural language such as C. It also assumes that the reader is already familiar with the usual janitorial tasks associated with programming: editing, moving files, and so forth.


[ Next: | Previous:Tutorial | Up:Tutorial ]

Getting started


[ Next: | Previous:Getting started | Up:Getting started ]

Starting up Smalltalk

Assuming that GNU Smalltalk has been installed on your system, starting it is as simple as:

     $ gst
the system loads in Smalltalk, and displays a startup banner like:
     Smalltalk Ready

     st>

You are now ready to try your hand at Smalltalk! By the way, when you're ready to quit, you exit Smalltalk by typing control-D on an empty line.


[ Next: | Previous:Starting Smalltalk | Up:Getting started ]

Saying hello

An initial exercise is to make Smalltalk say "hello" to you. Type in the following line (printNl is a upper case N and a lower case L):

     'Hello, world' printNl !
The system then prints back 'Hello, world' to you.1


[ Next: | Previous:Saying hello | Up:Getting started ]

What actually happened

The front-line Smalltalk interpreter gathers all text until a '!' character and executes it. So the actual Smalltalk code executed was:

     'Hello, world' printNl

This code does two things. First, it creates an object of type String which contains the characters "Hello, world". Second, it sends the message named printNl to the object. When the object is done processing the message, the code is done and we get our prompt back. You'll notice that we didn't say anything about printing ing the string, even though that's in fact what happened. This was very much on purpose: the code we typed in doesn't know anything about printing strings. It knew how to get a string object, and it knew how to send a message to that object. That's the end of the story for the code we wrote.

But for fun, let's take a look at what happened when the string object received the printNl message. The string object then went to a table 2 which lists the messages which strings can receive, and what code to execute. It found that there is indeed an entry for printNl in that table and ran this code. This code then walked through its characters, printing each of them out to the terminal. 3

The central point is that an object is entirely self-contained; only the object knew how to print itself out. When we want an object to print out, we ask the object itself to do the printing.


[ Next: | Previous:What happened | Up:Getting started ]

Doing math

A similar piece of code prints numbers:

    1234 printNl !

Notice how we used the same message, but have sent it to a new type of object-an integer (from class Integer). The way in which an integer is printed is much different from the way a string is printed on the inside, but because we are just sending a message, we do not have to be aware of this. We tell it to printNl, and it prints itself out.

As a user of an object, we can thus usually send a particular message and expect basically the same kind of behavior, regardless of object's internal structure (for instance, we have seen that sending printNl to an object makes the object print itself). In later chapters we will see a wide range of types of objects. Yet all of them can be printed out the same way-with "printNl".

White space is ignored, except as it separates words. This example could also have looked like:

                1234
     printNl         !

An integer can be sent a number of messages in addition to just printing itself. An important set of messages for integers are the ones which do math:

     (9 + 7) printNl !

Answers (correctly!) the value 16. The way that it does this, however, is a significant departure from a procedural language.


[ Previous:Doing math | Up:Getting started ]

Math in Smalltalk

In this case, what happened was that the object 9 (an Integer), received a + message with an argument of 7 (also an Integer). The + message for integers then caused Smalltalk to create a new object 16 and return it as the resultant object. This 16 object was then given the printNl message, and printed 16 on the terminal.

Thus, math is not a special case in Smalltalk; it is done, exactly like everything else, by creating objects, and sending them messages. This may seem odd to the Smalltalk novice, but this regularity turns out to be quite a boon: once you've mastered just a few paradigms, all of the language "falls into place." Before you go on to the next chapter, make sure you try math involving * (multiplication), - (subtraction), and / (division) also. These examples should get you started:

     (8 * (4 / 2)) printNl !
     (8 - (4 + 1)) printNl !
     (5 + 4) printNl !
     (2/3 + 7) printNl !
     (2 + 3 * 4) printNl !
     (2 + (3 * 4)) printNl !


[ Next: | Previous:Getting started | Up:Tutorial ]

Using some of the Smalltalk classes

This chapter has examples which need a place to hold the objects they create. The following line creates such a place; for now, treat it as magic. At the end of the chapter we will revisit it with an explanation. Type in:

     Smalltalk at: #x put: 0 !

Now let's create some new objects.


[ Next: | Previous:Some classes | Up:Some classes ]

An array in Smalltalk

An array in Smalltalk is similar to an array in any other language, although the syntax may seem peculiar at first. To create an array with room for 20 elements, do:

     x := Array new: 20 !

The Array new: 20 creates the array; the x := part connects the name x with the object. Until you assign something else to x, you can refer to this array by the name x. Changing elements of the array is not done using the := operator; this operator is used only to bind names to objects. In fact, you never modify data structures; instead, you send a message to the object, and it will modify itself.

For instance:

     (x at: 1) printNl !

which prints:

     nil

The slots of an array are initially set to "nothing" (which Smalltalk calls nil). Let's set the first slot to the number 99:

     x at: 1 put: 99 !

and now make sure the 99 is actually there:

     (x at: 1) printNl !

which then prints out:

     99

These examples show how to manipulate an array. They also show the standard way in which messages are passed arguments ments. In most cases, if a message takes an argument, its name will end with ":".4

So when we said x at: 1 we were sending a message to whatever object was currently bound to x with an argument of 1. For an array, this results in the first slot of the array being returned.

The second operation, x at: 1 put: 99 is a message with two arguments. It tells the array to place the second argument (99) in the slot specified by the first (1). Thus, when we re-examine the first slot, it does indeed now contain 99.

There is a shorthand for describing the messages you send to objects. You just run the message names together. So we would say that our array accepts both the at: and at:put: messages.

There is quite a bit of sanity checking built into an array. The request

     6 at: 1

fails with an error; 6 is an integer, and can't be indexed. Further,

     x at: 21

fails with an error, because the array we created only has room for 20 objects.

Finally, note that the object stored in an array is just like any other object, so we can do things like:

     ((x at: 1) + 1) printNl !

which (assuming you've been typing in the examples) will print 100.


[ Next: | Previous:Arrays | Up:Some classes ]

A set in Smalltalk

We're done with the array we've been using, so we'll assign something new to our x variable. Note that we don't need to do anything special about the old array: the fact that nobody is using it any more will be automatically detected, and the memory reclaimed. This is known as garbage collection and it is generally done when Smalltalk finds that it is running low on memory. So, to get our new object, simply do:

     x := Set new !

which creates an empty set. To view its contents, do:

     x printNl !

The kind of object is printed out (i.e., Set), and then the members are listed within parenthesis. Since it's empty, we see:

     Set ()

Now let's toss some stuff into it. We'll add the numbers 5 and 7, plus the string 'foo'. We could type:

     x add: 5 !
     x add: 7 !
     x add: 'foo' !

But let's save a little typing by using a Smalltalk shorthand:

     x add: 5; add: 7; add: 'foo' !

This line does exactly what the previous example's three lines did. The trick is that the semicolon operator causes the message to be sent to the same object as the last message sent. So saying ; add: 7 is the same as saying x add: 7, because x was the last thing a message was sent to. This may not seem like such a big savings, but compare the ease when your variable is named aVeryLongVariableName instead of just x! We'll revisit some other occasions where ; saves you trouble, but for now let's continue with our set. Type either version of the example, and make sure that we've added 5, 7, and "foo":

     x printNl !

we'll see that it now contains our data:

     Set (5 'foo' 7)

What if we add something twice? No problem-it just stays in the set. So a set is like a big checklist-either it's in there, or it isn't. To wit:

     x add:5; add: 5; add: 5; add: 5 !
     x printNl !

We've added 5 several times, but when we printed our set back out, we just see:

     Set (5 'foo' 7)

What you put into a set with "add:", you can take out with "remove:". Try:

     x remove: 5 !
     x printNl !

The set now prints as:

     Set ('foo' 7)

The "5" is indeed gone from the set.

We'll finish up with one more of the many things you can do with a set- checking for membership. Try:

     (x includes: 7) printNl !
     (x includes: 5) printNl !

From which we see that x does indeed contain 7, but not 5. Notice that the answer is printed as true or false. Once again, the thing returned is an object-in this case, an object known as a boolean. We'll look at the use of booleans later, but for now we'll just say that booleans are nothing more than objects which can only either be true or false-nothing else. So they're very useful for answers to yes or no questions, like the ones we just posed. Let's take a look at just one more kind of data structure:


[ Next: | Previous:Sets | Up:Some classes ]

Dictionaries

A dictionary is a special kind of collection. With a regular array, you must index it with integers. With dictionaries, you can index it with any object at all. Dictionaries thus provide a very powerful way of correlating one piece of information to another. Their only downside is that they are somewhat less efficient than simple arrays. Try the following:

     x := Dictionary new.
     x at: 'One' put: 1 !
     x at: 'Two' put: 2 !
     x at: 1 put: 'One' !
     x at: 2 put: 'Two' !

This fills our dictionary in with some data. The data is actually stored in pairs of key and value (the key is what you give to at:-it specifies a slot; the value is what is actually stored at that slot). Notice how we were able to specify not only integers but also strings as both the key and the value. In fact, we can use any kind of object we want as either-the dictionary doesn't care.

Now we can map each key to a value:

     (x at: 1) printNl !
     (x at: 'Two') printNl !

which prints respectively:

     'One'
     2

We can also ask a dictionary to print itself:

     x printNl !

which prints:

     Dictionary (1->'One' 2->'Two' 'One'->1 'Two'->2 )

where the first member of each pair is the key, and the second the value.


[ Next: | Previous:Dictionaries | Up:Some classes ]

Smalltalk dictionary

If you'll remember from the beginning of the chapter, we started out by saying:

     Smalltalk at: #x put: 0 !

This code should look familiar-the at:put: message is how we've been storing information in our own arrays and dictionaries. In a Smalltalk environment the name "Smalltalk" has been preset to point to a dictionary 5 which both you and Smalltalk can use. To see how this sharing works, we'll first try to use a variable which Smalltalk doesn't know about:

     y := 0 !

Smalltalk complains because y is an unknown variable. Using our knowledge of dictionaries, and taking advantage of our access to Smalltalk's dictionary, we can add it ourselves:

     Smalltalk at: #y put: 0 !

The only mystery left is why we're using #y instead of our usual quoted string. This is one of those simple questions whose answer runs surprisingly deep. The quick answer is that #y and 'y' are pretty much the same, except that the former will always be the same object each time you use it, whereas the latter can be a new string each time you do so. 6

Now that we've added "y" to Smalltalk's dictionary, we try again:

     y := 1 !
It works! Because you've added an entry for y, Smalltalk is now perfectly happy to let you use this new variable. If you have some spare time, you can print out the entire Smalltalk dictionary with:
     Smalltalk printNl !

As you might suspect, this will print out quite a large list of names! If you get tired of watching Smalltalk grind it out, use your interrupt key (control-C, usually) to bring Smalltalk back to interactive mode.


[ Previous:Smalltalk dictionary | Up:Some classes ]

Closing thoughts

You've seen how Smalltalk provides you with some very powerful data structures. You've also seen how Smalltalk itself uses these same facilities to implement the language. But this is only the tip of the iceberg-Smalltalk is much more than a collection of "neat" facilities to use. The objects and methods which are automatically available are only the beginning of the foundation on which you build your programs-Smalltalk allows you to add your own objects and methods into the system, and then use them along with everything else. The art of programming in Smalltalk is the art of looking at your problems in terms of objects, using the existing object types to good effect, and enhancing Smalltalk with new types of objects. Now that you've been exposed to the basics of Smalltalk manipulation, we can begin to look at this object-oriented technique of programming.


[ Next: | Previous:Some classes | Up:Tutorial ]

The Smalltalk class hierarchy

When programming in Smalltalk, you sometimes need to create new kinds of objects, and define what various messages will do to these objects. In the next chapter we will create some new classes, but first we need to understand how Smalltalk organizes the types and objects it contains. Because this is a pure "concept" chapter, without any actual Smalltalk code to run, we will keep it short and to the point.


[ Next: | Previous:The hierarchy | Up:The hierarchy ]

Class Object

Smalltalk organizes all of its classes as a tree hierarchy. At the very top of this hierarchy is class Object. Following somewhere below it are more specific classes, such as the ones we've worked with-strings, integers, arrays, and so forth. They are grouped together based on their similarities ities; for instance, types of objects which may be compared as greater or less than each other fall under a class known as Magnitude.

One of the first tasks when creating a new object is to figure out where within this hierarchy your object falls. Coming up with an answer to this problem is at least as much art as science, and there are no hard-and-fast rules to nail it down. We'll take a look at three kinds of objects to give you a feel for how this organization matters.


[ Next: | Previous:Class Object | Up:The hierarchy ]

Animals

Imagine that we have three kinds of objects, representing Animals, Parrots, and Pigs. Our messages will be eat, sing, and snort. Our first pass at inserting these objects into the Smalltalk hierarchy would organize them like:

     Object
         Animals
         Parrots
         Pigs

This means that Animals, Parrots, and Pigs are all direct descendants of Object, and are not descendants of each other.

Now we must define how each animal responds to each kind of message.

         Animals
             eat--Say "I have now eaten"
             sing--Error
             snort--Error
         Parrots
             eat--Say "I have now eaten"
             sing--Say "Tweet"
             snort--Error
         Pigs
             eat--Say "I have now eaten"
             sing--Error
             snort--Say "Oink"

Notice how we kept having to indicate an action for eat. An experienced object designer would immediately recognize this as a clue that we haven't set up our hierarchy correctly. Let's try a different organization:

         Animals
             Parrots
                    Pigs

That is, Parrots inherit from Animals, and Pigs from Parrots. Now Parrots inherit all of the actions from Animals, and Pigs from both Parrots and Animals. Because of this inheritance, we may now define a new set of actions which spares us the redundancy of the previous set:

         Animals
             eat--Say "I have now eaten"
             sing--Error
             snort--Error
         Parrots
             sing--Say "Tweet"
         Pigs
             snort--Say "Oink"

Because Parrots and Pigs both inherit from Animals, we have only had to define the eat action once. However, we have made one mistake in our class setup-what happens when we tell a Pig to sing? It says "Tweet", because we have put Pigs as an inheritor of Parrots. Let's try one final organization:

         Animals
             Parrots
             Pigs

Now Parrots and Pigs inherit from Animals, but not from each other. Let's also define one final pithy set of actions:

         Animals
             eat--Say "I have eaten"
         Parrots
             sing--Say "Tweet"
         Pigs
             snort--Say "Oink"

The change is just to leave out messages which are inappropriate. If Smalltalk detects that a message is not known by an object or any of its ancestors, it will automatically give an error-so you don't have to do this sort of thing yourself. Notice that now sending sing to a Pig does indeed not say "Tweet"-it will cause a Smalltalk error instead.


[ Previous:Animals | Up:The hierarchy ]

The bottom line of the class hierarchy

The goal of the class hierarchy is to allow you to organize objects into a relationship which allows a particular object to inherit the code of its ancestors. Once you have identified an effective organization of types, you should find that a particular technique need only be implemented once, then inherited by the children below. This keeps your code smaller, and allows you to fix a bug in a particular algorithm in only once place-then have all users of it just inherit the fix.

You will find your decisions for adding objects change as you gain experience. As you become more familiar with the existing set of objects and messages, your selections will increasingly "fit in" with the existing ones. But even a Smalltalk pro stops and thinks carefully at this stage, so don't be daunted if your first choices seem difficult and error-prone.


[ Next: | Previous:The hierarchy | Up:Tutorial ]

Creating a new class of objects

With the basic techniques presented in the preceding chapters, we're ready do our first real Smalltalk program. In this chapter we will construct three new types of objects (known as classes), using the Smalltalk technique of inheritance to tie the classes together, create new objects belonging to these classes (known as creating instances of the class), and send messages to these objects.

We'll exercise all this by implementing a toy home-finance accounting system. We will keep track of our overall cash, and will have special handling for our checking and savings accounts. From this point on, we will be defining classes which will be used in future chapters. Since you will probably not be running this whole tutorial in one Smalltalk session, it would be nice to save off the state of Smalltalk and resume it without having to retype all the previous examples. To save the current state of GNU Smalltalk, type:

     Smalltalk snapshot: 'myimage.im' !

and from your shell, to later restart Smalltalk from this "snapshot":

     $ gst -I myimage.im

Such a snapshot currently takes a little less than 700K bytes, and contains all variables, classes, and definitions you have added.


[ Next: | Previous:Creating classes | Up:Creating classes ]

Creating a new class

Guess how you create a new class? This should be getting monotonous by now-by sending a message to an object. The way we create our first "custom" class is by sending the following message:

     Object subclass: #Account
         instanceVariableNames: 'balance'
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !

Quite a mouthful, isn't it? Most people end up customizing their editor to pop this up at a push of a button. But conceptually, it isn't really that bad. The Smalltalk variable Object is bound to the grand-daddy of all classes on the system. What we're doing here is telling the Object class that we want to add to it a subclass known as Account. The other parts of the message can be ignored, but instanceVariableNames: 'balance' tells it that each object in this subclass will have a hidden variable named balance. 7


[ Next: | Previous:A new class | Up:Creating classes ]

Documenting the class

The next step is to associate a description with the class. You do this by sending a message to the new class:

     Account comment: 'I represent a place to deposit and withdraw money' !

A description is associated with every Smalltalk class, and it's considered good form to add a description to each new class you define. To get the description for a given class:

     (Account comment) printNl !

And your string is printed back to you. Try this with class Integer, too:

     (Integer comment) printNl !


[ Next: | Previous:Documenting the class | Up:Creating classes ]

Defining a method for the class

We have created a class, but it isn't ready to do any work for us-we have to define some messages which the class can process first. We'll start at the beginning by defining methods for instance creation:

    !Account class methodsFor: 'instance creation'!

     new
         | r |

         r := super new.
         r init.
         ^r
     !!

Again, programming your editor to do this is recommended. The important points about this are:

This is also the first example where we've had to use more than one statement, and thus a good place to present the statement separator-the . period. Like Pascal, and unlike C, statements are separated rather than terminated. Thus you need only use a . when you have finished one statement and are starting another. This is why our last statement, ^r, does not have a . following. Once again like Pascal, however, Smalltalk won't complain if your enter a spurious statement separator after the last statement.

The best way to describe how this method works is to step through it. Imagine we sent a message to the new class Account with the command line:

     Account new !

Account receives the message new and looks up how to process this message. It finds our new definition, and starts running it. The first line, | r |, creates a local variable named r which can be used as a placeholder for the objects we create. r will go away as soon as the message is done being processed.

The first real step is to actually create the object. The line r := super new does this using a fancy trick. The word super stands for the same object that the message new was originally sent to (remember? it's Account), except that when Smalltalk goes to search for the methods, it starts one level higher up in the hierarchy than the current level. So for a method in the Account class, this is the Object class (because the class Account inherits from is Object-go back and look at how we created the Account class), and the Object class' methods then execute some code in response to the "new" message. As it turns out, Object will do the actual creation of the object when sent a "new" message.

One more time in slow motion: the Account method new wants to do some fiddling about when new objects are created, but he also wants to let his parent do some work with a method of the same name. By saying r := super new he is letting his parent create the object, and then he is attaching it to the variable r. So after this line of code executes, we have a brand new object of type Account, and r is bound to it. You will understand this better as time goes on, but for now scratch your head once, accept it as a recipe, and keep going.

We have the new object, but we haven't set it up correctly. Remember the hidden variable balance which we saw in the beginning of this chapter? super new gives us the object with the "balance" field containing nothing, but we want our balance field to start at 0. 8

So what we need to do is ask the object to set itself up. By saying r init, we are sending the init message to our new Account. We'll define this method in the next section-for now just assume that sending the init message will get our Account set up.

Finally, we say ^r. In English, this is return what r is attached to. This means that whoever sent to Account the new message will get back this brand new account. At the same time, our temporary variable r ceases to exist.


[ Next: | Previous:Defining methods | Up:Creating classes ]

Defining an instance method

We need to define the init method for our Account objects, so that our new method defined above will work. Here's the Smalltalk code:

     !Account methodsFor: 'instance initialization'!
     init
         balance := 0
     !!

It looks quite a bit like the previous method definition, except that the first one said Account class methodsFor:..., and ours says Account methodsFor:....

The difference is that the first one defined a method for messages sent directly to "Account", but the second one is for messages which are sent to Account objects once they are created.

The method named init has only one line, balance := 0. This initializes the hidden variable balance (actually called an instance variable) to zero, which makes sense for an account balance. Notice that the method doesn't end with ^r or anything like it: this method doesn't return a value to the message sender. When you do not specify a return value, Smalltalk defaults the return value to the object currently executing. For clarity of programming, you might consider explicitly returning "self" in cases where you intend the return value to be used.9


[ Next: | Previous:Instance methods | Up:Creating classes ]

Looking at our Account

Let's create an instance of class Account:

     Smalltalk at: #a put: (Account new) !

Can you guess what this does? The Smalltalk at: #a put: <something> creates a Smalltalk variable. And the Account new creates a new Account, and returns it. So this line creates a Smalltalk variable named a, and attaches it to a new Account-all in one line. Let's take a look at the Account object we just created:

     a printNl !

It prints:

     an Account

Hmmm... not very informative. The problem is that we didn't tell our Account how to print itself, so we're just getting the default system printNl method-which tells what the object is, but not what it contains. So clearly we must add such a method:

     !Account methodsFor: 'printing'!
     printOn: stream
         super printOn: stream.
         stream nextPutAll: ' with balance: '.
         balance printOn: stream
     !!

Now give it a try again:

     a printNl !

which prints:

     an Account with balance: 0

This may seem a little strange. We added a new method, printOn:, and our printNl message starts behaving differently. It turns out that the printOn: message is the central printing function-once you've defined it, all of the other printing methods end up calling it. Its argument is a place to print to-quite often it is the variable Transcript. This variable is usually hooked to your terminal, and thus you get the printout to your screen.

The super printOn: stream lets our parent do what it did before-print out what our type is. The an Account part of the printout came from this. stream nextPutAll: ' with balance: ' creates the string with balance: , and prints it out to the stream, too; note that we don't use printOn: here because that would enclose our string within quotes. Finally, balance printOn: stream asks whatever object is hooked to the balance variable to print itself to the stream. We set balance to 0, so the 0 gets printed out.


[ Next: | Previous:A look at our object | Up:Creating classes ]

Moving money around

We can now create accounts, and look at them. As it stands, though, our balance will always be 0-what a tragedy! Our final methods will let us deposit and spend money. They're very simple:

     !Account methodsFor: 'moving money'!
     spend: amount
         balance := balance - amount
     !
     deposit: amount
         balance := balance + amount
     !!

With these methods you can now deposit and spend amounts of money. Try these operations:

     a deposit: 125!
     a deposit: 20!
     a printNl!
     a spend: 10!
     a printNl!


[ Previous:Moving money around | Up:Creating classes ]

What's next?

We now have a generic concept, "Account". We can create them, check their balance, and move money in and out of them. They provide a good foundation, but leave out important information that particular types of accounts might want. In the next chapter, we'll take a look at fixing this problem using subclasses.


[ Next: | Previous:Creating classes | Up:Tutorial ]

Two Subclasses for the Account Class

This chapter continues from the previous chapter in demonstrating how one creates classes and subclasses in Smalltalk. In this chapter we will create two special subclasses of Account, known as Checking and Savings. We will continue to inherit the capabilities of Account, but will tailor the two kinds of objects to better manage particular kinds of accounts.


[ Next: | Previous:Creating subclasses | Up:Creating subclasses ]

The Savings class

We create the Savings class as a subclass of Account. It holds money, just like an Account, but has an additional property that we will model: it is paid interest based on its balance. We create the class Savings as a subclass of Account:

     Account subclass: #Savings
         instanceVariableNames: 'interest'
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !

The instance variable interest will accumulate interest paid. Thus, in addition to the spend: and deposit: messages which we inherit from our parent, Account, we will need to define a method to add in interest deposits, and a way to clear the interest variable (which we would do yearly, after we have paid taxes). We first define a method for allocating a new account-we need to make sure that the interest field starts at 0.

     !Savings methodsFor: 'initialization'!
     init
         interest := 0.
         ^ super init
     !!

Recall that the parent took care of the new message, and created a new object of the appropriate size. After creation, the parent also sent an init message to the new object. As a subclass of Account, the new object will receive the init message first; it sets up its own instance variable, and then passes the init message up the chain to let its parent take care of its part of the initialization.

With our new Savings account created, we can define two methods for dealing specially with such an account:

     !Savings methodsFor: 'interest'!
     interest: amount
         interest := interest + amount.
         self deposit: amount
     !
     clearInterest
         | oldinterest |

         oldinterest := interest.
         interest := 0.
         ^oldinterest
     !!

The first method says that we add the amount to our running total of interest. The line self deposit: amount tells Smalltalk to send ourselves a message, in this case deposit: amount. This then causes Smalltalk to look up the method for deposit:, which it finds in our parent, Account. Executing this method then updates our overall balance.10

One may wonder why we don't just replace this with the simpler balance := balance + amount. The answer lies in one of the philosophies of object-oriented languages in general, and Smalltalk in particular. Our goal is to encode a technique for doing something once only, and then re-using that technique when needed. If we had directly encoded balance := balance + amount here, there would have been two places that knew how to update the balance from a deposit. This may seem like a useless difference. But consider if later we decided to start counting the number of deposits made. If we had encoded balance := balance + amount in each place that needed to update the balance, we would have to hunt each of them down in order to update the count of deposits. By sending self the message deposit:, we need only update this method once; each sender of this message would then automatically get the correct up-to-date technique for updating the balance.

The second method, clearInterest, is simpler. We create a temporary variable oldinterest to hold the current amount of interest. We then zero out our interest to start the year afresh. Finally, we return the old interest as our result, so that our year-end accountant can see how much we made.11


[ Next: | Previous:The Savings class | Up:Creating subclasses ]

The Checking class

Our second subclass of Account represents a checking account. We will keep track of two facets:

We will define this as another subclass of Account:

    Account subclass: #Checking
         instanceVariableNames: 'checknum checksleft'
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !

We have two instance variables, but we really only need to initialize one of them-if there are no checks left, the current check number can't matter. Remember, our parent class Account will send us the init message. We don't need our own class-specific new function, since our parent's will provide everything we need.

     !Checking methodsFor: 'Initialization'!
     init
         checksleft := 0.
         ^super init
     !!

As in Savings, we inherit most of abilities from our superclass, Account. For initialization, we leave checknum alone, but set the number of checks in our checkbook to zero. We finish by letting our parent class do its own initialization.


[ Previous:The Checking class | Up:Creating subclasses ]

Writing checks

We will finish this chapter by adding a method for spending money through our checkbook. The mechanics of taking a message and updating variables should be familiar:

     !Checking methodsFor: 'spending'!
     newChecks: number count: checkcount
         checknum := number.
         checksleft := checkcount
     !

     writeCheck: amount
         | num |

         num := checknum.
         checknum := checknum + 1.
         checksleft := checksleft - 1.
         self spend: amount.
         ^ num
     !!

newChecks: fills our checkbook with checks. We record what check number we're starting with, and update the count of the number of checks in the checkbook.

writeCheck: merely notes the next check number, then bumps up the check number, and down the check count. The message self spend: amount resends the message spend: to our own object. This causes its method to be looked up by Smalltalk. The method is then found in our parent class, Account, and our balance is then updated to reflect our spending.

You can try the following examples:

     Smalltalk at: #c put: (Checking new) !
     c printNl !
     c deposit: 250 !
     c printNl !
     c newChecks: 100 count: 50 !
     c printNl !
     (c writeCheck: 32) printNl !
     c printNl !

For amusement, you might want to add a printOn: message to the checking class so you can see the checking-specific information.

In this chapter, you have seen how to create subclasses of your own classes. You have added new methods, and inherited methods from the parent classes. These techniques provide the majority of the structure for building solutions to problems. In the following chapters we will be filling in details on further language mechanisms and types, and providing details on how to debug software written in Smalltalk.


[ Next: | Previous:Creating subclasses | Up:Tutorial ]

Code blocks

The Account/Saving/Checking example from the last chapter has several deficiencies. It has no record of the checks and their values. Worse, it allows you to write a check when there are no more checks-the Integer value for the number of checks will just calmly go negative! To fix these problems we will need to introduce more sophisticated control structures.


[ Next: | Previous:Code blocks (I) | Up:Code blocks (I) ]

Conditions and decision making

Let's first add some code to keep you from writing too many checks. We will simply update our current method for the Checking class; if you have entered the methods from the previous chapters, the old definition will be overridden by this new one.

     !Checking methodsFor: 'spending'!
     writeCheck: amount
         | num |

         (checksleft < 1)
             ifTrue: [ ^self error: 'Out of checks' ].
         num := checknum.
         checknum := checknum + 1.
         checksleft := checksleft - 1.
         self spend: amount
         ^ num
     !!

The two new lines are:

     (checksleft < 1)
         ifTrue: [ ^self error: 'Out of checks' ].

At first glance, this appears to be a completely new structure. But, look again! The only new construct is the square brackets.

The first line is a simple boolean expression. checksleft is our integer, as initialized by our Checking class. It is sent the message <, and the argument 1. The current number bound to checksleft compares itself against 1, and returns a boolean object telling whether it is less than 1.

Now this boolean, which is either true or false, is sent the message ifTrue:, with an argument which is called a code block. A code block is an object, just like any other. But instead of holding a number, or a Set, it holds executable statements. So what does a boolean do with a code block which is an argument to a ifTrue: message? It depends on which boolean! If the object is the true object, it executes the code block it has been handed. If it is the false object, it returns without executing the code block. So the traditional conditional construct has been replaced in Smalltalk with boolean objects which execute the indicated code block or not, depending on their truth-value. 12

In the case of our example, the actual code within the block sends an error message to the current object. error: is handled by the parent class Object, and will pop up an appropriate complaint when the user tries to write too many checks. In general, the way you handle a fatal error in Smalltalk is to send an error message to yourself (through the self pseudo-variable), and let the error handling mechanisms inherited from the Object class take over.

As you might guess, there is also an ifFalse: message which booleans accept. It works exactly like ifTrue:, except that the logic has been reversed; a boolean false will execute the code block, and a boolean true will not.

You should take a little time to play with this method of representing conditionals. You can run your checkbook, but can also invoke the conditional functions directly:

     true ifTrue: [ 'Hello, world!' printNl ] !
     false ifTrue: [ 'Hello, world!' printNl ] !
     true ifFalse: [ 'Hello, world!' printNl ] !
     false ifFalse: [ 'Hello, world!' printNl ] !


[ Previous:Conditions | Up:Code blocks (I) ]

Iteration and collections

Now that we have some sanity checking in place, it remains for us to keep a log of the checks we write. We will do so by adding a Dictionary object to our Checking class, logging checks into it, and providing some messages for querying our check-writing history. But this enhancement brings up a very interesting question-when we change the "shape" of an object (in this case, by adding a new instance variable to the Checking class-our dictionary), what happens to the existing class, and its objects? The answer is that the old objects are mutated to keep their new shape, and all methods are recompiled so that they work with the new shape. New objects will have the exact shape as old ones, but old objects might happen to be initialized incorrectly. As this can lead to very puzzling behavior, it is usually best to eradicate all of the old objects, and then implement your changes.

If this were more than a toy object accounting system, this would probably entail saving the objects off, converting to the new class, and reading the objects back into the new format. For now, we'll just ignore what's currently there, and define our latest Checking class.

     Account subclass: #Checking
         instanceVariableNames: 'checknum checksleft history'
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !

This is the same syntax as the last time we defined a checking account, except that we have three instance variables: the "checknum" and "checksleft" which have always been there, and our new "history" variable; since we have removed no instance variables, the old method will be recompiled without errors. We must now feed in our definitions for each of the messages our object can handle, since we are basically defining a new class under an old name.

With our new Checking instance variable, we are all set to start recording our checking history. Our first change will be in the handling of the init message:

     !Checking methodsFor: 'initialization'!
     init
         checksleft := 0.
         history := Dictionary new.
         ^ super init
     !!

This provides us with a Dictionary, and hooks it to our new history variable.

Our next method records each check as it's written. The method is a little more involved, as we've added some more sanity checks to the writing of checks.

     !Checking methodsFor: 'spending'!
     writeCheck: amount
         | num |

         "Sanity check that we have checks left in our checkbook"
         (checksleft < 1)
             ifTrue: [ ^self error: 'Out of checks' ].

         "Make sure we've never used this check number before"
         num := checknum.
         (history includesKey: num)
             ifTrue: [ ^self error: 'Duplicate check number' ].

         "Record the check number and amount"
         history at: num put: amount.

         "Update our next checknumber, checks left, and balance"
         checknum := checknum + 1.
         checksleft := checksleft - 1.
         self spend: amount.
         ^ num
     !!

We have added three things to our latest version of writeCheck:. First, since our routine has become somewhat involved, we have added comments. In Smalltalk, single quotes are used for strings; double quotes enclose comments. We have added comments before each section of code.

Second, we have added a sanity check on the check number we propose to use. Dictionary objects respond to the includesKey: message with a boolean, depending on whether something is currently stored under the given key in the dictionary. If the check number is already used, the error: message is sent to our object, aborting the operation.

Finally, we add a new entry to the dictionary. We have already seen the at:put: message (often found written as #at:put:, with a sharp in front of it) at the start of this tutorial. Our use here simply associates a check number with an amount of money spent.13 With this, we now have a working Checking class, with reasonable sanity checks and per-check information.

Let us finish the chapter by enhancing our ability to get access to all this information. We will start with some simple print-out functions.

     !Checking methodsFor: 'printing'!
     printOn: stream
         super printOn: stream.
         ', checks left: ' printOn: stream.
         checksleft printOn: stream.
         ', checks written: ' printOn: stream.
         (history size) printOn: stream.
     !
     check: num
         | c |
         c := history at: num ifAbsent: [ ^self error: 'No such check #' ].
         ^c
     !!

There should be very few surprises here. We format and print our information, while letting our parent classes handle their own share of the work. When looking up a check number, we once again take advantage of the fact that blocks of executable statements are an object; in this case, we are using the at:ifAbsent: message supported by the Dictionary class. As you can probably anticipate, if the requested key value is not found in the dictionary, the code block is executed. This allows us to customize our error handling, as the generic error would only tell the user "key not found".

While we can look up a check if we know its number, we have not yet written a way to riffle through our collection of checks. The following function loops over the checks, printing them out one per line. Because there is currently only a single numeric value under each key, this might seem wasteful. But we have already considered storing multiple values under each check number, so it is best to leave some room for each item. And, of course, because we are simply sending a printing message to an object, we will not have to come back and re-write this code so long as the object in the dictionary honors our printNl/printOn: messages sages.

     !Checking methodsFor: 'printing'!
     printChecks
         history associationsDo: [ :assoc |
             (assoc key) print.
             ' - ' print.
             (assoc value) printNl.
         ]
     !!

We still see a code block object being passed to the dictionary, but :assoc | is something new. A code block can optionally receive arguments. In this case, the argument is the key/value pair, known in Smalltalk as an Association. This is the way that a dictionary object stores its key/value pairs internally. In fact, when you sent an at:put: message to a dictionary object, the first thing it does is pack them into a new object from the Association class. If you only wanted the value portion, you could call history with a do: message instead; if you only wanted the key portion, you could call history with a keysDo: message instead.

Our code merely uses the key and value messages to ask the association for the two values. We then invoke our printing interface upon them. We don't want a newline until the end, so the print message is used instead. It is pretty much the same as printNl, since both implicitly use Transcript, except it doesn't add a newline.

It is important that you be clear on the relationship between an Association and the argument to a code block. In this example, we passed a associationsDo: message to a dictionary. A dictionary invokes the passed code block with an Association when processing an associationsDo: message. But code blocks can receive any type of argument: the type is determined by the code which invokes the code block; Dictionary's associationDo: method, in this case. In the next chapter we'll see more on how code blocks are used; we'll also look at how you can invoke code blocks in your own code.


[ Next: | Previous:Code blocks (I) | Up:Tutorial ]

Code blocks, part two

In the last chapter, we looked at how code blocks could be used to build conditional expressions, and how you could iterate across all entries in a collection.14 We built our own code blocks, and handed them off for use by system objects. But there is nothing magic about invoking code blocks; your own code will often need to do so. This chapter will shows some examples of loop construction in Smalltalk, and then demonstrate how you invoke code blocks for yourself.


[ Next: | Previous:Code blocks (II) | Up:Code blocks (II) ]

Integer loops

Integer loops are constructed by telling a number to drive the loop. Try this example to count from 1 to 20:

     1 to: 20 do: [:x | x printNl ] !

There's also a way to count up by more than one:

     1 to: 20 by: 2 do: [:x | x printNl ] !

Finally, counting down is done with a negative step:

     20 to: 1 by: -1 do: [:x | x printNl ] !


[ Next: | Previous:Integer loops | Up:Code blocks (II) ]

Intervals

It is also possible to represent a range of numbers as a standalone object. This allows you to represent a range of numbers as a single object, which can be passed around the system.

     Smalltalk at: #i put: (Interval from: 5 to: 10) !
     i printNl !
     i do: [:x | x printNl] !

As with the integer loops, the Interval class can also represent steps greater than 1. It is done much like it was for our numeric loop above:

     i := (Interval from: 5 to: 10 by: 2)
     i printNl !
     i do: [:x| x printNl] !


[ Previous:Intervals | Up:Code blocks (II) ]

Invoking code blocks

Let us revisit the checking example and add a method for scanning only checks over a certain amount. This would allow our user to find "big" checks, by passing in a value below which we will not invoke their function. We will invoke their code block with the check number as an argument ment; they can use our existing check: message to get the amount.

     !Checking methodsFor: 'scanning'!
     checksOver: amount do: aBlock
         history associationsDo: [:assoc|
             ((assoc value) > amount)
                    ifTrue: [aBlock value: (assoc key)]
         ]
     !!

The structure of this loop is much like our printChecks message sage from chapter 6. However, in this case we consider each entry, and only invoke the supplied block if the check's value is greater than the specified amount. The line:

     ifTrue: [aBlock value: (assoc key)]

invokes the user-supplied block, passing as an argument the association's key, which is the check number. The value: message, when received by a code block, causes the code block to execute. Code blocks take value, value:, value:value:, and value:value:value: messages, so you can pass from 0 to 3 arguments to a code block.15

You might find it puzzling that an association takes a "value" message sage, and so does a code block. Remember, each object can do its own thing with a message. A code block gets run when it receives a value message. An association merely returns the value part of its key/value pair. The fact that both take the same message is, in this case, coincidence.

Let's quickly set up a new checking account with $250 (wouldn't this be nice in real life?) and write a couple checks. Then we'll see if our new method does the job correctly:

     Smalltalk at: #mycheck put: (Checking new) !
     mycheck deposit: 250 !
     mycheck newChecks: 100 count: 40 !
     mycheck writeCheck: 10 !
     mycheck writeCheck: 52 !
     mycheck writeCheck: 15 !
     mycheck checksOver: 1 do: [:x | x printNl] !
     mycheck checksOver: 17 do: [:x | x printNl] !
     mycheck checksOver: 200 do: [:x | x printNl] !

We will finish this chapter with an alternative way of writing our checksOver: code. In this example, we will use the message select: to pick the checks which exceed our value, instead of doing the comparison ourselves. We can then invoke the new resulting collection against the user's code block.

     !Checking methodsFor: 'scanning'!
     checksOver: amount do: aBlock
         | chosen |
         chosen := history select: [:amt| amt > amount].
         chosen associationsDo: aBlock
     !!

Unlike our previous definition of checksOver:do:, this one passes the user's code block the association, not just a check number. How could this code be rewritten to remedy this, while still using select:?

Yet, this new behavior can be useful. You can use the same set of tests that we ran above. Notice that our code block:

     [:x| x printNl]
now prints out an Association. This has the very nice effect-with our old method, we were told which check numbers were above a given amount. With this new method, we get the check number and amount in the form of an Association. When we print an association, since the key is the check number and the value is the check amount, we get a list of checks over the amount in the format:
     CheckNum -> CheckVal


[ Next: | Previous:Code blocks (II) | Up:Tutorial ]

When Things Go Bad

So far we've been working with examples which work the first time. If you didn't type them in correctly, you probably received a flood of unintelligible complaints. You probably ignored the complaints, and typed the example again.

When developing your own Smalltalk code, however, these messages are the way you find out what went wrong. Because your objects, their methods, the error printout, and your interactive environment are all contained within the same Smalltalk session, you can use these error messages to debug your code using very powerful techniques.


[ Next: | Previous:Debugging | Up:Debugging ]

A Simple Error

First, let's take a look at a typical error. Type:

     7 plus: 1 !

This will print out:

     7 did not understand selector 'plus:'
     <blah blah>
     UndefinedObject>>#executeStatements

The first line is pretty simple; we sent a message to the 7 object which was not understood; not surprising since the plus: operation should have been +. Then there are a few lines of gobbledegook: just ignore them, they reflect the fact that the error passed throgh GNU Smalltalk's exception handling system. The remaining line reflect the way the GNU Smalltalk invokes code which we type to our command prompt; it generates a block of code which is invoked via an internal method executeStatements defined in class Object and evaluated like nil executeStatements (nil is an instance of UndefinedObject). Thus, this output tells you that you directly typed a line which sent an invalid message to the 7 object.

All the error output but the first line is actually a stack backtrace. The most recent call is the one nearer the top of the screen. In the next example, we will cause an error which happens deeper within an object.


[ Next: | Previous:Simple errors | Up:Debugging ]

Nested Calls

Type the following lines:

     Smalltalk at: #x put: (Dictionary new) !
     x at: 1 !

The error you receive will look like:

     Dictionary new: 31 "<0x33788>" error: key not found
     <blah blah>
     [] in Dictionary>>#at:
     [] in Dictionary>>#at:ifAbsent:
     Dictionary(Set)>>#findIndex:ifAbsent:
     Dictionary>>#at:ifAbsent:
     Dictionary>>#at:
     UndefinedObject(Object)>>#executeStatements

The error itself is pretty clear; we asked for something within the Dictionary which wasn't there. The object which had the error is identified as Dictionary new: 31. A Dictionary's default size is 31; thus, this is the object we created with Dictionary new.

The stack backtrace shows us the inner structure of how a Dictionary responds to the at: message. Our hand-entered command causes the usual entry for UndefinedObject(Object). Then we see a Dictionary object responding to an at: message (the "Dictionary>>#at" line). This code called the object with an at:ifAbsent: message. All of a sudden, Dictionary calls that strange method findIndex:ifAbsent:, which evaluates two blocks, and then the error happens.

To understand this better, it is necessary to know that a very common way to handle errors in Smalltalk is to hand down a block of code which will be called when an error occurs. For the Dictionary code, the at: message passes in a block of code to the at:ifAbsent: code to be called when at:ifAbsent: can't find the given key, and at:ifAbsent: does the same with findIndex:ifAbsent:. Thus, without even looking at the code for Dictionary itself, we can guess something of the code for Dictionary's implementation:

findIndex: key ifAbsent: errCodeBlock ...look for key... (keyNotFound) ifTrue: [ ^(errCodeBlock value) ] ...

at: key ^self at: key ifAbsent: [^self error: 'key not found']

Actually, findIndex:ifAbsent: lies in class Set, as that Dictionary(Set) in the backtrace says.

It would be nice if each entry on the stack backtrace included source line numbers. Unfortunately, at this point GNU Smalltalk doesn't provide this feature. Of course, you have the source code available....


[ Previous:Nested calls | Up:Debugging ]

Looking at Objects

When you are chasing an error, it is often helpful to examine the instance variables of your objects. While strategic calls to printNl will no doubt help, you can look at an object without having to write all the code yourself. The inspect message works on any object, and dumps out the values of each instance variable within the object.16

Thus:

     Smalltalk at: #x put: (Interval from: 1 to: 5) !
     x inspect !

displays:

     An instance of Interval
     start: 1
     stop: 5
     step: 1
     contents: [
         [1]: 1
         [2]: 2
         [3]: 3
         [4]: 4
         [5]: 5
     ]

We'll finish this chapter by emphasizing a technique which has already been covered: the use of the error: message in your own objects. As you saw in the case of Dictionary, an object can send itself an error: message with a descriptive string to abort execution and dump a stack backtrace. You should plan on using this technique in your own objects. It can be used both for explicit user-caused errors, as well as in internal sanity checks.


[ Next: | Previous:Debugging | Up:Tutorial ]

Coexisting in the Class Hierarchy

The early chapters of this tutorial discussed classes in one of two ways. The "toy" classes we developed were rooted at Object; the system-provided classes were treated as immutable entities. While one shouldn't modify the behavior of the standard classes lightly, "plugging in" your own classes in the right place among their system-provided brethren can provide you powerful new classes with very little effort.

This chapter will create two complete classes which enhance the existing Smalltalk hierarchy. The discussion will start with the issue of where to connect our new classes, and then continue onto implementation. Like most programming efforts, the result will leave many possibilities for improvements. The framework, however, should begin to give you an intuition of how to develop your own Smalltalk classes.


[ Next: | Previous:More subclassing | Up:More subclassing ]

The Existing Class Hierarchy

To discuss where a new class might go, it is helpful to have a map of the current classes. The following is the basic class hierarchy of GNU Smalltalk. Indentation means that the line inherits from the earlier line with one less level of indentation.17.

    Object
        Behavior
            ClassDescription
                Class
                Metaclass
        BlockClosure
        Boolean
            False
            True
        Browser
        CFunctionDescriptor
        CObject
            CAggregate
                CArray
                CPtr
            CScalar
                CChar
                CDouble
                CFloat
                CInt
                CLong
                CShort
                CSmalltalk
                CString
                CUChar
                    CByte
                        CBoolean
                CUInt
                CULong
                CUShort
            CStruct
                CStatStruct
        Collection
            Bag
            MappedCollection
            SequenceableCollection
                ArrayedCollection
                    Array
                    ByteArray
                    Interval
                    String
                        Symbol
                LinkedList
                    Semaphore
                OrderedCollection
                    RunArray
                    SortedCollection
            Set
                Dictionary
                    IdentityDictionary
                    SystemDictionary
                IdentitySet
        CompiledMethod
        ContextPart
            BlockContext
            MethodContext
        CType
            CArrayCType
            CPtrCType
            CScalarCType
        Delay
        DumperProxy
        ExceptionHandler
        File
            Directory
        FileSegment
        Link
            Process
            SymLink
        Magnitude
            Association
            Character
            Date
            Number
                Float
                Fraction
                Integer
                    LargeInteger
                        LargeNegativeInteger
                        LargePositiveInteger
                            LargeZeroInteger
            Time
        Memory
            ByteMemory
            WordMemory
        Message
            DirectedMessage
        MethodInfo
        PackageLoader
        Point
        ProcessorScheduler
        Rectangle
        SharedQueue
        Signal
        Stream
            ObjectDumper
            PositionableStream
                ReadStream
                WriteStream
                    ReadWriteStream
                        ByteStream
                            FileStream
            Random
            TokenStream
        TrappableEvent
            Exception
            ExceptionCollection
        UndefinedObject
        ValueAdaptor
            PluggableAdaptor
                DelayedAdaptor
            ValueHolder
    Autoload

While initially a daunting list, you should take the time to hunt down the classes we've examined in this tutorial so far. Notice, for instance, how an Array is a subclass below the SequenceableCollection class. This makes sense; you can walk an Array from one end to the other. By contrast, notice how a Set is at the same level as SequenceableCollection. It doesn't make sense to walk a Set from one end to the other.

A little puzzling is the relationship of a Dictionary to a Set; why is a Dictionary a subclass of a Set?18 The answer lies in the basic structure of both a Set and a Dictionary. Both hold an unordered collection of objects. For a set, they're any objects; for a Dictionary, they are Associations. Thus, Dictionary inherits some of the more basic mechanisms for creating itself, and then adds an extra layer of interpretation.19

Finally, look at the treatment of numbers-starting with the class Magnitude. While numbers can indeed be ordered by less than, greater than, and so forth, so can a number of other objects. Each subclass of Magnitude is such an object. So we can compare characters with other characters, dates with other dates, and times with other times, as well as numbers with numbers.


[ Next: | Previous:The existing hierarchy | Up:More subclassing ]

Playing with Arrays

Imagine that you need an array, but alas you need that if an index is out of bounds, it returns nil. You could modify the Smalltalk implementation, but that might break some code in the image, so it is not practical. Why not add a subclass?

     Array variableSubclass: #NiledArray
         instanceVariableNames: ''
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !

     !NiledArray methodsFor: 'bounds checking'!
     boundsCheck: index
         ^(index < 1) | (index > (self basicSize))
     !!

     !NiledArray methodsFor: 'basic'!
     at: index
         ^(self boundsCheck: index)
             ifTrue: [ nil ]
             ifFalse: [ super at: index ]

     !
     at: index put: val
         ^(self boundsCheck: index)
             ifTrue: [ val ]
             ifFalse: [ super at: index put: val ]
     !!

Much of the machinery of adding a class should be familiar. Instead of our usual subclass: message, we use a variableSubclass: message. This reflects the underlying structure of an Array object; we'll delay discussing this until the chapter on the nuts and bolts of arrays. In any case, we inherit all of the actual knowledge of how to create arrays, reference them, and so forth. All that we do is intercept at: and at:put: messages, call our common function to validate the array index, and do something special if the index is not valid. The way that we coded the bounds check bears a little examination.

Making a first cut at coding the bounds check, you might have coded the bounds check in NiledArray's methods twice (once for at:, and again for at:put:. As always, it's preferable to code things once, and then re-use them. So we instead add a method for bounds checking boundsCheck:, and use it for both cases. If we ever wanted to enhance the bounds checking (perhaps emit an error if the index is < 1 and answer nil only for indices greater than the array size?), we only have to change it in one place.

The actual math for calculating whether the bounds have been violated is a little interesting. The first part of the expression returned by the method:

     (index < 1) | (index > (self basicSize))

is true if the index is less than 1, otherwise it's false. This part of the expression thus becomes the boolean object true or false. The boolean object then receives the message |, and the argument (index > (self basicSize)). | means "or"-we want to OR together the two possible out-of-range checks. What is the second part of the expression? 20

index is our argument, an integer; it receives the message >, and thus will compare itself to the value self basicSize returns. While we haven't covered the underlying structures Smalltalk uses to build arrays, we can briefly say that the "basicSize" message returns the number of elements the Array object can contain. So the index is checked to see if it's less than 1 (the lowest legal Array index) or greater than the highest allocated slot in the Array. If it is either (the | operator!), the expression is true, otherwise false.

From there it's downhill; our boolean object, returned by boundsCheck:, receives the ifTrue:ifFalse: message, and a code block which will do the appropriate thing. Why do we have at:put: return val? Well, because that's what it's supposed to do: look at every implementor of at:put or at: and you'll find that it returns its second parameter. In general, the result is discarded; but one could write a program which uses it, so we'll write it this way anyway.


[ Next: | Previous:Playing with Arrays | Up:More subclassing ]

Adding a New Kind of Number

If we were programming an application which did a large amount of complex math, we could probably manage it with a number of two-element arrays. But we'd forever be writing in-line code for the math and comparisons; it would be much easier to just implement an object class to support the complex numeric type. Where in the class hierarchy would it be placed?

You've probably already guessed-but let's step down the hierarchy anyway. Everything inherits from Object, so that's a safe starting point. Complex numbers can not be compared with < and >, and yet we strongly suspect that, since they are numbers, we should place them under the Number class. But Number inherits from Magnitude-how do we resolve this conflict? A subclass can place itself under a superclass which allows some operations the subclass doesn't wish to allow. All that you must do is make sure you intercept these messages and return an error. So we will place our new Complex class under Number, and make sure to disallow comparisons.

One can reasonably ask whether the real and imaginary parts of our complex number will be integer or floating point. In the grand Smalltalk tradition, we'll just leave them as objects, and hope that they respond to numeric messages reasonably. If they don't, the user will doubtless receive errors and be able to track back their mistake with little fuss.

We'll define the four basic math operators, as well as the (illegal) relationals. We'll add printOn: so that the printing methods work, and that should give us our Complex class. The class as presented suffers some limitations, which we'll cover later in the chapter.

     Number subclass: #Complex
         instanceVariableNames: 'realpart imagpart'
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !
     !Complex class methodsFor: 'creating'!
     new
         ^self error: 'use real:imaginary:'
     !
     new: ignore
         ^self new
     !
     real: r imaginary: i
         ^(super new) setReal: r setImag: i
     !!

     !Complex methodsFor: 'creating--private'!
     setReal: r setImag: i
         realpart := r.
         imagpart := i.
         ^self
     !!

     !Complex methodsFor: 'basic'!
     real
         ^realpart
     !
     imaginary
         ^imagpart
     !!

     !Complex methodsFor: 'math'!
     + val
         ^Complex real: (realpart + (val real))
             imaginary: (imagpart + (val imaginary))
     !
     - val
         ^Complex real: (realpart - (val real))
             imaginary: (imagpart - (val imaginary))
     !
     * val
         ^Complex real: ((realpart * (val real)) - (imagpart * (val imaginary)))
             imaginary: ((realpart * (val imaginary)) +
                    (imagpart * (val real)))
     !
     / val
         | d r i |
         d := ((val real) * (val real)) + ((val imaginary) * (val imaginary)).
         r := ((realpart * (val real)) + (imagpart * (val imaginary))) / d.
         i := ((imagpart * (val real)) - (realpart * (val imaginary))) / d.
         ^Complex real: r imaginary: i
     !!

     !Complex methodsFor: 'comparison'!

     = val
         ^((realpart = (val real)) & (imagpart = (val imaginary)))
     !
     > val
         ^self shouldNotImplement
     !
     >= val
         ^self shouldNotImplement
     !
     < val
         ^self shouldNotImplement
     !
     <= val
         ^self shouldNotImplement
     !!

     !Complex methodsFor: 'printing'!
     printOn: aStream
         aStream nextPut: $(.
         realpart printOn: aStream.
         aStream nextPut: $,.
         imagpart printOn: aStream.
         aStream nextPut: $)
     !!

There should be surprisingly little which is actually new in this example. The printing method uses both printOn: as well as nextPut: to do its printing. While we haven't covered it, it's pretty clear that $( generates the ASCII character ( as an object, and nextPut: puts its argument as the next thing on the stream.

The math operations all generate a new object, calculating the real and imaginary parts, and invoking the Complex class to create the new object. Our creation code is a little more compact than earlier examples; instead of using a local variable to name the newly-created object, we just use the return value and send a message directly to the new object. Our initialization code explicitly returns self; what would happen if we left this off?


[ Previous:New kinds of Numbers | Up:More subclassing ]

Inheritance and Polymorphism

This is a good time to look at what we've done with the two previous examples at a higher level. With the NiledArray class, we inherited almost all of the functionality ality of arrays, with only a little bit of code added to address our specific needs. While you may have not thought to try it, all the existing methods for an Array continue to work without further effort-you might find it interesting to ponder why the following still works:

     Smalltalk at: #a put: (NiledArray new: 10) !
     a at: 5 put: 1234 !
     a do: [:i| i printNl ] !

The strength of inheritance is that you focus on the incremental changes you make; the things you don't change will generally continue to work.

In the Complex class, the value of polymorphism was exercised. A Complex number responds to exactly the same set of messages as any other number. If you had handed this code to someone, they would know how to do math with Complex numbers without further instruction. Compare this with C, where a complex number package would require the user to first find out if the complex-add function was complex_plus(), or perhaps complex_add(), or add_complex(), or....

However, one glaring deficiency is present in the Complex class: what happens if you mix normal numbers with Complex numbers? Currently, the Complex class assumes that it will only interact with other Complex numbers. But this is unrealistic: mathematically, a "normal" number is simply one with an imaginary part of 0. Smalltalk was designed to allow numbers to coerce themselves into a form which will work with other numbers.

The system is clever and requires very little additional code. Unfortunately, it would have tripled the amount of explanation required. If you're interested in how coercion works in GNU Smalltalk, you should find the Smalltalk library source, and trace back the execution of the retry:coercing: messages. You want to consider the value which the generality message returns for each type of number. Finally, you need to examine the coerce: handling in each numeric class.


[ Next: | Previous:More subclassing | Up:Tutorial ]

Smalltalk Streams

Our examples have used a mechanism extensively, even though we haven't discussed it yet. The Stream class provides a framework for a number of data structures, including input and output functionality, queues, and endless sources of dynamically-generated data. A Smalltalk stream is quite similar to the UNIX streams you've used from C. A stream provides a sequential view to an underlying resource; as you read or write elements, the stream position advances until you finally reach the end of the underlying medium. Most streams also allow you to set the current position, providing random access to the medium.


[ Next: | Previous:Streams | Up:Streams ]

The Output Stream

The examples in this book all work because they write their output to the Transcript stream. Each class implements the printOn: method, and writes its output to the supplied stream. The printNl method all objects use is simply to send the current object a printOn: message whose argument is Transcript (by default attached to the standard output stream found in the stdout global). You can invoke the standard output stream directly:

     'Hello, world' printOn: stdout !
     stdout inspect !

or you can do the same for the Transcript, which is yet another stream:

     'Hello, world' printOn: stdout !
     Transcript inspect !

the last inspect statement will show you how the Transcript is linked to stdout21.


[ Next: | Previous:The output stream | Up:Streams ]

Your Own Stream

Unlike a pipe you might create in C, the underlying storage of a Stream is under your control. Thus, a Stream can provide an anonymous buffer of data, but it can also provide a stream-like interpretation to an existing array of data. Consider this example:

     Smalltalk at: #a put: (Array new: 10) !
     a at: 4 put: 1234 !
     a at: 9 put: 5678 !
     Smalltalk at: #s put: (ReadWriteStream on: a) !
     s inspect !
     s position: 1 !
     s inspect !
     s nextPut: 11; nextPut: 22 !
     (a at: 1) printNl !
     a do: [:x| x printNl] !
     s position: 2 !
     s do: [:x| x printNl] !
     s position: 5 !
     s do: [:x| x printNl] !
     s inspect !

The key is the on: message; it tells a stream class to create itself in terms of the existing storage. Because of polymorphism, the object specified by on: does not have to be an Array; any object which responds to numeric at: messages can be used. If you happen to have the NiledArray class still loaded from the previous chapter, you might try streaming over that kind of array instead.

You're wondering if you're stuck with having to know how much data will be queued in a Stream at the time you create the stream. If you use the right class of stream, the answer is no. A ReadStream provides read-only access to an existing collection. You will receive an error if you try to write to it. If you try to read off the end of the stream, you will also get an error.

By contrast, WriteStream and ReadWriteStream (used in our example) will tell the underlying collection to grow when you write off the end of the existing collection. Thus, if you want to write several strings, and don't want to add up their lengths yourself:

     Smalltalk at: #s put: (ReadWriteStream on: (String new)) !
     s inspect !
     s nextPutAll: 'Hello, '!
     s inspect !
     s nextPutAll: 'world'!
     s inspect !
     s position: 1 !
     s inspect !
     s do: [:c | stdout nextPut: c ] !
     (s contents) printNl !

In this case, we have used a String as the collection for the Stream. The printOn: messages add bytes to the initially empty string. Once we've added the data, you can continue to treat the data as a stream. Alternatively, you can ask the stream to return to you the underlying object. After that, you can use the object (a String, in this example) using its own access methods.

There are many amenities available on a stream object. You can ask if there's more to read with atEnd. You can query the position with position, and set it with position:. You can see what will be read next with peek, and you can read the next element with next.

In the writing direction, you can write an element with nextPut:. You don't need to worry about objects doing a printOn: with your stream as a destination; this operation ends up as a sequence of nextPut: operations to your stream. If you have a collection of things to write, you can use nextPutAll: with the collection as an argument; each member of the collection will be written onto the stream. If you want to write an object to the stream several times, you can use next:put:, like this:

     Smalltalk at: #s put: (ReadWriteStream on: (Array new: 0)) !
     s next: 4 put: 'Hi!' !
     s position: 1 !
     s do: [:x | x printNl] !


[ Next: | Previous:Your own stream | Up:Streams ]

Files

Streams can also operate on files. If you wanted to dump the file "/etc/passwd" to your terminal, you could create a stream on the file, and then stream over its contents:

     Smalltalk at: #f put: (FileStream
         open: '/etc/passwd'
         mode: FileStream read) !
     f do: [:c| Transcript nextPut: c ] !
     f position: 30 !
     1 to: 25 do: [Transcript nextPut: (f next) ] !
     f close !

and, of course, you can load Smalltalk source code into your image:

     FileStream fileIn: '/users/myself/src/source.st' !


[ Previous:Files | Up:Streams ]

Dynamic Strings

Streams provide a powerful abstraction for a number of data structures. Concepts like current position, writing the next position, and changing the way you view a data structure when convenient combine to let you write compact, powerful code. The last example is taken from the actual Smalltalk source code-it shows a general method for making an object print itself onto a string.

     printString
         | stream |
         stream := WriteStream on: (String new).
         self printOn: stream.
         ^stream contents
     !

This method, residing in Object, is inherited by every class in Smalltalk. The first line creates a WriteStream which stores on a String whose length is currently 0 (String new simply creates an empty string. It then invokes the current object with printOn:. As the object prints itself to "stream", the String grows to accommodate new characters. When the object is done printing, the method simply returns the underlying string.

As we've written code, the assumption has been that printOn: would go to the terminal. But replacing a stream to a file like /dev/tty with a stream to a data structure (String new) works just as well. The last line tells the Stream to return its underlying collection, which will be the string which has had all the printing added to it. The result is that the printString message returns an object of the String class whose contents are the printed representation of the very object receiving the message.


[ Next: | Previous:Streams | Up:Tutorial ]

Some nice stuff from the Smalltalk innards

Just like with everything else, you'd probably end up asking yourself: how's it done? So here's this chapter, just to wheten your appetite...


[ Next: | Previous:Behind the scenes | Up:Behind the scenes ]

How Arrays Work

Smalltalk provides a very adequate selection of predefined classes from which to choose. Eventually, however, you will find the need to code a new basic data structure. Because Smalltalk's most fundamental storage allocation facilities are arrays, it is important that you understand how to use them to gain efficient access to this kind of storage.

The Array Class. Our examples have already shown the Array class, and its use is fairly obvious. For many applications, it will fill all your needs-when you need an array in a new class, you keep an instance variable, allocate a new Array and assign it to the variable, and then send array accesses via the instance variable.

This technique even works for string-like objects, although it is wasteful of storage. An Array object uses a Smalltalk pointer for each slot in the array; its exact size is transparent to the programmer, but you can generally guess that it'll be roughly the word size of your machine. 22 For storing an array of characters, therefore, an Array works but is inefficient.

Arrays at a Lower Level. So let's step down to a lower level of data structure. A ByteArray is much like an Array, but each slot holds only an integer from 0 to 255-and each slot uses only a byte of storage. If you only needed to store small quantities in each array slot, this would therefore be a much more efficient choice than an Array. As you might guess, this is the type of array which a String uses.

Aha! But when you go back to chapter 9 and look at the Smalltalk hierarchy, you notice that String does not inherit from ByteArray. To see why, we must delve down yet another level, and arrive at the basic methods for creating a class.

For most example classes, we've used the message:

         subclass:
         instanceVariableNames:
         classVariableNames:
         poolDictionaries:
         category:

But when we implemented our CheckedArray example, we used variableSubclass: instead of just subclass:. The choice of these two kinds of class creation (and two more we'll show shortly) defines the fundamental structure of Smalltalk objects created within a given class. Let's consider the differences in the next sub-sections.

subclass:. This kind of class creation specifies the simplest Smalltalk object. The object consists only of the storage needed to hold the instance variables. In C, this would be a simple structure with zero or more scalar fields.23.

variableSubclass:. All the other types of class are a superset of a subclass:. Storage is still allocated for any instance variables 24, but the objects of the class must be created with a new: message. The number passed as an argument to new: causes the new object, in addition to the space for instance variables, to also have that many slots of unnamed (indexed) storage allocated. The analog in C would be to have a dynamically allocated structure with some scalar fields, followed at its end by a array of pointers.

variableByteSubclass:. This is a special case of variableSubclass:; the storage age allocated as specified by new: is an array of bytes. The analog in C would be a dynamically allocated structure with scalar fields, followed by a array of char.

variableWordSubclass:. Once again, this is a special case of variableSubclass:; the storage age allocated as specified by new: is an array of C signed longs, which are represented in Smalltalk by Integer objects. The analog in C would be a dynamically allocated structure with scalar fields, followed by an array of long. This kind of subclass is only used in a few places in Smalltalk.

Accessing These New Arrays. You already know how to access instance variables-by name. But there doesn't seem to be a name for this new storage. The way an object accesses it is to send itself array-type messages like at:, at:put:, and so forth.

The problem is when an object wants to add a new level of interpretation to the at: and at:put: messages. Consider a Dictionary-it is a variableSubclass: type of object, but its at: message is in terms of a key, not an integer index of its storage. Since it has redefined the at: message, how does it access its fundamental storage?

The answer is that Smalltalk has defined basicAt: and basicAt:put:, which will access the basic storage even when the at: and at:put: messages have been defined to provide a different abstraction.

An Example. This can get pretty confusing in the abstract, so let's do an example to show how it's pretty simple in practice. Smalltalk arrays tend to start at 1; let's define an array type whose permissible range is arbitrary.

     ArrayedCollection variableSubclass: 'RangedArray'
         instanceVariableNames: 'base'
         classVariableNames: ''
         poolDictionaries: ''
         category: nil !
     RangedArray comment: 'I am an Array whose base is arbitrary' !
     !RangedArray class methodsFor: 'creation'!
     new
         ^self error: 'Use new:base:'
     !
     new: size
         ^self new: size base: 1
     !
     new: size base: b
         ^(super new: size) init: b
     !!
     !RangedArray methodsFor: 'init'!
     init: b
         base := (b - 1).   "- 1 because basicAt: works with a 1 base"
         ^self
     !!
     !RangedArray methodsFor: 'basic'!
     rangeCheck: i
         ((i <= base) | (i > (base + (self basicSize)))) ifTrue: [
             'Bad index value: ' printOn: stderr.
             i printOn: stderr.
             (Character nl) printOn: stderr.
             ^self error: 'illegal index'
         ]
     !
     at: i
         self rangeCheck: i.
         ^self basicAt: (i-base)
     !
     at: i put: v
         self rangeCheck: i.
         ^self basicAt: (i-base) put: v
     !!

The code has two parts; an initialization, which simply records what index you wish the array to start with, and the at: messages, which adjust the requested index so that the underlying storage receives its 1-based index instead. We've included a range check; its utility will demonstrate itself in a moment:

     Smalltalk at: #a put: (RangedArray new: 10 base: 5) !
     a at: 5 put: 0 !
     a at: 4 put: 1 !

Since 4 is below our base of 5, a range check error occurs. But this check can catch more than just our own misbehavior!

     a do: [:x| x printNl] !

Our do: message handling is broken! The stack backtrace pretty much tells the story:

     RangedArray>>#rangeCheck:
     RangedArray>>#at:
     RangedArray>>#do:

Our code received a do: message. We didn't define one, so we inherited the existing do: handling. We see that an Integer loop was constructed, that a code block was invoked, and that our own at: code was invoked. When we range checked, we trapped an illegal index. Just by coincidence, this version of our range checking code also dumps the index. We see that do: has assumed that all arrays start at 1.

     The immediate fix is obvious; we implement our own do:
     !RangedArray methodsFor: 'basic'!
     do: aBlock
         1 to: (self basicSize) do: [:x|
             aBlock value: (self basicAt: x)
         ]
     !!

But the issues start to run deep. If our parent class believed that it knew enough to assume a starting index of 1 25, why didn't it also assume that it could call basicAt:?

Object-oriented methodology says that one object should be entirely opaque to another. But what sort of privacy should there be between a higher class and its subclasses? How many assumption can a subclass make about its superclass, and how many can the superclass make before it begins infringing on the sovereignty of its subclasses? Alas, there are rarely easy answers.

Basic Allocation. In this chapter, we've seen the fundamental mechanisms used to allocate and index storage. When the storage need not be accessed with peak efficiency, you can use the existing array classes. When every access counts, having the storage be an integral part of your own object allows for the quickest access. When you move into this area of object development, inheritance and polymorphism become trickier; each level must coordinate its use of the underlying array with other levels.


[ Next: | Previous:Inside Arrays | Up:Behind the scenes ]

Two flavors of equality

As first seen in chapter two, Smalltalk keys its dictionary with things like #word, whereas we generally use 'word'. The former, as it turns out, is from class Symbol. The latter is from class String. What's the real difference between a Symbol and a String? To answer the question, we'll use an analogy from C.

In C, if you have a function for comparing strings, you might try to write it:

     streq(char *p, char *q)
     {
         return (p == q);
     }

But clearly this is wrong! The reason is that you can have two copies of a string, each with the same contents but each at its own address. A correct string compare must walk its way through the strings and compare each element.

In Smalltalk, exactly the same issue exists, although the details of manipulating storage addresses are hidden. If we have two Smalltalk strings, both with the same contents, we don't necessarily know if they're at the same storage address. In Smalltalk terms, we don't know if they're the same object.

The Smalltalk dictionary is searched frequently. To speed the search, it would be nice to not have to compare the characters of each element, but only compare the address itself. To do this, you need to have a guarantee that all strings with the same contents are the same object. The String class, created like:

     y := 'Hello' !

does not satisfy this. Each time you execute this line, you may well get a new object. But a very similar class, Symbol, will always return the same object:

     y := #Hello !

In general, you can use strings for almost all your tasks. If you ever get into a performance-critical function which looks up strings, you can switch to Symbol. It takes longer to create a Symbol, and the memory for a Symbol is never freed (since the class has to keep tabs on it indefinitely to guarantee it continues to return the same object). You can use it, but use it with care.

This tutorial has generally used the strcmp()-ish kind of checks for equality. If you ever need to ask the question "is this the same object?", you use the == operator instead of =:

     Smalltalk at: #x put: 0 !
     Smalltalk at: #y put: 0 !
     x := 'Hello' !
     y := 'Hello' !
     (x = y) printNl !
     (x == y) printNl !
     y := 'Hel', 'lo' !
     (x = y) printNl !
     (x == y) printNl !
     x := #Hello !
     y := #Hello !
     (x = y) printNl !
     (x == y) printNl !

Using C terms, = compares contents like strcmp(). == compares storage addresses, like a pointer comparison.


[ Previous:Two flavors of equality | Up:Behind the scenes ]

The truth in Smalltalk performance

Everybody says Smalltalk is slow, yet this is not completely true for at least three reasons. First, most of the time in graphical applications is spent waiting for the user to "do something", and most of the time in scripting applications (which GNU Smalltalk is particularly well versed in) is spent in disk I/O; implementing a travelling salesman problem in Smalltalk would indeed be slow, but for most real applications you can indeed exchange performance for Smalltalk's power and development speed.

Second, Smalltalk's automatic memory management is faster than C's manual one. Most C programs are sped up if you relink them with one of the garbage collecting systems available for C or C++.

Third, even though very few Smalltalk virtual machines are as optimized as, say, the Self environment (which reaches half the speed of optimized C!), they do perform some optimizations on Smalltalk code which would make them run at least twice as fast with respect to basic, non-optimized bytecodes. Let's look at some of these optimizations.

For certain frequently used 'special selectors', the compiler emits a send-special-selector bytecode instead of a send-message bytecode. Special selectors were created because they offer two advantages. First, code which sends special selectors compiles into fewer bytes than normal. Second, for some pairs of receiver classes and special selectors, the interpreter jumps directly to a primitive routine without looking up the method in the class: this is much faster than a normal message lookup.

A selector which is a special selector solely in order to save space has a normal behavior. But when the interpreter has to send a message which is a special selector in order to gain speed, it checks the class of the receiver and its arguments, and the selector. If the class-selector pair is a no-lookup pair, then the interpreter swiftly executes the same code which is tied to the corresponding primitive. (A special selector whose receiver or argument is not of the right class to make a no-lookup pair, is looked up normally). The pairs are listed below. No-lookup methods contain a primitive number specification, <primitive: xx>, but it is used only when the method is reached through a #perform:... message send. Since the method is not normally looked up, deleting the primitive number specification cannot in general prevent this primitive from running. No-lookup primitive can't fail, because they're executed only if they're guaranteed to succeed; for example, the / primitive for Integers fails if there is a remainder, so it does not constitute a no-lookup pair.

    Integer/Integer or Float/Float for   + - * =  ~=  >  <  >=  <=
    Integer/Integer for                  //  \\     bitOr:  bitShift:  bitAnd:
    Any class with any of                ==  isNil  notNil  yourself

Other messages are open coded by the compiler. That is, there are no message sends for these messages - if the compiler sees blocks without temporaries and with the correct number of arguments at the right places, the compiler unwinds them using jump bytecodes, producing very efficient code. These are:

    to:by:do: if the second arg. is an integer literal
    to:do:
    timesRepeat:
    and:, or:
    ifTrue:ifFalse:, ifFalse:ifTrue:, ifTrue:, ifFalse:
    whileTrue:, whileFalse:

Other minor optimizations are done. Some are done by a peephole optimizer which is ran on the compiled bytecodes. Or, for example, when GST pushes a boolean value on the stack, it automatically checks whether the following bytecode is a jump (which is a common pattern resulting from most of the open-coded messages above) and combines the execution of the two bytecodes. All these snippets can be optimized this way:

    1 to: 5 do: [ :i | ... ]
    a < b and: [ ... ]
    myObject isNil ifTrue: [ ... ]

That's all. If you want to know more, look at the virtual machine's source code in lib/interp.c.


[ Next: | Previous:Behind the scenes | Up:Tutorial ]

Some final words

The question is always how far to go in one document. At this point, you know how to create classes. You know how to use inheritance, polymorphism, and the basic storage management mechanisms of Smalltalk. You've also seen a sampling of Smalltalk's powerful classes. The rest of this chapter simply points out areas for further study; perhaps a newer version of this document might cover these in further chapters.


Viewing the Smalltalk Source Code
Lots of experience can be gained by looking at the source code for system methods; all of them are visible: data structure classes, the innards of the magic that makes classes be themselves objects and have a class, a compiler written in Smalltalk itself, the classes that implement the Smalltalk GUI and those that wrap sockets and TCP/IP.


Other Ways to Collect Objects
We've seen Array, ByteArray, Dictionary, Set, and the various streams. You'll want to look at the Bag, OrderedCollection, and SortedCollection classes. For special purposes, you'll want to examine the CObject and CType hierarchies.


Flow of Control
GNU Smalltalk has rudimentary support for threads of execution. The state is embodied in a Process class object; you'll also want to look at the Semaphore and ProcessorScheduler class.


Smalltalk Virtual Machine
GNU Smalltalk is implemented as a virtual instruction set. By invoking GNU Smalltalk with the -d option, you can view the byte opcodes which are generated as files on the command line are loaded. Similarly, running GNU Smalltalk with -e will trace the execution of instructions in your methods.

You can look at the GNU Smalltalk source to gain more information on the instruction set. A better first step if you want to pursue this subject is to start with A Little Smalltalk by Tim Budd. The source code is freely available, and the book provides a solid introduction to Smalltalk-type virtual machines; alas, Little Smalltalk is designed for compactness, not for being a full implementation of Smalltalk. So you might want to look at the canonical book is from the original designers of Smalltalk: Smalltalk-80: The Language and its Implementation, by Adele Goldberg and David Robson.


Where to get Help
The newsgroup comp.lang.smalltalk is read by many people with a great deal of Smalltalk experience. There are several commercial Smalltalk implementations; you can buy support for these, though it isn't cheap. For the GNU Smalltalk system in particular, you can try the author at:
     jtk@netcom.com

No guarantees, but the author will do his best!


[ Previous:And now | Up:Tutorial ]

A Simple Overview of Smalltalk Syntax

Smalltalk's power comes from its treatment of objects. In this document, we've mostly avoided the issue of syntax by using strictly parenthesized expressions as needed. When this leads to code which is hard to read due to the density of parentheses, a knowledge of Smalltalk's syntax can let you simplify expressions. In general, if it was hard for you to tell how an expression would parse, it will be hard for the next person, too.

The following presentation presents the grammar a couple of related elements at a time. We use an EBNF style of grammar. The form:

     [ ... ]

means that "..." can occur zero or one times.

     [ ... ]*

means zero or more;

     [ ... ]+

means one or more.

     ... | ... [ | ... ]*

means that one of the variants must be chosen. Characters in double quotes refer to the literal characters. Most elements may be separated by white space; where this is not legal, the elements are presented without white space between them.


methods: "!" id ["class"] "methodsFor:" string "!" [method "!"] "!"
Methods are introduced by first naming a class (the id element), specifying "class" if you're adding class methods instead of instance methods, and sending a string argument to the methodsFor: message. Each method is terminated with an "!"; two "!"'s in a row signify the end of the new methods.
method: message [prim] [temps] exprs
message: id | binsel id | [keysel id]+
prim: "<" "primitive:" number ">"
temps: "|" [id]* "|"
A method definition starts out with a kind of template. The message to be handled is specified with the message names spelled out and identifiers in the place of arguments. A special kind of definition is the primitive; it has not been covered in this tutorial; it provides an interface to the underlying Smalltalk virtual machine. temps is the declaration of local variables. Finally, exprs (covered soon) is the actual code for implementing the method.
unit: id | literal | block | "(" expr ")"
unaryexpr: unit [ id ]+
primary: unit | unaryexpr
These are the "building blocks" of Smalltalk expressions. A unit represents a single Smalltalk value, with the highest syntactic precedence. A unaryexpr is simply a unit which receives a number of unary messages. A unaryexpr has the next highest precedence. A primary is simply a convenient left-hand-side name for one of the above.
exprs: [expr "."]* [["^"] expr]
expr: [id ":="]* expr2
expr2: primary | msgexpr [ ";" cascade ]*
A sequence of expressions is separated by dots and can end with a returned value (^). There can be leading assignments; unlike C, assignments apply only to simple variable names. An expression is either a primary (with highest precedence) or a more complex message. cascade does not apply to primary constructions, as they are too simple to require the construct. Since all primary construct are unary, you can just add more unary messages:
     1234 printNl printNl printNl !

msgexpr: unaryexpr | binexpr | keyexpr
A complex message is either a unary message (which we have already covered), a binary message ("+", "-", and so forth), or a keyword message ("at:", "new:", ....) Unary has the highest precedence, followed by binary, and keyword messages have the lowest precedence. Examine the two versions of the following messages. The second have had parentheses added to show the default precedence.
     myvar at: 2 + 3 put: 4
     mybool ifTrue: [ ^ 2 / 4 roundup ]

     (myvar at: (2 + 3) put: (4))
     (mybool ifTrue: ([ ^ (2 / (4 roundup)) ]))

cascade: id | binmsg | keymsg
A cascade is used to direct further messages to the same object which was last used. The three types of messages ( id is how you send a unary message) can thus be sent.
binexpr: primary binmsg [ binmsg ]*
binmsg: binsel primary
binsel: selchar[selchar]
A binary message is sent to an object, which primary has identified. Each binary message is a binary selector, constructed from one or two characters, and an argument which is also provided by a primary.
     1 + 2 - 3 / 4

which parses as:

     (((1 + 2) - 3) / 4)

keyexpr: keyexpr2 keymsg
keyexpr2: binexpr | primary
keymsg: [keysel keyw2]+
keysel: id":"
Keyword expressions are much like binary expressions, except that the selectors are made up of identifiers with a colon appended. Where the arguments to a binary function can only be from primary, the arguments to a keyword can be binary expressions or primary ones. This is because keywords have the lowest precedence.
block: "[" [[":" id]* "|" ] exprs "]"
A code block is square brackets around a collection of Smalltalk expressions. The leading ": id" part is for block arguments.
literal: number | string | charconst | symconst | arrayconst
arrayconst: "#" array
array: "(" [number | string | symbol | array | charconst]* ")"
number: [[dig]+ "r"] ["-"] [alphanum]+ ["." [alphanum]+] ["e"["-"][dig]+].
string: "'"[char]*"'"
charconst: "$"char
symconst: "$"symbol
We have already shown the use of many of these constants. Although not covered in this tutorial, numbers can have a base specified at their front, and a trailing scientific notation. We have seen examples of character, string, and symbol constants. Array constants are simple enough; they would look like:
     Smalltalk at: #a put: #(1 2 'Hi' $x $Hello 4 26r5H) !

symbol: id | binsel | keysel[keysel]*
Symbols are mostly used to represent the names of methods. Thus, they can hold simple identifiers, binary selectors, and keyword selectors:
     #hello
     #+
     #at:put:

id: letter[letter|dig]*
selchar: "+" | "-" | "*" | "/" | "~" | "|" | "," |
"<" | ">" | "=" | "&"
alphanum: "0".."9" | "A".."Z"
dig: "0".."9"
These are the categories of characters and how they are combined at the most basic level. selchar simply lists the characters which can be combined to name a binary message.


[ Next: | Previous:Tutorial | Up:Top ]

Class reference

{No Value For "

BEFORE1"}Object{No Value For "AFTER1"} {No Value For "BEFORE1"} Behavior{No Value For "AFTER1"} {No Value For "BEFORE1"} ClassDescription{No Value For "AFTER1"} {No Value For "BEFORE1"} Class{No Value For "AFTER1"} {No Value For "BEFORE1"} Metaclass{No Value For "AFTER1"} {No Value For "BEFORE1"} BlockClosure{No Value For "AFTER1"} {No Value For "BEFORE1"} Boolean{No Value For "AFTER1"} {No Value For "BEFORE1"} False{No Value For "AFTER1"} {No Value For "BEFORE1"} True{No Value For "AFTER1"} {No Value For "BEFORE1"} Browser{No Value For "AFTER1"} {No Value For "BEFORE1"} CFunctionDescriptor{No Value For "AFTER1"} {No Value For "BEFORE1"} CObject{No Value For "AFTER1"} {No Value For "BEFORE1"} CAggregate{No Value For "AFTER1"} {No Value For "BEFORE1"} CArray{No Value For "AFTER1"} {No Value For "BEFORE1"} CPtr{No Value For "AFTER1"} {No Value For "BEFORE1"} CScalar{No Value For "AFTER1"} {No Value For "BEFORE1"} CChar{No Value For "AFTER1"} {No Value For "BEFORE1"} CDouble{No Value For "AFTER1"} {No Value For "BEFORE1"} CFloat{No Value For "AFTER1"} {No Value For "BEFORE1"} CInt{No Value For "AFTER1"} {No Value For "BEFORE1"} CLong{No Value For "AFTER1"} {No Value For "BEFORE1"} CShort{No Value For "AFTER1"} {No Value For "BEFORE1"} CSmalltalk{No Value For "AFTER1"} {No Value For "BEFORE1"} CString{No Value For "AFTER1"} {No Value For "BEFORE1"} CUChar{No Value For "AFTER1"} {No Value For "BEFORE1"} CByte{No Value For "AFTER1"} {No Value For "BEFORE1"} CBoolean{No Value For "AFTER1"} {No Value For "BEFORE1"} CUInt{No Value For "AFTER1"} {No Value For "BEFORE1"} CULong{No Value For "AFTER1"} {No Value For "BEFORE1"} CUShort{No Value For "AFTER1"} {No Value For "BEFORE1"} CStruct{No Value For "AFTER1"} {No Value For "BEFORE1"} Collection{No Value For "AFTER1"} {No Value For "BEFORE1"} Bag{No Value For "AFTER1"} {No Value For "BEFORE1"} MappedCollection{No Value For "AFTER1"} {No Value For "BEFORE1"} SequenceableCollection{No Value For "AFTER1"} {No Value For "BEFORE1"} ArrayedCollection{No Value For "AFTER1"} {No Value For "BEFORE1"} Array{No Value For "AFTER1"} {No Value For "BEFORE1"} ByteArray{No Value For "AFTER1"} {No Value For "BEFORE1"} CompiledMethod{No Value For "AFTER1"} {No Value For "BEFORE1"} Interval{No Value For "AFTER1"} {No Value For "BEFORE1"} String{No Value For "AFTER1"} {No Value For "BEFORE1"} Symbol{No Value For "AFTER1"} {No Value For "BEFORE1"} LinkedList{No Value For "AFTER1"} {No Value For "BEFORE1"} Semaphore{No Value For "AFTER1"} {No Value For "BEFORE1"} OrderedCollection{No Value For "AFTER1"} {No Value For "BEFORE1"} RunArray{No Value For "AFTER1"} {No Value For "BEFORE1"} SortedCollection{No Value For "AFTER1"} {No Value For "BEFORE1"} Set{No Value For "AFTER1"} {No Value For "BEFORE1"} Dictionary{No Value For "AFTER1"} {No Value For "BEFORE1"} IdentityDictionary{No Value For "AFTER1"} {No Value For "BEFORE1"} SystemDictionary{No Value For "AFTER1"} {No Value For "BEFORE1"} IdentitySet{No Value For "AFTER1"} {No Value For "BEFORE1"} ContextPart{No Value For "AFTER1"} {No Value For "BEFORE1"} BlockContext{No Value For "AFTER1"} {No Value For "BEFORE1"} MethodContext{No Value For "AFTER1"} {No Value For "BEFORE1"} CType{No Value For "AFTER1"} {No Value For "BEFORE1"} CArrayCType{No Value For "AFTER1"} {No Value For "BEFORE1"} CPtrCType{No Value For "AFTER1"} {No Value For "BEFORE1"} CScalarCType{No Value For "AFTER1"} {No Value For "BEFORE1"} Delay{No Value For "AFTER1"} {No Value For "BEFORE1"} DLD{No Value For "AFTER1"} {No Value For "BEFORE1"} DumperProxy{No Value For "AFTER1"} {No Value For "BEFORE1"} ExceptionHandler{No Value For "AFTER1"} {No Value For "BEFORE1"} File{No Value For "AFTER1"} {No Value For "BEFORE1"} Directory{No Value For "AFTER1"} {No Value For "BEFORE1"} FileSegment{No Value For "AFTER1"} {No Value For "BEFORE1"} Link{No Value For "AFTER1"} {No Value For "BEFORE1"} Process{No Value For "AFTER1"} {No Value For "BEFORE1"} SymLink{No Value For "AFTER1"} {No Value For "BEFORE1"} Magnitude{No Value For "AFTER1"} {No Value For "BEFORE1"} Association{No Value For "AFTER1"} {No Value For "BEFORE1"} Character{No Value For "AFTER1"} {No Value For "BEFORE1"} Date{No Value For "AFTER1"} {No Value For "BEFORE1"} Number{No Value For "AFTER1"} {No Value For "BEFORE1"} Float{No Value For "AFTER1"} {No Value For "BEFORE1"} Fraction{No Value For "AFTER1"} {No Value For "BEFORE1"} Integer{No Value For "AFTER1"} {No Value For "BEFORE1"} LargeInteger{No Value For "AFTER1"} {No Value For "BEFORE1"} LargeNegativeInteger{No Value For "AFTER1"} {No Value For "BEFORE1"} LargePositiveInteger{No Value For "AFTER1"} {No Value For "BEFORE1"} LargeZeroInteger{No Value For "AFTER1"} {No Value For "BEFORE1"} Time{No Value For "AFTER1"} {No Value For "BEFORE1"} Memory{No Value For "AFTER1"} {No Value For "BEFORE1"} ByteMemory{No Value For "AFTER1"} {No Value For "BEFORE1"} WordMemory{No Value For "AFTER1"} {No Value For "BEFORE1"} Message{No Value For "AFTER1"} {No Value For "BEFORE1"} DirectedMessage{No Value For "AFTER1"} {No Value For "BEFORE1"} MethodInfo{No Value For "AFTER1"} {No Value For "BEFORE1"} NullProxy{No Value For "AFTER1"} {No Value For "BEFORE1"} PackageLoader{No Value For "AFTER1"} {No Value For "BEFORE1"} Point{No Value For "AFTER1"} {No Value For "BEFORE1"} ProcessorScheduler{No Value For "AFTER1"} {No Value For "BEFORE1"} Rectangle{No Value For "AFTER1"} {No Value For "BEFORE1"} SharedQueue{No Value For "AFTER1"} {No Value For "BEFORE1"} Signal{No Value For "AFTER1"} {No Value For "BEFORE1"} Stream{No Value For "AFTER1"} {No Value For "BEFORE1"} ObjectDumper{No Value For "AFTER1"} {No Value For "BEFORE1"} PositionableStream{No Value For "AFTER1"} {No Value For "BEFORE1"} ReadStream{No Value For "AFTER1"} {No Value For "BEFORE1"} WriteStream{No Value For "AFTER1"} {No Value For "BEFORE1"} ReadWriteStream{No Value For "AFTER1"} {No Value For "BEFORE1"} ByteStream{No Value For "AFTER1"} {No Value For "BEFORE1"} FileStream{No Value For "AFTER1"} {No Value For "BEFORE1"} Random{No Value For "AFTER1"} {No Value For "BEFORE1"} TokenStream{No Value For "AFTER1"} {No Value For "BEFORE1"} TranscriptInterface{No Value For "AFTER1"} {No Value For "BEFORE1"} TrappableEvent{No Value For "AFTER1"} {No Value For "BEFORE1"} Exception{No Value For "AFTER1"} {No Value For "BEFORE1"} ExceptionCollection{No Value For "AFTER1"} {No Value For "BEFORE1"} UndefinedObject{No Value For "AFTER1"} {No Value For "BEFORE1"} ValueAdaptor{No Value For "AFTER1"} {No Value For "BEFORE1"} NullValueHolder{No Value For "AFTER1"} {No Value For "BEFORE1"} PluggableAdaptor{No Value For "AFTER1"} {No Value For "BEFORE1"} DelayedAdaptor{No Value For "AFTER1"} {No Value For "BEFORE1"} ValueHolder{No Value For "AFTER1"}


[ ]

Array

Category: Collections-Sequenceable
My instances are objects that have array-like properties: they are directly indexable by integers starting at 1, and they are fixed in size. I inherit object creation behavior messages such as #with:, as well as iteration and general access behavior from SequenceableCollection.


[ Next: | Up:Array ]

Array: built ins

at: anIndex
Answer the index-th indexed instance variable of the receiver.


at: anIndex put: value
Store value in the index-th indexed instance variable of the receiver


basicAt: anIndex
Answer the index-th indexed instance variable of the receiver. This method must not be overridden, override at: instead


basicAt: anIndex put: value
Store value in the index-th indexed instance variable of the receiver This method must not be overridden, override at:put: instead


[ Next: | Previous:Array-built ins | Up:Array ]

Array: mutating objects

multiBecome: anArray
Transform every object in the receiver in each corresponding object in anArray. anArray and the receiver must have the same size


[ Next: | Previous:Array-mutating objects | Up:Array ]

Array: printing

printOn: aStream
Print a representation for the receiver on aStream


[ Previous:Array-printing | Up:Array ]

Array: testing

isArray
Answer `false'.


[ ]

ArrayedCollection

Category: Collections-Sequenceable
My instances are objects that are generally fixed size, and are accessed by an integer index. The ordering of my instance's elements is determined externally; I will not rearrange the order of the elements.


[ Next: | Up:ArrayedCollection ]

ArrayedCollection class: instance creation

new
Answer an empty collection


new: size withAll: anObject
Answer a collection with the given size, whose elements are all set to anObject


with: element1
Answer a collection whose only element is element1


with: element1 with: element2
Answer a collection whose only elements are the parameters in the order they were passed


with: element1 with: element2 with: element3
Answer a collection whose only elements are the parameters in the order they were passed


with: element1 with: element2 with: element3 with: element4
Answer a collection whose only elements are the parameters in the order they were passed


withAll: aCollection
Answer a collection whose elements are the same as those in aCollection


[ Next: | Previous:ArrayedCollection class-instance creation | Up:ArrayedCollection ]

ArrayedCollection: basic

, aSequenceableCollection
Answer a new instance of an ArrayedCollection containing all the elements in the receiver, followed by all the elements in aSequenceableCollection


add: value
This method should not be called for instances of this class.


copyWithout: oldElement
Answer a copy of the receiver to which all occurrences of oldElement are removed


[ Next: | Previous:ArrayedCollection-basic | Up:ArrayedCollection ]

ArrayedCollection: built ins

size
Answer the size of the receiver


[ Next: | Previous:ArrayedCollection-built ins | Up:ArrayedCollection ]

ArrayedCollection: copying Collections

copyWith: newElement
Answer a new instance of an ArrayedCollection containing all the receiver's elements and, at the end, newElement


reverse
Answer the receivers' contents in reverse order


[ Next: | Previous:ArrayedCollection-copying Collections | Up:ArrayedCollection ]

ArrayedCollection: enumerating the elements of a collection

collect: aBlock
Answer a new instance of an ArrayedCollection containing all the results of evaluating aBlock passing each of the receiver's elements


reject: aBlock
Answer a new instance of an ArrayedCollection containing all the elements in the receiver which, when passed to aBlock, answer false


select: aBlock
Answer a new instance of an ArrayedCollection containing all the elements in the receiver which, when passed to aBlock, answer true


[ Previous:ArrayedCollection-enumerating the elements of a collection | Up:ArrayedCollection ]

ArrayedCollection: storing

storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ ]

Association

Category: Language-Data types
My instances represent a mapping between two objects. Typically, my "key" object is a symbol, but I don't require this. My "value" object has no conventions associated with it; it can be any object at all.


[ Next: | Up:Association ]

Association class: basic

key: aKey value: aValue
Answer a new association with the given key and value


[ Next: | Previous:Association class-basic | Up:Association ]

Association: accessing

key
Answer the association's key


key: aKey value: aValue
Set the association's key to aKey, and its value to aValue


value
Answer the association's value


value: aValue
Set the association's value to aValue


[ Next: | Previous:Association-accessing | Up:Association ]

Association: printing

printOn: aStream
Put on aStream a representation of the receiver


[ Next: | Previous:Association-printing | Up:Association ]

Association: storing

storeOn: aStream
Put on aStream some Smalltalk code compiling to the receiver


[ Previous:Association-storing | Up:Association ]

Association: testing

< anAssociation
Answer whether the association's key is less than anAssociation's


= anAssociation
Answer whether the association's key and value are the same as anAssociation's, or false if anAssociation is not an Association


hash
Answer an hash value for the receiver


[ ]

Bag

Category: Collections-Unordered
My instances are unordered collections of objects. You can think of me as a set with a memory; that is, if the same object is added to me twice, then I will report that that element has been stored twice.


[ Next: | Up:Bag ]

Bag class: basic

new
Answer a new instance of the receiver


[ Next: | Previous:Bag class-basic | Up:Bag ]

Bag: Adding to a collection

add: newObject
Add an occurrence of newObject to the receiver. Answer newObject


add: newObject withOccurrences: anInteger
If anInteger > 0, add anInteger occurrences of newObject to the receiver. If anInteger < 0, remove them. Answer newObject


[ Next: | Previous:Bag-Adding to a collection | Up:Bag ]

Bag: enumerating the elements of a collection

do: aBlock
Evaluate the block for all members in the collection.


[ Next: | Previous:Bag-enumerating the elements of a collection | Up:Bag ]

Bag: printing

printOn: aStream
Put on aStream a representation of the receiver


[ Next: | Previous:Bag-printing | Up:Bag ]

Bag: Removing from a collection

remove: oldObject ifAbsent: anExceptionBlock
Remove oldObject from the collection and return it. If can't be found, answer instead the result of evaluationg anExceptionBlock


[ Next: | Previous:Bag-Removing from a collection | Up:Bag ]

Bag: storing

storeOn: aStream
Put on aStream some Smalltalk code compiling to the receiver


[ Previous:Bag-storing | Up:Bag ]

Bag: testing collections

= aBag
Answer whether the receiver and aBag contain the same objects


hash
Answer an hash value for the receiver


occurrencesOf: anObject
Answer the number of occurrences of anObject found in the receiver


size
Answer the total number of objects found in the receiver


[ ]

Behavior

Category: Language-Implementation
I am the parent class of all "class" type methods. My instances know about the subclass/superclass relationships between classes, contain the description that instances are created from, and hold the method dictionary that's associated with each class. I provide methods for compiling methods, modifying the class inheritance hierarchy, examining the method dictionary, and iterating over the class hierarchy.


[ Next: | Up:Behavior ]

Behavior class: C interface

defineCFunc: cFuncNameString
withSelectorArgs: selectorAndArgs forClass: aClass returning: returnTypeSymbol args: argsArray Lookup the part on the C interface in this manual - it is too complex to describe it here ;-) Anyway this is private and kept for backward com- patibility. You should use defineCFunc:withSelectorArgs:returning:args: which also checks if the function is present in the DLD libraries.


[ Next: | Previous:Behavior class-C interface | Up:Behavior ]

Behavior class: creating lightweight classes

new
Create a new class. Having an instanceSpec defined this way won't be very useful, but at least it doesn't result in access violations!


[ Next: | Previous:Behavior class-creating lightweight classes | Up:Behavior ]

Behavior: accessing class hierarchy

allSubclasses
Answer the direct and indirect subclasses of the receiver in a Set


allSuperclasses
Answer all the receiver's superclasses in a collection


subclasses
Answer the direct subclasses of the receiver in a Set


superclass
Answer the receiver's superclass (if any, otherwise answer nil)


withAllSubclasses
Answer a Set containing the receiver together with its direct and indirect subclasses


withAllSuperclasses
Answer the receiver and all of its superclasses in a collection


[ Next: | Previous:Behavior-accessing class hierarchy | Up:Behavior ]

Behavior: accessing instances and variables

allClassVarNames
Return all the class variables understood by the receiver


allInstances
Returns a set of all instances of the receiver - you might get some nils in it: just discard them.


allInstVarNames
Answer all the instance variables for instances of the receiver


allSharedPools
Return the names of the shared pools defined by the class and any of its superclasses


classPool
Answer the class pool dictionary. Since Behavior does not support classes with class variables, we answer an empty one; adding variables to it results in an error.


classVarNames
Answer all the class variables for instances of the receiver


instanceCount
Return a count of all the instances of the receiver


instVarNames
Return all the instance variables added to the hierarchy by the receiver


sharedPools
Return the names of the shared pools defined by the class


subclassInstVarNames
Return all the instance variables inherited from the hierarchy by the receiver


[ Next: | Previous:Behavior-accessing instances and variables | Up:Behavior ]

Behavior: accessing the methodDictionary

>> selector
Return the compiled method associated with selector, from the local method dictionary. Error if not found.


allSelectors
Answer a Set of all the selectors understood by the receiver


compiledMethodAt: selector
Return the compiled method associated with selector, from the local method dictionary. Error if not found.


selectorAt: method
Return selector for the given compiledMethod


selectors
Answer a Set of the receiver's selectors


sourceCodeAt: selector
Answer source code (if available) for the given compiledMethod


sourceMethodAt: selector
This is too dependent on the original implementation


[ Next: | Previous:Behavior-accessing the methodDictionary | Up:Behavior ]

Behavior: browsing

getAllMethods
Answer the receiver's complete method dictionary - including inherited and not overridden methods. Each value in the dictionary is an Association, whose key is the class which defines the method, and whose value is the actual CompiledMethod


getDirectMethods
Answer the receiver's method dictionary; each value in the dictionary is not a CompiledMethod, but an Association, whose key is the class which defines the method (always the receiver), and whose value is the actual CompiledMethod


getIndirectMethods
Answer a dictionary of the receiver's inherited and not overridden methods. Each value in the dictionary is an Association, whose key is the class which defines the method, and whose value is the actual CompiledMethod


getMethods
Answer the receiver's complete method dictionary - including inherited and not overridden methods


getMethodsFor: aSelector
Get a dictionary with all the definitions of the given selector along the hierarchy. Each key in the dictionary is a class which defines the method, and each value in the dictionary is an Association, whose key is the class again, and whose value is the actual CompiledMethod


methodDictionary
Answer the receiver's method dictionary


newGetMethods
Answer the receiver's complete method dictionary - including inherited and not overridden methods. Each value in the dictionary is an Association, whose key is the class which defines the method, and whose value is the actual CompiledMethod


[ Next: | Previous:Behavior-browsing | Up:Behavior ]

Behavior: built ins

basicNew
Create a new instance of a class with no indexed instance variables


basicNew: numInstanceVariables
Create a new instance of a class with indexed instance variables. The instance has numInstanceVariables indexed instance variables.


compileString: aString
Compile the code in aString, with no category. Fail if the code does not obey Smalltalk syntax. Answer the generated CompiledMethod if it does


compileString: aString ifError: aBlock
Compile the code in aString, with no category. Evaluate aBlock (passing the file name, line number and description of the error) if the code does not obey Smalltalk syntax. Answer the generated CompiledMethod if it does


flushCache
Invalidate the method cache kept by the virtual machine. This message should not need to be called by user programs.


makeDescriptorFor: funcNameString
returning: returnTypeSymbol withArgs: argsArray Private - Answer a CFunctionDescriptor


methodsFor: category ifTrue: condition
Compile the following code inside the receiver, with the given category, if condition is true; else ignore it


new
Create a new instance of a class with no indexed instance variables


new: numInstanceVariables
Create a new instance of a class with indexed instance variables. The instance has numInstanceVariables indexed instance variables.


someInstance
Private - Answer the first instance of the receiver in the object table


[ Next: | Previous:Behavior-built ins | Up:Behavior ]

Behavior: C callout

defineCFunc: cFuncName
withSelectorArgs: selector returning: aReturnType args: argsArray Too complex to describe it here - Look up the C interface in the manual.


[ Next: | Previous:Behavior-C callout | Up:Behavior ]

Behavior: compilation (alternative)

methods
Don't use this, it's only present to file in from Smalltalk/V


methodsFor
Don't use this, it's only present to file in from Dolphin Smalltalk


methodsFor: category ifFeatures: features
Start compiling methods in the receiver if this implementation of Smalltalk has the given features, else skip the section


methodsFor: category stamp: notUsed
Don't use this, it's only present to file in from Squeak


privateMethods
Don't use this, it's only present to file in from IBM Smalltalk


publicMethods
Don't use this, it's only present to file in from IBM Smalltalk


[ Next: | Previous:Behavior-compilation (alternative) | Up:Behavior ]

Behavior: creating a class hierarchy

addSubclass: aClass
Add aClass asone of the receiver's subclasses.


removeSubclass: aClass
Remove aClass from the list of the receiver's subclasses


superclass: aClass
Set the receiver's superclass.


[ Next: | Previous:Behavior-creating a class hierarchy | Up:Behavior ]

Behavior: creating method dictionary

addSelector: selector withMethod: compiledMethod
Add the given compiledMethod to the method dictionary, giving it the passed selector. Answer compiledMethod


compile: code
Compile method source. If there are parsing errors, answer nil. Else, return a CompiledMethod result of compilation


compile: code ifError: block
Compile method source. If there are parsing errors, invoke exception block, 'block' passing file name, line number and error. description. Return a CompiledMethod result of compilation


compile: code notifying: requestor
Compile method source. If there are parsing errors, send #error: to the requestor object, else return a CompiledMethod result of compilation


compileAll
Recompile all selectors in the receiver. Ignore errors.


compileAll: aNotifier
Recompile all selectors in the receiver. Notify aNotifier by sen- ding #error: messages if something goes wrong.


compileAllSubclasses
Recompile all selector of all subclasses. Notify aNotifier by sen- ding #error: messages if something goes wrong.


compileAllSubclasses: aNotifier
Recompile all selector of all subclasses. Notify aNotifier by sen- ding #error: messages if something goes wrong.


createGetMethod: what
Create a method accessing the variable `what'.


createGetMethod: what default: value
Create a method accessing the variable `what', with a default value of `value', using lazy initialization


createSetMethod: what
Create a method which sets the variable `what'.


decompile: selector
Decompile the bytecodes for the given selector.


edit: selector
Open Emacs to edit the method with the passed selector, then compile it


methodDictionary: aDictionary
Set the receiver's method dictionary to aDictionary


recompile: selector
Recompile the given selector, answer nil if something goes wrong or the new CompiledMethod if everything's ok.


recompile: selector notifying: aNotifier
Recompile the given selector. If there are parsing errors, send #error: to the aNotifier object, else return a CompiledMethod result of compilation


removeSelector: selector
Remove the given selector from the method dictionary, answer the CompiledMethod attached to that selector


removeSelector: selector ifAbsent: aBlock
Remove the given selector from the method dictionary, answer the CompiledMethod attached to that selector. If the selector cannot be found, answer the result of evaluating aBlock.


[ Next: | Previous:Behavior-creating method dictionary | Up:Behavior ]

Behavior: enumerating

allInstancesDo: aBlock
Invokes aBlock for all instances of the receiver


allSubclassesDo: aBlock
Invokes aBlock for all subclasses, both direct and indirect.


allSubinstancesDo: aBlock
Invokes aBlock for all instances of each of the receiver's subclasses.


allSuperclassesDo: aBlock
Invokes aBlock for all superclasses, both direct and indirect.


selectSubclasses: aBlock
Return a Set of subclasses of the receiver satisfying aBlock.


selectSuperclasses: aBlock
Return a Set of superclasses of the receiver satisfying aBlock.


subclassesDo: aBlock
Invokes aBlock for all direct subclasses.


withAllSubclassesDo: aBlock
Invokes aBlock for the receiver and all subclasses, both direct and indirect.


withAllSuperclassesDo: aBlock
Invokes aBlock for the receiver and all superclasses, both direct and indirect.


[ Next: | Previous:Behavior-enumerating | Up:Behavior ]

Behavior: evaluating

evalString: aString to: anObject
Answer the stack top at the end of the evaluation of the code in aString. The code is executed as part of anObject


evalString: aString to: anObject ifError: aBlock
Answer the stack top at the end of the evaluation of the code in aString. If aString cannot be parsed, evaluate aBlock (see compileString:ifError:). The code is executed as part of anObject


evaluate: code
Evaluate Smalltalk expression in 'code' and return result.


evaluate: code ifError: block
Evaluate 'code'. If a parsing error is detected, invoke 'block'


evaluate: code notifying: requestor
Evaluate Smalltalk expression in 'code'. If a parsing error is encountered, invoke error block, 'block'


evaluate: code to: anObject
Evaluate Smalltalk expression as part of anObject's method definition


evaluate: code to: anObject ifError: block
Evaluate Smalltalk expression as part of anObject's method definition. This method is used to support Inspector expression evaluation. If a parsing error is encountered, invoke error block, 'block'


[ Next: | Previous:Behavior-evaluating | Up:Behavior ]

Behavior: hierarchy browsing

printHierarchy
Print my entire subclass hierarchy on the terminal.


printHierarchyEmacs
Print my entire subclass hierarchy on the terminal, in a format suitable for Emacs parsing.


[ Next: | Previous:Behavior-hierarchy browsing | Up:Behavior ]

Behavior: support for lightweight classes

name
Answer the class name - a dummy one, since Behavior does not support names. This class name is used, for example, to print the receiver.


[ Next: | Previous:Behavior-support for lightweight classes | Up:Behavior ]

Behavior: testing the class hierarchy

inheritsFrom: aClass
Returns true if aClass is a superclass of the receiver


kindOfSubclass
Return a string indicating the type of class the receiver is


[ Next: | Previous:Behavior-testing the class hierarchy | Up:Behavior ]

Behavior: testing the form of the instances

instSize
Answer how many fixed instance variables are reserved to each of the receiver's instances


isBits
Answer whether the instance variables of the receiver's instances are bytes or words


isBytes
Answer whether the instance variables of the receiver's instances are bytes


isFixed
Answer whether the receiver's instances have no indexed instance variables


isIdentity
Answer whether x = y implies x == y for instances of the receiver


isImmediate
Answer whether, if x is an instance of the receiver, x copy == x


isPointers
Answer whether the instance variables of the receiver's instances are objects


isVariable
Answer whether the receiver's instances have indexed instance variables


isWords
Answer whether the instance variables of the receiver's instances are words


[ Previous:Behavior-testing the form of the instances | Up:Behavior ]

Behavior: testing the method dictionary

canUnderstand: selector
Returns true if the instances of the receiver understand the given selector


hasMethods
Return whether the receiver has any methods defined


includesSelector: selector
Returns true if the local method dictionary contains the given selector


scopeHas: name ifTrue: aBlock
If methods understood by the receiver's instances have access to a symbol named 'name', evaluate aBlock


whichClassIncludesSelector: selector
Answer which class in the receiver's hierarchy contains the implementation of selector used by instances of the class (nil if none does)


whichSelectorsAccess: instVarName
Answer a Set of selectors which access the given instance variable


whichSelectorsReferTo: anObject
Returns a Set of selectors that refer to anObject


whichSelectorsReferToByteCode: aByteCode
Return the collection of selectors in the class which reference the byte code, aByteCode


[ ]

BlockClosure

Category: Language-Implementation
I am a factotum class. My instances represent Smalltalk blocks, portions of executeable code that have access to the environment that they were declared in, take parameters, and can be passed around as objects to be executed by methods outside the current class. Block closures are sent a message to compute their value and create a new execution context; this property can be used in the construction of control flow methods. They also provide some methods that are used in the creation of Processes from blocks.

Implementation note: here is the use of the variable storage: - byte 1 = number of args - byte 2 = number of temps - bytes 3/4 = initial IP in machine order.


[ Next: | Up:BlockClosure ]

BlockClosure: accessing

argumentCount
Answer the number of arguments passed to the receiver


initialIP
Answer the initial instruction pointer into the receiver


numTemps
Answer the number of temporary variables used by the receiver


outerContext
Answer the method/block context which is the immediate outer of the receiver


[ Next: | Previous:BlockClosure-accessing | Up:BlockClosure ]

BlockClosure: basic

whileFalse
Evaluate the receiver until it returns true


whileFalse: aBlock
Evaluate the receiver. If it returns false, evaluate aBlock and re- start


whileTrue
Evaluate the receiver until it returns false


whileTrue: aBlock
Evaluate the receiver. If it returns true, evaluate aBlock and re- start


[ Next: | Previous:BlockClosure-basic | Up:BlockClosure ]

BlockClosure: built ins

value
Evaluate the receiver passing no parameters


value: arg1
Evaluate the receiver passing arg1 as the only parameter


value: arg1 value: arg2
Evaluate the receiver passing arg1 and arg2 as the parameters


value: arg1 value: arg2 value: arg3
Evaluate the receiver passing arg1, arg2 and arg3 as the parameters


valueWithArguments: argumentsArray
Evaluate the receiver passing argArray's elements as the parameters


[ Next: | Previous:BlockClosure-built ins | Up:BlockClosure ]

BlockClosure: exception handling

ensure: aBlock
Evaluate the receiver; when any exception is signaled exit returning the result of evaluating aBlock; if no exception is raised, return the result of evaluating aBlock when the receiver has ended


ifCurtailed: aBlock
Evaluate the receiver; when any exception is signaled exit returning the result of evaluating aBlock; if no exception is raised, return the result of evaluating the receiver


on: anException do: aBlock
Evaluate the receiver; when anException is signaled, evaluate aBlock passing a Signal describing the exception. Answer either the result of evaluating the receiver or the parameter of a Signal>>#return:


on: e1 do: b1 on: e2 do: b2
Evaluate the receiver; when e1 or e2 are signaled, evaluate respectively b1 or b2, passing a Signal describing the exception. Answer either the result of evaluating the receiver or the argument of a Signal>>#return:


on: e1 do: b1 on: e2 do: b2 on: e3 do: b3
Evaluate the receiver; when e1, e2 or e3 are signaled, evaluate respectively b1, b2 or b3, passing a Signal describing the exception. Answer either the result of evaluating the receiver or the parameter of a Signal>>#return:


on: e1 do: b1 on: e2 do: b2 on: e3 do: b3 on: e4 do: b4
Evaluate the receiver; when e1, e2, e3 or e4 are signaled, evaluate respectively b1, b2, b3 or b4, passing a Signal describing the exception. Answer either the result of evaluating the receiver or the parameter of a Signal>>#return:


on: e1 do: b1 on: e2 do: b2 on: e3 do: b3 on: e4 do: b4 on: e5 do: b5
Evaluate the receiver; when e1, e2, e3, e4 or e5 are signaled, evaluate respectively b1, b2, b3, b4 or b5, passing a Signal describing the exception. Answer either the result of evaluating the receiver or the parameter of a Signal>>#return:


valueWithUnwind
Evaluate the receiver. Any errors caused by the block will cause a backtrace, but execution will continue in the method that sent #valueWithUnwind, after that call. Example: [ 1 / 0 ] valueWithUnwind. 'unwind works!' printNl. Important: this method is public, but it is intended to be used in very special cases. You should usually rely on #ensure: and #on:do:


[ Previous:BlockClosure-exception handling | Up:BlockClosure ]

BlockClosure: multiple process

fork
Create a new process executing the receiver and start it


forkAt: priority
Create a new process executing the receiver with given priority and start it


newProcess
Create a new process executing the receiver in suspended state. The priority is the same as for the calling process. The receiver must not contain returns


newProcessWith: anArray
Create a new process executing the receiver with the passed arguments, and leave it in suspended state. The priority is the same as for the calling process. The receiver must not contain returns


[ ]

BlockContext

Category: Language-Implementation
My instances represent executing Smalltalk blocks, which are portions of executeable code that have access to the environment that they were declared in, take parameters, and result from BlockClosure objects created to be executed by methods outside the current class. Block contexts are created by messages sent to compute a closure's value. They contain a stack and also provide some methods that can be used in inspection or debugging.


[ Next: | Up:BlockContext ]

BlockContext: accessing

caller
Answer the context that called the receiver


home
Answer the MethodContext to which the receiver refers


isBlock
Answer whether the receiver is a block context


method
Return the CompiledMethod being executed


numArgs
Answer the number of arguments passed to the receiver


numTemps
Answer the number of temporaries used by the receiver


outerContext
Answer the outer block/method context for the receiver


receiver
Return the receiver (self) for the method being executed


selector
Return the selector for the method being executed


[ Previous:BlockContext-accessing | Up:BlockContext ]

BlockContext: printing

printOn: aStream
Print a representation for the receiver on aStream


[ ]

Boolean

Category: Language-Data types
I have two instances in the Smalltalk system: true and false. I provide methods that are conditional on boolean values, such as conditional execution and loops, and conditional testing, such as conditional and and conditional or. I should say that I appear to provide those operations; my subclasses True and False actually provide those operations.


[ Next: | Up:Boolean ]

Boolean class: testing

isIdentity
Answer whether x = y implies x == y for instances of the receiver


isImmediate
Answer whether, if x is an instance of the receiver, x copy == x


[ Next: | Previous:Boolean class-testing | Up:Boolean ]

Boolean: basic

& aBoolean
This method's functionality should be implemented by subclasses of Boolean


and: aBlock
This method's functionality should be implemented by subclasses of Boolean


eqv: aBoolean
This method's functionality should be implemented by subclasses of Boolean


ifFalse: falseBlock
This method's functionality should be implemented by subclasses of Boolean


ifFalse: falseBlock ifTrue: trueBlock
This method's functionality should be implemented by subclasses of Boolean


ifTrue: trueBlock
This method's functionality should be implemented by subclasses of Boolean


ifTrue: trueBlock ifFalse: falseBlock
This method's functionality should be implemented by subclasses of Boolean


not
This method's functionality should be implemented by subclasses of Boolean


or: aBlock
This method's functionality should be implemented by subclasses of Boolean


xor: aBoolean
This method's functionality should be implemented by subclasses of Boolean


| aBoolean
This method's functionality should be implemented by subclasses of Boolean


[ Next: | Previous:Boolean-basic | Up:Boolean ]

Boolean: C hacks

asCBooleanValue
This method's functionality should be implemented by subclasses of Boolean


[ Next: | Previous:Boolean-C hacks | Up:Boolean ]

Boolean: overriding

deepCopy
Answer the receiver.


shallowCopy
Answer the receiver.


[ Previous:Boolean-overriding | Up:Boolean ]

Boolean: storing

storeOn: aStream
Store on aStream some Smalltalk code which compiles to the receiver


[ ]

Browser

Category: Language-Implementation


[ Up:Browser ]

Browser class: browsing

browseHierarchy
Tell Emacs tp browse the Smalltalk class hierarchy


browseMethods: methods forClass: class inBuffer: bufferName
Send to Emacs code that browses the methods in the `methods' Dictionary, showing them as part of the `class' class in a buffer with the given name


emacsFunction: funcName on: aBlock
Send to Emacs something like (funcName <aBlock is evaluated here>)


emacsListFunction: funcName on: aBlock
Send to Emacs something like (funcName '(<aBlock is evaluated here>))


finishEmacsMessage
Finish a message to be processed by emacs - does nothing for now


getAllSelectors: selector inBuffer: bufferName
Send to Emacs code that browses the implementors of the given selectors in a buffer with the given name


initialize
Initialize the Emacs browsing system


loadClassNames
Tell Emacs the class names (new version)


oldloadClassNames
Tell Emacs the class names


oldShowInstanceMethods: class
Send to Emacs code that browses instance methods for class


oldShowMethods: class for: methodType
Send to Emacs code that browses methods of the given type for class (methodType is either `class' or `instance')


selectorsForEmacs
Tell Emacs the names of ALL the defined selectors


showAllMethods: class inBuffer: bufferName
Send to Emacs code that browses ALL the methods understood by instances of the given class, in a buffer with the given name


showDirectMethods: class inBuffer: bufferName
Send to Emacs code that browses methods defined in the given class, in a buffer with the given name


showIndirectMethods: class inBuffer: bufferName
Send to Emacs code that browses the methods inherited (and not overridden) by the given class, in a buffer with the given name


showMethods: class for: methodType
Send to Emacs code that browses methods of the given type for class (methodType is either `class' or `instance')


startEmacsMessage
Start a message to be processed by emacs as Lisp


testMethods: aClass for: methodType
Send to Emacs code that browses methods of the given type for class (methodType is either `class' or `instance')


withGcOff: aBlock
Evaluate aBlock while the `GC flipping...' message is off


[ ]

ByteArray

Category: Collections-Unordered
My instances are similar to strings in that they are both represented as a sequence of bytes, but my individual elements are integers, where as a String's elements are characters.


[ Next: | Up:ByteArray ]

ByteArray: built ins

asCData: aCType
Convert the receiver to a CObject with the given type


byteAt: index
Answer the index-th indexed instance variable of the receiver


byteAt: index put: value
Store the `value' byte in the index-th indexed instance variable of the receiver


hash
Answer an hash value for the receiver


primReplaceFrom: start to: stop with: aByteArray startingAt: srcIndex
Private - Replace the characters from start to stop with the ASCII codes contained in aString (which, actually, can be any variable byte class), starting at the srcIndex location of aString


replaceFrom: start to: stop withString: aString startingAt: srcIndex
Replace the characters from start to stop with the ASCII codes contained in aString (which, actually, can be any variable byte class), starting at the srcIndex location of aString


[ Next: | Previous:ByteArray-built ins | Up:ByteArray ]

ByteArray: converting

asString
Answer a String whose character's ASCII codes are the receiver's contents


[ Next: | Previous:ByteArray-converting | Up:ByteArray ]

ByteArray: copying

deepCopy
Answer a shallow copy of the receiver


shallowCopy
Answer a shallow copy of the receiver


[ Previous:ByteArray-copying | Up:ByteArray ]

ByteArray: more advanced accessing

charAt: index
Access the C char at the given index in the receiver. The value is returned as a Smalltalk Character. Indices are 1-based just like for other Smalltalk access.


charAt: index put: value
Store as a C char the Smalltalk Character or Integer object identified by `value', at the given index in the receiver, using sizeof(char) bytes - i.e. 1 byte. Indices are 1-based just like for other Smalltalk access.


doubleAt: index
Access the C double at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


doubleAt: index put: value
Store the Smalltalk Float object identified by `value', at the given index in the receiver, writing it like a C double. Indices are 1-based just like for other Smalltalk access.


floatAt: index
Access the C float at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


floatAt: index put: value
Store the Smalltalk Float object identified by `value', at the given index in the receiver, writing it like a C float. Indices are 1-based just like for other Smalltalk access.


intAt: index
Access the C int at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


intAt: index put: value
Store the Smalltalk Integer object identified by `value', at the given index in the receiver, using sizeof(int) bytes. Indices are 1-based just like for other Smalltalk access.


longAt: index
Access the C long int at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


longAt: index put: value
Store the Smalltalk Integer object identified by `value', at the given index in the receiver, using sizeof(long) bytes. Indices are 1-based just like for other Smalltalk access.


objectAt: index
Access the Smalltalk object (OOP) at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


objectAt: index put: value
Store a pointer (OOP) to the Smalltalk object identified by `value', at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


shortAt: index
Access the C short int at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


shortAt: index put: value
Store the Smalltalk Integer object identified by `value', at the given index in the receiver, using sizeof(short) bytes. Indices are 1-based just like for other Smalltalk access.


stringAt: index
Access the string pointed by the C `char *' at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


stringAt: index put: value
Store the Smalltalk String object identified by `value', at the given index in the receiver, writing it like a *FRESHLY ALLOCATED* C string. It is the caller's responsibility to free it if necessary. Indices are 1-based just like for other Smalltalk access.


unsignedCharAt: index
Access the C unsigned char at the given index in the receiver. The value is returned as a Smalltalk Character. Indices are 1-based just like for other Smalltalk access.


unsignedCharAt: index put: value
Store as a C char the Smalltalk Character or Integer object identified by `value', at the given index in the receiver, using sizeof(char) bytes - i.e. 1 byte. Indices are 1-based just like for other Smalltalk access.


unsignedIntAt: index
Access the C unsigned int at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


unsignedIntAt: index put: value
Store the Smalltalk Integer object identified by `value', at the given index in the receiver, using sizeof(int) bytes. Indices are 1-based just like for other Smalltalk access.


unsignedLongAt: index
Access the C unsigned long int at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


unsignedLongAt: index put: value
Store the Smalltalk Integer object identified by `value', at the given index in the receiver, using sizeof(long) bytes. Indices are 1-based just like for other Smalltalk access.


unsignedShortAt: index
Access the C unsigned short int at the given index in the receiver. Indices are 1-based just like for other Smalltalk access.


unsignedShortAt: index put: value
Store the Smalltalk Integer object identified by `value', at the given index in the receiver, using sizeof(short) bytes. Indices are 1-based just like for other Smalltalk access.


[ ]

ByteMemory

Category: Language-Implementation
I have no instances. I provide messages to my class that access real memory as bytes. An alternative implementation would be to have a single instance of byte memory that represented all memory, and at: and at:put: accessor methods, but since you'd typically refer to that instance via a global variable, and since the global variable would probably be named ByteMemory, the actual method invocations are exactly the same in either case.


[ Up:ByteMemory ]

ByteMemory class: basic

at: address
Returns the byte at address as an integer


at: address put: value
Sets the byte at ADDRESS (an integer) to be VALUE (INTEGER 0..255)


[ ]

ByteStream

Category: Streams-Collections
My instances are read/write streams specially crafted for ByteArrays. They are able to write binary data to them.


[ Up:ByteStream ]

ByteStream: basic

next
Return the next *character* in the ByteArray


nextByte
Return the next byte in the byte array


nextByteArray: numBytes
Return the next numBytes bytes in the byte array


nextLong
Return the next 4 bytes in the byte array, interpreted as a 32 bit signed int


nextPut: aChar
Store aChar on the byte array


nextPutAll: aCollection
Write all the objects in aCollection to the receiver


nextPutByte: anInteger
Store anInteger (range: -128..255) on the byte array


nextPutByteArray: aByteArray
Store aByteArray on the byte array


nextPutLong: anInteger
Store anInteger (range: -2^31..2^32-1) on the byte array as 4 bytes


nextPutShort: anInteger
Store anInteger (range: -32768..65535) on the byte array as 2 bytes


nextShort
Return the next 2 bytes in the byte array, interpreted as a 16 bit signed int


nextSignedByte
Return the next byte in the byte array, interpreted as a 8 bit signed number


nextUlong
Return the next 4 bytes in the byte array, interpreted as a 32 bit unsigned int


nextUshort
Return the next 2 bytes in the byte array, interpreted as a 16 bit unsigned int


[ ]

CAggregate

Category: Language-C interface


[ Next: | Up:CAggregate ]

CAggregate class: accessing

alignof
Answer the receiver's instances required aligment


sizeof
Answer the receiver's instances size


[ Previous:CAggregate class-accessing | Up:CAggregate ]

CAggregate: accessing

+ anInteger
Return another CString pointing at &receiver[anInteger] (or, if you prefer, what `receiver + anInteger' does in C).


- intOrPtr
If intOrPtr is an integer, return another CString pointing at &receiver[-anInteger] (or, if you prefer, what `receiver - anInteger' does in C). If it is a CString, return the difference in chars, i.e. in bytes, between the two pointed addresses (or, if you prefer, what `receiver - anotherCharPtr' does in C)


addressAt: anIndex
Access the array, returning a new Smalltalk CObject of the element type, corresponding to the given indexed element of the array. anIndex is zero-based, just like with all other C-style accessing.


at: anIndex
Access the array, returning a new Smalltalk object of the element type, corresponding to the given indexed element of the array. anIndex is zero-based, just like with all other C-style accessing.


at: anIndex put: aValue
Store in the array the passed Smalltalk object `aValue', which should be of the element type, corresponding to the given indexed element. anIndex is zero-based, just like with all other C-style accessing.


decr
Adjust the pointer by sizeof(elementType) bytes down (i.e. -receiver)


decrBy: anInteger
Adjust the pointer by anInteger elements down (i.e. receiver -= anInteger)


deref
Access the object, returning a new Smalltalk object of the element type, corresponding to the dereferenced pointer or to the first element of the array.


deref: aValue
Modify the object, storing the object of the element type into the pointed address or to the first element of the array.


incr
Adjust the pointer by sizeof(elementType) bytes up (i.e. ++receiver)


incrBy: anInteger
Adjust the pointer by anInteger elements up (i.e. receiver += anInteger)


value
Access the array, returning a new Smalltalk object of the element type, corresponding to the first element of the array.


value: aValue
Modify the array, storing the object of the element type into the first element of the array.


[ ]

CArray

Category: Language-C interface


[ Up:CArray ]

CArray: accessing

alignof
Answer the receiver's required aligment


sizeof
Answer the receiver's size


[ ]

CArrayCType

Category: Language-C interface


[ Next: | Up:CArrayCType ]

CArrayCType class: instance creation

elementType: aCType numberOfElements: anInteger
Answer a new instance of CPtrCType that maps an array whose elements are of the given CType, and whose size is exactly anInteger elements (of course, anInteger only matters for allocation, not for access, since no out-of-bounds protection is provided for C objects).


[ Previous:CArrayCType class-instance creation | Up:CArrayCType ]

CArrayCType: accessing

alignof
Answer the alignment of the receiver's instances


elementType
Answer the type of the elements in the receiver's instances


numberOfElements
Answer the number of elements in the receiver's instances


sizeof
Answer the size of the receiver's instances


[ ]

CBoolean

Category: Language-C interface
I return true if a byte is not zero, false otherwise.


[ Up:CBoolean ]

CBoolean: accessing

value
Get the receiver's value - answer true if it is != 0, false if it is 0.


value: aBoolean
Set the receiver's value - it's the same as for CBytes, but we get a Boolean, not a Character


[ ]

CByte

Category: Language-C interface
You're a marine. You adapt - you improvise - you overcome

- Gunnery Sgt. Thomas Highway Heartbreak Ridge


[ Next: | Up:CByte ]

CByte class: conversion

scalarIndex
Nothing special in the default case - answer a CType for the receiver


type
Nothing special in the default case - answer a CType for the receiver


[ Previous:CByte class-conversion | Up:CByte ]

CByte: accessing

scalarIndex
Nothing special in the default case - answer the receiver's CType


type
Answer a CType for the receiver


value
Get the receiver's value - it's the same as for CUChars, but we convert the result to ASCII


value: anInteger
Set the receiver's value - it's the same as for CUChars, but we get an Integer, not a Character


[ ]

CChar

Category: Language-C interface


[ Next: | Up:CChar ]

CChar class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CChar class-accessing | Up:CChar ]

CChar: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CDouble

Category: Language-C interface


[ Next: | Up:CDouble ]

CDouble class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CDouble class-accessing | Up:CDouble ]

CDouble: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CFloat

Category: Language-C interface


[ Next: | Up:CFloat ]

CFloat class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CFloat class-accessing | Up:CFloat ]

CFloat: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CFunctionDescriptor

Category: Language-C interface
I am not part of the Smalltalk definition. My instances contain information about C functions that can be called from within Smalltalk, such as number and type of parameters. This information is used by the C callout mechanism to perform the actual call-out to C routines.


[ Next: | Up:CFunctionDescriptor ]

CFunctionDescriptor class: testing

addressOf: function
Answer the address (CObject) of the function which is registered (on the C side) with the given name, or zero if no such a function is registered.


isFunction: function
Answer whether a function is registered (on the C side) with the given name or is dynamically loadable.


[ Next: | Previous:CFunctionDescriptor class-testing | Up:CFunctionDescriptor ]

CFunctionDescriptor: accessing

address
Answer the address (CObject) of the function represented by the receiver


isValid
Answer whether the function represented by the receiver is actually a registered one


name
Answer the name of the function (on the C side) represented by the receiver


[ Previous:CFunctionDescriptor-accessing | Up:CFunctionDescriptor ]

CFunctionDescriptor: printing

printOn: aStream
Print a representation of the receiver onto aStream


[ ]

Character

Category: Language-Data types
My instances represent the 256 characters of the character set. I provide messages to translate between integers and character objects, and provide names for some of the common unprintable characters.


[ Next: | Up:Character ]

Character class: built ins

asciiValue: anInteger
Returns the character object corresponding to anInteger. Error if anInteger is not an integer, or not in 0..255.


value: anInteger
Returns the character object corresponding to anInteger. Error if anInteger is not an integer, or not in 0..255.


[ Next: | Previous:Character class-built ins | Up:Character ]

Character class: constants

backspace
Returns the character 'backspace'


cr
Returns the character 'cr'


eof
Returns the character 'eof', aka 'sub'


esc
Returns the character 'esc'


newPage
Returns the character 'newPage', aka 'ff'


nl
Returns the character 'nl'


nul
Returns the character 'nul'


space
Returns the character 'space'


tab
Returns the character 'tab'


[ Next: | Previous:Character class-constants | Up:Character ]

Character class: initializing lookup tables

initialize
Initialize the lookup table which is used to make case and digit-to-char conversions faster. Indices in Table are ASCII values incremented by one. Indices 1-256 classify chars (0 = nothing special, 2 = separator, 48 = digit, 55 = uppercase, 3 = lowercase), indices 257-512 map to lowercase chars, indices 513-768 map to uppercase chars.


[ Next: | Previous:Character class-initializing lookup tables | Up:Character ]

Character class: Instance creation

digitValue: anInteger
Returns a character that corresponds to anInteger. 0-9 map to $0-$9, 10-35 map to $A-$Z


[ Next: | Previous:Character class-Instance creation | Up:Character ]

Character class: testing

isIdentity
Answer whether x = y implies x == y for instances of the receiver


isImmediate
Answer whether, if x is an instance of the receiver, x copy == x


[ Next: | Previous:Character class-testing | Up:Character ]

Character: built ins

= char
Boolean return value; true if the characters are equal


asciiValue
Returns the integer value corresponding to self


asInteger
Returns the integer value corresponding to self


value
Returns the integer value corresponding to self


[ Next: | Previous:Character-built ins | Up:Character ]

Character: Coercion methods

asLowercase
Returns self as a lowercase character if it's an uppercase letter, otherwise returns the character unchanged.


asString
Returns the character self as a string.


asSymbol
Returns the character self as a symbol.


asUppercase
Returns self as a uppercase character if it's an lowercase letter, otherwise returns the character unchanged.


[ Next: | Previous:Character-Coercion methods | Up:Character ]

Character: comparing

< aCharacter
Compare the character's ASCII value. Answer whether the receiver's is the least.


<= aCharacter
Compare the character's ASCII value. Answer whether the receiver's is the least or their equal.


> aCharacter
Compare the character's ASCII value. Answer whether the receiver's is the greatest.


>= aCharacter
Compare the character's ASCII value. Answer whether the receiver's is the greatest or their equal.


[ Next: | Previous:Character-comparing | Up:Character ]

Character: converting

digitValue
Returns the value of self interpreted as a digit. Here, 'digit' means either 0-9, or A-Z, which maps to 10-35.


[ Next: | Previous:Character-converting | Up:Character ]

Character: printing

printOn: aStream
Store a representation of the receiver on aStream


[ Next: | Previous:Character-printing | Up:Character ]

Character: storing

storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Next: | Previous:Character-storing | Up:Character ]

Character: testing

isAlphaNumeric
True if self is a letter or a digit


isDigit
True if self is a 0-9 digit


isLetter
True if self is an upper- or lowercase letter


isLowercase
True if self is a lowercase letter


isSeparator
Returns true if self is a space, cr, tab, nl, or newPage


isUppercase
True if self is uppercase


isVowel
Returns true if self is a, e, i, o, or u; case insensitive


[ Previous:Character-testing | Up:Character ]

Character: testing functionality

isCharacter
Answer True. We're definitely characters


[ ]

CInt

Category: Language-C interface


[ Next: | Up:CInt ]

CInt class: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's size


[ Previous:CInt class-accessing | Up:CInt ]

CInt: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's instances size


[ ]

Class

Category: Language-Implementation
I am THE class object. My instances are the classes of the system


[ Next: | Up:Class ]

Class: accessing instances and variables

addClassVarName: aString
Add a class variable with the given name to the class pool dictionary


addSharedPool: aDictionary
Add the given shared pool to the list of the class' pool dictionaries


allClassVarNames
Answer the names of the variables in the receiver's class pool dictionary and in each of the superclasses' class pool dictionaries


classPool
Answer the class pool dictionary


classVarNames
Answer the names of the variables in the class pool dictionary


initialize
redefined in children (?)


removeClassVarName: aString
Removes the class variable from the class, error if not present, or still in use.


removeSharedPool: aDictionary
Remove the given dictionary to the list of the class' pool dictionaries


sharedPools
Return the names of the shared pools defined by the class


[ Next: | Previous:Class-accessing instances and variables | Up:Class ]

Class: filing

fileOutDeclarationOn: aFileStream
File out class definition to aFileStream


fileOutHeaderOn: aFileStream
Write date and time stamp to aFileStream


fileOutOn: aFileStream
File out complete class description: class definition, class and instance methods


[ Next: | Previous:Class-filing | Up:Class ]

Class: instance creation

subclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a fixed subclass of the receiver with the given name, instance variables, class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


variableByteSubclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a byte variable subclass of the receiver with the given name, instance variables (must be "), class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


variableSubclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a variable pointer subclass of the receiver with the given name, instance variables, class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


variableWordSubclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a word variable subclass of the receiver with the given name, instance variables (must be "), class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


[ Next: | Previous:Class-instance creation | Up:Class ]

Class: instance creation - alternative

categoriesFor: method are: categories
Don't use this, it is only present to file in from IBM Smalltalk


subclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


subclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableByteSubclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableByteSubclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableSubclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableSubclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableWordSubclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableWordSubclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


[ Next: | Previous:Class-instance creation - alternative | Up:Class ]

Class: printing

printOn: aStream
Print a representation of the receiver on aStream


storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Next: | Previous:Class-printing | Up:Class ]

Class: testing

= aClass
Returns true if the two class objects are to be considered equal.


[ Previous:Class-testing | Up:Class ]

Class: testing functionality

asClass
Answer the receiver.


isClass
Answer `true'.


[ ]

ClassDescription

Category: Language-Implementation
My instances record information generally attributed to classes and metaclasses; namely, the class name, class comment (you wouldn't be reading this if it weren't for me), a list of the instance variables of the class, and the class category. I provide methods that access classes by category, and allow whole categories of classes to be filed out to external disk files.


[ Next: | Up:ClassDescription ]

ClassDescription: accessing class description

addInstVarName: aString
Add the given instance variable to instance of the receiver


comment
Answer the class comment


comment: aString
Change the class name


name
Answer the class name


removeInstVarName: aString
Remove the given instance variable from the receiver and recompile all of the receiver's subclasses


[ Next: | Previous:ClassDescription-accessing class description | Up:ClassDescription ]

ClassDescription: accessing instances and variables

allInstVarNames
Answer the names of every instance variables the receiver contained in the receiver's instances


instVarNames
Answer an Array containing the instance variables defined by the receiver


subclassInstVarNames
Answer the names of the instance variables the receiver inherited from its superclass


[ Next: | Previous:ClassDescription-accessing instances and variables | Up:ClassDescription ]

ClassDescription: compiling

compile: code classified: categoryName
Compile code in the receiver, assigning the method to the given category. Answer the newly created CompiledMethod, or nil if an error was found.


compile: code classified: categoryName ifError: block
Compile method source and install in method category, categoryName. If there are parsing errors, invoke exception block, 'block' (see compile:ifError:). Return the method


compile: code classified: categoryName notifying: requestor
Compile method source and install in method category, categoryName. If there are parsing errors, send an error message to requestor


[ Next: | Previous:ClassDescription-compiling | Up:ClassDescription ]

ClassDescription: copying

copy: selector from: aClass
Copy the given selector from aClass, assigning it the same category


copy: selector from: aClass classified: categoryName
Copy the given selector from aClass, assigning it the given category


copyAll: arrayOfSelectors from: class
Copy all the selectors in arrayOfSelectors from class, assigning them the same category they have in class


copyAll: arrayOfSelectors from: class classified: categoryName
Copy all the selectors in arrayOfSelectors from aClass, assigning them the given category


copyAllCategoriesFrom: aClass
Copy all the selectors in aClass, assigning them the original category


copyCategory: categoryName from: aClass
Copy all the selectors in from aClass that belong to the given category


copyCategory: categoryName from: aClass classified: newCategoryName
Copy all the selectors in from aClass that belong to the given category, reclassifying them as belonging to the given category


[ Next: | Previous:ClassDescription-copying | Up:ClassDescription ]

ClassDescription: filing

fileOut: fileName
Open the given file and to file out a complete class description to it


fileOutCategory: categoryName to: fileName
File out all the methods belonging to the method category, categoryName, to the fileName file


fileOutCategory: category toStream: aFileStream
File out all the methods belonging to the method category, categoryName, to aFileStream


fileOutOn: aFileStream
File out complete class description: class definition, class and instance methods


fileOutSelector: selector to: fileName
File out the given selector to fileName


[ Next: | Previous:ClassDescription-filing | Up:ClassDescription ]

ClassDescription: organization of messages and classes

category
Answer the class category


category: aString
Change the class category to aString


createGetMethod: what
Create a method accessing the variable `what'.


createGetMethod: what default: value
Create a method accessing the variable `what', with a default value of `value', using lazy initialization


createSetMethod: what
Create a method which sets the variable `what'.


defineCFunc: cFuncNameString
withSelectorArgs: selectorAndArgs returning: returnTypeSymbol args: argsArray See documentation. Too complex to describe it here ;-)


removeCategory: aString
Remove from the receiver every method belonging to the given category


whichCategoryIncludesSelector: selector
Answer the category for the given selector, or nil if the selector is not found


[ Previous:ClassDescription-organization of messages and classes | Up:ClassDescription ]

ClassDescription: printing

classVariableString
This method's functionality should be implemented by subclasses of ClassDescription


instanceVariableString
Answer a string containing the name of the receiver's instance variables.


sharedVariableString
This method's functionality should be implemented by subclasses of ClassDescription


[ ]

CLong

Category: Language-C interface


[ Next: | Up:CLong ]

CLong class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CLong class-accessing | Up:CLong ]

CLong: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CObject

Category: Language-C interface
I am not part of the standard Smalltalk kernel class hierarchy. My instances contain values that are not interpreted by the Smalltalk system; they frequently hold "pointers" to data outside of the Smalltalk environment. The C callout mechanism allows my instances to be transformed into their corresponding C values for use in external routines.


[ Next: | Up:CObject ]

CObject class: conversion

scalarIndex
Nothing special in the default case - answer a CType for the receiver


type
Nothing special in the default case - answer a CType for the receiver


[ Next: | Previous:CObject class-conversion | Up:CObject ]

CObject class: instance creation

address: anInteger
Answer a new object pointing to the passed address, anInteger


alloc: nBytes
Allocate nBytes bytes and return an instance of the receiver


alloc: nBytes type: cTypeObject
Allocate nBytes bytes and return a CObject of the given type


new: nBytes
Allocate nBytes bytes and return an instance of the receiver


[ Next: | Previous:CObject class-instance creation | Up:CObject ]

CObject: accessing

address
Answer the address the receiver is pointing to.


address: anInteger
Set the receiver to point to the passed address, anInteger


printOn: aStream
Print a representation of the receiver


type: aCType
Set the receiver's type to aCType.


value
What can I return? So fail


value: anObject
What can I set? So fail


[ Next: | Previous:CObject-accessing | Up:CObject ]

CObject: C data access

at: byteOffset put: aValue type: aType
Store aValue as data of the given type from byteOffset bytes after the pointer stored in the receiver


at: byteOffset type: aType
Answer some data of the given type from byteOffset bytes after the pointer stored in the receiver


free
Free the receiver's pointer and set it to null. Big trouble hits you if the receiver doesn't point to the base of a malloc-ed area.


[ Next: | Previous:CObject-C data access | Up:CObject ]

CObject: conversion

castTo: aType
Answer another CObject, pointing to the same address as the receiver, but belonging to the aType CType.


scalarIndex
Nothing special in the default case - answer the receiver's CType


type
Answer a CType for the receiver


[ Previous:CObject-conversion | Up:CObject ]

CObject: finalization

finalize
To make the VM call this, use #addToBeFinalized. It frees automatically any memory pointed to by the CObject. It is not automatically enabled because big trouble hits you if you use #free and the receiver doesn't point to the base of a malloc-ed area.


[ ]

Collection

Category: Collections
I am an abstract class. My instances are collections of objects. My subclasses may place some restrictions or add some definitions to how the objects are stored or organized; I say nothing about this. I merely provide some object creation and access routines for general collections of objects.


[ Next: | Up:Collection ]

Collection class: instance creation

with: anObject
Answer a collection whose only element is anObject


with: firstObject with: secondObject
Answer a collection whose only elements are the parameters in the order they were passed


with: firstObject with: secondObject with: thirdObject
Answer a collection whose only elements are the parameters in the order they were passed


with: firstObject with: secondObject with: thirdObject with: fourthObject
Answer a collection whose only elements are the parameters in the order they were passed


withAll: aCollection
Answer a collection whose elements are all those in aCollection


[ Next: | Previous:Collection class-instance creation | Up:Collection ]

Collection: Adding to a collection

add: newObject
Add newObject to the receiver, answer it


addAll: aCollection
Adds all the elements of 'aCollection' to the receiver, answer aCollection


[ Next: | Previous:Collection-Adding to a collection | Up:Collection ]

Collection: converting

asArray
Answer an Array containing all the elements in the receiver


asBag
Answer a Bag containing all the elements in the receiver


asByteArray
Answer a ByteArray containing all the elements in the receiver


asOrderedCollection
Answer an OrderedCollection containing all the elements in the receiver


asRunArray
Answer the receiver converted to a RunArray. If the receiver is not ordered the order of the elements in the RunArray might not be the #do: order.


asSet
Answer a Set containing all the elements in the receiver with no duplicates


asSortedCollection
Answer a SortedCollection containing all the elements in the receiver with the default sort block - [ :a :b | a <= b ]


asSortedCollection: aBlock
Answer a SortedCollection whose elements are the elements of the receiver, sorted according to the sort block aBlock


[ Next: | Previous:Collection-converting | Up:Collection ]

Collection: copying Collections

copyReplacing: targetObject withObject: newObject
Copy replacing each object which is = to targetObject with newObject


copyWith: newElement
Answer a copy of the receiver to which newElement is added


copyWithout: oldElement
Answer a copy of the receiver to which all occurrences of oldElement are removed


[ Next: | Previous:Collection-copying Collections | Up:Collection ]

Collection: enumerating the elements of a collection

allSatisfy: aBlock
Search the receiver for an element for which aBlock returns false. Answer true if none does, false otherwise.


anyOne
Answer an unspecified element of the collection. Example usage: ^coll inject: coll anyOne into: [ :max :each | max max: each ] to be used when you don't have a valid lowest-possible-value (which happens in common cases too, such as with arbitrary numbers


anySatisfy: aBlock
Search the receiver for an element for which aBlock returns true. Answer true if some does, false otherwise.


collect: aBlock
Answer a new instance of a Collection containing all the results of evaluating aBlock passing each of the receiver's elements


conform: aBlock
Search the receiver for an element for which aBlock returns false. Answer true if none does, false otherwise.


contains: aBlock
Search the receiver for an element for which aBlock returns true. Answer true if some does, false otherwise.


detect: aBlock
Search the receiver for an element for which aBlock returns true. If some does, answer it. If none does, fail


detect: aBlock ifNone: exceptionBlock
Search the receiver for an element for which aBlock returns true. If some does, answer it. If none does, answer the result of evaluating aBlock


do: aBlock
Enumerate each object of the receiver, passing them to aBlock


do: aBlock separatedBy: separatorBlock
Enumerate each object of the receiver, passing them to aBlock. Between every two invocations of aBlock, invoke separatorBlock


inject: thisValue into: binaryBlock
Pass to binaryBlock receiver thisValue and the first element of the receiver; for each subsequent element, pass the result of the previous evaluation and an element. Answer the result of the last invocation.


reject: aBlock
Answer a new instance of a Collection containing all the elements in the receiver which, when passed to aBlock, don't answer true


select: aBlock
Answer a new instance of a Collection containing all the elements in the receiver which, when passed to aBlock, answer true


[ Next: | Previous:Collection-enumerating the elements of a collection | Up:Collection ]

Collection: printing

inspect
Print all the instance variables and objects in the receiver on the Transcript


printOn: aStream
Print a representation of the receiver on aStream


[ Next: | Previous:Collection-printing | Up:Collection ]

Collection: Removing from a collection

remove: oldObject
Remove oldObject from the receiver. If absent, fail, else answer oldObject.


remove: oldObject ifAbsent: anExceptionBlock
Remove oldObject from the receiver. If absent, evaluate anExceptionBlock and answer the result, else answer oldObject.


removeAll: aCollection
Remove each object in aCollection, answer aCollection, fail if some of them is absent. Warning: this could leave the collection in a semi-updated state.


removeAll: aCollection ifAbsent: aBlock
Remove each object in aCollection, answer aCollection; if some element is absent, pass it to aBlock.


[ Next: | Previous:Collection-Removing from a collection | Up:Collection ]

Collection: storing

storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Previous:Collection-storing | Up:Collection ]

Collection: testing collections

capacity
Answer how many elements the receiver can hold before having to grow.


includes: anObject
Answer whether we include anObject


isEmpty
Answer whether we are (still) empty


notEmpty
Answer whether we include at least one object


occurrencesOf: anObject
Answer how many occurrences of anObject we include


size
Answer how many objects we include


[ ]

CompiledMethod

Category: Language-Implementation
I represent methods that have been compiled. I can recompile methods from their source code, I can invoke Emacs to edit the source code for one of my instances, and I know how to access components of my instances.


[ Next: | Up:CompiledMethod ]

CompiledMethod class: instance creation

literals: lits numArgs: numArg numTemps: numTemp
primitive: primIndex bytecodes: bytecodes depth: depth Answer a full fledged CompiledMethod. Construct the method header from the parameters, and set the literals and bytecodes to the provided ones.


newMethod: numBytecodes header: anInteger literals: literals
Answer a new CompiledMethod with room for the given bytes and the given header


newMethod: numBytecodes header: anInteger numLiterals: numLiterals
Answer a new CompiledMethod with room for the given bytes and the given header


[ Next: | Previous:CompiledMethod class-instance creation | Up:CompiledMethod ]

CompiledMethod class: lean images

stripSourceCode
Remove all the references to method source code from the system


[ Next: | Previous:CompiledMethod class-lean images | Up:CompiledMethod ]

CompiledMethod: accessing

bytecodeAt: anIndex
Answer the anIndex-th bytecode


bytecodeAt: anIndex put: aValue
Store aValue as the anIndex-th bytecode


flags
Private - Answer the optimization flags for the receiver


literalAt: anIndex
Answer the anIndex-th literal


literalAt: anInteger put: aValue
Store aValue as the anIndex-th literal


literals
Not commented.


numArgs
Answer the number of arguments for the receiver


numLiterals
Answer the number of literals for the receiver


numTemps
Answer the number of temporaries for the receiver


primitive
Answer the primitive called by the receiver


stackDepth
Answer the number of stack slots needed for the receiver


[ Next: | Previous:CompiledMethod-accessing | Up:CompiledMethod ]

CompiledMethod: basic

= aMethod
Answer whether the receiver and aMethod are equal


hash
Answer an hash value for the receiver


methodCategory
Answer the method category


methodCategory: aCategory
Set the method category to the given string


methodSourceCode
Answer the method source code (a FileSegment or String or nil)


methodSourceFile
Answer the file where the method source code is stored


methodSourcePos
Answer the location where the method source code is stored in the methodSourceFile


methodSourceString
Answer the method source code as a string


[ Next: | Previous:CompiledMethod-basic | Up:CompiledMethod ]

CompiledMethod: copying

copy
Answer a shallow copy of the receiver


deepCopy
Answer a deep copy of the receiver


shallowCopy
Answer a shallow copy of the receiver


[ Next: | Previous:CompiledMethod-copying | Up:CompiledMethod ]

CompiledMethod: debugging

breakAtLine: lineNumber
This method's functionality has not been implemented yet.


breakpointAt: byteIndex
Put a break-point at the given bytecode


inspect
Print the contents of the receiver in a verbose way.


removeBreakpointAt: byteIndex
Remove the break-point at the given bytecode (don't fail if none was set


[ Next: | Previous:CompiledMethod-debugging | Up:CompiledMethod ]

CompiledMethod: printing

printOn: aStream
Print the receiver's source code on aStream


storeOn: aStream
Print code to create the receiver on aStream


[ Previous:CompiledMethod-printing | Up:CompiledMethod ]

CompiledMethod: testing accesses

accesses: instVarIndex
Answer whether the receiver access the instance variable with the given index


containsLiteral: anObject
Answer if the receiver contains a literal which is equal to anObject.


refersTo: anObject
Answer whether the receiver refers to the given object


[ ]

ContextPart

Category: Language-Implementation
My instances represent executing Smalltalk code, which represent the local environment of executable code. They contain a stack and also provide some methods that can be used in inspection or debugging.


[ Next: | Up:ContextPart ]

ContextPart class: exception handling

backtrace
Print a backtrace from the caller to the bottom of the stack on the Transcript


backtraceOn: aStream
Print a backtrace from the caller to the bottom of the stack on aStream


lastUnwindPoint
Private - Return the last context marked as an unwind point, or our en- vironment if the last unwind point belongs to another environment.


removeLastUnwindPoint
Private - Return and remove the last context marked as an unwind point, or our environment if the last unwind point belongs to another environment.


unwind
Return execution to the last context marked as an unwind point, returning nil on that stack.


unwind: returnValue
Return execution to the last context marked as an unwind point, returning returnValue on that stack.


unwindPoints
Answer an OrderedCollection of contexts marked as unwind points.


[ Next: | Previous:ContextPart class-exception handling | Up:ContextPart ]

ContextPart: accessing

environment
To create a valid execution environment for the interpreter even before it starts, GST creates a fake context whose selector is nil and which can be used as a marker for the current execution environment. This method answers that context. For processes, it answers the process block itself


hasBlock
Answer whether the receiver is the outer context for a BlockContext


home
Answer the MethodContext to which the receiver refers


ip
Answer the current instruction pointer into the receiver


ip: newIP
Set the instruction pointer for the receiver


isBlock
Answer whether the receiver is a block context


isProcess
Answer whether the receiver represents a process context, i.e. a context created by BlockClosure>>#newProcess. Such a context can be recognized because it has no parent but its selector is not nil, unlike the contexts created by the VM's prepareExecutionEnvironment function.


method
Return the CompiledMethod being executed


parentContext
Answer the context that called the receiver


receiver
Return the receiver (self) for the method being executed


selector
Return the selector for the method being executed


size
Answer the number of valid fields for the receiver. Any read access from (self size + 1) to (self basicSize) has undefined results - even crashing


sp
Answer the current stack pointer into the receiver


sp: newSP
Set the stack pointer for the receiver


validSize
Answer how many elements in the receiver should be inspected


[ Next: | Previous:ContextPart-accessing | Up:ContextPart ]

ContextPart: built ins

blockCopy: numArgs temporaries: numTemps
Generate a BlockClosure starting execution two bytecodes after the end of the 'send special message #blockCopy:' bytecode


[ Next: | Previous:ContextPart-built ins | Up:ContextPart ]

ContextPart: exception handling

mark
Add the receiver as a possible unwind point


returnTo: aContext
Set the context to which the receiver will return


unmark
Remove the receiver from the contexts to which an unwind operation might return


[ Next: | Previous:ContextPart-exception handling | Up:ContextPart ]

ContextPart: printing

backtrace
Print a backtrace from the receiver to the bottom of the stack on the Transcript.


backtraceOn: aStream
Print a backtrace from the caller to the bottom of the stack on aStream.


[ Previous:ContextPart-printing | Up:ContextPart ]

ContextPart: processes

nowHasBlock
Private - Tell the VM that the receiver has references in other objects


[ ]

CPtr

Category: Language-C interface


[ Up:CPtr ]

CPtr: accessing

alignof
Answer the receiver's required aligment


sizeof
Answer the receiver's size


[ ]

CPtrCType

Category: Language-C interface


[ Next: | Up:CPtrCType ]

CPtrCType class: instance creation

elementType: aCType
Answer a new instance of CPtrCType that maps pointers to the given CType


[ Previous:CPtrCType class-instance creation | Up:CPtrCType ]

CPtrCType: accessing

elementType
Answer the type of the elements in the receiver's instances


[ ]

CScalar

Category: Language-C interface


[ Next: | Up:CScalar ]

CScalar class: instance creation

type
Answer a CType for the receiver - for example, CByteType if the receiver is CByte.


value: anObject
Answer a newly allocated CObject containing the passed value, anObject. Remember to call #addToBeFinalized if you want the CObject to be automatically freed


[ Previous:CScalar class-instance creation | Up:CScalar ]

CScalar: accessing

value
Answer the value the receiver is pointing to. The exact returned value depends on the receiver's class


value: aValue
Set the receiver to point to the value, aValue. The exact meaning of aValue depends on the receiver's class


[ ]

CScalarCType

Category: Language-C interface


[ Next: | Up:CScalarCType ]

CScalarCType: accessing

valueType
valueType is used as a means to communicate to the interpreter the underlying type of the data. For scalars, it is supplied by the CObject subclass.


[ Previous:CScalarCType-accessing | Up:CScalarCType ]

CScalarCType: storing

storeOn: aStream
Store Smalltalk code that compiles to the receiver


[ ]

CShort

Category: Language-C interface


[ Next: | Up:CShort ]

CShort class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CShort class-accessing | Up:CShort ]

CShort: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CSmalltalk

Category: Language-C interface


[ Next: | Up:CSmalltalk ]

CSmalltalk class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CSmalltalk class-accessing | Up:CSmalltalk ]

CSmalltalk: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CString

Category: Language-C interface
Technically, CString is really a pointer to type char. However, it's so darn useful as a distinct datatype, and it is a separate datatype in Smalltalk, so we allow developers to express their semantics more precisely by using a more descriptive type.

In general, I behave like a cross between an array of characters and a pointer to a character. I provide the protocol for both data types. My #value method returns a Smalltalk String, as you would expect for a scalar datatype.


[ Next: | Up:CString ]

CString class: getting info

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's size


[ Next: | Previous:CString class-getting info | Up:CString ]

CString: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ Previous:CString-accessing | Up:CString ]

CString: pointer like behavior

+ anInteger
Return another CString pointing at &receiver[anInteger] (or, if you prefer, what `receiver + anInteger' does in C).


- intOrPtr
If intOrPtr is an integer, return another CString pointing at &receiver[-anInteger] (or, if you prefer, what `receiver - anInteger' does in C). If it is a CString, return the difference in chars, i.e. in bytes, between the two pointed addresses (or, if you prefer, what `receiver - anotherCharPtr' does in C)


addressAt: anIndex
Access the string, returning a Smalltalk CChar corresponding to the given indexed element of the string. anIndex is zero-based, just like with all other C-style accessing.


at: anIndex
Access the string, returning the Smalltalk Character corresponding to the given indexed element of the string. anIndex is zero-based, just like with all other C-style accessing.


at: anIndex put: aCharacter
Store in the string a Smalltalk Character, at the given indexed element of the string. anIndex is zero-based, just like with all other C-style accessing.


decr
Adjust the pointer by one byte down (i.e. -receiver)


decrBy: anInteger
Adjust the pointer by anInteger bytes down (i.e. receiver -= anInteger). Note that, unlike #-, #decrBy: does not support passing another CString as its parameter, since neither C supports something like `charPtr -= anotherCharPtr'


deref
Access the string, returning the Smalltalk CChar corresponding to the first element of the string. This may not make much sense, but it resembles what `*string' does in C.


deref: aCChar
Access the string, setting the first element of the string to the value of the passed CChar. This may not make much sense, but it resembles what we get in C if we do *string = 's'.


incr
Adjust the pointer by one byte up (i.e. ++receiver)


incrBy: anInteger
Adjust the pointer by anInteger bytes up (i.e. receiver += anInteger)


replaceWith: aString
Overwrite memory starting at the receiver's address, with the contents of the Smalltalk String aString, null-terminating it. Ensure there is free space enough, or big trouble will hit you!


[ ]

CStruct

Category: Language-C interface


[ Next: | Up:CStruct ]

CStruct class: instance creation

new
Allocate a new instance of the receiver. To free the memory after GC, remember to call #addToBeFinalized.


type
Answer a CType for the receiver


[ Next: | Previous:CStruct class-instance creation | Up:CStruct ]

CStruct class: subclass creation

compileSize: size align: alignment for: aClass
Private - Compile sizeof and alignof methods


computeAggregateType: type block: aBlock
Private - Called by computeTypeString:block: for pointers/arrays. Format of type: (array int 3) or (ptr FooStruct)


computeArrayType: type block: aBlock
Private - Called by computeAggregateType:block: for arrays


computePtrType: type block: aBlock
Private - Called by computeAggregateType:block: for pointers


computeTypeString: type block: aBlock
Private - Pass the size, alignment, and description of CType for aBlock, given the field description in `type' (the second element of each pair).


emitInspectTo: str for: name
Private - Emit onto the given stream the code for adding the given selector to the CStruct's inspector.


initialize
Initialize the receiver's TypeMap


newStruct: structName declaration: array
Create a new class with the given name that contains code to implement the given C struct - see documentation for more information


[ Previous:CStruct class-subclass creation | Up:CStruct ]

CStruct: instance creation

inspect
Inspect the contents of the receiver


inspectSelectorList
Answer a list of selectors whose return values should be inspected by #inspect.


[ ]

CType

Category: Language-C interface
I am not part of the standard Smalltalk kernel class hierarchy. I contain type information used by subclasses of CObject, which represents external C data items.

My subclasses have instances which represent the actual data types; for the scalar types, there is only one instance created of each, but for the aggregate types, there is at least one instance per base type and/or number of elements.


[ Next: | Up:CType ]

CType class: C instance creation

cObjectType: aCObjectSubclass
Create a new CType for the given subclass of CObject


[ Next: | Previous:CType class-C instance creation | Up:CType ]

CType: accessing

alignof
Answer the size of the receiver's instances


cObjectType
Answer the CObject subclass whose instance is created when new is sent to the receiver


sizeof
Answer the size of the receiver's instances


valueType
valueType is used as a means to communicate to the interpreter the underlying type of the data. For anything but scalars, it's just 'self'


[ Next: | Previous:CType-accessing | Up:CType ]

CType: C instance creation

new
Allocate a new CObject with the type (class) identified by the receiver. It is the caller's responsibility to free the memory allocated for it.


new: cObjOrInt
Create a new CObject with the type (class) identified by the receiver, pointing to the given address (identified by an Integer or CObject).


[ Previous:CType-C instance creation | Up:CType ]

CType: storing

storeOn: aStream
Store Smalltalk code that compiles to the receiver


[ ]

CUChar

Category: Language-C interface


[ Next: | Up:CUChar ]

CUChar class: getting info

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CUChar class-getting info | Up:CUChar ]

CUChar: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CUInt

Category: Language-C interface


[ Next: | Up:CUInt ]

CUInt class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CUInt class-accessing | Up:CUInt ]

CUInt: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CULong

Category: Language-C interface


[ Next: | Up:CULong ]

CULong class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CULong class-accessing | Up:CULong ]

CULong: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

CUShort

Category: Language-C interface


[ Next: | Up:CUShort ]

CUShort class: accessing

alignof
Answer the receiver's instances required aligment


scalarIndex
Private - Answer an index referring to the receiver's instances scalar type


sizeof
Answer the receiver's instances size


[ Previous:CUShort class-accessing | Up:CUShort ]

CUShort: accessing

alignof
Answer the receiver's required aligment


scalarIndex
Private - Answer an index referring to the receiver's scalar type


sizeof
Answer the receiver's size


[ ]

Date

Category: Language-Data types
My instances represent dates. My base date is defined to be Jan 1, 1901. I provide methods for instance creation (including via "symbolic" dates, such as "Date newDay: 14 month: #Feb year: 1990".

PLEASE BE WARNED - use this class only for dates after 1582 AD; that's the beginning of the epoch. Dates before 1582 will not be correctly printed. In addition, since ten days were lost from October 5 through October 15, operations between a Gregorian date (after 15-Oct-1582) and a Julian date (before 5-Oct-1582) will give incorrect results; or, 4-Oct-1582 + 2 days will yield 6-Oct-1582 (a non-existent day!), not 16-Oct-1582.

In fact, if you pass a year < 1582 to a method like #newDay:month:year: it will assume that it is a two-digit year (e.g. 90=1990, 1000=2900). The only way to create Julian calendar dates is with the #fromDays: instance creation method.


[ Next: | Up:Date ]

Date class: basic

dateAndTimeNow
Answer an array containing the current date and time


dayOfWeek: dayName
Answer the index of the day of week corresponding to the given name


daysInMonth: monthName forYear: yearInteger
Answer the number of days in the given (named) month for the given year


daysInYear: yearInteger
Answer the number of days in the given year


indexOfMonth: monthName
Answer the index of the month corresponding to the given name


initDayNameDict
Initialize the DayNameDict to the names of the days


initialize
Initialize the receiver


initMonthNameDict
Initialize the MonthNameDict to the names of the months


nameOfDay: dayIndex
Answer the name of the day of week corresponding to the given index


nameOfMonth: monthIndex
Answer the name of the month corresponding to the given index


shortNameOfMonth: monthIndex
Answer the name of the month corresponding to the given index


[ Next: | Previous:Date class-basic | Up:Date ]

Date class: instance creation

fromDays: dayCount
Answer a Date denoting dayCount days past 1/1/1901


fromJulian: jd
Answer a Date denoting the jd-th day in the astronomical Julian calendar.


fromSeconds: time
Answer a Date denoting the date time seconds past Jan 1st, 2000


newDay: day month: monthName year: yearInteger
Answer a Date denoting the dayCount day of the given (named) month and year


newDay: day monthIndex: monthIndex year: yearInteger
Answer a Date denoting the dayCount day of the given (as a number) month and year


newDay: dayCount year: yearInteger
Answer a Date denoting the dayCount day of the yearInteger year


today
Answer a Date denoting the current date


[ Next: | Previous:Date class-instance creation | Up:Date ]

Date: basic

addDays: dayCount
Answer a new Date pointing dayCount past the receiver


subtractDate: aDate
Answer the number of days between aDate and the receiver (negative if the receiver is before aDate)


subtractDays: dayCount
Answer a new Date pointing dayCount before the receiver


[ Next: | Previous:Date-basic | Up:Date ]

Date: date computations

asSeconds
Answer the date as the number of seconds from 1/1/1901.


day
Answer the day represented by the receiver


dayName
Answer the day of week of the receiver as a Symbol


dayOfWeek
Answer the day of week of the receiver. 1 = Monday, 7 = Sunday


dayOfYear
Answer the days passed since 31/12 of last year; e.g. New Year's Day is 1


daysFromBaseDay
Answer the days passed since 1/1/1901


daysInMonth
Answer the days in the month represented by the receiver


daysInYear
Answer the days in the year represented by the receiver


daysLeftInMonth
Answer the days to the end of the month represented by the receiver


daysLeftInYear
Answer the days to the end of the year represented by the receiver


firstDayOfMonth
Answer a Date representing the first day of the month represented by the receiver


lastDayOfMonth
Answer a Date representing the last day of the month represented by the receiver


month
Answer the month represented by the receiver


monthName
Answer the name of the month represented by the receiver


year
Answer the year represented by the receiver


[ Next: | Previous:Date-date computations | Up:Date ]

Date: printing

printOn: aStream
Print a representation for the receiver on aStream


[ Next: | Previous:Date-printing | Up:Date ]

Date: storing

storeOn: aStream
Store on aStream Smalltalk code compiling to the receiver


[ Previous:Date-storing | Up:Date ]

Date: testing

< aDate
Answer whether the receiver indicates a date preceding aDate


= aDate
Answer whether the receiver indicates the same date as aDate


hash
Answer an hash value for the receievr


[ ]

Delay

Category: Language-Processes
I am the ultimate agent for frustration in the world. I cause things to wait (typically much more than is appropriate, but it is those losing operating system's fault). When a process sends one of my instances a wait message, that process goes to sleep for the interval specified when the instance was created.


[ Next: | Up:Delay ]

Delay class: general inquiries

millisecondClockValue
Private - Answer the number of milliseconds since midnight


[ Next: | Previous:Delay class-general inquiries | Up:Delay ]

Delay class: initialization

initialize
Private - Initialize the receiver and the associated process


[ Next: | Previous:Delay class-initialization | Up:Delay ]

Delay class: instance creation

forMilliseconds: millisecondCount
Answer a Delay waiting for millisecondCount milliseconds


forSeconds: secondCount
Answer a Delay waiting for secondCount seconds


untilMilliseconds: millisecondCount
Answer a Delay waiting for millisecondCount milliseconds after midnight


[ Next: | Previous:Delay class-instance creation | Up:Delay ]

Delay: accessing

resumptionTime
Answer the time when a process waiting on a Delay will resume


[ Next: | Previous:Delay-accessing | Up:Delay ]

Delay: comparing

= aDelay
Answer whether the receiver and aDelay denote the same delay


hash
Answer an hash value for the receiver


[ Previous:Delay-comparing | Up:Delay ]

Delay: process delay

wait
Wait until the amount of time represented by the instance of Delay elapses


[ ]

DelayedAdaptor

Category: Language-Data types
I can be used where many expensive updates must be performed. My in- stances buffer the last value that was set, and only actually set the value when the #trigger message is sent. Apart from this, I'm equi- valent to PluggableAdaptor.


[ Up:DelayedAdaptor ]

DelayedAdaptor: accessing

trigger
Really set the value of the receiver.


value
Get the value of the receiver.


value: anObject
Set the value of the receiver - actually, the value is cached and is not set until the #trigger method is sent.


[ ]

Dictionary

Category: Collections-Keyed
I implement a dictionary, which is an object that is indexed by unique objects (typcially instances of Symbol), and associates another object with that index. I use the equality operator = to determine equality of indices.


[ Next: | Up:Dictionary ]

Dictionary class: instance creation

new
Create a new dictionary with a default size


[ Next: | Previous:Dictionary class-instance creation | Up:Dictionary ]

Dictionary: accessing

add: newObject
Add the newObject association to the receiver


associationAt: key
Answer the key/value Association for the given key. Fail if the key is not found


associationAt: key ifAbsent: aBlock
Answer the key/value Association for the given key. Evaluate aBlock (answering the result) if the key is not found


at: key
Answer the value associated to the given key. Fail if the key is not found


at: key ifAbsent: aBlock
Answer the value associated to the given key, or the result of evaluating aBlock if the key is not found


at: aKey ifAbsentPut: aBlock
Answer the value associated to the given key. If the key is not found, evaluate aBlock and associate the result to aKey before returning.


at: aKey ifPresent: aBlock
If aKey is absent, answer nil. Else, evaluate aBlock passing the associated value and answer the result of the invocation


at: key put: value
Store value as associated to the given key


keyAtValue: value
Answer the key associated to the given value. Evaluate exceptionBlock (answering the result) if the value is not found


keyAtValue: value ifAbsent: exceptionBlock
Answer the key associated to the given value. Evaluate exceptionBlock (answering the result) if the value is not found. IMPORTANT: == is used to compare values


keys
Answer a kind of Set containing the keys of the receiver


values
Answer a Bag containing the values of the receiver


[ Next: | Previous:Dictionary-accessing | Up:Dictionary ]

Dictionary: awful ST-80 compatibility hacks

findKeyIndex: key
Tries to see if key exists as a the key of an indexed variable. As soon as nil or an association with the correct key is found, the index of that slot is answered


[ Next: | Previous:Dictionary-awful ST-80 compatibility hacks | Up:Dictionary ]

Dictionary: dictionary enumerating

associationsDo: aBlock
Pass each association in the dictionary to aBlock


collect: aBlock
Answer a new dictionary where the keys are the same and the values are obtained by passing each value to aBlock and collecting the return values


do: aBlock
Pass each value in the dictionary to aBlock


keysAndValuesDo: aBlock
Pass each key/value pair in the dictionary as two distinct parameters to aBlock


keysDo: aBlock
Pass each key in the dictionary to aBlock


reject: aBlock
Answer a new dictionary containing the key/value pairs for which aBlock returns false. aBlock only receives the value part of the pairs.


select: aBlock
Answer a new dictionary containing the key/value pairs for which aBlock returns true. aBlock only receives the value part of the pairs.


[ Next: | Previous:Dictionary-dictionary enumerating | Up:Dictionary ]

Dictionary: dictionary removing

remove: anObject
This method should not be called for instances of this class.


remove: anObject ifAbsent: aBlock
This method should not be called for instances of this class.


removeAllKeys: keys
Remove all the keys in keys, without raising any errors


removeAllKeys: keys ifAbsent: aBlock
Remove all the keys in keys, passing the missing keys as parameters to aBlock as they're encountered


removeAssociation: anAssociation
Remove anAssociation's key from the dictionary


removeKey: key
Remove the passed key from the dictionary, fail if it is not found


removeKey: key ifAbsent: aBlock
Remove the passed key from the dictionary, answer the result of evaluating aBlock if it is not found


[ Next: | Previous:Dictionary-dictionary removing | Up:Dictionary ]

Dictionary: dictionary testing

includes: anObject
Answer whether the receiver contains anObject as one of its values


includesAssociation: anAssociation
Answer whether the receiver contains the key which is anAssociation's key and its value is anAssociation's value


includesKey: key
Answer whether the receiver contains the given key


occurrencesOf: aValue
Answer whether the number of occurrences of aValue as one of the receiver's values


[ Next: | Previous:Dictionary-dictionary testing | Up:Dictionary ]

Dictionary: printing

printOn: aStream
Print a representation of the receiver on aStream


[ Next: | Previous:Dictionary-printing | Up:Dictionary ]

Dictionary: storing

storeOn: aStream
Print Smalltalk code compiling to the receiver on aStream


[ Previous:Dictionary-storing | Up:Dictionary ]

Dictionary: testing

= aDictionary
Answer whether the receiver and aDictionary are equal


hash
Answer the hash value for the receiver


[ ]

DirectedMessage

Category: Language-Implementation
I represent a message send: I contain the receiver, selector and arguments for a message.


[ Next: | Up:DirectedMessage ]

DirectedMessage class: creating instances

selector: aSymbol arguments: anArray
This method should not be called for instances of this class.


selector: aSymbol arguments: anArray receiver: anObject
Create a new instance of the receiver


[ Next: | Previous:DirectedMessage class-creating instances | Up:DirectedMessage ]

DirectedMessage: accessing

receiver
Answer the receiver


receiver: anObject
Change the receiver


[ Previous:DirectedMessage-accessing | Up:DirectedMessage ]

DirectedMessage: basic

printOn: aStream
Print a representation of the receiver on aStream


send
Send the message


[ ]

Directory

Category: Streams-Files


[ Next: | Up:Directory ]

Directory class: C functions

primRemove: fileName
C call-out to rmdir. Do not modify!


primWorking: dirName
C call-out to chdir. Do not modify!


working
C call-out to getCurDirName. Do not modify!


[ Next: | Previous:Directory class-C functions | Up:Directory ]

Directory class: file operations

working: dirName
Change the current working directory to dirName.


[ Next: | Previous:Directory class-file operations | Up:Directory ]

Directory class: reading system defaults

home
Answer the path to the user's home directory


image
Answer the path to GNU Smalltalk's image file


kernel
Answer the path to the GNU Smalltalk kernel's Smalltalk source files


[ Next: | Previous:Directory class-reading system defaults | Up:Directory ]

Directory: accessing

contents
Answer an Array with the names of the files in the directory represented by the receiver.


do: aBlock
Evaluate aBlock once for each file in the directory represented by the receiver, passing its name.


[ Previous:Directory-accessing | Up:Directory ]

Directory: C functions

extractDirentName: dirent
C call-out to extractDirentName. Do not modify!


readDir: dirObject
C call-out to readdir. Do not modify!


rewindDir: dirObject
C call-out to rewinddir. Do not modify!


[ ]

DLD

Category: Language-C interface
...and Gandalf said: "Many folk like to know beforehand what is to be set on the table; but those who have laboured to prepare the feast like to keep their secret; for wonder makes the words of praise louder."

I am just an ancillary class used to reference some C functions. Most of my actual functionality is used by redefinitions of methods in CFunctionDescriptor and Behavior.


[ Next: | Up:DLD ]

DLD class: C functions

defineCFunc: aName as: aFuncAddr
C call-out to defineCFunc. Do not modify!


library: libHandle getFunc: aFuncString
C call-out to dldGetFunc. Do not modify!


linkFile: aFileName
C call-out to dldLink. Do not modify!


[ Previous:DLD class-C functions | Up:DLD ]

DLD class: Dynamic Linking

addLibrary: library
Add library to the search path of libraries to be used by DLD


defineExternFunc: aFuncName
This method calls #primDefineExternFunc: to try to link to a function with the given name, and answers whether the linkage was successful. You can redefine this method to restrict the ability to do dynamic linking.


defineExternFunc: aFuncName
withSelectorArgs: selector forClass: aClass returning: aReturnType args: argsArray Obsolete - Mantained for compatibility. This method does NOT look for statically linked functions.


initialize
Private - Initialize the receiver's class variables


libraryList
Answer a copy of the search path of libraries to be used by DLD


primDefineExternFunc: aFuncName
This method tries to link to a function with the given name, and answers whether the linkage was successful. It should not be overridden.


reset
Called on startup - Make DLD forget the handles of the libraries it used in the last session.


[ ]

DumperProxy

Category: Streams-Files
I am an helper class for ObjectDumper. When an object cannot be saved in the standard way, you can register a subclass of me to provide special means to save that object.


[ Next: | Up:DumperProxy ]

DumperProxy class: instance creation

on: anObject
Answer a proxy to be used to save anObject. IMPORTANT: the newly constructed DumperProxy must NOT have anObject in one of its in- stance variable, because that would result in an infinite loop!


[ Previous:DumperProxy class-instance creation | Up:DumperProxy ]

DumperProxy: reconstructing

object
Reconstruct the object stored in the proxy and answer it


[ ]

Exception

Category: Language-Exceptions
My instances describe a single event that can be trapped using #on:do:..., contain whether such execution can be resumed after such an event, a description of what happened, and a block that is used as an handler by default. Using my methods you can raise exceptions and create new exceptions. Exceptions are organized in a kind of hierarchy (different from the class hierarchy): intercepting an exception will intercept all its children too.


[ Next: | Up:Exception ]

Exception class: instance creation

new
Create a new exception whose parent is ExAll


[ Next: | Previous:Exception class-instance creation | Up:Exception ]

Exception: accessing

defaultHandler
Answer the default handler for the receiver


defaultHandler: aBlock
Set the default handler of the receiver to aBlock. A Signal object will be passed to aBlock


description
Answer a description of the receiver


description: aString
Set the description of the receiver to aString


isResumable
Answer true if the receiver is resumable


isResumable: aBoolean
Set the resumable flag of the receiver to aBoolean


parent
Answer the parent of the receiver


[ Next: | Previous:Exception-accessing | Up:Exception ]

Exception: basic

copy
Answer a copy of the receiver


[ Next: | Previous:Exception-basic | Up:Exception ]

Exception: enumerating

allExceptionsDo: aBlock
Private - Evaluate aBlock for every exception in the receiver. As it contains just one exception, evaluate it just once, passing the receiver


handles: exception
Answer whether the receiver handles `exception'.


[ Next: | Previous:Exception-enumerating | Up:Exception ]

Exception: exception handling

signal
Raise the exception described by the receiver, passing no parameters


signalWith: arg
Raise the exception described by the receiver, passing the parameter arg


signalWith: arg with: arg2
Raise the exception described by the receiver, passing the parameters arg and arg2


signalWithArguments: args
Raise the exception described by the receiver, passing the parameters in args


[ Previous:Exception-exception handling | Up:Exception ]

Exception: instance creation

newChild
Answer a child exception of the receiver. Its properties are set to those of the receiver


[ ]

ExceptionCollection

Category: Language-Exceptions
My instances are not real exceptions: they can only be used as arguments to #on:do:... methods in BlockClosure. They act as shortcuts that allows you to use the same handler for many exceptions without having to write duplicate code


[ Next: | Up:ExceptionCollection ]

ExceptionCollection class: instance creation

new
Private - Answer a new, empty ExceptionCollection


[ Previous:ExceptionCollection class-instance creation | Up:ExceptionCollection ]

ExceptionCollection: enumerating

allExceptionsDo: aBlock
Private - Evaluate aBlock for every exception in the receiver. Answer the receiver


handles: exception
Answer whether the receiver handles `exception'.


[ ]

ExceptionHandler

Category: Language-Exceptions
I am used internally by the exception handling system. My instances record the handler for an exception, the receiver of the #on:do:... method that established that handler, and a block that leaves that #on:do:... method


[ Next: | Up:ExceptionHandler ]

ExceptionHandler class: instance creation

onDoBlock: wdBlock exitBlock: eBlock handlerBlock: hBlock
Answer an ExceptionHandler instance with the given values for its instance variables.


[ Previous:ExceptionHandler class-instance creation | Up:ExceptionHandler ]

ExceptionHandler: accessing

exitBlock
Answer `exitBlock'.


handlerBlock
Answer `handlerBlock'.


isDisabled
Answer whether the receiver is disabled by a #valueWithUnwind.


onDoBlock
Answer `onDoBlock'.


onDoBlock: wdBlock exitBlock: eBlock handlerBlock: hBlock
Initialize the receiver's instance variables.


[ ]

False

Category: Language-Data types
I always tell lies. I have a single instance in the system, which represents the value false.


[ Next: | Up:False ]

False: basic

& aBoolean
We are false - anded with anything, we always answer false


and: aBlock
We are false - anded with anything, we always answer false


eqv: aBoolean
Answer whether the receiver and aBoolean represent the same boolean value


ifFalse: falseBlock
We are false - evaluate the falseBlock


ifFalse: falseBlock ifTrue: trueBlock
We are false - evaluate the falseBlock


ifTrue: trueBlock
We are false - answer nil


ifTrue: trueBlock ifFalse: falseBlock
We are false - evaluate the falseBlock


not
We are false - answer true


or: aBlock
We are false - ored with anything, we always answer the other operand, so evaluate aBlock


xor: aBoolean
Answer whether the receiver and aBoolean represent different boolean values


| aBoolean
We are false - ored with anything, we always answer the other operand


[ Next: | Previous:False-basic | Up:False ]

False: C hacks

asCBooleanValue
Answer `0'.


[ Previous:False-C hacks | Up:False ]

False: printing

printOn: aStream
Print a representation of the receiver on aStream


[ ]

File

Category: Streams-Files


[ Next: | Up:File ]

File class: C functions

errno
C call-out to errno. Do not modify!


primRemove: fileName
C call-out to unlink. Do not modify!


primRename: oldFileName to: newFileName
C call-out to rename. Do not modify!


[ Next: | Previous:File class-C functions | Up:File ]

File class: file operations

checkError
Return whether an error had been reported or not. If there had been one, raise an exception too


checkError: errno
The error with the C code `errno' has been reported. If errno >= 1, raise an exception


remove: fileName
Remove the file with the given path name


rename: oldFileName to: newFileName
Rename the file with the given path name oldFileName to newFileName


[ Next: | Previous:File class-file operations | Up:File ]

File class: initialization

initialize
Initialize the receiver's class variables


[ Next: | Previous:File class-initialization | Up:File ]

File class: instance creation

name: aName
Answer a new file with the given path. The path is not validated until some of the fields of the newly created objects are accessed


[ Next: | Previous:File class-instance creation | Up:File ]

File class: reading system defaults

image
Answer the full path to the image being used.


[ Next: | Previous:File class-reading system defaults | Up:File ]

File class: testing

exists: fileName
Answer whether a file with the given name exists


[ Next: | Previous:File class-testing | Up:File ]

File: accessing

creationTime
Answer the creation time of the file identified by the receiver. On some operating systems, this could actually be the last change time (the `last change time' has to do with permissions, ownership and the like).


lastAccessTime
Answer the last access time of the file identified by the receiver


lastChangeTime
Answer the last change time of the file identified by the receiver (the `last change time' has to do with permissions, ownership and the like). On some operating systems, this could actually be the file creation time.


lastModifyTime
Answer the last modify time of the file identified by the receiver (the `last modify time' has to do with the actual file contents).


name
Answer the name of the file identified by the receiver


refresh
Refresh the statistics for the receiver


size
Answer the size of the file identified by the receiver


[ Next: | Previous:File-accessing | Up:File ]

File: C functions

closeDir: dirObject
C call-out to closedir. Do not modify!


openDir: dirName
C call-out to opendir. Do not modify!


statOn: fileName into: statStruct
C call-out to stat. Do not modify!


[ Next: | Previous:File-C functions | Up:File ]

File: file operations

contents
Open a read-only FileStream on the receiver, read its contents, close the stream and answer the contents


open: mode
Open the receiver in the given mode (as answered by FileStream's class constant methods)


readStream
Open a read-only FileStream on the receiver


remove
Remove the file identified by the receiver


renameTo: newName
Remove the file identified by the receiver


writeStream
Open a write-only FileStream on the receiver


[ Previous:File-file operations | Up:File ]

File: testing

exists
Answer whether a file with the name contained in the receiver does exist.


isDirectory
Answer whether a file with the name contained in the receiver does exist and identifies a directory.


isFile
Answer whether a file with the name contained in the receiver does exist and does not identify a directory.


[ ]

FileSegment

Category: Language-Implementation
My instances represent sections of files. I am primarily used by the compiler to record source code locations. I am not a part of the normal Smalltalk-80 kernel; I am specific to the GNU Smalltalk implementation.


[ Next: | Up:FileSegment ]

FileSegment class: basic

on: aFile startingAt: startPos for: lengthInteger
Create a new FileSegment referring to the contents of the given file, from the startPos-th byte and for lengthInteger bytes


[ Next: | Previous:FileSegment class-basic | Up:FileSegment ]

FileSegment: basic

asString
Answer a String containing the required segment of the file


fileName
Answer the name of the file containing the segment


filePos
Answer the position in the file where the segment starts


[ Previous:FileSegment-basic | Up:FileSegment ]

FileSegment: equality

= aFileSegment
Answer whether the receiver and aFileSegment are equal.


hash
Answer an hash value for the receiver.


[ ]

FileStream

Category: Streams-Files
My instances are what conventional programmers think of as files. My instance creation methods accept the name of a disk file (or any named file object, such as /dev/rmt0 on UNIX or MTA0: on VMS).


[ Next: | Up:FileStream ]

FileStream class: basic

append
Open for writing. The file is created if it does not exist. The stream is positioned at the end of the file.


create
Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.


new
This method should not be called for instances of this class.


open: fileName
Open fileName in read-write mode - fail if the file cannot be opened. Else answer a new FileStream. The file will be automatically closed upon GC if the object is not referenced anymore, but you should close it with #close anyway. To keep a file open, send it #removeToBeFinalized


open: fileName mode: fileMode
Open fileName in the required mode - answered by #append, #create, #readWrite, #read or #write - and fail if the file cannot be opened. Else answer a new FileStream. For mode anyway you can use any standard C non-binary fopen mode. The file will be automatically closed upon GC if the object is not referenced anymore, but it is better to close it as soon as you're finished with it anyway, using #close. To keep a file open even when no references exist anymore, send it #removeToBeFinalized


open: fileName mode: fileMode ifFail: aBlock
Open fileName in the required mode - answered by #append, #create, #readWrite, #read or #write - and evaluate aBlock if the file cannot be opened. Else answer a new FileStream. For mode anyway you can use any The file will be automatically closed upon GC if the object is not referenced anymore, but it is better to close it as soon as you're finished with it anyway, using #close. To keep a file open even when no references exist anymore, send it #removeToBeFinalized


popen: commandName dir: direction
Open a pipe on the given command and fail if the file cannot be opened. Else answer a new FileStream. The pipe will not be automatically closed upon GC, even if the object is not referenced anymore, because when you close a pipe you have to wait for the associated process to terminate. To enforce automatic closing of the pipe, send it #addToBeFinalized. direction is returned by #read or #write ('r' or 'w') and is interpreted from the point of view of Smalltalk: reading means Smalltalk reads the standard output of the command, writing means Smalltalk writes the standard input of the command. The other channel (stdin when reading, stdout when writing) is the same as GST's, unless commandName alters it.


popen: commandName dir: direction ifFail: aBlock
Open a pipe on the given command and evaluate aBlock file cannot be opened. Else answer a new FileStream. The pipe will not be automatically closed upon GC, even if the object is not referenced anymore, because when you close a pipe you have to wait for the associated process to terminate. To enforce automatic closing of the pipe, send it #addToBeFinalized. direction is interpreted from the point of view of Smalltalk: reading means that Smalltalk reads the standard output of the command, writing means that Smalltalk writes the standard input of the command


read
Open text file for reading. The stream is positioned at the beginning of the file.


readWrite
Open for reading and writing. The stream is positioned at the beginning of the file.


write
Truncate file to zero length or create text file for writing. The stream is positioned at the beginning of the file.


[ Next: | Previous:FileStream class-basic | Up:FileStream ]

FileStream class: file-in

fileIn: aFileName
File in the aFileName file


fileIn: aFileName ifMissing: aSymbol
Conditionally do a file in, only if the key (often a class) specified by 'aSymbol' is not present in the Smalltalk system dictionary already


fileIn: aFileName ifTrue: aBoolean
Conditionally do a file in, only if the supplied boolean is true


fileIn: aFileName line: lineInteger from: realFileName at: aCharPos
File in the aFileName file giving errors such as if it was loaded from the given line, file name and starting position (instead of 1)


generateMakefileOnto: aStream
Generate a make file for the file-ins since record was last set to true. Store it on aStream


record: recordFlag
Set whether Smalltalk should record information aboutnested file-ins. When recording is enabled, use #generateMakefileOnto: to automatically generate a valid makefile for the intervening file-ins.


require: assoc
Conditionally do a file in from the value of assoc, only if the key of assoc is not present in the Smalltalk system dictionary already


verbose: verboseFlag
Set whether Smalltalk should output debugging messages when filing in


[ Next: | Previous:FileStream class-file-in | Up:FileStream ]

FileStream class: initialization

initialize
Initialize the receiver's class variables


[ Next: | Previous:FileStream class-initialization | Up:FileStream ]

FileStream: accessing

isPipe
Return whether the file is a pipe or an actual disk file


name
Return the name of the file


[ Next: | Previous:FileStream-accessing | Up:FileStream ]

FileStream: basic

close
Close the file


contents
Answer the whole contents of the file


copyFrom: start to: end
Answer the contents of the file between the two given positions


finalize
Close the file if it is still open by the time the object becomes garbage.


flush
Flush the output buffer


next
Return the next character in the file, or nil at eof


nextByte
Return the next byte in the file, or nil at eof


nextPut: aChar
Store aChar on the file


nextPutByte: anInteger
Store aChar on the file


nextPutByteArray: aByteArray
Store aByteArray on the file


peek
Peek a character in the file, don't change the position


peekFor: aCharacter
Peek a character in the file, don't change the position


position
Return the position of the file pointer in the receiver


position: bytePosition
Set the position of the file pointer in the receiver


reset
Reset the stream to its beginning


size
Return the current size of the file, in bytes


[ Next: | Previous:FileStream-basic | Up:FileStream ]

FileStream: built ins

fileIn
File in the contents of the receiver


fileInLine: lineNum fileName: aString at: charPosInt
Private - Much like a preprocessor #line directive


fileOp: ioFuncIndex
Private - Used to limit the number of primitives used by FileStreams


fileOp: ioFuncIndex ifFail: aBlock
Private - Used to limit the number of primitives used by FileStreams.


fileOp: ioFuncIndex with: arg1
Private - Used to limit the number of primitives used by FileStreams


fileOp: ioFuncIndex with: arg1 ifFail: aBlock
Private - Used to limit the number of primitives used by FileStreams.


fileOp: ioFuncIndex with: arg1 with: arg2
Private - Used to limit the number of primitives used by FileStreams


fileOp: ioFuncIndex with: arg1 with: arg2 ifFail: aBlock
Private - Used to limit the number of primitives used by FileStreams.


[ Next: | Previous:FileStream-built ins | Up:FileStream ]

FileStream: class type methods

isBinary
We answer characters, so answer false


isText
We answer characters, so answer true


species
Answer `String'.


[ Next: | Previous:FileStream-class type methods | Up:FileStream ]

FileStream: overriding inherited methods

isEmpty
Answer whether the receiver is empty


next: anInteger
return the next 'anInteger' characters from the stream, as a String.


nextPutAll: aCollection
Put all the characters in aCollection in the file


reverseContents
Return the contents of the file from the last byte to the first


setToEnd
Reset the file pointer to the end of the file


skip: anInteger
Skip anInteger bytes in the file


[ Next: | Previous:FileStream-overriding inherited methods | Up:FileStream ]

FileStream: printing

printOn: aStream
Print a representation of the receiver on aStream


[ Previous:FileStream-printing | Up:FileStream ]

FileStream: testing

atEnd
Answer whether data has come to an end


[ ]

Float

Category: Language-Data types
My instances represent floating point numbers that have 64 bits of precision (well, less than that in precision; they are precisely the same as C's "double" datatype). Besides the standard numerical operations, I provide transcendental operations too.


[ Next: | Up:Float ]

Float class: basic

e
Returns the value of e. Hope is that it is precise enough


epsilon
Return the smallest Float x for which is 1 + x ~= 1


infinity
Return a Float that represents positive infinity. I hope that it is big enough, IEEE 8 byte floating point values (C doubles) overflow at 1e308.


largest
Return the largest normalized Float that is not infinite.


log10Base2
Returns the value of log2 10. Hope is that it is precise enough


mantissaBits
Answer `53'.


nan
Return a Float that represents a mathematically indeterminate value (e.g. Inf - Inf, Inf / Inf)


negativeInfinity
Return a Float that represents negative infinity. I hope that it is big enough, IEEE 8 byte floating point values (C doubles) overflow at -1e308.


pi
Returns the value of pi. Hope is that it is precise enough


smallest
Return the smallest normalized Float that is not infinite.


smallestAbs
Return the smallest normalized Float that is > 0


[ Next: | Previous:Float class-basic | Up:Float ]

Float class: byte-order dependancies

exponentByte
Not commented.


leastSignificantMantissaByte
Not commented.


[ Next: | Previous:Float class-byte-order dependancies | Up:Float ]

Float class: converting

coerce: aNumber
Answer aNumber converted to a Float


[ Next: | Previous:Float class-converting | Up:Float ]

Float: arithmetic

// aNumber
Return the integer quotient of dividing the receiver by aNumber with truncation towards negative infinity.


\\ aNumber
Return the remainder of dividing the receiver by aNumber with truncation towards negative infinity.


integerPart
Return the receiver's integer part


[ Next: | Previous:Float-arithmetic | Up:Float ]

Float: built ins

* arg
Multiply the receiver and arg and answer another Number


+ arg
Sum the receiver and arg and answer another Number


- arg
Subtract arg from the receiver and answer another Number


/ arg
Divide the receiver by arg and answer another Float


< arg
Answer whether the receiver is less than arg


<= arg
Answer whether the receiver is less than or equal to arg


= arg
Answer whether the receiver is equal to arg


> arg
Answer whether the receiver is greater than arg


>= arg
Answer whether the receiver is greater than or equal to arg


arcCos
Answer the arc-cosine of the receiver


arcSin
Answer the arc-sine of the receiver


arcTan
Answer the arc-tangent of the receiver


ceiling
Answer the integer part of the receiver, truncated towards +infinity


cos
Answer the cosine of the receiver


exp
Answer 'e' (2.718281828459...) raised to the receiver


exponent
Answer the exponent of the receiver in mantissa*2^exponent representation ( |mantissa|<=1 )


floor
Answer the integer part of the receiver, truncated towards -infinity


fractionPart
Answer the fractional part of the receiver


ln
Answer the logarithm of the receiver in base 'e' (2.718281828459...)


raisedTo: aNumber
Answer the receiver raised to its aNumber power


sin
Answer the sine of the receiver


sqrt
Answer the square root of the receiver


tan
Answer the tangent of the receiver


timesTwoPower: arg
Answer the receiver multiplied by 2^arg


truncated
Truncate the receiver towards zero and answer the result


~= arg
Answer whether the receiver is not equal to arg


[ Next: | Previous:Float-built ins | Up:Float ]

Float: coercing

asExactFraction
Convert the receiver into a fraction with optimal approximation, but with usually huge terms.


asFloat
Just defined for completeness. Return the receiver.


asFraction
Convert the receiver into a fraction with a good (but undefined) approximation


coerce: aNumber
Coerce aNumber to the receiver's class


estimatedLog
Answer an estimate of (self abs floorLog: 10)


generality
Answer the receiver's generality


hash
Returns the hash value for the receiver (a Float). If it's representable as an integer, we use that value, since it's likely to be much more random, but if not, we scale the number so that it's within the integer range and then return the integer part


unity
Coerce 1 to the receiver's class


zero
Coerce 0 to the receiver's class


[ Next: | Previous:Float-coercing | Up:Float ]

Float: printing

printOn: aStream
Print a representation of the receiver on aStream


[ Next: | Previous:Float-printing | Up:Float ]

Float: storing

storeOn: aStream
Print a representation of the receiver on aStream


[ Next: | Previous:Float-storing | Up:Float ]

Float: testing

isInfinite
Answer whether the receiver represents positive or negative infinity


isNaN
Answer whether the receiver represents a NaN


negative
Answer whether the receiver is negative


positive
Answer whether the receiver is positive


sign
Answer 1 if the receiver is greater than 0, -1 if less than 0, else 0. Handle IEEE-754 negative-zero by reporting a sign of -1


strictlyPositive
Answer whether the receiver is > 0


[ Previous:Float-testing | Up:Float ]

Float: testing functionality

isFloat
Answer `true'.


[ ]

Fraction

Category: Language-Data types
I represent rational numbers in the form (p/q) where p and q are integers. The arithmetic operations *, +, -, /, on fractions, all return a reduced fraction.


[ Next: | Up:Fraction ]

Fraction class: converting

coerce: aNumber
Answer aNumber converted to a Fraction


[ Next: | Previous:Fraction class-converting | Up:Fraction ]

Fraction class: instance creation

initialize
Initialize the receiver's class variables


numerator: nInteger denominator: dInteger
Answer a new instance of fraction (nInteger/dInteger)


[ Next: | Previous:Fraction class-instance creation | Up:Fraction ]

Fraction: accessing

denominator
Answer the receiver's denominator


numerator
Answer the receiver's numerator


[ Next: | Previous:Fraction-accessing | Up:Fraction ]

Fraction: arithmetic

* aNumber
Multiply two numbers and answer the result.


+ aNumber
Sum two numbers and answer the result.


- aNumber
Subtract aNumber from the receiver and answer the result.


/ aNumber
Divide the receiver by aNumber and answer the result.


// aNumber
Return the integer quotient of dividing the receiver by aNumber with truncation towards negative infinity.


\\ aNumber
Return the remainder from dividing the receiver by aNumber, (using //).


estimatedLog
Answer an estimate of (self abs floorLog: 10)


[ Next: | Previous:Fraction-arithmetic | Up:Fraction ]

Fraction: coercing

coerce: aNumber
Coerce aNumber to the receiver's class


generality
Return the receiver's generality


truncated
Truncate the receiver and return the truncated result


unity
Coerce 1 to the receiver's class


zero
Coerce 0 to the receiver's class


[ Next: | Previous:Fraction-coercing | Up:Fraction ]

Fraction: comparing

< arg
Test if the receiver is less than arg.


<= arg
Test if the receiver is less than or equal to arg.


= arg
Test if the receiver equals arg.


> arg
Test if the receiver is more than arg.


>= arg
Test if the receiver is greater than or equal to arg.


hash
Answer an hash value for the receiver


[ Next: | Previous:Fraction-comparing | Up:Fraction ]

Fraction: converting

asFloat
Answer the receiver converted to a Float


asFraction
Answer the receiver converted to a Fraction


[ Next: | Previous:Fraction-converting | Up:Fraction ]

Fraction: optimized cases

negated
Return the receiver, with its sign changed.


raisedToInteger: anInteger
Return self raised to the anInteger-th power.


reciprocal
Return the reciprocal of the receiver.


squared
Return the square of the receiver.


[ Next: | Previous:Fraction-optimized cases | Up:Fraction ]

Fraction: printing

printOn: aStream
Print a representation of the receiver on aStream


storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Previous:Fraction-printing | Up:Fraction ]

Fraction: testing

isRational
Answer whether the receiver is rational - true


[ ]

IdentityDictionary

Category: Collections-Keyed
I am similar to dictionary, except that my representation is different, and I use the object identity comparision message == to determine equivalence of indices.


[ Next: | Up:IdentityDictionary ]

IdentityDictionary class: instance creation

new
Create a new dictionary with a default size


new: anInteger
Create a new dictionary with the given size


[ Next: | Previous:IdentityDictionary class-instance creation | Up:IdentityDictionary ]

IdentityDictionary: accessing

add: anAssociation
Add the anAssociation key to the receiver


associationAt: key ifAbsent: aBlock
Answer the key/value Association for the given key. Evaluate aBlock (answering the result) if the key is not found


at: key ifAbsent: aBlock
Answer the value associated to the given key, or the result of evaluating aBlock if the key is not found


at: aKey ifPresent: aBlock
If aKey is absent, answer nil. Else, evaluate aBlock passing the associated value and answer the result of the invocation


at: key put: value
Store value as associated to the given key


[ Next: | Previous:IdentityDictionary-accessing | Up:IdentityDictionary ]

IdentityDictionary: dictionary enumerating

associationsDo: aBlock
Pass each association in the dictionary to aBlock


keysAndValuesDo: aBlock
Pass each key/value pair in the dictionary as two distinct parameters to aBlock


[ Next: | Previous:IdentityDictionary-dictionary enumerating | Up:IdentityDictionary ]

IdentityDictionary: dictionary removing

removeKey: key ifAbsent: aBlock
Remove the passed key from the dictionary, answer the result of evaluating aBlock if it is not found


[ Next: | Previous:IdentityDictionary-dictionary removing | Up:IdentityDictionary ]

IdentityDictionary: rehashing

rehash
Rehash the receiver


[ Previous:IdentityDictionary-rehashing | Up:IdentityDictionary ]

IdentityDictionary: storing

storeOn: aStream
Print Smalltalk code compiling to the receiver on aStream


[ ]

IdentitySet

Category: Collections-Unordered
I am the typical set object; I can store any objects uniquely. I use the == operator to determine duplication of objects.


[ ]

Integer

Category: Language-Data types
I am the integer class of the GNU Smalltalk system. My instances can represent signed 30 bit integers and are as efficient as possible.


[ Next: | Up:Integer ]

Integer class: converting

coerce: aNumber
Answer aNumber converted to a kind of Integer


[ Next: | Previous:Integer class-converting | Up:Integer ]

Integer class: getting limits

bits
Answer the number of bits (excluding the sign) that can be represented directly in an object pointer


largest
Answer the largest integer represented directly in an object pointer


smallest
Answer the smallest integer represented directly in an object pointer


[ Next: | Previous:Integer class-getting limits | Up:Integer ]

Integer class: testing

isIdentity
Answer whether x = y implies x == y for instances of the receiver


[ Next: | Previous:Integer class-testing | Up:Integer ]

Integer: accessing

denominator
Answer `1'.


numerator
Answer the receiver.


[ Next: | Previous:Integer-accessing | Up:Integer ]

Integer: bit operators

allMask: anInteger
True if all 1 bits in anInteger are 1 in the receiver


anyMask: anInteger
True if any 1 bits in anInteger are 1 in the receiver


bitAt: index
Answer the index-th bit of the receiver (LSB: index = 1


bitClear: aMask
Answer an Integer equal to the receiver, except that all the bits that are set in aMask are cleared.


bitInvert
Return the 1's complement of the bits of the receiver


clearBit: index
Clear the index-th bit of the receiver and answer a new Integer


highBit
Return the index of the highest order 1 bit of the receiver


isBitSet: index
Answer whether the index-th bit of the receiver is set


noMask: anInteger
True if no 1 bits in anInteger are 1 in the receiver


setBit: index
Set the index-th bit of the receiver and answer a new Integer


[ Next: | Previous:Integer-bit operators | Up:Integer ]

Integer: built ins

* arg
Multiply the receiver and arg and answer another Number


+ arg
Sum the receiver and arg and answer another Number


- arg
Subtract arg from the receiver and answer another Number


/ arg
Divide the receiver by arg and answer another Integer or Fraction


// arg
Dividing receiver by arg (with truncation towards -infinity) and answer the result


< arg
Answer whether the receiver is less than arg


<= arg
Answer whether the receiver is less than or equal to arg


= arg
Answer whether the receiver is equal to arg


== arg
Answer whether the receiver is the same object as arg


> arg
Answer whether the receiver is greater than arg


>= arg
Answer whether the receiver is greater than or equal to arg


\\ arg
Calculate the remainder of dividing receiver by arg (with truncation towards -infinity) and answer it


asFloat
Convert the receiver to a Float, answer the result


asObject
Answer the object whose index is in the receiver, fail if no object found at that index


asObjectNoFail
Answer the object whose index is in the receiver, or nil if no object is found at that index


bitAnd: arg
Do a bitwise AND between the receiver and arg, answer the result


bitOr: arg
Do a bitwise OR between the receiver and arg, answer the result


bitShift: arg
Shift the receiver by arg places to the left if arg > 0, by arg places to the right if arg < 0, answer another Number


bitXor: arg
Do a bitwise XOR between the receiver and arg, answer the result


quo: arg
Dividing receiver by arg (with truncation towards zero) and answer the result


~= arg
Answer whether the receiver is not equal to arg


~~ arg
Answer whether the receiver is not the same object as arg


[ Next: | Previous:Integer-built ins | Up:Integer ]

Integer: Coercion methods (heh heh heh)

asCharacter
Return self as an ascii character


ceiling
Return the receiver - it's already truncated


coerce: aNumber
Coerce aNumber to the receiver's class


floor
Return the receiver - it's already truncated


generality
Return the receiver's generality


rounded
Return the receiver - it's already truncated


truncated
Return the receiver - it's already truncated


unity
Coerce 1 to the receiver's class


zero
Coerce 0 to the receiver's class


[ Next: | Previous:Integer-Coercion methods (heh heh heh) | Up:Integer ]

Integer: converting

asFraction
Return the receiver converted to a fraction


[ Next: | Previous:Integer-converting | Up:Integer ]

Integer: extension

alignTo: anInteger
Answer the receiver, truncated to the first higher or equal multiple of anInteger (which must be a power of two)


[ Next: | Previous:Integer-extension | Up:Integer ]

Integer: Math methods

estimatedLog
Answer an estimate of (self abs floorLog: 10)


even
Return whether the receiver is even


factorial
Return the receiver's factorial


floorLog: radix
return (self log: radix) floor. Optimized to answer an integer.


gcd: anInteger
Return the greatest common divisor (Euclid's algorithm) between the receiver and anInteger


lcm: anInteger
Return the least common multiple between the receiver and anInteger


odd
Return whether the receiver is odd


[ Next: | Previous:Integer-Math methods | Up:Integer ]

Integer: Misc math operators

hash
Answer an hash value for the receiver


[ Next: | Previous:Integer-Misc math operators | Up:Integer ]

Integer: Other iterators

timesRepeat: aBlock
Evaluate aBlock a number of times equal to the receiver's value. Compiled in-line for no argument aBlocks without temporaries, and therefore not overridable.


[ Next: | Previous:Integer-Other iterators | Up:Integer ]

Integer: printing

printOn: aStream
Print on aStream the base 10 representation of the receiver


printOn: aStream base: b
Print on aStream the base b representation of the receiver


printString: baseInteger
Return the base b representation of the receiver


radix: baseInteger
Return the base b representation of the receiver, with BBr in front of it


storeOn: aStream base: b
Print on aStream Smalltalk code compiling to the receiver, represented in base b


[ Next: | Previous:Integer-printing | Up:Integer ]

Integer: storing

storeOn: aStream
Print on aStream the base 10 representation of the receiver


[ Previous:Integer-storing | Up:Integer ]

Integer: testing functionality

isInteger
Answer `true'.


isRational
Answer whether the receiver is rational - true


isSmallInteger
Answer `true'.


[ ]

Interval

Category: Collections-Sequenceable
My instances represent ranges of objects, typically Number type objects. I provide iteration/enumeration messages for producing all the members that my instance represents.


[ Next: | Up:Interval ]

Interval class: instance creation

from: startInteger to: stopInteger
Answer an Interval going from startInteger to the stopInteger, with a step of 1


from: startInteger to: stopInteger by: stepInteger
Answer an Interval going from startInteger to the stopInteger, with a step of stepInteger


[ Next: | Previous:Interval class-instance creation | Up:Interval ]

Interval: basic

at: index
Answer the index-th element of the receiver.


at: index put: anObject
This method should not be called for instances of this class.


collect: aBlock
Evaluate the receiver for each element in aBlock, collect in an array the result of the evaluations.


do: aBlock
Evaluate the receiver for each element in aBlock


reverse
Not commented.


size
Answer the number of elements in the receiver.


species
Answer `Array'.


[ Next: | Previous:Interval-basic | Up:Interval ]

Interval: printing

printOn: aStream
Print a representation for the receiver on aStream


[ Next: | Previous:Interval-printing | Up:Interval ]

Interval: storing

storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Previous:Interval-storing | Up:Interval ]

Interval: testing

= anInterval
Answer whether anInterval is the same interval as the receiver


hash
Answer an hash value for the receiver


[ ]

LargeInteger

Category: Language-Data types
I represent a large integer, which has to be stored as a long sequence of bytes. I have methods to do arithmetics and comparisons, but I need some help from my children, LargePositiveInteger and LargeNegativeInteger, to speed them up a bit.


[ Next: | Up:LargeInteger ]

LargeInteger class: testing

isIdentity
Answer whether x = y implies x == y for instances of the receiver


[ Next: | Previous:LargeInteger class-testing | Up:LargeInteger ]

LargeInteger: arithmetic

* aNumber
Multiply aNumber and the receiver, answer the result


/ aNumber
Divide aNumber and the receiver, answer the result (an Integer or Fraction)


// aNumber
Divide aNumber and the receiver, answer the result truncated towards -infinity


\\ aNumber
Divide aNumber and the receiver, answer the remainder truncated towards -infinity


estimatedLog
Answer an estimate of (self abs floorLog: 10)


negated
Answer the receiver's negated


quo: aNumber
Divide aNumber and the receiver, answer the result truncated towards 0


rem: aNumber
Divide aNumber and the receiver, answer the remainder truncated towards 0


[ Next: | Previous:LargeInteger-arithmetic | Up:LargeInteger ]

LargeInteger: bit operations

bitAnd: aNumber
Answer the receiver ANDed with aNumber


bitAt: aNumber
Answer the aNumber-th bit in the receiver, where the LSB is 1


bitInvert
Answer the receiver's 1's complement


bitOr: aNumber
Answer the receiver ORed with aNumber


bitShift: aNumber
Answer the receiver shifted by aNumber places


bitXor: aNumber
Answer the receiver XORed with aNumber


[ Next: | Previous:LargeInteger-bit operations | Up:LargeInteger ]

LargeInteger: built-ins

at: anIndex
Answer the anIndex-th byte in the receiver's representation


at: anIndex put: aNumber
Answer the anIndex-th byte in the receiver's representation


digitAt: anIndex
Answer the anIndex-th base-256 digit in the receiver's representation


digitAt: anIndex put: aNumber
Answer the anIndex-th base-256 digit in the receiver's representation


digitLength
Answer the number of base-256 digits in the receiver


hash
Answer an hash value for the receiver


primReplaceFrom: start to: stop with: replacementString
startingAt: replaceStart Private - Replace the characters from start to stop with new characters contained in replacementString (which, actually, can be any variable byte class, starting at the replaceStart location of replacementString


size
Answer the number of indexed instance variable in the receiver


[ Next: | Previous:LargeInteger-built-ins | Up:LargeInteger ]

LargeInteger: coercion

coerce: aNumber
Truncate the number; if needed, convert it to LargeInteger representation.


generality
Answer the receiver's generality


unity
Coerce 1 to the receiver's class


zero
Coerce 0 to the receiver's class


[ Next: | Previous:LargeInteger-coercion | Up:LargeInteger ]

LargeInteger: disabled

asObject
This method always fails. The number of OOPs is far less than the minimum number represented with a LargeInteger.


asObjectNoFail
Answer `nil'.


[ Next: | Previous:LargeInteger-disabled | Up:LargeInteger ]

LargeInteger: primitive operations

basicLeftShift: totalShift
Private - Left shift the receiver by aNumber places


basicRightShift: totalShift
Private - Right shift the receiver by 'shift' places


largeNegated
Private - Same as negated, but always answer a LargeInteger


[ Next: | Previous:LargeInteger-primitive operations | Up:LargeInteger ]

LargeInteger: testing

< aNumber
Answer whether the receiver is smaller than aNumber


<= aNumber
Answer whether the receiver is smaller than aNumber or equal to it


= aNumber
Answer whether the receiver and aNumber identify the same number


> aNumber
Answer whether the receiver is greater than aNumber


>= aNumber
Answer whether the receiver is greater than aNumber or equal to it


~= aNumber
Answer whether the receiver and aNumber identify the same number


[ Previous:LargeInteger-testing | Up:LargeInteger ]

LargeInteger: testing functionality

isSmallInteger
Answer `false'.


[ ]

LargeNegativeInteger

Category: Language-Data types
Just like my brother LargePositiveInteger, I provide a few methods that allow LargeInteger to determine the sign of a large integer in a fast way during its calculations. For example, I can tell him I am smaller than any LargePositiveInteger


[ Next: | Up:LargeNegativeInteger ]

LargeNegativeInteger: arithmetic

+ aNumber
Sum the receiver and aNumber, answer the result


- aNumber
Sum the receiver and aNumber, answer the result


highBit
Answer the receiver's highest bit's index


[ Next: | Previous:LargeNegativeInteger-arithmetic | Up:LargeNegativeInteger ]

LargeNegativeInteger: converting

asFloat
Answer the receiver converted to a Float


[ Previous:LargeNegativeInteger-converting | Up:LargeNegativeInteger ]

LargeNegativeInteger: numeric testing

abs
Answer the receiver's absolute value.


negative
Answer whether the receiver is < 0


positive
Answer whether the receiver is >= 0


sign
Answer the receiver's sign


strictlyPositive
Answer whether the receiver is > 0


[ ]

LargePositiveInteger

Category: Language-Data types
Just like my brother LargeNegativeInteger, I provide a few methods that allow LargeInteger to determine the sign of a large integer in a fast way during its calculations. For example, I can tell him I am larger than any LargeNegativeInteger


[ Next: | Up:LargePositiveInteger ]

LargePositiveInteger: arithmetic

+ aNumber
Sum the receiver and aNumber, answer the result


- aNumber
Subtract aNumber from the receiver, answer the result


gcd: anInteger
Calculate the GCD between the receiver and anInteger


highBit
Answer the receiver's highest bit's index


[ Next: | Previous:LargePositiveInteger-arithmetic | Up:LargePositiveInteger ]

LargePositiveInteger: converting

asFloat
Answer the receiver converted to a Float


reverseStringBase: radix on: str
Return in a string the base radix representation of the receiver in reverse order


[ Next: | Previous:LargePositiveInteger-converting | Up:LargePositiveInteger ]

LargePositiveInteger: helper byte-level methods

bytes: byteArray1 from: j compare: byteArray2
Private - Answer the sign of byteArray2 - byteArray1; the j-th byte of byteArray1 is compared with the first of byteArray2, the j+1-th with the second, and so on.


bytes: byteArray1 from: j subtract: byteArray2
Private - Sutract the bytes in byteArray2 from those in byteArray1


bytes: bytes multiply: anInteger
Private - Multiply the bytes in bytes by anInteger, which must be < 255. Put the result back in bytes.


bytesLeftShift: aByteArray
Private - Left shift by 1 place the bytes in aByteArray


bytesLeftShift: aByteArray big: totalShift
Private - Left shift the bytes in aByteArray by totalShift places


bytesLeftShift: aByteArray n: shift
Private - Left shift by shift places the bytes in aByteArray (shift <= 7)


bytesRightShift: aByteArray big: totalShift
Private - Right shift the bytes in aByteArray by totalShift places


bytesRightShift: bytes n: aNumber
Private - Right shift the bytes in `bytes' by 'aNumber' places (shift <= 7)


bytesTrailingZeros: bytes
Private - Answer the number of trailing zero bits in the receiver


primDivide: rhs
Private - Implements Knuth's divide and correct algorithm from `Seminumerical Algorithms' 3rd Edition, section 4.3.1 (which is basically an enhanced version of the divide `algorithm' for two-digit divisors which is taught in primary school!!!)


[ Next: | Previous:LargePositiveInteger-helper byte-level methods | Up:LargePositiveInteger ]

LargePositiveInteger: numeric testing

abs
Answer the receiver's absolute value


negative
Answer whether the receiver is < 0


positive
Answer whether the receiver is >= 0


sign
Answer the receiver's sign


strictlyPositive
Answer whether the receiver is > 0


[ Previous:LargePositiveInteger-numeric testing | Up:LargePositiveInteger ]

LargePositiveInteger: primitive operations

divide: aNumber using: aBlock
Private - Divide the receiver by aNumber (unsigned division). Evaluate aBlock passing the result ByteArray, the remainder ByteArray, and whether the division had a remainder


isSmall
Private - Answer whether the receiver is small enough to employ simple scalar algorithms for division and multiplication


multiply: aNumber
Private - Multiply the receiver by aNumber (unsigned multiply)


[ ]

LargeZeroInteger

Category: Language-Data types
I am quite a strange class. Indeed, the concept of a "large integer" that is zero is a weird one. Actually my only instance is zero but is represented like LargeIntegers, has the same generality as Lar- geIntegers, and so on. That only instance is stored in the class variable Zero, and is used in arithmetical methods, when we have to coerce a parameter that is zero.


[ Next: | Up:LargeZeroInteger ]

LargeZeroInteger: accessing

at: anIndex
Answer `0'.


hash
Answer `0'.


size
Answer `0'.


[ Next: | Previous:LargeZeroInteger-accessing | Up:LargeZeroInteger ]

LargeZeroInteger: arithmetic

* aNumber
Multiply aNumber and the receiver, answer the result


+ aNumber
Sum the receiver and aNumber, answer the result


- aNumber
Subtract aNumber from the receiver, answer the result


/ aNumber
Divide aNumber and the receiver, answer the result (an Integer or Fraction)


// aNumber
Divide aNumber and the receiver, answer the result truncated towards -infinity


\\ aNumber
Divide aNumber and the receiver, answer the remainder truncated towards -infinity


quo: aNumber
Divide aNumber and the receiver, answer the result truncated towards 0


rem: aNumber
Divide aNumber and the receiver, answer the remainder truncated towards 0


[ Next: | Previous:LargeZeroInteger-arithmetic | Up:LargeZeroInteger ]

LargeZeroInteger: numeric testing

sign
Answer the receiver's sign


strictlyPositive
Answer whether the receiver is > 0


[ Previous:LargeZeroInteger-numeric testing | Up:LargeZeroInteger ]

LargeZeroInteger: printing

reverseStringBase: radix on: str
Return in a string the base radix representation of the receiver in reverse order


[ ]

Link

Category: Collections-Sequenceable
I represent simple linked lists. Generally, I am not used by myself, but rather a subclass adds other instance variables that hold the information for each node, and I hold the glue that keeps them together.


[ Next: | Up:Link ]

Link class: instance creation

nextLink: aLink
Create an instance with the given next link


[ Previous:Link class-instance creation | Up:Link ]

Link: basic

nextLink
Answer the next item in the list


nextLink: aLink
Set the next item in the list


[ ]

LinkedList

Category: Collections-Sequenceable
I provide methods that access and manipulate linked lists. I assume that the elements of the linked list are subclasses of Link, because I use the methods that class Link supplies to implement my methods.


[ Next: | Up:LinkedList ]

LinkedList: accessing

at: index
Return the element that is index into the linked list.


at: index put: object
This method should not be called for instances of this class.


[ Next: | Previous:LinkedList-accessing | Up:LinkedList ]

LinkedList: adding

add: aLink
Add aLink at the end of the list; return aLink.


addFirst: aLink
Add aLink at the head of the list; return aLink.


addLast: aLink
Add aLink at then end of the list; return aLink.


remove: aLink ifAbsent: aBlock
Remove aLink from the list and return it, or invoke aBlock if it's not found in the list.


removeFirst
Remove the first element from the list and return it, or error if the list is empty.


removeLast
Remove the final element from the list and return it, or error if the list is empty.


[ Next: | Previous:LinkedList-adding | Up:LinkedList ]

LinkedList: enumerating

do: aBlock
Enumerate each object in the list, passing it to aBlock


[ Previous:LinkedList-enumerating | Up:LinkedList ]

LinkedList: testing

isEmpty
Returns true if the list contains no members


[ ]

Magnitude

Category: Language-Data types
I am an abstract class. My objects represent things that are discrete and map to a number line. My instances can be compared with < and >.


[ Next: | Up:Magnitude ]

Magnitude: basic

< aMagnitude
Answer whether the receiver is less than aMagnitude


<= aMagnitude
Answer whether the receiver is less than or equal to aMagnitude


= aMagnitude
Answer whether the receiver is equal to aMagnitude


> aMagnitude
Answer whether the receiver is greater than aMagnitude


>= aMagnitude
Answer whether the receiver is greater than or equal to aMagnitude


[ Previous:Magnitude-basic | Up:Magnitude ]

Magnitude: misc methods

between: min and: max
Returns true if object is inclusively between min and max.


max: aMagnitude
Returns the greatest object between the receiver and aMagnitude


min: aMagnitude
Returns the least object between the receiver and aMagnitude


[ ]

MappedCollection

Category: Collections-Keyed
I represent collections of objects that are indirectly indexed by names. There are really two collections involved: domain and a map. The map maps between external names and indices into domain, which contains the real association. In order to work properly, the domain must be an instance of a subclass of SequenceableCollection, and the map must be an instance of Dictionary, or of a subclass of SequenceableCollection.

As an example of using me, consider implenting a Dictionary whose elements are indexed. The domain would be a SequenceableCollection with n elements, the map a Dictionary associating each key to an index in the domain. To access by key, to perform enumeration, etc. you would ask an instance of me; to access by index, you would access the domain directly.


[ Next: | Up:MappedCollection ]

MappedCollection class: instance creation

collection: aCollection map: aMap
Answer a new MappedCollection using the given domain (aCollection) and map


new
self shouldNotImplement


[ Previous:MappedCollection class-instance creation | Up:MappedCollection ]

MappedCollection: basic

add: anObject
This method should not be called for instances of this class.


at: key
Answer the object at the given key


at: key put: value
Store value at the given key


collect: aBlock
Answer a MappedCollection with a copy of the receiver's map and a domain obtained by passing each object through aBlock


contents
Answer a bag with the receiver's values


do: aBlock
Evaluate aBlock for each object


domain
Answer the domain


map
Answer the map


reject: aBlock
Answer the objects in the domain for which aBlock returns false


select: aBlock
Answer the objects in the domain for which aBlock returns true


size
Answer the receiver's size


[ ]

Memory

Category: Language-Implementation
I provide access to actual machine addresses of OOPs and objects. I have no instances; you send messages to my class to map between an object and the address of its OOP or object. In addition I provide direct memory access with different C types (ints, chars, OOPs, floats,...).


[ Next: | Up:Memory ]

Memory class: accessing

at: anAddress
Access the Smalltalk object (OOP) at the given address.


at: anAddress put: aValue
Store a pointer (OOP) to the Smalltalk object identified by `value' at the given address.


charAt: anAddress
Access the C char at the given address. The value is returned as a Smalltalk Character.


charAt: anAddress put: aValue
Store as a C char the Smalltalk Character or Integer object identified by `value', at the given address, using sizeof(char) bytes - i.e. 1 byte.


deref: anAddress
Access the C int pointed by the given address


doubleAt: anAddress
Access the C double at the given address.


doubleAt: anAddress put: aValue
Store the Smalltalk Float object identified by `value', at the given address, writing it like a C double.


floatAt: anAddress
Access the C float at the given address.


floatAt: anAddress put: aValue
Store the Smalltalk Float object identified by `value', at the given address, writing it like a C float.


intAt: anAddress
Access the C int at the given address.


intAt: anAddress put: aValue
Store the Smalltalk Integer object identified by `value', at the given address, using sizeof(int) bytes.


longAt: anAddress
Access the C long int at the given address.


longAt: anAddress put: aValue
Store the Smalltalk Integer object identified by `value', at the given address, using sizeof(long) bytes.


shortAt: anAddress
Access the C short int at the given address.


shortAt: anAddress put: aValue
Store the Smalltalk Integer object identified by `value', at the given address, using sizeof(short) bytes.


stringAt: anAddress
Access the string pointed by the C `char *' at the given given address.


stringAt: anAddress put: aValue
Store the Smalltalk String object identified by `value', at the given address in memory, writing it like a *FRESHLY ALLOCATED* C string. It is the caller's responsibility to free it if necessary.


unsignedCharAt: anAddress
Access the C unsigned char at the given address. The value is returned as a Smalltalk Character.


unsignedCharAt: anAddress put: aValue
Store as a C char the Smalltalk Character or Integer object identified by `value', at the given address, using sizeof(char) bytes - i.e. 1 byte.


unsignedIntAt: anAddress
Access the C unsigned int at the given address.


unsignedIntAt: anAddress put: aValue
Store the Smalltalk Integer object identified by `value', at the given address, using sizeof(int) bytes.


unsignedLongAt: anAddress
Access the C unsigned long int at the given address.


unsignedLongAt: anAddress put: aValue
Store the Smalltalk Integer object identified by `value', at the given address, using sizeof(long) bytes.


unsignedShortAt: anAddress
Access the C unsigned short int at the given address.


unsignedShortAt: anAddress put: aValue
Store the Smalltalk Integer object identified by `value', at the given address, using sizeof(short) bytes.


[ Previous:Memory class-accessing | Up:Memory ]

Memory class: basic

addressOf: anObject
Returns the address of the actual object that anObject references. The result might be invalidated after a garbage collection occurs.


addressOfOOP: anObject
Returns the address of the OOP (object table slot) for anObject. The result is still valid after a garbage collection occurs.


type: aType at: anAddress
Returns a particular type object from memory at anAddress


type: aType at: anAddress put: aValue
Sets the memory location anAddress to aValue


[ ]

Message

Category: Language-Implementation
I am a virtually existent class. By that I mean that logically instances of my class are created whenever a message is sent to an object, but in reality my instances are only created to hold a message that has failed, so that error reporting methods can examine the sender and arguments.


[ Next: | Up:Message ]

Message class: creating instances

selector: aSymbol arguments: anArray
Create a new Message with the given selector and arguments


[ Next: | Previous:Message class-creating instances | Up:Message ]

Message: accessing

arguments
Answer the receiver's arguments


arguments: anArray
Set the receiver's arguments


selector
Answer the receiver's selector


selector: aSymbol
Set the receiver's selector


[ Previous:Message-accessing | Up:Message ]

Message: basic

printOn: aStream
Print a representation of the receiver on aStream


reinvokeFor: aReceiver
Resend to aReceiver - present for compatibility


sendTo: aReceiver
Resend to aReceiver


[ ]

Metaclass

Category: Language-Implementation
I am the root of the class hierarchy. My instances are metaclasses, one for each real class. My instances have a single instance, which they hold onto, which is the class that they are the metaclass of. I provide methods for creation of actual class objects from metaclass object, and the creation of metaclass objects, which are my instances. If this is confusing to you, it should be...the Smalltalk metaclass system is strange and complex.


[ Next: | Up:Metaclass ]

Metaclass class: instance creation

subclassOf: superMeta
Answer a new metaclass representing a subclass of superMeta


[ Next: | Previous:Metaclass class-instance creation | Up:Metaclass ]

Metaclass: accessing

instanceClass
Answer the only instance of the metaclass


primaryInstance
Answer the only instance of the metaclass - present for compatibility


soleInstance
Answer the only instance of the metaclass - present for compatibility


[ Next: | Previous:Metaclass-accessing | Up:Metaclass ]

Metaclass: basic

instanceVariableNames: classInstVarNames
Set the class-instance variables for the receiver to be those in classInstVarNames


name: newName
environment: aSystemDictionary subclassOf: superclass instanceVariableNames: stringOfInstVarNames variable: variableBoolean words: wordBoolean pointers: pointerBoolean classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryName Private - create a full featured class and install it, or change an existing one


newMeta: newName
environment: aSystemDictionary subclassOf: superclass instanceVariableNames: stringOfInstVarNames variable: variableBoolean words: wordBoolean pointers: pointerBoolean classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryName Private - create a full featured class and install it


[ Next: | Previous:Metaclass-basic | Up:Metaclass ]

Metaclass: delegation

addClassVarName: aString
Add a class variable with the given name to the class pool dictionary


addSharedPool: aDictionary
Add the given shared pool to the list of the class' pool dictionaries


allClassVarNames
Answer the names of the variables in the receiver's class pool dictionary and in each of the superclasses' class pool dictionaries


allSharedPools
Return the names of the shared pools defined by the class and any of its superclasses


classPool
Answer the class pool dictionary


classVarNames
Answer the names of the variables in the class pool dictionary


removeClassVarName: aString
Removes the class variable from the class, error if not present, or still in use.


removeSharedPool: aDictionary
Remove the given dictionary to the list of the class' pool dictionaries


sharedPools
Return the names of the shared pools defined by the class


[ Next: | Previous:Metaclass-delegation | Up:Metaclass ]

Metaclass: filing

fileOutOn: aFileStream
File out complete class description: class definition, class and instance methods


[ Next: | Previous:Metaclass-filing | Up:Metaclass ]

Metaclass: printing

printOn: aStream
Print a represention of the receiver on aStream


storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Previous:Metaclass-printing | Up:Metaclass ]

Metaclass: testing functionality

asClass
Answer `instanceClass'.


isMetaclass
Answer `true'.


[ ]

MethodContext

Category: Language-Implementation
My instances represent an actively executing method. They record various bits of information about the execution environment, and contain the execution stack.


[ Next: | Up:MethodContext ]

MethodContext: accessing

home
Answer the MethodContext to which the receiver refers (i.e. the receiver itself)


isBlock
Answer whether the receiver is a block context


method
Return the CompiledMethod being executed


methodClass
Return the class in which the CompiledMethod being executed is defined


receiver
Return the receiver (self) for the method being executed


selector
Return the selector for the method being executed


sender
Return the context from which the receiver was sent


[ Previous:MethodContext-accessing | Up:MethodContext ]

MethodContext: printing

printOn: aStream
Print a representation for the receiver on aStream


[ ]

MethodInfo

Category: Language-Implementation
I provide information about particular methods. I can produce the category that a method was filed under, and can be used to access the source code of the method.


[ Next: | Up:MethodInfo ]

MethodInfo: accessing

category
Answer the method category


category: aCategory
Set the method category


sourceCode
Answer a FileSegment or String or nil containing the method source code


sourceFile
Answer the name of the file where the method source code is


sourcePos
Answer the starting position of the method source code in the sourceFile


sourceString
Answer a String containing the method source code


stripSourceCode
Remove the reference to the source code for the method


[ Previous:MethodInfo-accessing | Up:MethodInfo ]

MethodInfo: equality

= aMethodInfo
Compare the receiver and aMethodInfo, answer whether they're equal


hash
Answer an hash value for the receiver


[ ]

NullProxy

Category: Streams-Files
I am a proxy that does no special processing on the object to be saved - it uses about the same format as a #dump: without a proxy. It can be used to disable proxies for particular subclasses.


[ Next: | Up:NullProxy ]

NullProxy class: instance creation

on: anObject
Answer a proxy to be used to save anObject. IMPORTANT: the newly constructed DumperProxy must NOT have anObject in one of its in- stance variable, because that would result in an infinite loop!


[ Previous:NullProxy class-instance creation | Up:NullProxy ]

NullProxy: accessing

object
Reconstruct the object stored in the proxy and answer it


object: theObject
Private - Set the object to be dumped to theObject. This is set by the #on: class method; note that NullProxies don't conform to the rule that proxies must not have their object in an instance variable, because they are treated different from all other proxy objects in the ObjectDumper.


[ ]

NullValueHolder

Category: Language-Data types
I pretend to store my value in a variable, but I don't actually. You can use the only instance of my class (returned by `ValueHolder null') if you're not interested in a value that is returned as described in ValueHolder's comment.


[ Next: | Up:NullValueHolder ]

NullValueHolder class: creating instances

new
Not used - use `ValueHolder null' instead


[ Previous:NullValueHolder class-creating instances | Up:NullValueHolder ]

NullValueHolder: accessing

value
Retrive the value of the receiver. Always answer nil


value: anObject
Set the value of the receiver. Do nothing, discard the value


[ ]

Number

Category: Language-Data types
I am an abstract class that provides operations on numbers, both floating point and integer. I provide some generic predicates, and supply the implicit type coercing code for binary operations.


[ Next: | Up:Number ]

Number class: converting

coerce: aNumber
Answer aNumber - whatever class it belongs to, it is good


readFrom: aStream
Answer the number read from the rest of aStream, converted to an instance of the receiver. If the receiver is number, the class of the result is undefined - but the result is good.


[ Next: | Previous:Number class-converting | Up:Number ]

Number class: testing

isImmediate
Answer whether, if x is an instance of the receiver, x copy == x


[ Next: | Previous:Number class-testing | Up:Number ]

Number: arithmetic

* aNumber
Subtract the receiver and aNumber, answer the result


+ aNumber
Sum the receiver and aNumber, answer the result


- aNumber
Subtract aNumber from the receiver, answer the result


/ aNumber
Divide the receiver by aNumber, answer the result (no loss of precision)


// aNumber
Divide the receiver by aNumber, answer the result truncated towards -infinity


\\ aNumber
Divide the receiver by aNumber truncating towards -infinity, answer the remainder


quo: aNumber
Return the integer quotient of dividing the receiver by aNumber with truncation towards zero.


reciprocal
Return the reciprocal of the receiver


rem: aNumber
Return the remainder of dividing the receiver by aNumber with truncation towards zero.


[ Next: | Previous:Number-arithmetic | Up:Number ]

Number: converting

asRectangle
Answer an empty rectangle whose origin is (self asPoint)


coerce: aNumber
Answer aNumber - whatever class it belongs to, it is good


degreesToRadians
Convert the receiver to radians


generality
Answer the receiver's generality


radiansToDegrees
Convert the receiver from radians to degrees


retry: aSymbol coercing: aNumber
Coerce the number (between the receiver and aNumber) which has the lowest generality to the other's number class, and retry calling aSymbol.


unity
Coerce 1 to the receiver's class. The default implementation works, but is inefficient


zero
Coerce 0 to the receiver's class. The default implementation works, but is inefficient


[ Next: | Previous:Number-converting | Up:Number ]

Number: copying

deepCopy
Return the receiver - it's an immediate (immutable) object


shallowCopy
Return the receiver - it's an immediate (immutable) object


[ Next: | Previous:Number-copying | Up:Number ]

Number: Intervals & iterators

to: stop
Return an interval going from the receiver to stop by 1


to: stop by: step
Return an interval going from the receiver to stop with the given step


to: stop by: step do: aBlock
Evaluate aBlock for each value in the interval going from the receiver to stop with the given step. Compiled in-line for integer literal steps, and for one-argument aBlocks without temporaries, and therefore not overridable.


to: stop do: aBlock
Evaluate aBlock for each value in the interval going from the receiver to stop by 1. Compiled in-line for one-argument aBlocks without temporaries, and therefore not overridable.


[ Next: | Previous:Number-Intervals & iterators | Up:Number ]

Number: misc math

abs
Answer the absolute value of the receiver


arcCos
return the arc cosine of the receiver


arcSin
return the arc sine of the receiver


arcTan
return the arc tangent of the receiver


cos
return the cosine of the receiver


estimatedLog
Answer an estimate of (self abs floorLog: 10). This method should be overridden by subclasses, but Number's implementation does not raise errors - simply, it gives a correct result, so it is slow.


exp
return e raised to the receiver


floorLog: radix
return (self log: radix) floor. Optimized to answer an integer.


ln
return log base e of the receiver


log: aNumber
return log base aNumber of the receiver


negated
Answer the negated of the receiver


raisedTo: aNumber
Return self raised to aNumber power


raisedToInteger: anInteger
Return self raised to the anInteger-th power


sin
return the sine of the receiver


sqrt
return the square root of the receiver


squared
Answer the square of the receiver


tan
return the tangent of the receiver


[ Next: | Previous:Number-misc math | Up:Number ]

Number: point creation

@ y
Answer a new point whose x is the receiver and whose y is y


asPoint
Answer a new point, self @ self


[ Next: | Previous:Number-point creation | Up:Number ]

Number: testing

even
Returns true if self is divisible by 2


isNumber
Answer `true'.


isRational
Answer whether the receiver is rational - false by default


negative
Answer whether the receiver is < 0


odd
Returns true if self is not divisible by 2


positive
Answer whether the receiver is >= 0


sign
Returns the sign of the receiver.


strictlyPositive
Answer whether the receiver is > 0


[ Previous:Number-testing | Up:Number ]

Number: truncation and round off

asInteger
Answer the receiver, truncated towards zero


floor
Return the integer nearest the receiver toward negative infinity.


rounded
Returns the integer nearest the receiver


roundTo: aNumber
Answer the receiver, truncated to the nearest multiple of aNumber


truncated
Answer the receiver, truncated towards zero


truncateTo: aNumber
Answer the receiver, truncated towards zero to a multiple of aNumber


[ ]

Object

Category: Language-Implementation
I am the root of the Smalltalk class system. All classes in the system are subclasses of me.


[ Next: | Up:Object ]

Object: built ins

= arg
Answer whether the receiver is equal to arg. The equality test is by default the same as that for equal objects. = must not fail; answer false if the receiver cannot be compared to arg


== arg
Answer whether the receiver is the same object as arg. This is a very fast test and is called 'identity'


addToBeFinalized
Add the object to the list of objects to be finalized when there are no more references to them


asOop
Answer the object index associated to the receiver. The object index doesn't change when garbage collection is performed.


at: anIndex
Answer the index-th indexed instance variable of the receiver


at: anIndex put: value
Store value in the index-th indexed instance variable of the receiver


basicAt: anIndex
Answer the index-th indexed instance variable of the receiver. This method must not be overridden, override at: instead


basicAt: anIndex put: value
Store value in the index-th indexed instance variable of the receiver This method must not be overridden, override at:put: instead


basicPrint
Print a basic representation of the receiver


basicSize
Answer the number of indexed instance variable in the receiver


become: otherObject
Change all references to the receiver into references to otherObject. Depending on the implementation, references to otherObject might or might not be transformed into the receiver (respectively, 'two-way become' and 'one-way become'). Implementations doing one-way become answer the receiver (so that it is not lost). Most implementations doing two-way become answer otherObject, but this is not assured - so do answer the receiver for consistency. GNU Smalltalk does two-way become and answers otherObject, but this might change in future versions: programs should not rely on the behavior and results of #become: .


checkIndexableBounds: index
Private - Check the reason why an access to the given indexed instance variable failed


class
Answer the class to which the receiver belongs


doesNotUnderstand: aMessage
Called by the system when a selector was not found. message is a Message containing information on the receiver


error: message
Display a walkback for the receiver, with the given error message. Signal ExError


halt
Called to enter the debugger


halt: message
Display a walkback for the receiver, with the given error message. Signal ExHalt


hash
Answer an hash value for the receiver. This hash value is ok for objects that do not redefine ==.


identityHash
Answer an hash value for the receiver. This method must not be overridden


instVarAt: index
Answer the index-th instance variable of the receiver. This method must not be overridden.


instVarAt: index put: value
Store value in the index-th instance variable of the receiver. This method must not be overridden.


isReadOnly
Answer whether the object's indexed instance variables can be written


makeReadOnly: aBoolean
Set whether the object's indexed instance variables can be written


makeWeak
Make the object a 'weak' one. When an object is only referenced by weak objects, it is collected and the slots in the weak objects are changed to nils by the VM


mark: aSymbol
Private - use this method to mark code which needs to be reworked, removed, etc. You can then find all senders of #mark: to find all marked methods or you can look for all senders of the symbol that you sent to #mark: to find a category of marked methods.


nextInstance
Private - answer another instance of the receiver's class, or nil if the entire object table has been walked


notYetImplemented
Called when a method defined by a class is not yet implemented, but is going to be


perform: selectorOrMessage
Send the unary message named selectorOrMessage (if a Symbol) to the receiver, or the message and arguments it identifies (if a Message or DirectedMessage). This method should not be overridden


perform: selector with: arg1
Send the message named selector (a Symbol) to the receiver, passing arg1 to it. This method should not be overridden


perform: selector with: arg1 with: arg2
Send the message named selector (a Symbol) to the receiver, passing arg1 and arg2 to it. This method should not be overridden


perform: selector with: arg1 with: arg2 with: arg3
Send the message named selector (a Symbol) to the receiver, passing arg1, arg2 and arg3 to it. This method should not be overridden


perform: selector withArguments: argumentsArray
Send the message named selector (a Symbol) to the receiver, passing every element of argumentsArray to it. This method should not be overridden


primError: message
This might start the debugger... Note that we use #basicPrint 'cause #printOn: might invoke an error.


primitiveFailed
Called when a VM primitive fails


removeToBeFinalized
Remove the object from the list of objects to be finalized when there are no more references to them


shouldNotImplement
Called when objects belonging to a class should not answer a selector defined by a superclass


size
Answer the number of indexed instance variable in the receiver


specialBasicAt: index
Similar to basicAt: but without bounds checking. This method is used to support instance mutation when an instance's class definition is changed. This method must not be overriddent


subclassResponsibility
Called when a method defined by a class should be overridden in a subclass


userInterrupt
Display a walkback for the receiver, signalling ExUserBreak.


[ Next: | Previous:Object-built ins | Up:Object ]

Object: change and update

broadcast: aSymbol
Send the unary message aSymbol to each of the receiver's dependents


broadcast: aSymbol with: anObject
Send the message aSymbol to each of the receiver's dependents, passing anObject


broadcast: aSymbol withArguments: anArray
Send the message aSymbol to each of the receiver's dependents, passing the parameters in anArray


broadcast: aSymbol withBlock: aBlock
Send the message aSymbol to each of the receiver's dependents, passing the result of evaluating aBlock with each dependent as the parameter


changed
Send update: for each of the receiver's dependents, passing them the receiver


changed: aParameter
Send update: for each of the receiver's dependents, passing them aParameter


update: aParameter
Default behavior is to do nothing. Called by #changed and #changed:


[ Next: | Previous:Object-change and update | Up:Object ]

Object: class type methods

species
This method has no unique definition. Generally speaking, methods which always return the same type usually don't use #class, but #species. For example, a PositionableStream's species is the class of the collection on which it is streaming (used by upTo:, upToAll:, upToEnd). Stream uses species for obtaining the class of next:'s return value, Collection uses it in its #copyEmpty: message, which in turn is used by all collection-re- turning methods. An Interval's species is Array (used by collect:, select:, reject:, etc.).


yourself
Answer the receiver


[ Next: | Previous:Object-class type methods | Up:Object ]

Object: copying

copy
Returns a shallow copy of the receiver (the instance variables are not copied). The shallow copy receives the message postCopy and is then passed back


deepCopy
Returns a shallow copy of the receiver (the instance variables are copies of the receiver's instance variables)


postCopy
Performs any changes required to do on a copied object. This is the place where one could, for example, put code to replace objects with copies of the objects


shallowCopy
Returns a shallow copy of the receiver (the instance variables are not copied)


[ Next: | Previous:Object-copying | Up:Object ]

Object: debugging

breakpoint: context return: return
Called back by the system. Must return the value passed through the second parameter


inspect
Print all the instance variables of the receiver on the Transcript


validSize
Answer how many elements in the receiver should be inspected


[ Next: | Previous:Object-debugging | Up:Object ]

Object: dependents access

addDependent: anObject
Add anObject to the set of the receiver's dependents. Important: if an object has dependents, it won't be garbage collected.


dependents
Answer a collection of the receiver's dependents.


release
Remove all of the receiver's dependents from the set and allow the receiver to be garbage collected.


removeDependent: anObject
Remove anObject to the set of the receiver's dependents. No problem if anObject is not in the set of the receiver's dependents.


[ Next: | Previous:Object-dependents access | Up:Object ]

Object: finalization

finalize
Do nothing by default


[ Next: | Previous:Object-finalization | Up:Object ]

Object: printing

basicPrintNl
Print a basic representation of the receiver, followed by a new line.


print
Print a represention of the receiver on the Transcript (stdout the GUI is not active)


printNl
Print a represention of the receiver on stdout, put a new line the Transcript (stdout the GUI is not active)


printOn: aStream
Print a represention of the receiver on aStream


printString
Answer a String representing the receiver


[ Next: | Previous:Object-printing | Up:Object ]

Object: Relational operators

~= anObject
Answer whether the receiver and anObject are not equal


~~ anObject
Answer whether the receiver and anObject are not the same object


[ Next: | Previous:Object-Relational operators | Up:Object ]

Object: storing

store
Put a String of Smalltalk code compiling to the receiver on the Transcript (stdout the GUI is not active)


storeNl
Put a String of Smalltalk code compiling to the receiver, followed by a new line, on the Transcript (stdout the GUI is not active)


storeOn: aStream
Put Smalltalk code compiling to the receiver on aStream


storeString
Answer a String of Smalltalk code compiling to the receiver


[ Next: | Previous:Object-storing | Up:Object ]

Object: subclassed

TexinfoClassPublisher
Not commented


[ Next: | Previous:Object-subclassed | Up:Object ]

Object: syntax shortcuts

-> anObject
Creates a new instance of Association with the receiver being the key and the argument becoming the value


[ Next: | Previous:Object-syntax shortcuts | Up:Object ]

Object: testing functionality

ifNil: nilBlock
Evaluate nilBlock if the receiver is nil, else answer self


ifNil: nilBlock ifNotNil: notNilBlock
Evaluate nilBlock if the receiver is nil, else evaluate notNilBlock, passing the receiver.


ifNotNil: notNilBlock
Evaluate notNiilBlock if the receiver is not nil, passing the receiver. Else answer nil.


ifNotNil: notNilBlock ifNotNil: nilBlock
Evaluate nilBlock if the receiver is nil, else evaluate notNilBlock, passing the receiver.


isArray
Answer `false'.


isCharacter
Answer `false'.


isClass
Answer `false'.


isFloat
Answer `false'.


isInteger
Answer `false'.


isKindOf: aClass
Answer whether the receiver's class is aClass or a subclass of aClass


isMemberOf: aClass
Returns true if the receiver is an instance of the class 'aClass'


isMeta
Same as isMetaclass


isMetaclass
Answer `false'.


isMetaClass
Same as isMetaclass


isNil
Answer whether the receiver is nil


isNumber
Answer `false'.


isSmallInteger
Answer `false'.


isString
Answer `false'.


isSymbol
Answer `false'.


notNil
Answer whether the receiver is not nil


respondsTo: aSymbol
Returns true if the receiver understands the given selector


[ Previous:Object-testing functionality | Up:Object ]

Object: VM callbacks

badReturnError
Called back when a block performs a bad return


mustBeBoolean
Called by the system when ifTrue:*, ifFalse:*, and: or or: are sent to anything but a boolean


noRunnableProcess
Called back when all processes are suspended


[ ]

ObjectDumper

Category: Streams-Files
I'm not part of a normal Smalltalk system, but most Smalltalks provide a similar feature: that is, support for storing objects in a binary format; there are many advantages in using me instead of #storeOn: and the Smalltalk compiler - My instances store data in a very compact format - Loading is much faster when compared with compiling the Smalltalk code prepared by #storeOn: - Almost all Smalltalks don't allow programmers to ship the compiler as part of the run-time image - My instances support circular references between objects, while #storeOn: supports it only if you know of such references at design time and you override #storeOn: to deal with them


[ Next: | Up:ObjectDumper ]

ObjectDumper class: establishing proxy classes

disableProxyFor: aClass
Disable proxies for instances of aClass and its descendants


hasProxyFor: aClass
Answer whether a proxy class has been registered for instances of aClass.


proxyFor: anObject
Answer a valid proxy for an object, or nil if none could be found


registerProxyClass: aProxyClass for: aClass
Register the proxy class aProxyClass - descendent of DumperProxy - to be used for instances of aClass and its descendants


[ Next: | Previous:ObjectDumper class-establishing proxy classes | Up:ObjectDumper ]

ObjectDumper class: instance creation

new
This method should not be called for instances of this class.


on: aFileStream
Answer an ObjectDumper working on aFileStream.


[ Next: | Previous:ObjectDumper class-instance creation | Up:ObjectDumper ]

ObjectDumper class: shortcuts

dump: anObject to: aFileStream
Dump anObject to aFileStream. Answer anObject


loadFrom: aFileStream
Load an object from aFileStream and answer it


[ Next: | Previous:ObjectDumper class-shortcuts | Up:ObjectDumper ]

ObjectDumper class: testing

example
This is a real torture test: it outputs recursive objects, identical objects multiple times, classes, metaclasses, integers and characters!


[ Next: | Previous:ObjectDumper class-testing | Up:ObjectDumper ]

ObjectDumper: accessing

stream
Answer `stream'.


[ Next: | Previous:ObjectDumper-accessing | Up:ObjectDumper ]

ObjectDumper: loading/dumping objects

dump: anObject
Dump anObject on the stream associated with the receiver. Answer anObject


load
Load an object from the stream associated with the receiver and answer it


[ Previous:ObjectDumper-loading/dumping objects | Up:ObjectDumper ]

ObjectDumper: stream interface

atEnd
Answer whether the underlying stream is at EOF


next
Load an object from the underlying stream


nextPut: anObject
Store an object on the underlying stream


[ ]

OrderedCollection

Category: Collections-Sequenceable
My instances represent ordered collections of arbitrary typed objects which are not directly accessible by an index. They can be accessed indirectly through an index, and can be manipulated by adding to the end or based on content (such as add:after:)


[ Next: | Up:OrderedCollection ]

OrderedCollection class: instance creation

new
Answer an OrderedCollection of default size


new: anInteger
Answer an OrderedCollection of size anInteger


[ Next: | Previous:OrderedCollection class-instance creation | Up:OrderedCollection ]

OrderedCollection: accessing

after: oldObject
Return the element after oldObject. Error if oldObject not found or if no following object is available


at: anIndex
Answer the anIndex-th item of the receiver


at: anIndex put: anObject
Store anObject at the anIndex-th item of the receiver, answer anObject


before: oldObject
Return the element after oldObject. Error if oldObject not found or if no following object is available


size
Return the number of objects in the receiver


[ Next: | Previous:OrderedCollection-accessing | Up:OrderedCollection ]

OrderedCollection: adding

add: anObject
Add anObject in the receiver, answer it


add: newObject after: oldObject
Add newObject in the receiver just after oldObject, answer it. Fail if oldObject can't be found


add: newObject afterIndex: i
Add newObject in the receiver just after the i-th, answer it. Fail if i < 0 or i > self size


add: newObject before: oldObject
Add newObject in the receiver just before oldObject, answer it. Fail if oldObject can't be found


add: newObject beforeIndex: i
Add newObject in the receiver just before the i-th, answer it. Fail if i < 1 or i > self size + 1


addAll: aCollection
Add every item of aCollection to the receiver, answer it


addAll: newCollection after: oldObject
Add every item of newCollection to the receiver just after oldObject, answer it. Fail if oldObject is not found


addAll: newCollection afterIndex: i
Add every item of newCollection to the receiver just after the i-th, answer it. Fail if i < 0 or i > self size


addAll: newCollection before: oldObject
Add every item of newCollection to the receiver just before oldObject, answer it. Fail if oldObject is not found


addAll: newCollection beforeIndex: i
Add every item of newCollection to the receiver just before the i-th, answer it. Fail if i < 1 or i > self size + 1


addAllFirst: aCollection
Add every item of newCollection to the receiver right at the start of the receiver. Answer aCollection


addAllLast: aCollection
Add every item of newCollection to the receiver right at the end of the receiver. Answer aCollection


addFirst: newObject
Add newObject to the receiver right at the start of the receiver. Answer newObject


addLast: newObject
Add newObject to the receiver right at the end of the receiver. Answer newObject


[ Previous:OrderedCollection-adding | Up:OrderedCollection ]

OrderedCollection: removing

remove: anObject ifAbsent: aBlock
Remove anObject from the receiver. If it can't be found, answer the result of evaluating aBlock


removeAtIndex: anIndex
Remove the object at index anIndex from the receiver. Fail if the index is out of bounds


removeFirst
Remove an object from the start of the receiver. Fail if the receiver is empty


removeLast
Remove an object from the end of the receiver. Fail if the receiver is empty


[ ]

PackageLoader

Category: Language-Data types
I am not part of a standard Smalltalk system. I provide methods for loading packages into a Smalltalk image, correctly handling dependencies.


[ Next: | Up:PackageLoader ]

PackageLoader class: accessing

addPackage: package directory: dir fileIn: fileIns needs: prerequisites
Add the given package to the `packages' file, with the given directory (if relative, it is relative to the kernel directory), fileIns and prerequisites. fileIns and prerequisites should be two Collections of Strings. Note that none of this fields are optional. If there are no prere- quisites, just use #('Kernel') as the prerequisites.


directoryFor: package
Answer a complete path to the given package's file-in


fileInsFor: package
Answer a Set of Strings containing the filenames of the given package's file-ins (relative to the directory answered by #directoryFor:)


prerequisitesFor: package
Answer a Set of Strings containing the prerequisites for the given package


refreshDependencies
Reload the `packages' file in the image directory


[ Next: | Previous:PackageLoader class-accessing | Up:PackageLoader ]

PackageLoader class: loading

extractDependenciesFor: packagesList onError: aBlock
Answer an OrderedCollection containing all the packages which you have to load to enable the packages in packagesList, in an appropriate order. For example PackageLoader extractDependenciesFor: #('BloxTestSuite' 'Blox' 'Browser') on a newly built image will evaluate to an OrderedCollection containing 'Kernel', 'C:tclInit', 'Blox', 'BloxTestSuite' and 'Browser'. Note that Blox has been moved before BloxTestSuite. Pass an error message to aBlock if any of the packages needs C call-outs which are not defined.


fileInPackage: package
File in the given package into GNU Smalltalk.


fileInPackages: packagesList
File in all the packages in packagesList into GNU Smalltalk.


[ Previous:PackageLoader class-loading | Up:PackageLoader ]

PackageLoader class: testing

canLoad: package
Answer whether all the needed C call-outs are registered within GNU Smalltalk


[ ]

PluggableAdaptor

Category: Language-Data types
I mediate between complex get/set behavior and the #value/#value: protocol used by ValueAdaptors. The get/set behavior can be implemented by two blocks, or can be delegated to another object with messages such as #someProperty to get and #someProperty: to set.


[ Next: | Up:PluggableAdaptor ]

PluggableAdaptor class: creating instances

getBlock: getBlock putBlock: putBlock
Answer a PluggableAdaptor using the given blocks to implement #value and #value:


on: anObject aspect: aSymbol
Answer a PluggableAdaptor using anObject's aSymbol message to implement #value, and anObject's aSymbol: message (aSymbol followed by a colon) to implement #value:


on: anObject getSelector: getSelector putSelector: putSelector
Answer a PluggableAdaptor using anObject's getSelector message to implement #value, and anObject's putSelector message to implement #value:


on: anObject index: anIndex
Answer a PluggableAdaptor using anObject's #at: and #at:put: message to implement #value and #value:; the first parameter of #at: and #at:put: is anIndex


on: aDictionary key: aKey
Same as #on:index:. Provided for clarity and completeness.


[ Previous:PluggableAdaptor class-creating instances | Up:PluggableAdaptor ]

PluggableAdaptor: accessing

value
Get the value of the receiver.


value: anObject
Set the value of the receiver.


[ ]

Point

Category: Language-Data types
Beginning of a Point class for simple display manipulation. Has not been exhaustively tested but appears to work for the basic primitives and for the needs of the Rectangle class.


[ Next: | Up:Point ]

Point class: instance creation

new
Create a new point with both coordinates set to 0


x: xInteger y: yInteger
Create a new point with the given coordinates


[ Next: | Previous:Point class-instance creation | Up:Point ]

Point: accessing

x
Answer the x coordinate


x: aNumber
Set the x coordinate to aNumber


x: anXNumber y: aYNumber
Set the x and y coordinate to anXNumber and aYNumber, respectively


y
Answer the y coordinate


y: aNumber
Set the y coordinate to aNumber


[ Next: | Previous:Point-accessing | Up:Point ]

Point: arithmetic

* scale
Multiply the receiver by scale, which can be a Number or a Point


+ delta
Sum the receiver and delta, which can be a Number or a Point


- delta
Subtract delta, which can be a Number or a Point, from the receiver


/ scale
Divide the receiver by scale, which can be a Number or a Point, with no loss of precision


// scale
Divide the receiver by scale, which can be a Number or a Point, with truncation towards -infinity


abs
Answer a new point whose coordinates are the absolute values of the receiver's


[ Next: | Previous:Point-arithmetic | Up:Point ]

Point: comparing

< aPoint
Answer whether the receiver is higher and to the left of aPoint


<= aPoint
Answer whether aPoint is equal to the receiver, or the receiver is higher and to the left of aPoint


= aPoint
Answer whether the receiver is equal to aPoint


> aPoint
Answer whether the receiver is lower and to the right of aPoint


>= aPoint
Answer whether aPoint is equal to the receiver, or the receiver is lower and to the right of aPoint


max: aPoint
Answer self if it is lower and to the right of aPoint, aPoint otherwise


min: aPoint
Answer self if it is higher and to the left of aPoint, aPoint otherwise


[ Next: | Previous:Point-comparing | Up:Point ]

Point: converting

asPoint
Answer the receiver.


asRectangle
Answer an empty rectangle whose origin is self


corner: aPoint
Answer a Rectangle whose origin is the receiver and whose corner is aPoint


extent: aPoint
Answer a Rectangle whose origin is the receiver and whose extent is aPoint


hash
Answer an hash value for the receiver


[ Next: | Previous:Point-converting | Up:Point ]

Point: point functions

arcTan
Answer the angle (measured counterclockwise) between the receiver and a ray starting in (0, 0) and moving towards (1, 0) - i.e. 3 o'clock


dist: aPoint
Answer the distance between the receiver and aPoint


dotProduct: aPoint
Answer the dot product between the receiver and aPoint


grid: aPoint
Answer a new point whose coordinates are rounded towards the nearest multiple of aPoint


normal
Rotate the Point 90degrees clockwise and get the unit vector


transpose
Answer a new point whose coordinates are the receiver's coordinates exchanged (x becomes y, y becomes x)


truncatedGrid: aPoint
Answer a new point whose coordinates are rounded towards -infinity, to a multiple of grid (which must be a Point)


[ Next: | Previous:Point-point functions | Up:Point ]

Point: printing

printOn: aStream
Print a representation for the receiver on aStream


[ Next: | Previous:Point-printing | Up:Point ]

Point: storing

storeOn: aStream
Print Smalltalk code compiling to the receiver on aStream


[ Previous:Point-storing | Up:Point ]

Point: truncation and round off

rounded
Answer a new point whose coordinates are rounded to the nearest integer


truncateTo: grid
Answer a new point whose coordinates are rounded towards -infinity, to a multiple of grid (which must be a Number)


[ ]

PositionableStream

Category: Streams-Collections
My instances represent streams where explicit positioning is permitted. Thus, my streams act in a manner to normal disk files: you can read or write sequentially, but also position the file to a particular place whenever you choose. Generally, you'll want to use ReadStream, WriteStream or ReadWriteStream instead of me to create and use streams.


[ Next: | Up:PositionableStream ]

PositionableStream class: instance creation

on: aCollection
Answer an instance of the receiver streaming on the whole contents of aCollection


on: aCollection from: firstIndex to: lastIndex
Answer an instance of the receiver streaming from the firstIndex-th item of aCollection to the lastIndex-th


[ Next: | Previous:PositionableStream class-instance creation | Up:PositionableStream ]

PositionableStream: accessing-reading

contents
Returns a collection of the same type that the stream accesses, up to and including the final element.


copyFrom: start to: end
Answer the collection on which the receiver is streaming, from the start-th item to the end-th


next
Answer the next item of the receiver


nextLine
Returns a collection of the same type that the stream accesses, up to but not including the object anObject. Returns the entire rest of the stream's contents if anObject is not present.


peek
Returns the next element of the stream without moving the pointer. Returns nil when at end of stream.


peekFor: anObject
Returns true and gobbles the next element from the stream of it is equal to anObject, returns false and doesn't gobble the next element if the next element is not equal to anObject.


reverseContents
Returns a collection of the same type that the stream accesses, up to and including the final element, but in reverse order.


upTo: anObject
Returns a collection of the same type that the stream accesses, up to but not including the object anObject. Returns the entire rest of the stream's contents if anObject is not present.


upToAll: aCollection
If there is a sequence of objects remaining in the stream that is equal to the sequence in aCollection, set the stream position just past that sequence and answer the elements up to, but not including, the sequence. Else, set the stream position to its end and answer all the remaining elements.


upToEnd
Answer every item in the collection on which the receiver is streaming, from the next one to the last


[ Next: | Previous:PositionableStream-accessing-reading | Up:PositionableStream ]

PositionableStream: class type methods

species
The collections returned by #upTo: etc. are the same kind as those returned by the collection with methods such as #select:


[ Next: | Previous:PositionableStream-class type methods | Up:PositionableStream ]

PositionableStream: positioning

basicPosition: anInteger
Move the stream pointer to the anInteger-th object


position
Answer the current value of the stream pointer


position: anInteger
Move the stream pointer to the anInteger-th object


reset
Move the stream back to its first element. For write-only streams, the stream is truncated there.


setToEnd
Move the current position to the end of the stream.


skip: anInteger
Move the current position by anInteger places, either forwards or backwards.


skipTo: anObject
Move the current position to after the next occurrence of anObject and return true if anObject was found. If anObject doesn't exist, the pointer is atEnd, and false is returned.


skipToAll: aCollection
If there is a sequence of objects remaining in the stream that is equal to the sequence in aCollection, set the stream position just past that sequence and answer true. Else, set the stream position to its end and answer false.


[ Next: | Previous:PositionableStream-positioning | Up:PositionableStream ]

PositionableStream: testing

atEnd
Answer whether the objects in the stream have reached an end


basicAtEnd
Answer whether the objects in the stream have reached an end. This method must NOT be overridden.


isEmpty
Answer whether the stream has no objects


[ Previous:PositionableStream-testing | Up:PositionableStream ]

PositionableStream: truncating

truncate
Truncate the receiver to the current position - only valid for writing streams


[ ]

Process

Category: Language-Processes
I represent a unit of computation. My instances are independantly executable blocks that have a priority associated with them, and they can suspend themselves and resume themselves however they wish.


[ Next: | Up:Process ]

Process class: basic

on: aBlockContext at: aPriority
Private - Create a process running aBlockContext at the given priority


[ Next: | Previous:Process class-basic | Up:Process ]

Process: accessing

name
Answer `name'.


name: aString
Give the name aString to the process


priority
Answer the receiver's priority


priority: anInteger
Change the receiver's priority to anInteger


queueInterrupt: aBlock
Force the receiver to be interrupted and to evaluate aBlock as soon as it becomes the active process (this could mean NOW if the receiver is active). Answer the receiver


[ Next: | Previous:Process-accessing | Up:Process ]

Process: basic

forceResume
Private - Force a resume of the process from whatever status it was in (even if it was waiting on a semaphore). This is BAD practice, it is present only for some future possibility.


suspend
Do nothing if we're already suspended. Note that the blue book made suspend a primitive - but the real primitive is yielding control to another process. Suspending is nothing more than taking ourselves out of every scheduling list and THEN yield control to another process


terminate
Terminate the receiver - This is nothing more than prohibiting to resume the process, then suspending it.


[ Next: | Previous:Process-basic | Up:Process ]

Process: builtins

resume
Resume the receiver's execution


yield
Yield control from the receiver to other processes


[ Previous:Process-builtins | Up:Process ]

Process: printing

printOn: aStream
Print a representation of the receiver on aStream


[ ]

ProcessorScheduler

Category: Language-Processes
I provide methods that control the execution of processes.


[ Next: | Up:ProcessorScheduler ]

ProcessorScheduler: basic

activePriority
Answer the active process' priority


activeProcess
Answer the active process


changePriorityOf: aProcess to: aPriority
Private - Move aProcess to the execution list for aPriority, answer the new execution list


processesAt: aPriority
Private - Answer a linked list of processes at the given priority


terminateActive
Private - Terminate the active process


yield
Let the active process yield control to other processes


[ Next: | Previous:ProcessorScheduler-basic | Up:ProcessorScheduler ]

ProcessorScheduler: priorities

highIOPriority
Answer the priority for system high-priority I/O processes


lowIOPriority
Answer the priority for system low-priority I/O processes


priorityName: priority
Private - Answer a name for the given process priority


systemBackgroundPriority
Answer the priority for system background-priority processes


timingPriority
Answer the priority for system real-time processes


userBackgroundPriority
Answer the priority for user background-priority processes


userInterruptPriority
Answer the priority for user interrupt-priority processes


userSchedulingPriority
Answer the priority for user standard-priority processes


[ Previous:ProcessorScheduler-priorities | Up:ProcessorScheduler ]

ProcessorScheduler: timed invocation

isTimeoutProgrammed
Private - Answer whether there is a pending call to #signal:atMilliseconds:


signal: aSemaphore atMilliseconds: millis
Private - signal 'aSemaphore' after 'millis' milliseconds have elapsed


signal: aSemaphore onInterrupt: anIntegerSignalNumber
Private - signal 'aSemaphore' when the given C signal occurs


[ ]

Random

Category: Streams
My instances are generator streams that produce random numbers, which are floating point values between 0 and 1.


[ Next: | Up:Random ]

Random class: instance creation

new
Create a new random number generator whose seed is given by the current time on the millisecond clock


seed: aFloat
Create a new random number generator whose seed is aFloat


[ Next: | Previous:Random class-instance creation | Up:Random ]

Random: basic

atEnd
This stream never ends. Always answer false


next
Return the next random number in the sequence


nextPut: value
This method should not be called for instances of this class.


[ Previous:Random-basic | Up:Random ]

Random: testing

chiSquare
returns under Pentium II, NT 4.0, 93.0


chiSquare: n range: r
Return the chi-square deduced from calculating n random numbers in the 0..r range


[ ]

ReadStream

Category: Streams-Collections
I implement the set of read-only stream objects. You may read from my objects, but you may not write to them.


[ Next: | Up:ReadStream ]

ReadStream class: instance creation

on: aCollection
Answer a new stream working on aCollection from its start.


[ Previous:ReadStream class-instance creation | Up:ReadStream ]

ReadStream: accessing-reading

reverseContents
May be faster than generic stream reverseContents.


size
Answer the receiver's size.


[ ]

ReadWriteStream

Category: Streams-Collections
I am the class of streams that may be read and written from simultaneously. In some sense, I am the best of both ReadStream and WriteStream.


[ Next: | Up:ReadWriteStream ]

ReadWriteStream class: instance creation

on: aCollection
Answer a new stream working on aCollection from its end. You can use #skip: or #position: to move back.


onEmpty: aCollection
Extension: do not require the use of the entire stream - pretend that the stream is empty, regardless of the size of the collection that it operates over. Answer a new stream working on aCollection from its start.


[ Previous:ReadWriteStream class-instance creation | Up:ReadWriteStream ]

ReadWriteStream: positioning

position: anInteger
Unlike WriteStreams, ReadWriteStreams don't truncate the stream


skip: anInteger
Unlike WriteStreams, ReadWriteStreams don't truncate the stream


[ ]

Rectangle

Category: Language-Data types
Beginning of the Rectangle class for simple display manipulation. Rectangles require the Point class to be available. An extension to the Point class is made here that since it requires Rectangles to be defined (see converting)


[ Next: | Up:Rectangle ]

Rectangle class: instance creation

left: leftNumber right: rightNumber top: topNumber bottom: bottomNumber
Answer a rectangle with the given coordinates


new
Answer the (0 @ 0 corner: 0 @ 0) rectangle


origin: originPoint corner: cornerPoint
Answer a rectangle with the given corners


origin: originPoint extent: extentPoint
Answer a rectangle with the given origin and size


[ Next: | Previous:Rectangle class-instance creation | Up:Rectangle ]

Rectangle: accessing

bottom
Answer the corner's y of the receiver


bottom: aNumber
Set the corner's y of the receiver


bottomCenter
Answer the center of the receiver's bottom side


bottomLeft
Answer the bottom-left corner of the receiver


bottomLeft: aPoint
Answer the receiver with the bottom-left changed to aPoint


bottomRight
Answer the bottom-right corner of the receiver


bottomRight: aPoint
Change the bottom-right corner of the receiver


center
Answer the center of the receiver


corner
Answer the corner of the receiver


corner: aPoint
Set the corner of the receiver


extent
Answer the extent of the receiver


extent: aPoint
Change the size of the receiver, keeping the origin the same


height
Answer the height of the receiver


height: aNumber
Set the height of the receiver


left
Answer the x of the left edge of the receiver


left: aValue
Set the x of the left edge of the receiver


left: l top: t right: r bottom: b
Change all four the coordinates of the receiver's corners


leftCenter
Answer the center of the receiver's left side


origin
Answer the top-left corner of the receiver


origin: aPoint
Change the top-left corner of the receiver to aPoint


origin: pnt1 corner: pnt2
Change both the origin (top-left corner) and the corner (bottom-right corner) of the receiver


origin: pnt1 extent: pnt2
Change the top-left corner and the size of the receiver


right
Answer the x of the bottom-right corner of the receiver


right: aNumber
Change the x of the bottom-right corner of the receiver


rightCenter
Answer the center of the receiver's right side


top
Answer the y of the receiver's top-left corner


top: aValue
Change the y of the receiver's top-left corner


topCenter
Answer the center of the receiver's top side


topLeft
Answer the receiver's top-left corner


topLeft: aPoint
Change the receiver's top-left corner's coordinates to aPoint


topRight
Answer the receiver's top-right corner


topRight: aPoint
Change the receiver's top-right corner to aPoint


width
Answer the receiver's width


width: aNumber
Change the receiver's width to aNumber


[ Next: | Previous:Rectangle-accessing | Up:Rectangle ]

Rectangle: printing

printOn: aStream
Print a representation of the receiver on aStream


storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Next: | Previous:Rectangle-printing | Up:Rectangle ]

Rectangle: rectangle functions

amountToTranslateWithin: aRectangle
Answer a Point so that if aRectangle is translated by that point, its origin coincides with the receiver's.


area
Answer the receiver's area. The area is the width times the height, so it is possible for it to be negative if the rectangle is not normalized.


areasOutside: aRectangle
Answer a collection of rectangles containing the parts of the receiver outside of aRectangle. For all points in the receiver, but outside aRectangle, exactly one rectangle in the collection will contain that point.


expandBy: delta
Answer a new rectangle that is the receiver expanded by aValue: if aValue is a rectangle, calculate origin=origin-aValue origin, corner=corner+aValue corner; else calculate origin=origin-aValue, corner=corner+aValue.


insetBy: delta
Answer a new rectangle that is the receiver inset by aValue: if aValue is a rectangle, calculate origin=origin+aValue origin, corner=corner-aValue corner; else calculate origin=origin+aValue, corner=corner-aValue.


insetOriginBy: originDelta corner: cornerDelta
Answer a new rectangle that is the receiver inset so that origin=origin+originDelta, corner=corner-cornerDelta. The deltas can be points or numbers


intersect: aRectangle
Returns the rectangle (if any) created by the overlap of rectangles A and B.


merge: aRectangle
Answer a new rectangle which is the smallest rectangle containing both the receiver and aRectangle.


[ Next: | Previous:Rectangle-rectangle functions | Up:Rectangle ]

Rectangle: testing

= aRectangle
Answer whether the receiver is equal to aRectangle


contains: aRectangle
Answer true if the receiver contains (see containsPoint:) both aRectangle's origin and aRectangle's corner


containsPoint: aPoint
Answer true if aPoint is equal to, or below and to the right of, the receiver's origin; and aPoint is above and to the left of the receiver's corner


hash
Answer an hash value for the receiver


intersects: aRectangle
Answer true if the receiver intersect aRectangle, i.e. if it contains (see containsPoint:) any of aRectangle corners or if aRectangle contains the receiver


[ Next: | Previous:Rectangle-testing | Up:Rectangle ]

Rectangle: transforming

moveBy: aPoint
Change the receiver so that the origin and corner are shifted by aPoint


moveTo: aPoint
Change the receiver so that the origin moves to aPoint and the size remains unchanged


scaleBy: scale
Answer a copy of the receiver in which the origin and corner are multiplied by scale


translateBy: factor
Answer a copy of the receiver in which the origin and corner are shifted by aPoint


[ Previous:Rectangle-transforming | Up:Rectangle ]

Rectangle: truncation and round off

rounded
Answer a copy of the receiver with the coordinates rounded to the nearest integers


[ ]

RunArray

Category: Collection-Sequenceable
My instances are OrderedCollections that automatically apply Run Length Encoding compression to the things they store. Be careful when using me: I can provide great space savings, but my instances don't grant linear access time. RunArray's behavior currently is similar to that of OrderedCollection (you can add elements to RunArrays); maybe it should behave like an ArrayedCollection.


[ Next: | Up:RunArray ]

RunArray class: instance creation

new
Answer an empty RunArray


new: aSize
Answer a RunArray with space for aSize runs


[ Next: | Previous:RunArray class-instance creation | Up:RunArray ]

RunArray: accessing

at: anIndex
Answer the element at index anIndex


at: anIndex put: anObject
Replace the element at index anIndex with anObject and answer anObject


[ Next: | Previous:RunArray-accessing | Up:RunArray ]

RunArray: adding

add: anObject afterIndex: anIndex
Add anObject after the element at index anIndex


addAll: aCollection afterIndex: anIndex
Add all the elements of aCollection after the one at index anIndex. If aCollection is unordered, its elements could be added in an order which is not the #do: order


addAllFirst: aCollection
Add all the elements of aCollection at the beginning of the receiver. If aCollection is unordered, its elements could be added in an order which is not the #do: order


addAllLast: aCollection
Add all the elements of aCollection at the end of the receiver. If aCol- lection is unordered, its elements could be added in an order which is not the #do: order


addFirst: anObject
Add anObject at the beginning of the receiver. Watch out: this operation can cause serious performance pitfalls


addLast: anObject
Add anObject at the end of the receiver


[ Next: | Previous:RunArray-adding | Up:RunArray ]

RunArray: basic

first
Answer the first element in the receiver


last
Answer the last element of the receiver


size
Answer the number of elements in the receiver


[ Next: | Previous:RunArray-basic | Up:RunArray ]

RunArray: copying

deepCopy
Answer a copy of the receiver containing copies of the receiver's elements (#copy is used to obtain them)


shallowCopy
Answer a copy of the receiver. The elements are not copied


[ Next: | Previous:RunArray-copying | Up:RunArray ]

RunArray: enumerating

do: aBlock
Enumerate all the objects in the receiver, passing each one to aBlock


objectsAndRunLengthsDo: aBlock
Enumerate all the runs in the receiver, passing to aBlock two parameters for every run: the first is the repeated object, the second is the number of copies


[ Next: | Previous:RunArray-enumerating | Up:RunArray ]

RunArray: removing

removeAtIndex: anIndex
Remove the object at index anIndex from the receiver and answer the removed object


removeFirst
Remove the first object from the receiver and answer the removed object


removeLast
Remove the last object from the receiver and answer the removed object


[ Next: | Previous:RunArray-removing | Up:RunArray ]

RunArray: searching

indexOf: anObject startingAt: anIndex ifAbsent: aBlock
Answer the index of the first copy of anObject in the receiver, starting the search at the element at index anIndex. If no equal object is found, answer the result of evaluating aBlock


[ Previous:RunArray-searching | Up:RunArray ]

RunArray: testing

= anObject
Answer true if the receiver is equal to anObject


hash
Answer an hash value for the receiver


[ ]

Semaphore

Category: Language-Processes
My instances represent counting semaphores. I provide methods for signalling the semaphore's availability, and methods for waiting for its availability. I also provide some methods for implementing critical sections. I currently do not (because the underlying system does not) support asynchronous signals, such as might be generated by C signals.


[ Next: | Up:Semaphore ]

Semaphore class: instance creation

forMutualExclusion
Answer a new semaphore with a signal on it. These semaphores are a useful shortcut when you use semaphores as critical sections.


new
Answer a new semaphore


[ Next: | Previous:Semaphore class-instance creation | Up:Semaphore ]

Semaphore: builtins

signal
Signal the receiver, resuming a waiting process' if there is one


wait
Wait for the receiver to be signalled, suspending the executing process if it is not yet


[ Previous:Semaphore-builtins | Up:Semaphore ]

Semaphore: mutual exclusion

critical: aBlock
Wait for the receiver to be free, execute aBlock and signal the receiver again. Return the result of evaluating aBlock. aBlock MUST NOT CONTAIN A RETURN!!!


[ ]

SequenceableCollection

Category: Collections-Sequenceable
My instances represent collections of objects that are ordered. I provide some access and manipulation methods.


[ Next: | Up:SequenceableCollection ]

SequenceableCollection: basic

after: oldObject
Return the element after oldObject. Error if oldObject not found or if no following object is available


atAll: aCollection put: anObject
Put anObject at every index contained in aCollection


atAllPut: anObject
Put anObject at every index in the receiver


before: oldObject
Return the element before oldObject. Error if oldObject not found or if no preceding object is available


first
Answer the first item in the receiver


indexOf: anElement
Answer the index of the first occurrence of anElement in the receiver. Answer 0 if no item is found


indexOf: anElement ifAbsent: exceptionBlock
Answer the index of the first occurrence of anElement in the receiver. Invoke exceptionBlock and answer its result if no item is found


indexOf: anElement startingAt: anIndex
Answer the first index > anIndex which contains anElement. Answer 0 if no item is found


indexOf: anElement startingAt: anIndex ifAbsent: exceptionBlock
Answer the first index > anIndex which contains anElement. Invoke exceptionBlock and answer its result if no item is found


indexOfSubCollection: aSubCollection
Answer the first index > anIndex at which starts a sequence of items matching aSubCollection. Answer 0 if no such sequence is found.


indexOfSubCollection: aSubCollection ifAbsent: exceptionBlock
Answer the first index > anIndex at which starts a sequence of items matching aSubCollection. Answer 0 if no such sequence is found.


indexOfSubCollection: aSubCollection startingAt: anIndex
Answer the first index > anIndex at which starts a sequence of items matching aSubCollection. Answer 0 if no such sequence is found.


indexOfSubCollection: aSubCollection startingAt: anIndex ifAbsent: exceptionBlock
Answer the first index > anIndex at which starts a sequence of items matching aSubCollection. Invoke exceptionBlock and answer its result if no such sequence is found


last
Answer the last item in the receiver


[ Next: | Previous:SequenceableCollection-basic | Up:SequenceableCollection ]

SequenceableCollection: copying SequenceableCollections

, aSequenceableCollection
Append aSequenceableCollection at the end of the receiver (using #add:), and answer a new collection


copyFrom: start to: stop
Answer a new collection containing all the items in the receiver from the start-th and to the stop-th


copyReplaceAll: oldSubCollection with: newSubCollection
Answer a new collection in which all the sequences matching oldSubCollection are replaced with newSubCollection


copyReplaceFrom: start to: stop with: replacementCollection
Answer a new collection of the same class as the receiver that contains the same elements as the receiver, in the same order, except for elements from index `start' to index `stop'. If start < stop, these are replaced by the contents of the replacementCollection. Instead, If start = (stop + 1), like in `copyReplaceFrom: 4 to: 3 with: anArray', then every element of the receiver will be present in the answered copy; the operation will be an append if stop is equal to the size of the receiver or, if it is not, an insert before index `start'.


copyReplaceFrom: start to: stop withObject: anObject
Answer a new collection of the same class as the receiver that contains the same elements as the receiver, in the same order, except for elements from index `start' to index `stop'. If start < stop, these are replaced by the single element anObject. Instead, If start = (stop + 1), then every element of the receiver will be present in the answered copy; the operation will be an append if stop is equal to the size of the receiver or, if it is not, an insert before index `start'.


[ Next: | Previous:SequenceableCollection-copying SequenceableCollections | Up:SequenceableCollection ]

SequenceableCollection: enumerating

do: aBlock
Evaluate aBlock for all elements in the sequenceable collection


doWithIndex: aBlock
Evaluate aBlock for all elements in the sequenceable collection, passing the index of each element as the second parameter


findFirst: aBlock
Returns the index of the first element of the sequenceable collection for which aBlock returns true, or 0 if none


findLast: aBlock
Returns the index of the last element of the sequenceable collection for which aBlock returns true, or 0 if none does


from: startIndex to: stopIndex do: aBlock
Evaluate aBlock for all elements in the sequenceable collection whose indices are in the range index to stopIndex


from: startIndex to: stopIndex doWithIndex: aBlock
Evaluate aBlock for all elements in the sequenceable collection whose indices are in the range index to stopIndex, passing the index of each element as the second parameter


readStream
Answer a ReadStream streaming on the receiver


readWriteStream
Answer a ReadWriteStream which streams on the receiver


reverse
Answer the receivers' contents in reverse order


reverseDo: aBlock
Evaluate aBlock for all elements in the sequenceable collection, from the last to the first.


with: aSequenceableCollection do: aBlock
Evaluate aBlock for each pair of elements took respectively from the re- ceiver and from aSequenceableCollection. Fail if the receiver has not the same size as aSequenceableCollection.


writeStream
Answer a WriteStream streaming on the receiver


[ Next: | Previous:SequenceableCollection-enumerating | Up:SequenceableCollection ]

SequenceableCollection: replacing items

replaceFrom: start to: stop with: replacementCollection
Replace the items from start to stop with replacementCollection's items from 1 to stop-start+1


replaceFrom: start to: stop with: replacementCollection startingAt: repStart
Replace the items from start to stop with replacementCollection's items from repStart to repStart+stop-start


replaceFrom: anIndex to: stopIndex withObject: replacementObject
Replace every item from start to stop with replacementObject.


[ Previous:SequenceableCollection-replacing items | Up:SequenceableCollection ]

SequenceableCollection: testing

= aCollection
Answer whether the receiver's items match those in aCollection


hash
Answer an hash value for the receiver


inspect
Print all the instance variables and context of the receiver on the Transcript


[ ]

Set

Category: Collections-Unordered
I am the typical set object; I can store any objects uniquely. I use the = operator to determine duplication of objects.


[ Next: | Up:Set ]

Set class: instance creation

new
Answer a new instance of the receiver with a default size


new: anInteger
Answer a new instance of the receiver with the given size


[ Next: | Previous:Set class-instance creation | Up:Set ]

Set: accessing

add: newObject
Add newObject to the set, if and only if the set doesn't already contain an occurrence of it. Don't fail if a duplicate is found. Answer anObject


at: index
This method should not be called for instances of this class.


at: index put: value
This method should not be called for instances of this class.


[ Next: | Previous:Set-accessing | Up:Set ]

Set: awful ST-80 compatibility hacks

findObjectIndex: object
Tries to see if anObject exists as an indexed variable. As soon as nil or anObject is found, the index of that slot is answered


[ Next: | Previous:Set-awful ST-80 compatibility hacks | Up:Set ]

Set: enumerating the elements of a collection

do: aBlock
Enumerate all the non-nil members of the set


[ Next: | Previous:Set-enumerating the elements of a collection | Up:Set ]

Set: rehashing

rehash
Rehash the receiver


[ Next: | Previous:Set-rehashing | Up:Set ]

Set: Removing from a collection

remove: oldObject ifAbsent: anExceptionBlock
Remove oldObject to the set. If it is found, answer oldObject. Otherwise, evaluate anExceptionBlock and return its value.


[ Next: | Previous:Set-Removing from a collection | Up:Set ]

Set: storing

storeOn: aStream
Store on aStream some Smalltalk code which compiles to the receiver


[ Previous:Set-storing | Up:Set ]

Set: testing collections

= aSet
Returns true if the two sets have the same membership, false if not


capacity
Answer how many elements the receiver can hold before having to grow.


hash
Return the hash code for the members of the set. Since order is unimportant, we use a commutative operator to compute the hash value.


includes: anObject
Answer whether the receiver contains an instance of anObject.


isEmpty
Answer whether the receiver is empty.


occurrencesOf: anObject
Return the number of occurrences of anObject. Since we're a set, this is either 0 or 1. Nil is never directly in the set, so we special case it (the result is always 1).


size
Answer the receiver's size


[ ]

SharedQueue

Category: Language-Processes
My instances provide a guaranteed safe mechanism to allow for communication between processes. All access to the underlying data structures is controlled with critical sections so that things proceed smoothly.


[ Next: | Up:SharedQueue ]

SharedQueue class: instance creation

new
Create a new instance of the receiver


[ Previous:SharedQueue class-instance creation | Up:SharedQueue ]

SharedQueue: accessing

next
Wait for an object to be on the queue, then remove it and answer it


nextPut: value
Put value on the queue and answer it


[ ]

Signal

Category: Language-Exceptions
My instances describe an exception that has happened, and are passed to exception handlers. Apart from containing information on the generated exception and its arguments, they contain methods that allow you to resume execution, leave the #on:do:... snippet, and pass the exception to an handler with a lower priority.


[ Next: | Up:Signal ]

Signal: accessing

argument
Answer the first argument of the receiver


argumentCount
Answer how many arguments the receiver has


arguments
Answer the arguments of the receiver


description
Answer the description of the raised exception


exception
Answer the exception that was raised


[ Previous:Signal-accessing | Up:Signal ]

Signal: exception handling

defaultAction
Execute the default handler for the raised exception


isNested
Answer whether the current exception handler is within the scope of another handler for the same exception.


outer
Raise the exception that instantiated the receiver, passing the same parameters. If the receiver is resumable and the evaluated exception action resumes then the result returned from #outer will be the resumption value of the evaluated exception action. If the receiver is not resumable or if the exception action does not resume then this message will not return, and #outer will be equivalent to #pass.


pass
Yield control to the enclosing exception action for the receiver. Similar to #outer, but control does not return to the currently active exception handler.


resume
If the exception is resumable, resume the execution of the block that raised the exception; the method that was used to signal the exception will answer the receiver. Use this method IF AND ONLY IF you know who caused the exception and if it is possible to resume it in that particular case


resume: anObject
If the exception is resumable, resume the execution of the block that raised the exception; the method that was used to signal the exception will answer anObject. Use this method IF AND ONLY IF you know who caused the exception and if it is possible to resume it in that particular case


retry
Re-execute the receiver of the #on:do: message. All handlers are reinstated: watch out, this can easily cause an infinite loop.


retryUsing: aBlock
Execute aBlock reinstating all handlers, and return its result from the #signal method.


return
Exit the #on:do: snippet, answering anObject to its caller


return: anObject
Exit the #on:do: snippet, answering anObject to its caller


[ ]

SortedCollection

Category: Collections-Sequenceable
I am a collection of objects, stored and accessed according to some sorting criteria. I store things using a bubble sort. My instances have a comparison block associated with them; this block takes two arguments and is a predicate which returns true if the first argument should be sorted earlier than the second. The default block is [ :a :b | a <= b ], but I will accept any block that conforms to the above criteria.


[ Next: | Up:SortedCollection ]

SortedCollection class: hacking

defaultSortBlock
Answer a default sort block for the receiver.


[ Next: | Previous:SortedCollection class-hacking | Up:SortedCollection ]

SortedCollection class: instance creation

new
Answer a new collection with a default size and sort block


new: aSize
Answer a new collection with a default sort block and the given size


sortBlock: aSortBlock
Answer a new collection with a default size and the given sort block


[ Next: | Previous:SortedCollection class-instance creation | Up:SortedCollection ]

SortedCollection: basic

add: anObject
Add anObject into the collection at the proper place


add: anObject afterIndex: i
This method should not be called for instances of this class.


addAll: aCollection
Add all the elements in aCollection to the receiver in their proper places


addAll: aCollection afterIndex: i
This method should not be called for instances of this class.


addAllFirst: aCollection
This method should not be called for instances of this class.


addAllLast: aCollection
This method should not be called for instances of this class.


addFirst: anObject
This method should not be called for instances of this class.


addLast: anObject
This method should not be called for instances of this class.


at: index put: anObject
This method should not be called for instances of this class.


reverse
Answer an OrderedCollection containing the data in the receiver in reverse ordering


[ Next: | Previous:SortedCollection-basic | Up:SortedCollection ]

SortedCollection: copying

copyEmpty: newSize
Answer an empty copy of the receiver, with the same sort block as the receiver


[ Next: | Previous:SortedCollection-copying | Up:SortedCollection ]

SortedCollection: enumerating

collect: aBlock
Answer an OrderedCollection containing the data in the receiver filtered through the given block


[ Next: | Previous:SortedCollection-enumerating | Up:SortedCollection ]

SortedCollection: instance protocol

sortBlock
Answer the receiver's sort criteria


sortBlock: aSortBlock
Change the sort criteria for a sorted collection, resort the elements of the collection, and return it.


[ Previous:SortedCollection-instance protocol | Up:SortedCollection ]

SortedCollection: searching

includes: anObject
Private - Answer whether the receiver includes an item which is equal to anObject


indexOf: anObject startingAt: index ifAbsent: aBlock
Answer the first index > anIndex which contains anElement. Invoke exceptionBlock and answer its result if no item is found


occurrencesOf: anObject
Answer how many occurrences of anObject can be found in the receiver


[ ]

Stream

Category: Streams
I am an abstract class that provides interruptable sequential access to objects. I can return successive objects from a source, or accept successive objects and store them sequentially on a sink. I provide some simple iteration over the contents of one of my instances, and provide for writing collections sequentially.


[ Next: | Up:Stream ]

Stream: accessing-reading

contents
Answer the whole contents of the receiver, from the next object to the last


next
Return the next object in the receiver


next: anInteger
Return the next anInteger objects in the receiver


nextMatchFor: anObject
Answer whether the next object is equal to anObject. Even if it does not, anObject is lost


[ Next: | Previous:Stream-accessing-reading | Up:Stream ]

Stream: accessing-writing

next: anInteger put: anObject
Write anInteger copies of anObject to the receiver


nextPut: anObject
Write anObject to the receiver


nextPutAll: aCollection
Write all the objects in aCollection to the receiver


[ Next: | Previous:Stream-accessing-writing | Up:Stream ]

Stream: basic

species
Answer `Array'.


[ Next: | Previous:Stream-basic | Up:Stream ]

Stream: character writing

cr
Store a cr on the receiver


crTab
Store a cr and a tab on the receiver


nl
Store a new line on the receiver


nlTab
Store a new line and a tab on the receiver


space
Store a space on the receiver


tab
Store a tab on the receiver


[ Next: | Previous:Stream-character writing | Up:Stream ]

Stream: enumerating

do: aBlock
Evaluate aBlock once for every object in the receiver


[ Next: | Previous:Stream-enumerating | Up:Stream ]

Stream: filing out

fileOut: aClass
File out aClass on the receiver. If aClass is not a metaclass, file out class and instance methods; if aClass is a metaclass, file out only the class methods


[ Next: | Previous:Stream-filing out | Up:Stream ]

Stream: printing

print: anObject
Print anObject on the receiver by sending printOn: to anObject. This method is provided so that you can use cascading and obtain better-looking code


[ Next: | Previous:Stream-printing | Up:Stream ]

Stream: providing consistent protocols

close
Do nothing. This is provided for consistency with file streams


[ Next: | Previous:Stream-providing consistent protocols | Up:Stream ]

Stream: storing

store: anObject
Print Smalltalk code compiling to anObject on the receiver, by sending storeOn: to anObject. This method is provided so that you can use cascading and obtain better-looking code


[ Previous:Stream-storing | Up:Stream ]

Stream: testing

atEnd
Answer whether the stream has got to an end


[ ]

String

Category: Language-Data types
My instances represent string data types. I provide accessing and manipulation methods for string data types.


[ Next: | Up:String ]

String class: basic

fromString: aString
But we are already strings! So just answer a fresh copy of aString.


lineDelimiter
Answer a String which one can use as a line delimiter.


[ Next: | Previous:String class-basic | Up:String ]

String class: instance creation

fromCData: aCObject size: anInteger
Answer a String containing anInteger bytes starting at the location pointed to by aCObject


[ Next: | Previous:String class-instance creation | Up:String ]

String: built ins

asCData: aCType
Convert the receiver to a CObject with the given type


at: index
Answer the index-th character of the receiver.


at: index put: value
Change the index-th character of the receiver.


basicAt: index
Answer the index-th character of the receiver. This method must not be overridden; override at: instead. String overrides it so that it looks like it contains character objects even though it contains bytes


basicAt: index put: value
Change the index-th character of the receiver. This method must not be overridden; override at: instead. String overrides it so that it looks like it contains character objects even though it contains bytes


hash
Answer an hash value for the receiver


primReplaceFrom: start to: stop with: replacementString
startingAt: replaceStart Private - Replace the characters from start to stop with new characters contained in replacementString (which, actually, can be any variable byte class, starting at the replaceStart location of replacementString


replaceFrom: start to: stop with: aString startingAt: replaceStart
Replace the characters from start to stop with new characters whose ASCII codes are contained in aString, starting at the replaceStart location of aString


replaceFrom: start to: stop withByteArray: byteArray startingAt: replaceStart
Replace the characters from start to stop with new characters whose ASCII codes are contained in byteArray, starting at the replaceStart location of byteArray


size
Answer the size of the receiver


valueAt: index
Answer the ascii value of index-th character variable of the receiver


valueAt: index put: value
Store (Character value: value) in the index-th indexed instance variable of the receiver


[ Next: | Previous:String-built ins | Up:String ]

String: comparing

< aString
Return true if the receiver is less than aString, ignoring case differences.


<= aString
Returns true if the receiver is less than or equal to aString, ignoring case differences. If is receiver is an initial substring of aString, it is considered to be less than aString.


> aString
Return true if the receiver is greater than aString, ignoring case differences.


>= aString
Returns true if the receiver is greater than or equal to aString, ignoring case differences. If is aString is an initial substring of the receiver, it is considered to be less than the receiver.


indexOf: aString matchCase: aBoolean startingAt: anIndex
Answer an Interval of indices in the receiver which match the aString pattern. # in aString means 'match any character', * in aString means 'match any sequence of characters'. The first item of the returned in- terval is >= anIndex. If aBoolean is false, the search is case-insen- sitive, else it is case-sensitive. If no Interval matches the pattern, answer nil.


match: aString
Answer whether the receiver matches the aString pattern. # in aString means 'match any character', * in aString means 'match any sequence of characters'


sameAs: aString
Returns true if the receiver is the same string as aString, ignoring case differences.


[ Next: | Previous:String-comparing | Up:String ]

String: converting

asByteArray
Return the receiver, converted to a ByteArray of ASCII values


asClassPoolKey
Return the receiver, ready to be put in a class pool dictionary


asGlobalKey
Return the receiver, ready to be put in the Smalltalk dictionary


asInteger
Parse an Integer number from the receiver until the input character is invalid and answer the result at this point


asLowercase
Returns a copy of self as a lowercase string


asNumber
Parse a Number from the receiver until the input character is invalid and answer the result at this point


asPoolKey
Return the receiver, ready to be put in a pool dictionary


asString
But I already am a string! Really!


asSymbol
Returns the symbol corresponding to the string


asUppercase
Returns a copy of self as an uppercase string


fileName
But I don't HAVE a file name!


filePos
But I don't HAVE a file position!


isNumeric
Answer whether the receiver denotes a number


[ Next: | Previous:String-converting | Up:String ]

String: copying

, aString
Answer a new instance of an ArrayedCollection containing all the elements in the receiver, followed by all the elements in aSequenceableCollection


deepCopy
Returns a deep copy of the receiver. This is the same thing as a shallow copy for strings


replaceFrom: start to: stop with: replacementCollection
Replace the items from start to stop with replacementCollection's items from repStart to repStart+stop-start


shallowCopy
Returns a shallow copy of the receiver


[ Next: | Previous:String-copying | Up:String ]

String: printing

printOn: aStream
Print a representation of the receiver on aStream


[ Next: | Previous:String-printing | Up:String ]

String: storing

storeOn: aStream
Print Smalltalk code compiling to the receiver on aStream


[ Next: | Previous:String-storing | Up:String ]

String: string processing

bindWith: s1
Answer the receiver with every %1 replaced by s1


bindWith: s1 with: s2
Answer the receiver with every %1 or %2 replaced by s1 or s2, respectively


bindWith: s1 with: s2 with: s3
Answer the receiver with every %1, %2 or %3 replaced by s1, s2 or s3, respectively


bindWith: s1 with: s2 with: s3 with: s4
Answer the receiver with every %1, %2, %3 or %4 replaced by s1, s2, s3 or s4, respectively


bindWithArguments: anArray
Answer the receiver with every %n (1<=n<=9) replaced by the n-th element of anArray


substrings
Answer an OrderedCollection of substrings of the receiver. A new substring start at the start of the receiver, or after every sequence of white space characters


substrings: aCharacter
Answer an OrderedCollection of substrings of the receiver. A new substring start at the start of the receiver, or after every sequence of characters matching aCharacter


[ Next: | Previous:String-string processing | Up:String ]

String: testing functionality

isString
Answer `true'.


[ Previous:String-testing functionality | Up:String ]

String: useful functionality

linesDo: aBlock
Send 'aBlock' a substring of the receiver for each newline delimited line in the receiver


trimSeparators
Trim leading and trailing separators from the receiver and answer a new string


[ ]

Symbol

Category: Language-Implementation
My instances are unique throughout the Smalltalk system. My instances behave for the most part like strings, except that they print differently, and I guarantee that any two instances that have the same printed representation are in fact the same instance.


[ Next: | Up:Symbol ]

Symbol class: built ins

intern: aString
Private - Same as 'aString asSymbol'


[ Next: | Previous:Symbol class-built ins | Up:Symbol ]

Symbol class: instance creation

internCharacter: aCharacter
Answer the one-character symbol associated to the given character.


isSymbolString: aString
Answer whether aString has already been interned. Note that this works because String>>#hash calculates the same hash value used when interning strings into the SymbolTable. Changing one of the hashing methods without changing the other will break this method.


new
This method should not be called for instances of this class.


new: size
This method should not be called for instances of this class.


with: element1
Answer a collection whose only element is element1


with: element1 with: element2
Answer a collection whose only elements are the parameters in the order they were passed


with: element1 with: element2 with: element3
Answer a collection whose only elements are the parameters in the order they were passed


with: element1 with: element2 with: element3 with: element4
Answer a collection whose only elements are the parameters in the order they were passed


[ Next: | Previous:Symbol class-instance creation | Up:Symbol ]

Symbol: basic

argumentCount
Answer the number of arguments supported by the receiver, which is supposed to be a valid message name (#+, #not, #printOn:, #ifTrue:ifFalse:, etc.)


[ Next: | Previous:Symbol-basic | Up:Symbol ]

Symbol: built ins

= aSymbol
Answer whether the receiver and aSymbol are the same object


hash
Answer an hash value for the receiver. Symbols are optimized for speed


[ Next: | Previous:Symbol-built ins | Up:Symbol ]

Symbol: converting

asString
Answer a String with the same characters as the receiver


asSymbol
But we are already a Symbol, and furthermore, Symbols are identity objects! So answer the receiver.


[ Next: | Previous:Symbol-converting | Up:Symbol ]

Symbol: misc

species
Answer `String'.


[ Next: | Previous:Symbol-misc | Up:Symbol ]

Symbol: storing

storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream


[ Previous:Symbol-storing | Up:Symbol ]

Symbol: testing functionality

isString
Answer `false'.


isSymbol
Answer `true'.


[ ]

SymLink

Category: Language-Implementation
I am used to implement the Smalltalk symbol table. My instances are links that contain symbols, and the symbol table basically a hash table that points to chains of my instances.


[ Next: | Up:SymLink ]

SymLink: iteration

do: aBlock
Evaluate aBlock for each symbol in the list


[ Previous:SymLink-iteration | Up:SymLink ]

SymLink: printing

printOn: aStream
Print a representation of the receiver on aStream.


[ ]

SystemDictionary

Category: Language-Implementation
I am a special form of dictionary. Typically I only have one instance, called "Smalltalk", which is known to the Smalltalk interpreter. I define several methods that are "system" related, such as #quitPrimitive. My instance also helps keep track of dependencies between objects.


[ Next: | Up:SystemDictionary ]

SystemDictionary: basic

halt
Interrupt interpreter


initialize
Initialize the globals


printOn: aStream
Print a representation of the receiver


storeOn: aStream
Store Smalltalk code compiling to the receiver


[ Next: | Previous:SystemDictionary-basic | Up:SystemDictionary ]

SystemDictionary: builtins

byteCodeCounter
Answer the number of bytecodes executed by the VM


compact
Force a full garbage collection


debug
for DBX. Set breakpoint in debug() and invoke this primitive near where you want to stop


declarationTrace
Answer whether compiled bytecodes are printed on stdout


declarationTrace: aBoolean
Set whether compiled bytecodes are printed on stdout


enableGC: aBoolean
Enable GC of Smalltalk objects referenced in callins/callouts


executionTrace
Answer whether executed bytecodes are printed on stdout


executionTrace: aBoolean
Set whether executed bytecodes are printed on stdout


gcMessage
Answer whether messages indicating that garbage collection is taking place are printed on stdout


gcMessage: aBoolean
Set whether messages indicating that garbage collection is taking place are printed on stdout


getTraceFlag: anIndex
Private - Returns a boolean value which is one of the interpreter's tracing flags


growThresholdPercent
Answer the percentage of the amount of memory used by the system grows which has to be full for the system to allocate more memory


growThresholdPercent: growPercent
Set the percentage of the amount of memory used by the system grows which has to be full for the system to allocate more memory


growTo: numBytes
Grow the amount of memory used by the system grows to numBytes.


monitor: aBoolean
Start or stop profiling the VM's execution (if GNU Smalltalk was compiled with support for monitor(2), of course).


printStatistics
Print statistics about what the VM did since #resetStatistics was last called. Meaningful only if gst was made with `make profile' or `make profile_vm'


quitPrimitive
Quit the Smalltalk environment. Whether files are closed and other similar cleanup occurs depends on the platform


quitPrimitive: exitStatus
Quit the Smalltalk environment, passing the exitStatus integer to the OS. Whether files are closed and other similar cleanup occurs depends on the platform


resetStatistics
Reset the statistics about the VM which #printStatistics can print.


setTraceFlag: anIndex to: aBoolean
Private - Sets the value of one of the interpreter's tracing flags (indicated by 'anIndex') to the value aBoolean.


snapshot: aString
Save an image on the aString file


spaceGrowRate
Answer the rate with which the amount of memory used by the system grows


spaceGrowRate: rate
Set the rate with which the amount of memory used by the system grows


verboseTrace
Answer whether execution tracing prints the object on the stack top


verboseTrace: aBoolean
Set whether execution tracing prints the object on the stack top


[ Next: | Previous:SystemDictionary-builtins | Up:SystemDictionary ]

SystemDictionary: C functions

getArgc
C call-out to getArgc. Do not modify!


getArgv: index
C call-out to getArgv. Do not modify!


getenv: aString
C call-out to getenv. Do not modify!


putenv: aString
C call-out to putenv. Do not modify!


system: aString
C call-out to system. Do not modify!


[ Next: | Previous:SystemDictionary-C functions | Up:SystemDictionary ]

SystemDictionary: initialization

addInit: aBlock
Adds 'aBlock' to the array of blocks to be invoked after every start of the system. If the kernel has been already initialized, evaluate the block


doInits
Called after the system has loaded the image, this will invoke any init blocks that have been installed.


[ Next: | Previous:SystemDictionary-initialization | Up:SystemDictionary ]

SystemDictionary: miscellaneous

arguments
Return the command line arguments after the -a switch


backtrace
Print a backtrace on the Transcript.


snapshot
Save a snapshot on the image file that was loaded on startup


[ Previous:SystemDictionary-miscellaneous | Up:SystemDictionary ]

SystemDictionary: special accessing

addFeature: aFeature
Add the aFeature feature to the Features set


allBehaviorsDo: aBlock
Evaluate aBlock once for each class and metaclass in the system. Trick: the class objects for classes directly derived from nil (for example `Object class') are subclasses of *Class* (see UndefinedObject>>#subclass:instanceVariableNames:...)


allClassesDo: aBlock
Evaluate aBlock once for each class in the system. Trick: the class objects for classes directly derived from nil (for example `Object class') are subclasses of *Class* (see UndefinedObject>>#subclass:instanceVariableNames:...)


allClassObjectsDo: aBlock
Evaluate aBlock once for each class and metaclass in the system. Trick: the class objects for classes directly derived from nil (for example `Object class') are subclasses of *Class* (see UndefinedObject>>#subclass:instanceVariableNames:...)


allMetaclassesDo: aBlock
Evaluate aBlock once for each metaclass in the system. Trick: the class objects for classes directly derived from nil (for example `Object class') are subclasses of *Class* (see UndefinedObject>>#subclass:instanceVariableNames:...)


classAt: aKey
Answer the value corrisponding to aKey if it is a class. Fail if either aKey is not found or it is associated to something different from a class.


classAt: aKey ifAbsent: aBlock
Answer the value corrisponding to aKey if it is a class. Evaluate aBlock and answer its result if either aKey is not found or it is associated to something different from a class.


dependenciesAt: anObject
Answer the dependants of anObject (or nil if there's no key for anObject in the Dependencies IdentityDictionary)


hasFeatures: features
Returns true if the feature or features in 'features' is one of the implementation dependent features present


removeFeature: aFeature
Remove the aFeature feature to the Features set


version
Answer the current version of the GNU Smalltalk environment


[ ]

Time

Category: Language-Data types
My instances represent times of the day. I provide methods for instance creation, methods that access components (hours, minutes, and seconds) of a time value, and a block execution timing facility.


[ Next: | Up:Time ]

Time class: basic

fromSeconds: secondCount
Answer a Time representing secondCount seconds past midnight


initialize
(99 * 365 + 25) * 86400 secs/day.


millisecondClock
Answer the number of milliseconds since startup


millisecondClockValue
Answer the number of milliseconds since startup


millisecondsPerDay
Answer the number of milliseconds in a day


millisecondsToRun: timedBlock
Answer the number of milliseconds which timedBlock took to run


new
Answer a Time representing midnight


now
Answer a time representing the current time of day


onStartup
Private - Called on startup


secondClock
Answer the number of seconds since the midnight of 1/1/1901


[ Next: | Previous:Time class-basic | Up:Time ]

Time class: builtins

primMillisecondClock
Returns the number of milliseconds since midnight.


primSecondClock
Returns the number of seconds to/from 1/1/2000.


[ Next: | Previous:Time class-builtins | Up:Time ]

Time: accessing

asSeconds
Answer `seconds'.


hours
Answer the number of hours in the receiver


minutes
Answer the number of minutes in the receiver


seconds
Answer the number of seconds in the receiver


[ Next: | Previous:Time-accessing | Up:Time ]

Time: arithmetic

addTime: timeAmount
Answer a new Time that is timeAmount seconds after the receiver


printOn: aStream
Print a representation of the receiver on aStream


subtractTime: timeAmount
Answer a new Time that is timeAmount seconds before the receiver


[ Previous:Time-arithmetic | Up:Time ]

Time: comparing

< aTime
Answer whether the receiver is less than aTime


= aTime
Answer whether the receiver is equal to aTime


hash
Answer an hash value for the receiver


[ ]

TokenStream

Category: Streams-Collections
I am not a typical part of the Smalltalk kernel class hierarchy. I operate on a stream of characters and return distinct whitespace-delimited groups of characters; I am used to parse the parameters of class-creation methods.

Basically, I parse off whitespace separated tokens as substrings and return them (next). If the entire contents of the string are requested, I return them as an Array containing the individual strings.


[ Next: | Up:TokenStream ]

TokenStream class: instance creation

on: aString
Answer a TokenStream working on aString


onStream: aStream
Answer a TokenStream working on the collection on which aStream is in turn streaming.


[ Next: | Previous:TokenStream class-instance creation | Up:TokenStream ]

TokenStream: basic

atEnd
Answer whether the input stream has no more tokens.


next
Answer a new whitespace-separated token from the input stream


[ Previous:TokenStream-basic | Up:TokenStream ]

TokenStream: write methods

nextPut: anObject
This method should not be called for instances of this class.


[ ]

TranscriptInterface

Category: Streams


[ Next: | Up:TranscriptInterface ]

TranscriptInterface class: accessing

new
Answer the only instance of the receiver - which is stored in the global variable Transcript.


[ Next: | Previous:TranscriptInterface class-accessing | Up:TranscriptInterface ]

TranscriptInterface: accessing

cr
Emit a new-line (carriage return) to the Transcript


next: anInteger put: anObject
Write anInteger copies of anObject to the Transcript


nextPut: aCharacter
Emit aCharacter to the Transcript


nextPutAll: aString
Write aString to the Transcript


show: aString
Write aString to the Transcript


showCr: aString
Write aString to the Transcript, followed by a new-line character


showOnNewLine: aString
Write aString to the Transcript, preceded by a new-line character


[ Next: | Previous:TranscriptInterface-accessing | Up:TranscriptInterface ]

TranscriptInterface: printing

print: anObject
Print anObject's representation to the Transcript


printOn: aStream
Print a representation of the receiver onto aStream


[ Next: | Previous:TranscriptInterface-printing | Up:TranscriptInterface ]

TranscriptInterface: set up

message
Private - Answer an association representing the message to be sent to perform write operations. The key is the receiver, the value is the selector


message: anAssociation
Private - Set the message to be sent to perform write operations to the one represented by anAssociation. anAssociation's key is the receiver, while its value is the selector


[ Previous:TranscriptInterface-set up | Up:TranscriptInterface ]

TranscriptInterface: storing

store: anObject
Print Smalltalk code which evaluates to anObject on the Transcript


storeOn: aStream
Print Smalltalk code which evaluates to the receiver onto aStream


[ ]

TrappableEvent

Category: Language-Exceptions
I am an abstract class for arguments passed to #on:do:... methods in BlockClosure. I define a bunch of methods that apply to Exceptions and ExceptionCollections: they allow you to create ExceptionCollections and examine all the exceptions to be trapped.


[ Next: | Up:TrappableEvent ]

TrappableEvent: enumerating

allExceptionsDo: aBlock
Execute aBlock, passing it an Exception for every exception in the receiver.


handles: exception
Answer whether the receiver handles `exception'.


[ Previous:TrappableEvent-enumerating | Up:TrappableEvent ]

TrappableEvent: instance creation

, aTrappableEvent
Answer an ExceptionCollection containing all the exceptions in the receiver and all the exceptions in aTrappableEvent


[ ]

True

Category: Language-Data types
I represent truth and justice in the world. My motto is "semper veritatis".


[ Next: | Up:True ]

True: basic

& aBoolean
We are true - anded with anything, we always answer the other operand


and: aBlock
We are true - anded with anything, we always answer the other operand, so evaluate aBlock


eqv: aBoolean
Answer whether the receiver and aBoolean represent the same boolean value


ifFalse: falseBlock
We are true - answer nil


ifFalse: falseBlock ifTrue: trueBlock
We are true - evaluate trueBlock


ifTrue: trueBlock
We are true - evaluate trueBlock


ifTrue: trueBlock ifFalse: falseBlock
We are true - evaluate trueBlock


not
We are true - answer false


or: aBlock
We are true - ored with anything, we always answer true


xor: aBoolean
Answer whether the receiver and aBoolean represent different boolean values


| aBoolean
We are true - ored with anything, we always answer true


[ Next: | Previous:True-basic | Up:True ]

True: C hacks

asCBooleanValue
Answer `1'.


[ Previous:True-C hacks | Up:True ]

True: printing

printOn: aStream
Print a representation of the receiver on aStream


[ ]

UndefinedObject

Category: Language-Implementation
I have the questionable distinction of being a class with only one instance, which is the object "nil". I suspect that I should be sent messages when errors occur, but currently I am not.


[ Next: | Up:UndefinedObject ]

UndefinedObject: class creation

metaclassFor: classNameString
Create a Metaclass object for the given class name. The metaclass is a subclass of Class


subclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a fixed subclass of the receiver with the given name, instance variables, class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


variableByteSubclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a byte variable subclass of the receiver with the given name, instance variables, class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


variableSubclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a variable pointer subclass of the receiver with the given name, instance variables, class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


variableWordSubclass: classNameString
instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames category: categoryNameString Define a word variable subclass of the receiver with the given name, instance variables, class variables, pool dictionaries and category. If the class is already defined, if necessary, recompile everything needed.


[ Next: | Previous:UndefinedObject-class creation | Up:UndefinedObject ]

UndefinedObject: class creation - alternative

subclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


subclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableByteSubclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableByteSubclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableSubclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableSubclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableWordSubclass: classNameString classInstanceVariableNames: stringClassInstVarNames instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


variableWordSubclass: classNameString instanceVariableNames: stringInstVarNames classVariableNames: stringOfClassVarNames poolDictionaries: stringOfPoolNames
Don't use this, it is only present to file in from IBM Smalltalk


[ Next: | Previous:UndefinedObject-class creation - alternative | Up:UndefinedObject ]

UndefinedObject: printing

printOn: aStream
Print a representation of the receiver on aStream.


[ Next: | Previous:UndefinedObject-printing | Up:UndefinedObject ]

UndefinedObject: storing

storeOn: aStream
Store Smalltalk code compiling to the receiver on aStream.


[ Previous:UndefinedObject-storing | Up:UndefinedObject ]

UndefinedObject: testing

ifNil: nilBlock
Evaluate nilBlock if the receiver is nil, else answer nil


ifNil: nilBlock ifNotNil: notNilBlock
Evaluate nilBlock if the receiver is nil, else evaluate notNilBlock, passing the receiver.


ifNotNil: notNilBlock
Evaluate notNilBlock if the receiver is not nil, passing the receiver. Else answer nil


ifNotNil: notNilBlock ifNotNil: nilBlock
Evaluate nilBlock if the receiver is nil, else evaluate notNilBlock, passing the receiver.


isNil
Answer whether the receiver is the undefined object nil. Always answer true.


notNil
Answer whether the receiver is not the undefined object nil. Always answer false.


[ ]

ValueAdaptor

Category: Language-Data types
My subclasses are used to access data from different objects with a consistent protocol. However, I'm an abstract class.


[ Next: | Up:ValueAdaptor ]

ValueAdaptor class: creating instances

new
We don't know enough of subclasses to have a shared implementation of new


[ Next: | Previous:ValueAdaptor class-creating instances | Up:ValueAdaptor ]

ValueAdaptor: accessing

value
Retrive the value of the receiver. Must be implemented by ValueAdaptor's subclasses


value: anObject
Set the value of the receiver. Must be implemented by ValueAdaptor's subclasses


[ Previous:ValueAdaptor-accessing | Up:ValueAdaptor ]

ValueAdaptor: basic

printOn: aStream
Print a representation of the receiver


[ ]

ValueHolder

Category: Language-Data types
I store my value in a variable. For example, you can use me to pass num- bers by reference. Just instance me before calling a method and ask for my value after that method. There are a lot of other creative uses for my intances, though.


[ Next: | Up:ValueHolder ]

ValueHolder class: creating instances

new
Create a ValueHolder whose starting value is nil


null
Not commented.


with: anObject
Create a ValueHolder whose starting value is anObject


[ Previous:ValueHolder class-creating instances | Up:ValueHolder ]

ValueHolder: accessing

value
Get the value of the receiver.


value: anObject
Set the value of the receiver.


[ ]

WordMemory

Category: Language-Implementation
I have no instances. I provide messages to my class that access real memory as 32-bit words. An alternative implementation would be to have a single instance of word memory that represented all memory, and at: and at:put: accessor methods, but since you'd typically refer to that instance via a global variable, and since the global variable would probably be named WordMemory, the actual method invocations are exactly the same in either case.


[ Up:WordMemory ]

WordMemory class: accessing

at: address
Access a 32-bit word at the given address


at: address put: value
Store value as a 32-bit word at the given address


[ ]

WriteStream

Category: Streams-Collection
I am the class of writeable streams. I only allow write operations to my instances; reading is strictly forbidden.


[ Next: | Up:WriteStream ]

WriteStream class: instance creation

on: aCollection
Answer a new instance of the receiver which streams on aCollection. Every item of aCollection is discarded.


with: aCollection
Answer a new instance of the receiver which streams from the end of aCollection.


with: aCollection from: firstIndex to: lastIndex
Answer a new instance of the receiver which streams from the firstIndex-th item of aCollection to the lastIndex-th. The pointer is moved to the last item in that range.


[ Next: | Previous:WriteStream class-instance creation | Up:WriteStream ]

WriteStream: accessing

size
Answer how many objects have been written


[ Next: | Previous:WriteStream-accessing | Up:WriteStream ]

WriteStream: accessing-writing

nextPut: anObject
Store anObject as the next item in the receiver. Grow the collection if necessary


[ Previous:WriteStream-accessing-writing | Up:WriteStream ]

WriteStream: positioning

emptyStream
Extension - Reset the stream


position: anInteger
Skip to the anInteger-th item backwards in the stream. Fail if anInteger>self position. The stream is truncated after the pointer


skip: anInteger
Skip (anInteger negated) items backwards in the stream. Fail if anInteger>0. The stream is truncated after the pointer


[ Next: | Previous:Class reference | Up:Top ]

Future directions for GNU Smalltalk

Presented below is the set of tasks that I feel need to be performed to make GNU Smalltalk a more fully functional, viable system. They are presented in no particular order. I would very much welcome any volunteers who would like to help with the implementation of one or more of these tasks. Please write to me, Paolo Bonzini, at bonzini@gnu.org if you are interested in adding your efforts to the GNU Smalltalk Project.

Tasks:

Also, following is a brief description of the differences and omissions between GNU Smalltalk and "Blue Book" Smalltalk (Smalltalk-80).


[ Previous:Future | Up:Top ]

Acknowledgements

The tutorial

Thanks to Steve Byrne for writing GNU Smalltalk in the first place. Great thanks to Mark Bush and Bob Roos for their meticulous jobs of proofreading this document, and the generous amounts of input they provided on refinements to the contents and structure. Thanks also to Andrew Berg for his comments on the early chapters of the document.

This document is provided as-is, without warranty, but I will happily accept reports of any errors. If time permits, I will perhaps even release a corrected revision of the document.

I release this document into the public domain, and simply request that you acknowledge me as the original author in any use or derivative work you make of this document.

                         Andy Valencia
                         325 Union Ave #359
                         Campbell, CA 95008
                         jtk@netcom.com
                         November 27, 1992

The program

I would like to publically thank the following people, who have helped out in one way or another with the 1.1.5 release of GNU Smalltalk:

Fritz Nordby, Michael Mellinger, Doug McCallum, Karl Berry, Dave Bodenstab, Brad Diller, Mark Wadsworth, Bill Trost, William Cook, Trip Becket, Alan Knight, Alistair Grant, Michael Richardson, Andrew Gelsey, Kevin Hester, David MacKenzie, Doug Peters, Michael Bushnell, Florin Spanachi, David England, Charles Johnson, David B. Serafini, R James Noble, David Duke, Mark S. Johnson, Gary Campbell, Peter Dobcsany, Kent Williams, Wilson Ho, Karl Kleinpaste, Len Tower, Paul Regenhardt, Joe Pallas, Peter Kropf, Mark Bush, Per Bothner, Kevin Rigotti, Lance Norskog, Pascal Meheut, Richard Goerwitz, Horst Duchene, Olivier Blanc, Jeff Baird.

Other beta testers for version 1.6 are: Pahi Andras, Ulf Dambacher, Mark Elbrecht, Dwight Hughes, Peter William Lount, Christopher Painter-Wakefield, Philipp Tomsich.

I thank specially Alexander Shinn, who helped me by making a binary package for GNU Smalltalk and gathering bug reports. And I also thank the two people who followed me patiently through the revival of GNU Smalltalk, trying out the experimental extra-buggy versions that eventually led to the first beta: David V. Duccini, who helped a lot in the early testing, and Andreas Klimas, who made available to me his Smalltalk knowledge but, above all, his C and Unix expertise (I'm not proud of it, but I'm mainly a Windows guy...).

And of course, last but definitely not the least, Steve Byrne, for his enthusiasm for my efforts, for his feedback in discussing issues related to GNU Smalltalk's implementation, for having put me in contact with all the people asking him about GNU Smalltalk, and for having made available to me the source code for his own improvements to GST 1.1.5.

Table of Contents