TweetFollow Us on Twitter

Object Pascal
Volume Number:2
Issue Number:12
Column Tag:Pascal Procedures

Introduction to Object Pascal

By Ken Doyle, Apple Computer, Inc.


If you have been reading about MacApp, you may be wondering if you have to have the Macintosh Programmer's Workshop (MPW) and if MacApp programs must be written in Object Pascal. The answer is yes, for now. For those of you who like some of the other Pascal compilers out there, or prefer to program in another language such as C, you are currently out of luck. The reason is two-fold. Most languages for the Macintosh do not support the object-oriented concepts upon which MacApp so heavily relies, and even if they do, they don't use the same run-time scheme that Object Pascal does.

In this article I will first present a description of the syntax of Object Pascal and comment on some of the semantics involved in using the syntax. I will discuss the various degrees of compatibility that another language or compiler needs to achieve in order to make use of MacApp and what steps are necessary in meeting that goal. In particular, the exact format of the generated code and the run-time routines that deal with that code will be shown. I will talk a bit about how we added objects to MPW's Assembly language. Finally I present a scheme for optimizing what we've already learned.

Object Pascal

Object Pascal is an extension to the Pascal language that was developed at Apple in consultation with Niklaus Wirth, the inventor of Pascal. It is descended from an earlier attempt at an object-oriented version of Pascal called Clascal, which was available on the Lisa computer. MacApp itself is descended from the Lisa Toolkit, an application framework for creating Lisa applications. The Lisa Toolkit was written in Clascal.

There are actually very few syntactic additions to Pascal in Object Pascal. A new data type is added, the object. An object is very much like a record in that it can have multiple data fields of arbitrary types. In addition, you can specify a list of procedures and functions, referred to as methods, for a particular object type. These methods define the actions that an object of this type can perform. For example, you could define a Shape object type as follows:

 Shape = object
 color: Pattern;
 procedure Draw;
 procedure Erase;
 procedure Rotate(angle: integer);
 procedure Move(delta: Point);
 function Area: integer;

Furthermore, you can define an object type that inherits the fields and methods of another object type. The new type can define additional fields and methods and can choose to selectively override methods that it has inherited.

 Circle = object(Shape)
 radius: integer;
 procedure Draw; override;
 function Area: integer; override;
 procedure SetRadius(newRadius: integer);

 var aCircle: Circle;

An object type is often referred to as a class. In the above example, Circle is a subclass of Shape. Shape is the superclass of Circle. A class (object type) can have many subclasses (descendants), but only one superclass (immediate ancestor). When speaking of the relationships conceptually , I will more often use the class terminology. When speaking in terms of Pascal data types I use the object type terms.

Objects are created by calling the Pascal built-in procedure New on a variable of an object type. You say New(aCircle) to create an instance of the object type Circle. The New procedure, when used with an object type variable allocates sufficient storage on the heap for the object and sets the value of the variable to be a handle (pointer to a pointer) to that data. The double arrow normally required for handle dereferencing is done automatically by the compiler, so fields are accessed directly, eg: aCircle.bounds, NOT aCircle^^.bounds. Likewise, to invoke a method you use the same notation: aCircle.Draw invokes the Draw method of the Circle object type, presumably drawing itself on some display. Since all object type variables are actually handles to the data, an assignment such as shape1 := shape2 causes shape1 to point to the same data as shape2.

The fields of an object can themselves be references to other objects. For example you could have a nextShape field in the Shape definition if you wanted to have a linked list of shapes. Object Pascal allows you to specify the type of a field to be a reference to an object type not yet declared. In this manner, you can have circular references of object types to one another. If the compiler encounters an undeclared type identifier, it assumes it is an object type that will be declared later. If the type is not declared later, an error will be reported. The size of the not yet declared object is unimportant since the reference to it is always just a four byte handle.

The depth to which an object type can inherit is unlimited. You could define a descendant of Circle and another descendant of that type and so on. Each succeeding descendant inherits all of the fields and methods of all of its ancestors.

Figure 1.

Object Pascal requires that the object type definitions be at the highest level in a unit or program, always as a type declaration. For a unit this can be either in the interface or the implementation part. The body or actual code for the methods appears in the procedure and function part of the unit or program. If the body of a declared method does not appear in the file, the compiler issues a "method not implemented" error. The body of a method is just like that of any procedure or function:

 procedure Shape.Erase;

 procedure Circle.Draw;
 FillOval(bounds, color);

