Lazarus

Free Pascal => General => Topic started by: circular on April 02, 2020, 10:53:57 am

Title: Making the semicolon useless
Post by: circular on April 02, 2020, 10:53:57 am
The semicolon is useless most of the time. Though sometimes, it makes a difference. So I am thinking that we could simply avoid these cases and remove the semicolon completely. It seems that many people agree, though we can make it a compiler option so that anyone is free to do as they want.

Here are the only uses we have found of the semicolon.

Code: Delphi  [Select][+][-]
  1. if sometest then ;
To do nothing if the test happens. But one could simply write in this rare case the follwing:
Code: Pascal  [Select][+][-]
  1. if sometest then begin end
Also for the loop, the same thing applies.
Code: Delphi  [Select][+][-]
  1. for i := 1 to 10 do ;

Another case, that is arguably more significant is the following:
Code: Delphi  [Select][+][-]
  1. var
  2.  a: integer = 1;
  3. begin
  4.   case a of
  5.     1, 2: if a = 2 then
  6.               writeln(2);
  7.   else
  8.     writeln(1);
  9.   end;
  10. end;
  11.  
In this case, one can use the otherwise keyword to avoid the ambiguity:
Code: Pascal  [Select][+][-]
  1. var
  2.  a: integer = 1
  3. begin
  4.   case a of
  5.     1, 2: if a = 2 then
  6.               writeln(2)
  7.   otherwise
  8.     writeln(1)
  9.   end
  10. end
  11.  

What could help to transition towards a Pascal without semicolon would be to have a compiler switch to forbid the use of else instead of otherwise in a case statement and to forbid empty statements so that people would need to write begin end in these rare occurences.

After that, we could transition to an optional semicolon, and then to remove it completely.

An exception could be kept though to have multiple statements on one line.
Code: Delphi  [Select][+][-]
  1. begin
  2.   a := 1; b := 2
  3. end

What do you think?
Title: Re: Making the semicolon useless
Post by: 440bx on April 02, 2020, 11:11:45 am
What could help to transition towards a Pascal without semicolon would be to have a compiler switch to forbid the use of else instead of otherwise in a case statement and to forbid empty statements so that people would need to write begin end in these rare occurences.

After that, we could transition to an optional semicolon, and then to remove it completely.

An exception could be kept though to have multiple statements on one line.
Code: Delphi  [Select][+][-]
  1. begin
  2.   a := 1; b := 2
  3. end

What do you think?
Here are some thoughts.  The exception you mentioned creates an inconsistency, sometimes the semicolon would be required, other times it wouldn't be. 

The other cases you mention, such as disallowing "else" in "case" statements and requiring the use of "begin/end" to create an empty statement can be problematic for existing code.

Personally, not only I don't mind the semicolon, I like the instant visualization it provides to the end of the statement. 

I'd rather see some delimited statements being implemented, particularly something such as, "if/then/else/endif".  That gets rid of the "begin/end" for "if" statements and gets rid of "else" association problem and, that wouldn't cause any problems with existing code (at least none that I can think of as I type this.)

Title: Re: Making the semicolon useless
Post by: circular on April 02, 2020, 11:22:03 am
If the exception is an issue, I don't mind having no semicolon in this case.

Regarding existing code, precisely the idea is that you could enable the switch to make the code unambiguous regarding the semicolon and that it would not compile anymore. Then after fixing the very few cases that need an update, you could then remove all semicolons.

Using begin end for an empty statement may be cumbersome, so maybe we could write nil for example to express an empty statement.

The idea is to close the gap between semicolon or not, so that in the end it becomes equivalent to have it or not.
Title: Re: Making the semicolon useless
Post by: marcov on April 02, 2020, 11:58:05 am
Well, for me the incompatibility of it all is a killer. Even if you regard it is as feature it will split the pascal codebases yet again over silly dialect lines. (see all discussions about the local variable declaration of Delphi for this)

But to remain constructive, let's forget that for now;

But why not try to modify e.g. fcl-passrc to implement what you want rather than useless discussion? Just for a try out? The fcl-passrc is much more readable than the compiler parser.

I also want to reiterate the error handling point again, but I whipped up an example as illustration. Each time you change  fundamental (block-statement structure) of the language you have to rethink error handling.

Consider this

Code: [Select]

procedure aa(j:integer);  begin  end;
procedure bb; begin end;
procedure cc; begin end;
function yy(j:integer):integer; begin end;
function zz(j:integer):integer; begin end;

begin
 aa(yy(zz(33));
   bb();
   cc();
 end.

Now, the call to aa is unbalanced. Without a semicolon, bb would probably be parsed as part of the parameter construction of aa, and errors would be something like missing operator for on the bb  line. (aa bb has no + or so between them)

While now you get

Quote
Fatal: Syntax error, ")" expected but ";" found
 
on the right line (the aa() line with the unbalanced ), and an unrelated line bb() is not relevant. The message also conveys that a ) was expected, so is to the point.

Title: Re: Making the semicolon useless
Post by: kupferstecher on April 02, 2020, 12:44:18 pm
Now, the call to aa is unbalanced. Without a semicolon, bb would probably be parsed as part of the parameter construction of aa, and errors would be something like missing operator for on the bb  line.

While now you get
Quote
Fatal: Syntax error, ")" expected but ";" found
Omitting the semicolon would mean that a linebreak implicitly finishs the statement, so for the error handling this wouldn't be more difficult, but of course it results in a lot of places in the compiler code that needs adaption.
Because of the linebreak-sensitivity a new concept for multiline statements would be needed. In Fortran (90?) e.g. the character '&' is used to tell the compiler that the statement will go on in the next line.

--
There is currently one semicolon-thing in FPC that feels very odd to me:

Code: Pascal  [Select][+][-]
  1. if true then
  2.   aStatement // <- A completed statement without semicolon
  3. else
  4.   bStatement;

The missing semicolon makes more sense when a begin..end block is used instead.

Code: Pascal  [Select][+][-]
  1. if true then begin
  2.   aStatement; // <- A completed statement without semicolon
  3. end else
  4.   bStatement;

In a "if/then/elseif/else/endif"-syntax there wouldn't be such an issue.
Title: Re: Making the semicolon useless
Post by: MarkMLl on April 02, 2020, 12:58:46 pm
> The semicolon is useless most of the time. Though sometimes, it makes a difference.

It /always/ makes a difference, because it's a defined part of Pascal's syntax. End of discussion as far as Pascal's concerned.

If OP wants to change it- and note that I'm not saying "fix" here, then it's down to him to define and implement a new compiler mode which either has relaxed checking (and I suspect that he'd find this extraordinarily difficult) or with a language variant closer to Modula-2 /ALGOL-68/Ada.

MarkMLl


Title: Re: Making the semicolon useless
Post by: marcov on April 02, 2020, 01:09:46 pm
Omitting the semicolon would mean that a linebreak implicitly finishs the statement, so for the error handling this wouldn't be more difficult, but of course it results in a lot of places in the compiler code that needs adaption.
Because of the linebreak-sensitivity a new concept for multiline statements would be needed. In Fortran (90?) e.g. the character '&' is used to tell the compiler that the statement will go on in the next line.

Or backslash like C macros. Maybe you could also (ab)use indentation like Python   O:-)

Anyway, whatever solution you choose, parsing will be very different, and it is more to illustrate that it is more than a "simple if check" in the compiler to let the semicolon fall away. You need to rethink a lot of things.

