Recent

Author Topic: Modula, Oberon or Ada  (Read 12627 times)

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1106
Re: Modula, Oberon or Ada
« Reply #15 on: December 19, 2019, 09:02:26 am »
For those who have already used Modula, Oberon or Ada.
Do those programming languages have any interesting features that Free Pascal currently doesn't?
From memory, Modula2 was basically an incompatible continuation of Pascal, and had
  • A better block structure. Omits begin for all non procedure/function blocks, and makes END mandatory (also for one line blocks).
Wouldn't this make Modula-2 even more verbose than Pascal?

Quote
  • inner modules (nested units), which more or less served as a information hiding building block within a module/unit.
Is this still necessary when most people use an IDE [Lazarus] to program?

Quote
[/li]
[li] Opague pointer type. You could declare something in the interface as (geneneric) pointer, and redefine the pointer as a pointer to some record in the implementation. Great for handle types.[/li][/list]
Quote
  • FOR had a BY clause.
A controversial feature, but I think this could be a good idea.
However, I must add that I'll rarely need it...
Quote
  • Some interesting runtime library concepts that are however dated now 
    •         textwindowing unit, more than Crt, less than FV
    •         a cooperative multitasking unit
Quote
  • case sensitivity. Not an advantage IMHO
I agree.
Quote
  •   unsigned types by default (jury is still out on this one too)
Quote
  • End 'procedurename'  at the end of a block. A mixed blessing, made refactoring code more complicated, but "missing end"  kind of errors were less confusing. I think a distinct procedural END is a good thing, but recycling the procedurename a bridge too far.
Is this still necessary when most people use an IDE [Lazarus] to program?

Quote
But above all I really missed a decent way of handling strings. M2 string handling was too manual for my taste. I changed to FPC in 1998, but kept maintaining the old codebases till 2001-2003, when I move to win2000, first at work, later at home, and the dos binaries started very slow under windows 2000, so I ported the code to FPC.

Oberon was a minimalistic OOP follow up to Modula2, and IMHO too limited to function.

Ada's story is different and more distinct from the real Wirthian languages.  Best read up in wikipedia or so.

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1106
Re: Modula, Oberon or Ada
« Reply #16 on: December 19, 2019, 09:13:03 am »
For those who have already used Modula, Oberon or Ada.
Do those programming languages have any interesting features that Free Pascal currently doesn't?
In the case of Modula-2, coroutines. A coroutine is in-thread, you can transfer control from one coroutine to another at any point and then later revert to where you left off. At least some implementations also had IOTransfer() which could be hooked onto a physical interrupt, and those together are enough to write a scheduler.
Isn't this already solved by threads?

Quote
The other obvious thing was IF THEN END and IF THEN ELSE END etc. which, while not quite as elegant as Pascal syntax, did eliminate the dangling else issue.
Not so elegant for Pascal, but still a clean feature for another languages.

Quote
Unfortunately ALGOL's inline conditional a := IF b THEN c ELSE d;, which I consider to be an unfortunate omission from Pascal etc., is at least visually inconsistent with this.
Too ugly for Pascal, but an internal IIF() would be fine instead of external big IfThen().

