Modula-2 product hits 400 thousand copy markAt least since 06/02/02:But it's the way it is. This project is developed by users in their free time. People follow their interests (e.g. Florian improving the optimization, Jonas implementing the LLVM backend, me playing around in the parser).And me being a pain in the collective backside of the core developers for the last 15 years or so :-)
https://groups.google.com/forum/#!topic/comp.lang.modula2/DmRsV52YLb8
or is this the recruitment ? :-)
Afaik we came onto c.l.m2 about the same time (1994-1995 ?), and you might have submitted bugs/comments to my xtdlib library. So that would make it 25 years already :-)
For those who have already used Modula, Oberon or Ada.
Do those programming languages have any interesting features that Free Pascal currently doesn't?
For those who have already used Modula, Oberon or Ada.
Do those programming languages have any interesting features that Free Pascal currently doesn't?
A better block structure. Omits begin for all non procedure/function blocks, and makes END mandatory (also for one line blocks).
inner modules (nested units), which more or less served as a information hiding building block within a module/unit.
Some interesting runtime library concepts that are however dated now
- textwindowing unit, more than Crt, less than FV
- a cooperative multitasking unit
case sensitivity. Not an advantage IMHO
unsigned types by default (jury is still out on this one too)
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.
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.
inner modules (nested units), which more or less served as a information hiding building block within a module/unit.Pioneered by Brinch Hansen.
Some interesting runtime library concepts that are however dated now
- textwindowing unit, more than Crt, less than FV
- a cooperative multitasking unit
Not sure those were in the language, either as defined by Wirth or in the later (ISO?) standard. Might have been TopSpeed-specific, although coroutines were in the language.
The water is a bit muddied here by stuff that I think Wirth brought back to Europe from PARC, which were later sold by Logitech (e.g. a mouse toolkit which was the first time I'd seen the source of an input event message handling loop).
case sensitivity. Not an advantage IMHO
Arguable. Even if it's not mandatory, I'd like a way of enforcing it purely to improve documentation etc.
unsigned types by default (jury is still out on this one too)
Note that both signed integers and unsigned cardinals were supported.
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.
I think that M2 strings were /defined/ as being zero-terminated. Can't remember whether they were based on element zero, but they were basically arrays of chars rather than having special handling.
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.
It describes coroutines exclusively in the context of standard procedures. (no language enhancements for them, so could be purely library). Correct me if I'm wrong, it has been a while since I did anything with that.
case sensitivity. Not an advantage IMHO
Use formatters or IDEs, doesn't belong in a language. The old joke was that Wirth simply wanted twice the amount of one digit variables.
Afaik the only special handling was assignment of literals to array of chars even if sizes mismatched. The convention was zero terminated except when the length of the string matched the size of the allocation, then it was _not_ zero terminated. But static arrays only.
In assembler it was repne scasb iirc. with cx the size of the allocation. If it ran to completion, it was the non zero terminated case, if it didn't, there was a zero termination and the remainder in cx gave the position from the back.
@markov: Now I know what to do on christmas: P6 .....!
Which reminds me that I wanted to take a look at this (https://bugs.freepascal.org/view.php?id=25549) old feature request again. :-[
- FOR had a BY clause.
Just to remind I found this project is the Oberon equivalent of Free Pascal: https://github.com/kekcleader/FreeOberon (https://github.com/kekcleader/FreeOberon) It's even listed by the FSF: https://directory.fsf.org/wiki/Free_Oberon (https://directory.fsf.org/wiki/Free_Oberon)
Wouldn't this make Modula-2 even more verbose than Pascal?For those who have already used Modula, Oberon or Ada.From memory, Modula2 was basically an incompatible continuation of Pascal, and had
Do those programming languages have any interesting features that Free Pascal currently doesn't?
- A better block structure. Omits begin for all non procedure/function blocks, and makes END mandatory (also for one line blocks).
Is this still necessary when most people use an IDE [Lazarus] to program?
- inner modules (nested units), which more or less served as a information hiding building block within a module/unit.
[/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]
A controversial feature, but I think this could be a good idea.
- FOR had a BY clause.
- Some interesting runtime library concepts that are however dated now
- textwindowing unit, more than Crt, less than FV
- a cooperative multitasking unit
I agree.
- case sensitivity. Not an advantage IMHO
- unsigned types by default (jury is still out on this one too)
Is this still necessary when most people use an IDE [Lazarus] to program?
- 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.
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.
Isn't this already solved by threads?For those who have already used Modula, Oberon or Ada.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.
Do those programming languages have any interesting features that Free Pascal currently doesn't?
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.
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().
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.
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.
As I read, Ada was really a different story.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.
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?
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
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.
Going back to TP (for a brief while before migrating to FPC) felt as a blessing.
Another big difference ( and one I like to see in FPC someday) is more control over what identifiers are imported and exported (un)qualified.Could you elaborate a bit more?
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.
As a result for a lack of job offers, universities are restricting or even dropping practical disciplines of Compiler and Operational System building.Just to remind I found this project is the Oberon equivalent of Free Pascal: https://github.com/kekcleader/FreeOberon (https://github.com/kekcleader/FreeOberon) It's even listed by the FSF: https://directory.fsf.org/wiki/Free_Oberon (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.
Wouldn't this make Modula-2 even more verbose than Pascal?
- A better block structure. Omits begin for all non procedure/function blocks, and makes END mandatory (also for one line blocks).
QuoteIs this still necessary when most people use an IDE [Lazarus] to program?
- inner modules (nested units), which more or less served as a information hiding building block within a module/unit.
QuoteA controversial feature, but I think this could be a good idea.
- FOR had a BY clause.
However, I must add that I'll rarely need it...
QuoteIs this still necessary when most people use an IDE [Lazarus] to program?
- 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.
begin
begin
end;
end;
No. A thread is an operating system construct which is largely there to distribute processing over multiple processors.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?
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..
... 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.
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! :)
IF condition THEN statement1; statement2 ELSE statement3; statement4 END;
And I liked it.
Pascal needs this harder than M2 even, because pascal acceptsAlong 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.Code: [Select]begin
begin
end;
end;
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.
> 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).
... 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.
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! :)
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.
QuoteOne 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?
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.
Emphasising that an inline IF does not evaluate both expressions, while an IfThen() does. And I'm unhappy with something like IIF() that looks like a function but has different evaluation rules.QuoteUnfortunately 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().
QuoteQuoteIs this still necessary when most people use an IDE [Lazarus] to program?
- 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.
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.
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.
I think this is implicit to any language that allows up-level addressing via chained frames or a "display" which keeps track of areas of the stack(s). You can pass (the address of) a variable on a stack to a thread's constructor, or simply assume that variables remain valid.
coroutines have been implemented in the PIM style and these are accessible from SYSTEM. A number of supporting libraries (executive and file descriptor mapping to interrupt vector libraries are available through the -flibs=pim-coroutines,pim switch).
much better dwarf-2 debugging support and when used with gdb the programmer can display RECORDs, ARRAYs, SETs, subranges and constant char literals in Modula-2 syntax
Yes. It is also the case with nested procedures. ( type tprocedure = procedure is nested;), only valid till the parent returns. It was needed for ISO and was made visible in the FPC dialects via is nested.
Yes. It is also the case with nested procedures. ( type tprocedure = procedure is nested;), only valid till the parent returns. It was needed for ISO and was made visible in the FPC dialects via is nested.
No, since when you have a nested procedure you know that upper-level stackframes are still valid. You don't know that for threads or coroutines which have their own stack, but might internally have references to the parent stack.
What I dislike most from Oberon and Component Pascal is they are case sensitive and they force keywords to be UPPERCASE. I tried to write code in Oberon with OBNC compiler but as soon as I tried to write something more complex than HelloWorld everything turned out to be a nightmare.
Finding a text editor with proper syntax highlighting for them is very difficult let alone such powerful IDEs!https://github.com/programmingthomas/Oberon-Highlight (https://github.com/programmingthomas/Oberon-Highlight) oberon highlight for VIM
What I dislike most from Oberon and Component Pascal is they are case sensitive and they force keywords to be UPPERCASE.
Free Pascal currently still is the best Pascal dialect because it's suitable practical purpose, not only teaching like these later Wirthian languages. It's a balance between verbose and practical.
These languages must have very intelligent and powerful IDEs to make them usable because they are overly verbose.
The IDEs have to generate all of the boilerplate code for us (the OOP of them is very different, where object is pointer to procedure) and when we type keywords in lowercase it has to convert them to uppercase on the fly.
What I dislike most from Oberon and Component Pascal is they are case sensitive and they force keywords to be UPPERCASE. I tried to write code in Oberon with OBNC compiler but as soon as I tried to write something more complex than HelloWorld everything turned out to be a nightmare.
I've written a microkernel using Modula-2 which was case-sensitive. Editing wasn't particularly arduous, even allowing for the comparatively crude IDEs available in the 1990s.
Try debugging on bare metal. That will give you something to complain about >:-)
MarkMLl
Finding a text editor with proper syntax highlighting for them is very difficult let alone such powerful IDEs!https://github.com/programmingthomas/Oberon-Highlight (https://github.com/programmingthomas/Oberon-Highlight) oberon highlight for VIM
https://github.com/kekcleader/FreeOberon (https://github.com/kekcleader/FreeOberon) Oberon text IDE with code highlight
https://sourceforge.net/projects/npp-plugins/files/Oberon2Lexer/ (https://sourceforge.net/projects/npp-plugins/files/Oberon2Lexer/) Notepad++ oberon lexer
and i thin, FAR's Colorer have it too
if only i wanted, i can find more oberon code highlight tools and even IDE. (even if some of them are old and forgotten)
As said in other threads, I don't subscribe to your whole verbosity argumentation (and even less so for M2 which has tighter block structure).
If it was all true, people would complain about curly braces languages wearing out the shift buttons to make all those {}&! etc. You never hear that, so it is all in the head.
Oberon however is one of the languages with the shortest grammar. Writing a highlighter and some tools should be a breeze. But what to use it with ?
Afaik Microsoft supported component pascal with the first iterations of .NET. So an old Visual Studio (2003, 2005?) might do.
IMHO case insensitivity is sloppy, annoying, and distracting. If you're writing code you should be instinctively in the habit of thinking like a machine. To the machine, "A" is quite distinct from "a". What's next in the evolution? A language that's phonetically lenient? In which "aisle" and "isle" compile the same as you dictate your code into a microphone?
I don't agree with you, either. I could type { as fast as begin and the other } or end; should be automatically inserted by the text editor or IDE itself.
Oberon however is one of the languages with the shortest grammar. Writing a highlighter and some tools should be a breeze. But what to use it with ?
Afaik Microsoft supported component pascal with the first iterations of .NET. So an old Visual Studio (2003, 2005?) might do.
But in reality, very few IDEs or text editors support these languages. I tried Blackbox Component Builder and I could conclude it's something from the Win95 era, as I remember it's not even has syntax highlighting. I don't know why they could even call it an IDE. The only IDE I think good enough is from cfbsoftware (cpIDE) but it is commercial with a delusional price. If I have to choose between buying it and switch to another language, I definitely choose the later.
People are not machines, fortunately. A good language should help to write legibly, sensitivity in programming is an obvious path of bugs and clumsy errors. If you like computing, you will find that sensitivity mathematically increases the creation of insecure code.Disagree. The compiler should be your friend, an extra "pair of eyes". If the compiler ignores sloppy coding, then the compiler is not your friend. He is your "enabler" of bad habits.IMHO case insensitivity is sloppy, annoying, and distracting. If you're writing code you should be instinctively in the habit of thinking like a machine. To the machine, "A" is quite distinct from "a". What's next in the evolution? A language that's phonetically lenient? In which "aisle" and "isle" compile the same as you dictate your code into a microphone?
IMHO case insensitivity is sloppy, annoying, and distracting.
Furthermore it has a square root of that of making typo errors. :DIMHO case insensitivity is sloppy, annoying, and distracting.
Yes, and it HALVES the number of one digit identifiers to boot!
Maybe - but the compiler catches them before they raise further havoc as bugs.Furthermore it has a square root of that of making typo errors. :DIMHO case insensitivity is sloppy, annoying, and distracting.
Yes, and it HALVES the number of one digit identifiers to boot!
True - but if you're using one digit identifiers (other than for indexing), then you've got other problems.IMHO case insensitivity is sloppy, annoying, and distracting.
Yes, and it HALVES the number of one digit identifiers to boot!