And then you are not even forward compatible anymore (as in being able to compile arbitrary pascal code, since you first need to insert a lot of &'s), let alone backwards compatible.


This is why if you really mean this, you need to build a proof of concept. For everything, including errorhandling.

And pas2js/fcl-passrc is maybe a cleaner source to base that on than the compiler

Title: Re: Making the semicolon useless
Post by: Bart on April 02, 2020, 02:08:47 pm
But to remain constructive, let's forget that for now;

Pun intended?

Bart
Title: Re: Making the semicolon useless
Post by: marcov on April 02, 2020, 02:18:53 pm
But to remain constructive, let's forget that for now;

Pun intended?

No, accidental.
Title: Re: Making the semicolon useless
Post by: jwdietrich on April 02, 2020, 02:23:41 pm
Why should we? Even some languages of the C family, e.g. S and R, use the semicolon.

The main problem of dropping the semicolon is the loss of backwards-compatibilty. Moreover, I don't see a useful point in replacing a single character by "begn end".
Title: Re: Making the semicolon useless
Post by: MarkMLl on April 02, 2020, 03:18:31 pm
The main problem of dropping the semicolon is the loss of backwards-compatibilty. Moreover, I don't see a useful point in replacing a single character by "begn end".

The fact that OP suggests  then begin end  rather than simply  then end  suggests that he hasn't done his homework. For what it's worth, I'd be broadly in favour of an alternative mode supporting  if then else end  etc. (i.e. the ALGOL-68/Modula-2/Ada syntax) as an alternative mode, since Object Pascal is already half way there with things like  try finally end  not to mention e.g. record and object definitions. But the semicolon has an important function, even if a mandatory end made it easier for a parser to be more tolerant of sloppy placement.

MarkMLl
Title: Re: Making the semicolon useless
Post by: kupferstecher on April 02, 2020, 08:26:19 pm
This is why if you really mean this, you need to build a proof of concept. For everything, including errorhandling.
Just in case you overlooked, I'm not the TE and I wouldn't even vote for such a change. Some time before I had a different view on it, but compatibility is really essential.
Title: Re: Making the semicolon useless
Post by: Zoran on April 02, 2020, 09:25:04 pm
In my opinion, semicolon is of great help to code readability.
Isn't it a great feature that you can easily see where the statement ends (set aside that it is a great help to compiler).

It would be even better if semi-colon were statement terminator, as in C, not only separator; so it would be mandatory always, even in front of "end" and "else". But, to be honest, it doesn't matter much.

Uh, and I do hope you wouldn't want line endings to be significant in any way.

Title: Re: Making the semicolon useless
Post by: circular on April 02, 2020, 09:29:36 pm
I also want to reiterate the error handling point again, but I whipped up an example as illustration. Each time you change  fundamental (block-statement structure) of the language you have to rethink error handling.
Ok now that you gave an example I see what you are thinking about. Line endings.

Well that's not a problem. Without semicolons this would be:
Code: Delphi  [Select][+][-]
  1.  
  2. procedure aa(j:integer)  begin end
  3. procedure bb begin end
  4. procedure cc begin end
  5. function yy(j:integer):integer begin end
  6. function zz(j:integer):integer begin end
  7.  
  8. begin
  9.  aa(yy(zz(33))
  10.    bb()
  11.    cc()
  12.  end
  13.  
bb would not be considered as a parameter in anyway. Following a ")" by an identifier is not a continuation of instruction, it is in implicit end of instruction.
Title: Re: Making the semicolon useless
Post by: winni on April 02, 2020, 09:39:48 pm
Hi!

Without semicolons it looks " naked". That will be forbidden in the USA.

Yes I agree with Zoran - the semicolons increase the readability.

Winni
Title: Re: Making the semicolon useless
Post by: Zoran on April 02, 2020, 09:43:07 pm
I also want to reiterate the error handling point again, but I whipped up an example as illustration. Each time you change  fundamental (block-statement structure) of the language you have to rethink error handling.
Ok now that you gave an example I see what you are thinking about. Line endings.

Well that's not a problem. Without semicolons this would be:
Code: Delphi  [Select][+][-]
  1.  
  2. procedure aa(j:integer)  begin end
  3. procedure bb begin end
  4. procedure cc begin end
  5. function yy(j:integer):integer begin end
  6. function zz(j:integer):integer begin end
  7.  
  8. begin
  9.  aa(yy(zz(33))
  10.    bb()
  11.    cc()
  12.  end
  13.  
bb would not be considered as a parameter in anyway. Following a ")" by an identifier is not a continuation of instruction, it is in implicit end of instruction.

You obviously missed the point - in "aa line" there is one more open parentheses than closed. Compiler will not be able to notice anything wrong in that line, and will treat bb as (still) part of parameter of aa.
Title: Re: Making the semicolon useless
Post by: circular on April 02, 2020, 09:45:11 pm
Without semicolons it looks " naked". That will be forbidden in the USA.
:D

You obviously missed the point - in "aa line" there is one more open parentheses than closed. Compiler will not be able to notice anything wrong in that line, and will treat bb as parameter of aa.
Nope I understood the point. But as there is no comma, it will not be considered as the next parameter.
Title: Re: Making the semicolon useless
Post by: 440bx on April 02, 2020, 10:07:41 pm
Nope I understood the point. But as there is no comma, it will not be considered as the next parameter.
That makes statements "fragile" because one missing comma can change the semantics of the statement.  Usually, and hopefully, the compiler will catch the error later, maybe 3 or 4 tokens later, when that missing comma ends up creating something that is not semantically valid.

Worse is the possibility that the missing comma doesn't create a semantically invalid statement later.  In that case, the compiler will generate code that won't reflect the programmer's intentions.  This is the kind of stuff that makes C a lousy language.  One typo somewhere and, since the language is so poorly designed, the compiler is totally oblivious of the problem.  The result: the programmer has to get into the debugger to find out that a simple typo caused the program not to work as intended.

It's probably possible to make a version of Pascal that wouldn't need semicolons as statement separators but, the compiler implementation would be more complicated (since it has to infer the statement end) and diagnosing syntax errors would very likely result in less informative error message because there is more room for ambiguities in a syntactically incorrect statement.

The semicolons may be "useless" for the programmer but, they are far from useless for the compiler.


Title: Re: Making the semicolon useless
Post by: kupferstecher on April 02, 2020, 10:17:05 pm
Uh, and I do hope you wouldn't want line endings to be significant in any way.
Why not? The line ending is quite intuitive for being the end of a statement.
Title: Re: Making the semicolon useless
Post by: marcov on April 02, 2020, 10:26:16 pm
Nope I understood the point. But as there is no comma, it will not be considered as the next parameter.

It will be interpreted as an syntax error in the parameter block of aa(), while bb() isn't. 

So the question is

- what will you detect (as said well missing operator or so)
- where (as said probably at the BB token)
- how will you detect what is really going on (missing ")" on aa.

It is not the end of the world. C is also pretty bad at this (small syntax errors lead to errors a long way from the place where this mistake happens), and its programmers often don't even understand what you are talking about.

But it is step back in error generation quality. And something you will need to work on to at least minimize the regression
Title: Re: Making the semicolon useless
Post by: circular on April 02, 2020, 10:49:00 pm
There are things to think about for sure, though I don't think it will be more fragile. I find the "if then" fragile as one semicolon, not easy to spot, can disable it. Or the otherwise statement that can be confused with an else statement. I don't find the current state to be so safe regarding the semicolon. Maybe the line ending can be used by the compiler as an additional information, making it more "humain".
Title: Re: Making the semicolon useless
Post by: RayoGlauco on April 02, 2020, 11:41:30 pm
Pascal is as it is. It use semicolons to separate the declarations. Breaking the compatibility of billions of lines of code by changing this is not a good idea. If someone doesn't like semicolons, he/she better find another programming language!
Title: Re: Making the semicolon useless
Post by: Zath on April 03, 2020, 12:57:25 am
Pascal is as it is. It use semicolons to separate the declarations. Breaking the compatibility of billions of lines of code by changing this is not a good idea. If someone doesn't like semicolons, he/she better find another programming language!

I have to say I agree with this.

Just what is the issue with using the semicolon?
Title: Re: Making the semicolon useless
Post by: lainz on April 03, 2020, 01:52:07 am
Pascal is as it is. It use semicolons to separate the declarations. Breaking the compatibility of billions of lines of code by changing this is not a good idea. If someone doesn't like semicolons, he/she better find another programming language!

why to break compatibility? making it optional doesn't break any code
kotlin does that, just ignores the semicolon
Title: Re: Making the semicolon useless
Post by: 440bx on April 03, 2020, 02:13:04 am
why to break compatibility? making it optional doesn't break any code
It does have the potential to break code.  The example given in a previous post
Code: Delphi  [Select][+][-]
  1. var
  2.  a: integer = 1;
  3. begin
  4.   case a of
  5.     1, 2: if a = 2 then
  6.               writeln(2);
  7.   else
  8.     writeln(1);
  9.   end;
  10. end;
  11.  
shows that the statement is semantically different if the semicolon after the "writeln(2)" is not there.  I wish I could think of other examples but, none come to mind at this time but, that doesn't mean there aren't other cases like the one above.

My point is that, it is very dangerous to conclude the semicolon can be made optional in all cases without a careful analysis of the language's grammar.  As previously stated, even if it can be done, the compiler's complexity will increase because it will have to infer where/when statements end which could definitely have an impact on its compilation speed.  (a fast compiler is a very nice thing to have.)

kotlin does that, just ignores the semicolon
but it has a different grammar that allows it (and may even be designed) to make the semicolon optional.  Pascal's grammar relies on the semicolon to clearly establish the end of a statement.
Title: Re: Making the semicolon useless
Post by: lainz on April 03, 2020, 04:47:37 am
why to break compatibility? making it optional doesn't break any code
It does have the potential to break code.  The example given in a previous post
Code: Delphi  [Select][+][-]
  1. var
  2.  a: integer = 1;
  3. begin
  4.   case a of
  5.     1, 2: if a = 2 then
  6.               writeln(2);
  7.   else
  8.     writeln(1);
  9.   end;
  10. end;
  11.  
shows that the statement is semantically different if the semicolon after the "writeln(2)" is not there.  I wish I could think of other examples but, none come to mind at this time but, that doesn't mean there aren't other cases like the one above.

My point is that, it is very dangerous to conclude the semicolon can be made optional in all cases without a careful analysis of the language's grammar.  As previously stated, even if it can be done, the compiler's complexity will increase because it will have to infer where/when statements end which could definitely have an impact on its compilation speed.  (a fast compiler is a very nice thing to have.)

kotlin does that, just ignores the semicolon
but it has a different grammar that allows it (and may even be designed) to make the semicolon optional.  Pascal's grammar relies on the semicolon to clearly establish the end of a statement.

No I think it doesn't break old code. Because you will not be removing the semicolon in old code.

Also why not replace that odd else with something like "default " that's verbose as well.

Languages changes, evolves or die.
Title: Re: Making the semicolon useless
Post by: 440bx on April 03, 2020, 05:46:53 am
No I think it doesn't break old code. Because you will not be removing the semicolon in old code.
ok, that point is valid.

Also why not replace that odd else with something like "default " that's verbose as well.
That would mean a version of Pascal that allows "else", "otherwise" and "default" for the same thing.  That kind of stuff gives a strong impression that the language wasn't well thought out or, is driven by "Christmas tree design"  (shiny feature!.. we'll hang it over here.)

Languages changes, evolves or die.
Yes but, the evolution usually happens in ways that are significant and coherent with the essence of the language.   A change that causes the compiler to be slower and emit even less precise error messages doesn't seem to be evolution in the right direction.

There are more important capabilities that can be added to Pascal than not using a semicolon to separate statements.  Honestly, I think removing the semicolon separator between statements would be a step backwards since it would require the programmer to infer where statements end instead of having the semicolon as a clear end-statement marker.
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 08:36:51 am
Also why not replace that odd else with something like "default " that's verbose as well.
That would mean a version of Pascal that allows "else", "otherwise" and "default" for the same thing.  That kind of stuff gives a strong impression that the language wasn't well thought out or, is driven by "Christmas tree design"  (shiny feature!.. we'll hang it over here.)
In fact you can already write otherwise instead of else. There you have your Christmas tree.

For now, we have found very few specific examples that suggest that the semicolon would be necessary. That's the whole point of the discussion: if no one finds a reason to keep the semicolon, maybe there is no need for it.

In other words, if you are afraid of the danger of not having semicolon but cannot explain why, maybe there is no danger and it is safe. Hence the discussion to see together what could actually happen without semicolon.

I've thought a bit about it and maybe we don't have to change the compiler at all. It could be just some preprocessing. For example, the "semicolon-less" preprocessor could:
- check that there are no semicolon at the end of lines, otherwise throw an error
- at the end of the line, if the token is not line-continuing, and that there isn't an else at the begining of the next line, add a semicolon

Note that this is a theoretical discussion, it is not a demand and not even a request until there is a satisfactory way of doing it.
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 08:44:58 am
Pascal is as it is. It use semicolons to separate the declarations. Breaking the compatibility of billions of lines of code by changing this is not a good idea. If someone doesn't like semicolons, he/she better find another programming language!
Is it that you are afraid of loosing unity and that you would rather reject people to preserve it?
Title: Re: Making the semicolon useless
Post by: RayoGlauco on April 03, 2020, 09:28:40 am
Maybe I didn't express myself well. My english is poor. I just believe that a programming language that does not use semicolons to separate sentences can hardly be called Pascal. It's just my opinion!
Title: Re: Making the semicolon useless
Post by: marcov on April 03, 2020, 09:43:51 am
Languages changes, evolves or die.

And most mutations die.
Title: Re: Making the semicolon useless
Post by: guest58172 on April 03, 2020, 09:57:01 am
I don't think that the semi colon is a problem and I don't think it is useless either, as argumented by others. But to the opposiste I would even like it to be allowed in a specific case:

Code: Pascal  [Select][+][-]
  1. if condition then
  2.   trueStatement;
  3. else
  4.   falseStatement;

You see before the else.
Title: Re: Making the semicolon useless
Post by: Thaddy on April 03, 2020, 10:02:42 am
I don't think that the semi colon is a problem and I don't think it is useless either, as argumented by others. But to the opposiste I would even like it to be allowed in a specific case:

Code: Pascal  [Select][+][-]
  1. if condition then
  2.   trueStatement;
  3. else
  4.   falseStatement;

You see before the else.

In Pascal, ;  is the block or statement separator, what you ask is to introduce whitespace and line separators in the language that is a quadratic complexity added to the parser.... Very good idea...
Anyway, the whole discussion is rather futile given the fact that Pascal relies on the ; in more than one way as many explained. See Marco's answers for example.

I might add that the only language that I use that parses such things without effort is Python, not Go, which has its own quirks.
Anyway a teaser:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. {$macro on}{$Define endblock:=;}
  3. procedure truestatement;begin end endblock
  4. procedure falsestatement;begin end endblock
  5. var
  6.   condition:boolean = true;
  7. begin
  8. if condition then
  9.   trueStatement // endblock
  10. else
  11.   falseStatement endblock
  12. end.
Title: Re: Making the semicolon useless
Post by: MarkMLl on April 03, 2020, 10:25:19 am
In Pascal, ;  is the block or statement separator, what you ask is to introduce whitespace and line separators in the language that is a quadratic complexity added to the parser.... Very good idea...

Having spent time supporting and maintaining products such as operating systems which were driven by their compatibility with some dominant competitor (e.g. any DOS-compatible OS had to be able to run Lotus 1-2-3 and MS Flight Simulator), I'd suggest that having a codebase which is dominated by exceptions and hacks is a very bad idea indeed.

ALGOL-derived languages have firm rules as to the significance of statement separators, and with the exception of literal strings and the dot after end. treat line endings as simple whitespace which can be discarded early in order to allow the compiler to use lookahead. Adding exceptions to this without introducing a new language mode (e.g. one in which  ;  is not just optional but is forbidden) is a recipe for disaster.

MarkMLl
Title: Re: Making the semicolon useless
Post by: MarkMLl on April 03, 2020, 10:29:32 am
To err is human, but to really mess things up, you need a computer.

To err is human, but to really mess things up, you need a badly-implemented parser.

And you can't implement a parser properly without a robustly-designed syntax.

MarkMLl


Title: Re: Making the semicolon useless
Post by: Thaddy on April 03, 2020, 10:53:42 am
Indeed.
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 11:44:02 am
I don't think that the semi colon is a problem and I don't think it is useless either, as argumented by others. But to the opposiste I would even like it to be allowed in a specific case:

Code: Pascal  [Select][+][-]
  1. if condition then
  2.   trueStatement;
  3. else
  4.   falseStatement;

You see before the else.
I suppose that would be possible by considering the semicolon as required statement terminator. But then it would not just be allowed in this case but mandatory.
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 11:44:53 am
Languages changes, evolves or die.

And most mutations die.
That escalated quite quickly. This is just a discussion, relax.  8-)
Title: Re: Making the semicolon useless
Post by: marcov on April 03, 2020, 12:10:47 pm
Languages changes, evolves or die.

And most mutations die.
That escalated quite quickly. This is just a discussion, relax.  8-)

It wasn't meant in a bad way, so it is not an escalation, but I admit in retrospect it can be taken wrongly.

It was meant to note that in evolution few changes make it long term. IOW "Not every changement is an improvement". Sometimes even only after quite a while (e.g. when circumstances change and the change lead to overspecialisation).

I thought that a fitting analogue for how a simple idea like skipping semicolons can get complicated really quickly as this discussion demonstrates.