Quote
Modula-2 reserves braces { } to delimit a set of elements, and insists on (* *) (which were originally digraphs for braces) for comments. It also allows both single and double quotes for strings so that you could write e.g. "Wirth's Modula-2" (in some other stuff I've done I've allowed quote format to be extended and for quoted strings to carry additional info around with them, so that e.g. / / can be used to delimit a string to be treated as a regex when comparisons are involved, or as a backref if encountered as an rvalue.
I agree that this point could more coherent.

Quote
There were undoubtedly other things which were standardised as part of the language rather than being de-facto facilities defined by the implementation. LOOP EXIT END springs to mind.

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1106
Re: Modula, Oberon or Ada
« Reply #17 on: December 19, 2019, 09:23:39 am »
"History
In the 1970s, the US Department of Defense (DoD) was concerned by the number of different programming languages being used for its embedded computer system projects, many of which were obsolete or hardware-dependent, and none of which supported safe modular programming. In 1975, a working group, the High Order Language Working Group (HOLWG), was formed with the intent to reduce this number by finding or creating a programming language generally suitable for the department's and the UK Ministry of Defence requirements.
After many iterations beginning with an original Straw man proposal the eventual programming language was named Ada. The total number of high-level programming languages in use for such projects fell from over 450 in 1983 to 37 by 1996."
https://en.wikipedia.org/wiki/Ada_(programming_language)

Oberon was a minimalistic OOP follow up to Modula2, and IMHO too limited to function.
Agreed, from what little I know of it. I'd add that as I understand it there's also an Oberon GUI environment which still has its enthusiasts, but the real successor to M2 was M3 etc.
Ada's story is different and more distinct from the real Wirthian languages.  Best read up in wikipedia or so.
Agreed. Also Ada mandated that there could not be any language subsets and that a substantial "workbench" should accompany the compiler, and it was those that made it sufficiently large that it didn't fit onto an affordable PC.
As I read, Ada was really a different story.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Modula, Oberon or Ada
« Reply #18 on: December 19, 2019, 09:31:13 am »
In the case of Modula-2, coroutines. A coroutine is in-thread, you can transfer control from one coroutine to another at any point and then later revert to where you left off. At least some implementations also had IOTransfer() which could be hooked onto a physical interrupt, and those together are enough to write a scheduler.
Isn't this already solved by threads?

No. A thread is an operating system construct which is largely there to distribute processing over multiple processors.

A coroutine is entirely an in-language thing.

You can implement thread/process management on top of coroutines, but not the other way round. I'm afraid that I don't really have any good real-world examples that I can draw on, but I think that to some extent it would be fair to say that the rest of the World has rediscovered them as "continuations": functions that can be exited but preserve all their state. Think about having multiple state machines, each with state entirely compartmentalised into a separate coroutine.

I can't remember the exact Modula-2 semantics, but I think that in effect you ended up with a "cactus stack" so a coroutine had to be careful with referring to variables in an "older" function which might have disappeared. I can't remember whether IOTRANSFER() was standardised but the idea was that it could be hooked onto an interrupt, however there was controversy over its implementation (specifically, how well it should accommodate interrupt priorities).

In terms of information hiding etc. you can do as well- or better- with OO techniques. But Modula-2 was intended to be able to write an OS, and coroutines are the abstraction that allows context to be changed (specifically, CPU context: I don't think that Wirth had really considered large-scale memory context changing which these days is implemented by page tables).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1106
Re: Modula, Oberon or Ada
« Reply #19 on: December 19, 2019, 09:44:06 am »
Yes, but not just modules, some other functionality (like open array parameters) are now already in FPC too.

Depending on compiler, the interface of the units (definitions of the modules in M2 talk) are sometimes stored tokenized. But afaik not as complete symbolic streams as TP, Delphi and FPC do.

I didn't feel as strong about the separation of files, but I've mostly used during the nineties and always used IDEs, and used joe only for small potato programming (and even joe can open multiple files). With more grown up IDEs like Lazarus that have syntactic source navigation (codetools), it is even less pronounced
Quote
The M2 compilers that I knew were spending more time in parsing DEF files than in actually compiling code. That is a C disease, but in M2 it was unnecessary.
Interesting.

Quote
Going back to TP (for a brief while before migrating to FPC) felt as a blessing.
Quote
Another big difference ( and one I like to see in FPC someday) is more control over what identifiers are imported and exported (un)qualified.

This both in the module definition, you can e.g. say that symbol X from unit Y is ALWAYS exported qualified (so you must always write Y.X to use it. Imagine that X is a very common word, like "write" or "seek", and you see the point)

.. as in the module/program importing the module. So a program can chose to import all symbols of module Y qualified only. (so you must always use Y.).  You can also import some symbols unqualified (so that they are accessible without modulename prefix)

What I didn't like is that there is no equivalent of USES to mass import symbols unqualified.

One of the reasons to implement it in Pascal is because afaik some similar functionality is in the Extended Pascal (1990) standard.
Could you elaborate a bit more?
Does Free Pascal have a weak control of imported and exported identifiers?

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1106
Re: Modula, Oberon or Ada
« Reply #20 on: December 19, 2019, 10:04:57 am »
Just to remind I found this project is the Oberon equivalent of Free Pascal: https://github.com/kekcleader/FreeOberon It's even listed by the FSF: https://directory.fsf.org/wiki/Free_Oberon
There's also apparently people working on the operating system aspect of Oberon.
I don't know to what extent these are praiseworthy endeavours, unless they're also actively being used to teach newcomers to the profession (which for a long time was the objective of MINIX, as one particular example). Oberon (the language) dates back to when people looked at Ada and considered it too big and complex, but by today's standards 1980s Ada is probably rather svelte and feature-deficient.
As a result for a lack of job offers, universities are restricting or even dropping practical disciplines of Compiler and Operational System building.
Changing Compiler Building for only Parsers and Minix for Oberon might be examples of that.

News books are trying to catch up this tendency:
"...book offers a one semester introduction into compiler construction..."
Introduction to Compilers and Language Design, Douglas Thain, 2019, 246pp.
https://www.amazon.com/Introduction-Compilers-Language-Design-Douglas/dp/0359142834/

And we also must consider that current students don't have all that math from the 1960's and 1970's any more...

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Modula, Oberon or Ada
« Reply #21 on: December 19, 2019, 10:23:18 am »
> "...book offers a one semester introduction into compiler construction..."

etc. Might not actually be such a bad thing. Teach them the basics, and then if they need to know more they can make the pilgrimage to an established teacher and study at his feet.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Modula, Oberon or Ada
« Reply #22 on: December 19, 2019, 10:39:16 am »
    Quote

    • A better block structure. Omits begin for all non procedure/function blocks, and makes END mandatory (also for one line blocks).
    Wouldn't this make Modula-2 even more verbose than Pascal?

    No, less. You lose way more begins than you gain ends.   An "if then else" with begin..end blocks would keep just one end at the end, and you only lose a short end for every place where there is a single clause (usually after an IF). 

    But the nice part is that if you want to expand any block including onelines, you just can start typing, you don't have to insert a block first.   

    C programmers have a tendency to always use {}, and an M2 block is 3 or 4 characters (if you count the semicolon after END, C has no semicolon after }), so it is pretty close or the same (if you count e.g. the extra linefeed after the first { too if that is your style), but I like it more visually.

    [/list]
    Code: Pascal  [Select][+][-]
    1.    IF condition THEN
    2.         statement1;
    3.         statement2
    4.    ELSE
    5.         statement3;
    6.         statement4
    7.         END;
    8.  

      And I liked it.

    Quote
    Quote
    • inner modules (nested units), which more or less served as a information hiding building block within a module/unit.
    Is this still necessary when most people use an IDE [Lazarus] to program?

    One can argue if it was ever necessary, but the IDE doesn't change much. Using an IDE hasn't obsoleted other pure information hiding constructs as "private" either.
    Quote
    Quote
    • FOR had a BY clause.
    A controversial feature, but I think this could be a good idea.
    However, I must add that I'll rarely need it...

    I agree. I mentioned it for completeness, not because I'm a strong proponent of the feature.

    Quote
    Quote
    • End 'procedurename'  at the end of a block. A mixed blessing, made refactoring code more complicated, but "missing end"  kind of errors were less confusing. I think a distinct procedural END is a good thing, but recycling the procedurename a bridge too far.
    Is this still necessary when most people use an IDE [Lazarus] to program?

    IDE/Lazarus has no influence. What might make it less needed is that the use of OO extensions make nested procedures not as common as they were. Still it improved the error handling in the case of missing ENDs, and narrowed its scope.

    Pascal needs this harder than M2 even, because pascal accepts

    [/list]
    Code: [Select]
        begin
            begin
            end;
        end;

    Which means that when you forget the END in some nested procedure, the outer procedures might be interpreted as such nested blocks, and the error will be on the next function or procedure line.

    M2 suffers from this less, since BEGIN is only used for the procedure block. It would halt with an error on the first begin if it didn't have the end 'xx'  extension.
     
    I think IDE is something that makes this feature (and other forms of END disambiguation, BASIC style) easier because so many blocks are inserted by the IDE.

    I used to have the stance that doing it at procedure ends is a good first order limitation of the scope, and BASIC was overkill.  Nowadays I'm less sure. Maybe if I made a language myself I'd terminate some blocks (FOR, WHILE) too with the keyword (END FOR END WHILE)

    As for coroutines, the examples that I have seen were mostly for background tasks, cooperative multitasking style. Afaik the Topspeed compiler came with a traffic light control example. But maybe Mark is right, and should I revisit the feature with newly gained knowledge of continuations.
    « Last Edit: December 19, 2019, 10:41:52 am by marcov »

    valdir.marcos

    • Hero Member
    • *****
    • Posts: 1106
    Re: Modula, Oberon or Ada
    « Reply #23 on: December 19, 2019, 11:17:59 am »
    In the case of Modula-2, coroutines. A coroutine is in-thread, you can transfer control from one coroutine to another at any point and then later revert to where you left off. At least some implementations also had IOTransfer() which could be hooked onto a physical interrupt, and those together are enough to write a scheduler.
    Isn't this already solved by threads?
    No. A thread is an operating system construct which is largely there to distribute processing over multiple processors.

    A coroutine is entirely an in-language thing.

    You can implement thread/process management on top of coroutines, but not the other way round. I'm afraid that I don't really have any good real-world examples that I can draw on, but I think that to some extent it would be fair to say that the rest of the World has rediscovered them as "continuations": functions that can be exited but preserve all their state. Think about having multiple state machines, each with state entirely compartmentalised into a separate coroutine.

    I can't remember the exact Modula-2 semantics, but I think that in effect you ended up with a "cactus stack" so a coroutine had to be careful with referring to variables in an "older" function which might have disappeared. I can't remember whether IOTRANSFER() was standardised but the idea was that it could be hooked onto an interrupt, however there was controversy over its implementation (specifically, how well it should accommodate interrupt priorities).

    In terms of information hiding etc. you can do as well- or better- with OO techniques. But Modula-2 was intended to be able to write an OS, and coroutines are the abstraction that allows context to be changed (specifically, CPU context: I don't think that Wirth had really considered large-scale memory context changing which these days is implemented by page tables).
    As for coroutines, the examples that I have seen were mostly for background tasks, cooperative multitasking style. Afaik the Topspeed compiler came with a traffic light control example. But maybe Mark is right, and should I revisit the feature with newly gained knowledge of continuations.
    I did understand that co-routines is different from thread, but I could not guess how to use it..
    I just remember the "prepare" database command that forces a database command to stay in database server memory to be used recurrently as long as the connection remains active.
    For Lazarus, my idea of co-routines would be to prepare a report in background (something that I currently use a thread):
    Code: Pascal  [Select][+][-]
    1. begin
    2.   // FortesReport
    3.   frmRelatorio.RLReport1.Prepare;
    4.   frmRelatorio.RLPDFFilter1.FilterPages(frmRelatorio.RLReport1.Pages);
    5.   frmRelatorio.RLReport1.SaveToFile('Relatorio.pdf');
    6. end;

    440bx

    • Hero Member
    • *****
    • Posts: 3944
    Re: Modula, Oberon or Ada
    « Reply #24 on: December 19, 2019, 11:24:59 am »
    ... C has no semicolon after }
    and it would be syntactically incorrect to have one since in C a semicolon is a statement terminator (not a separator.)  It's really unfortunate that Pascal has statement separators instead of terminators.

    Code: Pascal  [Select][+][-]
    1.    IF condition THEN
    2.         statement1;
    3.         statement2
    4.    ELSE
    5.         statement3;
    6.         statement4
    7.     END;
    8.  

     And I liked it.
    I like it too because that way there is no "else" ambiguity, i.e, anything between IF and END belongs to that IF. It also eliminates the necessity for "compound statement" constructs, begin/end pairs in Pascal and { } in C. Another thing I like about it is, it provides less opportunities for some programmers to indulge in incorrect formatting and claim it's a matter of "style". ;)  Without begin/end pairs, "else begin" (on the same line) are gone! :)

    Pascal needs this harder than M2 even, because pascal accepts

    Code: [Select]
        begin
            begin
            end;
       end;
    Along with the two (2) null statements in that code that the compiler has to deal with gracefully because the semicolons are separators instead of terminators.

    Maybe if I made a language myself I'd terminate some blocks (FOR, WHILE) too with the keyword (END FOR END WHILE)
    languages that implement "end of construct" that way are much easier to visually group/block than those that do not, e.g, C and Pascal.
    (FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

    MarkMLl

    • Hero Member
    • *****
    • Posts: 6676
    Re: Modula, Oberon or Ada
    « Reply #25 on: December 19, 2019, 11:28:16 am »
    > For Lazarus, my idea of co-routines would be to prepare a report in background (something that I currently use a thread):

    Obviously, a thread has the advantage that it runs in the background which a coroutine emphatically doesn't.

    I don't know whether there are situations where one has to consider "coroutine safety" in the same way that one has to consider thread safety... I suspect that it's a subset (i.e. something can be coroutine-safe but not thread-safe).

    Again, a whole lot of this stuff was considered by Burroughs in the 1960s, and supported as part of the language by their ALGOL implementation (which also had limited success for exceptions etc.). And both Dijkstra and Knuth were paid consultants for Burroughs, with McCarty (boo, lithp) their sworn enemy by some accounts :-)

    MarkMLl
    MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
    Pet hate: people who boast about the size and sophistication of their computer.
    GitHub repositories: https://github.com/MarkMLl?tab=repositories

    MarkMLl

    • Hero Member
    • *****
    • Posts: 6676
    Re: Modula, Oberon or Ada
    « Reply #26 on: December 19, 2019, 11:33:33 am »
    > I like it too because that way there is no "else" ambiguity, i.e, anything between IF and END belongs to that IF.

    I'd add here that some early (ALGOL) manuals made extremely heavy going of explaining nested conditionals, I suspect in part because indentation was used far less in the punched card era so the technical authors couldn't intuitively see what they were expected to explain.

    Perhaps part of the problem with "dangling else" etc., which were resolved by ALGOL-68 and Modula-2, was that far too few people really understood the syntax.

    MarkMLl
    MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
    Pet hate: people who boast about the size and sophistication of their computer.
    GitHub repositories: https://github.com/MarkMLl?tab=repositories

    marcov

    • Administrator
    • Hero Member
    • *
    • Posts: 11383
    • FPC developer.
    Re: Modula, Oberon or Ada
    « Reply #27 on: December 19, 2019, 01:57:29 pm »
    > For Lazarus, my idea of co-routines would be to prepare a report in background (something that I currently use a thread):

    Obviously, a thread has the advantage that it runs in the background which a coroutine emphatically doesn't.

    I don't know whether there are situations where one has to consider "coroutine safety" in the same way that one has to consider thread safety... I suspect that it's a subset (i.e. something can be coroutine-safe but not thread-safe).

    E.g. VCL usage.   

    Cactus stack also rings a bell. To be honest I think if one would want to resurrect this, one would have to dig into old implementations and their usecases.

    marcov

    • Administrator
    • Hero Member
    • *
    • Posts: 11383
    • FPC developer.
    Re: Modula, Oberon or Ada
    « Reply #28 on: December 19, 2019, 02:02:58 pm »
    ... C has no semicolon after }
    and it would be syntactically incorrect to have one since in C a semicolon is a statement terminator (not a separator.)  It's really unfortunate that Pascal has statement separators instead of terminators.

    It works both ways. Pascal can omit them in places where C can't (e.g. before an END). I think in M2 it is a terminator though.

    To be honest I never cared much either way, except the disambiguation of nested ELSE with semicolons in Pascal. That always felt contrived.

    Quote
    I like it too because that way there is no "else" ambiguity, i.e, anything between IF and END belongs to that IF. It also eliminates the necessity for "compound statement" constructs, begin/end pairs in Pascal and { } in C. Another thing I like about it is, it provides less opportunities for some programmers to indulge in incorrect formatting and claim it's a matter of "style". ;)  Without begin/end pairs, "else begin" (on the same line) are gone! :)

    Dangling else elimination was the core reason indeed. But for me it is not so much that (as in how often do you encounter that) as that the solution is very elegant and readable in daily use.

    Quote
    Maybe if I made a language myself I'd terminate some blocks (FOR, WHILE) too with the keyword (END FOR END WHILE)
    languages that implement "end of construct" that way are much easier to visually group/block than those that do not, e.g, C and Pascal.

    C has so many caveats where a small typing error suddenly returns hundreds of errors on a previously compiling source that I think for C this is hopeless any which way. It has bigger problems.

    marcov

    • Administrator
    • Hero Member
    • *
    • Posts: 11383
    • FPC developer.
    Re: Modula, Oberon or Ada
    « Reply #29 on: December 19, 2019, 02:26:17 pm »
    Quote
    One of the reasons to implement it in Pascal is because afaik some similar functionality is in the Extended Pascal (1990) standard.
    Could you elaborate a bit more?
    Does Free Pascal have a weak control of imported and exported identifiers?

    Little to none. If you have a symbol X you basically have two choices,  put it in the interface or not.

    If it is in the interface then all units that USES that unit see it as  unitname.X and  just X.

    I took the book to reread the syntax in Wirths book and it is different from what I was used to (Topspeed Modula2).  The stuff in the book sounds weird to me for non nested modules.

    Anyway, you can imagine that you might want to import e.g. unit Windows in a way that you need to prefix Windows. to all identifiers to use them ("QUALIFIED"). This way the gazillion identifiers in unit Windows won't be in your default scope, and using something from the module is a conscious choice.

    However if you were a die hard windows programmer and doing e.g. a complicated overlay using the metafile format/api in a certain unit. Then you would want to get some identifiers (drawcircle, drawtext etc) to be used without qualification.

    instead of USES Windows you get

    Code: Pascal  [Select][+][-]
    1. From Windows import Drawcircle,drawtext;  // to be used without unit. prefix
    2. Uses QUALIFIED Windows;
    3.  
    There are also some tricks in the used unit.

    E.g. assume unit Windows had a procedure write, read etc. A normal uses would constantly risk overriding the more used general definition.

    To avoid this, unit windows can say

    Code: Pascal  [Select][+][-]
    1. export qualified read,write;

    to make sure that you can only use read and write with windows prefix, regardless how it is USESed (but afaik FROM.. IMPORT goes over this)

     

    TinyPortal © 2005-2018