There are several things to note in these two examples. The name of the method is given as TypeName.MethodName to distinguish which method is being defined. When inside a method, there is always an implicit parameter called SELF. SELF refers to the object that invoked the method. The fields of the object could be accessed as SELF.bounds or SELF.color, however the compiler provides an implicit "with SELF do" block around the method making the field names directly accessible. Similarly, you could invoke another method from within a method by saying SELF.OtherMethod but again just OtherMethod is sufficient. This obviates the need for SELF other than when one wishes to pass the object itself to another routine, eg: AddMeToList(SELF). For the statement aCircle.Draw, since aCircle is of type Circle, the Circle.Draw method would be called rather than the Shape.Draw method. In addition, if the aCircle.Erase is called, since Circle did not override the Erase method, the Shape.Erase method would be invoked. This is fairly straightforward. Slightly less obvious behavior occurs if the following code is executed:

 var aShape: Shape;
  aCircle: Circle;

 aCircle.bounds := someRect;
 aCircle.color := white;
 aCircle.radius := 60;
 aShape := aCircle;

When aShape.Draw is executed, which method is called: Shape.Draw or Circle.Draw? Even though aShape is declared as a Shape, the assignment to aCircle causes it to be a Circle object and thus Circle.Draw would be the method called. This is accomplished by means of a two byte type identifier at the beginning of every object (see Figure 1). This raises some important points. The assignment aShape := aCircle is "safe" because any fields or methods accessed for a Shape object will be valid for a Circle object. But the reverse assignment aCircle := aShape is not safe since the additional fields or methods in Circle will not necessarily be understood by a Shape object. For example, if we later tried to invoke aCircle.SetRadius it would not be understood had aShape been a regular Shape object. (In fact, the aShape variable could have referred to an entirely different descendant of Shape, say Triangle, which also would not understand any Circle-specific methods calls or field accesses.) The compiler issues an error message if such an assignment is attempted. If you are absolutely sure that in this case the Shape variable is guaranteed to be pointing to a Circle object, you can use coercion to override the compiler: aCircle := Circle(aShape). Even then, at run time, if range checking is turned on, the assignment will be checked to make sure it is valid.

The point to remember from this is that even though a variable is declared to be of a particular object type, at run time, its actual type may be that type or any descendant of that type. It is by this means that one could have a list if "shapes" that could each be told to "draw", where the actual types are a mixed collection of circles, squares, triangles, and so forth. As a result, the determination of which actual method to call must be made at run time. This is accomplished using a "method dispatch routine" that looks at the two byte type field of the object and uses tables of method locations to direct the call to the proper method. Method dispatching will be discussed in more detail later.

A final syntactic addition to Pascal is the inherited keyword. If you have overridden a method to add some code specific to your object type but still want to use the code in the overridden method, you would use the word inherited followed by the method name:

 procedure MyController.ProcessKeystroke(ch: char);
 if ch = 'X' then
 inherited ProcessKeystroke(ch);

Assuming Controller was the immediate ancestor of MyController, the inherited call would be a call to Controller.ProcessKeystroke (given that the method exists). In the case of inherited, the proper method to call can always be determined at compile time -- there is no need for a run time method dispatch. The call is always to the closest ancestor that implemented the method. Realize that this does not necessarily mean the immediate ancestor. If the immediate ancestor did not implement the method but an ancestor further up in the hierarchy did, the call would be to that method. By using the inherited keyword rather than explicitly naming an ancestor (superclass) object type, you are insulated from possible future changes that might insert or delete an implementation of the method in an ancestor or superclass. The compiler will issue an error message if inherited is used in a method that was not inherited from an ancestor object type.

Object Pascal also provides the built-in function Member. You can use Member to test if a particular object is in a certain class. For example you could say:

 if Member(aShape, Circle) then
 numCircles := numCircles+1;


Member returns true if the object's type is the same type or a descendant of the object type being tested. In the example above, numCircles would be bumped for ordinary circles and any specialized subclasses of Circle, but not for Squares, Triangles, or ordinary Shapes. The use of the Member function is somewhat contrary to the principles of object-oriented programming (you're not supposed to peek at your own type) so its use is generally discouraged except in unusual circumstances.