Title: Re: Making the semicolon useless
Post by: Thaddy on April 03, 2020, 02:19:15 pm
For such a feature to implement, you require a grammar that verifies its validity anyway.
And that is quite complex as I tried to explain: the parser for such a language becomes - at least!!- ll(N) instead of ll(1).
A formal Pascal grammar should be ll(1) by definition. (Don't worry, FPC already does not comply to this)

But I would start with a grammar that can prove correctness.
Title: Re: Making the semicolon useless
Post by: guest58172 on April 03, 2020, 05:08:34 pm
I don't think that the semi colon is a problem and I don't think it is useless either, as argumented by others. But to the opposiste I would even like it to be allowed in a specific case:

Code: Pascal  [Select][+][-]
  1. if condition then
  2.   trueStatement;
  3. else
  4.   falseStatement;

You see before the else.

In Pascal, ;  is the block or statement separator, what you ask is to introduce whitespace and line separators in the language that is a quadratic complexity added to the parser.... Very good idea...

There's a misunderstanding here. The semicolon before else does not introduce complexity.
To be clear in the discussion I was not partisan of making the semicolon optional, I just came to say that it could be allowed before else.

you have
Code: bnf  [Select][+][-]
  1. IfStatement   ::= 'if' Condition ThenStatement ElseStatement?
  2. ThenStatement ::= 'then' Statement
  3. ElseStatement ::= 'else' Statement


That's perfectly LL(1), in no way more than one lookup is necessary.
Title: Re: Making the semicolon useless
Post by: Thaddy on April 03, 2020, 05:16:41 pm
It introduces complexilty because of the dangling else .... That is not complex, isn't it... Try to adapt a Pascal grammar...<SIGH  >:D>
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 06:45:28 pm
It was meant to note that in evolution few changes make it long term. IOW "Not every changement is an improvement". Sometimes even only after quite a while (e.g. when circumstances change and the change lead to overspecialisation).
Ok I understand where you're coming from. I would agree in general with what you say.

In this case of course, it is not a random mutation and I would love to have a semicolon-less code. That's why I am entertaining this discussion, to get insights from others and not be alone thinking about it.
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 06:50:26 pm
you have
Code: bnf  [Select][+][-]
  1. IfStatement   ::= 'if' Condition ThenStatement ElseStatement?
  2. ThenStatement ::= 'then' Statement
  3. ElseStatement ::= 'else' Statement


That's perfectly LL(1), in no way more than one lookup is necessary.
I am not sure I understand where you define the semicolon here.

Though would like semicolons optional, if we have semicolons, I would rather like your idea, because more often than I would like, I am adding or removing the semicolon as I move the statement, add an else, etc. And it would be simpler not to have to do that.
Title: Re: Making the semicolon useless
Post by: marcov on April 03, 2020, 06:54:19 pm
In this case of course, it is not a random mutation and I would love to have a semicolon-less code. That's why I am entertaining this discussion, to get insights from others and not be alone thinking about it.

Well, I've said most arguments, the only remaining one is that in retrospect I think Mark and Thaddy are right. It cuts so deep into the base principle of the parser, that you probably have to start over.

So I would like to retract my earlier advise to try modify fcl-passrc, but advise you to whip up some relevant examples (also think about errorhandling, so also wrong/non compilable tests!) and try to use some parser generator tool to get some grammar that is roughly working on these examples to flesh out the details and get a starting point.
Title: Re: Making the semicolon useless
Post by: guest58172 on April 03, 2020, 07:43:02 pm
you have
Code: bnf  [Select][+][-]
  1. IfStatement   ::= 'if' Condition ThenStatement ElseStatement?
  2. ThenStatement ::= 'then' Statement
  3. ElseStatement ::= 'else' Statement


That's perfectly LL(1), in no way more than one lookup is necessary.
I am not sure I understand where you define the semicolon here.

Indeed TIL that in pascal the semicolon is not part of the Statement, unlike C.
So the simple change I thinked of would not work.

So the semicolon is introduced by this rule https://www.freepascal.org/docs-html/current/ref/refsu55.html#x161-18300013.2.1 ?
Mmmh I don't like this.

Title: Re: Making the semicolon useless
Post by: guest58172 on April 03, 2020, 07:45:16 pm
It introduces complexilty because of the dangling else .... That is not complex, isn't it... Try to adapt a Pascal grammar...<SIGH  >:D>

The explanation for the confusion is that I didn't know that the semicolon is not part of the Statement rule. I was actually thinking in C.
Title: Re: Making the semicolon useless
Post by: circular on April 03, 2020, 11:41:37 pm
So I would like to retract my earlier advise to try modify fcl-passrc, but advise you to whip up some relevant examples (also think about errorhandling, so also wrong/non compilable tests!) and try to use some parser generator tool to get some grammar that is roughly working on these examples to flesh out the details and get a starting point.
I understand the grammar approach, though as I explained before, I guess I would rather have a token approach. It is quite simple to have a preprocessor that adds semicolon. That could leave the compiler untouched.
Title: Re: Making the semicolon useless
Post by: marcov on April 04, 2020, 12:00:28 am
So I would like to retract my earlier advise to try modify fcl-passrc, but advise you to whip up some relevant examples (also think about errorhandling, so also wrong/non compilable tests!) and try to use some parser generator tool to get some grammar that is roughly working on these examples to flesh out the details and get a starting point.
I understand the grammar approach, though as I explained before, I guess I would rather have a token approach. It is quite simple to have a preprocessor that adds semicolon. That could leave the compiler untouched.

As said: Then better have an IDE tool to occasionally try to fix. Advantage: runs on less code at once so does have to be as perfect. And you don't need to carve up your buildsystem to pull al your source through the preprocessor before calling the real compiler.
Title: Re: Making the semicolon useless
Post by: 440bx on April 04, 2020, 12:19:09 am
Aside from any feasibility and compatibility considerations, I don't think that getting rid of the semicolon is really worth much effort.  Is there a semicolon phobia I don't know about... a "semiphobia" ? ;)

Thinking more about it, I think phobias should be semicolon separated too;  Just practicing my ataxophobia;  (the combination of tax phobia and; poorly formatted Pascal code phobia;)

Title: Re: Making the semicolon useless
Post by: circular on April 04, 2020, 10:39:28 am
 :D

I don't know of any phobia of that kind ; though I suppose it is possible ;

@marcov: Indeed an IDE tool could the the instant conversion between the view and the code file. Though I don't know how to do such a tool.
Title: Re: Making the semicolon useless
Post by: lainz on April 04, 2020, 02:36:37 pm
Languages changes, evolves or die.

And most mutations die.
That escalated quite quickly. This is just a discussion, relax.  8-)

Sorry, I only wanted to say in a language evolution, not species. I was tired so because that I wrote the 'die' part, not very well planned  :)

I mean, I never used semicolons to write Spanish or English, but I know these was often used in the past. Modern texts does't use them or most people don't know how to use them.
Title: Re: Making the semicolon useless
Post by: marcov on April 04, 2020, 02:44:23 pm
:D

I don't know of any phobia of that kind ; though I suppose it is possible ;

@marcov: Indeed an IDE tool could the the instant conversion between the view and the code file. Though I don't know how to do such a tool.

Maybe we are thinking about different things. I'm not talking about a new "language" or anything, just an edit menu option in lazarus to check a block of selected code and add missing semicolons. Just like e.g. tabs-to-spaces, which implementation could be followed.


Title: Re: Making the semicolon useless
Post by: marcov on April 04, 2020, 02:47:07 pm
I mean, I never used semicolons to write Spanish or English, but I know these was often used in the past. Modern texts does't use them or most people don't know how to use them.

True, and the main reason for that is that natural languages are hopelessly context sensitive and ambiguous and thus not machine parseable, which is the whole reason that programming languages exist :-)

Being easily parseable is the raison d'être of programming languages.
Title: Re: Making the semicolon useless
Post by: del on April 04, 2020, 03:21:56 pm
This is what happens when the first language people learn is Python. It's ugly. Trust me.
Title: Re: Making the semicolon useless
Post by: lainz on April 04, 2020, 04:28:07 pm
This is what happens when the first language people learn is Python. It's ugly. Trust me.

I do not agree. One of the fist languages of mine is Pascal. I don't use python.

Seems that it happens when I learned Kotlin, that's more evolved language currently in existence.
Title: Re: Making the semicolon useless
Post by: MarkMLl on April 04, 2020, 04:31:45 pm
This is what happens when the first language people learn is Python. It's ugly. Trust me.

I wouldn't touch it with a barge pole, and I don't trust you. Sorry :-)

MarkMLl
Title: Re: Making the semicolon useless
Post by: Otto on April 04, 2020, 07:33:18 pm
Hello everyone.

I would like to say that the question posed by circular is interesting, I believe that any proposal that aims to discuss a possible greater spread of Lazarus/FPC is to be considered. Simplifying code writing might be useful for this purpose.

However, I do not agree with the specific proposal: in my opinion the use of the symbol ";" in pascal is of fundamental importance, more for the programmer than for the compiler.
Many users have already reported a good reason why keeping a visible separator is of paramount importance.
I would like to add that for work, sometimes, I have to correct errors in codes written in VB.net by others. Very often I have to rewrite a lot of the code in C.C. and then convert it back to VB.net;  because, often, the causes are induced by errors of logic induced precisely by the permissiveness typical of the language VB.net. What I want to say is that if some programmers know that it is possible to use a system apparently "simplified" can make a bad use of it, in case of problems it will then be more complex to identify the real cause.

Surely it would be possible, more or less easily, to enter a mode that would allow the elimination of the ";"; but I think if you really had this need it would be better to use an external preprocessor functionality. In this case, the product code could be compiled normally without having to make any changes to the FPC compiler.

Otto.
Title: Re: Making the semicolon useless
Post by: circular on April 04, 2020, 10:28:55 pm
Maybe we are thinking about different things. I'm not talking about a new "language" or anything, just an edit menu option in lazarus to check a block of selected code and add missing semicolons. Just like e.g. tabs-to-spaces, which implementation could be followed.
Ah ok no I was thinking of making an editor where the semicolon do not appear, yet they are saved in the file for the compiler.
Title: Re: Making the semicolon useless
Post by: Thaddy on April 05, 2020, 11:30:22 am
But our Pascal doesn't use ';' as an end of statement but a separator between statements. It's the problem.
It separates code blocks It is no problem at all....
Title: Re: Making the semicolon useless
Post by: circular on April 05, 2020, 11:34:18 am
Hi Opaque,

I am talking about having the Source editor showing a code without semicolons. Either by converting it on the fly, or indeed by a compiler option. Such option need not a new compiler but could just enable a preprocessor that adds the semicolons.

I believe there are ways to deduce where to put the semicolons. This can be deduced from the tokens that begins and ends lines.
Title: Re: Making the semicolon useless
Post by: Thaddy on April 05, 2020, 11:42:54 am
I believe there are ways to deduce where to put the semicolons. This can be deduced from the tokens that begins and ends lines.
Well, adapt the grammar. Can you provide proof for these "ways"? Because I can prove it will not work. (disprove)
The simplest parsetree will already fail because of dis-ambiguity.
Title: Re: Making the semicolon useless
Post by: marcov on April 05, 2020, 12:05:31 pm
I am talking about having the Source editor showing a code without semicolons. Either by converting it on the fly, or indeed by a compiler option. Such option need not a new compiler but could just enable a preprocessor that adds the semicolons.

(Opague is the known troll nov97/giahung that likes to stir up language discussions. Note he never posts any Pascal code, and often compares to Freebasic, and often "pretends" to have discover new languages.  He just posts to create offtopic threads and keep them running)

As said several times, there are a few caveats that make this hard, even with correct code. But incorrect code will be mangled and the resulting errors will be incomprehensible. Which is the usual problem with hamfisted preprocessor usage.

Quote
I believe there are ways to deduce where to put the semicolons. This can be deduced from the tokens that begins and ends lines.

There are no tokens in pascal compilers for that. The scanner filters them already out before producing the real tokens.
Title: Re: Making the semicolon useless
Post by: 440bx on April 05, 2020, 12:54:54 pm
I believe there are ways to deduce where to put the semicolons. This can be deduced from the tokens that begins and ends lines.
Getting rid of semicolons is not that simple.  For instance
Code: Pascal  [Select][+][-]
  1. procedure aproc(var a; d, e, f : Boolean);
when the entire statement is syntactically correct, it's not too hard to figure out where there should be a semicolon but, if there is a syntax error then it's a completely different story.  For instance
Code: Pascal  [Select][+][-]
  1. procedure aproc(var a d, e, f : Boolean);
parameter "a" is in both cases untyped and if the semicolon is missing between the "a" and "d", most Pascal compilers don't even try to emit the correct error message because the resulting statement is syntactically ambiguous.  "a" may be an untyped parameter, in which case there should be a semicolon between "a" and "d".  if the problem is that the comma is missing, the compiler _assumes_ that "d" is a data type and says it expected a colon ":" (which is incorrect in this case since "d" is not a data type) when it could have easily been that the comma is the missing element.

For a preprocessor to have _some_ chance of accurately placing semicolons in the source, it would have to be a complete parser (one that would have to be _smarter_ than the one implemented in the compiler.)  It would have to know that if "d" is a data type, either a colon between "a" and "d" or a semicolon after "a" are required.  There is no way for the parser (no matter how smart it may be) to figure out which case is applicable because there isn't enough auxiliary syntactic information in the statement to make the determination (without using type information.)

Your "semicolon paster" would end up declaring untyped parameters every time there is a comma missing between "var" parameters resulting in one parameter being untyped and the remainder being passed by value instead of reference and, the worst part is, the programmer would not have a clue that the missing comma resulted in a definition with a completely different meaning than what he/she intended.

And that doesn't include the additional problems caused by the possibility that the programmer forgot the "var" keyword (which is required to declare untyped parameter but not typed ones.)

It is also worth noting that while parsing Pascal is usually reasonably fast, your preprocessor, if it were a full parser, it would definitely result in perceptibly slower compile times.



Title: Re: Making the semicolon useless
Post by: marcov on April 05, 2020, 01:33:33 pm
It is also worth noting that while parsing Pascal is usually reasonably fast, your preprocessor, if it were a full parser, it would definitely result in perceptibly slower compile times.

The preprocessor could be built into the IDE, and only update modified versions of the source files. Adding external preprocessor support to FPC has been rejected already many times.
Title: Re: Making the semicolon useless
Post by: Thaddy on April 05, 2020, 01:45:09 pm
Writing bindings is not the issue. You have to prove you can do it in the language itself...
Title: Re: Making the semicolon useless
Post by: PascalDragon on April 05, 2020, 01:47:19 pm
I would like to say that the question posed by circular is interesting, I believe that any proposal that aims to discuss a possible greater spread of Lazarus/FPC is to be considered. Simplifying code writing might be useful for this purpose.

If the feature results in increased maintenance (in this case increased complexity of the parser) for no real gain (really, you are all arguing about semicolons?!), then no it's not even remotely worth to be considered.
Title: Re: Making the semicolon useless
Post by: Handoko on April 05, 2020, 01:49:04 pm
@opaque

Please calm down sir.
Just some misunderstanding.

I can understand why some people here are too sensitive. Recently the forum has been repeatedly visited by trolls (or maybe a troll).
Title: Re: Making the semicolon useless
Post by: marcov on April 05, 2020, 02:01:45 pm
Really? Did you forgot I done a IUP binding for Pascal and code is still on my github?

One swallow doesn't make summer.

Quote
Did you ever see I compared Pascal with Basic except I said Basic code is twice as long as Pascal and I don't like long code?

Yes, a whole monologue about that.

Quote
Did I said anything about other language except the news about Ada++ I found on Phoronix? Sorry if it's insult you but I only want to know how people react to such news and you are too sensitive. Reread the first post on my Ada++ thread, I said: "I will just put it here and don't said anything", did I post anything after that?

