{"id":335,"date":"2023-02-05T21:46:59","date_gmt":"2023-02-06T05:46:59","guid":{"rendered":"http:\/\/eschatologist.net\/blog\/?p=335"},"modified":"2023-02-06T11:12:48","modified_gmt":"2023-02-06T19:12:48","slug":"lisa-source-code-clascal-evolution","status":"publish","type":"post","link":"https:\/\/eschatologist.net\/blog\/?p=335","title":{"rendered":"Lisa Source Code: Clascal Evolution"},"content":{"rendered":"<p>Here\u2019s another interesting thing I\u2019ve learned about Clascal and Object Pascal: It went through <em>exactly the same<\/em> evolution from combining object allocation &amp; initialization to separating them <em>that Objective-C did<\/em> a decade later!<\/p>\n<p>In early 1983 Clascal, classes were expected to implement a <code>New<\/code> method as a function returning that type, taking zero or more parameters, and returning an instance of that type by assigning to <code>SELF<\/code>\u2014sound familiar? This was always implemented as a \u201cstandard\u201d method (one <em>without<\/em> dynamic dispatch) so you couldn\u2019t call the wrong one. A cited advantage of this is that it would prevent use of the standard Pascal built-in <code>New()<\/code> within methods\u2014which I suspect turned out not to be what people wanted, since it would prevent interoperability.<\/p>\n<p>A class could also choose to implement an <code>OVERRIDE<\/code> of the also-included <code>Free<\/code> method to release any resources it had acquired, like file handles or other object instances. And each overridden <code>Free<\/code> method had to include <code>SUPERSELF.Free;<\/code> after it did so in order to ensure that its superclass would also release any resources it had acquired.<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\nINTERFACE\n\n  TYPE\n\n    Object = SUBCLASS OF NIL\n      FUNCTION New: Object; STANDARD;\n      PROCEDURE Free; DEFAULT;\n    END;\n\n    Person = SUBCLASS OF Object\n      name: String;\n      FUNCTION New(name: String): Person; STANDARD;\n      PROCEDURE Free; OVERRIDE;\n    END;\n\n  VAR\n\n    gHeap: Heap;\n\nIMPLEMENTATION\n\n  METHODS OF Object;\n\n    FUNCTION New{: Object}\n    BEGIN\n      SELF := Object(HAllocate(gHeap, Size(THISCLASS)));\n    END;\n\n    PROCEDURE Free\n    BEGIN\n      HFree(Handle(SELF));\n    END;\n\n  END;\n\n  METHODS OF Person;\n\n    FUNCTION New{(theName: String): Person;}\n    BEGIN\n      SELF := Person(HAllocate(gHeap, Size(THISCLASS)));\n      IF SELF &amp;lt;&amp;gt; NIL THEN\n        name := theName.Clone;\n    END;\n\n    PROCEDURE Free\n    BEGIN\n      name.Free;\n      SUPERSELF.Free;\n    END;\n  END;\n<\/pre>\n<p>By mid-1984, Clascal changed this to the <code>CREATE<\/code> method, which was declared as <code>ABSTRACT<\/code> in the base class. Note that it still doesn\u2019t use the standard Pascal built-in <code>New()<\/code> to create object instances. However, it takes a potentially-already-initialized object so that it\u2019s easier for a subclass to call through to its superclass for initialization, since <code>CREATE<\/code> is still not a dynamically-dispatched method. Also, instead of referencing a global variable for a heap zone in which to perform allocation, it takes the heap zone, providing some amount of locality-of-reference that may be helpful to the VM system.<\/p>\n<p>There was also a change in style to prefix class names with <code>T<\/code>.<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\nINTERFACE\n\n  TYPE\n\n    TObject = SUBCLASS OF NIL\n      FUNCTION CREATE(object: TObject; heap: THeap): TObject; ABSTRACT;\n      PROCEDURE Free; DEFAULT;\n    END;\n\n    TPerson = SUBCLASS OF TObject\n      name: TString;\n      FUNCTION CREATE(theName: TString; object: TObject; heap: THeap): TPerson; STANDARD;\n      PROCEDURE Free; OVERRIDE;\n    END;\n\nIMPLEMENTATION\n\n  METHODS OF TObject;\n\n    PROCEDURE Free\n    BEGIN\n      FreeObject(SELF);\n    END;\n\n  END;\n\n  METHODS OF TPerson;\n\n    FUNCTION CREATE{(theName: TString; object: TObject; heap: THeap): TPerson;}\n    BEGIN\n      IF object = NIL\n        object := NewObject(heap, THISCLASS);\n      SELF := TPerson(object);\n      WITH SELF DO\n        name := theName.Clone(heap);\n    END;\n\n    PROCEDURE Free\n    BEGIN\n      name.Free;\n      SUPERSELF.Free;\n    END;\n  END;\n<\/pre>\n<p>This is starting to look even more familiar to Objective-C developers, isn\u2019t it?<\/p>\n<p>The final form of the language, Object Pascal, actually backed off on the Smalltalk terminology a little bit and renamed \u201cclasses\u201d to \u201cobjects\u201d and went so far as to introduce an <code>OBJECT<\/code> keyword used for defining a class. It also changed <code>SUPERSELF.<\/code> to <code>INHERITED<\/code>\u2014yes, with whitespace instead of a dot!\u2014as, again, developers new to OOP found \u201csuperclass\u201d confusing.<\/p>\n<p>Object Pascal also, at long last, adopted the standard Pascal built-in <code>New()<\/code> to perform object allocation (along with its counterpart <code>Free()<\/code> for deallocation) directly instead of introducing a separate function for it, since the intent can be inferred by the compiler from the type system. It also removed the need to use the <code>METHODS OF<\/code> construct to add methods, instead just prefixing the method with the class name and a period.<\/p>\n<p>The final major change from Clascal to Object Pascal is that, with <code>New()<\/code> used for object allocation, the <code>CREATE<\/code> methods were changed into <em>initialization methods<\/em> instead since they just <em>initialize<\/em> the object after its allocation. They were also made procedures rather than functions returning values, and since the standard Pascal built-in <code>New()<\/code> is being used they no longer take a potentially-already-allocated object nor do they take a heap zone in which to perform the allocation. The convention is that for a class <code>TFoo<\/code> the initialization method has the form <code>IFoo<\/code>.<\/p>\n<p>There was also another stylistic change, prepending field names with <code>f<\/code> to make them easy to distinguish from zero-argument function methods at a glance.<\/p>\n<p>There was also a switch from not including the parameter list in the <code>IMPLEMENTATION<\/code> section to including it directly instead of in a comment.<\/p>\n<p>Here\u2019s what that looks like:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\nINTERFACE\n\n  TYPE\n\n    TObject = OBJECT\n      PROCEDURE IObject; ABSTRACT;\n      PROCEDURE Free; DEFAULT;\n    END;\n\n    TPerson = OBJECT(TObject)\n      fName: TString;\n      PROCEDURE IPerson(theName: TString); STANDARD;\n      PROCEDURE Free; OVERRIDE;\n    END;\n\nIMPLEMENTATION\n\n    PROCEDURE TObject.Free\n    BEGIN\n      Free(SELF);\n    END;\n\n    PROCEDURE TPerson.IPerson(theName: TString)\n    BEGIN\n      fName := theName.Clone();\n    END;\n\n    PROCEDURE TPerson.Free\n    BEGIN\n      fName.Free;\n      INHERITED Free;\n    END;\n<\/pre>\n<p>Based on the documentation I\u2019ve read, it wouldn\u2019t surprise me if the <em>only<\/em> reason initialization methods aren\u2019t consistently named <code>Initialize<\/code> is that the language design didn\u2019t support an <code>OVERRIDE<\/code> of a method using a different parameter list.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here\u2019s another interesting thing I\u2019ve learned about Clascal and Object Pascal: It went through exactly the same evolution from combining object allocation &amp; initialization to separating them that Objective-C did a decade later! In early 1983 Clascal, classes were expected to implement a New method as a function returning that type, taking zero or more&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3],"tags":[155,4,123,69,156],"class_list":["post-335","post","type-post","status-publish","format-standard","hentry","category-technology","tag-lisa","tag-mac","tag-oop","tag-pascal","tag-retrocomputing"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p74loH-5p","_links":{"self":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/335","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=335"}],"version-history":[{"count":2,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/335\/revisions"}],"predecessor-version":[{"id":337,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/335\/revisions\/337"}],"wp:attachment":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=335"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=335"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=335"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}