Since all object references are stored as handles to the object data on the heap, there are a couple of Pascal constructs that are unsafe to use on fields of an object. One is the use of a field as a VAR parameter in a procedure call. The Pascal compiler pushes the address of a VAR parameter on the stack. If the heap were to compact while processing the procedure, the address of the field of the object could become invalid. Another situation where the compiler computes an absolute address is if you use the with statement on an object field that is a record type, eg: "with aCircle.bounds do". If some statement in the with block caused a compaction, the computed address could become invalid. The compiler issues warnings when such a usage is detected. If you are sure the procedure or with statement will not compact the heap, you can precede the statement with the {$H-} compiler option. This tells the compiler not to issue the warning. You should follow the statement with {$H+} to turn heap warnings back on.

Levels of Compatibility

If you are a compiler writer who wants to use MacApp, there are a variety of levels of compatibility you can strive to achieve. The degree of compatibility can fall into the conceptual, the source file, or the object file level. (Note: The term object is used in two completely different contexts in this article. One use is with object-oriented phrases such as object type or an object on the heap. The second use is when speaking of the object file format, which is the term used for the structure of a file generated by a compiler.) To be conceptually compatible, the language must support the object-oriented concepts of object type definitions, inheritance, and method calls. Source file compatibility is a special case that only applies to Pascal compilers. The Pascal compiler would have to support all of the extensions to Pascal that the Macintosh Workshop Pascal supports, which in addition to the object-oriented extensions, includes such features as separately compiled units, expressions in constant declarations, and numerous compile time options such as conditional compilation. Finally, languages that are object file compatible would use the same object file format, namely that defined in the appendix of the MPW reference manual, and furthermore would support the specific method calling conventions and method table formats that Object Pascal generates.

If a language supports the object-oriented concepts of Object Pascal and if the programming structures of the language resemble the structures of Pascal, it should be fairly simple to write a program to do an automatic translation of MacApp into the desired language. For known constructs that are not automatically translatable, the program would flag that code for hand translation. The compiler writer could then distribute either the translated source or the compiled object form of MacApp, subject, of course, to whatever legal mumbo jumbo is required from Apple to redistribute MacApp. For compilers that do not use the MPW object file format, some variation of this will be the only alternative for those who want to use MacApp.

Pascal compilers that add the extensions of Macintosh Workshop Pascal can directly compile the MacApp sources themselves. If your compiler supports most but not all of the extensions, you may be able to modify the MacApp source files to not use the unsupported features. The object-oriented extensions would, of course, have to be supported.

Compilers that generate code using the MPW object file format and use the Object Pascal method table and method calling schemes will be able to link directly with compiled MacApp files. They will be able to link with Object Pascal building block files such as the Text and Dialog Box units.

Currently, most compilers do not support the MPW object file format. Hence, the only option available is that of translating MacApp into their particular language (which may be a trivial or null translation in the case of Object Pascal compatible compilers). If you as a compiler writer are not religiously (or pragmatically) devoted to your particular object file format, I would encourage you to consider using that of MPW. In any event, the discussion of our particular method table organization and method dispatching scheme that follows should be useful if you are considering adding object-oriented features to your language, even if you decide to implement your language in a completely different way.

Object File Format

As mentioned before, Apple's Object Pascal compiler generates files using the MPW object file format. The structure of the file consists of a collection of varying length records. There are eleven different kinds of records. The important ones for our purposes are the module, contents, and reference records. The module record specifies a new code or data module. Each procedure or function is represented by a code module. It is generally followed by one or more reference and/or contents records. The reference records specify what external modules are referenced from the current module. The contents records contain the actual code of the routine. The linker uses the reference and module records to patch branches and other instructions that have external references.

The Class Info Proc

When an object type is defined, a phony code module is generated. This code module is known as the "Class Info Proc". It contains information on who the ancestor is, what the size of an object of this type will be, and how many methods are implemented by this type. This is followed by the actual method table. This module is never actually called. It is placed in a special segment named %_MethTables with all other class info proc's. This segment also contains a very short routine called %_RTS1. The code for it is simply an RTS instruction. At application startup, %RTS1 is called, which loads the segment with all of the method tables.

The Method Call

Before I talk about the format of the method table itself, we need to understand how a method call works. Consider the following method call:


Method calls in Object Pascal naturally use Pascal calling conventions. First the parameters are pushed onto the stack (in the order they appear in the procedure declaration), then a JSR (Jump to Subroutine) call is made. Recall that in a method, there is always the implicit parameter SELF. This is pushed onto the stack after the actual parameters of the method. The object code for the method call above will look somewhat like this:

 MOVE.L dist,-(SP)
 MOVE.L aShape,-(SP)
 JSR    ??