You posted an url-only post about it twice, one of which in a new thread. And you have been warned against such behaviour before.

Quote
Did you have proof I'm a troll? Please show it. Otherwise don't make such claim, so everyone would ignore me and all of my threads asking for help.

I have several likenesses in behaviour and account data, some of which I have commented on here. If you insist, I'll pass it all on to my co moderators for judgement in a query about account deletion.

Or you can just own up to it, and get a fair last chance, just because I also overstepped a bit in a bad mood.

Despite you deleted your account the last time when I pmed you with warnings, I should still have gone that way instead of posting in the thread out of the blue. Mea culpa, and a last chance for you if you are honest about it.

Quote
If you want, just delete my thread about Ada++.

Done.
Title: Re: Making the semicolon useless
Post by: circular on April 05, 2020, 06:32:15 pm
Quote
I believe there are ways to deduce where to put the semicolons. This can be deduced from the tokens that begins and ends lines.
There are no tokens in pascal compilers for that. The scanner filters them already out before producing the real tokens.
I was talking about the tokens like "+" etc. I was kind of expecting the end of lines not to be tokens but discarded as whitespace. Is it possible to know the position of a token? If not then that would make it difficult to add the preprocessor in the current compiler stack.

Though for an external tool, that's not complicated to add a way to determine tokens location.

Your "semicolon paster" would end up declaring untyped parameters every time there is a comma missing between "var" parameters resulting in one parameter being untyped and the remainder being passed by value instead of reference and, the worst part is, the programmer would not have a clue that the missing comma resulted in a definition with a completely different meaning than what he/she intended.
No no I am talking about semicolons for instruction ending. And in fact I am ok for semicolons within the line.
Title: Re: Making the semicolon useless
Post by: GypsyPrince on April 05, 2020, 06:56:42 pm
Quote
Here are some thoughts.  The exception you mentioned creates an inconsistency, sometimes the semicolon would be required, other times it wouldn't be.

In my own worthless opinion, I agree with 440bx on this point.
Inconsistency makes things more difficult and inefficient.

While I have no particular sway toward using the semicolon or not, I do agree that it should be used consistently or not at all.  But again, that is just my own opinion.
Title: Re: Making the semicolon useless
Post by: Otto on April 05, 2020, 10:03:24 pm
@PascalDragon

Hello.
I'm sorry for the misunderstanding caused by me.
I would like to say that the question posed by circular is interesting, I believe that any proposal that aims to discuss a possible greater spread of Lazarus/FPC is to be considered. Simplifying code writing might be useful for this purpose.

If the feature results in increased maintenance (in this case increased complexity of the parser) for no real gain (really, you are all arguing about semicolons?!), then no it's not even remotely worth to be considered.

It is possible that I did not explain myself clearly enough, but in the rest of my post (which you did not report) I explained that I am absolutely opposed to the abolition of the ";".
In fact, I took the example of how difficult it is, sometimes, to identify the true cause of errors within codes written in VB.net (language that does not use the ";") and the risk that pascal would take if it eliminated the ";".

I also suggested, in case it was necessary, the use of an external tool to convert the code from VB.pascal (proposed by circular) to FPC.

The introductory speech (which you have reported) is a general consideration, I think circular had a positive purpose in proposing it.
For me, an interesting proposal should be discussed even if I do not approve of the content of the proposal itself.

Otto.
Title: Re: Making the semicolon useless
Post by: marcov on April 05, 2020, 11:26:22 pm
Quote
I believe there are ways to deduce where to put the semicolons. This can be deduced from the tokens that begins and ends lines.
There are no tokens in pascal compilers for that. The scanner filters them already out before producing the real tokens.
I was talking about the tokens like "+" etc. I was kind of expecting the end of lines not to be tokens but discarded as whitespace. Is it possible to know the position of a token? If not then that would make it difficult to add the preprocessor in the current compiler stack.

(purely hypothetical, as you are obviously not going to implement it, and nobody else believes it is doable)

There is an ability for location (line, column) of the current token I think. Most parsers do since that is needed to generate error information.

Since a compiler error needs that info. But the scanner (which includes the FPC internal preprocessor) and the parser are intertwined. It would be a colossal job to detangle them, create a new level inbetween to splice the external preprocessor into etc.

Quote
Though for an external tool, that's not complicated to add a way to determine tokens location.

Keep in mind the external tool would be extremely complicated since any manipulations must keep the token stream equivalent or the errors would be on the a different line and number. Study how the C preprocessor works etc etc.

And before to even attempt such thing (and then again, already purely hypothetical), you would have to demonstrate the concept using an own fork of FPC first, before one starts rearranging the whole parser.

Anyway, I think this is a dead end. If you really want something like that, you're better off crafting some language based on syntax concepts of a language that has no need for statement terminators like python or basic.
Title: Re: Making the semicolon useless
Post by: 440bx on April 06, 2020, 12:17:08 am
No no I am talking about semicolons for instruction ending. And in fact I am ok for semicolons within the line.
Even only in the case of instruction ending, it's not only the compiler that uses the semicolons to figure things out.  Tools like "codetools" and the "Code Explorer" (and possibly others) in the IDE, are almost certain to depend on semicolons in one way or another to do their job (I haven't looked at their implementation, therefore I cannot be precise about this.)

The more I think about it, the more I believe it is not feasible.  Eliminating the semicolon affects the syntactic structure of the language and, there are a lot of consequences to that.
Title: Re: Making the semicolon useless
Post by: PascalDragon on April 06, 2020, 09:30:59 am
@PascalDragon

Hello.
I'm sorry for the misunderstanding caused by me.
I would like to say that the question posed by circular is interesting, I believe that any proposal that aims to discuss a possible greater spread of Lazarus/FPC is to be considered. Simplifying code writing might be useful for this purpose.

If the feature results in increased maintenance (in this case increased complexity of the parser) for no real gain (really, you are all arguing about semicolons?!), then no it's not even remotely worth to be considered.

It is possible that I did not explain myself clearly enough, but in the rest of my post (which you did not report) I explained that I am absolutely opposed to the abolition of the ";".
In fact, I took the example of how difficult it is, sometimes, to identify the true cause of errors within codes written in VB.net (language that does not use the ";") and the risk that pascal would take if it eliminated the ";".

I also suggested, in case it was necessary, the use of an external tool to convert the code from VB.pascal (proposed by circular) to FPC.

The introductory speech (which you have reported) is a general consideration, I think circular had a positive purpose in proposing it.
For me, an interesting proposal should be discussed even if I do not approve of the content of the proposal itself.

Otto.

It's not only about this specific topic (the semicolons), but your generalisation I don't agree with:

I believe that any proposal that aims to discuss a possible greater spread of Lazarus/FPC is to be considered.
Title: Re: Making the semicolon useless
Post by: Otto on April 06, 2020, 11:32:43 am
Hello PascalDragon.

It's not only about this specific topic (the semicolons), but your generalisation I don't agree with:

I believe that any proposal that aims to discuss a possible greater spread of Lazarus/FPC is to be considered.
I respect your opinion.

However, I believe that in order to increase the use of FPC/Lazarus in the professional field, it is necessary to assess the criticism of the users of these products. Especially when such users have made and continue to make an important contribution to the community (as e.g. circular did).

In the generalization I have made, I wanted to point out that a proposal can be taken into account without the need to accept it. The most important thing is, in my opinion, to discuss the cause that led a programmer to ask that specific question. Discussing the cause might be helpful for other programmers to discuss their opinions. Not all of us have had the same kind of training, so discussing basic topics could help someone clarify some aspect of programming in FPC that doesn't match the one in the language he had previously learned.

Of course what I said is just my opinion, I do not pretend to be right.

Otto.
Title: Re: Making the semicolon useless
Post by: marcov on April 06, 2020, 12:03:33 pm
I wanted to point out that a proposal can be taken into account without the need to accept it. The most important thing is, in my opinion, to discuss the cause that led a programmer to ask that specific question. Discussing the cause might be helpful for other programmers to discuss their opinions. Not all of us have had the same kind of training, so discussing basic topics could help someone clarify some aspect of programming in FPC that doesn't match the one in the language he had previously learned.

I've always seen reasons given in rejections. So they were evaluated/considered.

Just as users request get the response, the users must also trust the developers in their judgement. :)
Title: Re: Making the semicolon useless
Post by: circular on April 06, 2020, 03:37:27 pm
Since a compiler error needs that info. But the scanner (which includes the FPC internal preprocessor) and the parser are intertwined. It would be a colossal job to detangle them, create a new level inbetween to splice the external preprocessor into etc.
I see so I would not try that then.

Quote
Keep in mind the external tool would be extremely complicated since any manipulations must keep the token stream equivalent or the errors would be on the a different line and number. Study how the C preprocessor works etc etc.
That's ok because it is just appending a token at the end of the line.

Quote
And before to even attempt such thing (and then again, already purely hypothetical), you would have to demonstrate the concept using an own fork of FPC first, before one starts rearranging the whole parser.
I am not requesting that any action be taken as of now.

Quote
Anyway, I think this is a dead end. If you really want something like that, you're better off crafting some language based on syntax concepts of a language that has no need for statement terminators like python or basic.
I disagree, I think there is potential for an alternate source editor and for tools that convert text code from and to semicolon-less.

I will see if I have the time to try it out.
Title: Re: Making the semicolon useless
Post by: Otto on April 06, 2020, 08:54:45 pm
@GypsyPrince
Hello.
I have read the "De Principatibus" in the original language and I can assure you that it is a literary work of which it is very easy to misunderstand the meaning.
Surely your interpretation does not match mine.
In short, my interpretation (limited to the argument you mentioned) is that in order to maintain order in a state, the governor must be forced, even in spite of himself, to make unpopular decisions to protect the state and therefore its people. To counteract the bad faith of some individuals will sometimes have to use cunning other times force. In these cases the Prince's behavior is not despicable but necessary.
So if Moderators/Administrators used this kind of behavior within the Forums, it would be, in my opinion, only a good thing.

Short quote of the original text:

Quote
Sendo, dunque, uno principe necessitato sapere bene usare la bestia, debbe di quelle pigliare la golpe e il lione; perché il lione non si defende da’ lacci, la golpe non si defende da’ lupi. Bisogna, adunque, essere golpe a conoscere e’ lacci, e lione a sbigottire e’ lupi. Coloro che stanno semplicemente in sul lione, non se ne intendano. Non può, pertanto, uno signore prudente, né debbe, osservare la fede, quando tale osservanzia li torni contro e che sono spente le cagioni che la feciono promettere. E se gli uomini fussino tutti buoni, questo precetto non sarebbe buono; ma perché sono tristi, e non la osservarebbono a te, tu etiam non l’hai ad osservare a loro.
Title: Re: Making the semicolon useless
Post by: Otto on April 06, 2020, 08:58:55 pm
@marcov

Hello.
I've always seen reasons given in rejections. So they were evaluated/considered.

Just as users request get the response, the users must also trust the developers in their judgement. :)
Marcov you are certainly right and I agree with you.
However, I do not understand why you made this statement to me. I have never said otherwise and I have never criticized the responses and judgments of the developers; if you had time I would ask you to check my previous posts.
The speech I had made earlier (which you only partially mentioned) had been made without polemical purpose; but just to better explain my previous post.

(-: I hope, this time, I'm better explained. :-)

Otto.
Title: Re: Making the semicolon useless
Post by: 440bx on April 06, 2020, 09:27:12 pm
I disagree, I think there is potential for an alternate source editor and for tools that convert text code from and to semicolon-less.

I will see if I have the time to try it out.
Putting aside my doubts about the feasibility, it seems really extreme to invest that much time and work to accomplish such a trivial and, not particularly useful, goal of getting rid of semicolons in Pascal.

Did a semicolon do something bad to you ? ;)  Here is a more pragmatic solution: go to church, admit your hatred of semicolons, repent, be forgiven after reciting 20 "our semicolon" and move on.



Title: Re: Making the semicolon useless
Post by: circular on April 06, 2020, 11:32:24 pm
Yeah, that wasn't even close to what I was talking about. I give up on this forum.
:'(
We can stick together and be strong despite negative feedbacks.

