File: README

package info (click to toggle)
tom 1.1.1-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 6,340 kB
  • ctags: 2,244
  • sloc: objc: 27,863; ansic: 9,804; sh: 7,411; yacc: 3,377; lex: 966; asm: 208; makefile: 62; cpp: 10
file content (341 lines) | stat: -rw-r--r-- 13,538 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
$Id: README,v 1.8 1996/01/23 16:54:28 tiggr Exp $

TOM

SPEED

	Speed optimizations may only be contemplated when they do not
	hamper the elegance or usability of the language.

	For instance, static method binding, which is a popular and
	effective speed optimization, can not be allowed since this
	hampers the usability of NSLs (Non Source Libraries, see below).

	On the other hand, static instance variable binding is an
	allowable optimization, since allowing it in the language
	definition does not refrain the programmer from always using
	dynamically bound methods to reference or set instance variables
	(not that this trick solves the actual problem).

	Also in favor of speed is static binding of operations on basic
	types.  If such static binding is undesirable, one can define
	objects containing such static types.  Such objects provide the
	programmer with the desired flexibility.  Of course, all
	occurences of the basic types not inside such a wrapper are still
	statically bound and not overridable.  However, since the builtin
	operations on basic types only involve rather strictly defined
	arithmetic and logic operations the decrease in the usability is
	not considered a issue.

STATIC BINDING

	As has been explained, instance variables and the builtin
	operations on the basic types are statically bound.  Especially in
	the first case, this introduces the problem that if the number of
	instance variables of a class changes (or is only increased, in
	case all instance variables are private to the class), all
	subclasses need to be recompiled.  This is a problem known as the
	fragile superclass.  However, it is not considered to be important
	enough to use dynamic instance variable binding despite the speed
	penalty.