Where does the JSR jump to? Since the actual method to call is dependent on the run time type of aShape, we cannot put a direct JSR to Shape.Move. At run time, aShape could be a Circle, Square, or some descendent not even known when this code was compiled. We need to go through a dispatch mechanism that examines the object to determine its type and then call the appropriate method based on that type. But so far, looking at the code above, we haven't even indicated what method we want to call. Most object-oriented languages use the selector technique to indicate to the dispatching routine what method is being called. A selector is some unique identifier for a particular method name. Often the selector is simply the name of the method itself. This, however can be expensive in terms of space required. Furthermore, Object Pascal allows methods in unrelated branches of the object hierarchy to have the same name with completely different parameter lists. The compiler treats these as totally separate method definitions. Simply using the method name for the selector would be ambiguous.

The Selector Proc

The question remains: how do we generate a unique selector for each method name? We let the linker do it! The linker, in resolving cross segment references, patches JSR's by having them branch into a jump table that then jumps to the correct routine. When segments are unloaded and reloaded in memory, the jump table entries are updated appropriately. The jump table is stored near an address pointed to by register A5. All JSR's into the jump table are of the form JSR x(A5) where x is some offset into the jump table. It is this offset x that the linker generates that we use as the method selector. As each new method name is encountered during the compilation of an object type definition, a very short procedure is generated. This procedure is referred to as the "selector proc". Its name is of the form TypeName$MethodName, such as Shape$Move. Note that the selector proc is not generated for method overrides, only when the method definition is first encountered. Methods by the same name in an unrelated branch of the hierarchy would have a selector proc, for example Employee$Move. The contents of the selector proc is simply a JSR to the actual method dispatching routine, called %_Method.

It is to the appropriate selector proc that all method calls are directed. The JSR instruction above would therefore be JSR Shape$Move. All selector procs are placed in another special segment, "%_SelProcs". All references to it are guaranteed to be through the jump table. The critical significance of this is that when the JSR is patched by the linker, the two-byte offset into the jump table is unique for that method name. The method dispatch routine examines those bytes and matches them against values stored in the method tables to determine what method is being called. Which brings us back to the format of the method tables.

Method Table Format

As mentioned above the method table for a particular object type appears at the end of the class info proc. The table is simply a list of pairs of references, one pair for each method implemented by this type. The first reference in each pair is to the selector proc and the second is to the actual method implementation. Each of these references are guaranteed to be across segments. Normally, when the linker is resolving a cross segment reference, it not only patches the offset bytes of the instruction, it also sets the bits in the instruction itself to make it A5 relative. For the method tables, there are no JSR's, just offsets that need to be patched. Fortunately there is a special bit (the A5-relative flag) in the reference record to tell the linker not to attempt to edit the word before the offset location.

Objects on the Heap and the New Routine

Objects are created using the New procedure. The compiler detects whether the parameter is an object type variable. It calls a quite different procedure than the normal New for pointer types. This procedure, %_OBNEW, allocates the data on the application heap. (Normal pointer New calls get data allocated on a special Pascal Heap.) %_OBNEW must also set the two byte class identifier field for the object. Like almost every other two byte field we've seen so far, this is an A5 offset into the jump table. This time the reference is to the class info proc of the class of the parameter to New. The actual calling sequence for New(aCircle) is:

 PEA    aCircle
 PEA    Circle's Class Info Proc + 2
 MOVE.W #size of instance,-(SP)

The "+ 2" for the class info proc is somewhat of a hack. The jump table entry for the class info proc is JMP x where x is the address of the class info proc. We don't want to execute the code there, we just want to look at the information in it. By bumping the pointer by two we are in effect creating a handle to the class info proc, where the master pointer is the address stored after the JMP instruction in the jump table. %_OBNEW calls a routine %_SetClassIndex that subtracts A5 from this "handle" and stuffs the result into the two byte type identifier field. When a method is called, %_Method adds A5 back to the two byte field of the object, thus reconstructing the handle to the class info proc.

Figure 2.

The Method Dispatch Routine