Here is a sample project to remove/add/fix semicolons:
Code: Delphi  [Select][+][-]
  1. program semicolonless;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$MODESWITCH AdvancedRecords}
  5.  
  6. uses
  7.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  8.   cthreads,
  9.   {$ENDIF}{$ENDIF}
  10.   Classes
  11.   { you can add units after this },
  12.   PScanner,
  13.   SysUtils;
  14.  
  15. type
  16.   TPascalScannerIgnoreDirectives = class; // this ending semicolon is necessary
  17.  
  18. var
  19.   outTokens: array of record
  20.     TokenKind: TToken;
  21.     TokenString: string;
  22.   end;
  23.   outTokenCount: integer;
  24.  
  25. procedure AddToOutput(ATokenType: TToken; ATokenString: string); forward;
  26. procedure InsertIntoOutput(AIndex: integer; ATokenType: TToken; ATokenString: string); forward;
  27.  
  28. const
  29.   TokensWhereSemicolonIndicatesEmptyStatement = [tkColon, tkdo, tkelse, tkthen{, tkOtherwise}];
  30.   TokensNeutrallyFollowedBySemicolon =
  31.    [tkIdentifier, tkString, tkNumber, tkChar, tkBraceClose, tkSquaredBraceClose, tkCaret,
  32.     tkdispinterface, tkend, tkfalse, tkfile, tkinherited, tkinline, tkinterface,
  33.     tknil, tkobject, tkself, tkthreadvar, tktrue]; { - private protected public published otherwise }
  34.   TokensNotIndicatingStatementContinuation =
  35.    [tkWhitespace, tkComment, tkIdentifier, tkString, tkNumber, tkChar,
  36.     tkBraceOpen, tkAt, tkasm, tkbegin, tkcase, tkconst, tkend, tkexports,
  37.     tkfinalization, tkfor, tkfunction, tkgoto, tkif, tkimplementation, tkinherited,
  38.     tkinitialization, tklabel, tklibrary, tkoperator, tkprocedure, tkprogram, tkproperty,
  39.     tkraise, tkrepeat, tkResourceString, tkthreadvar, tktry, tktype, tkunit, tkuntil,
  40.     tkuses, tkvar, tkwhile, tkwith];
  41.  
  42. type
  43.   { TPascalScannerIgnoreDirectives }
  44.  
  45.   TPascalScannerIgnoreDirectives = class(TPascalScanner)
  46.   protected
  47.     function HandleDirective(const {%H-}ADirectiveText: String): TToken; override;
  48.   end;
  49.  
  50. function TPascalScannerIgnoreDirectives.HandleDirective(const ADirectiveText: String): TToken;
  51. begin
  52.   Result:= tkComment; // treat directives as comments
  53. end;
  54.  
  55. {********************** Output *********************}
  56.  
  57. procedure AddToOutput(ATokenType: TToken; ATokenString: string);
  58. begin
  59.   if outTokenCount >= length(outTokens) then
  60.     SetLength(outTokens, outTokenCount * 2 + 4);
  61.   outTokens[outTokenCount].TokenKind:= ATokenType;
  62.   outTokens[outTokenCount].TokenString:= ATokenString;
  63.   inc(outTokenCount);
  64. end;
  65.  
  66. procedure InsertIntoOutput(AIndex: integer; ATokenType: TToken; ATokenString: string);
  67. var
  68.   i: Integer;
  69. begin
  70.   if (AIndex < 0) or (AIndex > outTokenCount) then raise exception.Create('Index out of bounds');
  71.   if outTokenCount >= length(outTokens) then
  72.     SetLength(outTokens, outTokenCount * 2 + 4);
  73.   for i := outTokenCount-1 downto AIndex do
  74.     outTokens[i+1] := outTokens[i];
  75.   outTokens[AIndex].TokenKind:= ATokenType;
  76.   outTokens[AIndex].TokenString:= ATokenString;
  77.   inc(outTokenCount);
  78. end;
  79.  
  80. procedure ReadInput(AInputName: string);
  81. var
  82.   resolver: TFileResolver;
  83.   scanner: TPascalScanner;
  84.   curToken: TToken;
  85.   curColStart, curColEnd: integer;
  86.   curInputLine: string;
  87.  
  88.   procedure FetchNextToken;
  89.   var
  90.     inputRow: Integer;
  91.   begin
  92.     inputRow := scanner.CurRow;
  93.     curColStart := scanner.CurColumn;
  94.     curInputLine := scanner.CurLine;
  95.     curToken := scanner.FetchToken;
  96.     if scanner.CurRow > inputRow then
  97.       curColEnd := length(curInputLine)
  98.       else curColEnd:= scanner.CurColumn;
  99.   end;
  100.  
  101. begin
  102.   outTokens := nil;
  103.   outTokenCount := 0;
  104.   resolver := TFileResolver.Create;
  105.   scanner := TPascalScannerIgnoreDirectives.Create(resolver);
  106.   try
  107.     scanner.OpenFile(AInputName);
  108.     FetchNextToken;
  109.     while curToken <> tkEOF do
  110.     begin
  111.       case curToken of
  112.         tkWhitespace, tkComment: AddToOutput(curToken,
  113.             copy(curInputLine, curColStart + 1, curColEnd - curColStart));
  114.         tkIdentifier..tkChar: AddToOutput(curToken, scanner.CurTokenString);
  115.         tkTab: AddToOutput(tkTab, #9); (* keep tabs *)
  116.         tkLineEnding: AddToOutput(tkLineEnding, LineEnding);
  117.         otherwise
  118.           AddToOutput(curToken, TokenInfos[curToken]);
  119.       end;
  120.       FetchNextToken;
  121.     end;
  122.   finally
  123.     scanner.Free;
  124.     resolver.Free;
  125.   end;
  126. end;
  127.  
  128. procedure WriteOutput(AOutputName: string);
  129. var
  130.   i: Integer;
  131.   fout: TextFile;
  132. begin
  133.   assignfile(fout, AOutputName);
  134.   Rewrite(fout);
  135.   for i := 0 to outTokenCount-1 do
  136.     write(fout, outTokens[i].TokenString);
  137.   closefile(fout);
  138. end;
  139.  
  140. {******************** Processing ********************}
  141.  
  142. procedure RemoveSemicolonsInOutput;
  143. var
  144.   i, j: Integer;
  145.   prevToken, nextToken, nextLineToken: TToken;
  146.   nextTokenPos: integer;
  147.   prevTokenStr: String;
  148. begin
  149.   for i := 0 to outTokenCount-1 do
  150.     if (outTokens[i].TokenKind = tkSemicolon) then
  151.     begin
  152.       nextToken := tkLineEnding;
  153.       nextTokenPos:= i;
  154.       for j := i+1 to outTokenCount-1 do
  155.         if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace] then
  156.           continue else
  157.         begin
  158.           nextToken := outTokens[j].TokenKind;
  159.           nextTokenPos := j;
  160.           break;
  161.         end;
  162.       // found a semicolon that might be removed
  163.       if nextToken = tkLineEnding then
  164.       begin
  165.         nextLineToken := tkEOF;
  166.         for j := nextTokenPos+1 to outTokenCount-1 do
  167.           if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding] then
  168.             continue else
  169.           begin
  170.             nextLineToken:= outTokens[j].TokenKind;
  171.             break;
  172.           end;
  173.         if nextLineToken in TokensNotIndicatingStatementContinuation then
  174.         begin
  175.           prevToken := tkLineEnding;
  176.           prevTokenStr := '';
  177.           for j := i-1 downto 0 do
  178.             if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding]
  179.                 then continue else
  180.               begin
  181.                 prevToken := outTokens[j].TokenKind;
  182.                 prevTokenStr := outTokens[j].TokenString;
  183.                 break;
  184.               end;
  185.           if (prevToken in TokensWhereSemicolonIndicatesEmptyStatement) or
  186.                   (compareText(prevTokenStr, 'otherwise') = 0) then
  187.           begin
  188.             outTokens[i].TokenKind:= tknil;
  189.             outTokens[i].TokenString:= 'nil';
  190.           end
  191.           else if (prevToken in TokensNeutrallyFollowedBySemicolon) and
  192.                   (compareText(prevTokenStr, 'otherwise') <> 0) and
  193.                   (compareText(prevTokenStr, 'private') <> 0) and
  194.                   (compareText(prevTokenStr, 'protected') <> 0) and
  195.                   (compareText(prevTokenStr, 'public') <> 0) and
  196.                   (compareText(prevTokenStr, 'published') <> 0) then
  197.           begin
  198.             outTokens[i].TokenKind:= tkWhitespace;
  199.             outTokens[i].TokenString:= '';
  200.           end;
  201.         end;
  202.       end;
  203.     end;
  204. end;
  205.  
  206. procedure RemoveSemicolons(AInputName, AOutputName : string);
  207. begin
  208.   ReadInput(AInputName);
  209.   RemoveSemicolonsInOutput;
  210.   WriteOutput(AOutputName);
  211. end;
  212.  
  213. procedure AddSemicolonsInOutput;
  214. var
  215.   i, j, prevTokenPos: Integer;
  216.   prevToken, prevToken2, nextToken, classToken: TToken;
  217.   prevTokenStr, prevTokenStr2: String;
  218.   forFound: Boolean;
  219. begin
  220.   for i := outTokenCount downto 0 do
  221.     if (i = outTokenCount) or (outTokens[i].TokenKind = tkLineEnding) then
  222.     begin
  223.       prevToken := tkLineEnding;
  224.       prevTokenPos := i;
  225.       for j := i-1 downto 0 do
  226.         if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace] then
  227.           continue else
  228.         begin
  229.           prevToken := outTokens[j].TokenKind;
  230.           prevTokenPos := j;
  231.           prevTokenStr := outTokens[j].TokenString;
  232.           break;
  233.         end;
  234.       if prevToken = tknil then
  235.       begin
  236.         prevToken2 := tkLineEnding;
  237.         prevTokenStr2 := '';
  238.         for j := prevTokenPos-1 downto 0 do
  239.           if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding] then
  240.             continue else
  241.           begin
  242.             prevToken2 := outTokens[j].TokenKind;
  243.             prevTokenStr2 := outTokens[j].TokenString;
  244.             break;
  245.           end;
  246.         if (prevToken2 in TokensWhereSemicolonIndicatesEmptyStatement) or
  247.            (CompareText(prevTokenStr2, 'otherwise')=0) then
  248.         begin
  249.           outTokens[prevTokenPos].TokenKind := tkSemicolon;
  250.           outTokens[prevTokenPos].TokenString:= ';';
  251.           continue;
  252.         end;
  253.       end;
  254.       if (prevToken in TokensNeutrallyFollowedBySemicolon) and
  255.         (compareText(prevTokenStr, 'otherwise') <> 0) and
  256.         (compareText(prevTokenStr, 'private') <> 0) and
  257.         (compareText(prevTokenStr, 'protected') <> 0) and
  258.         (compareText(prevTokenStr, 'public') <> 0) and
  259.         (compareText(prevTokenStr, 'published') <> 0) then
  260.       begin
  261.         // class|record|type helper for T
  262.         if prevToken = tkIdentifier then
  263.         begin
  264.           forFound := false;
  265.           for j := prevTokenPos-1 downto 0 do
  266.             if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding,
  267.                                           tkDot, tkIdentifier] then
  268.               continue else
  269.             if outTokens[j].TokenKind = tkfor then
  270.             begin
  271.               forFound := true;
  272.               break;
  273.             end else break;
  274.           if forFound then continue;
  275.         end;
  276.         // type class|object|interface|dispinterface(parent1...)
  277.         if prevToken = tkBraceClose then
  278.         begin
  279.           classToken:= tkLineEnding;
  280.           for j := prevTokenPos-1 downto 0 do
  281.             if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding,
  282.                                           tkDot, tkIdentifier, tkComma,
  283.                                           tkGreaterThan, tkLessThan, tkspecialize] then
  284.               continue else
  285.             if outTokens[j].TokenKind = tkBraceOpen then
  286.             begin
  287.               if j > 0 then classToken := outTokens[j-1].TokenKind;
  288.               break;
  289.             end else break;
  290.           if classToken in[tkclass, tkobject, tkinterface, tkdispinterface] then continue;
  291.         end;
  292.  
  293.         nextToken := tkLineEnding;
  294.         for j := i+1 to outTokenCount-1 do
  295.           if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding] then
  296.             continue else
  297.           begin
  298.             nextToken := outTokens[j].TokenKind;
  299.             break;
  300.           end;
  301.         if nextToken in TokensNotIndicatingStatementContinuation then
  302.           InsertIntoOutput(prevTokenPos+1, tkSemicolon, ';');
  303.       end;
  304.     end;
  305. end;
  306.  
  307. procedure AddSemicolons(AInputName, AOutputName : string);
  308. begin
  309.   ReadInput(AInputName);
  310.   AddSemicolonsInOutput;
  311.   WriteOutput(AOutputName);
  312. end;
  313.  
  314. procedure FixSemicolons(AInputName, AOutputName : string);
  315. begin
  316.   ReadInput(AInputName);
  317.   RemoveSemicolonsInOutput;
  318.   AddSemicolonsInOutput;
  319.   WriteOutput(AOutputName);
  320. end;
  321.  
  322. {********************** Testing *********************}
  323.  
  324. type
  325.   { TPointHelper }
  326.  
  327.   TPointHelper = record helper for TPoint
  328.     function Sum: integer;
  329.   end;
  330.  
  331.   function TPointHelper.Sum: integer;
  332.   begin
  333.     result := x + y;
  334.   end;
  335.  
  336. procedure TestStatements;
  337. var c: char;
  338. begin
  339.   write('hihi');;
  340.  
  341.   //test empty statement
  342.   if true then ;
  343.  
  344.   //test case else
  345.   case random(4) of
  346.     1: ;
  347.     7: if true then write('haha');
  348.     else write('hoho');
  349.   end;
  350.  
  351.   c := 'A';
  352.   case c of
  353.     'B': ;
  354.     'C': if true then write('haha');
  355.     otherwise
  356.       ;
  357.   end;
  358. end;
  359.  
  360. {******************* Main program *******************}
  361.  
  362. var
  363.   sourceFile, targetFile, mode: string;
  364.  
  365. begin
  366.   if ParamCount < 2 then
  367.   begin
  368.     writeln('Usage: semicolonless -L|-M|-F <input file> [<output file>]');
  369.     writeln;
  370.     writeln('-L : less semicolons (default extension .less)');
  371.     writeln('-M : more semicolons (default extension .pas)');
  372.     writeln('-F : fix semicolons');
  373.     halt;
  374.   end;
  375.  
  376.   mode := paramstr(1);
  377.   if copy(mode,1,1) <> '-' then
  378.   begin
  379.     writeln('Expecting mode');
  380.     halt;
  381.   end;
  382.  
  383.   sourceFile := paramstr(2);
  384.   if not FileExists(sourceFile) then
  385.   begin
  386.     writeln('Input file not found');
  387.     halt;
  388.   end;
  389.  
  390.   if ParamCount >= 3 then
  391.     targetFile := paramStr(3)
  392.     else targetFile := '';
  393.  
  394.   if mode = '-L' then
  395.   begin
  396.     if targetFile = '' then targetFile := ChangeFileExt(sourceFile,'.less') else
  397.     if ExtractFileExt(targetFile) = '' then targetFile += '.less';
  398.     RemoveSemicolons(sourceFile, targetFile);
  399.   end else
  400.   if mode = '-M' then
  401.   begin
  402.     if targetFile = '' then targetFile := ChangeFileExt(sourceFile, '.pas') else
  403.     if ExtractFileExt(targetFile) = '' then targetFile += '.pas';
  404.     AddSemicolons(sourceFile, targetFile);
  405.   end else
  406.   if mode = '-F' then
  407.   begin
  408.     if targetFile = '' then targetFile := sourceFile;
  409.     FixSemicolons(sourceFile, targetFile);
  410.   end else
  411.     writeln('Unknown mode');
  412. end.
