GNU Smalltalk User Manual
GNU Smalltalk Documentation
[ Next:Overview
| Previous:Top
| Up:Top
]
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.
- 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.
- 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.
- 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:
- You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
- 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.
- 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.
- 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:
- 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,
- 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,
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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:Installation
| Previous:Copying
| Up:Top
]
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:Using GNU Smalltalk
| Previous:Overview
| Up:Top
]
- Compiling: : How to compile the GNU Smalltalk system.
- More legal stuff: : Legal consequences of including Smalltalk in your
programs.
- Extending: : How to add your own features to GNU Smalltalk.
[ Next:More legal stuff
| Previous:Installation
| Up:Installation
]
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:Extending
| Previous:Compiling
| Up:Installation
]
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
]
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:Features
| Previous:Installation
| Up:Top
]
- Command line: : What you can specify on the command line.
- Startup: : A step-by-step description of the GNU Smalltalk
startup process.
- Syntax: : A description of the input file syntax
- Operation: : A short description of how to interact with
GNU Smalltalk.
- Init file: : How to have GNU Smalltalk load your own method
definitions.
- Test suite: : How to run the test suite system.
[ Next:Startup
| Up:Using GNU Smalltalk
]
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:Syntax
| Previous:Command line
| Up:Using GNU Smalltalk
]
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:Operation
| Previous:Startup
| Up:Using 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:Init file
| Previous:Syntax
| Up:Using 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:Test suite
| Previous:Operation
| Up:Using GNU Smalltalk
]
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
]
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:C and Smalltalk
| Previous:Using GNU Smalltalk
| Up:Top
]
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).
- Save binary file: : Save the virtual machine's image at arbitrary points.
- system: : Invoke arbitrary UNIX programs with system(3) from
within Smalltalk.
- getenv: : Query the value of an environment variable from within
GNU Smalltalk.
- Init Blocks: : You can specify certain blocks of code are send a
value
message on system startup.
- Memory access: : The direct memory accessing classes and methods.
- backtrace: : Produce a backtrace of method invocation.
- executionTrace: : Control tracing of bytecode execution.
- verboseTrace: : Printing Smalltalk stack during execution.
- debug: : Assistance using C debuggers.
- monitor: : Control C profiling during execution of methods.
- gcMessage: : Control generation of GC flip messages.
- quitPrimitive: : Exit from GNU Smalltalk explicitly
- UNIX file-IO: : Methods for reading and writing standard UNIX files.
- Object dumping: : Methods that read and write objects in binary format.
- FileIn: : You can explicitly load Smalltalk files by using the
fileIn:
message.
- Special objects: : Methods to assign particular properties to objects.
- Context unwinding: : A way to protect execution of blocks from exceptions.
- Packages: : An easy way to install Smalltalk code into an image.
[ Next:system
| Previous:Features
| Up:Features
]
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:getenv
| Previous:Save binary file
| Up:Features
]
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:Init Blocks
| Previous:system
| Up:Features
]
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:Memory access
| Previous:getenv
| Up:Features
]
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:backtrace
| Previous:Init Blocks
| Up:Features
]
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:executionTrace
| Previous:Memory access
| Up:Features
]
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:verboseTrace
| Previous:backtrace
| Up:Features
]
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:debug
| Previous:executionTrace
| Up:Features
]
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:monitor
| Previous:verboseTrace
| Up:Features
]
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:gcMessage
| Previous:debug
| Up:Features
]
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:quitPrimitive
| Previous:monitor
| Up:Features
]
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:UNIX file-IO
| Previous:gcMessage
| Up:Features
]
SystemDictionary quitPrimitive
- Invoking this method causes an immediate and unconditional exit from GNU
Smalltalk.
[ Next:Object dumping
| Previous:quitPrimitive
| Up:Features
]
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:FileIn
| Previous:UNIX file-IO
| Up:Features
]
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:Special objects
| Previous:Object dumping
| Up:Features
]
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:Context unwinding
| Previous:FileIn
| Up:Features
]
A few methods in Object support the creation of particular objects.
This include:
- finalizable objects
- weak objects (i.e. objects whose contents are not considered,
during garbage collection, when scanning the heap for live objects).
- 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:Packages
| Previous:Special objects
| Up:Features
]
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.
- ContextPart class>>#unwind
- ContextPart class>>#unwind:
- ContextPart class>>#unwindPoints
- ContextPart>>#mark
- ContextPart>>#unmark
- ContextPart>>#returnTo:
[ Previous:Context unwinding
| Up:Features
]
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:
- Blox, which is needed for Browser and BloxTestSuite, so it is
loaded before them)
- Tokenizer, not specified on the command line, but needed by Parser
- Parser, not specified on the command line, but needed by Compiler
- BloxTestSuite
- Browser
- Compiler (since Blox was already loaded)
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:Compiler
| Previous:Packages
| Up:Packages
]
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:Dynamic loading
| Previous:Blox
| Up:Packages
]
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
]
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:Tutorial
| Previous:Features
| Up:Top
]
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:C data types
| Previous:C and Smalltalk
| Up:C and Smalltalk
]
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:Smalltalk types
| Previous:C callout
| Up:C and Smalltalk
]
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
long
(unsigned too)
short
(unsigned too)
char
(unsigned too) & byte type
float
(and double
)
string
(NUL terminated sequence of char * )
- arrays of any type
- pointers to any type
- other structs containing any fixed size types
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:Smalltalk callin
| Previous:C data types
| Up:C and Smalltalk
]
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
- a pointer to the actual object data
- a bunch of flags, most of which interest the garbage collection process
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:Other C functions
| Previous:Smalltalk types
| Up:C and 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:Object representation
| Previous:Smalltalk callin
| Up:C and Smalltalk
]
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:Incubator
| Previous:Other C functions
| Up:C and Smalltalk
]
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:
- Defining the Smalltalk class
- Defining a C
struct
that maps the representation of the class
- Actually using the C struct
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:Using Smalltalk
| Previous:Object representation
| Up:C and Smalltalk
]
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
]
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:Class reference
| Previous:C and Smalltalk
| Up:Top
]
- 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:Some classes
| Previous:Tutorial
| Up:Tutorial
]
[ Next:Saying hello
| Previous:Getting started
| Up:Getting started
]
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:What happened
| Previous:Starting Smalltalk
| Up:Getting started
]
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:Doing math
| Previous:Saying hello
| Up:Getting started
]
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:Math in Smalltalk
| Previous:What happened
| Up:Getting started
]
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
]
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:The hierarchy
| Previous:Getting started
| Up:Tutorial
]
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:Sets
| Previous:Some classes
| Up:Some classes
]
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:Dictionaries
| Previous:Arrays
| Up:Some classes
]
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:Smalltalk dictionary
| Previous:Sets
| Up:Some classes
]
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:Closing thoughts
| Previous:Dictionaries
| Up:Some classes
]
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
]
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:Creating classes
| Previous:Some classes
| Up:Tutorial
]
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.
- Class Object: : The grandfather of every class
- Animals: : A classic in learning OOP!
- But why: : The bottom line of the class hierarchy
[ Next:Animals
| Previous:The hierarchy
| Up:The hierarchy
]
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:But why
| Previous:Class Object
| Up:The hierarchy
]
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 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:Creating subclasses
| Previous:The hierarchy
| Up:Tutorial
]
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:Documenting the class
| Previous:Creating classes
| Up:Creating classes
]
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:Defining methods
| Previous:A new class
| Up:Creating classes
]
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:Instance methods
| Previous:Documenting the class
| Up:Creating classes
]
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:
Account class
means that we are defining messages which are
to be sent to the Account class itself.
methodsFor: 'instance creation'
is more documentation support; it says that all of the methods
defined will be to support creating objects of type
Account.
- The text starting with
new
and ending
with !!
defined what action to take for the message new
.
When you enter this definition, GNU Smalltalk will simply
give you another prompt, but your method has been compiled in
and is ready for use. GNU Smalltalk is pretty quiet on successful
method definitions-but you'll get plenty of error
messages if there's a problem!
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:A look at our object
| Previous:Defining methods
| Up:Creating classes
]
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:Moving money around
| Previous:Instance methods
| Up:Creating classes
]
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:Next coming
| Previous:A look at our object
| Up:Creating classes
]
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
]
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:Code blocks (I)
| Previous:Creating classes
| Up:Tutorial
]
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:The Checking class
| Previous:Creating subclasses
| Up:Creating subclasses
]
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:Writing checks
| Previous:The Savings class
| Up:Creating subclasses
]
Our second subclass of Account represents a checking
account. We will keep track of two facets:
- What check number we are on
- How many checks we have left in our checkbook
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
]
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:Code blocks (II)
| Previous:Creating subclasses
| Up:Tutorial
]
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:Iteration
| Previous:Code blocks (I)
| Up:Code blocks (I)
]
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)
]
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:Debugging
| Previous:Code blocks (I)
| Up:Tutorial
]
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:Intervals
| Previous:Code blocks (II)
| Up:Code blocks (II)
]
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:Invoking code blocks
| Previous:Integer loops
| Up:Code blocks (II)
]
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)
]
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:More subclassing
| Previous:Code blocks (II)
| Up:Tutorial
]
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:Nested calls
| Previous:Debugging
| Up:Debugging
]
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:Looking at objects
| Previous:Simple errors
| Up:Debugging
]
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
]
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:Streams
| Previous:Debugging
| Up:Tutorial
]
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:Playing with Arrays
| Previous:More subclassing
| Up:More subclassing
]
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:New kinds of Numbers
| Previous:The existing hierarchy
| Up:More subclassing
]
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:Inheritance and Polymorphism
| Previous:Playing with Arrays
| Up:More subclassing
]
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
]
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:Behind the scenes
| Previous:More subclassing
| Up:Tutorial
]
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:Your own stream
| Previous:Streams
| Up:Streams
]
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 stdout
21.
[ Next:Files
| Previous:The output stream
| Up:Streams
]
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:Dynamic Strings
| Previous:Your own stream
| Up:Streams
]
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
]
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:And now
| Previous:Streams
| Up:Tutorial
]
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:Two flavors of equality
| Previous:Behind the scenes
| Up:Behind the scenes
]
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:Performance
| Previous:Inside Arrays
| Up:Behind the scenes
]
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
]
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:The syntax
| Previous:Behind the scenes
| Up:Tutorial
]
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
]
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:Future
| Previous:Tutorial
| Up:Top
]
{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"}
[ ]
- 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:Array-mutating objects
| Up:Array
]
- 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:Array-printing
| Previous:Array-built ins
| Up:Array
]
- multiBecome: anArray
- Transform every object in the receiver in each corresponding object in anArray. anArray and the receiver must have the same size
[ Next:Array-testing
| Previous:Array-mutating objects
| Up:Array
]
- printOn: aStream
- Print a representation for the receiver on aStream
[ Previous:Array-printing
| Up:Array
]
- isArray
- Answer `false'.
[ ]
- 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:ArrayedCollection-basic
| Up:ArrayedCollection
]
- 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:ArrayedCollection-built ins
| Previous:ArrayedCollection class-instance creation
| Up:ArrayedCollection
]
- , 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:ArrayedCollection-copying Collections
| Previous:ArrayedCollection-basic
| Up:ArrayedCollection
]
- size
- Answer the size of the receiver
[ Next:ArrayedCollection-enumerating the elements of a collection
| Previous:ArrayedCollection-built ins
| Up:ArrayedCollection
]
- 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:ArrayedCollection-storing
| Previous:ArrayedCollection-copying Collections
| Up:ArrayedCollection
]
- 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
]
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ ]
- 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:Association-accessing
| Up:Association
]
- key: aKey value: aValue
- Answer a new association with the given key and value
[ Next:Association-printing
| Previous:Association class-basic
| Up:Association
]
- 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:Association-storing
| Previous:Association-accessing
| Up:Association
]
- printOn: aStream
- Put on aStream a representation of the receiver
[ Next:Association-testing
| Previous:Association-printing
| Up:Association
]
- storeOn: aStream
- Put on aStream some Smalltalk code compiling to the receiver
[ Previous:Association-storing
| Up:Association
]
- < 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
[ ]
- 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:Bag-Adding to a collection
| Up:Bag
]
- new
- Answer a new instance of the receiver
[ Next:Bag-enumerating the elements of a collection
| Previous:Bag class-basic
| Up:Bag
]
- 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:Bag-printing
| Previous:Bag-Adding to a collection
| Up:Bag
]
- do: aBlock
- Evaluate the block for all members in the collection.
[ Next:Bag-Removing from a collection
| Previous:Bag-enumerating the elements of a collection
| Up:Bag
]
- printOn: aStream
- Put on aStream a representation of the receiver
[ Next:Bag-storing
| Previous:Bag-printing
| Up:Bag
]
- 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:Bag-testing collections
| Previous:Bag-Removing from a collection
| Up:Bag
]
- storeOn: aStream
- Put on aStream some Smalltalk code compiling to the receiver
[ Previous:Bag-storing
| Up:Bag
]
- = 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
[ ]
- 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:Behavior class-creating lightweight classes
| Up:Behavior
]
- 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:Behavior-accessing class hierarchy
| Previous:Behavior class-C interface
| Up:Behavior
]
- 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:Behavior-accessing instances and variables
| Previous:Behavior class-creating lightweight classes
| Up:Behavior
]
- 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:Behavior-accessing the methodDictionary
| Previous:Behavior-accessing class hierarchy
| Up:Behavior
]
- 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:Behavior-browsing
| Previous:Behavior-accessing instances and variables
| Up:Behavior
]
- >> 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:Behavior-built ins
| Previous:Behavior-accessing the methodDictionary
| Up:Behavior
]
- 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:Behavior-C callout
| Previous:Behavior-browsing
| Up:Behavior
]
- 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:Behavior-compilation (alternative)
| Previous:Behavior-built ins
| Up:Behavior
]
- defineCFunc: cFuncName
- withSelectorArgs: selector
returning: aReturnType
args: argsArray
Too complex to describe it here - Look up the C interface in the manual.
[ Next:Behavior-creating a class hierarchy
| Previous:Behavior-C callout
| Up:Behavior
]
- 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:Behavior-creating method dictionary
| Previous:Behavior-compilation (alternative)
| Up:Behavior
]
- 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:Behavior-enumerating
| Previous:Behavior-creating a class hierarchy
| Up:Behavior
]
- 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:Behavior-evaluating
| Previous:Behavior-creating method dictionary
| Up:Behavior
]
- 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:Behavior-hierarchy browsing
| Previous:Behavior-enumerating
| Up:Behavior
]
- 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:Behavior-support for lightweight classes
| Previous:Behavior-evaluating
| Up:Behavior
]
- 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:Behavior-testing the class hierarchy
| Previous:Behavior-hierarchy browsing
| Up:Behavior
]
- 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:Behavior-testing the form of the instances
| Previous:Behavior-support for lightweight classes
| Up:Behavior
]
- 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:Behavior-testing the method dictionary
| Previous:Behavior-testing the class hierarchy
| Up:Behavior
]
- 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
]
- 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
[ ]
- 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:BlockClosure-basic
| Up:BlockClosure
]
- 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:BlockClosure-built ins
| Previous:BlockClosure-accessing
| Up:BlockClosure
]
- 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:BlockClosure-exception handling
| Previous:BlockClosure-basic
| Up:BlockClosure
]
- 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:BlockClosure-multiple process
| Previous:BlockClosure-built ins
| Up:BlockClosure
]
- 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
]
- 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
[ ]
- 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:BlockContext-printing
| Up:BlockContext
]
- 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
]
- printOn: aStream
- Print a representation for the receiver on aStream
[ ]
- 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:Boolean-basic
| Up:Boolean
]
- 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:Boolean-C hacks
| Previous:Boolean class-testing
| Up:Boolean
]
- & 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:Boolean-overriding
| Previous:Boolean-basic
| Up:Boolean
]
- asCBooleanValue
- This method's functionality should be implemented by subclasses of Boolean
[ Next:Boolean-storing
| Previous:Boolean-C hacks
| Up:Boolean
]
- deepCopy
- Answer the receiver.
- shallowCopy
- Answer the receiver.
[ Previous:Boolean-overriding
| Up:Boolean
]
- storeOn: aStream
- Store on aStream some Smalltalk code which compiles to the receiver
[ ]
- Category: Language-Implementation
-
[ Up:Browser
]
- 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
[ ]
- 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:ByteArray-converting
| Up:ByteArray
]
- 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:ByteArray-copying
| Previous:ByteArray-built ins
| Up:ByteArray
]
- asString
- Answer a String whose character's ASCII codes are the receiver's contents
[ Next:ByteArray-more advanced accessing
| Previous:ByteArray-converting
| Up:ByteArray
]
- deepCopy
- Answer a shallow copy of the receiver
- shallowCopy
- Answer a shallow copy of the receiver
[ Previous:ByteArray-copying
| Up:ByteArray
]
- 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.
[ ]
- 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
]
- 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)
[ ]
- Category: Streams-Collections
- My instances are read/write streams specially crafted for ByteArrays.
They are able to write binary data to them.
[ Up:ByteStream
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CAggregate-accessing
| Up:CAggregate
]
- alignof
- Answer the receiver's instances required aligment
- sizeof
- Answer the receiver's instances size
[ Previous:CAggregate class-accessing
| Up:CAggregate
]
- + 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.
[ ]
- Category: Language-C interface
-
[ Up:CArray
]
- alignof
- Answer the receiver's required aligment
- sizeof
- Answer the receiver's size
[ ]
- Category: Language-C interface
-
[ Next:CArrayCType-accessing
| Up:CArrayCType
]
- 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
]
- 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
[ ]
- Category: Language-C interface
- I return true if a byte is not zero, false otherwise.
[ Up:CBoolean
]
- 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
[ ]
- Category: Language-C interface
- You're a marine.
You adapt - you improvise - you overcome
- Gunnery Sgt. Thomas Highway
Heartbreak Ridge
[ Next:CByte-accessing
| Up:CByte
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CChar-accessing
| Up:CChar
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CDouble-accessing
| Up:CDouble
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CFloat-accessing
| Up:CFloat
]
- 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
]
- 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
[ ]
- 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:CFunctionDescriptor-accessing
| Up:CFunctionDescriptor
]
- 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:CFunctionDescriptor-printing
| Previous:CFunctionDescriptor class-testing
| Up:CFunctionDescriptor
]
- 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
]
- printOn: aStream
- Print a representation of the receiver onto aStream
[ ]
- 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:Character class-constants
| Up:Character
]
- 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:Character class-initializing lookup tables
| Previous:Character class-built ins
| Up:Character
]
- 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:Character class-Instance creation
| Previous:Character class-constants
| Up:Character
]
- 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:Character class-testing
| Previous:Character class-initializing lookup tables
| Up:Character
]
- digitValue: anInteger
- Returns a character that corresponds to anInteger. 0-9 map to $0-$9, 10-35 map to $A-$Z
[ Next:Character-built ins
| Previous:Character class-Instance creation
| Up:Character
]
- 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:Character-Coercion methods
| Previous:Character class-testing
| Up:Character
]
- = 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:Character-comparing
| Previous:Character-built ins
| Up:Character
]
- 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:Character-converting
| Previous:Character-Coercion methods
| Up:Character
]
- < 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:Character-printing
| Previous:Character-comparing
| Up:Character
]
- 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:Character-storing
| Previous:Character-converting
| Up:Character
]
- printOn: aStream
- Store a representation of the receiver on aStream
[ Next:Character-testing
| Previous:Character-printing
| Up:Character
]
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ Next:Character-testing functionality
| Previous:Character-storing
| Up:Character
]
- 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
]
- isCharacter
- Answer True. We're definitely characters
[ ]
- Category: Language-C interface
-
[ Next:CInt-accessing
| Up:CInt
]
- 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
]
- 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
[ ]
- Category: Language-Implementation
- I am THE class object. My instances are the classes of the system
[ Next:Class-filing
| Up:Class
]
- 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:Class-instance creation
| Previous:Class-accessing instances and variables
| Up:Class
]
- 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:Class-instance creation - alternative
| Previous:Class-filing
| Up: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 (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:Class-printing
| Previous:Class-instance creation
| Up:Class
]
- 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:Class-testing
| Previous:Class-instance creation - alternative
| Up:Class
]
- printOn: aStream
- Print a representation of the receiver on aStream
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ Next:Class-testing functionality
| Previous:Class-printing
| Up:Class
]
- = aClass
- Returns true if the two class objects are to be considered equal.
[ Previous:Class-testing
| Up:Class
]
- asClass
- Answer the receiver.
- isClass
- Answer `true'.
[ ]
- 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:ClassDescription-accessing instances and variables
| Up:ClassDescription
]
- 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:ClassDescription-compiling
| Previous:ClassDescription-accessing class description
| Up:ClassDescription
]
- 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:ClassDescription-copying
| Previous:ClassDescription-accessing instances and variables
| Up:ClassDescription
]
- 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:ClassDescription-filing
| Previous:ClassDescription-compiling
| Up:ClassDescription
]
- 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:ClassDescription-organization of messages and classes
| Previous:ClassDescription-copying
| Up:ClassDescription
]
- 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:ClassDescription-printing
| Previous:ClassDescription-filing
| Up:ClassDescription
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CLong-accessing
| Up:CLong
]
- 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
]
- 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
[ ]
- 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:CObject class-instance creation
| Up:CObject
]
- 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:CObject-accessing
| Previous:CObject class-conversion
| Up:CObject
]
- 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:CObject-C data access
| Previous:CObject class-instance creation
| Up:CObject
]
- 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:CObject-conversion
| Previous:CObject-accessing
| Up:CObject
]
- 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:CObject-finalization
| Previous:CObject-C data access
| Up:CObject
]
- 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
]
- 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.
[ ]
- 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:Collection-Adding to a collection
| Up:Collection
]
- 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:Collection-converting
| Previous:Collection class-instance creation
| Up:Collection
]
- add: newObject
- Add newObject to the receiver, answer it
- addAll: aCollection
- Adds all the elements of 'aCollection' to the receiver, answer aCollection
[ Next:Collection-copying Collections
| Previous:Collection-Adding to a collection
| Up:Collection
]
- 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:Collection-enumerating the elements of a collection
| Previous:Collection-converting
| Up:Collection
]
- 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:Collection-printing
| Previous:Collection-copying Collections
| Up: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:Collection-Removing from a collection
| Previous:Collection-enumerating the elements of a collection
| Up:Collection
]
- 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:Collection-storing
| Previous:Collection-printing
| Up: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:Collection-testing collections
| Previous:Collection-Removing from a collection
| Up:Collection
]
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ Previous:Collection-storing
| Up:Collection
]
- 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
[ ]
- 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:CompiledMethod class-lean images
| Up:CompiledMethod
]
- 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:CompiledMethod-accessing
| Previous:CompiledMethod class-instance creation
| Up:CompiledMethod
]
- stripSourceCode
- Remove all the references to method source code from the system
[ Next:CompiledMethod-basic
| Previous:CompiledMethod class-lean images
| Up:CompiledMethod
]
- 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:CompiledMethod-copying
| Previous:CompiledMethod-accessing
| Up:CompiledMethod
]
- = 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:CompiledMethod-debugging
| Previous:CompiledMethod-basic
| Up:CompiledMethod
]
- 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:CompiledMethod-printing
| Previous:CompiledMethod-copying
| Up:CompiledMethod
]
- 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:CompiledMethod-testing accesses
| Previous:CompiledMethod-debugging
| Up:CompiledMethod
]
- 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
]
- 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
[ ]
- 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:ContextPart-accessing
| Up:ContextPart
]
- 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:ContextPart-built ins
| Previous:ContextPart class-exception handling
| Up:ContextPart
]
- 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:ContextPart-exception handling
| Previous:ContextPart-accessing
| Up:ContextPart
]
- blockCopy: numArgs temporaries: numTemps
- Generate a BlockClosure starting execution two bytecodes after the end of the 'send special message #blockCopy:' bytecode
[ Next:ContextPart-printing
| Previous:ContextPart-built ins
| Up:ContextPart
]
- 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:ContextPart-processes
| Previous:ContextPart-exception handling
| Up:ContextPart
]
- 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
]
- nowHasBlock
- Private - Tell the VM that the receiver has references in other objects
[ ]
- Category: Language-C interface
-
[ Up:CPtr
]
- alignof
- Answer the receiver's required aligment
- sizeof
- Answer the receiver's size
[ ]
- Category: Language-C interface
-
[ Next:CPtrCType-accessing
| Up:CPtrCType
]
- elementType: aCType
- Answer a new instance of CPtrCType that maps pointers to the given CType
[ Previous:CPtrCType class-instance creation
| Up:CPtrCType
]
- elementType
- Answer the type of the elements in the receiver's instances
[ ]
- Category: Language-C interface
-
[ Next:CScalar-accessing
| Up:CScalar
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CScalarCType-storing
| Up:CScalarCType
]
- 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
]
- storeOn: aStream
- Store Smalltalk code that compiles to the receiver
[ ]
- Category: Language-C interface
-
[ Next:CShort-accessing
| Up:CShort
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CSmalltalk-accessing
| Up:CSmalltalk
]
- 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
]
- 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
[ ]
- 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:CString-accessing
| Up:CString
]
- 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:CString-pointer like behavior
| Previous:CString class-getting info
| Up:CString
]
- 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
]
- + 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!
[ ]
- Category: Language-C interface
-
[ Next:CStruct class-subclass creation
| Up:CStruct
]
- 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:CStruct-instance creation
| Previous:CStruct class-instance creation
| Up:CStruct
]
- 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
]
- inspect
- Inspect the contents of the receiver
- inspectSelectorList
- Answer a list of selectors whose return values should be inspected by #inspect.
[ ]
- 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:CType-accessing
| Up:CType
]
- cObjectType: aCObjectSubclass
- Create a new CType for the given subclass of CObject
[ Next:CType-C instance creation
| Previous:CType class-C instance creation
| Up:CType
]
- 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:CType-storing
| Previous:CType-accessing
| Up:CType
]
- 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
]
- storeOn: aStream
- Store Smalltalk code that compiles to the receiver
[ ]
- Category: Language-C interface
-
[ Next:CUChar-accessing
| Up:CUChar
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CUInt-accessing
| Up:CUInt
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CULong-accessing
| Up:CULong
]
- 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
]
- 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
[ ]
- Category: Language-C interface
-
[ Next:CUShort-accessing
| Up:CUShort
]
- 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
]
- 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
[ ]
- 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:Date class-instance creation
| Up:Date
]
- 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:Date-basic
| Previous:Date class-basic
| Up:Date
]
- 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:Date-date computations
| Previous:Date class-instance creation
| Up:Date
]
- 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:Date-printing
| Previous:Date-basic
| Up:Date
]
- 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:Date-storing
| Previous:Date-date computations
| Up:Date
]
- printOn: aStream
- Print a representation for the receiver on aStream
[ Next:Date-testing
| Previous:Date-printing
| Up:Date
]
- storeOn: aStream
- Store on aStream Smalltalk code compiling to the receiver
[ Previous:Date-storing
| Up:Date
]
- < 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
[ ]
- 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:Delay class-initialization
| Up:Delay
]
- millisecondClockValue
- Private - Answer the number of milliseconds since midnight
[ Next:Delay class-instance creation
| Previous:Delay class-general inquiries
| Up:Delay
]
- initialize
- Private - Initialize the receiver and the associated process
[ Next:Delay-accessing
| Previous:Delay class-initialization
| Up:Delay
]
- 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:Delay-comparing
| Previous:Delay class-instance creation
| Up:Delay
]
- resumptionTime
- Answer the time when a process waiting on a Delay will resume
[ Next:Delay-process delay
| Previous:Delay-accessing
| Up:Delay
]
- = aDelay
- Answer whether the receiver and aDelay denote the same delay
- hash
- Answer an hash value for the receiver
[ Previous:Delay-comparing
| Up:Delay
]
- wait
- Wait until the amount of time represented by the instance of Delay elapses
[ ]
- 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
]
- 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.
[ ]
- 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:Dictionary-accessing
| Up:Dictionary
]
- new
- Create a new dictionary with a default size
[ Next:Dictionary-awful ST-80 compatibility hacks
| Previous:Dictionary class-instance creation
| Up:Dictionary
]
- 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:Dictionary-dictionary enumerating
| Previous:Dictionary-accessing
| Up:Dictionary
]
- 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:Dictionary-dictionary removing
| Previous:Dictionary-awful ST-80 compatibility hacks
| Up:Dictionary
]
- 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:Dictionary-dictionary testing
| Previous:Dictionary-dictionary enumerating
| Up:Dictionary
]
- 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:Dictionary-printing
| Previous:Dictionary-dictionary removing
| Up:Dictionary
]
- 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:Dictionary-storing
| Previous:Dictionary-dictionary testing
| Up:Dictionary
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ Next:Dictionary-testing
| Previous:Dictionary-printing
| Up:Dictionary
]
- storeOn: aStream
- Print Smalltalk code compiling to the receiver on aStream
[ Previous:Dictionary-storing
| Up:Dictionary
]
- = aDictionary
- Answer whether the receiver and aDictionary are equal
- hash
- Answer the hash value for the receiver
[ ]
- Category: Language-Implementation
- I represent a message send: I contain the receiver, selector and arguments
for a message.
[ Next:DirectedMessage-accessing
| Up:DirectedMessage
]
- 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:DirectedMessage-basic
| Previous:DirectedMessage class-creating instances
| Up:DirectedMessage
]
- receiver
- Answer the receiver
- receiver: anObject
- Change the receiver
[ Previous:DirectedMessage-accessing
| Up:DirectedMessage
]
- printOn: aStream
- Print a representation of the receiver on aStream
- send
- Send the message
[ ]
- Category: Streams-Files
-
[ Next:Directory class-file operations
| Up:Directory
]
- 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:Directory class-reading system defaults
| Previous:Directory class-C functions
| Up:Directory
]
- working: dirName
- Change the current working directory to dirName.
[ Next:Directory-accessing
| Previous:Directory class-file operations
| Up:Directory
]
- 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:Directory-C functions
| Previous:Directory class-reading system defaults
| Up:Directory
]
- 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
]
- 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!
[ ]
- 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:DLD class-Dynamic Linking
| Up:DLD
]
- 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
]
- 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.
[ ]
- 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:DumperProxy-reconstructing
| Up:DumperProxy
]
- 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
]
- object
- Reconstruct the object stored in the proxy and answer it
[ ]
- 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:Exception-accessing
| Up:Exception
]
- new
- Create a new exception whose parent is ExAll
[ Next:Exception-basic
| Previous:Exception class-instance creation
| Up:Exception
]
- 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:Exception-enumerating
| Previous:Exception-accessing
| Up:Exception
]
- copy
- Answer a copy of the receiver
[ Next:Exception-exception handling
| Previous:Exception-basic
| Up:Exception
]
- 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:Exception-instance creation
| Previous:Exception-enumerating
| Up:Exception
]
- 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
]
- newChild
- Answer a child exception of the receiver. Its properties are set to those of the receiver
[ ]
- 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:ExceptionCollection-enumerating
| Up:ExceptionCollection
]
- new
- Private - Answer a new, empty ExceptionCollection
[ Previous:ExceptionCollection class-instance creation
| Up:ExceptionCollection
]
- allExceptionsDo: aBlock
- Private - Evaluate aBlock for every exception in the receiver. Answer the receiver
- handles: exception
- Answer whether the receiver handles `exception'.
[ ]
- 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:ExceptionHandler-accessing
| Up:ExceptionHandler
]
- 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
]
- 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.
[ ]
- Category: Language-Data types
- I always tell lies.
I have a single instance in the system, which represents the value false.
[ Next:False-C hacks
| Up:False
]
- & 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:False-printing
| Previous:False-basic
| Up:False
]
- asCBooleanValue
- Answer `0'.
[ Previous:False-C hacks
| Up:False
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ ]
- Category: Streams-Files
-
[ Next:File class-file operations
| Up:File
]
- 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:File class-initialization
| Previous:File class-C functions
| Up:File
]
- 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:File class-instance creation
| Previous:File class-file operations
| Up:File
]
- initialize
- Initialize the receiver's class variables
[ Next:File class-reading system defaults
| Previous:File class-initialization
| Up:File
]
- 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:File class-testing
| Previous:File class-instance creation
| Up:File
]
- image
- Answer the full path to the image being used.
[ Next:File-accessing
| Previous:File class-reading system defaults
| Up:File
]
- exists: fileName
- Answer whether a file with the given name exists
[ Next:File-C functions
| Previous:File class-testing
| Up:File
]
- 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:File-file operations
| Previous:File-accessing
| Up:File
]
- 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:File-testing
| Previous:File-C functions
| Up:File
]
- 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
]
- 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.
[ ]
- 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:FileSegment-basic
| Up:FileSegment
]
- 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:FileSegment-equality
| Previous:FileSegment class-basic
| Up:FileSegment
]
- 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
]
- = aFileSegment
- Answer whether the receiver and aFileSegment are equal.
- hash
- Answer an hash value for the receiver.
[ ]
- 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:FileStream class-file-in
| Up:FileStream
]
- 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:FileStream class-initialization
| Previous:FileStream class-basic
| Up:FileStream
]
- 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:FileStream-accessing
| Previous:FileStream class-file-in
| Up:FileStream
]
- initialize
- Initialize the receiver's class variables
[ Next:FileStream-basic
| Previous:FileStream class-initialization
| Up:FileStream
]
- isPipe
- Return whether the file is a pipe or an actual disk file
- name
- Return the name of the file
[ Next:FileStream-built ins
| Previous:FileStream-accessing
| Up:FileStream
]
- 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:FileStream-class type methods
| Previous:FileStream-basic
| Up:FileStream
]
- 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:FileStream-overriding inherited methods
| Previous:FileStream-built ins
| Up:FileStream
]
- isBinary
- We answer characters, so answer false
- isText
- We answer characters, so answer true
- species
- Answer `String'.
[ Next:FileStream-printing
| Previous:FileStream-class type methods
| Up:FileStream
]
- 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:FileStream-testing
| Previous:FileStream-overriding inherited methods
| Up:FileStream
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ Previous:FileStream-printing
| Up:FileStream
]
- atEnd
- Answer whether data has come to an end
[ ]
- 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:Float class-byte-order dependancies
| Up:Float
]
- 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:Float class-converting
| Previous:Float class-basic
| Up:Float
]
- exponentByte
- Not commented.
- leastSignificantMantissaByte
- Not commented.
[ Next:Float-arithmetic
| Previous:Float class-byte-order dependancies
| Up:Float
]
- coerce: aNumber
- Answer aNumber converted to a Float
[ Next:Float-built ins
| Previous:Float class-converting
| Up:Float
]
- // 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:Float-coercing
| Previous:Float-arithmetic
| Up:Float
]
- * 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:Float-printing
| Previous:Float-built ins
| Up:Float
]
- 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:Float-storing
| Previous:Float-coercing
| Up:Float
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ Next:Float-testing
| Previous:Float-printing
| Up:Float
]
- storeOn: aStream
- Print a representation of the receiver on aStream
[ Next:Float-testing functionality
| Previous:Float-storing
| Up:Float
]
- 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
]
- isFloat
- Answer `true'.
[ ]
- 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:Fraction class-instance creation
| Up:Fraction
]
- coerce: aNumber
- Answer aNumber converted to a Fraction
[ Next:Fraction-accessing
| Previous:Fraction class-converting
| Up:Fraction
]
- initialize
- Initialize the receiver's class variables
- numerator: nInteger denominator: dInteger
- Answer a new instance of fraction (nInteger/dInteger)
[ Next:Fraction-arithmetic
| Previous:Fraction class-instance creation
| Up:Fraction
]
- denominator
- Answer the receiver's denominator
- numerator
- Answer the receiver's numerator
[ Next:Fraction-coercing
| Previous:Fraction-accessing
| Up:Fraction
]
- * 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:Fraction-comparing
| Previous:Fraction-arithmetic
| Up:Fraction
]
- 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:Fraction-converting
| Previous:Fraction-coercing
| Up:Fraction
]
- < 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:Fraction-optimized cases
| Previous:Fraction-comparing
| Up:Fraction
]
- asFloat
- Answer the receiver converted to a Float
- asFraction
- Answer the receiver converted to a Fraction
[ Next:Fraction-printing
| Previous:Fraction-converting
| Up:Fraction
]
- 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:Fraction-testing
| Previous:Fraction-optimized cases
| Up:Fraction
]
- 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
]
- isRational
- Answer whether the receiver is rational - true
[ ]
- 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:IdentityDictionary-accessing
| Up:IdentityDictionary
]
- new
- Create a new dictionary with a default size
- new: anInteger
- Create a new dictionary with the given size
[ Next:IdentityDictionary-dictionary enumerating
| Previous:IdentityDictionary class-instance creation
| Up:IdentityDictionary
]
- 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:IdentityDictionary-dictionary removing
| Previous:IdentityDictionary-accessing
| Up:IdentityDictionary
]
- 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:IdentityDictionary-rehashing
| Previous:IdentityDictionary-dictionary enumerating
| Up:IdentityDictionary
]
- removeKey: key ifAbsent: aBlock
- Remove the passed key from the dictionary, answer the result of evaluating aBlock if it is not found
[ Next:IdentityDictionary-storing
| Previous:IdentityDictionary-dictionary removing
| Up:IdentityDictionary
]
- rehash
- Rehash the receiver
[ Previous:IdentityDictionary-rehashing
| Up:IdentityDictionary
]
- storeOn: aStream
- Print Smalltalk code compiling to the receiver on aStream
[ ]
- Category: Collections-Unordered
- I am the typical set object; I can store any objects uniquely. I
use the == operator to determine duplication of objects.
[ ]
- 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:Integer class-getting limits
| Up:Integer
]
- coerce: aNumber
- Answer aNumber converted to a kind of Integer
[ Next:Integer class-testing
| Previous:Integer class-converting
| Up:Integer
]
- 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:Integer-accessing
| Previous:Integer class-getting limits
| Up:Integer
]
- isIdentity
- Answer whether x = y implies x == y for instances of the receiver
[ Next:Integer-bit operators
| Previous:Integer class-testing
| Up:Integer
]
- denominator
- Answer `1'.
- numerator
- Answer the receiver.
[ Next:Integer-built ins
| Previous:Integer-accessing
| Up:Integer
]
- 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:Integer-Coercion methods (heh heh heh)
| Previous:Integer-bit operators
| Up:Integer
]
- * 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:Integer-converting
| Previous:Integer-built ins
| Up:Integer
]
- 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:Integer-extension
| Previous:Integer-Coercion methods (heh heh heh)
| Up:Integer
]
- asFraction
- Return the receiver converted to a fraction
[ Next:Integer-Math methods
| Previous:Integer-converting
| Up:Integer
]
- alignTo: anInteger
- Answer the receiver, truncated to the first higher or equal multiple of anInteger (which must be a power of two)
[ Next:Integer-Misc math operators
| Previous:Integer-extension
| Up:Integer
]
- 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:Integer-Other iterators
| Previous:Integer-Math methods
| Up:Integer
]
- hash
- Answer an hash value for the receiver
[ Next:Integer-printing
| Previous:Integer-Misc math operators
| Up:Integer
]
- 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:Integer-storing
| Previous:Integer-Other iterators
| Up:Integer
]
- 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:Integer-testing functionality
| Previous:Integer-printing
| Up:Integer
]
- storeOn: aStream
- Print on aStream the base 10 representation of the receiver
[ Previous:Integer-storing
| Up:Integer
]
- isInteger
- Answer `true'.
- isRational
- Answer whether the receiver is rational - true
- isSmallInteger
- Answer `true'.
[ ]
- 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:Interval-basic
| Up:Interval
]
- 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:Interval-printing
| Previous:Interval class-instance creation
| Up:Interval
]
- 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:Interval-storing
| Previous:Interval-basic
| Up:Interval
]
- printOn: aStream
- Print a representation for the receiver on aStream
[ Next:Interval-testing
| Previous:Interval-printing
| Up:Interval
]
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ Previous:Interval-storing
| Up:Interval
]
- = anInterval
- Answer whether anInterval is the same interval as the receiver
- hash
- Answer an hash value for the receiver
[ ]
- 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:LargeInteger-arithmetic
| Up:LargeInteger
]
- isIdentity
- Answer whether x = y implies x == y for instances of the receiver
[ Next:LargeInteger-bit operations
| Previous:LargeInteger class-testing
| Up:LargeInteger
]
- * 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:LargeInteger-built-ins
| Previous:LargeInteger-arithmetic
| Up:LargeInteger
]
- 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:LargeInteger-coercion
| Previous:LargeInteger-bit operations
| Up:LargeInteger
]
- 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:LargeInteger-disabled
| Previous:LargeInteger-built-ins
| Up:LargeInteger
]
- 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:LargeInteger-primitive operations
| Previous:LargeInteger-coercion
| Up:LargeInteger
]
- asObject
- This method always fails. The number of OOPs is far less than the minimum number represented with a LargeInteger.
- asObjectNoFail
- Answer `nil'.
[ Next:LargeInteger-testing
| Previous:LargeInteger-disabled
| Up:LargeInteger
]
- 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:LargeInteger-testing functionality
| Previous:LargeInteger-primitive operations
| Up:LargeInteger
]
- < 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
]
- isSmallInteger
- Answer `false'.
[ ]
- 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:LargeNegativeInteger-converting
| Up:LargeNegativeInteger
]
- + 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:LargeNegativeInteger-numeric testing
| Previous:LargeNegativeInteger-arithmetic
| Up:LargeNegativeInteger
]
- asFloat
- Answer the receiver converted to a Float
[ Previous:LargeNegativeInteger-converting
| Up:LargeNegativeInteger
]
- 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
[ ]
- 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:LargePositiveInteger-converting
| Up:LargePositiveInteger
]
- + 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:LargePositiveInteger-helper byte-level methods
| Previous:LargePositiveInteger-arithmetic
| Up:LargePositiveInteger
]
- 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:LargePositiveInteger-numeric testing
| Previous:LargePositiveInteger-converting
| Up:LargePositiveInteger
]
- 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:LargePositiveInteger-primitive operations
| Previous:LargePositiveInteger-helper byte-level methods
| Up:LargePositiveInteger
]
- 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
]
- 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)
[ ]
- 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:LargeZeroInteger-arithmetic
| Up:LargeZeroInteger
]
- at: anIndex
- Answer `0'.
- hash
- Answer `0'.
- size
- Answer `0'.
[ Next:LargeZeroInteger-numeric testing
| Previous:LargeZeroInteger-accessing
| Up:LargeZeroInteger
]
- * 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:LargeZeroInteger-printing
| Previous:LargeZeroInteger-arithmetic
| Up:LargeZeroInteger
]
- sign
- Answer the receiver's sign
- strictlyPositive
- Answer whether the receiver is > 0
[ Previous:LargeZeroInteger-numeric testing
| Up:LargeZeroInteger
]
- reverseStringBase: radix on: str
- Return in a string the base radix representation of the receiver in reverse order
[ ]
- 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:Link-basic
| Up:Link
]
- nextLink: aLink
- Create an instance with the given next link
[ Previous:Link class-instance creation
| Up:Link
]
- nextLink
- Answer the next item in the list
- nextLink: aLink
- Set the next item in the list
[ ]
- 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:LinkedList-adding
| Up:LinkedList
]
- 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:LinkedList-enumerating
| Previous:LinkedList-accessing
| Up:LinkedList
]
- 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:LinkedList-testing
| Previous:LinkedList-adding
| Up:LinkedList
]
- do: aBlock
- Enumerate each object in the list, passing it to aBlock
[ Previous:LinkedList-enumerating
| Up:LinkedList
]
- isEmpty
- Returns true if the list contains no members
[ ]
- 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:Magnitude-misc methods
| Up:Magnitude
]
- < 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
]
- 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
[ ]
- 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:MappedCollection-basic
| Up:MappedCollection
]
- 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
]
- 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
[ ]
- 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:Memory class-basic
| Up:Memory
]
- 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
]
- 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
[ ]
- 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:Message-accessing
| Up:Message
]
- selector: aSymbol arguments: anArray
- Create a new Message with the given selector and arguments
[ Next:Message-basic
| Previous:Message class-creating instances
| Up:Message
]
- 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
]
- printOn: aStream
- Print a representation of the receiver on aStream
- reinvokeFor: aReceiver
- Resend to aReceiver - present for compatibility
- sendTo: aReceiver
- Resend to aReceiver
[ ]
- 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:Metaclass-accessing
| Up:Metaclass
]
- subclassOf: superMeta
- Answer a new metaclass representing a subclass of superMeta
[ Next:Metaclass-basic
| Previous:Metaclass class-instance creation
| Up:Metaclass
]
- 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:Metaclass-delegation
| Previous:Metaclass-accessing
| Up:Metaclass
]
- 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:Metaclass-filing
| Previous:Metaclass-basic
| Up:Metaclass
]
- 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:Metaclass-printing
| Previous:Metaclass-delegation
| Up:Metaclass
]
- fileOutOn: aFileStream
- File out complete class description: class definition, class and instance methods
[ Next:Metaclass-testing functionality
| Previous:Metaclass-filing
| Up:Metaclass
]
- 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
]
- asClass
- Answer `instanceClass'.
- isMetaclass
- Answer `true'.
[ ]
- 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:MethodContext-printing
| Up:MethodContext
]
- 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
]
- printOn: aStream
- Print a representation for the receiver on aStream
[ ]
- 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:MethodInfo-equality
| Up:MethodInfo
]
- 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
]
- = aMethodInfo
- Compare the receiver and aMethodInfo, answer whether they're equal
- hash
- Answer an hash value for the receiver
[ ]
- 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:NullProxy-accessing
| Up:NullProxy
]
- 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
]
- 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.
[ ]
- 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:NullValueHolder-accessing
| Up:NullValueHolder
]
- new
- Not used - use `ValueHolder null' instead
[ Previous:NullValueHolder class-creating instances
| Up:NullValueHolder
]
- value
- Retrive the value of the receiver. Always answer nil
- value: anObject
- Set the value of the receiver. Do nothing, discard the value
[ ]
- 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:Number class-testing
| Up:Number
]
- 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:Number-arithmetic
| Previous:Number class-converting
| Up:Number
]
- isImmediate
- Answer whether, if x is an instance of the receiver, x copy == x
[ Next:Number-converting
| Previous:Number class-testing
| Up:Number
]
- * 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:Number-copying
| Previous:Number-arithmetic
| Up:Number
]
- 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:Number-Intervals & iterators
| Previous:Number-converting
| Up:Number
]
- deepCopy
- Return the receiver - it's an immediate (immutable) object
- shallowCopy
- Return the receiver - it's an immediate (immutable) object
[ Next:Number-misc math
| Previous:Number-copying
| Up:Number
]
- 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:Number-point creation
| Previous:Number-Intervals & iterators
| Up:Number
]
- 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:Number-testing
| Previous:Number-misc math
| Up:Number
]
- @ y
- Answer a new point whose x is the receiver and whose y is y
- asPoint
- Answer a new point, self @ self
[ Next:Number-truncation and round off
| Previous:Number-point creation
| Up:Number
]
- 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
]
- 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
[ ]
- Category: Language-Implementation
- I am the root of the Smalltalk class system.
All classes in the system are subclasses of me.
[ Next:Object-change and update
| Up:Object
]
- = 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:Object-class type methods
| Previous:Object-built ins
| Up:Object
]
- 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:Object-copying
| Previous:Object-change and update
| Up:Object
]
- 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:Object-debugging
| Previous:Object-class type methods
| Up:Object
]
- 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:Object-dependents access
| Previous:Object-copying
| Up:Object
]
- 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:Object-finalization
| Previous:Object-debugging
| Up:Object
]
- 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:Object-printing
| Previous:Object-dependents access
| Up:Object
]
- finalize
- Do nothing by default
[ Next:Object-Relational operators
| Previous:Object-finalization
| Up:Object
]
- 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:Object-storing
| Previous:Object-printing
| Up:Object
]
- ~= anObject
- Answer whether the receiver and anObject are not equal
- ~~ anObject
- Answer whether the receiver and anObject are not the same object
[ Next:Object-subclassed
| Previous:Object-Relational operators
| Up:Object
]
- 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:Object-syntax shortcuts
| Previous:Object-storing
| Up:Object
]
- TexinfoClassPublisher
- Not commented
[ Next:Object-testing functionality
| Previous:Object-subclassed
| Up:Object
]
- -> anObject
- Creates a new instance of Association with the receiver being the key and the argument becoming the value
[ Next:Object-VM callbacks
| Previous:Object-syntax shortcuts
| Up:Object
]
- 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
]
- 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
[ ]
- 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:ObjectDumper class-instance creation
| Up:ObjectDumper
]
- 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:ObjectDumper class-shortcuts
| Previous:ObjectDumper class-establishing proxy classes
| Up:ObjectDumper
]
- new
- This method should not be called for instances of this class.
- on: aFileStream
- Answer an ObjectDumper working on aFileStream.
[ Next:ObjectDumper class-testing
| Previous:ObjectDumper class-instance creation
| Up:ObjectDumper
]
- dump: anObject to: aFileStream
- Dump anObject to aFileStream. Answer anObject
- loadFrom: aFileStream
- Load an object from aFileStream and answer it
[ Next:ObjectDumper-accessing
| Previous:ObjectDumper class-shortcuts
| Up:ObjectDumper
]
- example
- This is a real torture test: it outputs recursive objects, identical objects multiple times, classes, metaclasses, integers and characters!
[ Next:ObjectDumper-loading/dumping objects
| Previous:ObjectDumper class-testing
| Up:ObjectDumper
]
- stream
- Answer `stream'.
[ Next:ObjectDumper-stream interface
| Previous:ObjectDumper-accessing
| Up:ObjectDumper
]
- 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
]
- 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
[ ]
- 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:OrderedCollection-accessing
| Up:OrderedCollection
]
- new
- Answer an OrderedCollection of default size
- new: anInteger
- Answer an OrderedCollection of size anInteger
[ Next:OrderedCollection-adding
| Previous:OrderedCollection class-instance creation
| Up:OrderedCollection
]
- 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:OrderedCollection-removing
| Previous:OrderedCollection-accessing
| Up:OrderedCollection
]
- 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
]
- 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
[ ]
- 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:PackageLoader class-loading
| Up:PackageLoader
]
- 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:PackageLoader class-testing
| Previous:PackageLoader class-accessing
| Up:PackageLoader
]
- 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
]
- canLoad: package
- Answer whether all the needed C call-outs are registered within GNU Smalltalk
[ ]
- 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:PluggableAdaptor-accessing
| Up:PluggableAdaptor
]
- 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
]
- value
- Get the value of the receiver.
- value: anObject
- Set the value of the receiver.
[ ]
- 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:Point-accessing
| Up:Point
]
- new
- Create a new point with both coordinates set to 0
- x: xInteger y: yInteger
- Create a new point with the given coordinates
[ Next:Point-arithmetic
| Previous:Point class-instance creation
| Up:Point
]
- 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:Point-comparing
| Previous:Point-accessing
| Up:Point
]
- * 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:Point-converting
| Previous:Point-arithmetic
| Up:Point
]
- < 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:Point-point functions
| Previous:Point-comparing
| Up:Point
]
- 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:Point-printing
| Previous:Point-converting
| Up:Point
]
- 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:Point-storing
| Previous:Point-point functions
| Up:Point
]
- printOn: aStream
- Print a representation for the receiver on aStream
[ Next:Point-truncation and round off
| Previous:Point-printing
| Up:Point
]
- storeOn: aStream
- Print Smalltalk code compiling to the receiver on aStream
[ Previous:Point-storing
| Up:Point
]
- 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)
[ ]
- 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:PositionableStream-accessing-reading
| Up:PositionableStream
]
- 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:PositionableStream-class type methods
| Previous:PositionableStream class-instance creation
| Up:PositionableStream
]
- 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:PositionableStream-positioning
| Previous:PositionableStream-accessing-reading
| Up:PositionableStream
]
- species
- The collections returned by #upTo: etc. are the same kind as those returned by the collection with methods such as #select:
[ Next:PositionableStream-testing
| Previous:PositionableStream-class type methods
| Up:PositionableStream
]
- 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:PositionableStream-truncating
| Previous:PositionableStream-positioning
| Up:PositionableStream
]
- 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
]
- truncate
- Truncate the receiver to the current position - only valid for writing streams
[ ]
- 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:Process-accessing
| Up:Process
]
- on: aBlockContext at: aPriority
- Private - Create a process running aBlockContext at the given priority
[ Next:Process-basic
| Previous:Process class-basic
| Up:Process
]
- 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:Process-builtins
| Previous:Process-accessing
| Up:Process
]
- 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:Process-printing
| Previous:Process-basic
| Up:Process
]
- resume
- Resume the receiver's execution
- yield
- Yield control from the receiver to other processes
[ Previous:Process-builtins
| Up:Process
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ ]
- Category: Language-Processes
- I provide methods that control the execution of processes.
[ Next:ProcessorScheduler-priorities
| Up:ProcessorScheduler
]
- 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:ProcessorScheduler-timed invocation
| Previous:ProcessorScheduler-basic
| Up:ProcessorScheduler
]
- 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
]
- 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
[ ]
- Category: Streams
- My instances are generator streams that produce random numbers, which are
floating point values between 0 and 1.
[ Next:Random-basic
| Up:Random
]
- 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:Random-testing
| Previous:Random class-instance creation
| Up:Random
]
- 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
]
- 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
[ ]
- 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:ReadStream-accessing-reading
| Up:ReadStream
]
- on: aCollection
- Answer a new stream working on aCollection from its start.
[ Previous:ReadStream class-instance creation
| Up:ReadStream
]
- reverseContents
- May be faster than generic stream reverseContents.
- size
- Answer the receiver's size.
[ ]
- 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:ReadWriteStream-positioning
| Up:ReadWriteStream
]
- 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
]
- position: anInteger
- Unlike WriteStreams, ReadWriteStreams don't truncate the stream
- skip: anInteger
- Unlike WriteStreams, ReadWriteStreams don't truncate the stream
[ ]
- 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:Rectangle-accessing
| Up:Rectangle
]
- 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:Rectangle-printing
| Previous:Rectangle class-instance creation
| Up:Rectangle
]
- 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:Rectangle-rectangle functions
| Previous:Rectangle-accessing
| Up:Rectangle
]
- printOn: aStream
- Print a representation of the receiver on aStream
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ Next:Rectangle-testing
| Previous:Rectangle-printing
| Up:Rectangle
]
- 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:Rectangle-transforming
| Previous:Rectangle-rectangle functions
| Up:Rectangle
]
- = 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:Rectangle-truncation and round off
| Previous:Rectangle-testing
| Up:Rectangle
]
- 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
]
- rounded
- Answer a copy of the receiver with the coordinates rounded to the nearest integers
[ ]
- 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:RunArray-accessing
| Up:RunArray
]
- new
- Answer an empty RunArray
- new: aSize
- Answer a RunArray with space for aSize runs
[ Next:RunArray-adding
| Previous:RunArray class-instance creation
| Up:RunArray
]
- at: anIndex
- Answer the element at index anIndex
- at: anIndex put: anObject
- Replace the element at index anIndex with anObject and answer anObject
[ Next:RunArray-basic
| Previous:RunArray-accessing
| Up:RunArray
]
- 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:RunArray-copying
| Previous:RunArray-adding
| Up:RunArray
]
- 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:RunArray-enumerating
| Previous:RunArray-basic
| Up:RunArray
]
- 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:RunArray-removing
| Previous:RunArray-copying
| Up:RunArray
]
- 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:RunArray-searching
| Previous:RunArray-enumerating
| Up:RunArray
]
- 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:RunArray-testing
| Previous:RunArray-removing
| Up:RunArray
]
- 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
]
- = anObject
- Answer true if the receiver is equal to anObject
- hash
- Answer an hash value for the receiver
[ ]
- 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:Semaphore-builtins
| Up:Semaphore
]
- 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:Semaphore-mutual exclusion
| Previous:Semaphore class-instance creation
| Up:Semaphore
]
- 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
]
- 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!!!
[ ]
- Category: Collections-Sequenceable
- My instances represent collections of objects that are ordered. I provide
some access and manipulation methods.
[ Next:SequenceableCollection-copying SequenceableCollections
| Up:SequenceableCollection
]
- 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:SequenceableCollection-enumerating
| Previous:SequenceableCollection-basic
| Up:SequenceableCollection
]
- , 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:SequenceableCollection-replacing items
| Previous:SequenceableCollection-copying SequenceableCollections
| Up:SequenceableCollection
]
- 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:SequenceableCollection-testing
| Previous:SequenceableCollection-enumerating
| Up:SequenceableCollection
]
- 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
]
- = 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
[ ]
- 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:Set-accessing
| Up:Set
]
- 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:Set-awful ST-80 compatibility hacks
| Previous:Set class-instance creation
| Up:Set
]
- 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:Set-enumerating the elements of a collection
| Previous:Set-accessing
| Up:Set
]
- 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:Set-rehashing
| Previous:Set-awful ST-80 compatibility hacks
| Up:Set
]
- do: aBlock
- Enumerate all the non-nil members of the set
[ Next:Set-Removing from a collection
| Previous:Set-enumerating the elements of a collection
| Up:Set
]
- rehash
- Rehash the receiver
[ Next:Set-storing
| Previous:Set-rehashing
| Up:Set
]
- remove: oldObject ifAbsent: anExceptionBlock
- Remove oldObject to the set. If it is found, answer oldObject. Otherwise, evaluate anExceptionBlock and return its value.
[ Next:Set-testing collections
| Previous:Set-Removing from a collection
| Up:Set
]
- storeOn: aStream
- Store on aStream some Smalltalk code which compiles to the receiver
[ Previous:Set-storing
| Up:Set
]
- = 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
[ ]
- 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:SharedQueue-accessing
| Up:SharedQueue
]
- new
- Create a new instance of the receiver
[ Previous:SharedQueue class-instance creation
| Up:SharedQueue
]
- 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
[ ]
- 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:Signal-exception handling
| Up:Signal
]
- 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
]
- 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
[ ]
- 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:SortedCollection class-instance creation
| Up:SortedCollection
]
- defaultSortBlock
- Answer a default sort block for the receiver.
[ Next:SortedCollection-basic
| Previous:SortedCollection class-hacking
| Up:SortedCollection
]
- 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:SortedCollection-copying
| Previous:SortedCollection class-instance creation
| Up:SortedCollection
]
- 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:SortedCollection-enumerating
| Previous:SortedCollection-basic
| Up:SortedCollection
]
- copyEmpty: newSize
- Answer an empty copy of the receiver, with the same sort block as the receiver
[ Next:SortedCollection-instance protocol
| Previous:SortedCollection-copying
| Up:SortedCollection
]
- collect: aBlock
- Answer an OrderedCollection containing the data in the receiver filtered through the given block
[ Next:SortedCollection-searching
| Previous:SortedCollection-enumerating
| Up:SortedCollection
]
- 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
]
- 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
[ ]
- 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:Stream-accessing-writing
| Up:Stream
]
- 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:Stream-basic
| Previous:Stream-accessing-reading
| Up:Stream
]
- 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:Stream-character writing
| Previous:Stream-accessing-writing
| Up:Stream
]
- species
- Answer `Array'.
[ Next:Stream-enumerating
| Previous:Stream-basic
| Up:Stream
]
- 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:Stream-filing out
| Previous:Stream-character writing
| Up:Stream
]
- do: aBlock
- Evaluate aBlock once for every object in the receiver
[ Next:Stream-printing
| Previous:Stream-enumerating
| Up:Stream
]
- 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:Stream-providing consistent protocols
| Previous:Stream-filing out
| Up:Stream
]
- 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:Stream-storing
| Previous:Stream-printing
| Up:Stream
]
- close
- Do nothing. This is provided for consistency with file streams
[ Next:Stream-testing
| Previous:Stream-providing consistent protocols
| Up:Stream
]
- 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
]
- atEnd
- Answer whether the stream has got to an end
[ ]
- Category: Language-Data types
- My instances represent string data types. I provide accessing and
manipulation methods for string data types.
[ Next:String class-instance creation
| Up:String
]
- 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:String-built ins
| Previous:String class-basic
| Up:String
]
- fromCData: aCObject size: anInteger
- Answer a String containing anInteger bytes starting at the location pointed to by aCObject
[ Next:String-comparing
| Previous:String class-instance creation
| Up:String
]
- 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:String-converting
| Previous:String-built ins
| Up:String
]
- < 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:String-copying
| Previous:String-comparing
| Up:String
]
- 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:String-printing
| Previous:String-converting
| Up:String
]
- , 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:String-storing
| Previous:String-copying
| Up:String
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ Next:String-string processing
| Previous:String-printing
| Up:String
]
- storeOn: aStream
- Print Smalltalk code compiling to the receiver on aStream
[ Next:String-testing functionality
| Previous:String-storing
| Up:String
]
- 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:String-useful functionality
| Previous:String-string processing
| Up:String
]
- isString
- Answer `true'.
[ Previous:String-testing functionality
| Up:String
]
- 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
[ ]
- 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:Symbol class-instance creation
| Up:Symbol
]
- intern: aString
- Private - Same as 'aString asSymbol'
[ Next:Symbol-basic
| Previous:Symbol class-built ins
| Up:Symbol
]
- 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:Symbol-built ins
| Previous:Symbol class-instance creation
| Up:Symbol
]
- 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:Symbol-converting
| Previous:Symbol-basic
| Up:Symbol
]
- = 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:Symbol-misc
| Previous:Symbol-built ins
| Up:Symbol
]
- 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:Symbol-storing
| Previous:Symbol-converting
| Up:Symbol
]
- species
- Answer `String'.
[ Next:Symbol-testing functionality
| Previous:Symbol-misc
| Up:Symbol
]
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream
[ Previous:Symbol-storing
| Up:Symbol
]
- isString
- Answer `false'.
- isSymbol
- Answer `true'.
[ ]
- 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:SymLink-printing
| Up:SymLink
]
- do: aBlock
- Evaluate aBlock for each symbol in the list
[ Previous:SymLink-iteration
| Up:SymLink
]
- printOn: aStream
- Print a representation of the receiver on aStream.
[ ]
- 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:SystemDictionary-builtins
| Up:SystemDictionary
]
- 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:SystemDictionary-C functions
| Previous:SystemDictionary-basic
| Up:SystemDictionary
]
- 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:SystemDictionary-initialization
| Previous:SystemDictionary-builtins
| Up:SystemDictionary
]
- 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:SystemDictionary-miscellaneous
| Previous:SystemDictionary-C functions
| Up:SystemDictionary
]
- 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:SystemDictionary-special accessing
| Previous:SystemDictionary-initialization
| Up:SystemDictionary
]
- 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
]
- 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
[ ]
- 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:Time class-builtins
| Up:Time
]
- 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:Time-accessing
| Previous:Time class-basic
| Up:Time
]
- primMillisecondClock
- Returns the number of milliseconds since midnight.
- primSecondClock
- Returns the number of seconds to/from 1/1/2000.
[ Next:Time-arithmetic
| Previous:Time class-builtins
| Up:Time
]
- 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:Time-comparing
| Previous:Time-accessing
| Up:Time
]
- 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
]
- < 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
[ ]
- 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:TokenStream-basic
| Up:TokenStream
]
- 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:TokenStream-write methods
| Previous:TokenStream class-instance creation
| Up:TokenStream
]
- 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
]
- nextPut: anObject
- This method should not be called for instances of this class.
[ ]
- Category: Streams
-
[ Next:TranscriptInterface-accessing
| Up:TranscriptInterface
]
- new
- Answer the only instance of the receiver - which is stored in the global variable Transcript.
[ Next:TranscriptInterface-printing
| Previous:TranscriptInterface class-accessing
| Up:TranscriptInterface
]
- 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:TranscriptInterface-set up
| Previous:TranscriptInterface-accessing
| Up:TranscriptInterface
]
- print: anObject
- Print anObject's representation to the Transcript
- printOn: aStream
- Print a representation of the receiver onto aStream
[ Next:TranscriptInterface-storing
| Previous:TranscriptInterface-printing
| Up:TranscriptInterface
]
- 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
]
- store: anObject
- Print Smalltalk code which evaluates to anObject on the Transcript
- storeOn: aStream
- Print Smalltalk code which evaluates to the receiver onto aStream
[ ]
- 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:TrappableEvent-instance creation
| Up:TrappableEvent
]
- 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
]
- , aTrappableEvent
- Answer an ExceptionCollection containing all the exceptions in the receiver and all the exceptions in aTrappableEvent
[ ]
- Category: Language-Data types
- I represent truth and justice in the world. My motto is "semper veritatis".
[ Next:True-C hacks
| Up:True
]
- & 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:True-printing
| Previous:True-basic
| Up:True
]
- asCBooleanValue
- Answer `1'.
[ Previous:True-C hacks
| Up:True
]
- printOn: aStream
- Print a representation of the receiver on aStream
[ ]
- 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:UndefinedObject-class creation - alternative
| Up:UndefinedObject
]
- 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:UndefinedObject-printing
| Previous:UndefinedObject-class creation
| Up:UndefinedObject
]
- 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:UndefinedObject-storing
| Previous:UndefinedObject-class creation - alternative
| Up:UndefinedObject
]
- printOn: aStream
- Print a representation of the receiver on aStream.
[ Next:UndefinedObject-testing
| Previous:UndefinedObject-printing
| Up:UndefinedObject
]
- storeOn: aStream
- Store Smalltalk code compiling to the receiver on aStream.
[ Previous:UndefinedObject-storing
| Up:UndefinedObject
]
- 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.
[ ]
- 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:ValueAdaptor-accessing
| Up:ValueAdaptor
]
- new
- We don't know enough of subclasses to have a shared implementation of new
[ Next:ValueAdaptor-basic
| Previous:ValueAdaptor class-creating instances
| Up:ValueAdaptor
]
- 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
]
- printOn: aStream
- Print a representation of the receiver
[ ]
- 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:ValueHolder-accessing
| Up:ValueHolder
]
- 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
]
- value
- Get the value of the receiver.
- value: anObject
- Set the value of the receiver.
[ ]
- 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
]
- 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
[ ]
- Category: Streams-Collection
- I am the class of writeable streams. I only allow write operations to
my instances; reading is strictly forbidden.
[ Next:WriteStream-accessing
| Up:WriteStream
]
- 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:WriteStream-accessing-writing
| Previous:WriteStream class-instance creation
| Up:WriteStream
]
- size
- Answer how many objects have been written
[ Next:WriteStream-positioning
| Previous:WriteStream-accessing
| Up:WriteStream
]
- nextPut: anObject
- Store anObject as the next item in the receiver. Grow the collection if necessary
[ Previous:WriteStream-accessing-writing
| Up:WriteStream
]
- 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:Acknowledgements
| Previous:Class reference
| Up:Top
]
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:
- Port to other computers/operating systems. The code thus far has
shown itself to be relatively portable to various machines and
UNIX derivatives. The architecture must support 32 or 64 bit
pointers and long integers, and have allocated addresses that
are either all positive or all negative.
- Comment the C code more thoroughly. The C source code could
definitely stand a more thorough commenting.
- Create more precise versions of the Delay class primitive. This
needs to use some kernel call to set up an interrupt after the
appropriate number of milliseconds. Unfortunately, I do not have
access to a true System V UNIX box to find out what kernel call
allows me to do this (BSD has
setitimer
(2), and I use
CreateThread
under Win32).
- Add more test cases to the test suite. The test suite is much too
small. Ideally, after making changes to the Smalltalk system,
you'd put it through its paces by running with the test suite and
make sure that you hadn't broken anything.
- Improve the byte-code interpreter's efficiency. This could bring
major performance boosts, but it is the hardest thing of all. Anyway,
if you find a way to add even just 5 percent of performance, that is
important too and I'll be happy to hear from you.
- Improve the memory manager. The current one is effective, but not
at all cunning.
Also, following is a brief description of the differences and
omissions between GNU Smalltalk and "Blue Book" Smalltalk
(Smalltalk-80).
- No long integers in Smalltalk code (yet)
- As I said above, class Delay is not precise enough (1 sec) for most
architectures
[ Previous:Future
| Up:Top
]
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
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
- Installation
- Using GNU Smalltalk
- Features of GNU Smalltalk
- Interoperability between C and GNU Smalltalk
- Tutorial
- Class reference
- Future directions for GNU Smalltalk
- Acknowledgements
Footnotes
-
It also prints out a lot of statistics. Ignore these; they
provide information on the performance of the underlying Smalltalk
engine. You can inhibit them by starting Smalltalk as either:
$ gst -q
or
$ gst -r
-
Which table? This is determined by the type
of the object. An object has a type, known as the
class to which it belongs. Each class has a table
of methods. For the object we created, it is
known as a member of the String
class. So we go
to the table associated with the String class.
-
Actually, the message printNl
was inherited
from Object. It sent a print
message, also
inherited by Object, which then sent printOn:
to
the object, specifying that it print to the Transcript
object. The String class then prints its characters to the
standard output.
-
Alert readers will remember that the math
examples of the previous chapter deviated from this.
-
Actually,
a SystemDictionary, which is just a Dictionary with some
extra methods to run things when Smalltalk first starts and
to do nice things with a Smalltalk environment
-
For more detail, See Two flavors of equality
-
In case you're having a hard time making out
the font, the " after classVariableNames:
and
poolDictionaries:
are a pair of single quotes-an
empty string.
-
And unlike C, Smalltalk
draws a distinction between 0
and nil
. nil
is the nothing object, and you will receive an error if you
try to do, say, math on it. It really does matter that we
initialize our instance variable to the number 0 if we wish
to do math on it in the future.
-
And why didn't the designers default the
return value to nil? Perhaps they didn't appreciate
the value of void functions. After all, at
the time Smalltalk was being designed, C didn't
even have a void data type.
-
self
is much like super
, except that
self
will start looking for a method at the bottom
of the type hierarchy for the object, while
super
starts looking one level up from the current
level. Thus, using super
forces inheritance,
but self
will find the first definition
of the message which it can.
-
Of course, in a real accounting system we
would never discard such information-we'd probably
throw it into a Dictionary object, indexed by the
year that we're finishing. The ambitious might
want to try their hand at implementing such an
enhancement.
-
It is interesting to note that because of the
way conditionals are done, conditional constructs
are not part of the Smalltalk language, instead they are
merely a defined behavior for the Boolean class of
objects.
-
You might start to wonder what
one would do if you wished to associate two pieces of
information under one key. Say, the value and who the
check was written to. There are several ways; the
best would probably be to create a new, custom
object which contained this information, and then
store this object under the check number key in
the dictionary. It would also be valid (though
probably over-kill) to store a dictionary as the
value-and then store as many pieces of information
as you'd like under each slot!
-
The do:
message is understood by most types
of Smalltalk collections. It works for the
Dictionary class, as well as sets, arrays, strings,
intervals, linked lists, bags, and streams. The
associationsDo:
message works only with dictionaries.
The difference is that do:
passes only the
value portion, while associationsDo:
passes the
entire key/value pair in an Association object.
-
There is also a valueWithArguments:
message
which accepts an array holding as many arguments
as you would like.
-
When using
the Blox GUI, it actually pops up a so-called Inspector window.
-
This listing is courtesy of the
printHierarchy method supplied by GNU Smalltalk author Steve
Byrne. If you have the GNU Smalltalk source, it's
in the kernel/Browser.st
file
-
You
have had an anticipation of this in the section on debugging, where
you found that findIndex:ifAbsent:
is actually defined in
Set.
-
Actually, a Dictionary inherits much more:
it inherits the representation of itself as a hash table, and most of
the code needed to implement hash tables!
-
Smalltalk also offers an or:
message, which
is different in a subtle way from |
. or: takes
a code block, and only invokes the code block if
it's necessary to determine the value of the
expression. This is analogous to the guaranteed C
semantic that &&
evaluates left-to-right only as
far as needed. We could have written the expressions
as ((index < 1) or: [index > (self basic-Size)])
.
Since we expect both sides of or: to be
false most of the time, there isn't much reason to
delay evaluation of either side in this case.
-
Try executing it under Blox, where the
Transcript is linked to the omonymous window!
-
For GNU Smalltalk, the size of a C long
, which
is usually 32 bits.
-
C
requires one or more; zero is allowed in Smalltalk-actually,
one field is implicitly allocated for the object's class
-
This is not always true for other Smalltalk
implementations
-
Actually, in GNU Smalltalk do:
is not the only
message assuming that.