In Figures 2 and 3 we see how a typical method call works. As we saw before, the parameters of the method, if any, are pushed onto the stack followed by the handle to the object itself. We then do a JSR to the selector proc, in this case Shape$Rotate. Shape$Rotate, like all selector procs, is simply a JSR to %_Method, the dispatch routine. In the method dispatch routine we first grab the handle to the object from the stack. We then extract the class identifier bytes from the object header. Adding A5 to these bytes gives us a handle to Circle's class info proc. The method "selector" is the two offset bytes after the JSR instruction to the selector proc. We search through the method table in the class info proc for a match to this selector. Since Rotate is not overridden in Circle, we do not find a match in this table. We then find the class info proc of the superclass, namely that of Shape. We go through the same search for the method selector and this time we do find a match for Rotate. We then jump to the proper routine, Shape.Rotate.

Figure 3.

Type Checking

Previously I mentioned that if you use type coercion to do an assignment of one object type variable to another, a run time check would be generated. The check is to see if the type of the object being assigned is the same type or a descendant type of the variable on the left side of the assignment. This is the same check that is made when you call the Member function. The routine that does this is called %_OBCHK. It takes two parameters, a handle to the object and a pointer to the jump table entry of the class info proc for the class whose membership is being tested. %_OBCHK returns the object handle if the test succeeds and nil if it fails. It calls the routine boolean routine %_InObj to do the actual test.

The information presented thus far should be sufficient for someone to implement object-oriented features in their language. The following discussion of "Object Assembler" is an example of how we took another "language" and generated the same method table formats and so forth to create an object file compatible alternative to programming exclusively in Object Pascal.

Object Assembler

Despite the many advantages of using a higher level language, we wanted to be able to escape to assembly language when necessary to efficiently code-time critical parts of an application. Using the powerful macro language available with the MPW 68000 Assembler, I was able to write a set of macros that allows one to define a class, implement and call methods, and create new objects, all in 68000 assembly language.

For example, the Shape and Circle definitions we saw in Pascal would look like:

 (color,2), \
 (Erase), \

 ObjectDefCircle,Shape,   \