Title: Re: Making the semicolon useless
Post by: circular on April 06, 2020, 11:33:51 pm
Same code without useless semicolons:
Code: Delphi  [Select][+][-]
  1. program semicolonless
  2.  
  3. {$mode objfpc}{$H+}
  4. {$MODESWITCH AdvancedRecords}
  5.  
  6. uses
  7.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  8.   cthreads,
  9.   {$ENDIF}{$ENDIF}
  10.   Classes
  11.   { you can add units after this },
  12.   PScanner,
  13.   SysUtils
  14.  
  15. type
  16.   TPascalScannerIgnoreDirectives = class; // this ending semicolon is necessary
  17.  
  18. var
  19.   outTokens: array of record
  20.     TokenKind: TToken
  21.     TokenString: string
  22.   end
  23.   outTokenCount: integer
  24.  
  25. procedure AddToOutput(ATokenType: TToken; ATokenString: string); forward
  26. procedure InsertIntoOutput(AIndex: integer; ATokenType: TToken; ATokenString: string); forward
  27.  
  28. const
  29.   TokensWhereSemicolonIndicatesEmptyStatement = [tkColon, tkdo, tkelse, tkthen{, tkOtherwise}]
  30.   TokensNeutrallyFollowedBySemicolon =
  31.    [tkIdentifier, tkString, tkNumber, tkChar, tkBraceClose, tkSquaredBraceClose, tkCaret,
  32.     tkdispinterface, tkend, tkfalse, tkfile, tkinherited, tkinline, tkinterface,
  33.     tknil, tkobject, tkself, tkthreadvar, tktrue] { - private protected public published otherwise }
  34.   TokensNotIndicatingStatementContinuation =
  35.    [tkWhitespace, tkComment, tkIdentifier, tkString, tkNumber, tkChar,
  36.     tkBraceOpen, tkAt, tkasm, tkbegin, tkcase, tkconst, tkend, tkexports,
  37.     tkfinalization, tkfor, tkfunction, tkgoto, tkif, tkimplementation, tkinherited,
  38.     tkinitialization, tklabel, tklibrary, tkoperator, tkprocedure, tkprogram, tkproperty,
  39.     tkraise, tkrepeat, tkResourceString, tkthreadvar, tktry, tktype, tkunit, tkuntil,
  40.     tkuses, tkvar, tkwhile, tkwith]
  41.  
  42. type
  43.   { TPascalScannerIgnoreDirectives }
  44.  
  45.   TPascalScannerIgnoreDirectives = class(TPascalScanner)
  46.   protected
  47.     function HandleDirective(const {%H-}ADirectiveText: String): TToken; override
  48.   end
  49.  
  50. function TPascalScannerIgnoreDirectives.HandleDirective(const ADirectiveText: String): TToken
  51. begin
  52.   Result:= tkComment // treat directives as comments
  53. end
  54.  
  55. {********************** Output *********************}
  56.  
  57. procedure AddToOutput(ATokenType: TToken; ATokenString: string)
  58. begin
  59.   if outTokenCount >= length(outTokens) then
  60.     SetLength(outTokens, outTokenCount * 2 + 4)
  61.   outTokens[outTokenCount].TokenKind:= ATokenType
  62.   outTokens[outTokenCount].TokenString:= ATokenString
  63.   inc(outTokenCount)
  64. end
  65.  
  66. procedure InsertIntoOutput(AIndex: integer; ATokenType: TToken; ATokenString: string)
  67. var
  68.   i: Integer
  69. begin
  70.   if (AIndex < 0) or (AIndex > outTokenCount) then raise exception.Create('Index out of bounds')
  71.   if outTokenCount >= length(outTokens) then
  72.     SetLength(outTokens, outTokenCount * 2 + 4)
  73.   for i := outTokenCount-1 downto AIndex do
  74.     outTokens[i+1] := outTokens[i]
  75.   outTokens[AIndex].TokenKind:= ATokenType
  76.   outTokens[AIndex].TokenString:= ATokenString
  77.   inc(outTokenCount)
  78. end
  79.  
  80. procedure ReadInput(AInputName: string)
  81. var
  82.   resolver: TFileResolver
  83.   scanner: TPascalScanner
  84.   curToken: TToken
  85.   curColStart, curColEnd: integer
  86.   curInputLine: string
  87.  
  88.   procedure FetchNextToken
  89.   var
  90.     inputRow: Integer
  91.   begin
  92.     inputRow := scanner.CurRow
  93.     curColStart := scanner.CurColumn
  94.     curInputLine := scanner.CurLine
  95.     curToken := scanner.FetchToken
  96.     if scanner.CurRow > inputRow then
  97.       curColEnd := length(curInputLine)
  98.       else curColEnd:= scanner.CurColumn
  99.   end
  100.  
  101. begin
  102.   outTokens := nil
  103.   outTokenCount := 0
  104.   resolver := TFileResolver.Create
  105.   scanner := TPascalScannerIgnoreDirectives.Create(resolver)
  106.   try
  107.     scanner.OpenFile(AInputName)
  108.     FetchNextToken
  109.     while curToken <> tkEOF do
  110.     begin
  111.       case curToken of
  112.         tkWhitespace, tkComment: AddToOutput(curToken,
  113.             copy(curInputLine, curColStart + 1, curColEnd - curColStart))
  114.         tkIdentifier..tkChar: AddToOutput(curToken, scanner.CurTokenString)
  115.         tkTab: AddToOutput(tkTab, #9) (* keep tabs *)
  116.         tkLineEnding: AddToOutput(tkLineEnding, LineEnding)
  117.         otherwise
  118.           AddToOutput(curToken, TokenInfos[curToken])
  119.       end
  120.       FetchNextToken
  121.     end;
  122.   finally
  123.     scanner.Free
  124.     resolver.Free
  125.   end
  126. end
  127.  
  128. procedure WriteOutput(AOutputName: string)
  129. var
  130.   i: Integer
  131.   fout: TextFile
  132. begin
  133.   assignfile(fout, AOutputName)
  134.   Rewrite(fout)
  135.   for i := 0 to outTokenCount-1 do
  136.     write(fout, outTokens[i].TokenString)
  137.   closefile(fout)
  138. end
  139.  
  140. {******************** Processing ********************}
  141.  
  142. procedure RemoveSemicolonsInOutput
  143. var
  144.   i, j: Integer
  145.   prevToken, nextToken, nextLineToken: TToken
  146.   nextTokenPos: integer
  147.   prevTokenStr: String
  148. begin
  149.   for i := 0 to outTokenCount-1 do
  150.     if (outTokens[i].TokenKind = tkSemicolon) then
  151.     begin
  152.       nextToken := tkLineEnding
  153.       nextTokenPos:= i
  154.       for j := i+1 to outTokenCount-1 do
  155.         if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace] then
  156.           continue else
  157.         begin
  158.           nextToken := outTokens[j].TokenKind
  159.           nextTokenPos := j
  160.           break
  161.         end
  162.       // found a semicolon that might be removed
  163.       if nextToken = tkLineEnding then
  164.       begin
  165.         nextLineToken := tkEOF
  166.         for j := nextTokenPos+1 to outTokenCount-1 do
  167.           if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding] then
  168.             continue else
  169.           begin
  170.             nextLineToken:= outTokens[j].TokenKind
  171.             break
  172.           end
  173.         if nextLineToken in TokensNotIndicatingStatementContinuation then
  174.         begin
  175.           prevToken := tkLineEnding
  176.           prevTokenStr := ''
  177.           for j := i-1 downto 0 do
  178.             if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding]
  179.                 then continue else
  180.               begin
  181.                 prevToken := outTokens[j].TokenKind
  182.                 prevTokenStr := outTokens[j].TokenString
  183.                 break
  184.               end
  185.           if (prevToken in TokensWhereSemicolonIndicatesEmptyStatement) or
  186.                   (compareText(prevTokenStr, 'otherwise') = 0) then
  187.           begin
  188.             outTokens[i].TokenKind:= tknil
  189.             outTokens[i].TokenString:= 'nil'
  190.           end
  191.           else if (prevToken in TokensNeutrallyFollowedBySemicolon) and
  192.                   (compareText(prevTokenStr, 'otherwise') <> 0) and
  193.                   (compareText(prevTokenStr, 'private') <> 0) and
  194.                   (compareText(prevTokenStr, 'protected') <> 0) and
  195.                   (compareText(prevTokenStr, 'public') <> 0) and
  196.                   (compareText(prevTokenStr, 'published') <> 0) then
  197.           begin
  198.             outTokens[i].TokenKind:= tkWhitespace
  199.             outTokens[i].TokenString:= ''
  200.           end
  201.         end
  202.       end
  203.     end
  204. end
  205.  
  206. procedure RemoveSemicolons(AInputName, AOutputName : string)
  207. begin
  208.   ReadInput(AInputName)
  209.   RemoveSemicolonsInOutput
  210.   WriteOutput(AOutputName)
  211. end
  212.  
  213. procedure AddSemicolonsInOutput
  214. var
  215.   i, j, prevTokenPos: Integer
  216.   prevToken, prevToken2, nextToken, classToken: TToken
  217.   prevTokenStr, prevTokenStr2: String
  218.   forFound: Boolean
  219. begin
  220.   for i := outTokenCount downto 0 do
  221.     if (i = outTokenCount) or (outTokens[i].TokenKind = tkLineEnding) then
  222.     begin
  223.       prevToken := tkLineEnding
  224.       prevTokenPos := i
  225.       for j := i-1 downto 0 do
  226.         if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace] then
  227.           continue else
  228.         begin
  229.           prevToken := outTokens[j].TokenKind
  230.           prevTokenPos := j
  231.           prevTokenStr := outTokens[j].TokenString
  232.           break
  233.         end
  234.       if prevToken = tknil then
  235.       begin
  236.         prevToken2 := tkLineEnding
  237.         prevTokenStr2 := ''
  238.         for j := prevTokenPos-1 downto 0 do
  239.           if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding] then
  240.             continue else
  241.           begin
  242.             prevToken2 := outTokens[j].TokenKind
  243.             prevTokenStr2 := outTokens[j].TokenString
  244.             break
  245.           end
  246.         if (prevToken2 in TokensWhereSemicolonIndicatesEmptyStatement) or
  247.            (CompareText(prevTokenStr2, 'otherwise')=0) then
  248.         begin
  249.           outTokens[prevTokenPos].TokenKind := tkSemicolon
  250.           outTokens[prevTokenPos].TokenString:= ';'
  251.           continue
  252.         end
  253.       end
  254.       if (prevToken in TokensNeutrallyFollowedBySemicolon) and
  255.         (compareText(prevTokenStr, 'otherwise') <> 0) and
  256.         (compareText(prevTokenStr, 'private') <> 0) and
  257.         (compareText(prevTokenStr, 'protected') <> 0) and
  258.         (compareText(prevTokenStr, 'public') <> 0) and
  259.         (compareText(prevTokenStr, 'published') <> 0) then
  260.       begin
  261.         // class|record|type helper for T
  262.         if prevToken = tkIdentifier then
  263.         begin
  264.           forFound := false
  265.           for j := prevTokenPos-1 downto 0 do
  266.             if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding,
  267.                                           tkDot, tkIdentifier] then
  268.               continue else
  269.             if outTokens[j].TokenKind = tkfor then
  270.             begin
  271.               forFound := true
  272.               break
  273.             end else break
  274.           if forFound then continue
  275.         end
  276.         // type class|object|interface|dispinterface(parent1...)
  277.         if prevToken = tkBraceClose then
  278.         begin
  279.           classToken:= tkLineEnding
  280.           for j := prevTokenPos-1 downto 0 do
  281.             if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding,
  282.                                           tkDot, tkIdentifier, tkComma,
  283.                                           tkGreaterThan, tkLessThan, tkspecialize] then
  284.               continue else
  285.             if outTokens[j].TokenKind = tkBraceOpen then
  286.             begin
  287.               if j > 0 then classToken := outTokens[j-1].TokenKind
  288.               break
  289.             end else break
  290.           if classToken in[tkclass, tkobject, tkinterface, tkdispinterface] then continue
  291.         end
  292.  
  293.         nextToken := tkLineEnding
  294.         for j := i+1 to outTokenCount-1 do
  295.           if outTokens[j].TokenKind in [tkComment, tkTab, tkWhiteSpace, tkLineEnding] then
  296.             continue else
  297.           begin
  298.             nextToken := outTokens[j].TokenKind
  299.             break
  300.           end
  301.         if nextToken in TokensNotIndicatingStatementContinuation then
  302.           InsertIntoOutput(prevTokenPos+1, tkSemicolon, ';')
  303.       end
  304.     end
  305. end
  306.  
  307. procedure AddSemicolons(AInputName, AOutputName : string)
  308. begin
  309.   ReadInput(AInputName)
  310.   AddSemicolonsInOutput
  311.   WriteOutput(AOutputName)
  312. end
  313.  
  314. procedure FixSemicolons(AInputName, AOutputName : string)
  315. begin
  316.   ReadInput(AInputName)
  317.   RemoveSemicolonsInOutput
  318.   AddSemicolonsInOutput
  319.   WriteOutput(AOutputName)
  320. end
  321.  
  322. {********************** Testing *********************}
  323.  
  324. type
  325.   { TPointHelper }
  326.  
  327.   TPointHelper = record helper for TPoint
  328.     function Sum: integer
  329.   end
  330.  
  331.   function TPointHelper.Sum: integer
  332.   begin
  333.     result := x + y
  334.   end
  335.  
  336. procedure TestStatements
  337. var c: char
  338. begin
  339.   write('hihi');;
  340.  
  341.   //test empty statement
  342.   if true then nil
  343.  
  344.   //test case else
  345.   case random(4) of
  346.     1: nil
  347.     7: if true then write('haha');
  348.     else write('hoho')
  349.   end
  350.  
  351.   c := 'A'
  352.   case c of
  353.     'B': nil
  354.     'C': if true then write('haha')
  355.     otherwise
  356.       nil
  357.   end
  358. end
  359.  
  360. {******************* Main program *******************}
  361.  
  362. var
  363.   sourceFile, targetFile, mode: string
  364.  
  365. begin
  366.   if ParamCount < 2 then
  367.   begin
  368.     writeln('Usage: semicolonless -L|-M|-F <input file> [<output file>]')
  369.     writeln
  370.     writeln('-L : less semicolons (default extension .less)')
  371.     writeln('-M : more semicolons (default extension .pas)')
  372.     writeln('-F : fix semicolons')
  373.     halt
  374.   end
  375.  
  376.   mode := paramstr(1)
  377.   if copy(mode,1,1) <> '-' then
  378.   begin
  379.     writeln('Expecting mode')
  380.     halt
  381.   end
  382.  
  383.   sourceFile := paramstr(2)
  384.   if not FileExists(sourceFile) then
  385.   begin
  386.     writeln('Input file not found')
  387.     halt
  388.   end
  389.  
  390.   if ParamCount >= 3 then
  391.     targetFile := paramStr(3)
  392.     else targetFile := ''
  393.  
  394.   if mode = '-L' then
  395.   begin
  396.     if targetFile = '' then targetFile := ChangeFileExt(sourceFile,'.less') else
  397.     if ExtractFileExt(targetFile) = '' then targetFile += '.less'
  398.     RemoveSemicolons(sourceFile, targetFile)
  399.   end else
  400.   if mode = '-M' then
  401.   begin
  402.     if targetFile = '' then targetFile := ChangeFileExt(sourceFile, '.pas') else
  403.     if ExtractFileExt(targetFile) = '' then targetFile += '.pas'
  404.     AddSemicolons(sourceFile, targetFile)
  405.   end else
  406.   if mode = '-F' then
  407.   begin
  408.     if targetFile = '' then targetFile := sourceFile
  409.     FixSemicolons(sourceFile, targetFile)
  410.   end else
  411.     writeln('Unknown mode')
  412. end.