USABILITY

	A popular OO term is reusability.  A (related) term, which is just
	as important, is _usability_, i.e. the way in which classes,
	especially those written by others, can be used.  Usability is
	severely hampered in case of bugs in classes provided in a Non
	Source Library (NSL), i.e. a library of which the source code is
	unavailable.  Even under such circumstances, usability can still
	reach an acceptable level if all methods are dynamically bound and
	class definitions can be adjusted, meaning that method
	implementations can be added.

	As an example, a very interesting method to override is the
	allocation of new instances of a class.  If a class X from an NSL
	is unusable due to bugs or a bad design, one can replace its
	allocation method to return something different from an instance
	of X, for instance an object over which one does have source
	control.  (Obviously, due to type matching restrictions, the
	object being returned must be an instance of a subclass of X.)
	Since all methods are dynamically bound, _all_ usage of the class
	X, also within the library proper, will effectively use the
	replacement class set up by overriding the allocation method.

	Replacing the alloc method of a class is not sufficient to fix
	bugs in classes which are also subclassed, since the overriding
	allocation only works for instances of the class, not of its
	proper subclasses.  Objective-C provides class posing as a runtime
	hack, which must be explicitly done by the imposter as early as
	possible, for instance in `+load'.  However, in a compile time
	type checked system, this solution implies that the imposter can
	not add functionality which can actually be used, unless the
	definition of the class being posed as is also adjusted.  However,
	this is troublesome, to say the least.  Combining these two
	observations leads one to believe that class posing should be
	possible through a simple keyword in the language.

	Due to the statically bound instance variables, a posing class can
	not add instance variables.

BASIC TYPES

	The basic types are:

	name	bitsize	kind
	----------------------------------------------------------------------
	bool		basic, builtin, bool

	char	8	basic, builtin, numeric, integer
	short	16	basic, builtin, numeric, integer
	int	32	basic, builtin, numeric, integer
	long	64	basic, builtin, numeric, integer

	float	32	basic, builtin, numeric, fp
	double	64	basic, builtin, numeric, fp

	object		basic, builtin, object
	----------------------------------------------------------------------

	Clearly, all basic values are unboxed; all objects are boxed.

	The derived types are:

	name		kind
	----------------------------------------------------------------------
	tuple		derived, tuple
	array		derived, array, generic, object
	----------------------------------------------------------------------

	Semantically, tuples are unboxed.  Arrays, which are objects, are
	boxed.

OPERATORS

	The statically bound operations are easily recognizable as they
	come with special syntax.

	-	minus	 	numeric -> same
	~	bitwise invert	integer -> top
	!	not		builtin|object -> bool

	*	multiply	numeric * numeric -> top
	/	divide		id
	%	modulo		integer * integer -> top

	+	add		numeric * numeric -> top
	-	subtract	id

	<<	shift left	integer * integer -> top
	>>	shift right	id

	&	bitwise and	integer * integer -> top

	|	bitwise or	id

	^	bitwise eor	id

	<	lt		numeric * numeric -> bool
	<=	le		id
	==	eq		any * same -> bool
	!=	ne		id
	=>	ge		numeric * numeric -> bool
	>	gt		id

	&&	s.c. and	bool * bool -> bool

	||	s.c. or		id

	->	s.c. implies	id

	?:	ite		bool * any * same -> same

	Integer arithmetic is performed using ints, unless one of the
	operands is a long, in which case the computation is performed
	using longs, and the result will be a long.  Otherwise, the result
	is an int.  Floating point arithmetic is performed using and
	producing floats, unless one of the arguments is a double, in
	which case both computation and result are doubles.

	Casting a numeric type to another numeric type can only be
	accomplished through assignment, or to promotion due to arithmetic
	rules.  Thus, explicit narrowing casts are only possible using
	assignment.

TUPLES

	A tuple is a product type, much like a struct in C.  However, the
	operations on tuple typed values are limited, since it is not
	allowed (i.e. impossible) to declare variables of a tuple type.
	This is deliberate; one should use objects to store complex state.

	Examples of things that can be done with tuples are:

		The tuple can be the return type of a method.  E.g.,
		`(int) foo' is a method returning an int; `(int, int) foo'
		is a method returning two ints.

		A tuple can be the type of arguments to a method.  For
		instance, `void foo (int, int) (a, b)' declares a method
		accepting a tuple with two integers as its argument.

		Tuples can be used in assignment statements to stand for
		simultaneous assignment (and a swap can be written as `(a,
		b) = (b, a)').

		If a method returns a tuple, like `(int, float) foo' and
		the value of the int is not necessary, partial assignment
		can be performed, as in `(, a) = [rcv foo]'.

	Two tuples have the same type if they have the same number of
	fields and corresponding fields have the same type.

	The notation used here for tuples seems to imply that a tuple with
	a single component is not tuple-typed but has the type of the
	component.  Actually, the tuple has both types, whereas the
	component itself only has its own type.  This is consistent with
	normal use of parenthesized expressions.

	[Aside: The first version of this writing suggested the
	possibility of the existence of tuple-typed variables, with the
	following note: One other operation (it's not really a distinct
	operation) is possible on a tuple: it can be assigned to a
	tuple-typed variable.  However, in a first implementation of the
	language, the tuple typed values will probably not be first class
	values, and tuple-typed variables can not be declared.  End aside.]