(The '\' character is required by the Assembler when continuing a line)

The ObjectDef macro actually generates the class info proc and selector procs as specified earlier. It also sets up data structures for allowing field accesses and method calls later in the code. A method is defined as follows:

 Erase: ProcMethOf Shape
 LINK   #0,A6
 MoveSelf A0
 MOVE.L (A0),A0
 PEA    bounds(A0)
 UNLK   A6
 MOVE.L (SP),(SP)+

The ProcMethOf macro (and the FuncMethOf macro) invoke another macro, ObjectWith, that allows field references like bounds(A0) to work properly. MoveSelf is a simple macro that gets SELF off of the stack. It assumes that you started the method with a LINK A6. The routine above loads SELF into A0, dereferences it, and pushes the bounds field onto the stack so that EraseRect can be called. After the Unlink, the stack is fixed up by stuffing the return address on top of the single parameter, SELF, and the method returns.

Method calls are made using the MethCall macro:

 MoveSelf -(SP)
 MethCall Draw,Shape

MethCall generates a JSR to the proper Selector proc for Draw. If the call was made from inside of a method of Shape or a subclass of Shape, the parameter Shape could have been omitted. The other important macros are Inherited and NewObject:

 MoveSelf -(SP)


Inherited behaves as in Object Pascal. NewObject requires a memory reference parameter and a type name. The handle of the new object is stored into the memory location specified by the parameter.

A full description of the macros available is contained in both the MPW Assembler Manual and the MacApp Reference Guide. Since these macros generate the same code that Object Pascal does, any code written in "Object Assembly" language can be linked with MacApp object files. In fact, specific methods in Object Pascal can be declared external and coded in assembly language using the macros. In addition, the assembled files can be run through the Optimizer described in the next section.

The Optimizer and the New Run Time Environment

In running sample applications written in MacApp, the performance has been quite good, despite the fact that every method call must go through the method dispatch mechanism before being executed. However, we realized that some significant optimizations were possible once the entire object type hierarchy was known. We have developed an optimizer program that processes the object files just before they are linked. It builds an internal representation of the entire object type hierarchy and proceeds to analyze it for potential optimizations.

Treatment of Monomorphic Methods

The most significant savings arises from being able to identify those methods that are implemented in only one object type, in other words, methods that are never overridden. Since these "monomorphic" methods have only one implementation, there is no need for a call to them to go through method dispatching. The Optimizer reroutes calls to these methods to jump directly to the method. Recall that originally the call was to a "selector proc" that in turn called the method dispatch routine. Not only does this increase the speed dramatically for these method calls but the space required is reduced. There no longer needs to be a selector proc nor the jump table entry that pointed to it. Also the entry in the method table for that method can be eliminated.

We have found that approximately 75% of the methods defined in MacApp applications are monomorphic. These include many internal methods of the MacApp classes themselves. For any "leaf" object type, one that has no descendants, any new method it defines will be monomorphic.

Transposition of the Method Tables for Polymorphic Methods

For the remaining "polymorphic" methods, those methods that are implemented by more than one class, the now reduced method tables are transposed. That is, where before each method table was a list of the methods implemented by a particular class, now each table is a list of classes that implement a particular method. This results in more tables of shorter length. Previously the method tables were stored in the class info procs. Now the tables are stored in the selector procs. In fact, they are stored immediately after the JSR instruction that jumps to the method dispatch routine. Thus the address of the method table is on the top of the stack when the dispatch routine is entered.

The form of this new method table is a list of two byte pairs. The first element in the pair is a class number that is generated by the optimizer. The second element is a reference to the actual implementation of the method, which the linker has patched with an A5 offset into the jump table. (This element is unchanged from the previous method table format.) The class number of a particular class is always greater than that of its superclass. The entries in the method table are sorted in descending order of class number. By numbering the classes in this way and keeping a separate table of superclasses, the method dispatch routine can properly search the method table. A Class number is always an even positive integer, making accesses to the superclass table simpler. A handle to the superclass table is stored in a low memory location.

The New Object Header

In the optimized run time environment objects have a different two byte class identifier than before. The A5 offset to the jump table entry of the class info proc is replaced by the class number that was generated by the optimizer. The class info proc no longer contains the method tables or a reference to the superclass. In fact it has just a single two byte entry, namely the class number. The calling sequence to %_OBNEW is the same as before, but the Optimizer actually redirects the %_SetClassIndex call in %_OBNEW to instead call %_OptSetCI. %_OptSetCI gets the class number from the class info proc and stuffs it into the object header.

The New Method Dispatch Routine

The new method table format requires a new method dispatching scheme. In fact, this is the scheme used by the method dispatch routine in the 128K ROM. The routine is also available in the libraries for 64K ROM machines.

A somewhat complicated algorithm is used to check only those methods that belong to the hierarchy of the object processing the method. For example, following the example in Figures 4 and 5, if aShape.Rotate was called and aShape was currently a Circle object the search would proceed as follows. First check to see if the most recent search was for a Circle by checking the cache at the beginning of the table. If we get a match, we jump immediately to the method (via the cached jump table offset). If we don't get a match, then check each entry in the table until we do get a match OR we arrive at a class number that is less than the current number. Since the current number is 8, we will skip the 10 (square.rotate) and stop at 6 (triangle.rotate). If we match, we jump to the method. It isn't a match, so now we look up Circle's superclass in the superclass table. The superclass is 4 (shape), and we proceed as before searching for a match or a number less than the current number (now 4). The next entry is a 4 so we match. Before jumping to the method, we stuff the original class number 8 in the class number cache and the jump table offset for shape.rotate in the method cache. If the next call to Rotate is for a circle object we'll get an immediate hit in the cache.

Figure 4.

The Optimizer also redirects the %_InObj routine to %_OptInObj. This is the boolean function that tests object membership in a particular class. The new routine uses the class number of the object and the superclass table to test the object.

Figure 5.

Future Optimizations

Other optimizations are possible when the entire class hierarchy is known. Say a variable aCircle is declared to be of type Circle and furthermore that there is no descendant of Circle defined. Then any method call that aCircle makes can be resolved before run time. This is because any object type variable can only reference an object whose type is the declared class or a descendant of that class. Since Circle has no descendants we know that aCircle must be a Circle object. Therefore we know that if Draw is invoked, we should call Circle.Draw and if Erase is invoked we call Shape.Erase (since Circle did not implement Erase) and so on. This is a little more difficult to implement and has not yet been put into the Optimizer.

Supporting the MacApp Debugger

One of the most appealing features of MacApp is its powerful debugger. The debugger is independent of the object-orientedness of MacApp. When an application is compiled with debugging flags turned on, the MacApp debugger is installed in a separate window on the screen. At any time while running the application you can go into the debugger and look at the stack or see a recent history of procedure calls. You can examine objects on the heap and even set up intentional error conditions such as nil object handles. You can set break points at specific methods and you can step through the code a method at a time. There are many other useful features.

To support the debugger, the Object Pascal compiler inserts a call to a special routine called BP at the beginning of every routine. It also inserts a call to EP at the end of every routine and a call to EX for Exits or GOTO's that jump out of a routine. In addition, the name of each routine is appended after the code of the routine. BP, EP, and EX are implemented in the UTrace unit that comes with MacApp. If you want to support the MacApp debugger, you should look at how it works and see if you can tailor it to your particular language.

The C+- Language

We at Apple are anxious to see more compilers support object-oriented concepts and be able to make use of the several man-years of effort that went into developing MacApp. In particular we recognize the popularity of the C language and the proliferation of C compilers available on the Macintosh. Since the C compiler that comes with MPW was done by a third party and they were under considerable time pressure to deliver as it was, we were not able to get object-oriented features put into it.

In the meantime, however, we have come up with a recommended specification for an object-oriented C. It is based on the C++ language from Bell Labs. It is essentially a subset of C++ that includes just those features necessary to support MacApp. We call this language C+-. The specification is available as a technical report from the Apple Library. Of course, if you want to support the full C++ specification, you will still be compatible with C+-.

How to Get Help

If you do decide to use some of the information presented in this article in order to be able to use MacApp, contact Harvey Alcabes at Apple. Harvey is the Product Manager for MacApp and is coordinating third party efforts to add objects to their languages. He can advise you on any licensing requirements for distributing translated versions of MacApp and so forth.


Object Pascal Report, by Larry Tesler; Feb 22, 1985, published in Structured Language World, Volume 9, No 3.

The MacApp Programmers Reference Guide

C+- Specification, by Larry Tesler; May 26, 1986

Apple Technical Report #2

Object-Oriented Programming for the Macintosh, by Kurt Schmucker; 1986; Published by Hayden Press


Community Search:
MacTech Search:

Software Updates via MacUpdate

Acorn 5.6.1 - Bitmap image editor.
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Dash 3.4.3 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
Microsoft Remote Desktop 8.0.37 - Connec...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
Macs Fan Control - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
MacFamilyTree 8.1.3 - Create and explore...
MacFamilyTree gives genealogy a facelift: modern, interactive, convenient and fast. Explore your family tree and your family history in a way generations of chroniclers before you would have loved.... Read more
Boom 2 1.5.2 - $14.99
Boom 2 is a system-wide volume booster and equalizer app that is designed especially for OS X 10.10 Yosemite. It comes with a smart interface, self-calibrates itself according to your Mac, offers... Read more
Macs Fan Control - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
Boom 2 1.5.2 - $14.99
Boom 2 is a system-wide volume booster and equalizer app that is designed especially for OS X 10.10 Yosemite. It comes with a smart interface, self-calibrates itself according to your Mac, offers... Read more
MacFamilyTree 8.1.3 - Create and explore...
MacFamilyTree gives genealogy a facelift: modern, interactive, convenient and fast. Explore your family tree and your family history in a way generations of chroniclers before you would have loved.... Read more
WhiteCap 6.6 - Visual plug-in for iTunes...
WhiteCap is a sleek and sophisticated music visualizer and screensaver that features futuristic, wireframe mesh visuals with dynamic backgrounds and colors. WhiteCap contains thousands of visual... Read more

Stickman Surfer rides in with the tide t...
Stickson is back and this time he's taken up yet another extreme sport - surfing. Stickman Surfer is out this Thursday on both iOS and Android, so if you've been following the other Stickman adventures, you might be interested in picking this one... | Read more »
Z-Exemplar (Games)
Z-Exemplar 1.4 Device: iOS Universal Category: Games Price: $3.99, Version: 1.4 (iTunes) Description: | Read more »
5 dastardly difficult roguelikes like th...
Edmund McMillen's popular roguelike creation The Binding of Isaac: Rebirth has finally crawled onto mobile devices. It's a grotesque dual-stick shooter that tosses you into an endless, procedurally generated basement as you, the pitiable Isaac,... | Read more »
Last week on PocketGamer
Welcome to a weekly feature looking back on the past seven days of coverage on our sister website, PocketGamer. It’s taken a while for 2017 to really get going, at least when it comes to the world of portable gaming. Thank goodness, then, for... | Read more »
ROME: Total War - Barbarian Invasion set...
To the delight of mobile strategy fans, Feral Interactive released ROME: Total War just a few months ago. Now the game's expansion, Barbarian Invasion is marching onto iPads as a standalone release. [Read more] | Read more »
Yuri (Games)
Yuri 1.0 Device: iOS iPhone Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: It's night. Yuri opens his eyes. He wakes up in a strange forest.The small, courageous explorer rides on his bed on casters in this... | Read more »
Space schmup Xenoraid launches on the Ap...
10Tons Xenoraid is out today on the App Store, bringing some high-speed space action to your mobile gadgets just in time for the weekend. The company's last premium title, another sci-fi game titled Neon Chrome, did quite well for itself, so... | Read more »
Star Wars: Force Arena Beginner's G...
Star Wars: Force Arena joined the populous ranks of Star Wars games on mobile today. It's a two-lane MOBA starring many familiar faces from George Lucas's famed sci-fi franchise. As with most games of this nature, Force Arena can be a little obtuse... | Read more »
Mysterium: The Board Game (Games)
Mysterium: The Board Game 1.0 Device: iOS Universal Category: Games Price: $6.99, Version: 1.0 (iTunes) Description: The official adaptation of the famous board game Mysterium! | Read more »
Sonny (Games)
Sonny 1.0.4 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.4 (iTunes) Description: Reimagined for iOS, cult-hit RPG Sonny brings challenging turn-based combat that requires strategy and mastery of each new skill to... | Read more »

Price Scanner via

Back in stock: Apple refurbished 13-inch Reti...
Apple has Certified Refurbished 2015 13″ Retina MacBook Pros available for up to $360 off original MSRP, starting at $1099. An Apple one-year warranty is included with each model, and shipping is... Read more
CalcTape for macOS 1.2 Adding Machine App for...
schoettler Software has announced CalcTape 1.2, an update to their desktop calculator for macOS. When it comes to adding long columns of numbers, doing complex calculations or playing around with... Read more
New MacBooks And MacBook Pros WIth Kaby Lake...
Digitimes’ Joseph Tsai cites a Chinese-language Economic Daily News (EDN) report that unnamed market watchers are predicting Apple MacBook shipments to grow 10 percent in 2017, and projecting 15... Read more
New 2016 13-inch MacBook Pros on sale for up...
B&H Photo has the new 2016 13″ MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.9GHz/512GB Touch Bar MacBook Pro... Read more
New 15-inch Touch Bar MacBook Pros in stock a...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more
Opera Announces Neon Concept Browser For Mac
Opera is inviting users to get a glimpse of what Opera for computers could become with its Opera Neon browser concept. Each Opera Neon feature is described as “an alternate reality” for the Opera... Read more
Tellini Releases TabView 3.0 Missing Tool fo...
Tellini has announced the release of TabView 3.0. TabView has been the first macOS viewer for PowerTab tablatures. PowerTab is a well-known and widely adopted tablature editor for Windows systems and... Read more
13-inch 1.6GHz/128GB MacBook Air on sale for... has the 1.6GHz/128GB 13″ MacBook Air on sale for $130 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (MMGF2LL/A): $869.99 $130 off MSRP Their price is the lowest... Read more
12-inch 32GB Space Gray iPad Pro on sale for...
B&H Photo has 12″ Space Gray 32GB WiFi Apple iPad Pros on sale for $55 off MSRP including free shipping. B&H charges sales tax in NY only: - 12″ Space Gray 32GB WiFi iPad Pro: $744.44 $55 off... Read more
9-inch 32GB Space Gray iPad Pro on sale for $...
B&H Photo has the 9.7″ 32GB Space Gray Apple iPad Pro on sale for $549 for a limited time. Shipping is free, and B&H charges NY sales tax only. Read more

Jobs Board

*Apple* Retail - Multiple Positions (Multi-L...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* & PC Desktop Support Technician...
Apple & PC Desktop Support Technician job in Stamford, CT We have immediate job openings for several Desktop Support Technicians with one of our most well-known Read more
*Apple* macOS Systems Integration Administra...
…most exceptional support available in the industry. SCI is seeking an Junior Apple macOS systems integration administrator that will be responsible for providing Read more
*Apple* Premier Retailer - Service Technicia...
DescriptionSimply Mac is the largest premier retailer for Apple products and solutions. At Simply Mac we are all Apple , all the time. Same products. Same prices. Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.