Title: Re: Making the semicolon useless
Post by: ASBzone on April 07, 2020, 12:08:12 am
Same code without useless semicolons:
Code: Delphi  [Select][+][-]
  1. program semicolonless
  2. ...
  3. end.

I'm sorry...  I usually take great interest in the feature request posts (regardless of my own personal feelings about the feature in question, the discussions and reasoning are generally helpful, intriguing and enlightening to me.

For this specific request, however, my mind is boggled.

Not only can I not see what the point is, or what would be gained, but in order to help various parsers figure out what the programmer deemed a single statement to be, all line endings would become important, and an additional character would need to be provided to support multi-line statements.

 :o :o :o

Yes, yes, the request will be "optional", yet that code will have to exist and be a branch for the code that is used by people who have no desire for this feature.

I really can't see the benefit in the least.

And I looked at the semicolonless code and generated a seg fault.  The simultaneous recognition of pascal like syntax, but without semicolons, was quite odd.

Okay... Back to my corner...
Title: Re: Making the semicolon useless
Post by: circular on April 07, 2020, 09:47:53 am
To put things in perspective...

I made a comment on a topic that proposes a "Go-flavoured" Pascal compiler. And as you may know, Go does not have semicolons at the end of lines. So I suggested to remove the semicolons. This sparked a discussion and marcov reproached me of invading the thread with another topic. So I created this stand-alone topic.

I personally don't think semicolons are the most important thing. Though I find it beautiful without semicolons to be honest.

Quote
an additional character would need to be provided to support multi-line statements.
I am not sure, but I can see one case where this may be useful. For example if you make a call on the next line:
Code: Pascal  [Select][+][-]
  1. MyProc
  2. (MyParameter)

This would be interpreted as two lines. Though one can avoid that by writing:
Code: Pascal  [Select][+][-]
  1. MyProc(
  2. MyParameter)

In a way that makes the code less ambiguous anyway at first glance.
Title: Re: Making the semicolon useless
Post by: munair on April 07, 2020, 10:16:57 am
The semicolon is useless most of the time. Though sometimes, it makes a difference. So I am thinking that we could simply avoid these cases and remove the semicolon completely. It seems that many people agree, though we can make it a compiler option so that anyone is free to do as they want.
I have not read all the comments to your idea so my comment might be superfluous, but I have two remarks.

1. Have you ever looked at how a compiler is designed and what kind of impact it has to change basic syntax rules? It might be analogous to designing a brand new language.

2. The semicolon as a statement terminator is very useful, both from a readability and from a practical point of view. Consider the following BASIC example without semicolon support:
Code: FreeBasic  [Select][+][-]
  1. buf = "command " _
  2.   + spec _
  3.   + ext _
  4.   + libs _
  5.   + switch _
  6.   + outp
... and the same with semicolon support:
Code: FreeBasic  [Select][+][-]
  1. buf = "command "
  2.   + spec
  3.   + ext
  4.   + libs
  5.   + switch
  6.   + outp;
As you can see, without a statement terminator, every statement must be written on a single line. IMO a statement terminator is preferable over a statement continuation symbol.
Title: Re: Making the semicolon useless
Post by: munair on April 07, 2020, 11:41:12 am
For completeness, there is a difference between statement separators and statement terminators. In Pascal the semicolon is a statement separator, whereas in C it is a statement terminator. I prefer the latter.

Because Go was mentioned in this discussion, it also uses the semicolon as a statement separator. While optional, the Go compiler inserts it where omitted, which IMO is not a good approach.

I have been programming with BASIC type languages that use the line ending as statement terminator. While simple and seemingly convenient, many times I wished for an explicit terminator if it were only for code readability, which is always an issue with high level programming languages.

The only language that really qualifies for not needing a statement separator or terminator is assembly.
(EDIT: an explicit separator symbol of course)
Title: Re: Making the semicolon useless
Post by: lucamar on April 07, 2020, 12:11:03 pm
The only language that really qualifies for not needing a statement separator or terminator is assembly.

Note that (almost?) all assemblers do require that statements end (or is separated from the next) with a line end, and assembly sintax is (usually) even stricter than Pascal, which is why it's so (relatively) easy to write one. Not really a good example, is it?  ;D

Indeed, explicit statement separators/terminator where introduced to be able to disregard extra spaces, including line ends, and thus allow for "free-format" gramars (as compared to the strict column/line oriented ones of the far past).
Title: Re: Making the semicolon useless
Post by: munair on April 07, 2020, 12:19:57 pm
The only language that really qualifies for not needing a statement separator or terminator is assembly.

Note that (almost?) all assemblers do require that statements end (or is separated from the next) with a line end, and assembly sintax is (usually) even stricter than Pascal, which is why it's so (relatively) easy to write one. Not really a good example, is it?  ;D
I was speaking in terms of explicit separators. I consider the line ending an implicit separator if it is treated as such by the compiler; it is impossible to forget a line ending by the programmer unless you put two statements on one line which really doesn't make sense: mov ax, 1 mov dx, 2  :(
Title: Re: Making the semicolon useless
Post by: marcov on April 07, 2020, 01:14:36 pm
Because Go was mentioned in this discussion, it also uses the semicolon as a statement separator. While optional, the Go compiler inserts it where omitted, which IMO is not a good approach.

For Goers (Goists?), it would be interesting to see how GO solves the quoted error generation case.
Title: Re: Making the semicolon useless
Post by: circular on April 07, 2020, 02:08:17 pm
2. The semicolon as a statement terminator is very useful, both from a readability and from a practical point of view. Consider the following BASIC example without semicolon support:
Code: FreeBasic  [Select][+][-]
  1. buf = "command " _
  2.   + spec _
  3.   + ext _
  4.   + libs _
  5.   + switch _
  6.   + outp
... and the same with semicolon support:
Code: FreeBasic  [Select][+][-]
  1. buf = "command "
  2.   + spec
  3.   + ext
  4.   + libs
  5.   + switch
  6.   + outp;
This was fixed in VB.Net by guessing line continuation. Now you very rarely need write explicit line continuation. So you see it is not either one or the other.

In fact the only case where there is a need for a terminator/separator, is when it would make sense to start a new instruction on the new line. In the example you provided, the + symbol cannot start a statement, so there is no ambiguity.
Title: Re: Making the semicolon useless
Post by: munair on April 07, 2020, 02:57:25 pm
In fact the only case where there is a need for a terminator/separator, is when it would make sense to start a new instruction on the new line. In the example you provided, the + symbol cannot start a statement, so there is no ambiguity.
Maybe not in this particular example, but that would require the programmer to know where and where not to break a statement to the next line. What if you break it before an identifier? It would add a LOT of complexity to the compiler to distinguish between an assignment, procedure call or line continuation.

Language design is all about consistency, or at least it should be, and explicit statement termination was introduced to provide just that - to leave no ambiguous situations as to when a statement ends, apart from the fact that it greatly improves readability, which, as I said earlier is often a big issue with high level languages.

Also think about language extension. Without clarity and consistency, compiler engineers quickly would need to resort to patch work making maintenance/extension more and more difficult over time. Having everything in place consistently leaves little to no room for ambiguity making a compiler so much more simple to maintain and extend. Believe me, I know this from first hand experience.

Also, do not mix the statement separation/termination issue with other building blocks like Pascal's IF statement, which I agree, isn't the best or easiest to understand.

In any case, redesigning FPC to make the statement separator optional simply is NOT doable nor preferable. I can say this with confidence even without having looked one single time at the FPC source code. It would require a complete redesign of the parser which in turn would greatly affect the parts of the compiler that are directly parser-dependent to the extent that the compiler will break completely. Trust me, you'd be better off designing a new language.
Title: Re: Making the semicolon useless
Post by: guest65405 on April 07, 2020, 07:07:15 pm
I have several likenesses in behaviour and account data, some of which I have commented on here. If you insist, I'll pass it all on to my co moderators for judgement in a query about account deletion.

Or you can just own up to it, and get a fair last chance, just because I also overstepped a bit in a bad mood.

Despite you deleted your account the last time when I pmed you with warnings, I should still have gone that way instead of posting in the thread out of the blue. Mea culpa, and a last chance for you if you are honest about it.

I liked Pascal but I don't like Lazarus. Indeed I don't like the RAD philosophy.

I want to make Pascal a normal language like C++, do not stuck with any frameworks and free to do everything as a general purpose language.

Did anyone ever think about using Pascal to code GTK+ alongside with Glade and not through the LCL abstraction?

This is my idea.

Creating the IUP binding is part of my project to de-Lazarus Free Pascal. But after I actually use it on my projects I found it opened another can of worms. In anyway, when we do GUI we need a designer. I don't have knowledge do build a designer. And the way IUP was designed it needs to paired with languages like LED or Lua to be useful. So what is the point at all? All the efforts I made go to nothing.

It's circular reasoning. We need a designer to do GUI efficiently with IUP without relying on languages like LED or Lua. But we don't have it and have to write one. In other to write one we need to do GUI in IUP since we avoided the LCL. So on and so on.

I give it up sir. You are free to think about me the way you like. I will delete my account, you don't have to care about me anymore.

I hope someday someone capable will pick up my idea and actually turn it to real. A Pascal without Lazarus. But I think it will never happen.

p/s: Believe it or not, I'm not the troll you mentioned.
Title: Re: Making the semicolon useless
Post by: howardpc on April 07, 2020, 07:39:53 pm
I hope someday someone capable will pick up my idea and actually turn it to real. A Pascal without Lazarus. But I think it will never happen.
It is certainly not likely to be pursued with any enthusiasm on a forum which is dedicated in both name and purpose to Lazarus.
Title: Re: Making the semicolon useless
Post by: Fred vS on April 07, 2020, 07:54:28 pm
Quote
I hope someday someone capable will pick up my idea and actually turn it to real. A Pascal without Lazarus. But I think it will never happen.

MSEide, MaXimus from fpGUI, ideU?

https://wiki.freepascal.org/IDE
Title: Re: Making the semicolon useless
Post by: marcov on April 07, 2020, 08:05:53 pm
Quote
Did anyone ever think about using Pascal to code GTK+ alongside with Glade and not through the LCL abstraction?

Yes.

p.s. fpgtk before fpgui, even.
Title: Re: Making the semicolon useless
Post by: Fred vS on April 07, 2020, 08:12:09 pm
Quote
p.s. fpgtk before fpgui, even.

Hu, fpgtk, what is that, no mention in wiki?