ARRAYS

	An array is an indexable collection of values.  Such values can be
	of any type.  Basic operations like querying, replacing elements
	and extending the array are statically bound.  In other respects,
	an array behaves like an object.  There are, however, some subtle
	issues involved.

	`array (int) a' declares A to be a reference to an array
	containing integers.  (XXX I'm not sure of this syntax.)

	An array is a generic type, in that it its elements can have any
	type, be it int, double, object or what else.

	An array can have fixed bounds, a fixed lower and variable higher
	bound, or variable lower and higher bounds.  An array which is
	created with fixed bounds initially has all elements set to the
	default element value, with is 0 for numbers, false for booleans
	and void for object references.  The default value for tuples is a
	tuple filled with the default values of the types of its fields.

	Since an array is an object, it can be subclassed.  However, only
	a concrete array can be subclassed.  The generic array (which is
	parameterized in its type) can not be subclassed.  The reason for
	this has to do with the issue of usability and
	recompilation-for-a-different-type-parameter.  (XXX Yeah, sure.)

	Given the restrictions on array subclassing, array subclassing is
	much like creating a class which has an array as one of its
	instance variables.

OVERLOADING

	The method `(int) value' is different from `(double) value'.
	Similarly, `(void) setValue: (int)' is different from `(void)
	setValue: (double)'.  This distinction on argument and return
	types can be made at compile-time.

	Overloading on object type is not allowed, since, at compile time,
	it is not known how a class may be adapted in the final program.
	For instance, suppose the existence of a class A: C, D, a class B:
	A, E, and two methods, `(void) foo: (C)' and `(void) foo: (E)'.
	Apart from the question how to decide which method to call for an
	instance of B, the method to invoke for an A can not be fixed at
	the first foo, because A can be adapted later on to also conform
	to `E', and either method can be chosen, just as for B.

	Since it is considered too expensive to match on argument types at
	run time, overloading on object type is not possible.

TYPE DEFINITIONS

	Types can be given a name, by using the `typedef' keyword.  Thus,
	just like `int a' declares a value named a of type int, `typedef
	int a' declares a type named a being the type int.  This is most
	useful in giving names to tuple types, as in `typedef (float,
	float) NXPoint'.

	Type definition only gives a (different) name to an already
	existing type.  Hence, type equality is defined in terms of the
	basic types.  Thus, given `typedef int a; typedef int b;', the
	types `a' and `b' are type-equal.  However, the compiler could
	issue warnings about the possibly unintended passing of an `a'
	typed value where a `b' typed value is expected.

	Also note that, given the previous definitions of `a' and `b',
	`a', `b' and `int' can not be discerned for overloading method
	arguments.  Only one method may be defined to act on the integer
	typed value, be it `a', `b' or `int'.

	Each typedef implicitly introduces a set of functions by the same
	name, which can be used to convert the type of an expression to
	the indicated type.  Of course, the two types involved in type
	conversion must be compatible.  (XXX Define.)

TYPE CONVERSION

	Numeric types are convertible to each other.

	Object types are convertible to each other, if there exists an
	instantiable subclass common to the source type and the
	destination type.  The reason for this is depicted below.

	Suppose the existence of an object of which some instance variable
	can be read and set through the methods `(A) value' and `(void)
	setValue: (A)', respectively.  This ivar can be set to any B, as
	long as B is a subclass of A.  If the value is then retrieved, the
	object is still a B, and must be allowed to be a B.  The B can
	then used as an argument to another method, which expects an
	object of type C, as long as B is a subclass of C.  In the same
	situation without an explicit assignment to B, the A typed value
	retrieved is passed as a C typed argument.  This can only be
	possible if the B class exists.

TYPES OF ARGUMENTS TO METHODS

	If a class P declares a method `(A) foo: (B)', which is redeclared
	by a subclass Q to be `(C) foo: (D)', then there are some
	restrictions on the types C and D which I yet have to settle
	(XXX).

SCOPING

	Scoping is lexical.  The global scope (within a project) contains
	only type and class names.  Inheriting from a class brings the
	definitions of that class into scope.  Within an instance
	definition, the global scope is first extended by all class scopes
	of the classes inherited, followed by the instance scopes of the
	classes inherited.  (Thus, the innermost enclosing scope is the
	instance scope of the first superclass.)

BINDING

	There are a lot of syntactical ways to invoke a method.  Some
	allow the receiver to be specified implicitly to be the class of
	the receiver of the current method.

STATEMENTS

    ASSIGNMENT

	Assignment is a statement, as in `a = b', which says the the value
	of `a' after execution will be the value of `b'.  A and B must
	have the same type.  Tuple assignment, as in `(a_1, a_2, ...) = b'
	assigns to each a_i the value of the corresponding field in the
	tuple-typed value of b.  Any a_i may be empty (an empty string),
	indicating that the value of the corresponding field in b is not
	retrieved.

    RETURN

	The return statement looks like an assignment with an empty lhs.
	For instance, the statement `= 0' will exit the current method
	with a value of 0.