https://wiki.freepascal.org/IDE
Title: Re: Making the semicolon useless
Post by: 440bx on April 07, 2020, 08:27:05 pm
A Pascal without Lazarus. But I think it will never happen.
It has already happened.  FPC doesn't need Lazarus in any way to produce an object file.

I don't use Lazarus as a RAD.  I only use it as a front end to GDB.  I use FPC as a replacement for C.

I agree with Munair.  The semicolon isn't an "ornament" in the language grammar.  Without it, the parser would have to work a lot harder to figure out where a new statement begins and, trivial syntax errors could make that determination ambiguous in many cases, leading to poor error messages (and quite likely several tokens _after_ the error actually is.) Most compilers aren't particularly good about emitting precise, genuinely informative error messages, an "improvement" that makes emitting good error messages harder or impossible for the compiler simply is no improvement at all.

Can the semicolon be removed from Pascal ?... probably, after all, PL/I allows the programmer to define variables named the same as "reserved" words.  If that can be parsed,  Pascal without semicolons can likely be parsed too but, the question that comes to mind is, why would anyone invest the time and aggravation in producing such a parser ?... a small semicolon for man, a giant leap for Computer Science ?... I don't think that one will go down in history.
 



Title: Re: Making the semicolon useless
Post by: marcov on April 07, 2020, 09:07:52 pm
Quote
p.s. fpgtk before fpgui, even.

Hu, fpgtk, what is that, no mention in wiki?

https://wiki.freepascal.org/IDE

Sebastian worked on a parallel IDE called Kassandra with the KCL as library around 2000. However that was massive and progressed slowly, so he created a OOP wrapper for GTK (1.2 on *nix/ 1.3 on Windows)called FPGTK library to do his current projects.

One or two years later, he got more windows customers, and created FPGUI library  to have one library for both gtk and windows (GDI) for immediate use.

The first editor/ide for fpdoc documentation files was called fpde and was a fpgtk application.

 
Title: Re: Making the semicolon useless
Post by: Fred vS on April 07, 2020, 09:18:25 pm
Ha, it was also Sebastian that did it!

Wow, very creative man.

I did find a program file here:

fpc/trunk/packages/fpgtk/src/pgtk/pgtk.pp

Is it still maintained and compilable (first shot was not out-of-the-box)?

Title: Re: Making the semicolon useless
Post by: marcov on April 07, 2020, 10:04:56 pm
fpc/trunk/packages/fpgtk/src/pgtk/pgtk.pp

Is it still maintained and compilable (first shot was not out-of-the-box)?

As far as I can see I migrated it from the old base/extra structure to the unified packages/ in 2008, and nothing has been done with it since. The mutations seem to be only makefile regenerations and spelling fixes in comments and license tests.

And, you'd have to dig out gtk1 somewhere.
Title: Re: Making the semicolon useless
Post by: Fred vS on April 07, 2020, 10:06:55 pm
About pgtk.pp, OK, I get it, adding some -Fu../* did the trick.

Hum, it is a command-line that gives without parameter as result:

Quote
Give 2 filenames :
   First the object description file
   Second the Pascal unit filename

Hum, ok, must jump into it to catch the thing.

Anyway, thanks Marco for the discover.

And sorry to monopolize with something out of the topic.

Fre;D
Title: Re: Making the semicolon useless
Post by: munair on April 12, 2020, 07:55:45 am
All of the things you mentioned, do not work. Some abandoned. Some hopelessly outdated. These broken things can't be used to hide the fact we are so dependent on the LCL.

I have done my work to do GUI without the LCL. Thanks to the Windows API and a wrapper library I ported from C. But I still have to use Lazarus as IDE because there is no real alternative.
Don't be surprised. Nowadays GUIs are huge and it is a lot of work to just keep things up-to-date. Windows is just one part. GTK development is going so fast, it is hard to keep up, especially by people who do not get paid for it.
Title: Re: Making the semicolon useless
Post by: munair on April 14, 2020, 09:27:58 am
Back to the topic, another perhaps not so trivial reason not to abandon the semicolon is the ability to arrange code in a way that makes it easier to read/understand. This can be the case with more complex expressions that otherwise would have to be crammed on a single line.

Here is a somewhat exaggerated example from the project I'm working on, but it illustrates the issue very well:
Code: Text  [Select][+][-]
  1. func leapy(y:int):bool
  2. do
  3.   leapy =
  4.     (
  5.       y % 4 = 0
  6.     and
  7.       y % 100 <> 0
  8.     )
  9.     or
  10.     (
  11.       y % 400 = 0
  12.     ); // semicolons are a blessing
  13. end;

It computes leap years according to the Gregorian calendar and it is one of my favorites to test expression parsing. Each part of the expression can be comfortably commented on. With more complex programs this is non-trivial. It definitely makes them easier to read and maintain, even after several years when the function of certain parts have become less obvious  ;)
Title: Re: Making the semicolon useless
Post by: 440bx on April 14, 2020, 11:43:09 am
@Munair,

An unrelated question, I see your function uses the function name to assign it a return value.  Do you plan to implement something like "result" in FPC in your compiler to optionally use that instead of the function's name ?
Title: Re: Making the semicolon useless
Post by: circular on April 14, 2020, 12:13:10 pm
Here is a somewhat exaggerated example from the project I'm working on, but it illustrates the issue very well:
Code: Text  [Select][+][-]
  1. func leapy(y:int):bool
  2. do
  3.   leapy =        //last token "=" expects something after
  4.     (            //token expects something after
  5.       y % 4 = 0
  6.     and          //token expects something before and after
  7.       y % 100 <> 0
  8.     )            //token expects something before
  9.     or           //token expects something before and after
  10.     (            //token expects something after
  11.       y % 400 = 0
  12.     );           //first token ")" expects something before
  13. end;
In fact this expression is not a problem. It depends a bit of the rules using to continue lines, but using the rules I proposed before, it would work, because there are tokens that either need something afterwards or something before. I have put each case as comments in the code.
Title: Re: Making the semicolon useless
Post by: munair on April 14, 2020, 12:23:06 pm
@Munair,

An unrelated question, I see your function uses the function name to assign it a return value.  Do you plan to implement something like "result" in FPC in your compiler to optionally use that instead of the function's name ?

That is a good question and after yesterday's discussion I am seriously thinking about it. But it might have a somewhat different form, a 'variable' name that makes it even more obvious that it belongs to the function, maybe something like 'funcr'. A name like 'result' is still too general for my taste.

Of course, 'return' is also supported, but that would generate the extra jump instruction.
Title: Re: Making the semicolon useless
Post by: marcov on April 14, 2020, 12:28:42 pm
What do you think of C++/M2 return <x>?

Saves on typing, but isn't a pseudo function like syntax. (IOW syntax that isn't used anywhere else)

p.s. keep in mind that Pascal parsers generally only have one token lookahead.
Title: Re: Making the semicolon useless
Post by: munair on April 14, 2020, 12:29:58 pm
Here is a somewhat exaggerated example from the project I'm working on, but it illustrates the issue very well:
Code: Text  [Select][+][-]
  1. func leapy(y:int):bool
  2. do
  3.   leapy =        //last token "=" expects something after
  4.     (            //token expects something after
  5.       y % 4 = 0
  6.     and          //token expects something before and after
  7.       y % 100 <> 0
  8.     )            //token expects something before
  9.     or           //token expects something before and after
  10.     (            //token expects something after
  11.       y % 400 = 0
  12.     );           //first token ")" expects something before
  13. end;
In fact this expression is not a problem. It depends a bit of the rules using to continue lines, but using the rules I proposed before, it would work, because there are tokens that either need something afterwards or something before. I have put each case as comments in the code.

I invite you to develop a compiler that supports the rules you suggest. Do you have any idea how much more complicated and *less* efficient an expression parser becomes having to consider line endings? Not to mention the lexer!

Why make it so much more complicated while a statement terminator makes the statement unambiguous and allows for much more accurate error reporting?
Title: Re: Making the semicolon useless
Post by: munair on April 14, 2020, 12:32:47 pm
What do you think of C++/M2 return <x>?

Saves on typing, but isn't a pseudo function like syntax. (IOW syntax that isn't used anywhere else)

p.s. keep in mind that Pascal parsers generally only have one token lookahead.
Great suggestion.

BTW, SharpBASIC also has only one look-ahead character.
Title: Re: Making the semicolon useless
Post by: marcov on April 14, 2020, 12:43:17 pm
BTW, SharpBASIC also has only one look-ahead character.

But does it require line continuations ? Because then the line separator acts as a semicolon in pascal, so that would not be comparable.
Title: Re: Making the semicolon useless
Post by: munair on April 14, 2020, 12:54:34 pm
BTW, SharpBASIC also has only one look-ahead character.

But does it require line continuations ? Because then the line separator acts as a semicolon in pascal, so that would not be comparable.

No! Line endings are considered garbage by the lexer and line continuations such as BASIC's underscore would generate a syntax error. For example, the function assignment in leapy would be lexed as:

Code: Text  [Select][+][-]
  1.  1000         BOI           CHARACTER     BOI
  2.  3006         leapy         LITERAL       IDENTIFIER
  3.  4001         =             OPERATOR      =
  4.  5006         (             SYMBOL        (
  5.  3006         y             LITERAL       IDENTIFIER
  6.  4009         %             OPERATOR      %
  7.  3002         4             LITERAL       INTEGER
  8.  4001         =             OPERATOR      =
  9.  3002         0             LITERAL       INTEGER
  10.  6001         and           KEYWORD       and
  11.  3006         y             LITERAL       IDENTIFIER
  12.  4009         %             OPERATOR      %
  13.  3002         100           LITERAL       INTEGER
  14.  4002         <>            OPERATOR      <>
  15.  3002         0             LITERAL       INTEGER
  16.  5009         )             SYMBOL        )
  17.  6022         or            KEYWORD       or
  18.  5006         (             SYMBOL        (
  19.  3006         y             LITERAL       IDENTIFIER
  20.  4009         %             OPERATOR      %
  21.  3002         400           LITERAL       INTEGER
  22.  4001         =             OPERATOR      =
  23.  3002         0             LITERAL       INTEGER
  24.  5009         )             SYMBOL        )
  25.  5010         ;             SYMBOL        ;
  26.  1001         EOI           CHARACTER     EOI

whereby BOI=beginning of input and EOI = end of input. Spaces, tabs, line feeds, line comments and block comments are filtered out.
Title: Re: Making the semicolon useless
Post by: circular on April 14, 2020, 06:35:37 pm
I invite you to develop a compiler that supports the rules you suggest. Do you have any idea how much more complicated and *less* efficient an expression parser becomes having to consider line endings? Not to mention the lexer!
That might be the case, though your example doesn't work, and you're not admitting it.  :P
Title: Re: Making the semicolon useless
Post by: circular on April 25, 2020, 01:37:22 pm
I had a look at FPC compiler and wow it would need a lot of refactoring.

Things that surprised me for example:
- global variables in scanner units are used to store values that would rather be inside the scanner class.
- other units accessing characters (stored in global variable c) directly instead of using token.
Title: Re: Making the semicolon useless
Post by: 440bx on April 25, 2020, 02:07:59 pm
I had a look at FPC compiler and wow it would need a lot of refactoring.
Aside from the things you found.  Removing the semicolon from the Pascal syntax would significantly increase the amount of work the compiler would have to perform in order to emit anything that would be a half-way decent error message.
Title: Re: Making the semicolon useless
Post by: marcov on April 25, 2020, 02:10:42 pm
This has been discussed many times. The answer is that these were deliberately left out when OOPing the compiler from 1.0.x to 2.x because they had a measurable impact on speed.

That doesn't mean it couldn't/shouldn't be reevaluated though. Modern processors scale things in relative tight loops up more than other things, so bottlenecks might have changed. But afaik FPK regularly plays with these kind of things.

Actually since a recent FPC get-together I asked, about internal parallelization (threads in the compiler), for which this (global state reduction) would be important too.

But the problem was that that isn't the hard part, the problem to tackle this is in the module system, iow the toplevel bit that handles if units should be recompiled etc, and the way compiling cascades from program to unit to unit etc.

This part is said to be enormously complex with many pitfalls, and has been scheduled for a rewrite for over 15 years now. (originally pushed to "after 2.0", then to "after 2.2" etc etc)
Title: Re: Making the semicolon useless
Post by: circular on April 25, 2020, 02:48:36 pm
@marcov

For sure going full OOP would slow down the compiler. Though there are other ways to encapsulate.

In the case of the scanner, for example, many public functions are not actually used elsewhere, and just making one or two virtual functions would probably not have so much effect. Then one could instantiate a derived class that would act as a bridge to do some preprocessing.

The main obstacle I see is rather that direct access to characters would be possible only in a scanner, which would require some refactoring. For example, the assembler scanner is not actually defined as a scanner, but hacks into the current scanner.

Regarding parallel compilation, I imagine that encapsulating everything could be even more work and that some deep refactoring would be needed for thread safety.

@440px

I feel your pessimism.
Title: Re: Making the semicolon useless
Post by: munair on April 26, 2020, 01:25:15 am
I invite you to develop a compiler that supports the rules you suggest. Do you have any idea how much more complicated and *less* efficient an expression parser becomes having to consider line endings? Not to mention the lexer!
That might be the case, though your example doesn't work, and you're not admitting it.

Apparently I missed this one. I'm not sure what doesn't work or what there is to admit. My example was to illustrate (as I said literally) "the ability to arrange code in a way that makes it easier to read/understand", which has nothing to do with the question whether or not a parser can swallow it without a semicolon. With enough time almost anything can be done. The question is if it is preferable.
TinyPortal © 2005-2018