• Re: question about linker

    From Waldek Hebisch@21:1/5 to Keith Thompson on Sat Nov 30 00:55:01 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Bart <bc@freeuk.com> writes:
    It's another point of confusion. In my language I don't treat function
    declarations like variable declarations. A function is not a
    variable. There is no data storage associated with it.

    In C, declarations can declare objects, functions, types, etc. I fail
    to see how your language is relevant.

    In C it is unfortunate, as it makes it hard to trivially distinguish a
    function declaration (or the start of a function definition) from a
    variable declaration.

    It's not as hard as you insist on pretending it is. A function
    declaration includes a pair of parentheses, either empty or
    containing a list of parameters or parameter types.

    Function declarations outside header files are valid, but tend to be
    rare in well-written C code.

    Hmm, in well-written code static functions are likely to be a
    majority. Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself. Conseqently, function declarations are not
    rare in such code. Do you consider it well-written?

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Sat Nov 30 00:57:56 2024
    On 29/11/2024 23:44, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    On 29/11/2024 20:35, Keith Thompson wrote:

    (So it would have a different type from E declared on in the same
    declaration:

    int D[3][4][5], E;

    ? In that case tell that to David Brown!)

    Yes, of course D and E have different types. I'm certain he's
    aware of that.

    Apparently the quibble is about the meaning of 'totally different'. I
    would have thought that 'incompatible' would have covered it.

    But it looks like, for the sake of argument, types aren't 'totally'
    different if they have even the slightest point of similarity. So an
    'int' type, and a bloody great function, not even a real type, must be considered somewhat identical if the latter happens to returns an int?

    In my language which you despise but provides a great perspective,
    variables declared in the same declaration have 100% the same type. If
    they are even 1% different, then that is a separate type and they need
    their own declarations. They are no gradations!

    What "range of types" do you think D can have?

    If DB is talking about the type of D[i][j][k], then it is also necessary
    to consider the types of D, D[i] etc. That's why it's not useful to talk
    about anything other than the type of the value stored in D (and in C,
    before D is used in any expression).

    Would you write "const int F();"? Or would you omit the "const"? How
    does the fact that "const" is allowed inconvenience you?

    It's another point of confusion. In my language I don't treat function
    declarations like variable declarations. A function is not a
    variable. There is no data storage associated with it.

    In C, declarations can declare objects, functions, types, etc.

    Actually types would be another category, that can also start off
    looking like a variable declaration.

    to see how your language is relevant.

    Because it's confusing in C. The perspective of a quite different syntax
    /for the same class of language/ makes that extra clear to me.

    In C all declarations are based around the syntax as used for variables,
    even function definitions.


    In C it is unfortunate, as it makes it hard to trivially distinguish a
    function declaration (or the start of a function definition) from a
    variable declaration.

    It's not as hard as you insist on pretending it is. A function
    declaration includes a pair of parentheses, either empty or
    containing a list of parameters or parameter types.

    Yes it is, I'm not pretending at all.

    Perhaps you can post a trivial bit of C code which reads in C source
    code and shows the first lines of all the function definitions, not
    prototypes nor function pointers. It can assume that each starts at the beginning of a line.

    However each may start with a user-defined type or there may be a macros
    in any positions.

    I can tell that in my syntax, function definitions start with a line
    like this ([...] means optional; | separates choices):

    ['global'|'export'] 'func'|'proc' name ...

    Which one do you think would be easier? (Function declarations are
    generally not used.)

    Function declarations outside header files are valid, but tend to be
    rare in well-written C code.

    Function declarations are everywhere. They are usually needed for static function otherwise you will have hundreds of function definitions that
    must be written and maintained in a specific order.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Waldek Hebisch on Fri Nov 29 20:38:51 2024
    On 11/29/24 19:55, Waldek Hebisch wrote:
    ...
    Hmm, in well-written code static functions are likely to be a
    majority. Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself. Conseqently, function declarations are not
    rare in such code. Do you consider it well-written?

    I wouldn't go so far as to say that it's poorly written, but I don't
    like the unnecessary redundancy of that approach. Whenever possible, I
    prefer to let each static function's definition serve as it's only
    declaration. This isn't possible, for instance, if you have a pair of
    mutually recursive functions.

    The redundancy between a header file's function declaration and the corresponding function definition is necessary, given the way that C
    works. Avoiding that is one of the reasons I like declaring static
    functions, where appropriate.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Sat Nov 30 04:03:39 2024
    On 30.11.2024 00:44, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]

    The point is that there are restrictions on what can be combined into a single declaration. But these days it's usually considered good style
    to declare only one identifier in each declaration, [...]

    For quite large values of "these days"; for more than 3 decades as far
    as my observation goes. - Deviations I've mostly only seen in contexts
    of, say, uninitialized loop variables, like 'int i, j, k;'. But there's
    also some folks who just don't care. That's why we had that regulated
    with our coding standards in these early days.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sat Nov 30 04:13:21 2024
    On 30.11.2024 01:57, Bart wrote:
    [...]

    In my language [...],
    variables declared in the same declaration have 100% the same type. If
    they are even 1% different, then that is a separate type and they need
    their own declarations. They are no gradations!

    Reminds me the Pascal days, where (depending on the Pascal dialect)
    there were differences what grade of Strong Typing was implemented.
    Is a homonymous type declarator the same type, or only if the same
    'type' declaration is used? - was a question that had been answered
    differently by Pascal implementations. (IIRC)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Sat Nov 30 04:25:24 2024
    On 30.11.2024 02:28, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    I can tell that in my syntax, function definitions start with a line
    like this ([...] means optional; | separates choices):

    ['global'|'export'] 'func'|'proc' name ...

    Which one do you think would be easier? (Function declarations are
    generally not used.)

    I don't care.

    Yes, languages than C can have better declaration syntax than C does
    (where "better" is clearly subjective). Perhaps yours does. [...]

    From the various bits and pieces spread around I saw that Bart had
    obviously adopted many syntactical elements of Algol 68, and I wonder
    why he hadn't used just this language (or any "better" language than
    "C") if he dislikes it so much that he even implemented own languages.
    But okay.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Sat Nov 30 11:59:34 2024
    On 30/11/2024 03:25, Janis Papanagnou wrote:
    On 30.11.2024 02:28, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    I can tell that in my syntax, function definitions start with a line
    like this ([...] means optional; | separates choices):

    ['global'|'export'] 'func'|'proc' name ...

    Which one do you think would be easier? (Function declarations are
    generally not used.)

    I don't care.

    Yes, languages than C can have better declaration syntax than C does
    (where "better" is clearly subjective). Perhaps yours does. [...]

    From the various bits and pieces spread around I saw that Bart had
    obviously adopted many syntactical elements of Algol 68, and I wonder
    why he hadn't used just this language (or any "better" language than
    "C") if he dislikes it so much that he even implemented own languages.

    It needed to be a lower level language that could be practically
    implemented on a then small machine.

    Algol68 implementations were scarce especially on 8-bit systems.

    But I also considered it too high level and hard to understand. Even the
    syntax had features I didn't like, like keyword stropping and fiddly
    rules about semicolon placement.

    As for better languages than C, there were very few at that level. Even
    C was not so practical: C compilers cost money (I wasn't a programmer,
    my boss wouldn't pay for it!).

    There would have been problems just getting it into the machine (since
    on CP/M, every machine used its own disk format). And by the accounts I
    read later on in old Byte magazine articles, C compilers were hopelessly
    slow running on floppy disks. (Perhaps Turbo C excepted.)

    By the time C might have been viable, I found that my language was
    preferable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Sat Nov 30 11:46:24 2024
    On 30/11/2024 01:28, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    Perhaps you can post a trivial bit of C code which reads in C source
    code and shows the first lines of all the function definitions, not
    prototypes nor function pointers. It can assume that each starts at
    the beginning of a line.

    No. It's straightforward for an experienced C programmer looking at
    code that's not deliberately obscure. A program that can do the same
    thing reliably would have to include a C preprocessor and parser.

    It's obvious that :
    int foo(int);
    is intended to be a function declaration,

    By itself? Sure. Within a large very busy source file, it'll get lost in
    the noise. Where is the start of each function? I don't want to analyse
    each line!

    A week ago somebody on reddit posted a link to a C project. The source
    code was unusual: it was 'clean' for a start, but also each function
    started with:

    func ....

    Presumably that was some empty macro; I don't recall.

    But an amazing thing happened: if viewed within my editor, I could
    navigate between functions with PageUp and PageDown keys. That's never
    happened before with C. (Note this is /my/ crude text-mode editor.)

    Normally, to do that, I'd have to use a visualisation tool to turn C
    code into my syntax, then it becomes instantly clear. (Unfortunately I
    can't compile it; that would need a lot more work.)


    I acknowledged elsewhere that I forgot about declarations of static functions. (Hundreds of function definitions in a single source file
    seem unlikely.)


    I'm working with a single-file Lua implementation. It has 880 function definitions. My SQL test file has 2100 functions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Sat Nov 30 09:10:52 2024
    On 11/29/24 22:25, Janis Papanagnou wrote:
    ...
    From the various bits and pieces spread around I saw that Bart had
    obviously adopted many syntactical elements of Algol 68, and I wonder
    why he hadn't used just this language (or any "better" language than
    "C") if he dislikes it so much that he even implemented own languages.
    But okay.

    No existing language meets Bart's needs as well as his own does. He
    attributes this to all of the other language designers being idiots for creating those languages, and to all the other languages' users being
    idiots for not rejecting those languages. He refuses to accept the
    possibility that his own preferences for language design might be
    somewhat idiosyncratic.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Bart on Sat Nov 30 14:44:09 2024
    On 30/11/2024 11:46, Bart wrote:
    On 30/11/2024 01:28, Keith Thompson wrote:

    It's obvious that :
         int foo(int);
    is intended to be a function declaration,

    By itself? Sure. Within a large very busy source file, it'll get lost in
    the noise. Where is the start of each function? I don't want to analyse
    each line!

    A week ago somebody on reddit posted a link to a C project. The source
    code was unusual: it was 'clean' for a start, but also each function
    started with:

     func ....

    Presumably that was some empty macro; I don't recall.

    But an amazing thing happened: if viewed within my editor, I could
    navigate between functions with PageUp and PageDown keys. That's never happened before with C.

    This project:

    https://github.com/PascalBeyer/Headerless-C-Compiler/tree/main/src

    Although it still won't let me easily search for a specific function,
    since there is still an arbitrary type between 'func' and the function name.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sat Nov 30 16:57:41 2024
    On 29/11/2024 19:26, Bart wrote:
    On 29/11/2024 16:42, David Brown wrote:
    On 29/11/2024 15:15, Michael S wrote:
    On Fri, 29 Nov 2024 13:33:30 +0000
    Bart <bc@freeuk.com> wrote:


    * It allows a list of variable names in the same declaration to each
        have their own modifiers, so each can be a totally different type >>>>

    They can't have "totally different" types - they can have added
    indirection or array indicators, following C's philosophy of
    describing the type by how the variable is used:

         int x, *y, z[10];

    Thus "x", "*y" and "z[i]" are all of type "int".

    C's syntax allows a 14-parameter function F to be declared in the same statement as a simple int 'i'.

    And the laws of physics allow me to drop a 20 kg dumbbell on my toe.
    That does not mean that anyone thinks it is a good idea.



    I'd say that F and i are different types! (Actually I wouldn't even
    consider F to be type, but a function.)

    Functions have types in most typed languages, including C.

    And yes, F and i are different types - but they are related types. Use
    the declared identifier in an expression of a form matching what you
    wrote in the declaration, and the expression will have type "int".
    That's how C's declarations work.



    That F(1, 2, 3.0, "5", "six", seven, ...) might yield the same type as
    'i' is irrelevant here.

    No, it is exactly the point - it is how C is defined.


    Usually, given these declarations:

      int A[100]
      int *B;
      int (*C)();

    people would consider the types of A, B and C to be array, pointer and function pointer respectively. Otherwise, which of the 4 or 5 possible
    types would you say that D has here:

    They are different - but related - types.


      int D[3][4][5];

    It depends on how it is used in an expression, which can be any of &D,
    D, D[i], D[i][j], D[i][j][k], none of which include 'Array' type!

    Here's another puzzler:

      const int F();

    why is 'const' allowed here? There is no storage involved. It's not as
    though you could write 'F = 0' is there was no 'const'.

    "const" is allowed here because it is part of the type returned by F().

    Really, most of this is pretty straightforward. No one is asking you to
    /like/ the rules of C's declarations (I personally dislike that a single declaration can be used for different types, even if they are related).
    But /please/ stop pretending it's difficult to understand.


    C allows this, but I personally would be happier if it did not.  As
    Michael says below, most serious programmers don't write such code.

    It doesn't matter. If you're implementing the language, you need to
    allow it.

    I am not implementing the language. No one else here is implementing
    it. You have, apparently, implemented at least some of the language
    while being completely incapable of understanding it. I am surprised
    that is possible, but it is what you seem to be claiming.



    If trying to figure out why some people have trouble understanding, it's something to consider.


    I have met a good many C programmers over the years, and some of them
    have had misunderstandings. I have never heard of anyone who comes
    close to your level, however.

    For most people new to C, it's enough to tell them that "int* a, b;"
    declares "a" as a "pointer to int" and "b" as an "int". You tell them
    it is a bad idea to write such code, even re-arranged as "int *a, b;",
    because it is easy to get wrong - they should split the line into two declarations (preferably with initialisations). The C newbie will thank
    you for the lesson, and move on to write C code without writing such
    mixed declarations.

    /That/ is how you solve problems with syntax that can be abused to write unclear code.

    It's also something to keep in mind if trying to understand somebody
    else's code: are they making use of that feature or not?

    So this is a wider view that just dismissing design misfeatures just
    because you personally won't use them.


    So what is your preferred solution? Whine endlessly on newsgroups for
    decades on end about the same things you dislike, to people who have
    absolutely no influence on the thing that bothers you? How productive
    has that been for you?

    The sane response to a "design misfeature" is to avoid using it
    yourself, and encourage others to stop using it when you see them doing so.

    With the kind of C I would write, you could discard everything after
    C99, and even half of C99, because the subset I personally use is very conservative.


    You say that as though you think it is a good thing - it is not.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to James Kuyper on Sat Nov 30 19:08:29 2024
    On Fri, 29 Nov 2024 20:38:51 -0500
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

    On 11/29/24 19:55, Waldek Hebisch wrote:
    ...
    Hmm, in well-written code static functions are likely to be a
    majority. Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself. Conseqently, function declarations are not
    rare in such code. Do you consider it well-written?

    I wouldn't go so far as to say that it's poorly written, but I don't
    like the unnecessary redundancy of that approach. Whenever possible, I
    prefer to let each static function's definition serve as it's only declaration. This isn't possible, for instance, if you have a pair of mutually recursive functions.

    The redundancy between a header file's function declaration and the corresponding function definition is necessary, given the way that C
    works. Avoiding that is one of the reasons I like declaring static
    functions, where appropriate.

    Top-down-minded people don't like details textually preceding "big
    picture".

    [O.T.]
    Better solution would be if static function definition anywhere in the
    file serves like declaration (prototype) for the whole file, including preceding part. We are long past the time where single-pass compiler
    was a legit argument against such arrangement. Nowadays the only
    possible counter argument would be breaking existing code. But I don't
    see how such change breaks anything.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Sat Nov 30 09:54:30 2024
    Michael S <already5chosen@yahoo.com> writes:

    IMHO, any way to mix more than one 'modifier' (not in C standard
    meaning of the word, but in more general meaning) is potentially
    confusing. It does not matter whether modifier is 'const' or '*'
    or [] or ().

    It surprises me that you would say this. Certainly there are type
    forms that might be difficult to absorb (e.g., 'float *********')
    but that doesn't mean they are necessarily confusing. There are two
    obvious ways to write type forms that are easy to decode. One way
    is to write any derivings right-to-left:

    [] * (double,double) * float

    which can be read directly as "array of pointer to function that
    returns a pointer to float", and the other way is simply the reversal
    of that:

    float * (double,double) * []

    which can be read right-to-left the same way. The constructors for
    derived types (pointer, array, function) act like nouns. Qualifiers
    such as const or volatile act like adjectives and always go to the
    left of the noun they modify, so for example

    [] volatile* float

    is an array of volatile pointer to float, or in the other ordering

    float volatile* []

    which is simply a reversal of noun phrases, with any modifying
    adjectives staying on the left side of the noun they modify.

    The syntax used in C is harder to read for two reasons: one, the
    ordering of derivations is both left-to-right and right-to-left,
    depending on what derivation is being applied; and two, any
    identifier being declared goes in the middle of the type rather
    than at one of the ends. Both of those confusions can be removed
    simply by using a consistent ordering, either left-to-right or
    right-to-left (with qualifying adjectives always on the left of
    the noun they modify).

    Note that both of the consistent orderings correspond directly to a
    natural English wording, which accounts for them being easier to
    comprehend than C-style type forms. (I conjecture that some foreign
    languages might not have that property, but since I am for the most
    part ignorant of essentially all natural languages other than
    English I have no more to say about that.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sat Nov 30 17:38:19 2024
    On 30/11/2024 15:57, David Brown wrote:
    On 29/11/2024 19:26, Bart wrote:


    C's syntax allows a 14-parameter function F to be declared in the same
    statement as a simple int 'i'.

    And the laws of physics allow me to drop a 20 kg dumbbell on my toe.
    That does not mean that anyone thinks it is a good idea.

    Who said it's a good idea? I merely said that C allows such disparate
    types in declarations. You disagree that they are different types, while
    at the same time saying it's a bad idea to mix them in the same declaration!

    I'd say that F and i are different types! (Actually I wouldn't even
    consider F to be type, but a function.)

    Functions have types in most typed languages, including C.

    And yes, F and i are different types - but they are related types.  Use
    the declared identifier in an expression of a form matching what you
    wrote in the declaration, and the expression will have type "int".
    That's how C's declarations work.

    That's not how people's minds work. If you declare A, B, and C, then
    what is important is the types of A, B, and C, not what might yielded as
    they result of some expression.

    People can write A in an expression using all the modifiers specified
    for it, or they can write with none or some of the modifiers, or they
    might write &A; generally they will yield different types.

    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable with type 'ref i32' (expressed in other syntax)
    B is a local variable with type '[10]i32'
    C is a function with return type of 'i32', taking one unnamed
    parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same declaration
    can also create names in different scopes!)

    However writing:

    A; B; C;

    creates expressions with types 'ref i32', 'ref i32', and 'ref
    proc(i32)i32' according to C rules. All quite different from your claim
    that they all yield 'int' (while C makes the scalar A and array B the
    same type!).

    So the key types are what are specified in the symbol table. And those
    are different and incompatible.

    BTW here are A, B, C in my syntax:

    ref i32 A
    [10]i32 B

    proc(i32)i32 C

    (The last is a function declaration, which only exist for FFI functions;
    it can only appear in an 'importdll' block.)

    I don't think anyone outside the C world would consider even A and B as
    having related types - int vs array - let alone C. Yet you are claiming
    this.


    Really, most of this is pretty straightforward.  No one is asking you to /like/ the rules of C's declarations (I personally dislike that a single declaration can be used for different types, even if they are related).
    But /please/ stop pretending it's difficult to understand.

    I keep saying that my language is easier than this with simpler rules.
    That makes C harder. It also makes it more errorprone. It can make it
    more confusing. That is just the truth.


    C allows this, but I personally would be happier if it did not.  As
    Michael says below, most serious programmers don't write such code.

    It doesn't matter. If you're implementing the language, you need to
    allow it.

    I am not implementing the language.  No one else here is implementing
    it.  You have, apparently, implemented at least some of the language
    while being completely incapable of understanding it.

    And you seem utterly incapable of understanding that A implementing some complicated and badly designed system X doesn't mean that A becomes an
    expert in using X, or suddenly thinks of it as simple and well-designed.

    Quite the opposite in fact, since they get to see the nitty-gritty
    details, and especially where people have papered over the cracks.

    They will also get to see a vast amount of badly written code that
    breaks all the rules, compared to B who not only uses just their
    prefered subset of X, but additional systems Y and Z to hide some of the problems.


    /That/ is how you solve problems with syntax that can be abused to write unclear code.

    You solve it by fixing the language. If you can't fix the language then
    you use a strong workaround, such as a new syntax wrapper around it.

    The C newbie will thank
    you for the lesson, and move on to write C code without writing such
    mixed declarations.

    You can't give such a lesson to everyone, so there will still be a
    million programmers who pick up bad habits, not helped by the tools they
    use being lax.


    With the kind of C I would write, you could discard everything after
    C99, and even half of C99, because the subset I personally use is very
    conservative.


    You say that as though you think it is a good thing - it is not.

    Why?

    I reckon people will have an easier type understanding and working with
    my code than yours. It will at least work with more compiles.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to James Kuyper on Sat Nov 30 17:59:41 2024
    On 30/11/2024 14:10, James Kuyper wrote:
    On 11/29/24 22:25, Janis Papanagnou wrote:
    ...
    From the various bits and pieces spread around I saw that Bart had
    obviously adopted many syntactical elements of Algol 68, and I wonder
    why he hadn't used just this language (or any "better" language than
    "C") if he dislikes it so much that he even implemented own languages.
    But okay.

    No existing language meets Bart's needs as well as his own does.

    He
    attributes this to all of the other language designers being idiots for creating those languages, and to all the other languages' users being
    idiots for not rejecting those languages.

    In this group, I am only saying that my systems language does systems programming better than C does.

    It fixes lots of the problems and issues with C.

    C has changed little. There might be valid reasons for that (although a
    lot more could have been done in 50 years: Fortran has changed beyond recognition in just 40).


    He attributes this to all of the other language designers being idiots
    for creating those languages


    When other languages require you to write:

    @import("std").debug.print("A={} B={}\n", .{a, b});

    while I normally write:

    println =a, =b

    then you're damn right about what I think of the creator of that
    language! Zig, in case you don't recognise it.

    Which also, initially, refused to recognises CRLF line endings in source
    files, because the creator hated Microsoft. And which still bans the use
    of hard tabs.

    He refuses to accept the
    possibility that his own preferences for language design might be
    somewhat idiosyncratic.


    Actually, my stuff is remarkably conservative. Being simple and clean is
    a characteristic.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Bart on Sat Nov 30 20:17:35 2024
    On 30/11/2024 17:38, Bart wrote:

    If I write this

      int *A, B[10], C(int);

    However writing:

      A; B; C;

    creates expressions with types 'ref i32', 'ref i32', and 'ref
    proc(i32)i32' according to C rules.

    BTW here are A, B, C in my syntax:

       ref i32 A
       [10]i32 B

       proc(i32)i32 C

    (The last is a function declaration, which only exist for FFI functions;
    it can only appear in an 'importdll' block.)

    Although nobody here will care in the slightest, that last is the wrong
    syntax and irks me. It wasn't fully converted from the function pointer
    version earlier. The proper syntax would be:

    func C(i32)i32

    The name is placed earlier. This helps draw a firmer line between
    functions and variables.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to James Kuyper on Sun Dec 1 10:47:05 2024
    On 30.11.2024 15:10, James Kuyper wrote:
    On 11/29/24 22:25, Janis Papanagnou wrote:
    ...
    From the various bits and pieces spread around I saw that Bart had
    obviously adopted many syntactical elements of Algol 68, and I wonder
    why he hadn't used just this language (or any "better" language than
    "C") if he dislikes it so much that he even implemented own languages.
    But okay.

    No existing language meets Bart's needs as well as his own does. He attributes this to all of the other language designers being idiots for creating those languages, and to all the other languages' users being
    idiots for not rejecting those languages. He refuses to accept the possibility that his own preferences for language design might be
    somewhat idiosyncratic.

    It would probably have been good - and I don't say that ironically
    or anything - if Bart would either have presented his language(s)
    on the market (to be part of the competition process for the best
    product), or if he would have participated in the standardization
    committees (to get his design ideas discussed, and then implemented
    or dismissed).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Sun Dec 1 10:55:30 2024
    On 30.11.2024 16:57, David Brown wrote:

    For most people new to C, it's enough to tell them that "int* a, b;"
    declares "a" as a "pointer to int" and "b" as an "int". You tell them
    it is a bad idea to write such code, even re-arranged as "int *a, b;", because it is easy to get wrong - they should split the line into two declarations (preferably with initialisations). The C newbie will thank
    you for the lesson, and move on to write C code without writing such
    mixed declarations.

    That's why the newbies are preferred for programming; they are flexible,
    cheap, and they do what they are told. ;-) (Sorry, could not resist.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sun Dec 1 10:36:17 2024
    On 30.11.2024 12:59, Bart wrote:
    On 30/11/2024 03:25, Janis Papanagnou wrote:

    From the various bits and pieces spread around I saw that Bart had
    obviously adopted many syntactical elements of Algol 68, and I wonder
    why he hadn't used just this language (or any "better" language than
    "C") if he dislikes it so much that he even implemented own languages.

    It needed to be a lower level language that could be practically
    implemented on a then small machine.

    Okay.


    Algol68 implementations were scarce especially on 8-bit systems.

    Indeed. (If existing at all; I can't tell.)


    But I also considered it too high level and hard to understand.

    This I find astonishing, given that it is (IMO; and different from C)
    a so cleanly defined language.

    Even the
    syntax had features I didn't like, like keyword stropping

    Stropping was a way to solve the limited characters available in the
    system character sets. Practically, as an implementer, you could use
    any mechanism you like. (On the mainframe I had used symbols preceded
    by a dot, the Genie compiler uses uppercase, for example. None is a
    problem for the implementer.)

    and fiddly rules about semicolon placement.

    Huh? - The semicolon placement as delimiters is quite clear and (as so
    many things in Algol 68) also clearly defined (IMO). - So what do you
    have in mind here?


    As for better languages than C, there were very few at that level.

    (But you know you can use Algol 68 on a system development level; we
    can read that it had been done at those day. - All that's "missing",
    and that's a good design decision, were pointers.)

    But okay, it's of course a personal judgement what's "better", and
    what you like to use to program or like to use as a paragon for an
    own language design and own implementation.

    Even
    C was not so practical: C compilers cost money (I wasn't a programmer,
    my boss wouldn't pay for it!).

    At those days everything had cost money. (Probably with the notable
    exception of UNIX, as they say, which had more sort of a fee than a
    market price, at least for the universities.) But, according to some
    historic sources I read, you also payed primarily the system not the
    software; vendors supported availability of languages to sell their
    hardware.


    There would have been problems just getting it into the machine (since
    on CP/M, every machine used its own disk format). And by the accounts I
    read later on in old Byte magazine articles, C compilers were hopelessly
    slow running on floppy disks. (Perhaps Turbo C excepted.)

    (I don't get what argument you are trying to make. - That you wanted
    some terse language, maybe, as you already said above?)


    By the time C might have been viable, I found that my language was preferable.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sun Dec 1 12:03:32 2024
    On 01/12/2024 11:34, David Brown wrote:

    "int", "void" and "double" are totally different types in my view.
    "int", "pointer to int", "array of int", "function returning int" all
    have a relation that means I would not describe them as /totally/
    different types - though I would obviously still call them /different/
    types.


    What about 'array of int', 'array of double' and 'array of void*'; do
    they have a relation too?

    Your examples, expressed left-to-right, happen to share the last
    element. They could also share other elements; so what?

    Function declarations outside header files are valid, but tend to be
    rare in well-written C code.


    A function definition - as typically written - is also a function declaration.  So presumably you mean non-defining declaration here.

    Some people have a style where they write forward declarations of all functions defined in a C file near the top of the file.  I am not a fan
    of that myself - especially as over time, this redundant information is rarely kept fully in sync with the rest of the code.

    That's a separate problem. But without forward declarations, at some
    point you're going to add some expression in the middle of the file, but
    find you're calling a function which is declared later on in the file
    rather than earlier.

    That's not something you want to waste time thinking about.

    When I first wrote a big C program, I used a 300-line script to convert
    a thinly syntax-wrapped version of C, into actual C.

    The script also generated an include file of all static function
    declarations (which was included in this module) and a separate file of exported function declarations.

    Everything was automatically kept in sync.

    Now, why can't the language do that?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Sun Dec 1 11:52:17 2024
    On 01/12/2024 09:36, Janis Papanagnou wrote:
    On 30.11.2024 12:59, Bart wrote:

    [About Algol68]

    But I also considered it too high level and hard to understand.

    This I find astonishing, given that it is (IMO; and different from C)
    a so cleanly defined language.

    Algol68 was famous for its impenetrable specification. Its Revised
    Report was the programming language equivalent of James Joyce's 'Ulysses'.

    I needed a clean simple syntax and 100% obvious and explicit semantics.

    Even the
    syntax had features I didn't like, like keyword stropping

    Stropping was a way to solve the limited characters available in the
    system character sets. Practically, as an implementer, you could use
    any mechanism you like. (On the mainframe I had used symbols preceded
    by a dot, the Genie compiler uses uppercase, for example. None is a
    problem for the implementer.)

    Yes, but they made writing, reading and maintaining source code
    impossible. You'd spend most of your time switching case, or babysitting semicolons (see below).

    I can live without embedded spaces within identifiers - most languages
    do. That was the primary reason for the stropping.

    If I really need to use a reserved word as an identifier now (which only happens if porting from another language), I can use a backtick:

    int `Int, `INT, `Int

    This also enables case-sensitivity (my syntax was case-insensitive). I
    don't think case-stropping for example can manage that.

    and fiddly rules about semicolon placement.

    Huh? - The semicolon placement as delimiters is quite clear and (as so
    many things in Algol 68) also clearly defined (IMO). - So what do you
    have in mind here?

    It just makes life harder. It special-cases the last statement of any
    block, which must be semicolon free, as it's strictly a separator. So:

    * Adding a new statement to the end of a block, you must apply ; to the
    current last statement

    * Deleting the last line, you must delete the ; on the previous.

    * Move any of the lines about, and you may again need to update the
    semicolons if the last was included

    * Temporarily comment out lines including the last, you must also
    temporarily remove ; from the line before the comments

    * Copy the whole block elsewhere, you might need to add ;

    * Temporarily comment out a whole block (or start off with an empty
    block that will be populated later) you need to use SKIP, another annoyance.

    Usually you're not aware of this until the compiler tells you and you
    have to go back in and fix it.

    Allow semicolons to be a /terminator/, and all that goes away. It's a no brainer. But then I don't like having to write semicolons at all, and
    generally I don't.

    The whole thing with stropping and semicolons is just a colossal
    time-waster.

    As for better languages than C, there were very few at that level.

    (But you know you can use Algol 68 on a system development level; we
    can read that it had been done at those day. - All that's "missing",
    and that's a good design decision, were pointers.)

    The only actual implementation I've come across is A68G. That's an
    interpreter.

    It runs my Fibonacci benchmark in 16 seconds. My main /dynamic/ language interpreter runs it in 1.3 seconds. My C interpreter, which I consider hopelessly slow, takes 6 seconds. My unoptimised C is 0.24 seconds.

    Optimised C is 0.12 seconds, 130 times faster than A68G.

    It's quite unsuited to systems programming, and not just because of its execution speed. However, I'd quite like to see A68G implemented in A68G!

    Algol68 was a fascinating and refreshing language back then. It looked
    great when typeset in a book. But its practicalities were annoying, and
    now it is quite dated.


    There would have been problems just getting it into the machine (since
    on CP/M, every machine used its own disk format). And by the accounts I
    read later on in old Byte magazine articles, C compilers were hopelessly
    slow running on floppy disks. (Perhaps Turbo C excepted.)

    (I don't get what argument you are trying to make. - That you wanted
    some terse language, maybe, as you already said above?)

    That there were practical problems in physically getting the program
    into the machine. And when it did run, it would have taken minutes to
    build anything rather than seconds.

    (See: https://archive.org/details/byte-magazine-1983-08/page/n111/mode/2up

    A chart of compile-times is on page 122. The same issue compares 8086 C compilers, and introduces the C language.)

    A lot of my HLL programs were short and intended to test some hardware.
    My resident in-memory compiler translated them more or less instantly. A
    formal build using disk-based programs, source files, object files, and
    linkers would have been too time-consuming (little has changed!).

    I was generally regarded as a whizz-kid; that would have been difficult
    to keep up if my boss saw me twiddling my thumbs everytime he looked in.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Sun Dec 1 12:34:41 2024
    On 30/11/2024 00:44, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    On 29/11/2024 20:35, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    C's syntax allows a 14-parameter function F to be declared in the same >>>> statement as a simple int 'i'.
    Yes (except that it's a declaration, not a statement) :
    int i = 42, F(int, int, int, int, int, int, int,
    int, int, int, int, int, int, int);
    Are you under the impression that anyone here was not already aware
    of
    that? Would you prefer it if the number of parameters were arbitrarily
    restricted to 13?
    Do you think that anyone would actually write code like the above?
    C generally doesn't impose arbitrary restrictions. Because of that,
    it's possible to write absurd code like the declaration above. 99% of
    programmers simply don't do that, so it's not a problem in practice.

    I'd say that F and i are different types! (Actually I wouldn't even
    consider F to be type, but a function.)
    Neither F nor i is a type. i is an object (of type int), and F is a
    function (of type int(int, int, int, int, int, int, int, int, int, int,
    int, int, int, int)).

    That F(1, 2, 3.0, "5", "six", seven, ...) might yield the same type as >>>> 'i' is irrelevant here.
    It's relevant to the syntax. i and F can be declared in the same
    declaration only because the type of i and the return type of F happen
    to be the same. If F returned void, i and F would have to be declared
    separately.
    Which, of course, is a good idea anyway.
    You're posting repeatedly trying to convince everyone that C allows
    ridiculous code. We already know that. You are wasting everyone's time >>> telling us something that we already know. Most of us just don't obsess >>> about it as much as you do. Most of us recognize that, however
    convoluted C's declaration syntax might be, it cannot be fixed in a
    language calling itself "C".
    Most of us here are more interested in talking about C as it's
    specified, and actually trying to understand it, than in complaining
    about it.

    Usually, given these declarations:

    int A[100]
    int *B;
    int (*C)();

    people would consider the types of A, B and C to be array, pointer and >>>> function pointer respectively. Otherwise, which of the 4 or 5 possible >>>> types would you say that D has here:

    int D[3][4][5];

    It depends on how it is used in an expression, which can be any of &D, >>>> D, D[i], D[i][j], D[i][j][k], none of which include 'Array' type!
    No, the object D unambiguously has type int[3][4][5]

    (So it would have a different type from E declared on in the same
    declaration:

    int D[3][4][5], E;

    ? In that case tell that to David Brown!)

    Yes, of course D and E have different types. I'm certain he's
    aware of that.

    Yes, I am. (I know you wisely dislike speaking for other people, but
    you are pretty good at it!)


    I wrote that the object D is unambiguously of type int[3][4][5], and the expression D can be of the array type int[3][4][5] or of the pointer
    type int(*)[3][4], depending on the context. Do you agree? Or do you
    still claim that D can have any of "4 or 5 possible types"?

    (Note that I'm not talking about the type of the expression D[i] or of
    any other expression that includes D as a subexpression.)

    You seem have missed the point of my post, which was a reply to
    David's remark that 'they can't have totally different types' which
    was in response to my saying that each variable in the same
    declaration can 'be [of] a totally different type'.

    David apparently has a different definition of "totally different types"
    than you do. Since the standard doesn't define that phrase, I suggest
    not wasting time arguing about it.


    "int", "void" and "double" are totally different types in my view.
    "int", "pointer to int", "array of int", "function returning int" all
    have a relation that means I would not describe them as /totally/
    different types - though I would obviously still call them /different/
    types.

    The syntax of C allows one declaration statement to declare multiple identifiers of types related in this way - it does not allow declaration
    of types of /totally/ different types.

    That was the point I was trying, and clearly failing, to explain to Bart.


    Given:
    int D[3][4][5], E;
    the object D is of type int[3][4][5], and E is of type int. Do you understand that?

    If you wanted to change the type of D from int[3][4][5] to
    double[3][4][5], you'd have to use two separate declarations.
    Do you understand that? (Of course you do, but will you admit that
    you understand it?)

    I think that distinction is what David had in mind. double[3][4][5] and
    int are "totally different types", but int[3][4][5] and int are not.
    Entities of "totally different types" cannot be declared in a single declaration. You don't have to accept that meaning of the phrase (which
    I find a bit vague), but it's clearly what David meant.

    It is certainly a vague term - there is no well-defined difference
    between "totally different types" and "different types". But since Bart specifically called them /totally/ different types, the only way I could interpret that is suggesting that they could be any types at all. And
    as we all know (even Bart, though he seems determined to feign
    ignorance), multiple identifiers in the same declaration cannot be of completely independent types.


    The point is that there are restrictions on what can be combined into a single declaration. But these days it's usually considered good style
    to declare only one identifier in each declaration, so while this :
    int i, *p;
    is perfectly valid, and every C compiler must accept it, this :
    int i;
    int *p;
    is preferred by most C programmers.

    Do you understand that?

    DB is assuming the type of the variable after it's been used in an
    expression that is fully evaluated to yield its base type. So my
    A[100] is used as A[i], and D[3][4][5] is used as D[i][j][k].

    I was trying to explain that this the principle C syntax uses - "A" and
    "D" have different types, but expressions of the same format as used in
    the common declaration have a common type.


    But of course they may be evaluated only partially, yielding a range
    of types.

    What "range of types" do you think D can have?

    Would you write "const int F();"? Or would you omit the "const"? How
    does the fact that "const" is allowed inconvenience you?

    It's another point of confusion. In my language I don't treat function
    declarations like variable declarations. A function is not a
    variable. There is no data storage associated with it.

    In C, declarations can declare objects, functions, types, etc. I fail
    to see how your language is relevant.

    In C it is unfortunate, as it makes it hard to trivially distinguish a
    function declaration (or the start of a function definition) from a
    variable declaration.

    It's not as hard as you insist on pretending it is. A function
    declaration includes a pair of parentheses, either empty or
    containing a list of parameters or parameter types.

    Function declarations outside header files are valid, but tend to be
    rare in well-written C code.


    A function definition - as typically written - is also a function
    declaration. So presumably you mean non-defining declaration here.

    Some people have a style where they write forward declarations of all
    functions defined in a C file near the top of the file. I am not a fan
    of that myself - especially as over time, this redundant information is
    rarely kept fully in sync with the rest of the code. But it is
    definitely something you'll sometimes see in real-world C code. (You
    could argue that the code is then not "well-written" C, but that would
    be a very subjective opinion.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Waldek Hebisch on Sun Dec 1 14:50:40 2024
    On 30/11/2024 01:55, Waldek Hebisch wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Bart <bc@freeuk.com> writes:
    It's another point of confusion. In my language I don't treat function
    declarations like variable declarations. A function is not a
    variable. There is no data storage associated with it.

    In C, declarations can declare objects, functions, types, etc. I fail
    to see how your language is relevant.

    In C it is unfortunate, as it makes it hard to trivially distinguish a
    function declaration (or the start of a function definition) from a
    variable declaration.

    It's not as hard as you insist on pretending it is. A function
    declaration includes a pair of parentheses, either empty or
    containing a list of parameters or parameter types.

    Function declarations outside header files are valid, but tend to be
    rare in well-written C code.

    Hmm, in well-written code static functions are likely to be a
    majority. Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself. Conseqently, function declarations are not
    rare in such code. Do you consider it well-written?


    Without doubt, most functions (and non-local data) should be static.

    However, IMHO writing (non-defining) declarations for your static
    functions is a bad idea unless it is actually necessary to the code
    because you are using them in function pointers or have particularly
    good reasons for the way you order your code.

    I don't find redundant declarations of static functions at all useful -
    and I find them of significant cost in maintaining files. It is far too
    easy to forget to update them when you change, delete or add new
    functions. And a list of such declarations that you don't feel you can
    trust entirely, is worse than useless.

    Such lists might have been helpful to some people decades ago, when
    editors were more primitive. If I need a list of functions in a file
    (maybe it's someone else's code, or old code of mine), any programmer's
    editor or IDE will give me it - updated correctly in real-time, and not
    out of sync.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sun Dec 1 14:23:30 2024
    On 01/12/2024 13:50, David Brown wrote:
    On 30/11/2024 01:55, Waldek Hebisch wrote:

    Hmm, in well-written code static functions are likely to be a
    majority.  Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself.  Conseqently, function declarations are not
    rare in such code.  Do you consider it well-written?


    Without doubt, most functions (and non-local data) should be static.

    I have a tool that translates C programs to my syntax. Most functions of codebases I tried are marked 'global', because the C version did not use 'static'.

    Generally those functions don't need to be exported. This is just
    laziness or ignorance on the part of the program, not helped by C using
    the wrong default.

    However, IMHO writing (non-defining) declarations for your static
    functions is a bad idea unless it is actually necessary to the code
    because you are using them in function pointers or have particularly
    good reasons for the way you order your code.

    A good reason might be NOT CARING how the code is ordered. I have to
    constantly keep that in mind when writing C programs. I don't like
    movings functions about after they've been written, it is easier to add
    a forward declaration, even though I'd rather not do that at all.

    It is just another annoyance.

    Some people may also prefer top-down ordering of their functions.

    I don't find redundant declarations of static functions at all useful -
    and I find them of significant cost in maintaining files.  It is far too easy to forget to update them when you change, delete or add new
    functions.  And a list of such declarations that you don't feel you can trust entirely, is worse than useless.

    Why doesn't the compiler report a declaration that doen't match the
    definition?


    Such lists might have been helpful to some people decades ago, when
    editors were more primitive.  If I need a list of functions in a file
    (maybe it's someone else's code, or old code of mine), any programmer's editor or IDE will give me it - updated correctly in real-time, and not
    out of sync.

    Why isn't this a problem for exported/shared functions?

    That is, for all sorts of functions and variables declared in headers
    where there is a declaration in header, and a definition in some 'home'
    module.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sun Dec 1 15:34:04 2024
    On 01/12/2024 13:03, Bart wrote:
    On 01/12/2024 11:34, David Brown wrote:

    "int", "void" and "double" are totally different types in my view.
    "int", "pointer to int", "array of int", "function returning int" all
    have a relation that means I would not describe them as /totally/
    different types - though I would obviously still call them /different/
    types.


    What about 'array of int', 'array of double' and 'array of void*'; do
    they have a relation too?


    In a different context, yes - they can all be used in expressions of the
    form "a[i]". Different context, different relationship.

    Your examples, expressed left-to-right, happen to share the last
    element. They could also share other elements; so what?


    All I was saying is that it is wrong to say a single declaration can
    have identifiers of /totally/ different types - the types you are
    allowed to use in one declaration have a very clear relationship with
    each other.

    Function declarations outside header files are valid, but tend to be
    rare in well-written C code.


    A function definition - as typically written - is also a function
    declaration.  So presumably you mean non-defining declaration here.

    Some people have a style where they write forward declarations of all
    functions defined in a C file near the top of the file.  I am not a
    fan of that myself - especially as over time, this redundant
    information is rarely kept fully in sync with the rest of the code.

    That's a separate problem. But without forward declarations, at some
    point you're going to add some expression in the middle of the file, but
    find you're calling a function which is declared later on in the file
    rather than earlier.

    That's not something you want to waste time thinking about.

    It's not something I find to be a noticeable issue. I prefer, on the
    whole, to avoid forward declarations - I like to order by code so that functions are defined before they are called. It makes it easier to see
    the structure of the code and call trees. There are exceptions when I
    feel a different order is clearest, but those are rare and I can put up
    with writing static function declarations in those cases. (For
    non-static functions, there is invariably a declaration in a matching
    header file.)

    I can see some advantages in a language being happy with any order of
    function definition, without requiring forward declarations to use a
    function before it is defined. But C is not like that, and I cannot
    honestly say it bothers me one way or the other. And apparently, it
    does not particularly bother many people - there is, I think, no serious impediment or backwards compatibility issue that would prevent C being
    changed in this way. Yet no one has felt the need for it - at least not strongly enough to fight for it going in the standard or being a common compiler extension.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sun Dec 1 15:49:42 2024
    On 30/11/2024 18:38, Bart wrote:
    On 30/11/2024 15:57, David Brown wrote:
    On 29/11/2024 19:26, Bart wrote:


    C's syntax allows a 14-parameter function F to be declared in the
    same statement as a simple int 'i'.

    And the laws of physics allow me to drop a 20 kg dumbbell on my toe.
    That does not mean that anyone thinks it is a good idea.

    Who said it's a good idea? I merely said that C allows such disparate
    types in declarations. You disagree that they are different types, while
    at the same time saying it's a bad idea to mix them in the same
    declaration!

    So if we all agree that it's a bad idea, and no one does it, why is it
    such a problem for you?


    I'd say that F and i are different types! (Actually I wouldn't even
    consider F to be type, but a function.)

    Functions have types in most typed languages, including C.

    And yes, F and i are different types - but they are related types.
    Use the declared identifier in an expression of a form matching what
    you wrote in the declaration, and the expression will have type "int".
    That's how C's declarations work.

    That's not how people's minds work.

    Are you extrapolating from how /you/ think, to how everyone else (or at
    least, every other C programmer) thinks? Given the negligible support
    you have here for most (though not all) of your multitudes of pet hates
    in C, I think that's a rather bold approach.

    If you declare A, B, and C, then
    what is important is the types of A, B, and C, not what might yielded as
    they result of some expression.


    Why do you think that? After all, A, B and C are going to be used
    primarily in those types of expression. If "A" is an array, you will
    use it as "A[i]" in the majority of cases - and care about the type of
    "A[i]" more than the type of "A".

    Note - in case you missed it - that personally I would prefer if C did
    not allow declaring identifiers of different types together. And I
    would probably have preferred a declaration syntax where the identifier
    comes either fully before, or fully after, all type-related symbols.

    But C is defined the way it is defined, and with good logical
    justification. Most C programmers find it helpful to understand that.

    With the kind of C I would write, you could discard everything after
    C99, and even half of C99, because the subset I personally use is
    very conservative.


    You say that as though you think it is a good thing - it is not.

    Why?

    I reckon people will have an easier type understanding and working with
    my code than yours.

    You are joking, right? If you are not lying about how confusing you
    find C and how error-prone you think it is, then your C code works by
    luck. And that is not something people are going to find easy to
    understand. (And if you are talking about your own language, then no
    one else understands it.)

    It will at least work with more compiles.


    And why would that matter? No actual developer would care if their code
    can be compiled by your little toy compiler, or even more complete
    little tools like tcc. Code needs to work on the compilers that are
    suitable for the job - compatibility with anything else would just be a
    waste of effort and missing out on useful features that makes the code
    better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sun Dec 1 16:08:49 2024
    On 01.12.2024 12:52, Bart wrote:
    On 01/12/2024 09:36, Janis Papanagnou wrote:
    On 30.11.2024 12:59, Bart wrote:

    [About Algol68]

    But I also considered it too high level and hard to understand.

    This I find astonishing, given that it is (IMO; and different from C)
    a so cleanly defined language.

    Algol68 was famous for its impenetrable specification. Its Revised
    Report was the programming language equivalent of James Joyce's 'Ulysses'.

    I see, you mostly find the specification document hard to understand,
    and you have a point. (Not that I think that the C standard documents
    texts that are occasionally posted here would be easy to understand.
    Standards are certainly no textbooks. Myself, for example, I had the
    arguable honor to implement an X.500 system for an European telephone
    directory collaboration; the ITU-T X.500 series was vastly copious.)

    Where I'd disagree is if you mean that Algol 68 as a language is, from
    a programmer's perspective, hard to understand. Compared to "C" I think
    it's a lot simpler (despite its richness of language features) due to
    its clear formal design (and as opposed to "C" with all its design
    quirks). And that's also true if compared with languages that have a
    more streamlined design. (YMMV.)


    I needed a clean simple syntax and 100% obvious and explicit semantics.

    Looks like we agree. (But you obviously came to a different conclusion
    than me.)

    [ Stropping ]

    Yes, but they made writing, reading and maintaining source code
    impossible. [...]

    Really? - For me it's exactly the opposite; having the keywords stand
    out lexically (or graphically) is what adds to legibility! (Even if I
    design and formulate an algorithm as a sketch on paper or white board
    I underline the keywords. On a contemporary terminal you'd use syntax highlighting [ that some folks, as I've learned, also don't like ].)

    (I admit that hitting the Shift or the Caps-Lock key may be considered cumbersome by [some/most] people. - I "pay the price" for legibility.)

    [...]

    If I really need to use a reserved word as an identifier now [...]

    (BTW, some language allows that by context sensitivity; in Unix shell,
    for example, you can write for for in in ; do : ; done without "stropping".)

    [ snip examples of "Bart's language" ]

    (It makes no sense to compare Algol 68 with "your language" and discuss
    that with me. - I understood that you find it a good idea to implement
    an own [irrelevant] language to serve your needs [and preferences].)


    and fiddly rules about semicolon placement.

    Huh? - The semicolon placement as delimiters is quite clear and (as so
    many things in Algol 68) also clearly defined (IMO). - So what do you
    have in mind here?

    It just makes life harder. It special-cases the last statement of any
    block, which must be semicolon free, as it's strictly a separator. So:

    * Adding a new statement to the end of a block, you must apply ; to the
    current last statement

    * Deleting the last line, you must delete the ; on the previous.

    * Move any of the lines about, and you may again need to update the semicolons if the last was included

    * Temporarily comment out lines including the last, you must also
    temporarily remove ; from the line before the comments

    * Copy the whole block elsewhere, you might need to add ;

    * Temporarily comment out a whole block (or start off with an empty
    block that will be populated later) you need to use SKIP, another
    annoyance.

    You have problems to separate new statements from existing ones,
    and remove that semicolon if you delete/relocate code. - Okay, I
    see where you're coming from; I'm feeling with you. - But really,
    we're typing tons of code and your problem is the semicolon in
    cases where you restructure parts of your code? - (You may be a
    candidate for using an IDE that alleviates you from such mundane
    tasks.)

    With your argumentation I'm curious what you think about having
    to add a semicolon in "C" if you replace a {...} block.
    Or, in the first place, what you think about semicolons in "C"s
    'if-else' construct (with parenthesis-blocks or single statements).
    And what's actually the "statement" in 'if(b)s;' and 'else s;'
    and what you think about 'if(b){}else{}' being a statement (or
    not, since it's lacking a semicolon).


    Usually you're not aware of this until the compiler tells you and you
    have to go back in and fix it.

    (This is obviously an issue you have; not the language. You should
    have better written "Usually I'm not aware of this ...". And that's
    of course a fair point [for you].)


    Allow semicolons to be a /terminator/, and all that goes away. It's a no brainer.

    History and also facts of contemporary languages disagree with you.
    (Re: "no brainer": You need a brain to understand or know that, of
    course. - So my suggestion to you is obvious; inform yourself.)

    But then I don't like having to write semicolons at all, and
    generally I don't.

    (You're a Python fan/candidate? - It might serve your needs here.)

    Frankly, after the era of line-oriented languages, there's a need
    in syntactically organized imperative formally specified languages
    to separate the statements from each other. (Some designers used
    terminators instead for "easier parsing", as they said.) Not using
    semicolons at all is commonly seen in shell or scripting languages
    where (again) the line termination typically fills the gap. Where I
    use Shell or Awk I also avoid spurious semicolons. But that is not
    the case in the "regular" ("non-scripting") programming languages.

    If I have terminators, good, if I have separators, good, if the
    language allows 'Empty Statements', good, if I may use 'SKIP', good,
    if I can omit it, good, if my language has line-terminated commands,
    fine. - I'm sure that someone who will have a strong opinion of
    what's good or not in that list is doomed to implement a language
    supporting his own preferences (unless choosing any existing one
    that supports is anyway).


    The whole thing with stropping and semicolons is just a colossal
    time-waster.

    (I have completely different view on that but I accept your opinion.
    For example I find it a "colossal time-waster" to write an own
    language given the many different existing ones - some even available
    in source code to continue working on an existing code base. Colossal
    is here a really perfect chosen adjective. - Your scale seems to have
    got impaired; you spot marginal time "wastes" and miss the real ones, qualitatively and quantitatively.)


    As for better languages than C, there were very few at that level.

    (But you know you can use Algol 68 on a system development level; we
    can read that it had been done at those day. - All that's "missing",
    and that's a good design decision, were pointers.)

    [ re-iterated speed argument in comparison with "own" languages
    while completely neglecting the other factors (including speed
    of development process) snipped ]

    It's quite unsuited to systems programming, and not just because of its execution speed. However, I'd quite like to see A68G implemented in A68G!

    I've heard and read, as I said, a differing thing about that.
    Specifically I recall to have read about that special topic you
    mention of writing an Algol 68 compiler in Algol 68; it has been
    done.

    (Your personal preferences and enthusiasm should not get in the way
    of either checking the facts or formulate your opinions/thoughts as
    what they are, here basically wrong assumptions based on ignorance.)


    Algol68 was a fascinating and refreshing language back then. It looked
    great when typeset in a book. But its practicalities were annoying, and
    now it is quite dated.

    You are generalizing and (beyond stropping and semicolons) vague
    about "its practicalities". (And the two specific design decisions
    you obviously have issues with are not an Algol 68 specific thing.)

    It makes me smile if you speak about "looking great when typeset",
    given that the languages we use nowadays, specifically (e.g.) "C",
    C++, don't even look good "when typeset". And the problems you/we
    buy with that are directly observable in the languages. Rather we
    seem to have accepted all their deficiencies and just work through
    (or around) them. Most do that with not complaints. What I find
    astonishing is that you - here known to complain about a lot of "C"
    details - are now praising things (and at the same time despise
    sensible concepts in an exceptionally well designed language as
    Algol 68).

    YMMV.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Sun Dec 1 16:37:01 2024
    On 01.12.2024 14:50, David Brown wrote:
    On 30/11/2024 01:55, Waldek Hebisch wrote:

    Hmm, in well-written code static functions are likely to be a
    majority. Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself. Conseqently, function declarations are not
    rare in such code. Do you consider it well-written?

    Without doubt, most functions (and non-local data) should be static.

    Most functions should be part of a 'class' declaration.

    *oops* - wrong newsgroup. ;-)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sun Dec 1 16:50:15 2024
    On 01/12/2024 15:23, Bart wrote:
    On 01/12/2024 13:50, David Brown wrote:
    On 30/11/2024 01:55, Waldek Hebisch wrote:

    Hmm, in well-written code static functions are likely to be a
    majority.  Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself.  Conseqently, function declarations are not
    rare in such code.  Do you consider it well-written?


    Without doubt, most functions (and non-local data) should be static.

    I have a tool that translates C programs to my syntax. Most functions of codebases I tried are marked 'global', because the C version did not use 'static'.

    Generally those functions don't need to be exported. This is just
    laziness or ignorance on the part of the program, not helped by C using
    the wrong default.


    I agree that the default for a language should be small scope (in this
    case, functions should be static to the file) rather than large scope.
    But it's not difficult to have a habit of adding "static" to all your
    functions that are not exported - even for a C generator.

    However, IMHO writing (non-defining) declarations for your static
    functions is a bad idea unless it is actually necessary to the code
    because you are using them in function pointers or have particularly
    good reasons for the way you order your code.

    A good reason might be NOT CARING how the code is ordered.

    I care how my code is organised and structured. I care, regardless of
    whether or not the language cares. I might be a little freer in the the ordering if the language does not require or promote a particular
    ordering - but I pick the order intentionally.

    I'd be quite happy with code in Python, or any other language which does
    not impose a bottom-up ordering like C, to be written using a top-down
    approach where each function calls other functions defined below it.
    I'd also be happy with major algorithmic functions written one place and
    small utility functions in a different section, or publicly callable
    code first then private internal code. There's lots of organisation of
    code that can make sense.

    I'd not be impressed with "don't care" as an organisation.


    I don't find redundant declarations of static functions at all useful
    - and I find them of significant cost in maintaining files.  It is far
    too easy to forget to update them when you change, delete or add new
    functions.  And a list of such declarations that you don't feel you
    can trust entirely, is worse than useless.

    Why doesn't the compiler report a declaration that doen't match the definition?


    If the declarations are a mismatch - you have a function declared and
    defined with different parameter or return types - it is an error. But
    it is not an error to declare static functions that are never defined as
    long as they are never used - so renamed or deleted functions can have
    their declarations left behind. ("gcc -Wall" will warn about this, but
    you would not want to use a tool that is potentially helpful.) And
    defining and using a static function without a forward declaration is
    rarely considered something to warn about, so missing declarations in
    the list will not be diagnosed. (Maybe clang or clang-tidy have
    warnings for that - they support more warnings than gcc.)


    Such lists might have been helpful to some people decades ago, when
    editors were more primitive.  If I need a list of functions in a file
    (maybe it's someone else's code, or old code of mine), any
    programmer's editor or IDE will give me it - updated correctly in
    real-time, and not out of sync.

    Why isn't this a problem for exported/shared functions?

    That is, for all sorts of functions and variables declared in headers
    where there is a declaration in header, and a definition in some 'home' module.


    What do you mean here?

    I certainly consider it a weakness in C that you don't have clear
    requirements and limitations for what can be in a header or a C file, or
    how things can be mixed and matched. Keeping code clear and
    well-ordered therefore requires discipline and standardised arrangement
    of code and declarations. Different kinds of projects will have
    different requirements here, but for my own code I find it best to be
    strict that for any C file "file.c", there will be a header "file.h"
    which contains "extern" declarations of any exported functions or data,
    along with any type declarations needed to support these. My tools will
    warn on any mismatches, such as non-static functions without a matching "extern" declaration. They can't catch everything - the way C is built
    up, there is no distinction between external declarations that should be defined in the same module and ones that are imported from elsewhere.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Tim Rentsch on Sun Dec 1 18:47:17 2024
    On Sat, 30 Nov 2024 09:54:30 -0800
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    Michael S <already5chosen@yahoo.com> writes:

    IMHO, any way to mix more than one 'modifier' (not in C standard
    meaning of the word, but in more general meaning) is potentially
    confusing. It does not matter whether modifier is 'const' or '*'
    or [] or ().

    It surprises me that you would say this. Certainly there are type
    forms that might be difficult to absorb (e.g., 'float *********')
    but that doesn't mean they are necessarily confusing. There are two
    obvious ways to write type forms that are easy to decode. One way
    is to write any derivings right-to-left:

    [] * (double,double) * float

    which can be read directly as "array of pointer to function that
    returns a pointer to float", and the other way is simply the reversal
    of that:

    float * (double,double) * []

    which can be read right-to-left the same way. The constructors for
    derived types (pointer, array, function) act like nouns. Qualifiers
    such as const or volatile act like adjectives and always go to the
    left of the noun they modify, so for example

    [] volatile* float

    is an array of volatile pointer to float, or in the other ordering

    float volatile* []

    which is simply a reversal of noun phrases, with any modifying
    adjectives staying on the left side of the noun they modify.


    That's nice. It's a pity it will never be adapted in C.


    The syntax used in C is harder to read for two reasons: one, the
    ordering of derivations is both left-to-right and right-to-left,
    depending on what derivation is being applied; and two, any
    identifier being declared goes in the middle of the type rather
    than at one of the ends. Both of those confusions can be removed
    simply by using a consistent ordering, either left-to-right or
    right-to-left (with qualifying adjectives always on the left of
    the noun they modify).

    Note that both of the consistent orderings correspond directly to a
    natural English wording, which accounts for them being easier to
    comprehend than C-style type forms. (I conjecture that some foreign languages might not have that property, but since I am for the most
    part ignorant of essentially all natural languages other than
    English I have no more to say about that.)

    As you can see, in a reply to my post Bart already suggested that the problematic part is not a chain itself, but mixture of terms that has
    to be read left-to-right with those has to be read right-to-left.
    You can also see that I already mostly agreed with him.
    Mostly rather than completely, because I think that when a single
    declaration has more than half a dozen terms it is difficult to
    understand even when it does not change direction in the middle.

    But my main disagreement with Bart was orthogonal to this discussion.
    It was about 'const' not being any harder to understand than other "right-to-left' type modifiers.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Sun Dec 1 16:42:02 2024
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    Yes, but they made writing, reading and maintaining source code
    impossible. [...]

    Really? - For me it's exactly the opposite; having the keywords stand
    out lexically (or graphically) is what adds to legibility!

    In my syntax, you can write keywords in capitals if you want. It's case-insensitive! People using my scripting language liked to capitalise
    them. But now colour-highlighing is widely used.


    (I admit that hitting the Shift or the Caps-Lock key may be considered cumbersome by [some/most] people. - I "pay the price" for legibility.)

    There's a lot of Shift and Caps-Lock with writing C or C-style syntax.

    [ snip examples of "Bart's language" ]

    (It makes no sense to compare Algol 68 with "your language"

    I had to look back to see what examples I'd posted. It seems you're
    refering to my backtick examples.

    I was just saying that there are ways to use reserved words as
    identifiers in the rare cases that are necessary. I think C# uses "@"
    for example. In my case I sometimes need case-sensitive ones too.

    The point is, these are exceptions; Algol68 requires every reserved
    word, which includes types names, to be stropped. It gives a very
    peculiar look to source code, which you see very rarely in other languages.

    that with me. - I understood that you find it a good idea to implement
    an own [irrelevant] language

    You keep saying that. It's a real language and has been tried and tested
    over decades. Maybe it would be better if I'd just made up hypothetical features and posted about ideas?

    (You may be a
    candidate for using an IDE that alleviates you from such mundane
    tasks.)

    I use a syntax that alleviates me from that!

    Many languages allow trailing commas in multi-line lists. The reason is
    EXACTLY to simplify maintenance. But you're suggesting it is only me who
    has such a problem with this stuff. Obviously others do as well.

    With your argumentation I'm curious what you think about having
    to add a semicolon in "C" if you replace a {...} block.

    That's just more fun and games. I don't get the rules there either.
    Sometimes "};" is needed; sometimes it's not needed but is harmless;
    sometimes it can cause an error.

    Or, in the first place, what you think about semicolons in "C"s
    'if-else' construct (with parenthesis-blocks or single statements).
    And what's actually the "statement" in 'if(b)s;' and 'else s;'
    and what you think about 'if(b){}else{}' being a statement (or
    not, since it's lacking a semicolon).

    That's something else that Algol68 fixed, and which other languages have
    copied (Lua for one).


    (This is obviously an issue you have; not the language. You should
    have better written "Usually I'm not aware of this ...". And that's
    of course a fair point [for you].)

    The last bit of Algol68 I wrote, approaximately half my time was dealing
    with ";" errors or "SKIP", or forgetting to use upper case for keywords.
    Fact.

    Allow semicolons to be a /terminator/, and all that goes away. It's a no
    brainer.

    History and also facts of contemporary languages disagree with you.
    (Re: "no brainer": You need a brain to understand or know that, of
    course. - So my suggestion to you is obvious; inform yourself.)

    Lots of languages have also done away with semicolons, or arranged
    things so that they rarely need to be written.


    For example I find it a "colossal time-waster" to write an own
    language given the many different existing ones

    Not at the time I started doing that. Certainly not in a form that was available to me.

    So the language already exists, and I'm just evolving it.

    I was going to give it up in 1992 and switch to C (I had in mind
    changing jobs). Then I had another look at C - and changed my mind!


    - some even available
    in source code to continue working on an existing code base. Colossal
    is here a really perfect chosen adjective. - Your scale seems to have
    got impaired; you spot marginal time "wastes" and miss the real ones, qualitatively and quantitatively.)

    I put a lot of weight on syntax; obviously you don't.

    My syntax makes typing easier because it is case-insensitive, there is considerably less punctuation, it's not fussy about semicolons, it
    allows type-sharing more, it doesn't need separate declarations, or
    headers, or ....

    The end result is that less text needs to be typed, source looks cleaner
    and it's less error prone. I don't need to write:

    for (int index = 0; index < N; ++index)

    for example. Or, to share a named entity, I don't need to write two
    versions of it, one here and the other in a shared header. You don't
    think that is a good thing?

    So what bad language features do you think are time-wasters that I
    should instead look at?

    It's quite unsuited to systems programming, and not just because of its
    execution speed. However, I'd quite like to see A68G implemented in A68G!

    I've heard and read, as I said, a differing thing about that.
    Specifically I recall to have read about that special topic you
    mention of writing an Algol 68 compiler in Algol 68; it has been
    done.

    I'm sure it has. My point about A68G is that it is interpreter, a fairly
    slow one. So how fast would A68 code run under an interpreter running
    under A68G?


    (Your personal preferences and enthusiasm should not get in the way
    of either checking the facts or formulate your opinions/thoughts as
    what they are, here basically wrong assumptions based on ignorance.)

    Really? I've written countless compilers and interpreters. Mainly I
    devised systems programming languages. You think I don't know my field?

    IMO A68 is unsuitable for such things, and A68G doubly so.


    It makes me smile if you speak about "looking great when typeset",
    given that the languages we use nowadays, specifically (e.g.) "C",
    C++, don't even look good "when typeset".

    Yeah. The first time I saw C code was in K&R1, in a book I bought in
    1982 (for £12; a lot of money). It looked dreadful. The typeface used
    made it look anaemic. That really put me off, more than the practical
    problems.

    I didn't consider it again until 1992 as I said, because I would have
    needed a new compiler for my language to work with Windows. I ended up
    writing that new compiler (and became self-employed).

    And the problems you/we
    buy with that are directly observable in the languages. Rather we
    seem to have accepted all their deficiencies and just work through
    (or around) them. Most do that with not complaints. What I find
    astonishing is that you - here known to complain about a lot of "C"
    details - are now praising things (and at the same time despise
    sensible concepts in an exceptionally well designed language as
    Algol 68).

    I admire languages that adapt and evolve. Fortran for example. C adapted
    poorly and slowly. Algol68 apparently hasn't evolved at all. I guess it couldn't do without changing it's RR, a big undertaking.

    Which means it's stuck in the 1960s with some dated design choices.

    BTW below is an actual example of Algol68 for A68G. It shows various
    issues, other than syntax (but notice those jarring ";" after the END of
    each function). You can't mix signed/unsigned arithmetic easily, it
    needs BITS, which are awkward to initialise.

    It is really dreadful. It makes writing in C attractive!

    (Below that is my version in the Algol68-inspired syntax, but you can
    see it looks quite different - and shorter.)

    BTW under A68, the 100,000-loop ran in 11 seconds.

    With my compiler, the 100,000,000-loop run in 1.5 seconds (1 second if optimised). So apparently 10,000 times faster.

    If I use 100,000 in my version, and get my compiler to interpreter it
    (very slowly), it takes only 0.1 seconds, still 100 times faster!

    (I think those long types slow down the A68 version.)

    ----------------------------------------------
    MODE LI = LONG INT,
    LB = LONG BITS;

    LB mask = 8r 1 777 777 777 777 777 777 777;
    LI mod = ABS mask + 1, l2 = 2;
    LI t23 = l2^23, t25 = l2^25, t39 = l2^39, t41 = l2^41, t63 = l2^63;

    [0:20631] LI q;

    INT flag:=0;

    LI carry := 36243678541,
    xcng := 12367890123456;
    LB xs := BIN LONG 521288629546311;

    INT indx := UPB q+1;

    PROC cng = LI: BEGIN
    xcng *:= 6906969069 +:= 123 %*:= mod
    END;

    PROC xxs = LI: BEGIN
    ABS ( xs := xs XOR (xs SHL 13 AND mask);
    xs := xs XOR xs SHR 17;
    xs := xs XOR (xs SHL 43 AND mask) )
    END;

    PROC supr = LI: BEGIN
    LI s;
    IF indx <= UPB q THEN
    s:=q[indx];

    indx+:=1
    ELSE
    s:=refill
    FI;
    s
    END;

    PROC kiss = LI: BEGIN
    LI s,c,x;

    s:=supr;
    c:=cng;
    x:=xxs;

    (s+c+x) %* mod
    END;

    PROC refill = LI: BEGIN
    FOR i FROM 0 TO UPB q DO
    LI h = ABS ODD carry,
    z = ABS (q[i]*t41%2 + q[i]*t39%2 + carry%2) %* mod;
    carry := ABS (q[i]%t23 + q[i]%t25 + z%t63) %* mod;
    q[i] := ABS NOT BIN (z*2 + h) %* mod
    OD;
    indx:=1;
    flag+:=1;

    q[0]
    END;

    LI x;

    FOR i FROM 0 TO UPB q DO q[i] := (cng + xxs) %* mod OD;

    FOR n TO 100000
    DO
    x := kiss
    OD;

    print (x)

    ----------------------------------------------

    [0..20631]word Q
    word carry = 36243678541
    word xcng = 12367890123456
    word xs = 521288629546311
    word indx = Q.len

    function refill:int =
    word h,z, cy

    cy:=carry
    for i in Q.bounds do
    h := cy iand 1
    z := (Q[i]<<41)>>1 + (Q[i]<<39)>>1 + cy>>1
    cy := Q[i]>>23 + Q[i]>>25 + z>>63
    Q[i] := inot (z<<1+h)
    od
    indx:=1
    carry:=cy
    Q[Q.lwb]
    end

    macro kiss = supr() + cng + xxs

    function supr:int s=
    if indx <= Q.upb then
    Q[indx++]
    else
    refill()
    fi
    end

    macro xxs=(xs :=xs ixor xs<<13; xs :=xs ixor xs>>17; xs :=xs ixor xs<<43)

    macro cng = xcng:=(6906969069) * xcng + (123)

    proc main=
    word x

    for i in Q.bounds do
    Q[i] := cng + xxs
    od

    to 100'000'000 do
    x:=kiss
    od

    println "x =",x
    end

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Sun Dec 1 18:57:40 2024
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any order of function definition, without requiring forward declarations to use a
    function before it is defined. But C is not like that, and I cannot
    honestly say it bothers me one way or the other. And apparently, it
    does not particularly bother many people - there is, I think, no
    serious impediment or backwards compatibility issue that would
    prevent C being changed in this way. Yet no one has felt the need
    for it - at least not strongly enough to fight for it going in the
    standard or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Sun Dec 1 19:33:08 2024
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any order of
    function definition, without requiring forward declarations to use a
    function before it is defined. But C is not like that, and I cannot
    honestly say it bothers me one way or the other. And apparently, it
    does not particularly bother many people - there is, I think, no
    serious impediment or backwards compatibility issue that would
    prevent C being changed in this way. Yet no one has felt the need
    for it - at least not strongly enough to fight for it going in the
    standard or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem here?

    What, specifically, are you thinking of?

    The changes in declarations in C23, AFAIK, are that "void foo();" now
    means the same as "void foo(void);", and that in general non-prototype
    function declarations are no longer allowed. (That is a good change, of
    course - 30 years late, but still welcome.) But I can't think of a
    situation where code that is correct under the current "declare before
    using" rule would no longer be correct if "declare before or after" were allowed at the file-scope level.

    Maybe you could construct something by playing silly-buggers with macros
    to re-define identifiers at different points in the code.

    I can't say I've thought much about the consequences of such a rule
    change - it doesn't seem a realistic change to me, and I have no problem
    with the current rule. So it's quite possible that I've missed something.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sun Dec 1 20:12:25 2024
    On 01/12/2024 15:50, David Brown wrote:
    On 01/12/2024 15:23, Bart wrote:

    Such lists might have been helpful to some people decades ago, when
    editors were more primitive.  If I need a list of functions in a file
    (maybe it's someone else's code, or old code of mine), any
    programmer's editor or IDE will give me it - updated correctly in
    real-time, and not out of sync.

    Why isn't this a problem for exported/shared functions?

    That is, for all sorts of functions and variables declared in headers
    where there is a declaration in header, and a definition in some
    'home' module.


    What do you mean here?

    You said you didn't want a list of declarations to maintain for static functions within a module.

    But for non-static functions, which are shared via a header, you /need/
    such a list to be maintained:

    prog.h: int F(int);


    prog.c: #include "prog.h"

    static int G(int a);

    int F(int a) {return 0;}

    static int G(int a) {return 0;}


    Here, you object to having to maintain the declaration for G, but you
    still need to do so for F, and inside a separate file.

    The declaration for F could also get out of sync, but you don't consider
    that a problem?

    And if it isn't because your tools help with this, then they can help
    with G too.

    I certainly consider it a weakness in C that you don't have clear requirements and limitations for what can be in a header or a C file, or
    how things can be mixed and matched.  Keeping code clear and
    well-ordered therefore requires discipline and standardised arrangement
    of code and declarations.  Different kinds of projects will have
    different requirements here, but for my own code I find it best to be
    strict that for any C file "file.c", there will be a header "file.h"
    which contains "extern" declarations of any exported functions or data,
    along with any type declarations needed to support these.  My tools will warn on any mismatches, such as non-static functions without a matching "extern" declaration.  They can't catch everything - the way C is built
    up, there is no distinction between external declarations that should be defined in the same module and ones that are imported from elsewhere.

    Yes, this is why a module scheme (such as the kind I use) is invaluable.

    In the example above, you'd define both F and G in one place. There is
    no header and there are no separate declarations.

    If another module wishes to use F, then it imports the whole module that defines F.

    Some schemes can selectively import individual functions, but to me
    that's pointless micro-managing.

    In my scheme, it is not even necessary for individual modules to
    explicitly import each other: a simple list of modules is provided in
    one place, and they will automatically import each others' exported
    entities (which include functions, variables, types, enums, structs,
    named constants, and macros).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Mon Dec 2 11:42:19 2024
    On 01/12/2024 23:04, Keith Thompson wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 30/11/2024 00:44, Keith Thompson wrote:

    (I hope that the issue of "totally different types" is now cleared up
    and can be laid to rest.)


    A function definition - as typically written - is also a function
    declaration. So presumably you mean non-defining declaration here.

    Yes.

    Some people have a style where they write forward declarations of all
    functions defined in a C file near the top of the file. I am not a
    fan of that myself - especially as over time, this redundant
    information is rarely kept fully in sync with the rest of the code.
    But it is definitely something you'll sometimes see in real-world C
    code. (You could argue that the code is then not "well-written" C,
    but that would be a very subjective opinion.)

    Yes, that was an oversight on my part.

    If someone wanted to ensure that all static functions defined in a translation unit are declared near the top, there could be a separate
    tool to generate, or at least check, the declarations. I'm not aware of
    any such tool, which suggests there probably isn't much demand for it.


    It is also possible that people who want such tools would simply write
    them themselves. I suspect that for most people, writing a script that
    would do this job for their own code would be quick and simple, while
    writing one that worked fully for all possible cases would be much more
    of an effort.

    For example, in my own code I know that all static functions are defined
    with "static" at the start of the line, and I know that I never have
    static data definitions that include parentheses unless it is part of an initialiser (and therefore after the equals sign). This would make
    writing such a script for my own use very simple. But a general tool
    could not use such shortcuts - someone could use function pointer types
    in a static variable declaration, and of course it would have to
    pre-process the code before extracting the declarations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Mon Dec 2 11:30:35 2024
    On 01/12/2024 21:12, Bart wrote:
    On 01/12/2024 15:50, David Brown wrote:
    On 01/12/2024 15:23, Bart wrote:

    Such lists might have been helpful to some people decades ago, when
    editors were more primitive.  If I need a list of functions in a
    file (maybe it's someone else's code, or old code of mine), any
    programmer's editor or IDE will give me it - updated correctly in
    real-time, and not out of sync.

    Why isn't this a problem for exported/shared functions?

    That is, for all sorts of functions and variables declared in headers
    where there is a declaration in header, and a definition in some
    'home' module.


    What do you mean here?

    You said you didn't want a list of declarations to maintain for static functions within a module.

    But for non-static functions, which are shared via a header, you /need/
    such a list to be maintained:

    Okay, I understand your point now. And I can see there is a certain
    similarity between between maintaining the extern function declarations
    in a header, and maintaining a list of static function declarations in
    the C file. (I refer to "extern function declarations" to distinguish
    them from static declarations - and because I personally like to include
    the optional "extern" keyword.)

    But there are many important differences.

    The biggest difference is that header files form the public interface
    for the "module". That will mean documentation (comments), include's
    for any modules that are required for the declarations, type
    declarations, possibly data, macros, etc., as well as extern function declarations. The header is where you put the specification for the
    module - it's not something that changes often, and the choice of
    function declarations is done with care and planing, usually before
    writing any implementations. And the header with all its contents is
    vital information for both the implementer of the module, and the users.

    Static functions, on the other hand, are internal to the implementation
    and can be changed often. A list of static function declarations gives
    little or no useful information to anyone.


     prog.h:   int F(int);


     prog.c:   #include "prog.h"

               static int G(int a);

               int F(int a) {return 0;}

               static int G(int a) {return 0;}


    Here, you object to having to maintain the declaration for G, but you
    still need to do so for F, and inside a separate file.


    I can't speak for how you or anyone else writes code, but my code would
    never look like that in practice. (Obviously I know what you wrote is a
    quick example, not real code.) A local static function might have a
    small, simple name - it is of very local scope, so like local variables
    its purpose can be seen clearly from its definition and use. An
    exported function, on the other hand, will have a good name, properly
    named parameters, carefully chosen parameter types, comments, and a
    position in the header to suit the structure of the code. Thus "F" and
    "G" are very different in my code.

    Obviously I still need to make sure the declarations and definitions
    match up.

    The declaration for F could also get out of sync, but you don't consider
    that a problem?

    It would be a problem if it happened, yes.

    Fortunately, most such errors get caught during a build. A mismatch
    between a function declaration and its definition will be caught
    immediately as a C error. Warnings from my compiler catch non-static
    function definitions that don't have a matching extern declaration. And
    if there is an extern declaration for a function but no definition, then
    there will be a link-time error if that function is used by other
    modules. (But no error or warning if it is not used.)


    And if it isn't because your tools help with this, then they can help
    with G too.


    As I explained earlier, they /can/ help with some sync errors in lists
    of static forward declarations.

    And if I wanted to have such lists of static function declarations, then
    it would not be difficult to make a quick utility script that either
    checked such a list, or generated it directly. That script could then
    be included in the makefile for automation.

    But since I don't use such lists, and don't see any benefit in them, I
    haven't bothered writing such a script. If those who do write such
    lists use some kind of automation to ensure they are correct, then that
    would be great.

    I certainly consider it a weakness in C that you don't have clear
    requirements and limitations for what can be in a header or a C file,
    or how things can be mixed and matched.  Keeping code clear and
    well-ordered therefore requires discipline and standardised
    arrangement of code and declarations.  Different kinds of projects
    will have different requirements here, but for my own code I find it
    best to be strict that for any C file "file.c", there will be a header
    "file.h" which contains "extern" declarations of any exported
    functions or data, along with any type declarations needed to support
    these.  My tools will warn on any mismatches, such as non-static
    functions without a matching "extern" declaration.  They can't catch
    everything - the way C is built up, there is no distinction between
    external declarations that should be defined in the same module and
    ones that are imported from elsewhere.

    Yes, this is why a module scheme (such as the kind I use) is invaluable.


    Agreed. C does not have a real module scheme as such. But it supports
    getting similar effects - you just have to be disciplined in the way you
    write your headers. This has the disadvantage of being less consistent
    than, say, Pascal or Modula 2, especially if the programmer is not
    disciplined. And it has the advantage in flexibility - I have a scheme
    that I like and that works well for the kind of code I work with, but
    other people prefer other schemes. It's easy to fall into the trap of
    "my way is the right way", especially when you make your own language
    and you are the only user, but there is always a balance to be sought
    between consistency and flexibility.

    In the example above, you'd define both F and G in one place. There is
    no header and there are no separate declarations.

    If another module wishes to use F, then it imports the whole module that defines F.

    Some schemes can selectively import individual functions, but to me
    that's pointless micro-managing.


    To me, it is absolutely vital that the importing unit can only see the identifiers that were explicitly exported. It is also absolutely vital
    (and this is a critical missing feature for C - and a good reason to
    switch to C++ even if you use no other feature of that language) that
    the imported identifiers be in their own namespace so that they do not
    conflict with identifiers in the importing unit. If the language
    provides a feature for importing the external identifiers directly into
    the current unit's namespace, then it has to allow selective import of identifiers - otherwise all concepts of scalability and modularity go
    out the window.

    In my scheme, it is not even necessary for individual modules to
    explicitly import each other: a simple list of modules is provided in
    one place, and they will automatically import each others' exported
    entities (which include functions, variables, types, enums, structs,
    named constants, and macros).


    That sounds, frankly, utterly terrible for anyone who worked with other
    people.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Mon Dec 2 12:24:11 2024
    On 02/12/2024 10:30, David Brown wrote:
    On 01/12/2024 21:12, Bart wrote:

    Yes, this is why a module scheme (such as the kind I use) is invaluable.


    Agreed.  C does not have a real module scheme as such.  But it supports getting similar effects - you just have to be disciplined in the way you write your headers.  This has the disadvantage of being less consistent than, say, Pascal or Modula 2, especially if the programmer is not disciplined.  And it has the advantage in flexibility - I have a scheme
    that I like and that works well for the kind of code I work with, but
    other people prefer other schemes.  It's easy to fall into the trap of
    "my way is the right way", especially when you make your own language
    and you are the only user, but there is always a balance to be sought
    between consistency and flexibility.

    In the example above, you'd define both F and G in one place. There is
    no header and there are no separate declarations.

    If another module wishes to use F, then it imports the whole module
    that defines F.

    Some schemes can selectively import individual functions, but to me
    that's pointless micro-managing.


    To me, it is absolutely vital that the importing unit can only see the identifiers that were explicitly exported.

    Speaking for my scheme, that is exactly what happens.

    (First, I should say that my programs - sets of source files that will
    comprise one binary - are organised into 'subprograms', each of which is
    a chummy collection of modules that effectively import each other. The following is about one subprogram.)

    Only entities marked with 'global' are visble from other modules. But if
    module X exports names A, B, C, all will be visible from Y.

    Further, exported names D, E, F from X will be visible from X. Imports
    can be circular (but subprograms are hierarchical).

    What I object to in other schemes are:

    * Where each of dozens of modules contains a ragtag list of imports at
    the top. These look untidy and need to be endlessly maintained as a
    fresh imported function is needed from module not yet listed, or an
    import needs to be deleted as references to it are dropped. (This used
    to be my scheme too!)

    * Where functions are selectively imported from each module. FGS!
    Instead of a few dozen imports, now there could be hundreds of lines of imported function names to maintain. You'd have time for nothing else!


      It is also absolutely vital
    (and this is a critical missing feature for C - and a good reason to
    switch to C++ even if you use no other feature of that language) that
    the imported identifiers be in their own namespace so that they do not conflict with identifiers in the importing unit.  If the language
    provides a feature for importing the external identifiers directly into
    the current unit's namespace, then it has to allow selective import of identifiers - otherwise all concepts of scalability and modularity go
    out the window.

    Each of my modules creates a namespace. (Also, each of my subprograms
    creates one namespace for all entities exported from the whole library:
    that requires 'export' rather than 'global'.

    However that namespace is rarely used. If this module imports X which
    exports function F, then I can write F() instead of X.F().

    I only need to use the namespace if:

    * This module imports two modules that both export F so there is an
    ambiguity (this is reported)

    * This module has its own F so it shadows any imported versions. This is
    not reported, but has the issue that, if a local F is freshly created,
    it can silently shadow the previously imported F().


    In my scheme, it is not even necessary for individual modules to
    explicitly import each other: a simple list of modules is provided in
    one place, and they will automatically import each others' exported
    entities (which include functions, variables, types, enums, structs,
    named constants, and macros).


    That sounds, frankly, utterly terrible for anyone who worked with other people.

    You've never used my scheme. One significant advantage is that because
    all modules (and subprogram imports) are listed in the lead module
    (usually that's all it contains), it is very easy to build a different configuration using an alternative lead module with a different collection.

    Alternatively, different modules can be commented in or out, in one
    place. Below is the lead module of my C compiler, what is submitted to
    my main compiler. No other modules contain any project info (only pcl.m,
    a separate subprogram/library).

    The only thing I haven't yet figured out is how the compiler knows the
    location of an imported library which may reside elsewhere in the file
    system. For now this is hardcoded.

    --------------------------------

    project =
    module cc_cli

    # Global Data and Tables

    module cc_decls
    module cc_tables

    # Lexing and Parsing
    module cc_lex
    module cc_parse

    # Generate PCL
    module cc_genpcl
    module cc_blockpcl
    module cc_libpcl

    # General

    module cc_lib
    module cc_support

    # Bundled headers

    module cc_headers # full set of embedded std headers
    # module cc_headersx # dummy module with 0 headers

    !Diagnostics
    module cc_show
    # module cc_showdummy

    !IL Backend
    $sourcepath "c:/px/"
    import pcl # fully loaded backend
    # import pclint # interpret only
    end


    (As is, this builds a 336KB C compiler with multiple options. With all
    those alternate modules commented in instead, it builds a 178KB C
    interpreter.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Mon Dec 2 16:24:29 2024
    On 02/12/2024 13:24, Bart wrote:
    On 02/12/2024 10:30, David Brown wrote:
    On 01/12/2024 21:12, Bart wrote:

    Yes, this is why a module scheme (such as the kind I use) is invaluable. >>>

    Agreed.  C does not have a real module scheme as such.  But it
    supports getting similar effects - you just have to be disciplined in
    the way you write your headers.  This has the disadvantage of being
    less consistent than, say, Pascal or Modula 2, especially if the
    programmer is not disciplined.  And it has the advantage in
    flexibility - I have a scheme that I like and that works well for the
    kind of code I work with, but other people prefer other schemes.  It's
    easy to fall into the trap of "my way is the right way", especially
    when you make your own language and you are the only user, but there
    is always a balance to be sought between consistency and flexibility.

    In the example above, you'd define both F and G in one place. There
    is no header and there are no separate declarations.

    If another module wishes to use F, then it imports the whole module
    that defines F.

    Some schemes can selectively import individual functions, but to me
    that's pointless micro-managing.


    To me, it is absolutely vital that the importing unit can only see the
    identifiers that were explicitly exported.

    Speaking for my scheme, that is exactly what happens.

    Good. (That was not clear to me from your description.)


    (First, I should say that my programs - sets of source files that will comprise one binary - are organised into 'subprograms', each of which is
    a chummy collection of modules that effectively import each other. The following is about one subprogram.)

    Only entities marked with 'global' are visble from other modules. But if module X exports names A, B, C, all will be visible from Y.

    Further, exported names D, E, F from X will be visible from X. Imports
    can be circular (but subprograms are hierarchical).


    That sounds a bit looser than I would like, but I am not sure there is
    any point in discussing the details here. It is straying way too far
    from C for this newsgroup.

    What I object to in other schemes are:

    * Where each of dozens of modules contains a ragtag list of imports at
    the top. These look untidy and need to be endlessly maintained as a
    fresh imported function is needed from module not yet listed, or an
    import needs to be deleted as references to it are dropped. (This used
    to be my scheme too!)

    I like to keep a /neat/ list of dependencies at the top of files. I
    usually have a rather good idea of which headers each C and header file requires. In the way I organise my headers, any header file which
    requires other headers, does so in that header. All my headers have
    guards to allow safe re-inclusion. So they can be ordered and arranged
    freely. I also usually have a "common" include file that includes the
    standard headers that I invariably need (like <stdbool.h>, <stdint.h>
    and <stddef.h>) along with a selection of definitions, static inline
    functions, macros, etc., that I use regularly in most projects.

    I would consider any kind of automatic import system to be a bad idea.


    * Where functions are selectively imported from each module. FGS!
    Instead of a few dozen imports, now there could be hundreds of lines of imported function names to maintain. You'd have time for nothing else!


    That sounds like you have a very poor organisation of your files.
    Either you have far too many small files, or you have a few files that
    are far too big, or you have far too complex connections between your
    source files. I rarely have more than perhaps a dozen "include" lines
    in a C or header file. There are exceptions that require more -
    typically a "main" file that pulls everything together.


      It is also absolutely vital (and this is a critical missing feature
    for C - and a good reason to switch to C++ even if you use no other
    feature of that language) that the imported identifiers be in their
    own namespace so that they do not conflict with identifiers in the
    importing unit.  If the language provides a feature for importing the
    external identifiers directly into the current unit's namespace, then
    it has to allow selective import of identifiers - otherwise all
    concepts of scalability and modularity go out the window.

    Each of my modules creates a namespace. (Also, each of my subprograms
    creates one namespace for all entities exported from the whole library:
    that requires 'export' rather than 'global'.

    However that namespace is rarely used. If this module imports X which
    exports function F, then I can write F() instead of X.F().

    I only need to use the namespace if:

    * This module imports two modules that both export F so there is an
    ambiguity (this is reported)

    * This module has its own F so it shadows any imported versions. This is
    not reported, but has the issue that, if a local F is freshly created,
    it can silently shadow the previously imported F().


    I like structured and modular programming. It is strange to me that
    someone would have the tools for that, and then choose not to use them.
    But some people seem to prefer piling everything together in one name space.


    In my scheme, it is not even necessary for individual modules to
    explicitly import each other: a simple list of modules is provided in
    one place, and they will automatically import each others' exported
    entities (which include functions, variables, types, enums, structs,
    named constants, and macros).


    That sounds, frankly, utterly terrible for anyone who worked with
    other people.

    You've never used my scheme.

    Indeed - that's why I say it /sounds/ terrible to me. As I said above,
    I prefer a clear and modular organisation. If I am writing module "foo"
    and a colleague is writing module "bar" as part of the same program, the
    last thing we want is automatic import of each other's modules, symbols, functions, etc. - especially not jumbled into the main namespace for the
    code!

    One significant advantage is that because
    all modules (and subprogram imports) are listed in the lead module
    (usually that's all it contains), it is very easy to build a different configuration using an alternative lead module with a different collection.

    Alternatively, different modules can be commented in or out, in one
    place. Below is the lead module of my C compiler, what is submitted to
    my main compiler. No other modules contain any project info (only pcl.m,
    a separate subprogram/library).

    The only thing I haven't yet figured out is how the compiler knows the location of an imported library which may reside elsewhere in the file system. For now this is hardcoded.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Janis Papanagnou on Mon Dec 2 18:13:35 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.


    But I want my software maintainable and readable. So my experience
    is that I want some lexical "accentuation"; common answers to that
    are for identifiers (for example) Camel-Case (that I used in C++), >underscores (that I use in Unix shell, Awk, etc.), or spaces (like
    in Algol 68, but which is practically irrelevant for me).

    CamelCase reduced typing speed and adds little benefit when compared
    with the alternatives (rational abbreviations, or even underscores).


    it's not fussy about semicolons,

    From the languages I know of in detail and I'm experienced in none
    is "fussy" about semicolons. Rather it's a simple and well designed >syntactical token, whether used as separator or terminator. You've
    just to put it where it's defined.

    Indeed. One wonders at Bart's familiarity with formal grammars.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Mon Dec 2 18:32:29 2024
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    Yes, but they made writing, reading and maintaining source code
    impossible. [...]

    Really? - For me it's exactly the opposite; having the keywords stand
    out lexically (or graphically) is what adds to legibility!

    In my syntax, you can write keywords in capitals if you want. It's case-insensitive! People using my scripting language liked to capitalise them. But now colour-highlighing is widely used.

    I'm used to case-insensitivity; that was common back in the mainframe
    days (given that there often was just upper case available; lower case
    was, if at all available, achievable only in complex ways). That's why
    other stropping types were prevalent, like a dot as a prefix, which
    was also used for symbols unavailable in the character sets. I recall
    Pascal's a[x] was written as a.(x.) (or something like that).



    (I admit that hitting the Shift or the Caps-Lock key may be considered
    cumbersome by [some/most] people. - I "pay the price" for legibility.)

    There's a lot of Shift and Caps-Lock with writing C or C-style syntax.

    (I think we should agree on that it's (at best) a personal preference.)

    If we have a closer look and (instead of a single character) inspect a
    more complete code fragment you may see that legibility, usability, and cumbersomeness is existing to a much larger degree on other places, if
    we compare code with different language design. To take a commonly seen construct in "C"

    if (cond) {
    stmt1;
    stmt2;
    }
    else {
    stmt3;
    stmt4;
    }

    with [spurious; compared to other languages] parentheses and braces.

    IF cond
    THEN
    stmt1;
    stmt2
    ELSE
    stmt3;
    stmt4
    FI

    (of course you format that, e.g. the 'THEN', as you prefer), or just

    ( cond | stmt1 ; stmt2 | stmt3 ; stmt4 )

    or would you really think final semicolons (which are not allowed like
    that in Algol 68) make that better

    ( cond | stmt1; stmt2; | stmt3; stmt4; )

    If I'd follow your complaints I'd get heated up by all these spurious
    and annoying parentheses and braces in "C".

    More so if you consider "cultural" ("locale") differences. Keyboards
    in my country, for example, have no easy (ergonomic) access to the
    characters { [ ] } which are accessible only by the 'AltGr' key and
    above the number keys 7 8 9 0 . It's certainly easier to type the
    common ( and ) keys for a formalized representation or use the legible
    form with keywords IF THEN ELSE FI, which are both easily typed on any keyboard. (I'm aware that my statement is ignoring Chineese keyboards,
    for example.)

    [...]

    The point is, these are exceptions; Algol68 requires every reserved
    word, which includes types names, to be stropped. It gives a very
    peculiar look to source code, which you see very rarely in other languages.

    (Not "every" reserved word if you use other representations; like (||)
    instead of IF/THEN/ELSE/FI, but okay.)

    Well, concerning "peculiarities" I'm certainly not annoyed or anything
    with what you seem to dislike [in Algol 68].

    I certainly agree that the historic disadvantages with the restricted
    character sets that lead to the prefix-point sort of stropping didn't
    look nice (we had to accept that at those long past days). Though in
    context of reserved names I never considered it an issue, it's more an
    issue, IMO, (if you see the Pascal example above) in combination with
    other characters.

    And I certainly also have no problem with all-caps stropping, that
    [for me] even adds to legibility (as I already explained).


    that with me. - I understood that you find it a good idea to implement
    an own [irrelevant] language

    You keep saying that. It's a real language and has been tried and tested
    over decades. Maybe it would be better if I'd just made up hypothetical features and posted about ideas?

    I know your [irrelevant] language is an existing language - I don't
    know where it's used, and I also don't care (and many/most/all here
    also don't seem to care much).

    You can of course (and certainly should) post your ideas with some
    syntax that expresses your ideas.

    Only the fact that you constantly mention "your language(s)" in the
    discussions spreads the impression that you think we should compare
    it - your language, not any feature - with "C" (or Algol 68), or with
    any specific "C" compiler. I also have my doubts that "your language"
    (and also your compiler) would withstand the market demands. That
    are the reasons why I point out its irrelevance where you give the
    impression that you think "your language" is the solution to some
    problem. Often I observe that you have a very limited local focus
    when valuating features, speed factor, and whatnot. - My personal
    valuation is that it makes little sense to discuss any features in
    the spotlight of your compiler(s) or language(s).


    (You may be a
    candidate for using an IDE that alleviates you from such mundane
    tasks.)

    I use a syntax that alleviates me from that!

    Many languages allow trailing commas in multi-line lists. The reason is EXACTLY to simplify maintenance. But you're suggesting it is only me who
    has such a problem with this stuff. Obviously others do as well.

    No, I'm saying that you are discussing minor things, blow them up unnecessarily, see problems in a detail and miss the whole picture
    with the real issues and challenges.

    And I don't want to start or foster a "Delimiter vs. Terminator"
    war. (I'd suppose this has been done in the past and opinions and
    pros/cons can be looked up.)


    With your argumentation I'm curious what you think about having
    to add a semicolon in "C" if you replace a {...} block.

    That's just more fun and games. I don't get the rules there either.
    Sometimes "};" is needed; sometimes it's not needed but is harmless; sometimes it can cause an error.

    Actually you seem to know "C" less than many people here. - I know
    where the commas and the braces have to go.

    My point was another with these examples. (But I'm tired to explain
    that in detail; thought it would be obvious.)


    Or, in the first place, what you think about semicolons in "C"s
    'if-else' construct (with parenthesis-blocks or single statements).
    And what's actually the "statement" in 'if(b)s;' and 'else s;'
    and what you think about 'if(b){}else{}' being a statement (or
    not, since it's lacking a semicolon).

    That's something else that Algol68 fixed, and which other languages have copied (Lua for one).

    I'm not sure what (wrong) paragon you think Algol 68 had that it
    would have fixed. To me it seems that they effectively designed
    the language ("almost") from scratch. It was influential to many
    languages (including "C" and Unix shell - just mentioning these
    two since it's not obviously seen given their syntax - or Eiffel,
    and many more).

    (I can't tell about Lua, a language that I just don't know.)


    [ snip personal problems with writing Algol 68 programs ]

    [...]

    - some even available
    in source code to continue working on an existing code base. Colossal
    is here a really perfect chosen adjective. - Your scale seems to have
    got impaired; you spot marginal time "wastes" and miss the real ones,
    qualitatively and quantitatively.)

    I put a lot of weight on syntax; obviously you don't.

    Where do you get that idea from? - Your mind is a puzzle to me.

    Given that (in the course of the threads) I mentioned so many
    syntactically different languages I'm practically experienced
    in, and specifically discuss so many syntactical issues (good
    ones and bad ones), I have no idea what your brain does when
    it reads the posts.


    My syntax

    (See what I wrote above about "your {language,compiler,syntax}".)

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    But I want my software maintainable and readable. So my experience
    is that I want some lexical "accentuation"; common answers to that
    are for identifiers (for example) Camel-Case (that I used in C++),
    underscores (that I use in Unix shell, Awk, etc.), or spaces (like
    in Algol 68, but which is practically irrelevant for me).

    For keywords I prefer to use uppercase (if the language is case
    insensitive, like in Simula, or if the compiler requires it, like
    in Algol 68).

    there is considerably less punctuation,

    A language property I very much appreciate.

    (Sadly "C" and C++, that I commonly use, are bloated with it.)

    it's not fussy about semicolons,

    From the languages I know of in detail and I'm experienced in none
    is "fussy" about semicolons. Rather it's a simple and well designed
    syntactical token, whether used as separator or terminator. You've
    just to put it where it's defined.

    (Don't confuse "fussy" handling with "not matching your ideas or
    preferences". - It's really, and obviously, you who has a problem;
    here supposedly: understanding of serialization concepts.)

    it allows type-sharing more,

    (Don't know what you mean here.)

    it doesn't need separate declarations,

    Huh?

    or headers, or ....

    (You're obviously again trying to mis-match any language with your
    personal software project.)


    The end result is that less text needs to be typed, source looks cleaner
    and it's less error prone. I don't need to write:

    for (int index = 0; index < N; ++index)

    Sure. And there's a lot languages existing where you don't need to
    write such ugly syntactical constructs (Simula, Algol 68, Pascal,
    Eiffel, ...). That's what we have to buy when using languages that
    inherited their syntax from "C".


    for example. Or, to share a named entity, I don't need to write two
    versions of it, one here and the other in a shared header. You don't
    think that is a good thing?

    For answers see above. (We can discuss any feature you like.)


    So what bad language features do you think are time-wasters that I
    should instead look at?

    (Does this sentence make sense? - I don't understand it.)

    What I can say on the keywords (language, features, time-wasters) you
    used is...

    There's thousands of languages existing, and many dozens widely used.
    It's certainly a "colossal" (I like your word) time-waster to write an
    own language instead of choosing a sufficiently fitting existing one.

    Features are what they are; you need them or not.

    (My suspicion is that at the time you started your project(s) you
    haven't seen any options and wanted [to create] some solution. And
    once you had your code base it was easier to continue your chosen
    path than to reconsider the [later available] options. - There's
    nothing to criticize with that. After all, it's a personal project.)


    It's quite unsuited to systems programming, and not just because of its
    execution speed. However, I'd quite like to see A68G implemented in
    A68G!

    I've heard and read, as I said, a differing thing about that.
    Specifically I recall to have read about that special topic you
    mention of writing an Algol 68 compiler in Algol 68; it has been
    done.

    I'm sure it has. My point about A68G is that it is interpreter, a fairly
    slow one.

    Have you checked? (I haven't, since I anyway only rarely use it.)

    So how fast would A68 code run under an interpreter running
    under A68G?

    We had been discussing your point about Algol 68 being a system
    programming language. It had been classified as such.

    We had been discussing about your (just for the argument made up)
    question whether there's an Algol 68 compiler written in Algol 68
    (likely as an indication of the previous point). And I said that
    this was indeed the case. (Despite it being not necessary to prove
    the system programming language property.)

    Then you project a current Algol implementation in a try to make
    a principal argument. - You're obviously not interested in a fair
    dispute about the languages or systems.

    Concerning the Algol 68 Genie compiler - that you seem to mean
    when you write "A68G"; there's an 'a68g' executable, but there's
    no Algol 68G implementation, as opposed to Algol 68C, R, H, etc.)
    - it's documented as "Algol 68 hybrid compiler-interpreter". (You
    can read about the implementation concept in the "Genie" manual.)


    (Your personal preferences and enthusiasm should not get in the way
    of either checking the facts or formulate your opinions/thoughts as
    what they are, here basically wrong assumptions based on ignorance.)

    Really? I've written countless compilers and interpreters. Mainly I
    devised systems programming languages. You think I don't know my field?

    From your posts I've got quite a good impression of what you know
    (and what you don't know, or just prefer to ignore).

    (Your post that I'm replying to here confirms my impression.)


    IMO A68 is unsuitable for such things, and A68G doubly so.

    Yes, I have already acknowledged that every opinion (yous included)
    is fine.


    It makes me smile if you speak about "looking great when typeset",
    given that the languages we use nowadays, specifically (e.g.) "C",
    C++, don't even look good "when typeset".

    Yeah. The first time I saw C code was in K&R1, in a book I bought in
    1982 (for £12; a lot of money). It looked dreadful. The typeface used
    made it look anaemic. That really put me off, more than the practical problems.

    Well, I'm of course biased by my own experiences and valuations.

    Some others in my vicinity were euphoric about the language and
    about the book. Concerning the language I did as I did with every
    language I was confronted with; I tried to identify the good parts
    and pondered about how to use the bad parts to my advantage; it's
    not that "C" wouldn't have its merits. The book, OTOH, left me with
    more questions than I initially had. (I seem to recall to have heard
    that later editions were better in that respect.)

    [...]

    [...]

    I admire languages that adapt and evolve. Fortran for example. C adapted poorly and slowly. Algol68 apparently hasn't evolved at all. I guess it couldn't do without changing it's RR, a big undertaking.

    I haven't followed Fortran beyond F77; I wholeheartedly dislike it.
    (I used Fortran just twice in my life; in a University project and
    at the DLR to access a random-noise function from a Fortran library.)
    I agree with what you say of "C" and Algol 68. (Although Marcel had
    supported quite some noteworthy features in the "Genie" compiler!)
    I don't understand what you are referring to with "RR". (For me it's
    just an acronym for RoboRally, a nice board game.)


    Which means it's stuck in the 1960s with some dated design choices.

    BTW below is an actual example of Algol68 for A68G. It shows various
    issues, other than syntax (but notice those jarring ";" after the END of
    each function).

    Well, we already addressed that; you need some separation token (or
    else a termination token). (And we don't need to repeat ourselves.)

    You can't mix signed/unsigned arithmetic easily, it
    needs BITS, which are awkward to initialise.

    I will snip that. In this detail I think it's inappropriate for this
    newsgroup, and I certainly don't want to discuss that here. The posts
    got already far too long (and for little gain, as I see it).

    I will inspect your efforts, though; I'm always keen to learn. :-)
    And thanks for providing the Algol 68 example; rarely seen nowadays.


    It is really dreadful. It makes writing in C attractive!

    As I wrote above, "C" has its merits. (And not only in comparison.)

    (BTW, I find your Algol 68 sample not very well written, quite ugly,
    to my taste. - As so often said; you can in any language write good
    or bad code. - And style and readability preferences vary anyway.)

    But the Algol 68 code - even your low-level code - "dreadful"!?
    (I suggest to downgrade your comparisons a bit.)

    Janis

    [ Low-level code sample in Algol 68 vs. Bart's language snipped ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Mon Dec 2 19:23:59 2024
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...]

    A suspicion that I got as well (also from other posts of him).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Mon Dec 2 18:27:22 2024
    On 02/12/2024 15:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:

    I would consider any kind of automatic import system to be a bad idea.

    It's not automatic; you have to list the modules. If you don't want data shared, then don't export it!

    If you want selected imports between arbitrary module subsets, then my
    scheme has 'subprograms' (see below), or you choose a language with a
    more chaotic module scheme that can give that flexibility, but requires
    more maintenance.

    I like structured and modular programming.  It is strange to me that
    someone would have the tools for that, and then choose not to use them.
    But some people seem to prefer piling everything together in one name
    space.

    This point was about individual functions not files. For example this in Python:

    from math import sqrt

    (which also has the effect of making 'sqrt' part of this module's
    namespace).


    Indeed - that's why I say it /sounds/ terrible to me.  As I said above,
    I prefer a clear and modular organisation.  If I am writing module "foo"
    and a colleague is writing module "bar" as part of the same program, the
    last thing we want is automatic import of each other's modules, symbols, functions, etc. - especially not jumbled into the main namespace for the code!

    If you don't then you're not really writing the same part of the
    program. I mentioned my programs comprise subprograms, which have
    stricter import rules and which are non-hierarchical/non-circular.

    It sounds like, in my scheme, you'd be working on different subprograms:
    each team member has their own chummy collection of modules.

    But it's possible you are also working on the same collection. Then you
    talk!

    C for example has one giant namespace anyway that contains all shared
    entities. /Then/ you have a problem, especially when people avoid 'static'.

    My scheme allows modules A and B to both export a function F. If A and B
    are part of the same subprogram collection, then this means needing to
    qualify the function name, as A.F() or B.F(), depending on where it's
    defined:

    p.m:
    module a
    module b

    proc main =
    a.f()
    b.f()
    end

    a.m:
    global proc F = println "FA" end

    b.m:
    global proc F = println "FB" end

    c:\mx>mm -r p
    FA
    FB

    If I try the same in C:

    a.c:
    #include <stdio.h>
    void F(void){ puts("FA");}

    b.c:
    #include <stdio.h>
    void F(void){ puts("FB");}

    I get a 'multiple definition of F'. This is without even getting as far
    as writing `p.c`, where it is impossible two distinguish between those
    two F functions.

    When generating shared libraries like DLLs however, I can only export
    the base-name 'F'. If A and B are both compiled to its own DLL, that can produce similar difficulties.

    A typical one here is that the linking process will only match one of
    the 'F's (my compiler matches A.F, gcc matches B.F, but neither report
    any ambiguity).

    (Actually my scripting language handles this properly, but only because
    it requires its FFI to match each imported symbol with a specific DLL.
    So both A.F and B.F can be accessible from two DLLs that each export an unadorned 'F'.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Mon Dec 2 19:12:12 2024
    On 02/12/2024 18:23, Janis Papanagnou wrote:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...]

    A suspicion that I got as well (also from other posts of him).

    Then you'd both be wrong. DB's remark was anyway a misunderstanding.

    My projects have all relevant modules, usually measured in dozens, in
    the same folder.

    If projects share the same library, then the library forms its own
    project with its own folder.

    You consider that poor?

    For distribution, I would use ONE source file. Here, I'll create one
    such file right now:

    c:\cx>tm mm -ma cc.m
    Writing cc.ma
    TM: 0.08

    It took 1/12th of a second to create an amalgamated source file
    containing everything needed (except a compiler) to build an EXE of my C compiler, including the shared backend sources, and including bundled C
    header files.

    I can email it to you if you like; it's 0.6MB, or 30Kloc.

    So, according to you, this is badly organised? Excuse me for struggling
    to see how a single file can be poorly organised!

    BTW cc.m contains that project info I posted earlier.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Scott Lurndal on Mon Dec 2 20:02:14 2024
    On 02.12.2024 19:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    Can you give some hints (or keywords) to be able to better understand
    your opinion?

    As you see, I have no strong opinion on that. In the past I've worked
    with languages of both sorts, and I never felt an urge to complain;
    I suppose because the languages tend to consider their design on all
    boundary conditions, and in cases where there's only upper characters
    are available on a [legacy-]system the language designers certainly
    tried to make the best out of it. - I use what's provided/supported.



    But I want my software maintainable and readable. So my experience
    is that I want some lexical "accentuation"; common answers to that
    are for identifiers (for example) Camel-Case (that I used in C++),
    underscores (that I use in Unix shell, Awk, etc.), or spaces (like
    in Algol 68, but which is practically irrelevant for me).

    CamelCase reduced typing speed and adds little benefit when compared
    with the alternatives (rational abbreviations, or even underscores).

    I cannot follow your speed argument - for speed questions ask Bart ;-)

    For camel-case I need just the Shift-key, and underscores requires
    me to type an extra character, the underscore (which also needs the
    Shift-key), so the latter should be slower (and [for me] is slower).

    Using abbreviations is an orthogonal concept that you can use with
    underscores and camel-case or with anything else (including use it
    alone; which is not what I typically do [unless standard abbrevs.]).

    Here as well, I use what what appears to serve me best in the given
    context. (Unless in company's project contexts where we define and
    use standards and conventions.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Janis Papanagnou on Mon Dec 2 19:57:19 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 02.12.2024 19:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    Can you give some hints (or keywords) to be able to better understand
    your opinion?

    My primary complaint is that for me, switching case frequently will
    decrease typeing speed and is an unnecessarily complication.

    I spent much of a decade programming EBCDIC mainframes; there it was
    all uppercase for the most part. The keyboards defaulted to upper
    case, making things pretty straightfoward. Needing to type lower
    case was rare.

    Even on early unix systems using uppercase only teletypes was fine,
    since there was seldom any need to use lowercase (the unix tty driver
    handled converting to lower-case automatically on input devices that
    only supported upper-case). Using lower case on those input devices
    meant escaping each lowercase character - less than optimal, indeed.


    I cannot follow your speed argument - for speed questions ask Bart ;-)

    For camel-case I need just the Shift-key, and underscores requires
    me to type an extra character, the underscore (which also needs the >Shift-key), so the latter should be slower (and [for me] is slower).

    Anytime I need to move from the home position, for example to find
    the shift key, it affects my throughput a bit. Having to do twice for every variable name is annoying (there is a natural race bewtween pressing
    the shift key and the target letter key, missing that race means
    backspace and correct). The underscore is so widely used in
    programming that I find it easier to use than camelcase.

    YMMV.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Janis Papanagnou on Mon Dec 2 19:58:01 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...]

    A suspicion that I got as well (also from other posts of him).

    I believe he (Bart) claimed that he keeps everything in one directory.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Mon Dec 2 22:06:19 2024
    On 02/12/2024 19:27, Bart wrote:
    On 02/12/2024 15:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:

    I would consider any kind of automatic import system to be a bad idea.

    It's not automatic; you have to list the modules. If you don't want data shared, then don't export it!


    As I understood it, or perhaps failed to understand it (after all, it's
    not as if there are published specifications, references, tutorials or
    examples for your language), you would list your modules for a program
    in one place, and then other modules in the program automatically import
    them all.

    If you want selected imports between arbitrary module subsets, then my
    scheme has 'subprograms' (see below), or you choose a language with a
    more chaotic module scheme that can give that flexibility, but requires
    more maintenance.

    I like structured and modular programming.  It is strange to me that
    someone would have the tools for that, and then choose not to use
    them. But some people seem to prefer piling everything together in one
    name space.

    This point was about individual functions not files. For example this in Python:

      from math import sqrt

    (which also has the effect of making 'sqrt' part of this module's
    namespace).


    This is sometimes convenient for functions that you are going to use a
    lot. At other times, you use "import math" and then refer to "math.sqrt".


    Indeed - that's why I say it /sounds/ terrible to me.  As I said
    above, I prefer a clear and modular organisation.  If I am writing
    module "foo" and a colleague is writing module "bar" as part of the
    same program, the last thing we want is automatic import of each
    other's modules, symbols, functions, etc. - especially not jumbled
    into the main namespace for the code!

    If you don't then you're not really writing the same part of the
    program. I mentioned my programs comprise subprograms, which have
    stricter import rules and which are non-hierarchical/non-circular.


    If you are linking everything together into one program, it is one
    program. (Having a hierarchy within that is fine - but it's still one program.)

    It sounds like, in my scheme, you'd be working on different subprograms:
    each team member has their own chummy collection of modules.


    Perhaps you simply don't know how teams might work.

    But it's possible you are also working on the same collection. Then you
    talk!

    C for example has one giant namespace anyway that contains all shared entities. /Then/ you have a problem, especially when people avoid 'static'.


    That's one reason why C programmers don't avoid "static" if they know
    what they are doing.

    And yes, the single shared "external linkage" namespace for a C program
    is a limitation to scalability and an inconvenience.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Mon Dec 2 21:00:12 2024
    On 02/12/2024 19:58, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...]

    A suspicion that I got as well (also from other posts of him).

    I believe he (Bart) claimed that he keeps everything in one directory.

    Not 'everything', just what's relevant.

    One project for example comprises 16 source files, all kept in one folder.

    So, what's wrong with that, and what's the advantage of arbitrarily
    grouping them into 2 to 16 separate folders, possibly nested, and
    possibly scattered all over the file system?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Mon Dec 2 22:16:13 2024
    On 02/12/2024 20:12, Bart wrote:
    On 02/12/2024 18:23, Janis Papanagnou wrote:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...]

    A suspicion that I got as well (also from other posts of him).

    Then you'd both be wrong. DB's remark was anyway a misunderstanding.

    My projects have all relevant modules, usually measured in dozens, in
    the same folder.


    Oh, dozens of modules! I never realised your programs were that big!

    In my current project, there are 155 C files, 44 C++ files, 272 header
    files, and 5 linker files over 71 directories. Most of the C files and
    a substantial proportion of the headers are libraries and SDKs for the
    device in use, most of the C++ files were written by me, but some were
    written by four other developers at the same time.

    When you work with more serious projects, you need a better organisation
    than you do for little one-man hobby programs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to David Brown on Mon Dec 2 21:58:34 2024
    David Brown <david.brown@hesbynett.no> writes:
    On 02/12/2024 20:12, Bart wrote:
    On 02/12/2024 18:23, Janis Papanagnou wrote:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...] >>>
    A suspicion that I got as well (also from other posts of him).

    Then you'd both be wrong. DB's remark was anyway a misunderstanding.

    My projects have all relevant modules, usually measured in dozens, in
    the same folder.


    Oh, dozens of modules! I never realised your programs were that big!

    In my current project, there are 155 C files, 44 C++ files, 272 header
    files, and 5 linker files over 71 directories. Most of the C files and
    a substantial proportion of the headers are libraries and SDKs for the
    device in use, most of the C++ files were written by me, but some were >written by four other developers at the same time.


    $ find . \( -name '*.c' -o -name '*.cpp' -o -name '*.h' \) -print | wc -l
    4240
    $ find . -type d -print | wc -l
    1189

    Somewhere in the vicinity of 3,000,000 SLOC, 12 years since
    development started.

    A significant fraction of the SLOC (perhaps 66%) are C/C++
    header files generated from YAML files describing data
    structures.


    When you work with more serious projects, you need a better organisation
    than you do for little one-man hobby programs.

    Indeed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Mon Dec 2 21:53:55 2024
    On 02/12/2024 21:16, David Brown wrote:
    On 02/12/2024 20:12, Bart wrote:
    On 02/12/2024 18:23, Janis Papanagnou wrote:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...] >>>
    A suspicion that I got as well (also from other posts of him).

    Then you'd both be wrong. DB's remark was anyway a misunderstanding.

    My projects have all relevant modules, usually measured in dozens, in
    the same folder.


    Oh, dozens of modules!  I never realised your programs were that big!

    In my current project, there are 155 C files, 44 C++ files, 272 header
    files, and 5 linker files over 71 directories.  Most of the C files and
    a substantial proportion of the headers are libraries and SDKs for the
    device in use, most of the C++ files were written by me, but some were written by four other developers at the same time.

    When you work with more serious projects, you need a better organisation
    than you do for little one-man hobby programs.

    So, how would you have organised the 16-module example I posted
    elsewhere? (Not a C project, these are 16 source files, so no headers etc.)

    Because two posters here have suggested my organisation is poor, but
    without knowing how big, small, or complex my projects are.

    BTW your project doesn't sound that big, especially if you have a
    penchant for having a larger number of smaller files.

    A line-count would give a better idea.

    The largest C project I attempted to build (with my compiler) was the
    Seed7 language a few years ago. I think there were 130-odd .c files,
    probably a comparable number of header files.

    It took my compiler 1-2 seconds to build from scratch, producing I think
    a 1.6MB executable. (That project is notable for coming with nearly 20 different makefiles, tuned for different compilers and platforms.)

    The current version includes 176 .c files and 148 .h files (not all used
    in any one configuration), which are all kept in one ./src folder. About 190Kloc in all.

    I guess that's poorly organised too? It sounds like everybody else's
    projects are!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Mon Dec 2 22:11:32 2024
    On 02/12/2024 21:06, David Brown wrote:
    On 02/12/2024 19:27, Bart wrote:
    On 02/12/2024 15:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:

    I would consider any kind of automatic import system to be a bad idea.

    It's not automatic; you have to list the modules. If you don't want
    data shared, then don't export it!


    As I understood it, or perhaps failed to understand it (after all, it's
    not as if there are published specifications, references,

    https://github.com/sal55/langs/blob/master/Modules24.md

    (A summary, mainly for my benefit, about a year old.)

    tutorials or
    examples for your language)

    I gave an example in my post, of the lead module for my C compiler.
    Older examples are in that link.

    In all (counting the 'pcl' backend library) it comprises 36 source files
    in two folders; plus about 40 C headers in two folders, which are
    embedded into the executable.

    This information is enough for the compiler, and nothing else, to locate
    all the necessary files and to build an EXE file.


    you would list your modules for a program
    in one place, and then other modules in the program automatically import
    them all.

    The logic used in the name resolution pass of the compiler allows
    visibiliy without needing full name-qualifying.

    That is incredibly convenient. It means clean source code with no xxx.
    or xxx:: littering everywhere. I don't even need different sets of
    'import xxx' in each module.

    I can rename any module, and I only need to change the one file. I can
    move an exported function from one module to another, without making any
    other changes (eg. change all xxx.F() to yyy.F()).

    I just wonder what sort of dog's breakfast C++'s new module scheme is,
    or will be.

       from math import sqrt

    (which also has the effect of making 'sqrt' part of this module's
    namespace).


    This is sometimes convenient for functions that you are going to use a
    lot.  At other times, you use "import math" and then refer to "math.sqrt".

    You can achieve the same thing with 'sqrt = math.sqrt'. Meanwhile my
    module scheme gives you that for free. With 20 minutes spare I could add
    an option for to turn it off.

    Perhaps you simply don't know how teams might work.

    Perhaps not. So? Not everyone works in a team.

    However one scripting language I created allowed anybody to create
    'horizontal' addons for my application with my involvement. They didn't
    need to modify or rebuild my app (or even restart it). Multiple people
    could create scripts even for the same instance of a running application.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Bart on Tue Dec 3 00:27:23 2024
    On Mon, 2 Dec 2024 22:11:32 +0000
    Bart <bc@freeuk.com> wrote:

    On 02/12/2024 21:06, David Brown wrote:

    Perhaps you simply don't know how teams might work.

    Perhaps not. So? Not everyone works in a team.


    L'enfer – c'est les autres.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Mon Dec 2 17:23:29 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 01.12.2024 17:42, Bart wrote:

    On 01/12/2024 15:08, Janis Papanagnou wrote:

    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    In my view case-insensitive matching/lookup is clearly worse than case-sensitive matching. There may be some contexts where a
    case-insensitive rule is tolerable or even preferable, but offhand
    I'm not thinking of one. Of course sometimes I do want matching
    to allow either case, for which 'grep -i' or some other common
    tool solves the problem; the key is that it's my choice, not
    a fixed choice imposed by a procrustean software system.

    But I want my software maintainable and readable. So my experience
    is that I want some lexical "accentuation"; common answers to that
    are for identifiers (for example) Camel-Case (that I used in C++),
    underscores (that I use in Unix shell, Awk, etc.), or spaces (like
    in Algol 68, but which is practically irrelevant for me).

    CamelCase reduced typing speed and adds little benefit when compared
    with the alternatives (rational abbreviations, or even underscores).

    My complaint about CamelCase (or camelCase, which I put in the same
    category) is that my eyes have to work quite a bit harder compared
    to text using underscores between words. Reading either form of
    camelCase is slower, and also requires more mental effort, relative
    to using underscores. Exception: CamelCase for a short noun phrase
    (up to perhaps three or four words) seems to work well for type
    names, probably because I can recognize the phrase as a whole
    without needing (most of the time) to look at the individual words.
    That property does not hold for names of variables or functions.

    For the most part I don't use abbreviations in the usual sense of
    the word, although I do sometimes use short non-words in a small
    local context (here "short" means usually one or two letters, and
    never more than four or five).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Bart on Tue Dec 3 11:15:44 2024
    Bart <bc@freeuk.com> writes:
    ...
    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable with type 'ref i32' (expressed in other syntax)
    B is a local variable with type '[10]i32'
    C is a function with return type of 'i32', taking one unnamed
    parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same declaration can also create names in different scopes!)

    A small correction: that declaration gives all three names the same
    scope[1]. You are confusing scope with linkage.

    [1] Well almost the same. The scope of A includes the declarators for B
    and C, and the scope of B includes the declarator for C.
    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Ben Bacarisse on Tue Dec 3 12:34:45 2024
    On 03/12/2024 11:15, Ben Bacarisse wrote:
    Bart <bc@freeuk.com> writes:
    ...
    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable with type 'ref i32' (expressed in other syntax)
    B is a local variable with type '[10]i32'
    C is a function with return type of 'i32', taking one unnamed
    parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same declaration can >> also create names in different scopes!)

    A small correction: that declaration gives all three names the same
    scope[1].

    This is what I observed my compiler doing, because it displays the
    symbol table. It puts C into module-scope, so I can access it also from
    another function without another declaration (so non-conforming, but I'm
    long past caring).

    I can't see gcc's symbol table, but I can't access C from another
    function without it having its own declaration, or there being a
    module-scope one.

    With gcc, such a declaration inside a function suffices to be able
    access a function 'C' defined later in the file.

    You are confusing scope with linkage.

    It's possible. So a function declaration inside a function gives the
    name external linkage (?). Which in this context means the function will
    be outside this one, but elsewhere in the module, rather than being
    imported from elsewhere module.

    If I say I find these quirks of C confusing, people will have another go
    at me. So let's say it makes perfect sense for 'extern' to mean two
    different things!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Tue Dec 3 15:33:05 2024
    On 02.12.2024 20:12, Bart wrote:
    On 02/12/2024 18:23, Janis Papanagnou wrote:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files. [...]

    A suspicion that I got as well (also from other posts of him).

    Then you'd both be wrong. [...]

    Maybe. - But given that single file compile times are an issue in
    your environment is a strong indication that you compile too many
    sources at once, or too huge source files, or both (or in case of
    full-builds don't do necessary [yet more time demanding] testing).

    And nothing you posted in the past or here gave me any indication
    of sensibly organized projects. (Not that I'd care much about your
    personal projects or issues you have in your chosen environment.)

    In our (huge) projects the compiles (triggered on demand by 'make')
    were all sub-second with standard compilers. Of course there's yet
    more about software organization, like [reducing] dependencies, etc.
    etc. etc.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Tue Dec 3 15:34:05 2024
    On 02/12/2024 22:53, Bart wrote:
    On 02/12/2024 21:16, David Brown wrote:
    On 02/12/2024 20:12, Bart wrote:
    On 02/12/2024 18:23, Janis Papanagnou wrote:
    On 02.12.2024 16:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:
    [...]

    That sounds like you have a very poor organisation of your files.
    [...]

    A suspicion that I got as well (also from other posts of him).

    Then you'd both be wrong. DB's remark was anyway a misunderstanding.

    My projects have all relevant modules, usually measured in dozens, in
    the same folder.


    Oh, dozens of modules!  I never realised your programs were that big!

    In my current project, there are 155 C files, 44 C++ files, 272 header
    files, and 5 linker files over 71 directories.  Most of the C files
    and a substantial proportion of the headers are libraries and SDKs for
    the device in use, most of the C++ files were written by me, but some
    were written by four other developers at the same time.

    When you work with more serious projects, you need a better
    organisation than you do for little one-man hobby programs.

    So, how would you have organised the 16-module example I posted
    elsewhere? (Not a C project, these are 16 source files, so no headers etc.)

    Because two posters here have suggested my organisation is poor, but
    without knowing how big, small, or complex my projects are.

    No one (as far as I have noticed) have said that your organisation /is/
    poor - they have said it /sounds/ poor from the way you describe it.
    The difference is very significant.

    For file organisation, I'd likely have all the modules in one directory
    unless there is a particular reason to split them up. I would not have
    any non-project files in that directory.

    But the questions raised about your organisation was not a matter of
    where you store your files, or how they are divided in directories. It
    is about how you organise the code and split functionality between files
    (or directories, for bigger projects).

    What you have described is modules that have far too much in one file,
    modules with little or no structure as to where things are in the file,
    little to no structure or control over which modules use facilities from
    which other modules, and completely random inter-module dependencies
    which can happily be circular.

    These opinions are formed from how you describe your code and your language.


    BTW your project doesn't sound that big, especially if you have a
    penchant for having a larger number of smaller files.

    A line-count would give a better idea.


    For the whole project (relevant to things like the build and the
    organisation):

    ----------------------------------------------------------------------- Language files blank comment code -----------------------------------------------------------------------
    C 155 13849 34547 80139
    C/C++ Header 284 13719 62329 61056
    C++ 43 2447 1230 13009 -----------------------------------------------------------------------
    SUM: 482 30015 98106 154204 -----------------------------------------------------------------------


    For the project-specific code, rather than libraries, SDK, etc.:

    ----------------------------------------------------------------------- Language files blank comment code -----------------------------------------------------------------------
    C++ 39 2217 1020 11820
    C/C++ Header 44 1078 798 2696
    C 3 259 237 1152 -----------------------------------------------------------------------
    SUM: 86 3554 2055 15668 ------------------------------------------------------------------------


    The largest C project I attempted to build (with my compiler) was the
    Seed7 language a few years ago. I think there were 130-odd .c files,
    probably a comparable number of header files.

    It took my compiler 1-2 seconds to build from scratch, producing I think
     a 1.6MB executable. (That project is notable for coming with nearly 20 different makefiles, tuned for different compilers and platforms.)

    The current version includes 176 .c files and 148 .h files (not all used
    in any one configuration), which are all kept in one ./src folder. About 190Kloc in all.

    I guess that's poorly organised too? It sounds like everybody else's
    projects are!


    I have no idea how good or bad organisation that project is - I don't
    know enough about it to tell. But 200+ files in one directory does not
    sound like a good start. (Note again that I can only judge the
    /appearance/ of poor organisation of your projects from your own
    descriptions.)

    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds. There are 18 binary images produced in the build
    - three different sets of builds (each with their own tree of object
    files from compiling with different options for the different but
    closely related programs) along with a number of variations of link
    setups and post-processing.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Tim Rentsch on Tue Dec 3 16:00:38 2024
    On 03/12/2024 02:23, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 01.12.2024 17:42, Bart wrote:

    On 01/12/2024 15:08, Janis Papanagnou wrote:

    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    In my view case-insensitive matching/lookup is clearly worse than case-sensitive matching. There may be some contexts where a
    case-insensitive rule is tolerable or even preferable, but offhand
    I'm not thinking of one. Of course sometimes I do want matching
    to allow either case, for which 'grep -i' or some other common
    tool solves the problem; the key is that it's my choice, not
    a fixed choice imposed by a procrustean software system.


    I would agree on that.

    I would not say that it is often a good idea to have identifiers which
    differ only in letter case - but it is not entirely unreasonable if a particular coding standard and naming convention supports it (such as
    naming your types "Foo" and allowing local declarations "Foo foo;").

    On the other hand, I would say it is very definitely a bad idea if
    different capitalisation is used for the same identifier in different
    parts of the code - it makes it a lot harder to read and easier to get
    wrong. I am happy that most of the languages I use are case-sensitive.


    But I want my software maintainable and readable. So my experience
    is that I want some lexical "accentuation"; common answers to that
    are for identifiers (for example) Camel-Case (that I used in C++),
    underscores (that I use in Unix shell, Awk, etc.), or spaces (like
    in Algol 68, but which is practically irrelevant for me).

    CamelCase reduced typing speed and adds little benefit when compared
    with the alternatives (rational abbreviations, or even underscores).

    My complaint about CamelCase (or camelCase, which I put in the same
    category) is that my eyes have to work quite a bit harder compared
    to text using underscores between words. Reading either form of
    camelCase is slower, and also requires more mental effort, relative
    to using underscores. Exception: CamelCase for a short noun phrase
    (up to perhaps three or four words) seems to work well for type
    names, probably because I can recognize the phrase as a whole
    without needing (most of the time) to look at the individual words.
    That property does not hold for names of variables or functions.


    I use camelCase sometimes, but I find myself using underscores a lot
    more in recent times. It is, I think, an eye thing - strangely, my eyes
    have got older over time, and the legibility of identifiers has become
    more important to me!

    For the most part I don't use abbreviations in the usual sense of
    the word, although I do sometimes use short non-words in a small
    local context (here "short" means usually one or two letters, and
    never more than four or five).

    A general guideline followed by most people is to have the length of identifiers (or their semantic content) increase with larger scope of
    the identifier. "i" is fine as a counter of a small loop, but you would
    not want to use it for a file-scope static.

    Which abbreviations are appropriate is often context-dependent. As long
    as the context is clear, they can be very helpful - in a genetics
    program, you would definitely want to use "DNA_string" in preference to "deoxyribonucleic_acid_string" as an identifier!

    But I dislike it when people use things like "indx" for "index" or "cnt"
    for "count".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Tim Rentsch on Tue Dec 3 16:09:22 2024
    On 03.12.2024 02:23, Tim Rentsch wrote:

    In my view case-insensitive matching/lookup is clearly worse than case-sensitive matching. There may be some contexts where a
    case-insensitive rule is tolerable or even preferable, but offhand
    I'm not thinking of one. Of course sometimes I do want matching
    to allow either case, for which 'grep -i' or some other common
    tool solves the problem; the key is that it's my choice, not
    a fixed choice imposed by a procrustean software system.

    These days, where case-sensitive data is normal, the often seen case-insensitive default for searching is a pain, IMO.

    What I'd prefer is; if I search with mixed case terms I want to
    get case sensitivity. Or more generally, a deliberate use of the
    shift key should be an indication of a case-sensitive search.
    (This of course might not be helpful or even bad for folks who
    are used to copy/paste with the mouse, where the first character
    might just be capitalized to match the locale/language rules.)


    My complaint about CamelCase (or camelCase, which I put in the same
    category) is that my eyes have to work quite a bit harder compared
    to text using underscores between words. Reading either form of
    camelCase is slower, and also requires more mental effort, relative
    to using underscores.

    That's certainly true. (This would also be an argument in favor
    of Algol 68's "identifiers with spaces" feature.)

    Exception: CamelCase for a short noun phrase
    (up to perhaps three or four words) seems to work well for type
    names, probably because I can recognize the phrase as a whole
    without needing (most of the time) to look at the individual words.
    That property does not hold for names of variables or functions.

    We used (I think it was also a common convention) to start class
    and type names with a capital letter, all the rest starting with
    lower case, with the exception of C-preprocessor elements that we
    wrote in all caps (but that we anyway only rarely used in C++).


    For the most part I don't use abbreviations in the usual sense of
    the word, although I do sometimes use short non-words in a small
    local context (here "short" means usually one or two letters, and
    never more than four or five).

    Also sensible (and I think quite typical); to consider local and
    global visibility, and differentiate technical and semantical
    entities. By abbreviations in the previous post I associated also
    common abbreviations (XML, SQL, IP) which in case of camel-case
    were written like word components (Xml, Sql, Ip).

    But much of all that are personal preferences or conventions that
    have to be followed for consistency as part of companies' coding
    standards.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Tue Dec 3 16:24:18 2024
    On 03/12/2024 13:34, Bart wrote:
    On 03/12/2024 11:15, Ben Bacarisse wrote:
    Bart <bc@freeuk.com> writes:
    ...
    If I write this

       int *A, B[10], C(int);

    My compiler tells me that:

       A is a local variable with type 'ref i32' (expressed in other syntax) >>>    B is a local variable with type '[10]i32'
       C is a function with return type of 'i32', taking one unnamed
         parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same
    declaration can
    also create names in different scopes!)

    A small correction: that declaration gives all three names the same
    scope[1].

    This is what I observed my compiler doing, because it displays the
    symbol table. It puts C into module-scope, so I can access it also from another function without another declaration (so non-conforming, but I'm
    long past caring).

    I can't see gcc's symbol table, but I can't access C from another
    function without it having its own declaration, or there being a
    module-scope one.

    Declarations are scoped in C. Of course you can't make a declaration
    like this inside one block and then access it from inside another block
    (that is not a subblock). You don't need to see gcc's symbol table to understand this - you just need to know the basics of structured
    programming.


    With gcc, such a declaration inside a function suffices to be able
    access a function 'C' defined later in the file.

    "int C(int);" declares that there exists an external linkage function
    "C" with prototype "int C(int)". If that identifier is used, then there
    must be a single function of that name and type defined somewhere in the program (in the same file or a different file). The block-scope
    declaration is only visible within that one block, of course.


     You are confusing scope with linkage.

    It's possible. So a function declaration inside a function gives the
    name external linkage (?).

    The declaration "int C(int)" is an external linkage declaration, because
    that is always the case for function declarations that are not
    explicitly declared "static". (And you can't have a static function declaration at block scope.)

    Which in this context means the function will
    be outside this one, but elsewhere in the module, rather than being
    imported from elsewhere module.

    Not at all. It could be elsewhere in the unit, or in a different unit.
    There is no distinction.


    If I say I find these quirks of C confusing, people will have another go
    at me. So let's say it makes perfect sense for 'extern' to mean two
    different things!


    Of course people will have another go at you for making wild and untrue assertions about things that should be pretty obvious to anyone who has
    thought about and read about scopes, identifiers and declarations - and
    which pretty much no one would ever write in real code.

    You are under no obligation to make your compiler conforming, but you
    don't get to claim you have made a compiler with different rules from C
    and that means C is confusing or ambiguous! It simply means that /you/
    were wrong, /you/ got confused, /you/ didn't make any effort to look at
    the standards and the definition of the language.

    Of course lots of C programmers have never read the standards. But they generally know that they don't know these details, and don't try to
    pretend that the language details that they don't know are confusing.
    They simply get on with the job of writing clear C code as best they can.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to David Brown on Tue Dec 3 15:20:44 2024
    David Brown <david.brown@hesbynett.no> writes:
    On 03/12/2024 02:23, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:


    For the most part I don't use abbreviations in the usual sense of
    the word, although I do sometimes use short non-words in a small
    local context (here "short" means usually one or two letters, and
    never more than four or five).

    A general guideline followed by most people is to have the length of >identifiers (or their semantic content) increase with larger scope of
    the identifier. "i" is fine as a counter of a small loop, but you would
    not want to use it for a file-scope static.

    Which abbreviations are appropriate is often context-dependent. As long
    as the context is clear, they can be very helpful - in a genetics
    program, you would definitely want to use "DNA_string" in preference to >"deoxyribonucleic_acid_string" as an identifier!

    I agree with both of these. In addition, when processing
    character strings, I'll often use 'cp' as a character pointer.


    But I dislike it when people use things like "indx" for "index" or "cnt"
    for "count".

    The use by programmers of the variable name 'index' has, in the past,
    caused issues (primarily due to conflicts with the BSD 'index' function).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Tue Dec 3 16:36:59 2024
    On 03.12.2024 16:00, David Brown wrote:

    A general guideline followed by most people is to have the length of identifiers (or their semantic content) increase with larger scope of
    the identifier. "i" is fine as a counter of a small loop, but you would
    not want to use it for a file-scope static.

    We've basically had just two types; semantical entities with
    explicit names, and local technical entities. But we anyway
    hadn't handled that too strictly; feedback from code-reviews
    corrected the worst excesses, or suggested name alternatives.

    [...]

    But I dislike it when people use things like "indx" for "index" or "cnt"
    for "count".

    (I also dislike saving single characters "indx" or "creat()".)

    Actually in local contexts (small scope) I have no issues with
    writing 'c' instead of 'count', or 'msg' instead of 'message'.

    The terser formulation (in a local structure) I think usually
    increases readability.

    Typically 'count' appears not being better than 'c' since both
    are technical entities and don't carry semantical information,
    in contexts like 'count++' or 'c++' you see it's counting even
    when writing 'x++' or 'foobar++'.

    Where the semantics of such an entity is relevant its name was
    even larger, like, say, 'inhabitants_count'. Or you may even
    strip the technical count 'inhabitants++', or 'nof_inhabitants'
    (we used the common "number of ..." abbreviated as "nof_...").

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Janis Papanagnou on Tue Dec 3 16:09:12 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 03.12.2024 02:23, Tim Rentsch wrote:

    In my view case-insensitive matching/lookup is clearly worse than
    case-sensitive matching. There may be some contexts where a
    case-insensitive rule is tolerable or even preferable, but offhand
    I'm not thinking of one. Of course sometimes I do want matching
    to allow either case, for which 'grep -i' or some other common
    tool solves the problem; the key is that it's my choice, not
    a fixed choice imposed by a procrustean software system.

    These days, where case-sensitive data is normal, the often seen >case-insensitive default for searching is a pain, IMO.

    In which utility is the default case insensitivity? vim
    and grep, for example, require options to provide case insensitive
    searches. (grep -i, vim :set ic, locate -i, et alia).

    I suppose windows might do something so useless.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Tue Dec 3 15:47:02 2024
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    So, how would you have organised the 16-module example I posted
    elsewhere? (Not a C project, these are 16 source files, so no headers
    etc.)

    Because two posters here have suggested my organisation is poor, but
    without knowing how big, small, or complex my projects are.

    No one (as far as I have noticed) have said that your organisation /is/
    poor - they have said it /sounds/ poor from the way you describe it. The difference is very significant.

    For file organisation, I'd likely have all the modules in one directory unless there is a particular reason to split them up.  I would not have
    any non-project files in that directory.

    But the questions raised about your organisation was not a matter of
    where you store your files, or how they are divided in directories.  It
    is about how you organise the code and split functionality between files
    (or directories, for bigger projects).

    What you have described is modules that have far too much in one file, modules with little or no structure as to where things are in the file,

    Because it doesn't really matter. (My language allows out-of-order
    everything. So all module-scope variables could go at the end of the
    file, or file-scope variables at the end of the function! However I
    don't do that.

    But I really don't want to care about whether function F precedes G in
    the file, or follows it. Any more than I would care whether a file "F"
    is stored before or after file "G" in a directory! The ordering could be
    sorted in different ways for display; perhaps an editor could do the
    same. (I guess your IDE does that.)

    little to no structure or control over which modules use facilities from which other modules, and completely random inter-module dependencies
    which can happily be circular.

    They can be circular when it makes sense. They are after all part of the
    same program!

    In C, if you have 100 modules, but modules 23 and 87 need to share some variable or function, it can be visible to the other 98 too, or can
    clash with the same name thaty 17 and 26 want to share. Or with a name
    that module 72 forgot to make static.

    Or module 49 exports variable 'abc' as int, but 53 imports it as
    'char*', then fun and games follow. C has a lot worse problems!


    Being able to split a too-large module into two or more files without
    worrying about hierarchy is a good thing; isn't it? If the original
    function exported F G H, accessed as X.F, X.G, X.H, do you then have to
    change all the calls to X.F, Y.G, Z.G because of how the original file
    has been split up?

    My scheme just makes this stuff very easy and effortless.

    These opinions are formed from how you describe your code and your
    language.

    Below I've given the actual set of modules from my C compiler project,
    partly annotated. It comprises three libraries whose sources files are
    compiled into one executable.

    The 'PCL' one (pc_ files) will probably be split up too at some point;
    right now there's no need.

    The average module size is 1000 lines, but some are larger. For example, pc_genmcl, which is a set of 150 handler functions for the 150 opcodes
    of my IL.

    And pc_run, which is the interpreter for the IL, whose core is an
    1100-line function containing a special kind of looping switch which is implemented as a computed-goto (different from a normal switch since
    there are N dispatch points rather than 1).

    So a module is larger when it needs to encapsulate functions that do
    part of the same job. There are several modules which have to dispatch
    on an IL bytecode, or AST tag, or native code instruction.



    BTW your project doesn't sound that big, especially if you have a
    penchant for having a larger number of smaller files.

    A line-count would give a better idea.


    For the whole project (relevant to things like the build and the organisation):

    ----------------------------------------------------------------------- Language             files          blank        comment           code
    ----------------------------------------------------------------------- C                      155          13849          34547          80139
    C/C++ Header           284          13719          62329          61056
    C++                     43           2447           1230          13009
    ----------------------------------------------------------------------- SUM:                   482          30015          98106         154204
    -----------------------------------------------------------------------

    So about 600 lines per file.


    For the project-specific code, rather than libraries, SDK, etc.:

    ----------------------------------------------------------------------- Language             files          blank        comment           code
    ----------------------------------------------------------------------- C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    ----------------------------------------------------------------------- SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------

    And here about 250 lines per file. Total line count isn't that different
    from my 1990s CAD app, which was about 150Kloc, more than half
    consisting of scripted modules.

    This doesn't include the add-on scripted modules that OEMs would write
    (plus alls sorts of data files, libraries of parts etc) to form the
    final product.

    Anyway, below are my C compiler modules as promised.

    Here, there is a hierarchy. None of the second two libraries can access anything from the main application. Both the first two can can access
    imported entities from the third library.


    -----------------------------------
    # Main application

    project =
    module cc_cli

    # Global Data and Tables
    module cc_decls
    module cc_tables

    # Lexing and Parsing
    module cc_lex
    module cc_parse

    # Generate PCL
    module cc_genpcl
    module cc_blockpcl
    module cc_libpcl

    # General
    module cc_lib
    module cc_support

    # Bundled headers
    module cc_headers
    # module cc_headersx

    # Diagnostics
    module cc_show
    # module cc_showdummy

    # IL Backend
    $sourcepath "c:/px/"
    import pcl
    end

    # Backend library

    project =
    module pc_decls

    # API to generate IL from a front-end compiler
    module pc_api

    # IL Diagnostics
    module pc_diags
    # module pc_diags_dummy

    module pc_reduce # experimental IL optimiser

    # PCL (IL) Interpreter
    module pc_run
    module pc_runaux

    # Tables (eg. types and IL opcodes)
    module pc_tables

    # x64 backend (pcl -> mcl)
    module mc_GenMCL # Main loop scanning PCL code
    module mc_AuxMCL
    module mc_LibMCL # API for building MCL (native code) representation
    module mc_StackMCL # Deal with converting stack-based IL to reg-based native code

    # Generate SS tables (MCL -> SS; SS is binary native code)
    module mc_GenSS

    module mc_Decls as md # (eg. x64 opcode enums)
    module mc_OBJdecls # Describe PE-format data structures

    # Write ASM (currently only one at a time is compiled in)
    module mc_WriteASM # MCL -> ASM source
    # module mc_WriteNASM # MCL -> NASM-format source

    # Write EXE/DLL/OBJ (from SS)
    module mc_WriteEXE # Create PE image and write EXE or DLL
    module mc_WriteOBJ

    # SS diagnostic display
    # module mc_writess
    # module mc_disasm # x64 disassembler for code segments
    module mc_writess_dummy

    # SS -> MCU -> MCX/MCB (Runnable in-memory code; or MX binary file)
    module mx_decls
    module mx_run
    module mx_lib
    module mx_write # Write MX-format binary

    end

    # Standard library of my language (this is imported by default)

    project =
    module msys # Language support
    module mlib # The std library
    module mclib # Import some C std library functions
    module mwindows # OS-specific functions
    module mwindll # provides LIBFFI-like capabilities
    end
    -----------------------------------

    When I used to support Linux targets, then mwindows was replaced by
    'mlinux', or 'mnos' for an OS-neutral version. This module provides a
    common set of wrapper functions over some OS-specfic functions

    For a C target (of the compiler for this project, then a target of this project), then mwindll is replaced mwindllc, which provides some limited functionality using HLL code only (so that it can be transpiled to C)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Tue Dec 3 17:12:44 2024
    On 03.12.2024 16:24, David Brown wrote:
    On 03/12/2024 13:34, Bart wrote:
    [...]

    Of course lots of C programmers have never read the standards. But they generally know that they don't know these details, and don't try to
    pretend that the language details that they don't know are confusing.
    They simply get on with the job of writing clear C code as best they can.

    I feel an urge to point out that the C standard is not necessary to
    understand concepts that can be read about in textbooks or inferred
    (or just tried out, if the available sources are unclear about some
    detail).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Scott Lurndal on Tue Dec 3 17:35:27 2024
    On 03.12.2024 17:09, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    These days, where case-sensitive data is normal, the often seen
    case-insensitive default for searching is a pain, IMO.

    In which utility is the default case insensitivity?

    In common daily use, the search in a browser, for example.
    Also search engines, Google.

    vim
    and grep, for example, require options to provide case insensitive
    searches. (grep -i, vim :set ic, locate -i, et alia).

    Sure. - In Vim or Grep I explicitly activate it in those
    [rare] cases where I need it.

    Unsurprisingly case-sensitivity is or seems generally be
    the default behavior for Unix tools that usually provide
    Regexp searches.

    In Vim, specifically, there's also a 'smartcase' setting
    available (which resembles what I wrote in my previous
    post about a search depending on whether there's a cap
    character in the search pattern)!


    I suppose windows might do something so useless.

    I'm not inclined to speak for or comment on Windows. :-)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to David Brown on Tue Dec 3 17:42:20 2024
    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any order of
    function definition, without requiring forward declarations to use a
    function before it is defined. But C is not like that, and I cannot
    honestly say it bothers me one way or the other. And apparently, it
    does not particularly bother many people - there is, I think, no
    serious impediment or backwards compatibility issue that would
    prevent C being changed in this way. Yet no one has felt the need
    for it - at least not strongly enough to fight for it going in the
    standard or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem here?

    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'. AFAICS the are on troubles with
    automatic reordering of "pure" declarations. But variable declarations
    may have initialization and 'constexpr' allows not entirely trivial
    expressions for initialization. And C wants to be compatible with
    C++, where even now initialization is much more "interesting".

    So, reordering variable declarations is problematic due to
    initalization and it would be ugly to have special case for
    function declarations.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Tue Dec 3 19:02:24 2024
    On 03/12/2024 16:47, Bart wrote:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    So, how would you have organised the 16-module example I posted
    elsewhere? (Not a C project, these are 16 source files, so no headers
    etc.)

    Because two posters here have suggested my organisation is poor, but
    without knowing how big, small, or complex my projects are.

    No one (as far as I have noticed) have said that your organisation
    /is/ poor - they have said it /sounds/ poor from the way you describe
    it. The difference is very significant.

    For file organisation, I'd likely have all the modules in one
    directory unless there is a particular reason to split them up.  I
    would not have any non-project files in that directory.

    But the questions raised about your organisation was not a matter of
    where you store your files, or how they are divided in directories.
    It is about how you organise the code and split functionality between
    files (or directories, for bigger projects).

    What you have described is modules that have far too much in one file,
    modules with little or no structure as to where things are in the file,

    Because it doesn't really matter.

    It really /does/ matter - regardless of what the language allows or does
    not allow. If your language does not enforce ordering rules, that gives
    you more flexibility, but it does not relieve you of your responsibility
    as a programmer of writing code in a logical and structured manner.

    (My language allows out-of-order
    everything. So all module-scope variables could go at the end of the
    file, or file-scope variables at the end of the function! However I
    don't do that.

    But I really don't want to care about whether function F precedes G in
    the file, or follows it. Any more than I would care whether a file "F"
    is stored before or after file "G" in a directory! The ordering could be sorted in different ways for display; perhaps an editor could do the
    same. (I guess your IDE does that.)

    little to no structure or control over which modules use facilities
    from which other modules, and completely random inter-module
    dependencies which can happily be circular.

    They can be circular when it makes sense. They are after all part of the
    same program!

    In C, if you have 100 modules, but modules 23 and 87 need to share some variable or function, it can be visible to the other 98 too, or can
    clash with the same name thaty 17 and 26 want to share. Or with a name
    that module 72 forgot to make static.


    C has a risk of name clashes - that's why I am a fan of namespaces
    (proper ones, not your weird half-arsed solution). But if only modules
    23 and 87 need access to the identifiers exported by module 42, then
    only those modules (and 42 itself) should include header 42. Module 68
    will not include it, and can happily re-use the same identifiers as
    static identifiers or local variables. And if the writer of module 72
    forgot to make a function static, ban them from the coffee machine until
    they have learned to use their tools correctly.

    You don't get to say that because it is possible to have certain
    problems in large C programs, anarchy should reign - especially not when
    you are making your own language and can get it right!

    Or module 49 exports variable 'abc' as int, but 53 imports it as
    'char*', then fun and games follow. C has a lot worse problems!

    That will be caught at link time, if not before - unless you have crappy
    tools or an ignorant programmer who doesn't know how to use them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Tue Dec 3 18:42:47 2024
    On 03/12/2024 18:02, David Brown wrote:
    On 03/12/2024 16:47, Bart wrote:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    So, how would you have organised the 16-module example I posted
    elsewhere? (Not a C project, these are 16 source files, so no
    headers etc.)

    Because two posters here have suggested my organisation is poor, but
    without knowing how big, small, or complex my projects are.

    No one (as far as I have noticed) have said that your organisation
    /is/ poor - they have said it /sounds/ poor from the way you describe
    it. The difference is very significant.

    For file organisation, I'd likely have all the modules in one
    directory unless there is a particular reason to split them up.  I
    would not have any non-project files in that directory.

    But the questions raised about your organisation was not a matter of
    where you store your files, or how they are divided in directories.
    It is about how you organise the code and split functionality between
    files (or directories, for bigger projects).

    What you have described is modules that have far too much in one
    file, modules with little or no structure as to where things are in
    the file,

    Because it doesn't really matter.


    It really /does/ matter - regardless of what the language allows or does
    not allow.

    Why?

    What possible difference can it make if functions are in the order F G H
    in the file or H G F?

    (Of course, it might matter for the C language for those who can't be
    bothered to provide the forward references the language makes possible.

    But I assume you have something else in mind. Note that lots of
    languages now allow out-of-order functions - allow a call to F before F
    is defined - so what you are complaining about here applies to those too.)



    If your language does not enforce ordering rules,

    There ARE no ordering rules! That's what 'out-of-order' means.

    (The only place where ordering might matter, is in the list of modules
    that describe the project. And that's only because of a feature where a
    special initialisation function in each module can be invoked
    automatically. The app may need those called in a certain order.)

    that gives
    you more flexibility, but it does not relieve you of your responsibility
    as a programmer of writing code in a logical and structured manner.

    With forward declarations provided, then C provides exactly the same flexibility in function ordering.


    In C, if you have 100 modules, but modules 23 and 87 need to share
    some variable or function, it can be visible to the other 98 too, or
    can clash with the same name thaty 17 and 26 want to share. Or with a
    name that module 72 forgot to make static.

    C has a risk of name clashes - that's why I am a fan of namespaces
    (proper ones, not your weird half-arsed solution).

    What's wrong with my solution? You seem to be making assumptions about it.

    All it does is allow you to write F() instead of A.F(). You can do the
    same thing in C++ (there it saves you writing A::), by doing this (AIUI):

    using A;

    I could spend 30 minutes in providing an option so that it needs to be
    explicit like this, but I don't have a pressing need to do so.

    BTW what happens in C++ when you do this:

    using A;
    using B;
    F();

    and both A and B export (or make public) F? What happens if there is
    also a locally defined F?

    Or module 49 exports variable 'abc' as int, but 53 imports it as
    'char*', then fun and games follow. C has a lot worse problems!

    That will be caught at link time, if not before

    Is it?

    c:\cx>type a.c

    extern void F(void);

    int abc;

    int main(void) {
    abc=12345;
    F();
    }

    c:\cx>type b.c
    #include <stdio.h>

    extern char* abc;

    void F() {
    puts(abc);
    }

    c:\cx>gcc a.c b.c
    c:\cx>a
    ....

    This crashes. This program is impossible to write in my language when
    both modules are part of the program.

    Only when the two functions are in different binaries so that one
    program needs to work with a potentially incorrect declaration. Even
    then, generating a DLL can also export an interface file with the
    correct declarations.

    Then it can only go wrong if one binary is updated and recompiled, but
    not the other. But this applies to any language.

    So it's a lot more fool-proof.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to BGB on Tue Dec 3 20:27:51 2024
    On 03.12.2024 19:57, BGB wrote:
    On 12/2/2024 12:13 PM, Scott Lurndal wrote:

    Indeed. One wonders at Bart's familiarity with formal grammars.

    In my case, personally I haven't encountered much that doesn't work well enough with a recursive-descent parser.

    Is that meant as a contradiction? - If so, how?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Tue Dec 3 11:31:12 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Fri, 29 Nov 2024 20:38:51 -0500
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

    On 11/29/24 19:55, Waldek Hebisch wrote:
    ...

    Hmm, in well-written code static functions are likely to be a
    majority. Some people prefer to declare all functions and
    put declarations of static functions in the same file as the
    functions itself. Conseqently, function declarations are not
    rare in such code. Do you consider it well-written?

    I wouldn't go so far as to say that it's poorly written, but I don't
    like the unnecessary redundancy of that approach. Whenever possible, I
    prefer to let each static function's definition serve as it's only
    declaration. This isn't possible, for instance, if you have a pair of
    mutually recursive functions.

    The redundancy between a header file's function declaration and the
    corresponding function definition is necessary, given the way that C
    works. Avoiding that is one of the reasons I like declaring static
    functions, where appropriate.

    Top-down-minded people don't like details textually preceding "big
    picture".

    [O.T.]
    Better solution would be if static function definition anywhere in the
    file serves like declaration (prototype) for the whole file, including preceding part. We are long past the time where single-pass compiler
    was a legit argument against such arrangement. Nowadays the only
    possible counter argument would be breaking existing code. But I don't
    see how such change breaks anything.

    You have my vote.

    I also vote for whole-file declarations for defined objects as well
    as functions, and for whole-file declarations for definitions of
    entities that have external linkage as well as statics.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Tue Dec 3 21:51:59 2024
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    ----------------------------------------------------------------------- Language             files          blank        comment           code
    ----------------------------------------------------------------------- C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    ----------------------------------------------------------------------- SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------


    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on my
    machine), I set up a comparable test. I took an 800-line C program, and duplicated it in 200 separate files f1.c to f200.c, for a total line
    count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    My two C compilers were rubbish so I won't report those timings (the
    newer one only works a file at a time anyway so needs invoking 200 times).

    However the equivalent test in my language, of 160 versions of a
    somewhat larger module, took 0.57 seconds (unoptimised compiler).

    Anyway, the gcc timings give a different picture from your 1-3 seconds.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Bart on Wed Dec 4 00:15:03 2024
    On 03/12/2024 21:51, Bart wrote:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    -----------------------------------------------------------------------
    Language             files          blank        comment           code
    -----------------------------------------------------------------------
    C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    -----------------------------------------------------------------------
    SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------


    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on my machine), I set up a comparable test. I took an 800-line C program, and duplicated it in 200 separate files f1.c to f200.c, for a total line
    count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    My two C compilers were rubbish so I won't report those timings (the
    newer one only works a file at a time anyway so needs invoking 200 times).

    The timing from one was about 9 seconds when it was generating 200 .obj
    files, before I tweaked things to allow an EXE to be created (by using
    'static' in each file to avoid clashes).

    If I also include my original compiler when I strived to make multiple
    files more efficient, then timings on Windows are:

    mm 0.53 seconds (Non-C test inputs)
    tcc 0.64 seconds
    bcc 1 second
    mcc 3 seconds
    cc 5 seconds (to produce 200 .obj files)
    gcc 32 seconds (-O0, v.14.1; the WSL timing was for 9.4)

    The original 93 seconds for gcc-O2 was for a test using non-static
    functions and generating 200 .o files. I reran it for EXE using -O0 but
    not with -O2.

    If I do so now, gcc-O2 takes 18 seconds, but it produces a too-small EXE
    file. Presumably it is largely discarding the 199 modules that comprise
    only static functions.

    So that timing is erroneous.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Tue Dec 3 17:14:08 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    If someone wanted to ensure that all static functions defined in a translation unit are declared near the top, there could be a separate
    tool to generate, or at least check, the declarations. I'm not aware of
    any such tool, which suggests there probably isn't much demand for it.

    What it suggests to me is that there are tools being used that
    you aren't aware of.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Wed Dec 4 00:56:17 2024
    On 02/12/2024 18:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    OK. I think the opposite. So who's right?



    it's not fussy about semicolons,

    From the languages I know of in detail and I'm experienced in none
    is "fussy" about semicolons. Rather it's a simple and well designed
    syntactical token, whether used as separator or terminator. You've
    just to put it where it's defined.

    Indeed. One wonders at Bart's familiarity with formal grammars.

    Why?

    I've no idea about your familiarity with such things, and I couldn't
    care less. Why are you so fascinated with my credentials?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Tue Dec 3 17:19:12 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    David Brown <david.brown@hesbynett.no> writes:

    On 03/12/2024 02:23, Tim Rentsch wrote:

    scott@slp53.sl.home (Scott Lurndal) writes:


    For the most part I don't use abbreviations in the usual sense of
    the word, although I do sometimes use short non-words in a small
    local context (here "short" means usually one or two letters, and
    never more than four or five).

    A general guideline followed by most people is to have the length of
    identifiers (or their semantic content) increase with larger scope of
    the identifier. "i" is fine as a counter of a small loop, but you would
    not want to use it for a file-scope static.

    Which abbreviations are appropriate is often context-dependent. As long
    as the context is clear, they can be very helpful - in a genetics
    program, you would definitely want to use "DNA_string" in preference to
    "deoxyribonucleic_acid_string" as an identifier!

    I agree with both of these. In addition, when processing
    character strings, I'll often use 'cp' as a character pointer.

    My rule is not to use abbreviations, only words (with the
    short-non-word exception noted earlier). Widely known
    and commonly used acronyms, such as DNA, HTML, or TCP,
    are considered words, not abbreviations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Bart on Wed Dec 4 02:04:37 2024
    Bart <bc@freeuk.com> wrote:
    On 02/12/2024 21:06, David Brown wrote:
    On 02/12/2024 19:27, Bart wrote:
    On 02/12/2024 15:24, David Brown wrote:
    On 02/12/2024 13:24, Bart wrote:

    I would consider any kind of automatic import system to be a bad idea.

    It's not automatic; you have to list the modules. If you don't want
    data shared, then don't export it!


    As I understood it, or perhaps failed to understand it (after all, it's
    not as if there are published specifications, references,

    https://github.com/sal55/langs/blob/master/Modules24.md

    (A summary, mainly for my benefit, about a year old.)

    tutorials or
    examples for your language)

    I gave an example in my post, of the lead module for my C compiler.
    Older examples are in that link.

    In all (counting the 'pcl' backend library) it comprises 36 source files
    in two folders; plus about 40 C headers in two folders, which are
    embedded into the executable.

    This information is enough for the compiler, and nothing else, to locate
    all the necessary files and to build an EXE file.

    Your example does not show if you can have function with the same
    name say 'fun1' in two different modules say 'A' and 'B'. We
    want use of 'fun1' in module 'C' to refer to 'fun1' in 'A' and
    use of 'fun1' in module 'D to refer to 'fun1' in 'B'. 'A', 'B',
    'C', 'D' and possibly other modules are supposed to be linked
    together.

    you would list your modules for a program
    in one place, and then other modules in the program automatically import
    them all.

    The logic used in the name resolution pass of the compiler allows
    visibiliy without needing full name-qualifying.

    Most module system allows this, so really nothing new here.

    I can rename any module, and I only need to change the one file. I can
    move an exported function from one module to another, without making any other changes (eg. change all xxx.F() to yyy.F()).

    In one system that I use module names are independent of file names.
    I can rename file contaning a module and this is change of single
    line in a Makefile (could be 0 lines with more fancy Makefile, but
    I want to have explit list of files). When renaming a module, I
    need to change all places that reference it. For me it is not
    a big deal, that normally is few minutes of work (in most cases
    I could get away with simple mass search/replace which is single
    longish command line in the shell, but I prefer to be careful
    here) and is resonably infrequent. Note that in my case module
    names are part of "user interface", so I want to keep this
    resonably stable to limit impact on the users.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to BGB on Wed Dec 4 02:22:46 2024
    On 2024-12-03, BGB <cr88192@gmail.com> wrote:
    On 12/3/2024 1:27 PM, Janis Papanagnou wrote:
    On 03.12.2024 19:57, BGB wrote:
    On 12/2/2024 12:13 PM, Scott Lurndal wrote:

    Indeed. One wonders at Bart's familiarity with formal grammars.

    In my case, personally I haven't encountered much that doesn't work well >>> enough with a recursive-descent parser.

    Is that meant as a contradiction? - If so, how?


    Formal grammars and parser generators aren't usually necessary IME,
    since recursive descent can deal with most everything (and is generally
    more flexible than what one can deal with in a formal grammar).

    A hand written recursive descent parser will have the best tooling.

    If the language it is written in has a good debugger, then the
    parser automatically has a good debugger.

    This is not true of table driven parsers. They implement an ad-hoc
    virtual machine driven by tables, and that virtual machine typically has
    next to no debug support.

    In a recursive descent parser, you can put a breakpoint on "parse_expr"
    and see in the call stack that was called from "parse_statement_body"
    which was called from "parse_if_statement" and so on.

    That can be an important advantage. Parser generators are still used, nonetheless. The generated code has good performance, and the
    declarative nature has some points in its favor; you just get your shit debugged in other ways. Some of it can be mitigated by doing the minimal
    work in the parser: e.g. just building an abstract syntax tree,
    rather than the entire translation scheme.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Wed Dec 4 10:02:38 2024
    On 03/12/2024 19:42, Bart wrote:
    On 03/12/2024 18:02, David Brown wrote:
    On 03/12/2024 16:47, Bart wrote:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    So, how would you have organised the 16-module example I posted
    elsewhere? (Not a C project, these are 16 source files, so no
    headers etc.)

    Because two posters here have suggested my organisation is poor,
    but without knowing how big, small, or complex my projects are.

    No one (as far as I have noticed) have said that your organisation
    /is/ poor - they have said it /sounds/ poor from the way you
    describe it. The difference is very significant.

    For file organisation, I'd likely have all the modules in one
    directory unless there is a particular reason to split them up.  I
    would not have any non-project files in that directory.

    But the questions raised about your organisation was not a matter of
    where you store your files, or how they are divided in directories.
    It is about how you organise the code and split functionality
    between files (or directories, for bigger projects).

    What you have described is modules that have far too much in one
    file, modules with little or no structure as to where things are in
    the file,

    Because it doesn't really matter.


    It really /does/ matter - regardless of what the language allows or
    does not allow.

    Why?

    code the reading is important order people to.

    Or, if you prefer,

    Order is important to people reading the code.


    The compiler spends milliseconds reading the code. Programmers spend
    hours, days, or more reading the code. It's not particularly important
    if the language requires a particular order or not, except in how it
    helps or hinders the programmer in their order of the code. And it is certainly the case that different programmers will prefer different ways
    to order and arrange their code - but that does not stop it being
    important. When you write code, write it for human readers - other
    people, including your future self. If you like bottom-up ordering,
    fine. If you like top-down ordering, fine. If you like grouping
    functions and data in other ways, fine. If you like a dog's breakfast,
    not so fine.


    In C, if you have 100 modules, but modules 23 and 87 need to share
    some variable or function, it can be visible to the other 98 too, or
    can clash with the same name thaty 17 and 26 want to share. Or with a
    name that module 72 forgot to make static.

    C has a risk of name clashes - that's why I am a fan of namespaces
    (proper ones, not your weird half-arsed solution).

    What's wrong with my solution? You seem to be making assumptions about it.


    Yes, I am making assumptions - I am assuming that what you write about
    your language is true. I know that is far from a valid assumption when
    you write about C, but for your language, I've nothing else to go on.

    I've already made it clear what I think is wrong about your solution -
    the jumbling of namespaces. (And /please/ don't harp on about C's
    system again - the fact that C does not have a good way of handling
    namespaces does not suddenly make /your/ version good.)

    All it does is allow you to write F() instead of A.F(). You can do the
    same thing in C++ (there it saves you writing A::), by doing this (AIUI):

      using A;

    (You mean "using namespace A;". It's no problem that you don't know the
    right syntax for C++, but I'm correcting it in case you want to try
    anything on godbolt.org.)

    Yes, C++ /allows/ you to do that - if you explicitly choose to do so for
    a particular namespace. Thus if you are going to use identifiers from a namespace often, and you are confident it will not lead to conflicts,
    then you can do so. C++ "using namespace A;" is commonly used in a few circumstances:

    1. At file scope to pull in a small namespace that you use extensively throughout the code in the file.

    2. For things like "using std;" at file scope for quick and dirty
    programs - test programs, or code written by lazy programmers, to the
    annoyance of anyone later dealing with the code.

    3. In block scope within a function that makes a lot of use of the
    namespace. Within the function, you have far tighter control about what identifiers are used there so the code can remain clear.

    4. For pulling in things like user-defined literals that would look
    really ugly with explicit namespace qualifiers. These will usually be
    within a small block scope.


    Having every module in a program automatically pull in every exported identifier from every other module in the program is not structured or
    modular programming - it is anarchy.


    I could spend 30 minutes in providing an option so that it needs to be explicit like this, but I don't have a pressing need to do so.

    BTW what happens in C++ when you do this:

      using A;
      using B;
      F();

    and both A and B export (or make public) F? What happens if there is
    also a locally defined F?


    (Again - you mean either "using namespace A;" or "using A::F;".)

    You get an error if you try to use "F", as it is ambiguous. (Defining a
    new local function F is also an error even if F is never called.)


    Or module 49 exports variable 'abc' as int, but 53 imports it as
    'char*', then fun and games follow. C has a lot worse problems!

    That will be caught at link time, if not before

    Is it?

      c:\cx>type a.c

       extern void F(void);

       int abc;

       int main(void) {
           abc=12345;
           F();
       }

      c:\cx>type b.c
       #include <stdio.h>

       extern char* abc;

       void F() {
           puts(abc);
       }

       c:\cx>gcc a.c b.c
       c:\cx>a
       ....

    This crashes. This program is impossible to write in my language when
    both modules are part of the program.

    I'm sorry, I thought you meant if a sane C programmer wrote good code
    but accidentally had conflicting types. C is not as tolerant of idiots
    as some languages.


    Only when the two functions are in different binaries so that one
    program needs to work with a potentially incorrect declaration. Even
    then, generating a DLL can also export an interface file with the
    correct declarations.

    Then it can only go wrong if one binary is updated and recompiled, but
    not the other. But this applies to any language.

    So it's a lot more fool-proof.


    If you are a fool, you should probably avoid programming entirely.

    Languages and tools should try to be accident-proof, not fool-proof.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Wed Dec 4 10:54:48 2024
    On 03/12/2024 22:51, Bart wrote:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    -----------------------------------------------------------------------
    Language             files          blank        comment           code
    -----------------------------------------------------------------------
    C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    -----------------------------------------------------------------------
    SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------


    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.


    By "a typical build", I mean I make some modifications or changes to
    some code, then build the project to check for any static warnings and
    have the binaries ready to download to the target board for testing.
    Nothing is being "missed out".

    So, to get an idea of how long gcc really takes (or would take on my machine), I set up a comparable test. I took an 800-line C program, and duplicated it in 200 separate files f1.c to f200.c, for a total line
    count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    My two C compilers were rubbish so I won't report those timings (the
    newer one only works a file at a time anyway so needs invoking 200 times).

    However the equivalent test in my language, of 160 versions of a
    somewhat larger module, took 0.57 seconds (unoptimised compiler).

    Anyway, the gcc timings give a different picture from your 1-3 seconds.


    All you are showing is that you don't understand how to use compilers or
    how to build projects beyond little "hello world" tests.

    That's okay - we knew that from before. And you have shown
    extraordinary fortitude in resisting any information, advice, or help on
    the matter - we have to respect your perseverance in standing up for
    your beliefs in the face of overwhelming evidence to the contrary.

    You can show a flat-earther the curvature of the horizon, but you can't
    force them to change their minds. I can tell you that my typical build
    times when working on a project like this are a couple of seconds, but I
    can't make you believe me.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Wed Dec 4 11:00:18 2024
    On 04/12/2024 01:15, Bart wrote:
    On 03/12/2024 21:51, Bart wrote:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    -----------------------------------------------------------------------
    Language             files          blank        comment           code
    -----------------------------------------------------------------------
    C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    -----------------------------------------------------------------------
    SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------ >>>

    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on my
    machine), I set up a comparable test. I took an 800-line C program,
    and duplicated it in 200 separate files f1.c to f200.c, for a total
    line count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    My two C compilers were rubbish so I won't report those timings (the
    newer one only works a file at a time anyway so needs invoking 200
    times).

    The timing from one was about 9 seconds when it was generating 200 .obj files, before I tweaked things to allow an EXE to be created (by using 'static' in each file to avoid clashes).

    If I also include my original compiler when I strived to make multiple
    files more efficient, then timings on Windows are:

      mm   0.53 seconds  (Non-C test inputs)
      tcc  0.64 seconds
      bcc  1    second
      mcc  3    seconds
      cc   5    seconds (to produce 200 .obj files)
      gcc 32    seconds (-O0, v.14.1; the WSL timing was for 9.4)

    The original 93 seconds for gcc-O2 was for a test using non-static
    functions and generating 200 .o files. I reran it for EXE using -O0 but
    not with -O2.

    If I do so now, gcc-O2 takes 18 seconds, but it produces a too-small EXE file. Presumably it is largely discarding the 199 modules that comprise
    only static functions.

    So that timing is erroneous.


    I don't know why you are bothering with this. Most of the compilers you
    use here are useless for actual work, and the timings for them are
    therefore irrelevant. Your nonsense collection of random files with meaningless choices of "static" or "non-static" is in no way
    representative of anything.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to BGB on Wed Dec 4 11:45:36 2024
    On 03.12.2024 21:49, BGB wrote:
    On 12/3/2024 1:27 PM, Janis Papanagnou wrote:
    On 03.12.2024 19:57, BGB wrote:
    On 12/2/2024 12:13 PM, Scott Lurndal wrote:

    Indeed. One wonders at Bart's familiarity with formal grammars.

    In my case, personally I haven't encountered much that doesn't work well >>> enough with a recursive-descent parser.

    Is that meant as a contradiction? - If so, how?

    Formal grammars and parser generators aren't usually necessary IME,
    since recursive descent can deal with most everything (and is generally
    more flexible than what one can deal with in a formal grammar).

    Hmm, okay. We obviously widely disagree here. IMO a language needs a
    consistent grammar that one can look up to understand the syntactic
    structure of a language as a clean basis for its semantics. (I don't
    usually want to read [language implementation-]code (if available in
    the first place) to understand the languages' syntactical structure.)

    Language and grammar belongs together. Implementing a compiler or an interpreter for a language where no grammar was (or can be?) defined
    sounds absolutely odd to me.

    Of course you don't "need" a grammar to _implement_ a language tool,
    but it serves (and not only) to build a coherent language. Once you
    have a grammar for your language you can then make use of tools and
    formal rules to create a reliable outcome.

    (There's a small textbook from N. Wirth where he explains compiler
    construction (or rather, a specific, simple form of it) based on an
    LL(1) grammar and implemented that by a Recursive Descent parser. -
    Emphasis on the _grammar_ as base of the design and development! -
    I pointed to this example because - I think for simplicity - it also
    decided to implement the language using a Recursive Descent parser.
    Usually more powerful grammars and parsers are used; LR, LALR, ...)


    Though, it seems I didn't read enough, they were debating about
    syntactic use of semicolons as a separator rather than parser writing...

    Right. (Semicolons are a very basic element of a language and its
    "formal grammar" that Scott was referring to.)

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Wed Dec 4 11:51:36 2024
    On 04.12.2024 01:56, Bart wrote:
    On 02/12/2024 18:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    OK. I think the opposite. So who's right?

    There's many things that are not black/white, right or wrong.

    On this topic there's obviously opinions, there's pros and cons,
    depending on the specific language's context, and own experiences.

    We already have enough such "X/Y-wars"; we don't need another one.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to David Brown on Wed Dec 4 10:54:14 2024
    David Brown <david.brown@hesbynett.no> wrote:
    On 03/12/2024 18:42, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any order of >>>>> function definition, without requiring forward declarations to use a >>>>> function before it is defined. But C is not like that, and I cannot >>>>> honestly say it bothers me one way or the other. And apparently, it >>>>> does not particularly bother many people - there is, I think, no
    serious impediment or backwards compatibility issue that would
    prevent C being changed in this way. Yet no one has felt the need
    for it - at least not strongly enough to fight for it going in the
    standard or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem here? >>>
    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'. AFAICS the are on troubles with
    ^^
    no
    automatic reordering of "pure" declarations. But variable declarations
    may have initialization and 'constexpr' allows not entirely trivial
    expressions for initialization. And C wants to be compatible with
    C++, where even now initialization is much more "interesting".

    So, reordering variable declarations is problematic due to
    initalization and it would be ugly to have special case for
    function declarations.


    Prior to C23 you could have non-trivial expressions for initialisations
    that depend on the order of the declarations in the code:

    enum { a = 1, b = 10, c = 100 };
    const int y = (a * b) - (c / 10);

    constexpr in C23 gives you a lot of flexibility to do more here, using different types (not just "int"). Prior to C23, people would use
    #define'd macros:

    #define pi 3.14159265359
    const double zeta_2 = (pi * pi) / 6;

    constexpr does not actually change the principles here, it just makes
    them clearer and neater.


    Since macros are not scoped, and can be undefined and redefined, they
    will always be an issue for any re-ordering of code. Replacing such "literal" macros with constexpr declarations would make it a lot easier
    to support a single wide file-level scope where declaration order does
    not matter, rather than making it harder.

    From point of view of C standard, since macro expansion is logically
    a separate pass, it poses no problem, simply macros should be expanded
    before any possible reordering.

    Concerning C23 versus earlier C, C23 confirmed earlier direction,
    but already in earlier C reordering of function declarations
    would create significant inconsistency.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Waldek Hebisch on Wed Dec 4 11:26:42 2024
    On 03/12/2024 18:42, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any order of
    function definition, without requiring forward declarations to use a
    function before it is defined. But C is not like that, and I cannot
    honestly say it bothers me one way or the other. And apparently, it
    does not particularly bother many people - there is, I think, no
    serious impediment or backwards compatibility issue that would
    prevent C being changed in this way. Yet no one has felt the need
    for it - at least not strongly enough to fight for it going in the
    standard or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem here?

    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'. AFAICS the are on troubles with automatic reordering of "pure" declarations. But variable declarations
    may have initialization and 'constexpr' allows not entirely trivial expressions for initialization. And C wants to be compatible with
    C++, where even now initialization is much more "interesting".

    So, reordering variable declarations is problematic due to
    initalization and it would be ugly to have special case for
    function declarations.


    Prior to C23 you could have non-trivial expressions for initialisations
    that depend on the order of the declarations in the code:

    enum { a = 1, b = 10, c = 100 };
    const int y = (a * b) - (c / 10);

    constexpr in C23 gives you a lot of flexibility to do more here, using different types (not just "int"). Prior to C23, people would use
    #define'd macros:

    #define pi 3.14159265359
    const double zeta_2 = (pi * pi) / 6;

    constexpr does not actually change the principles here, it just makes
    them clearer and neater.


    Since macros are not scoped, and can be undefined and redefined, they
    will always be an issue for any re-ordering of code. Replacing such
    "literal" macros with constexpr declarations would make it a lot easier
    to support a single wide file-level scope where declaration order does
    not matter, rather than making it harder.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Keith Thompson on Wed Dec 4 13:35:22 2024
    On Tue, 03 Dec 2024 17:30:08 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    If someone wanted to ensure that all static functions defined in a
    translation unit are declared near the top, there could be a
    separate tool to generate, or at least check, the declarations.
    I'm not aware of any such tool, which suggests there probably
    isn't much demand for it.

    What it suggests to me is that there are tools being used that
    you aren't aware of.

    What that suggests to me is that you feel the need to snipe without
    sharing any actual information.

    Of course there are tools that I'm not aware of. I would have
    thought that would be too obvious to bother stating.

    Are you aware of any such tools? If so, do you have some reason
    for concealing information about them? If not, what is the basis
    for your assumption that such tools exist?


    I can't say that it took me 5 seconds of binging, because it took more.
    But it took less than 10 minutes. https://invisible-island.net/cproto/cproto.html
    'cptoto -S' + a little of makefile magic will do the job.
    Plus or minus bugs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Wed Dec 4 13:08:27 2024
    On 03/12/2024 17:12, Janis Papanagnou wrote:
    On 03.12.2024 16:24, David Brown wrote:
    On 03/12/2024 13:34, Bart wrote:
    [...]

    Of course lots of C programmers have never read the standards. But they
    generally know that they don't know these details, and don't try to
    pretend that the language details that they don't know are confusing.
    They simply get on with the job of writing clear C code as best they can.

    I feel an urge to point out that the C standard is not necessary to understand concepts that can be read about in textbooks or inferred
    (or just tried out, if the available sources are unclear about some
    detail).


    Sure. And it is certainly /possible/ to know all the small details of C without ever reading the standards. But it's quite unlikely. This was
    a small detail of how declaring a function from inside a block interacts
    with a definition of the same function in the same unit. That is not
    something that will occur often in real code - it only came up because
    Bart is an expert at thinking up things in C that confuse him. In the
    real world, programmers simply don't do that kind of thing - and the
    kind of C programmer who is interested in these details will almost
    certainly also be interested in reading the standards.

    Most C programmers never look at the standards - textbooks, decent
    reference sites (like www.cppreference.com), common sense, and trial and
    error with quality compilers is sufficient for most programmers.

    There's nothing at all wrong with not knowing the whole language, or not
    having read the standards. There's nothing wrong with saying "I find
    this thing in C confusing" when you don't know how it works. But there
    /is/ something wrong with saying "C /is/ confusing" when you haven't
    learned how it works or consulted the standards and good references.
    The first is accepting personal responsibility, so that you can either
    learn about the feature or accept that it is a feature you want to avoid
    in your programming. The second is trying to pass the buck - blame your
    tools, blame other people, blame anyone but yourself. (If you find a
    feature in the language that you understand and have read about in the standards, and which a large proportion of programmers have trouble with
    - /then/ you have justification for saying that this particular feature
    of C is confusing.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Waldek Hebisch on Wed Dec 4 13:56:53 2024
    On Tue, 3 Dec 2024 17:42:20 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any
    order of function definition, without requiring forward
    declarations to use a function before it is defined. But C is
    not like that, and I cannot honestly say it bothers me one way or
    the other. And apparently, it does not particularly bother many
    people - there is, I think, no serious impediment or backwards
    compatibility issue that would prevent C being changed in this
    way. Yet no one has felt the need for it - at least not strongly
    enough to fight for it going in the standard or being a common
    compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem
    here?

    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'.

    No, I am afraid of cases where function is used without prototype and
    then there is conflicting definition later in the module.
    Of course, it's UB, but in practice it could often work fine.
    Something like that:

    static int bar();
    int foo(void)
    {
    return bar(42);
    }

    static int bar(int a, int b)
    {
    if (a == 42)
    return -1;
    return a - b;
    }


    Under c23 rules the code above is illegal, but before c23 it's merely
    a UB.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Bart on Wed Dec 4 11:16:14 2024
    Bart <bc@freeuk.com> writes:

    On 03/12/2024 11:15, Ben Bacarisse wrote:
    Bart <bc@freeuk.com> writes:
    ...
    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable with type 'ref i32' (expressed in other syntax) >>> B is a local variable with type '[10]i32'
    C is a function with return type of 'i32', taking one unnamed
    parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same declaration can >>> also create names in different scopes!)
    A small correction: that declaration gives all three names the same
    scope[1].

    This is what I observed my compiler doing, because it displays the symbol table. It puts C into module-scope, so I can access it also from another function without another declaration (so non-conforming, but I'm long past caring).

    You invented the term "module-scope" and that means you've lost track of
    what the scope of a name is in C. The scope of a name is the portion of
    the text program text in which that name can be used to refer the
    "thing" that was declared. Take this example

    // We'll assume that none of the names A, B and C are previously
    // declared here.

    if (...) {
    int *A, B[10], C(int);
    ...
    // The names A, B and C can be used here to refer the things
    // declared (and in the case of A and B defined) above.
    ...
    }
    // None of the names A, B and C can be used here. The scope ended
    // at the closing brace.

    To understand C you need to know what scope is and what linkage is. C
    will have external linkage, because all non-static function declarations
    get given external linkage. That is entirely separate from the scope of
    the name being declared.

    I can't see gcc's symbol table, but I can't access C from another function without it having its own declaration, or there being a module-scope one.

    With gcc, such a declaration inside a function suffices to be able access a function 'C' defined later in the file.

    You are confusing scope with linkage.

    It's possible. So a function declaration inside a function gives the name external linkage (?).

    Yes.

    Which in this context means the function will be outside this one, but elsewhere in the module, rather than being imported from elsewhere
    module.

    I can't say yes or no unless you explain all your terms. C does not
    have imports or modules. A good C book (or the standard) will explain
    what external linkage really means.

    If I say I find these quirks of C confusing, people will have another go at me. So let's say it makes perfect sense for 'extern' to mean two different things!

    I don't want to have a go at you, but it seems odd that you don't know
    what the scope of a declared name is. For a compiler writer, that is a
    very important concept.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Bart on Wed Dec 4 12:29:21 2024
    Bart <bc@freeuk.com> wrote:
    You've never used my scheme.

    Your scheme, not. But you should understand that when speaking
    about module systems C is an outlier, having almost no support
    for modules. Some languages, like C++ and Lisp go half way,
    providing namespaces but rest is up to programmer. Other do
    more. By now classis is _logical_ separation into interface
    and implementation, which seem to be absent from your system.

    One significant advantage is that because
    all modules (and subprogram imports) are listed in the lead module
    (usually that's all it contains), it is very easy to build a different configuration using an alternative lead module with a different collection.

    This is not enforced, but easy to do in any resonable module system.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Wed Dec 4 13:15:53 2024
    On 04/12/2024 12:56, Michael S wrote:
    On Tue, 3 Dec 2024 17:42:20 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any
    order of function definition, without requiring forward
    declarations to use a function before it is defined. But C is
    not like that, and I cannot honestly say it bothers me one way or
    the other. And apparently, it does not particularly bother many
    people - there is, I think, no serious impediment or backwards
    compatibility issue that would prevent C being changed in this
    way. Yet no one has felt the need for it - at least not strongly
    enough to fight for it going in the standard or being a common
    compiler extension.




    I think, arguing in favor of such change would be easier on top of
    the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more categorical
    claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem
    here?

    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'.

    No, I am afraid of cases where function is used without prototype and
    then there is conflicting definition later in the module.
    Of course, it's UB, but in practice it could often work fine.
    Something like that:

    static int bar();
    int foo(void)
    {
    return bar(42);
    }

    static int bar(int a, int b)
    {
    if (a == 42)
    return -1;
    return a - b;
    }


    Under c23 rules the code above is illegal, but before c23 it's merely
    a UB.


    I think it is always better to have a hard error than to allow UB!

    But this is not actually anything to do with ordering of functions or declarations. You could omit "foo" entirely and the code is still an
    error in C23, because "static int bar();" /is/ a prototype declaration
    in C23 - it means the same as "static int bar(void);".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Wed Dec 4 14:45:12 2024
    On 04/12/2024 14:36, Michael S wrote:
    On Wed, 4 Dec 2024 13:15:53 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 04/12/2024 12:56, Michael S wrote:
    On Tue, 3 Dec 2024 17:42:20 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any
    order of function definition, without requiring forward
    declarations to use a function before it is defined. But C is
    not like that, and I cannot honestly say it bothers me one way
    or the other. And apparently, it does not particularly bother
    many people - there is, I think, no serious impediment or
    backwards compatibility issue that would prevent C being
    changed in this way. Yet no one has felt the need for it - at
    least not strongly enough to fight for it going in the standard
    or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top
    of the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more
    categorical claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem
    here?

    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'.

    No, I am afraid of cases where function is used without prototype
    and then there is conflicting definition later in the module.
    Of course, it's UB, but in practice it could often work fine.
    Something like that:

    static int bar();
    int foo(void)
    {
    return bar(42);
    }

    static int bar(int a, int b)
    {
    if (a == 42)
    return -1;
    return a - b;
    }


    Under c23 rules the code above is illegal, but before c23 it's
    merely a UB.


    I think it is always better to have a hard error than to allow UB!

    But this is not actually anything to do with ordering of functions or
    declarations. You could omit "foo" entirely and the code is still an
    error in C23, because "static int bar();" /is/ a prototype
    declaration in C23 - it means the same as "static int bar(void);".


    In case you lost the context, in the post above I am explaining why I
    think that the suggested change that turns any static function
    definition into "retroactive" module-scale prototype declaration can potentially break working pre-C23 code. On the other hand, so far I was
    not able to imagine a case in which such change would break C23 code.
    And that is the reason why I think that the change is easier to
    introduce on top of C23.


    Thank you - that clarifies things a lot. I thought you had been saying
    that C23 made it /harder/ (or impossible) to introduce "module-scope"
    static identifiers in C without backwards compatibility issues. I agree
    that would be (at least slightly) easier in C23.

    Sorry for my misunderstanding.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Wed Dec 4 15:36:38 2024
    On Wed, 4 Dec 2024 13:15:53 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 04/12/2024 12:56, Michael S wrote:
    On Tue, 3 Dec 2024 17:42:20 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    David Brown <david.brown@hesbynett.no> wrote:
    On 01/12/2024 17:57, Michael S wrote:
    On Sun, 1 Dec 2024 15:34:04 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    I can see some advantages in a language being happy with any
    order of function definition, without requiring forward
    declarations to use a function before it is defined. But C is
    not like that, and I cannot honestly say it bothers me one way
    or the other. And apparently, it does not particularly bother
    many people - there is, I think, no serious impediment or
    backwards compatibility issue that would prevent C being
    changed in this way. Yet no one has felt the need for it - at
    least not strongly enough to fight for it going in the standard
    or being a common compiler extension.




    I think, arguing in favor of such change would be easier on top
    of the changes made in C23.
    Before C23 there were, as you put it "no serious impediment or
    backwards compatibility issue". After C23 we could more
    categorical claim that there are no new issues.


    Does that mean there was something that you think was allowed in C
    before C23, but not after C23, that would potentially be a problem
    here?

    What, specifically, are you thinking of?

    Michael probably meant 'constexpr'.

    No, I am afraid of cases where function is used without prototype
    and then there is conflicting definition later in the module.
    Of course, it's UB, but in practice it could often work fine.
    Something like that:

    static int bar();
    int foo(void)
    {
    return bar(42);
    }

    static int bar(int a, int b)
    {
    if (a == 42)
    return -1;
    return a - b;
    }


    Under c23 rules the code above is illegal, but before c23 it's
    merely a UB.


    I think it is always better to have a hard error than to allow UB!

    But this is not actually anything to do with ordering of functions or declarations. You could omit "foo" entirely and the code is still an
    error in C23, because "static int bar();" /is/ a prototype
    declaration in C23 - it means the same as "static int bar(void);".


    In case you lost the context, in the post above I am explaining why I
    think that the suggested change that turns any static function
    definition into "retroactive" module-scale prototype declaration can potentially break working pre-C23 code. On the other hand, so far I was
    not able to imagine a case in which such change would break C23 code.
    And that is the reason why I think that the change is easier to
    introduce on top of C23.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Wed Dec 4 15:09:12 2024
    On 04/12/2024 09:02, David Brown wrote:
    On 03/12/2024 19:42, Bart wrote:

    It really /does/ matter - regardless of what the language allows or
    does not allow.

    Why?

    code the reading is important order people to.

    Or, if you prefer,

    Order is important to people reading the code.



    The compiler spends milliseconds reading the code.  Programmers spend
    hours, days, or more reading the code.  It's not particularly important
    if the language requires a particular order or not, except in how it
    helps or hinders the programmer in their order of the code.

    You've lost me.

    A language source file isn't a story that needs to be consumed
    sequentially. It will be a collection of functions that will have some arbitrary call-pattern at runtime, perhaps different each time.

    So the static ordering is irrelevant. If you're looking at F, which
    calls G, and you want to look at G, then G is not always going to be immediately before F! It might be at any point before, so it might
    equally be at any point after. Or it could be located at anywhere in the
    100s of modules that comprise the project.

    In any case, you'd probably just click on G and it will take you there.

    To put in another way, I've never noticed any particular pattern in
    function ordering of any open source project.

    This sounds like something peculiar to you.


      And it is
    certainly the case that different programmers will prefer different ways
    to order and arrange their code - but that does not stop it being important.  When you write code, write it for human readers - other

    And here I've lost track of what this particular complaint about me is
    about. But it looks like it would apply to the majority of the world's programmers.

    Perhaps functions should be in alphabetic order?


    I've already made it clear what I think is wrong about your solution -
    the jumbling of namespaces.  (And /please/ don't harp on about C's
    system again - the fact that C does not have a good way of handling namespaces does not suddenly make /your/ version good.)

    All it does is allow you to write F() instead of A.F(). You can do the
    same thing in C++ (there it saves you writing A::), by doing this (AIUI):

       using A;

    (You mean "using namespace A;".  It's no problem that you don't know the right syntax for C++, but I'm correcting it in case you want to try
    anything on godbolt.org.)

    Yes, C++ /allows/ you to do that - if you explicitly choose to do so for
    a particular namespace.  Thus if you are going to use identifiers from a namespace often, and you are confident it will not lead to conflicts,
    then you can do so.  C++ "using namespace A;" is commonly used in a few circumstances:

    It's used to avoid cluttering code with ugly xxx:: qualifiers, and save
    some typing at the same time. That's pretty much it.

    To that end, C++ and my language achieve the same thing. I just decided
    to make 'using namespace xxx' the default, and haven't got around to
    making it optional. (In an early version, I did need such a directive.)

    (However it most likely differs from C++ in what it calls 'namespaces'.

    My remarks have been about the namespace that is created by a module.

    I understand that C++ namespaces can be created in other ways, like
    classes. I sort of have that too, but rarely use the feature:

    record foo =
    proc F = println "FOO/F" end
    end

    record bar =
    proc F = println "BAR/F" end
    end

    proc F = println "MAIN/F" end

    proc main =
    foo.F()
    bar.F()
    F()
    end

    Here, I don't need to create instances of foo and bar; they serve to encapsulate any kinds of named entities.)



    Having every module in a program automatically pull in every exported identifier from every other module in the program is not structured or modular programming - it is anarchy.

    In the 'subprogram'. The structure is there.

    in every exported identifier

    Yes, every EXPORTED identifier. An exporting module doesn't know which
    modules are going to access that identifier, and it doesn't have any
    control over that (I don't know of any scheme allows that; maybe you do?)

    So it knows it could be used from anywhere that imports this module.

    I decided to create a concept of a 'chummy' set of modules (the
    'subprogram') which freely see others exports, while not seeing the
    local entities which are kept private.

    Much like people in a rooming house call each other by their first names.

    You get an error if you try to use "F", as it is ambiguous.

    Same here.

      (Defining a
    new local function F is also an error even if F is never called.)

    That I don't do, as it is the typical and expected behaviour when you
    have shadowing of names in an outer scope; generally it is not reported.

    However, things can always be tweaked. I just find the model works fine
    for me.

    This crashes. This program is impossible to write in my language when
    both modules are part of the program.

    I'm sorry, I thought you meant if a sane C programmer wrote good code
    but accidentally had conflicting types.  C is not as tolerant of idiots
    as some languages.

    So it's a lot more fool-proof.

    If you are a fool, you should probably avoid programming entirely.

    Fuck you. Obviously you're going to shoot down whatever I say, trash
    whatever I have achieved, because .... I've really no idea.

    Yesterday you tried to give the misleading impression that compiling a substantial 200Kloc project only took 1-3 seconds with gcc.

    I gave some timings that showed gcc-O0 taking 50 times longer than tcc,
    and 150 times longer with -O2.

    That is the real picture. Maybe your machine is faster than mine, but I
    doubt it is 100 times faster. (If you don't like my benchmark, then
    provide another in portable C.)

    All this just so you can crap all over the benefits of small, faster,
    simpler tools.

    I'm pretty sure tcc won't compile your projects, because your projects
    will be 100% dependent on the special features, extensions, and options
    of your prefered tools. So that is hardly surprising.

    But that's not a reason to dismiss it for everyone else.

    Languages and tools should try to be accident-proof, not fool-proof.

    And yet my product IS fool-proof. So again, fuck you.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Kaz Kylheku on Wed Dec 4 08:04:59 2024
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    A hand written recursive descent parser will have the best tooling.

    Recursive descent parsers work well for some classes of
    context-free grammars. Other context-free grammars, not
    so much.

    A hand written recursive descent parser might have better
    tooling than any table-driven parser for the same language.
    Then again, it might not, depending on how it was written,
    and what table-driven alternatives are available.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Waldek Hebisch on Wed Dec 4 15:46:55 2024
    On 04/12/2024 12:29, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    You've never used my scheme.

    Your scheme, not. But you should understand that when speaking
    about module systems C is an outlier, having almost no support
    for modules. Some languages, like C++ and Lisp go half way,
    providing namespaces but rest is up to programmer. Other do
    more. By now classis is _logical_ separation into interface
    and implementation, which seem to be absent from your system.

    It is there, but at a different boundary.

    My language is intended for whole program compilation. There are no
    interfaces between modules (that is, a file listing the exports of a
    module, separately from the implementation).

    Because the compiler can see (and will compile) the actual implementation

    Such interface files exist between programs, which usually means between
    a main program and the libraries it uses, which are generally
    dynamically loaded.

    To that end, when compiling a set of modules into a library, the
    compiler can generate a suitable interface file (I used to call them
    exports files).

    This part is poorly developed, as it is little used, but it can create
    such files for my two languages, and /could/ generate them for C. There,
    it would take the form of a header file.

    Example library, called fred.m:

    export func add3(int a,b,c)int =
    a+b+c
    end

    Create the DLL and interface:

    c:\mapps>mm -dll fred
    Compiling fred.m to fred.dll
    Writing exports file to fred_lib.m

    The interface file produced (fred_lib.m):

    importdllfred =
    func add3(i64 a,b,c) => i64
    end

    The C version would be:

    extern i64 add3(i64, i64, i64);

    Back to my version, I can use that DLL like this:

    module fred_lib

    proc main =
    println add3(10,20,30)
    end

    Compile and run that:

    c:\mapps>mm -r test
    Compiling test.m to test.(run)
    60

    As a bonus, this simple example will also run unchanged in my dynamic
    scripting language; I just need to change the file extensions. So I can trivially create native-code functions to call from dynamic code.

    But in practice, more work is needed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to BGB on Wed Dec 4 16:49:32 2024
    BGB <cr88192@gmail.com> writes:
    On 12/3/2024 1:27 PM, Janis Papanagnou wrote:
    On 03.12.2024 19:57, BGB wrote:
    On 12/2/2024 12:13 PM, Scott Lurndal wrote:

    Indeed. One wonders at Bart's familiarity with formal grammars.

    In my case, personally I haven't encountered much that doesn't work well >>> enough with a recursive-descent parser.

    Is that meant as a contradiction? - If so, how?


    Formal grammars and parser generators aren't usually necessary IME,
    since recursive descent can deal with most everything (and is generally
    more flexible than what one can deal with in a formal grammar).

    How can you write a correct recursive descent parser without a
    formal grammar (at least on paper) for the language being parsed?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Wed Dec 4 16:57:47 2024
    Bart <bc@freeuk.com> writes:
    On 02/12/2024 18:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    OK. I think the opposite. So who's right?

    The consensus so far does not favor your viewpoint.

    From the languages I know of in detail and I'm experienced in none
    is "fussy" about semicolons. Rather it's a simple and well designed
    syntactical token, whether used as separator or terminator. You've
    just to put it where it's defined.

    Indeed. One wonders at Bart's familiarity with formal grammars.

    Why?

    Because having a formal grammar is the keystone of a good
    language design.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Ben Bacarisse on Wed Dec 4 08:38:53 2024
    Ben Bacarisse <ben@bsb.me.uk> writes:

    Bart <bc@freeuk.com> writes:

    On 03/12/2024 11:15, Ben Bacarisse wrote:

    Bart <bc@freeuk.com> writes:
    ...

    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable [...]
    B is a local variable [...]
    C is a function with return type of 'i32', taking one
    unnamed parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same
    declaration can also create names in different scopes!)

    That means your compiler is not compiling standard C. In standard C
    all entities declared locally have block scope, not file scope.

    A small correction: that declaration gives all three names the
    same scope[1].

    This is what I observed my compiler doing, because it displays the
    symbol table. It puts C into module-scope, so I can access it also
    from another function without another declaration (so
    non-conforming, but I'm long past caring).

    You invented the term "module-scope" and that means you've lost
    track of what the scope of a name is in C. [...]

    To be fair, the C standard does use the phrase "file scope", and
    mentions giving file scope to function identifiers (even locally
    declared ones) as a common extension.

    That doesn't invalidate your reaction to Bart's statement, because
    he is being sloppy with language, and that deserves being pointed
    out. The important point here, even though what is being done is
    not standard C, is that a single declaration is putting names into
    different /kinds/ of scopes. It would have been better if he had
    said "different kinds of scopes" rather than just "different
    scopes". Besides being wrong, what he did say raises the question
    of whether he knows the difference.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Wed Dec 4 16:55:43 2024
    Bart <bc@freeuk.com> writes:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    -----------------------------------------------------------------------
    Language             files          blank        comment           code
    -----------------------------------------------------------------------
    C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    -----------------------------------------------------------------------
    SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------


    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on my >machine), I set up a comparable test. I took an 800-line C program, and >duplicated it in 200 separate files f1.c to f200.c, for a total line
    count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    Here's a typical build for my project:

    $ make -s -j 64
    ...

    COMPILE apc2.cpp
    COMPILE bcp2.cpp
    BUILD /scratch/lib/libdevice_yyy.so
    XXXX_BUILT
    BUILDSO /scratch/libxxxx.so.1.0
    BUILD TARGET /scratch/bin/xxxx
    COMPILE shim.cpp

    real 13m48.24s
    user 1h2m9.78s
    sys 0m56.73s

    13 minutes by the wall clock, a bit over an hour
    of CPU time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Tim Rentsch on Wed Dec 4 17:26:23 2024
    On 04/12/2024 16:38, Tim Rentsch wrote:
    Ben Bacarisse <ben@bsb.me.uk> writes:

    Bart <bc@freeuk.com> writes:

    On 03/12/2024 11:15, Ben Bacarisse wrote:

    Bart <bc@freeuk.com> writes:
    ...

    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable [...]
    B is a local variable [...]
    C is a function with return type of 'i32', taking one
    unnamed parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same
    declaration can also create names in different scopes!)

    That means your compiler is not compiling standard C. In standard C
    all entities declared locally have block scope, not file scope.

    OK, it can be added to the list of things that make C harder to compile.

    Elsewhere the discussion ventured into module schemes and I complained
    about those that needed or allowed external functions to be individually imported, instead of just importing everything a module exports.

    C needs individual declarations to import a bunch of functions from
    elsewhere. But it goes further: each function in this module can define
    its own private subset of imported functions!

    Actually it goes further still: each nested block scope can also define
    its own subset. So there can be several such sets within any function,
    and each function can have its own collection of sets.

    To me, that is frankly crazy.

    So actually I'm glad I don't implement that. And maybe that pointless
    freedom can be dropped from future versions.


    That doesn't invalidate your reaction to Bart's statement, because
    he is being sloppy with language,

    But creating a tighter, more rigorous subset of C too, even if not intentionally.

    It comes down to whether you are implementing a tool that will
    mindlessly translate all existing C code (which I now know could take a lifetime), or one that will let you write or generate new, useful
    programs in a large subset of the language.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Wed Dec 4 17:43:00 2024
    On 04/12/2024 16:57, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 02/12/2024 18:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't
    think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    OK. I think the opposite. So who's right?

    The consensus so far does not favor your viewpoint.

    From the languages I know of in detail and I'm experienced in none
    is "fussy" about semicolons. Rather it's a simple and well designed
    syntactical token, whether used as separator or terminator. You've
    just to put it where it's defined.

    Indeed. One wonders at Bart's familiarity with formal grammars.

    Why?

    Because having a formal grammar is the keystone of a good
    language design.


    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    Parsers don't need such grammars. The information needed to construct
    one manually can be in the programmer's mind, it might be an informal description in English, it might be defined by examples of an existing languages.

    Or the parser was created for a trivial language and has evolved.

    A formal or informal grammar might be useful in a language reference -
    once the language is stable.

    A formal one will be needed if planning to use an automatic tool that
    will generate your parser, or maybe you want to check it for ambiguities
    etc. (Mine will likely fail that test, but I already know what they are.)

    So, I know what they are, I just don't think they're useful for the
    informal tools I write.

    Sometimes people make a big deal out of this stuff: a typical textbook
    on compilers may devote 100s of pages to the theory behind lexing,
    parsing, CFGs and so on.

    For the rest of us, that part is the simplest part of a compiler. You
    write it, and move on.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Wed Dec 4 18:43:06 2024
    Bart <bc@freeuk.com> writes:
    On 04/12/2024 16:57, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 02/12/2024 18:13, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 01.12.2024 17:42, Bart wrote:
    On 01/12/2024 15:08, Janis Papanagnou wrote:
    On 01.12.2024 12:52, Bart wrote:

    makes typing easier because it is case-insensitive,

    I don't think that case-insensitivity is a Good Thing. (I also don't >>>>> think it's a Bad Thing.)

    I think it's a _real bad thing_ in almost every context related
    to programming.

    OK. I think the opposite. So who's right?

    The consensus so far does not favor your viewpoint.

    From the languages I know of in detail and I'm experienced in none
    is "fussy" about semicolons. Rather it's a simple and well designed
    syntactical token, whether used as separator or terminator. You've
    just to put it where it's defined.

    Indeed. One wonders at Bart's familiarity with formal grammars.

    Why?

    Because having a formal grammar is the keystone of a good
    language design.


    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    I don't parse csv files, there are dozens of tools already
    available to perform that action for me with no need
    to reinvent the wheel.

    for example, cvstool comes with most linux distributions:

    https://github.com/maroofi/csvtool

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Wed Dec 4 20:23:26 2024
    On 04.12.2024 18:43, Bart wrote:
    [...]

    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    Is that the reason why there's so many versions around that are
    incompatible? CSV-parsing is not "trivial" if you look into the
    details; you have to specify these (at first glance not obvious
    details) to be sure that your "CSV-data" works not only with your
    "CSV-parser" but that there's a common understanding of the CSV-
    "language". (It's only few details; delimiters in string values,
    escapes, and such, but enough to initiate incompatible formats.)
    Yes, of course; if there would have been a formal specification
    in the first place we wouldn't have the mess we now actually have.

    And if you anyway write your tools only for yourself, and if you
    don't intend to exchange data with others, no one cares what you
    think a/the "CSV-format" actually is.

    But we weren't discussing such comparably simple structures; we
    have been discussing programming languages (and their grammars).
    And most of us are considering sensible languages, not privately
    hacked up toy languages or implementations of personal hobbies.


    Parsers don't need such grammars. The information needed to construct
    one manually can be in the programmer's mind,

    And since you cannot look into the "C" language programmer's mind
    you have issues understanding placement of braces vs. semicolons?
    (Don't you see how stupid that is as an argument.)

    Of course you can parse arbitrary data without grammar, and write
    the tool to do that. - Is it because you can write your parser in
    "0.3 seconds" where writing a specification requires "6.8 seconds"
    that you don't specify but just start hacking (and document later)?

    it might be an informal
    description in English, it might be defined by examples of an existing languages.

    Human languages (specifically English with its many irregularities)
    are worse than a formal language and a unreliable base and unsuited
    as programming languages.

    That's nothing more then a hacker's feeble excuse to justify his
    ignorance.


    Or the parser was created for a trivial language and has evolved.

    Like, as I've heard, the Unix shell, with all it's irregularities
    and quirks? - You really think this is a good paragon?

    Even if some hacker defines a language ad hoc - and Intercal comes
    to my mind - for a serious programming language you should have
    [documented] syntax and semantics, and why the hell would anyone
    use English instead of a formal specification for syntax.


    A formal or informal grammar might be useful in a language reference -
    once the language is stable.

    For a hacker like you maybe. Professionals typically specify before implementation.

    [...]

    For the rest of us, that part is the simplest part of a compiler. You
    write it, and move on.

    Is that the reason why your languages and compilers are so widespread
    used? </sarcasm>

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to BGB on Wed Dec 4 20:33:41 2024
    On 04.12.2024 20:21, BGB wrote:
    On 12/4/2024 10:49 AM, Scott Lurndal wrote:

    How can you write a correct recursive descent parser without a
    formal grammar (at least on paper) for the language being parsed?

    It is usually a thing of pattern matching the next N tokens, based on
    the structure of the language.

    You can write or reference a syntax in BNF or EBNF or similar, but it is
    not necessary, and some languages (like C) may contain things that can't
    be fully expressed via an BNF (say, for example, things that depend on
    prior typedefs, etc).

    Knowledge of the theory of formal languages would give you answers
    concerning what a Context Free Grammar can do and what not, for what
    parts you need, say, attributed grammars, contexts, and so on. - So
    that's not really an argument against formal grammars if we discuss
    syntax.

    (Algol 68 of course went a step further with van Wijngaarden Grammar.
    Just to mention another sort and a further step of advanced grammar
    concepts.)

    Janis

    [snip rest; tldr]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Wed Dec 4 20:47:51 2024
    On 04.12.2024 13:08, David Brown wrote:
    On 03/12/2024 17:12, Janis Papanagnou wrote:
    On 03.12.2024 16:24, David Brown wrote:
    On 03/12/2024 13:34, Bart wrote:
    [...]

    Of course lots of C programmers have never read the standards. But they >>> generally know that they don't know these details, and don't try to
    pretend that the language details that they don't know are confusing.
    They simply get on with the job of writing clear C code as best they
    can.

    I feel an urge to point out that the C standard is not necessary to
    understand concepts that can be read about in textbooks or inferred
    (or just tried out, if the available sources are unclear about some
    detail).

    Sure. And it is certainly /possible/ to know all the small details of C without ever reading the standards. But it's quite unlikely.

    The question is (IMO) not so much to know "all" and even "all small"
    details. Even in a language like "C" (that I'd consider to be fairly
    incoherent if compared to other languages' design) you can get all
    "important" language properties (including details) from textbooks.

    If cases where that is different, the standards documents - which
    have their very own special way of being written - would be even
    less comprehensibly as they (inherently) already are. - That said
    from a programmer's POV (not from the language implementors').

    I look into language standards only if I want to confirm/falsify
    an implementation; in this case I'm taking the role of a language
    implementor (not a programmer). Personally I do that anyway only
    rarely, for specific languages only, and just out of academical
    interest.

    [...]
    Bart is an expert at thinking up things in C that confuse him.

    Well, that's an own topic. - Where I was really astonished was the
    statement of being confused about the braces/semicolons, which is
    so fundamental (and primitive) but technically just a detail that
    I'd thought it should be clear - i.e. without reading a language
    standard. - But I don't want to blame him (or anyone) on that.
    Ignorance is the human standard case, knowledge the exception.
    That's why we exchange or knowledges, assumptions, and opinions.

    In the
    real world, programmers simply don't do that kind of thing - and the
    kind of C programmer who is interested in these details will almost
    certainly also be interested in reading the standards.

    Again I feel an urge to point out that there are people interested
    in such things and details (academically) and don't need standards.


    Most C programmers never look at the standards - textbooks, decent
    reference sites (like www.cppreference.com), common sense, and trial and error with quality compilers is sufficient for most programmers.

    Experiences from other languages help as well to understand things.


    There's nothing at all wrong with not knowing [...]

    Yes. Ignorance is the human standard case, knowledge the exception.

    ("ipse se nihil scire id unum sciat", sort of.)

    The second is trying to pass the buck - blame your
    tools, blame other people, blame anyone but yourself. [...]

    ...or build your own tools - LOL. :-)

    Yes, that's a bit annoying. And a waste of time.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Scott Lurndal on Wed Dec 4 21:57:49 2024
    On 04/12/2024 17:55, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    -----------------------------------------------------------------------
    Language             files          blank        comment           code
    -----------------------------------------------------------------------
    C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    -----------------------------------------------------------------------
    SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------ >>>

    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on my
    machine), I set up a comparable test. I took an 800-line C program, and
    duplicated it in 200 separate files f1.c to f200.c, for a total line
    count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    Here's a typical build for my project:

    $ make -s -j 64
    ...

    COMPILE apc2.cpp
    COMPILE bcp2.cpp
    BUILD /scratch/lib/libdevice_yyy.so
    XXXX_BUILT
    BUILDSO /scratch/libxxxx.so.1.0
    BUILD TARGET /scratch/bin/xxxx
    COMPILE shim.cpp

    real 13m48.24s
    user 1h2m9.78s
    sys 0m56.73s

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Wed Dec 4 20:47:48 2024
    On 04/12/2024 19:23, Janis Papanagnou wrote:
    On 04.12.2024 18:43, Bart wrote:
    [...]

    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    Is that the reason why there's so many versions around that are
    incompatible? CSV-parsing is not "trivial" if you look into the
    details; you have to specify these (at first glance not obvious
    details) to be sure that your "CSV-data" works not only with your "CSV-parser" but that there's a common understanding of the CSV-
    "language". (It's only few details; delimiters in string values,
    escapes, and such, but enough to initiate incompatible formats.)
    Yes, of course; if there would have been a formal specification
    in the first place we wouldn't have the mess we now actually have.

    And if you anyway write your tools only for yourself, and if you
    don't intend to exchange data with others, no one cares what you
    think a/the "CSV-format" actually is.

    But we weren't discussing such comparably simple structures; we
    have been discussing programming languages (and their grammars).
    And most of us are considering sensible languages, not privately
    hacked up toy languages or implementations of personal hobbies.

    You really hate toy languages don't you?

    The fact is that a compiler is only a bit of software like anything
    else. It might take some input, process it, and produce output.

    When someone has claimed to write some program, do you always demand
    they produce a 'formal grammar' for it?

    What is the complexity threshold anyway for something to need such a
    formal specification?

    What input would even be classed as a language: are binary file formats languages? What about the commands of a CLI?

    More importantly, why are some people here so supercilious,
    condescending and patronising?

    I don't create formal grammars for everything for the same reasons I
    don't file a flight plan every time I drive to the supermarket.

    I'm starting to suspect that the few details that have emerged of my
    languages' module scheme have shown it is actually quite decent. So
    let's find something else to belittle Bart with!

    Human languages (specifically English with its many irregularities)
    are worse than a formal language and a unreliable base and unsuited
    as programming languages.

    PE file is described in English. Most file binary file formats are.

    That's nothing more then a hacker's feeble excuse to justify his
    ignorance.

    So you're calling me a hacker, and you're calling me ignorant.

    Nice.



    Or the parser was created for a trivial language and has evolved.

    Like, as I've heard, the Unix shell, with all it's irregularities
    and quirks? - You really think this is a good paragon?

    Even if some hacker defines a language ad hoc - and Intercal comes
    to my mind - for a serious programming language you should have
    [documented] syntax and semantics, and why the hell would anyone
    use English instead of a formal specification for syntax.

    When YOU devise a language, then YOU can choose to do it whichever way
    YOU like. I wouldn't care one way or another.

    My own products were in-house tools to get stuff done. And they worked spectacularly well.

    A formal or informal grammar might be useful in a language reference -
    once the language is stable.

    For a hacker like you maybe. Professionals typically specify before implementation.

    Again. I bet the first C compiler didn't bother with a grammar!

    What is it with people here?

    OK, you're a professional; I'm an amateur (an amateur who managed to
    retire at 42). I will give you that. Satisfied?


    [...]

    For the rest of us, that part is the simplest part of a compiler. You
    write it, and move on.

    Is that the reason why your languages and compilers are so widespread
    used? </sarcasm>

    By contrast, the languages that you've devised are in common use of course?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Wed Dec 4 21:01:07 2024
    On 04/12/2024 19:47, Janis Papanagnou wrote:
    On 04.12.2024 13:08, David Brown wrote:

    Sure. And it is certainly /possible/ to know all the small details of C
    without ever reading the standards. But it's quite unlikely.

    The question is (IMO) not so much to know "all" and even "all small"
    details. Even in a language like "C" (that I'd consider to be fairly incoherent if compared to other languages' design) you can get all "important" language properties (including details) from textbooks.

    If cases where that is different, the standards documents - which
    have their very own special way of being written - would be even
    less comprehensibly as they (inherently) already are. - That said
    from a programmer's POV (not from the language implementors').

    I look into language standards only if I want to confirm/falsify
    an implementation; in this case I'm taking the role of a language
    implementor (not a programmer). Personally I do that anyway only
    rarely, for specific languages only, and just out of academical
    interest.

    [...]
    Bart is an expert at thinking up things in C that confuse him.

    Well, that's an own topic. - Where I was really astonished was the
    statement of being confused about the braces/semicolons, which is
    so fundamental (and primitive) but technically just a detail that
    I'd thought it should be clear


    OK, if it's so simple, explain it to me.

    Apparently the first line here needs a semicolon after }, the second
    doesn't:

    int X[1] = {0};
    void Y() {}

    Similarly here:

    if (x) y;
    if (x) {}

    Why?

    "Because that's what the grammar says" isn't a valid answer.

    The C language is one of the most quirky ones around full of apparently ridiculous things. Why shouldn't you be able to write this for example:

    {
    ....
    L:
    }

    This stupid rule means that EVERY label in my generated code needs to be written as L:; instead of just L:

    Please don't say the label is only defined to be a prefix to another
    statement. I asking why it was done like that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Wed Dec 4 21:55:37 2024
    On 04/12/2024 16:09, Bart wrote:
    On 04/12/2024 09:02, David Brown wrote:
    On 03/12/2024 19:42, Bart wrote:

    It really /does/ matter - regardless of what the language allows or
    does not allow.

    Why?

    code the reading is important order people to.

    Or, if you prefer,

    Order is important to people reading the code.



    The compiler spends milliseconds reading the code.  Programmers spend
    hours, days, or more reading the code.  It's not particularly
    important if the language requires a particular order or not, except
    in how it helps or hinders the programmer in their order of the code.

    You've lost me.

    A language source file isn't a story that needs to be consumed
    sequentially. It will be a collection of functions that will have some arbitrary call-pattern at runtime, perhaps different each time.


    Nobody said the file has to be read by people sequentially - though it
    is usually a good idea if it makes sense that way. (How else would you
    expect a new maintainer of the code to read it?) I simply said it has
    to be ordered with due care and attention - a code file should not just
    be a random pile of functions and data.

    So the static ordering is irrelevant.

    Yes, apparently I /have/ lost you.


    I've already made it clear what I think is wrong about your solution -
    the jumbling of namespaces.  (And /please/ don't harp on about C's
    system again - the fact that C does not have a good way of handling
    namespaces does not suddenly make /your/ version good.)

    All it does is allow you to write F() instead of A.F(). You can do
    the same thing in C++ (there it saves you writing A::), by doing this
    (AIUI):

       using A;

    (You mean "using namespace A;".  It's no problem that you don't know
    the right syntax for C++, but I'm correcting it in case you want to
    try anything on godbolt.org.)

    Yes, C++ /allows/ you to do that - if you explicitly choose to do so
    for a particular namespace.  Thus if you are going to use identifiers
    from a namespace often, and you are confident it will not lead to
    conflicts, then you can do so.  C++ "using namespace A;" is commonly
    used in a few circumstances:

    It's used to avoid cluttering code with ugly xxx:: qualifiers, and save
    some typing at the same time. That's pretty much it.

    Buy a better keyboard. Saving typing is a pathetic excuse.

    There's nothing wrong with having an /optional/ way to make shortcuts in
    the code syntax to make it easier to read - that can definitely be a
    good thing. Overly long identifiers do not help readability. But it
    should be opt-in - like in C++ namespaces - not jumble everything by
    default. (For the same reason, C functions should have been "static" by default and required explicit "extern" indicators.)


    To that end, C++ and my language achieve the same thing.

    No, you got it backwards - apparently because laziness trumps code
    structure and scalability in your book.

    I just decided
    to make 'using namespace xxx' the default, and haven't got around to
    making it optional. (In an early version, I did need such a directive.)

    (However it most likely differs from C++ in what it calls 'namespaces'.

    My remarks have been about the namespace that is created by a module.

    I understand that C++ namespaces can be created in other ways, like
    classes.

    In reference to C++, I have been using the term "namespaces" the way C++ specifically defines the term "namespace". Perhaps I should have given
    a reference to that in some way - this is comp.lang.c, after all.

    What you are now talking about is what C calls "name spaces" - with a
    space. C++ does not use that term in its standards (at least, not in
    the C++20 standards I have open here) - it does not have a clear name
    for the concept, as far as I have found. (I am not nearly as familiar
    with the C++ standards as I am with the C standards, so if this matters
    then perhaps someone else can chime in.)

    I sort of have that too, but rarely use the feature:

     record foo =
         proc F = println "FOO/F" end
     end

     record bar =
         proc F = println "BAR/F" end
     end

     proc F = println "MAIN/F" end

     proc main =
         foo.F()
         bar.F()
         F()
     end

    Here, I don't need to create instances of foo and bar; they serve to encapsulate any kinds of named entities.)


    That seems to be something akin to C++ classes or structs with static
    methods. But I'm not sure, and certainly not sure how it is relevant.


    This crashes. This program is impossible to write in my language when
    both modules are part of the program.

    I'm sorry, I thought you meant if a sane C programmer wrote good code
    but accidentally had conflicting types.  C is not as tolerant of
    idiots as some languages.

    So it's a lot more fool-proof.

    If you are a fool, you should probably avoid programming entirely.

    Fuck you.

    Did I call you a fool, or otherwise insult you? No, I said that fools
    should not be programming, and programming languages and tools should
    not be designed to cater for fools. A language or compiler should do
    its best to help spot mistakes in code, because every programmer makes
    mistakes sometimes - but it doesn't have to bother about people writing
    clearly and intentionally bad code.

    Obviously you're going to shoot down whatever I say, trash
    whatever I have achieved, because .... I've really no idea.


    I have been trying to stick to facts and justified opinions. As always,
    I think some things in your languages are good, other things are bad.
    Some are simply disappointing - you had the opportunity to make
    something better with no regard for backwards compatibility or existing
    code, yet you choose not to. Instead, you emphasised laziness and lack
    of structure. Okay, it's your language and your choice, and you are the
    only one that might suffer from it. Perhaps you simply don't care what
    anyone else might think or how future maintainers might view the code,
    because you know no one else will ever use it.

    Yesterday you tried to give the misleading impression that compiling a substantial 200Kloc project only took 1-3 seconds with gcc.


    No, I did not. I said my builds of that project typically take 1-3
    seconds. I believe I was quite clear on the matter.

    If I do a full, clean re-compile of the code, it takes about 12 seconds
    or so. But only a fool would do that for their normal builds. Are you
    such a fool? I haven't suggested you are - it's up to you to say if
    that's how you normally build projects.

    If I do a full, clean re-compile /sequentially/, rather than with
    parallel jobs, it would be perhaps 160 seconds. But only a fool would
    do that.

    I gave some timings that showed gcc-O0 taking 50 times longer than tcc,
    and 150 times longer with -O2.

    That is the real picture. Maybe your machine is faster than mine, but I
    doubt it is 100 times faster. (If you don't like my benchmark, then
    provide another in portable C.)

    All this just so you can crap all over the benefits of small, faster,
    simpler tools.

    Your small, fast, simple tools are - as I have said countless times -
    utterly useless to me. Perhaps you find them useful, but I have never
    known any other C programmer who would choose such tools for anything
    but very niche use-cases.

    The real picture is that real developers can use real tools in ways that
    they find convenient. If you can't do that, it's your fault. (I don't
    even believe it is true that you can't do it - you actively /choose/ not
    to.)

    And since compile speed is a non-issue for C compilers under most circumstances, compiler size is /definitely/ a non-issue, and
    "simplicity" in this case is just another word for "lacking useful
    features", there are no benefits to your tools.

    If you feel these tools are useful to you, fine - use them. Don't
    expect anyone else to think they are a good idea.


    I'm pretty sure tcc won't compile your projects, because your projects
    will be 100% dependent on the special features, extensions, and options
    of your prefered tools. So that is hardly surprising.


    Of course tcc won't work - I work with embedded systems, and as I have
    said countless times, your little tools don't target the devices I use.
    I /need/ good optimisations - it's not an option, it's a requirement to
    get fast enough code for the end system to work. So your toys would not
    be usable even if they supported the right target. I use C++ as well as
    C - your toys don't support that. I use C17 (and will move to C23 when
    my tools support it) - tcc supports only up to partial C99 support, and
    $DEITY only knows what partial C standard your compiler handles. I use
    some extensions - I know tcc supports some gcc extensions, but it's
    unlikely to handle everything I use. And I need additional features and
    tools beyond the compiler, such as specific linker scripts and setups.

    But that's not a reason to dismiss it for everyone else.


    Other people make their own choices - I don't decide for them. They
    will have their own reasons for dismissing tcc.

    Languages and tools should try to be accident-proof, not fool-proof.

    And yet my product IS fool-proof. So again, fuck you.


    It's nice to see you have a clear, reasoned argument for your case.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Wed Dec 4 21:31:05 2024
    On 04/12/2024 20:55, David Brown wrote:
    On 04/12/2024 16:09, Bart wrote:

    It's used to avoid cluttering code with ugly xxx:: qualifiers, and
    save some typing at the same time. That's pretty much it.

    Buy a better keyboard.  Saving typing is a pathetic excuse.

    How does a better keyboard make this less cluttery:

    std::cout << xxx::X << yyy::Y << std::endl

    Compare with:

    cout << X << Y endl



    That seems to be something akin to C++ classes or structs with static methods.  But I'm not sure, and certainly not sure how it is relevant.

    You said my namespaces were jumbled. They generally work as people
    expect, other than some different rules on name resolution.

    Compare for example how filenames are resolved in a file system, when
    both absolute and relative paths are missing. Sometimes it will look in
    a list of special places (eg. using Windows' PATH variable) if not found locally.

    You don't agree with my choices, OK.

    Of course tcc won't work - I work with embedded systems, and as I have
    said countless times, your little tools don't target the devices I use.

    In my hardware days I built boards with embedded processors too.

    I programmed them with my 'toy' language. Sometimes I didn't have have a compiler, so a couple of times I wrote an assembler for the device. The assembler (obviously, you will consider that a toy) was written in my
    toy language. (One was for 80188, the other was 8035 or 8051.)

    My point is that 'toy' implementations /could/ work just as well, and
    here I was able to get working prototypes. (At least, until my boss had
    some new ideas and I moved on to something else.)


    I /need/ good optimisations - it's not an option, it's a requirement to
    get fast enough code for the end system to work.  So your toys would not
    be usable even if they supported the right target.

    And I did without an optimising compiler for 20 years. Not that C
    compilers were that much better for a lot of that period, of 82-02.

      I use C++ as well as
    C - your toys don't support that.  I use C17 (and will move to C23 when
    my tools support it) - tcc supports only up to partial C99 support, and $DEITY only knows what partial C standard your compiler handles.

    My C compiler is for my personal use. It will build only a tiny fraction
    of existing code, but will compile 100% of the code I write, or generate.

    So I'm not asking people to use it. But it shows what is possible.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Wed Dec 4 22:31:36 2024
    Bart <bc@freeuk.com> writes:
    On 04/12/2024 19:23, Janis Papanagnou wrote:
    On 04.12.2024 18:43, Bart wrote:
    [...]

    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    Is that the reason why there's so many versions around that are
    incompatible? CSV-parsing is not "trivial" if you look into the
    details; you have to specify these (at first glance not obvious
    details) to be sure that your "CSV-data" works not only with your
    "CSV-parser" but that there's a common understanding of the CSV-
    "language". (It's only few details; delimiters in string values,
    escapes, and such, but enough to initiate incompatible formats.)
    Yes, of course; if there would have been a formal specification
    in the first place we wouldn't have the mess we now actually have.

    And if you anyway write your tools only for yourself, and if you
    don't intend to exchange data with others, no one cares what you
    think a/the "CSV-format" actually is.

    But we weren't discussing such comparably simple structures; we
    have been discussing programming languages (and their grammars).
    And most of us are considering sensible languages, not privately
    hacked up toy languages or implementations of personal hobbies.

    You really hate toy languages don't you?

    Nobody has made that claim other than yourself.

    I don't feel that your 'toy' languages are interesting
    in the context of comp.lang.c.


    The fact is that a compiler is only a bit of software like anything
    else. It might take some input, process it, and produce output.

    When someone has claimed to write some program, do you always demand
    they produce a 'formal grammar' for it?

    Now you're being ridiculous. Intentionally, no doubt, to induce
    a response.


    What is the complexity threshold anyway for something to need such a
    formal specification?

    Most real-world working applications start with a formal specification.
    As do most other real-world projects whether it is a payroll application
    or a massive construction project like Vogtle Unit #3.

    snip rant

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Bart on Thu Dec 5 00:41:12 2024
    On Wed, 4 Dec 2024 21:01:07 +0000
    Bart <bc@freeuk.com> wrote:


    The C language is one of the most quirky ones around full of
    apparently ridiculous things. Why shouldn't you be able to write this
    for example:

    {
    ....
    L:
    }

    This stupid rule means that EVERY label in my generated code needs to
    be written as L:; instead of just L:

    Please don't say the label is only defined to be a prefix to another statement. I asking why it was done like that.



    No good reasons. It was a mistake of Committee 35 years ago.
    I don't know why it was not fixed in 3 subsequent iteration.
    Finally fixed in the latest edition.
    Still, this mistake less bad than ; as a separator in Pascal.
    And even the latter is minor.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to David Brown on Wed Dec 4 22:48:20 2024
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 17:55, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    ----------------------------------------------------------------------- >>>> Language             files          blank        comment           code
    ----------------------------------------------------------------------- >>>> C++                     39           2217           1020          11820
    C/C++ Header            44           1078            798           2696
    C                        3            259            237           1152
    ----------------------------------------------------------------------- >>>> SUM:                    86           3554           2055          15668
    ------------------------------------------------------------------------ >>>>

    Not that it really matters, but a typical build for my project takes
    about 1 to 3 seconds.

    I don't really know what they means, because I don't know is involved,
    and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on my
    machine), I set up a comparable test. I took an 800-line C program, and
    duplicated it in 200 separate files f1.c to f200.c, for a total line
    count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it can't
    link due to Win32 imports).

    Tiny C took 0.64 seconds.

    Here's a typical build for my project:

    $ make -s -j 64
    ...

    COMPILE apc2.cpp
    COMPILE bcp2.cpp
    BUILD /scratch/lib/libdevice_yyy.so
    XXXX_BUILT
    BUILDSO /scratch/libxxxx.so.1.0
    BUILD TARGET /scratch/bin/xxxx
    COMPILE shim.cpp

    real 13m48.24s
    user 1h2m9.78s
    sys 0m56.73s

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?


    That was a build that touched a key header file, so maybe
    85% full. A full build adds a minute or two wall time.

    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Wed Dec 4 22:59:02 2024
    Bart <bc@freeuk.com> writes:
    On 04/12/2024 19:47, Janis Papanagnou wrote:
    On 04.12.2024 13:08, David Brown wrote:

    Sure. And it is certainly /possible/ to know all the small details of C >>> without ever reading the standards. But it's quite unlikely.

    The question is (IMO) not so much to know "all" and even "all small"
    details. Even in a language like "C" (that I'd consider to be fairly
    incoherent if compared to other languages' design) you can get all
    "important" language properties (including details) from textbooks.

    If cases where that is different, the standards documents - which
    have their very own special way of being written - would be even
    less comprehensibly as they (inherently) already are. - That said
    from a programmer's POV (not from the language implementors').

    I look into language standards only if I want to confirm/falsify
    an implementation; in this case I'm taking the role of a language
    implementor (not a programmer). Personally I do that anyway only
    rarely, for specific languages only, and just out of academical
    interest.

    [...]
    Bart is an expert at thinking up things in C that confuse him.

    Well, that's an own topic. - Where I was really astonished was the
    statement of being confused about the braces/semicolons, which is
    so fundamental (and primitive) but technically just a detail that
    I'd thought it should be clear


    OK, if it's so simple, explain it to me.

    Apparently the first line here needs a semicolon after }, the second
    doesn't:

    int X[1] = {0};
    void Y() {}

    Similarly here:

    if (x) y;
    if (x) {}

    Why?

    "Because that's what the grammar says" isn't a valid answer.

    The C language is one of the most quirky ones around full of apparently >ridiculous things. Why shouldn't you be able to write this for example:

    {
    ....
    L:
    }

    This stupid rule means that EVERY label in my generated code needs to be >written as L:; instead of just L:

    The formal grammar requires that a label prefix a statement. The
    closing brace isn't a statement.


    Please don't say the label is only defined to be a prefix to another >statement.

    Too late.

    I asking why it was done like that.

    Ask Dennis, if you can find a real medium. One might suppose that
    it makes the grammar less complex. Recall it was the same group
    of people who built lex and yacc.

    case NAME:
    if (nextchar()==':') {
    peekc = 0;
    o1 = csym;
    if (o1->hclass>0) {
    if (o1->hblklev==0) {
    pushdecl(o1);
    o1->hoffset = 0;
    } else {
    defsym = o1;
    redec();
    goto stmt;
    }
    }
    o1->hclass = STATIC;
    o1->htype = ARRAY;
    o1->hflag =| FLABL;
    if (o1->hoffset==0)
    o1->hoffset = isn++;
    label(o1->hoffset);
    goto stmt;
    }

    This is from the V6 C compiler first pass (c02.c). After processing
    the label, the parser expects to find a statement.

    https://github.com/huangguiyang/UnixV6-CC/blob/master/c/c02.c

    Subsequent compilers maintained this semantic and it was eventually
    codified by ANSI.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Wed Dec 4 23:30:35 2024
    Bart <bc@freeuk.com> writes:
    On 04/12/2024 22:31, Scott Lurndal wrote:

    /My/ real-world apps started with a general idea and then evolved.

    I mean, what would be the formal specification for AutoCAD? (The nearest >product to mine at the time.)

    You would have to ask AutoDesk, not random readers on comp.lang.c.

    I have no doubt that they had a formal specification for the first
    version of their CAD tool. It was certainly required at Burroughs
    for all internal software and anything that might get shipped to
    a customer. I still have copies of many of those specifications.

    We first did a Conceptual design document which laid out the high-level
    goals and overall design framework, language choices, etc.

    Then a functional specification was developed. That was followed by
    a detailed design document that covered the major data structures and
    any unusual algorithms.

    Finally code was produced, tested and shipped.

    Subsequent employers have used similar formal design processes
    (e.g. SGI, an unnamed internet security company, a couple of
    startups and two fabless semi's).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Keith Thompson on Wed Dec 4 23:34:03 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    Bart <bc@freeuk.com> writes:
    [...]
    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    I wouldn't call CSV trivial, and yes, I'd want to have a precise >specification of the format in front of me if I wanted to implement
    it. RFC 4180 seems to be the closest thing we have to a standard,
    but it's not universally followed.

    I don't parse csv files, there are dozens of tools already
    available to perform that action for me with no need
    to reinvent the wheel.

    for example, cvstool comes with most linux distributions:

    https://github.com/maroofi/csvtool

    The csvtool that's available for most Linux distributions isn't
    that one. It's another tool of the same name, implemented in OCaml,
    with a completely different user interface. I don't know whether
    they implement the same CSV specification.

    https://github.com/Chris00/ocaml-csv

    Yes, I messed up the google search. Ubuntu/Debian
    install:

    Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: csv
    Upstream-Contact: Christophe Troestler <Christophe.Troestler@umons.ac.be> Source: https://forge.ocamlcore.org/projects/csv/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Wed Dec 4 23:21:27 2024
    On 04/12/2024 22:31, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 04/12/2024 19:23, Janis Papanagnou wrote:
    On 04.12.2024 18:43, Bart wrote:
    [...]

    Do you use a formal grammar when parsing a CSV file, or something
    equally trivial?

    Is that the reason why there's so many versions around that are
    incompatible? CSV-parsing is not "trivial" if you look into the
    details; you have to specify these (at first glance not obvious
    details) to be sure that your "CSV-data" works not only with your
    "CSV-parser" but that there's a common understanding of the CSV-
    "language". (It's only few details; delimiters in string values,
    escapes, and such, but enough to initiate incompatible formats.)
    Yes, of course; if there would have been a formal specification
    in the first place we wouldn't have the mess we now actually have.

    And if you anyway write your tools only for yourself, and if you
    don't intend to exchange data with others, no one cares what you
    think a/the "CSV-format" actually is.

    But we weren't discussing such comparably simple structures; we
    have been discussing programming languages (and their grammars).
    And most of us are considering sensible languages, not privately
    hacked up toy languages or implementations of personal hobbies.

    You really hate toy languages don't you?

    Nobody has made that claim other than yourself.

    I don't feel that your 'toy' languages are interesting
    in the context of comp.lang.c.

    My systems language is actually one of the closest to C in its type
    system, language level, and the sorts of things it can do.

    /How/ it does them regarding syntax and some modern features is rather different.

    So I think it is interesting as an alternate take on what such a
    language could look like.





    The fact is that a compiler is only a bit of software like anything
    else. It might take some input, process it, and produce output.

    When someone has claimed to write some program, do you always demand
    they produce a 'formal grammar' for it?

    Now you're being ridiculous.

    No, JP was. But of course you wouldn't be rude to him or make belittling remarks.


    Intentionally, no doubt, to induce
    a response.

    Wow. All this Bart-baiting ('fool', 'ignorant', 'hacker', 'feeble',
    'idiot', mentioning 'Professional' with a clear insinuation that I
    wasn't, 'toy' this and 'toy' that), isn't exactly that?

    You lot are attacking on multiple fronts, I'm just defending.



    What is the complexity threshold anyway for something to need such a
    formal specification?

    Most real-world working applications start with a formal specification.

    And you know that for a fact?

    /My/ real-world apps started with a general idea and then evolved.

    I mean, what would be the formal specification for AutoCAD? (The nearest product to mine at the time.)

    As do most other real-world projects whether it is a payroll application

    I've done a payroll app. It was a custom job and the rough specs were
    provided by my client. There was never a formal paper spec. It was part
    of a larger app and ran a $1m a year business for over 20 years.

    or a massive construction project like Vogtle Unit #3.

    snip rant

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Wed Dec 4 23:57:25 2024
    On 04/12/2024 22:58, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    OK, if it's so simple, explain it to me.

    I'll pretend that was a sincere question.

    Let's put it this way: if somebody asked me what the rule was, I
    wouldn't be able to tell them.

    You seem to be under the impression that a closing brace should
    either always or never be followed by a semicolon. I don't know
    where you got that idea.

    Braces ("{", "}") are used in different contexts with different
    meanings. They're generally used for some kind of grouping (of
    statements, declarations, initializers), but the distinct uses are
    distinct, and there's no particular reason for them to follow the
    same rules.

    Apparently the first line here needs a semicolon after }, the second
    doesn't:

    int X[1] = {0};
    void Y() {}

    Yes. The first is a declaration, and a declaration requires a
    semicolon. I suppose the language could have a special-case rule
    that if a declaration happens to end with a "}", the semicolon is
    not required, but that would be silly.

    The second is a function definition (and can only appear at file
    scope). Function definitions do not require or allow a semicolon
    after the closing "}". Why should they?

    Consistency? I posted a bit of Algol68 the other day; each function
    definition needed a semicolon, to separate it from the next.

    Similarly here:

    if (x) y;
    if (x) {}

    Why?

    "Because that's what the grammar says" isn't a valid answer.

    Because that's what the grammar says.

    Not all statements require a closing semicolon. In particular,
    compound statements do not, likely because the closing
    "}" unambiguously marks the end of the statement. Sure, the
    language could have been specified to require a semicolon, but why?

    Consistency again? But then you'd get this: if () {}; else {};. It would
    be incompatible with how it works now.

    So overall it's just messy. It works for BEGIN/END when semicolon is a separator, rather than a terminator. So you write END ELSE not END; ELSE.

    But because C uses ";" as a terminator, it's made a rod for its own back.

    (I'll note that languages that use "begin"/"end" rather than "{"/"}"
    often require a semicolon after the "end".)

    That's my A68 example.

    And you can add a semicolon after a compound statement if you like
    (it's a null statement),

    But not here I guess: if () {}; else ...

    Of course you know all this.

    I'm aware of how messy and conistent it is. I've said that languages
    that use ";" as a separator probably fair better, but are still not
    ideal because the last statement of a block is now an annoying special case.

    So it's an interesting language design problem.

    My own made a compromise here: use ";" as separator, but introduce some
    rules so that explicit ";" is rarely need. I think that wins.

    Meanwhile, if I compile this:

    void F(){}; void G(){};

    My compilers report a syntax error. But gcc passes it by default. So I
    take what the grammar says more seriously than gcc!

    IS ";" between function definitions legal or not? If not, then fail the program.

    Please don't say the label is only defined to be a prefix to another
    statement. I asking why it was done like that.

    The label is only defined to be a prefix to another statement.
    It was simple to define it that way, and not particularly
    inconvenient to add a semicolon if you happen to want a label at
    the end of a block. I'd be surprised if this rule has ever actually
    caused you any inconvenience.

    I said that my generated code has to use ":;" after each label; it looks
    weird.

    But you'll be delighted to know that C23 changed the grammar for a
    compound statement, so a label can appear before any of a statement,
    a declaration, or the closing "}". So now you have exactly what you
    want. (Just kidding; you'll still find a way to be angry about it.)

    No, that's amazing. Presumably, some people must complained about it
    (maybe it actually caused some inconvenience!), and it eventually got fixed.

    Of course, if it was just me, then it would be pointless ranting. 'How
    hard is to add the semicolon?'

    Well, 'How hard is it to delete the semicolon' from my above example?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Thu Dec 5 00:10:38 2024
    On 04/12/2024 23:09, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    My language is intended for whole program compilation. There are no
    interfaces between modules (that is, a file listing the exports of a
    module, separately from the implementation).

    Since you keep telling us about your language,

    Someone raised a point about it, and I replied.


    I have a few questions:

    What is it called? (I'm assuming it has a name.)

    Is there an implementation that others can use?

    Is there a specification?

    There were specs, docs, binaries in the past, even versions that could
    be built from a C rendering of the source code.

    I no longer do that. The support is just too much. My health is not
    great, and I can guarantee nothing.

    Besides few people are interested in this kind of low-level language;
    they're mostly into modern alternatives.

    The people who like C, will find it too different (and most work on
    Linux). Plus they expect tooling, community, libraries etc.

    If you're actually interested in what it looks like, I can give some
    links but they're out of date (it's constantly being tweaked).


    Would you consider supporting the creation of a new alt.comp.lang.<name> newsgroup where people who are actually interested in it can discuss it?


    No. It would be an empty wasteland.

    Somebody did try to put it on Rosetta Code, under the name Mosaic. I
    call it just 'M'.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Janis Papanagnou on Wed Dec 4 17:29:46 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 03.12.2024 16:24, David Brown wrote:

    On 03/12/2024 13:34, Bart wrote:

    [...]

    Of course lots of C programmers have never read the standards.
    But they generally know that they don't know these details, and
    don't try to pretend that the language details that they don't
    know are confusing. They simply get on with the job of writing
    clear C code as best they can.

    I feel an urge to point out that the C standard is not necessary
    to understand concepts that can be read about in textbooks

    That assumes that such textbooks exist, that they can be identified,
    located, and obtained without too much difficulty, and don't cost too
    much to get. The C standard is easily located and obtained, and
    costs nothing to download (for a draft that is virtually identical
    to the actual standard).

    or inferred (or just tried out, if the available sources are
    unclear about some detail).

    Two problems with that suggestion. One, trying to figure out what
    the rules are by experimentation is sometimes difficult and
    unreliable. Two, some details, such as what constructs result in
    undefined behavior, simply cannot be determined by means of
    experimentation.

    Also, the idea that one can figure out the rules of the C language
    by looking at compiler sources is just laughable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to David Brown on Thu Dec 5 03:11:23 2024
    David Brown <david.brown@hesbynett.no> wrote:
    On 04/12/2024 16:09, Bart wrote:
    On 04/12/2024 09:02, David Brown wrote:
    On 03/12/2024 19:42, Bart wrote:

    Yesterday you tried to give the misleading impression that compiling a
    substantial 200Kloc project only took 1-3 seconds with gcc.


    No, I did not. I said my builds of that project typically take 1-3
    seconds. I believe I was quite clear on the matter.

    Without word "make" it was not clear if you mean full build (say
    after checkout from repository). Frequently people talk about re-making
    when they mean running make after a small edit and reserve build
    for full build. So it was not clear if you claim to have a compile
    farm with few hundred cores (so you can compile all files in parallel).

    If I do a full, clean re-compile of the code, it takes about 12 seconds
    or so. But only a fool would do that for their normal builds. Are you
    such a fool? I haven't suggested you are - it's up to you to say if
    that's how you normally build projects.

    If I do a full, clean re-compile /sequentially/, rather than with
    parallel jobs, it would be perhaps 160 seconds. But only a fool would
    do that.

    Well, when I download a project from internt the first (ant frequently
    the only compilation is a full build). And if build fails, IME
    to is much harder to find problem from log of parallel build.
    So I frequently run full builds sequentially. Of course, I find
    something to do when computer is busy (300sec of computer time
    spent on full build is not worth extra 30 seconds to find trouble
    in parallel log (and for bigger things _both_ times grow so
    conclusion is the same)).

    I gave some timings that showed gcc-O0 taking 50 times longer than tcc,
    and 150 times longer with -O2.

    That is the real picture. Maybe your machine is faster than mine, but I
    doubt it is 100 times faster. (If you don't like my benchmark, then
    provide another in portable C.)

    All this just so you can crap all over the benefits of small, faster,
    simpler tools.

    Your small, fast, simple tools are - as I have said countless times -
    utterly useless to me. Perhaps you find them useful, but I have never
    known any other C programmer who would choose such tools for anything
    but very niche use-cases.

    The real picture is that real developers can use real tools in ways that
    they find convenient. If you can't do that, it's your fault. (I don't
    even believe it is true that you can't do it - you actively /choose/ not
    to.)

    And since compile speed is a non-issue for C compilers under most circumstances, compiler size is /definitely/ a non-issue, and
    "simplicity" in this case is just another word for "lacking useful
    features", there are no benefits to your tools.

    I somewhat disagree. You probaly represent opinion of majority of
    developers. But that leads to uncontrolled runaway complexity and
    bloat. You clearly see need to have fast and resonably small code
    on your targets. But there are also machines like Raspberry Pi,
    where normal tools, including compilers can be quite helpful.
    But such machines may have rather tight "disc" space and CPU
    use corresponds to power consumption which preferably should be
    low. So there is some interest and benefits from smaller, more
    efficient tools.

    OTOH, people do not want to drop all features. And concerning
    gcc, AFAIK is is actually a compromise for good reason. Some
    other projects are slow and bloated apparenty for no good
    reason. Some time ago I found a text about Netscape mail
    index file. The author (IIRC Jame Zawinsky) explained how
    it fastures ensured small size and fast loading. But in
    later developement it was replaced by some generic DB-like
    solution leadind to huge slowdown and much higher space
    use (apparently new developers were not willing to spent
    a litte time to learn how old code worked). And similar
    examples are quite common.

    And concerning compiler size, I do not know if GCC/clang
    developers care. But cleary Debian developers care,
    they use shared libraries, split debug info to separate
    packages and similar to reduce size.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Wed Dec 4 19:33:53 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Fri, 29 Nov 2024 13:33:30 +0000
    Bart <bc@freeuk.com> wrote:

    [C syntax] allows a list of variable names in the same declaration
    to each have their own modifiers, so each can be a totally
    different type

    Not in every context. It is not allowed in function prototypes.
    Even when it is allowed, it's never necessary and avoided by
    majority of experienced programmers.
    I'd guess, TimR will disagree with the last part.

    I might say I mostly agree. Most of the declarations I write
    have only one declarator. I don't have an absolute rule against
    declaring multiple names in a single declaration; depending on
    what is being declared and on other circumstances it might look
    reasonable. Generally I find rules that admit no exceptions
    under any circumstances to be unnecessarily rigid. These days
    it's the fashion to treat programmers like they're dumb and
    incapable of exercising good independent judgment. I have a
    different view.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Bart on Thu Dec 5 03:23:05 2024
    Bart <bc@freeuk.com> wrote:
    On 04/12/2024 12:29, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    You've never used my scheme.

    Your scheme, not. But you should understand that when speaking
    about module systems C is an outlier, having almost no support
    for modules. Some languages, like C++ and Lisp go half way,
    providing namespaces but rest is up to programmer. Other do
    more. By now classis is _logical_ separation into interface
    and implementation, which seem to be absent from your system.

    It is there, but at a different boundary.

    My language is intended for whole program compilation. There are no interfaces between modules (that is, a file listing the exports of a
    module, separately from the implementation).

    I wrote about _logical_ separation. Oberon puts module in a single
    files, IIRC declarations of exporeded things just have stars before.
    So the is only tiny overhead in terms of extra charaters, but logical separation is there.

    Because the compiler can see (and will compile) the actual implementation

    Such interface files exist between programs, which usually means between
    a main program and the libraries it uses, which are generally
    dynamically loaded.

    In other words, you only support modularization at library level,
    more or less what C is doing (using either compiler extentions or
    external tools one can control what is exported from shared libraries
    build from C files).

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to All on Wed Dec 4 19:42:44 2024
    Michael S <already5chosen@yahoo.com> writes:

    [on adding a rule to the C standard so functions defined
    with a prototype anywhere in a file cause those functions'
    types available throughout the same file]

    No, I am afraid of cases where function is used without prototype and
    then there is conflicting definition later in the module.
    Of course, it's UB, but in practice it could often work fine.
    Something like that:

    static int bar();
    int foo(void)
    {
    return bar(42);
    }

    static int bar(int a, int b)
    {
    if (a == 42)
    return -1;
    return a - b;
    }

    As history-breaking changes go, this one seems about as
    benign as one could hope. Clearly a win IMO.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Tim Rentsch on Thu Dec 5 11:20:48 2024
    On 05.12.2024 02:29, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 03.12.2024 16:24, David Brown wrote:

    Of course lots of C programmers have never read the standards.
    But they generally know that they don't know these details, and
    don't try to pretend that the language details that they don't
    know are confusing. They simply get on with the job of writing
    clear C code as best they can.

    I feel an urge to point out that the C standard is not necessary
    to understand concepts that can be read about in textbooks

    That assumes that such textbooks exist, that they can be identified,
    located, and obtained without too much difficulty, and don't cost too
    much to get.

    Actually no. I was just reporting experiences about the various
    (many) programmers I've met in several companies during decades,
    and from our technical (and academical) discussions. - Literally
    no one had read the "C" standard, all had read one or more books
    and all had some programming and/or computer science background.
    Most people bought their books, some asked their company to buy
    them, one company had built over time a library (physical books).
    (And some/few people also used public or academical libraries.)

    The C standard is easily located and obtained, and
    costs nothing to download (for a draft that is virtually identical
    to the actual standard).

    When I started there was no Web and not even Email available in
    my country. Standards documents were harder to obtain than books.
    Only after around 1990 things (only slowly) changed hereabouts.
    The first standards I got were extremely expensive, the companies
    bought them on demand. The first downloads were unreliable; e.g. I
    wasn't able to download the ITU-T standards because the connection
    constantly dropped, because the documents were "too large" - not
    because of the text but because they stupidly decided to publish
    them using a bulky MS *.DOC format.

    I'm sure these things got better later, and (given what you say)
    that there was a better situation (in all respects) with the "C"
    standard later. But since we know in what "standards language"
    the texts are written I'd not have expected that folks typically
    read standards but prefer textbooks; and that was backed up by
    what I actually observed. (The largest crowd of people knowing
    and quoting standards _regularly_ I saw in this newsgroup, BTW.
    Well, okay, in the farther past I also read a "C++/std" group.)


    or inferred (or just tried out, if the available sources are
    unclear about some detail).

    Two problems with that suggestion. One, trying to figure out what
    the rules are by experimentation is sometimes difficult and
    unreliable.

    You're absolutely correct. Deriving rules by behavioral analysis
    is not what you shall do (or what I would suggest).

    Two, some details, such as what constructs result in
    undefined behavior, simply cannot be determined by means of
    experimentation.

    Sure.

    All I wanted to say is that *some* [types of] questions about
    details you still have after reading a book (after learning the
    language) can be just tried out to confirm the understanding of
    the primary source of information (or experience-based assumption).


    Also, the idea that one can figure out the rules of the C language
    by looking at compiler sources is just laughable.

    Sure. (But that wasn't something that I said. By "sources" I did
    not mean "source code" but sources of information, books, etc.)

    The idea to consider source code quasi as a [syntax-]"defining"
    source came from Bart elsethread.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Thu Dec 5 11:59:45 2024
    On 05.12.2024 00:57, Bart wrote:
    On 04/12/2024 22:58, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    OK, if it's so simple, explain it to me.

    I'll pretend that was a sincere question.

    Let's put it this way: if somebody asked me what the rule was, I
    wouldn't be able to tell them.

    If that is true I suggest to read one or two textbooks.

    But as you are actually a language designer I would suppose that
    it should suffice if you look at the constructs and think about
    them; about the syntactic options and requirements of separate
    statements, their separation/termination, embraced blocks, and
    empty statements. From anyone who implements a language (like
    you did) I'd certainly expect to get that just by own thinking.

    [...]

    Consistency? I posted a bit of Algol68 the other day; each function definition needed a semicolon, to separate it from the next.

    Why do you explicitly name functions here? - Semicolons are a
    general (sequentializing) separator in Algol 68, and not really
    different from other programming languages.

    [...]

    I'm aware of how messy and conistent it is. I've said that languages
    that use ";" as a separator probably fair better, [...]

    (Oh, I thought you said you preferred terminators in languages.)

    [...]

    My own made a compromise here: use ";" as separator,

    (I know that from Awk, where I regularly use that feature.)

    but introduce some
    rules so that explicit ";" is rarely need. I think that wins.

    Would that then be (like in Awk) that you then assume the line-end
    as separator? (For a scripting language I think it's okay. YMMV.
    But generally I would certainly consider that to be a Bad Idea.)


    I said that my generated code has to use ":;" after each label; it looks weird.

    It's funny that you put such an emphasis on labels. - Jumps to
    labels have academically been long deprecated but, more importantly,
    in my practical work I never had a need to use them (or even think
    or considering to use them). (I suppose it's how one got socialized
    to design and write programs.)

    [...]
    [...]

    Of course, if it was just me, then it would be pointless ranting. 'How
    hard is to add the semicolon?'

    Well, 'How hard is it to delete the semicolon' from my above example?

    You obviously have problems on a level that other folks don't have.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Thu Dec 5 12:15:39 2024
    On 05.12.2024 01:19, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    Let's put it this way: if somebody asked me what the rule was, I
    wouldn't be able to tell them.

    Probably because there's no single rule. As I wrote, "{" and "}"
    are used in different contexts with different meanings. [...]

    The context in the post was not about the many places where the
    braces are used in "C" but was concerning only a very specific
    case; mainly an empty statement (terminated by a semicolon) and
    an empty block (an empty compound statement). - If that already
    confuses him you can imagine what you do when pointing out that
    there's yet more uses of braces. :-)

    [...]

    Consistency? I posted a bit of Algol68 the other day; each function
    definition needed a semicolon, to separate it from the next.

    (In Algol 68 not specifically only function definitions. "Things"
    just need separation "to tell them apart". That's quite typical
    for [programming] languages.)


    C is not Algol68. In C, the syntax of a function definition is such
    that they can be appended without ambiguity. Requiring a semicolon
    after each definition would not help anything. [...]

    Any why would one want to introduce an inconsistency here? The
    "C" syntax may be disliked but at least it makes sense [here].

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Thu Dec 5 11:54:38 2024
    On 05/12/2024 10:59, Janis Papanagnou wrote:
    On 05.12.2024 00:57, Bart wrote:
    On 04/12/2024 22:58, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    OK, if it's so simple, explain it to me.

    I'll pretend that was a sincere question.

    Let's put it this way: if somebody asked me what the rule was, I
    wouldn't be able to tell them.

    If that is true I suggest to read one or two textbooks.

    That answer suggests we're talking at cross-purposes.

    So if the rules really aren't that simple, 100M users of the language
    aren't going to find it any easier but wasting time looking this up in textbooks.

    That's not going to happen, and it they are casual users of their
    compilers, they WILL write semicolons in the wrong place with no errors reported. Until it bites.

    Fixing the language is always the best solution. Failing that, make
    compilers report extraneous semicolons.

    Consistency? I posted a bit of Algol68 the other day; each function
    definition needed a semicolon, to separate it from the next.

    Why do you explicitly name functions here? - Semicolons are a
    general (sequentializing) separator in Algol 68, and not really
    different from other programming languages.

    This is my point. Algol68 requires semicolons between function
    definitions because its following a simple, consistent rule. C doesn't
    require them.

    I mean, I'd rather not have to write }; everything, but I'm sure many
    will be confused by the inconsistency.



    [...]

    I'm aware of how messy and conistent it is. I've said that languages
    that use ";" as a separator probably fair better, [...]

    (Oh, I thought you said you preferred terminators in languages.)

    Both pure separators and pure terminators have issues.

    My compromise is not pure.


    [...]

    My own made a compromise here: use ";" as separator,

    (I know that from Awk, where I regularly use that feature.)

    but introduce some
    rules so that explicit ";" is rarely need. I think that wins.

    Would that then be (like in Awk) that you then assume the line-end
    as separator? (For a scripting language I think it's okay.

    What's the difference between a scripting language and any other?

    I've always wondered why people think a clean, clear, easy-to-understand
    syntax is OK for a scripting language, but is no good at all for a
    'REAL' programming language.

    Maybe they consider a scripting language is one that needs to be useable
    by 'plebs' and others who might not be able to get their head around a
    'hard' syntax?

    I think those useful properties of a syntax that make it as simple as pseudo-code, will work across all levels of languages.

    (My two languages, systems and scripting, have pretty much the same
    syntax. The former needs more type annotations, but such annotations can
    appear in some contexts of the scripting language too.

    This complete program:

    proc main =
    for i to 20 do
    println i, sqrt i
    od
    end

    since it has no types, works unchanged in both my languages.)

    I said that my generated code has to use ":;" after each label; it looks
    weird.

    It's funny that you put such an emphasis on labels. - Jumps to
    labels have academically been long deprecated but, more importantly,
    in my practical work I never had a need to use them (or even think
    or considering to use them). (I suppose it's how one got socialized
    to design and write programs.)

    So you're one of those who never uses 'goto'. OK.

    I'm not. I use 'goto' perhaps once or twice per 1000 lines, because it
    is the simplest solution. And use labels a LOT in both generated HLL
    code, and in linear IL and ASM targets.

    In the Linux kernel code (as of 10 years ago), there were about 140,000
    gotos, I think about once in 150 lines on average.

    You obviously have problems on a level that other folks don't have.

    I see things on a different level from others because I implement this
    stuff, both devising languages and implementing them.

    Is that not obvious?


    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Thu Dec 5 12:00:32 2024
    On 05/12/2024 10:20, Janis Papanagnou wrote:
    On 05.12.2024 02:29, Tim Rentsch wrote:

    Also, the idea that one can figure out the rules of the C language
    by looking at compiler sources is just laughable.

    Sure. (But that wasn't something that I said. By "sources" I did
    not mean "source code" but sources of information, books, etc.)

    The idea to consider source code quasi as a [syntax-]"defining"
    source came from Bart elsethread.

    If you look at the data parts of my compiler source code, then many
    elements of the syntax are listed: types, reserved words, operators,
    tokens, precedences, scopes, properties, conversions...

    For the shape of the syntax, then since the compiler is self-hosted,
    then it serves also as a 30,000-line example of what it looks like.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Thu Dec 5 13:42:07 2024
    On 04.12.2024 21:47, Bart wrote:
    On 04/12/2024 19:23, Janis Papanagnou wrote:
    On 04.12.2024 18:43, Bart wrote:

    You really hate toy languages don't you?

    No.

    [...]

    When someone has claimed to write some program, do you always demand
    they produce a 'formal grammar' for it?

    No.


    What is the complexity threshold anyway for something to need such a
    formal specification?

    It depends. (There can't be a simple answer here.)


    What input would even be classed as a language: are binary file formats languages? What about the commands of a CLI?

    Inspect the Web, for example Wikipedia, to learn what a language
    and specifically a formal language is (if you really don't know
    that).

    [...]

    That's nothing more then a hacker's feeble excuse to justify his
    ignorance.

    So you're calling me a hacker, and you're calling me ignorant.

    Yes, I think in some areas of software development you expose the
    mentality of a hacker.

    Yes, I think you are ignorant concerning some basic topics we were
    discussing here...


    Nice.

    ...but obviously (as opposed to you) I don't consider "ignorance"
    ("not knowing") being a Bad Thing; rather I think that ignorance
    is a human's normal state where we all start from and (hopefully)
    from where we continue learning.

    (Showing ignorance on a topic while at the same time pretending
    to know is not what I appreciate, though.)

    [...]

    My own products were in-house tools to get stuff done. And they worked spectacularly well.

    Yes, that was already acknowledged (also by me) several times here.

    [...]

    OK, you're a professional; I'm an amateur (an amateur who managed to
    retire at 42). I will give you that. Satisfied?

    Huh? - Most people here I consider to be "professionals" (in one
    way or the other, maybe), and I didn't exclude you.

    I am speaking about professional contexts where it matters more
    what decisions you make with a project. Where you can't just try
    out many things, where you have to plan things, where you make
    studies and market analysis, where you work in teams, cooperate
    with other companies, in local, distributed, or global settings
    where you specify your products and test them, where you use and
    rely on standards. And so on...

    When you once wrote about whether I wouldn't think that you are
    a capable software writer (or some such), I can assert you that
    I think you are. - But what I thought was: What potential would
    that guy have if he'd have had more contact with a couple of
    companies to merge his own capabilities with the companies', so
    that the companies and he himself would gain from that.

    [...]

    For the rest of us, that part is the simplest part of a compiler. You
    write it, and move on.

    Is that the reason why your languages and compilers are so widespread
    used? </sarcasm>

    By contrast, the languages that you've devised are in common use of course?

    I'm not a developer of languages - at least I don't count my own
    language implementations as worthwhile since they just served my
    personal purposes, and it certainly wouldn't appear to me to brag
    about them. - Generally there was no necessity; in professional
    contexts we certainly used existing languages (for good reasons),
    and also privately I'm using existing languages for programming.
    I mean, it would be really silly if I want to write an OO designed
    system and, instead of just using C++, would complain about its
    crude syntax and write my own C+++ before doing the intended job.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Scott Lurndal on Thu Dec 5 15:45:33 2024
    On Wed, 04 Dec 2024 22:48:20 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 17:55, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 03/12/2024 14:34, David Brown wrote:
    On 02/12/2024 22:53, Bart wrote:

    For the project-specific code, rather than libraries, SDK, etc.:

    ----------------------------------------------------------------------- >>>> Language             files          blank        comment
      code
    ----------------------------------------------------------------------- >>>> C++                     39           2217           1020
    11820 C/C++ Header            44           1078            798
             2696 C                        3            259
      237           1152
    ----------------------------------------------------------------------- >>>> SUM:                    86           3554           2055
    15668
    ------------------------------------------------------------------------

    Not that it really matters, but a typical build for my project
    takes about 1 to 3 seconds.

    I don't really know what they means, because I don't know is
    involved, and what is being missed out.

    So, to get an idea of how long gcc really takes (or would take on
    my machine), I set up a comparable test. I took an 800-line C
    program, and duplicated it in 200 separate files f1.c to f200.c,
    for a total line count of 167Kloc.

    gcc took 30 to 90 seconds to create an EXE using -O0 and -O2.

    Under WSL, it took 18 to 54 seconds 'real time' (to .o files; it
    can't link due to Win32 imports).

    Tiny C took 0.64 seconds.

    Here's a typical build for my project:

    $ make -s -j 64
    ...

    COMPILE apc2.cpp
    COMPILE bcp2.cpp
    BUILD /scratch/lib/libdevice_yyy.so
    XXXX_BUILT
    BUILDSO /scratch/libxxxx.so.1.0
    BUILD TARGET /scratch/bin/xxxx
    COMPILE shim.cpp

    real 13m48.24s
    user 1h2m9.78s
    sys 0m56.73s

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?


    That was a build that touched a key header file, so maybe
    85% full. A full build adds a minute or two wall time.

    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    LLVM/clang or gcc?

    Sounds like you can benefit both from faster compiler and from faster
    make utility.

    Also it sounds likely that you are already benefiting from faster
    linker. Which was created by google guy (Ian Lance Taylor) despite that
    back then prevailing opinion among people that share your attitude was
    that gnu ld is o.k. and at most need small tweaks.

    BTW, can you experiment with -O0 ? What speedup does it provide over
    -O2 in the project as big as yours?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Thu Dec 5 15:00:57 2024
    On 04/12/2024 22:31, Bart wrote:
    On 04/12/2024 20:55, David Brown wrote:
    On 04/12/2024 16:09, Bart wrote:

    It's used to avoid cluttering code with ugly xxx:: qualifiers, and
    save some typing at the same time. That's pretty much it.

    Buy a better keyboard.  Saving typing is a pathetic excuse.

    How does a better keyboard make this less cluttery:

       std::cout << xxx::X << yyy::Y << std::endl

    Compare with:

       cout << X << Y endl


    Maybe a better keyboard would stop you from complaining about the
    horrors of having to press the shift key occasionally, or otherwise
    having to type more than an absolute minimum number of symbols.

    And while you are at it, buy a better screen. You were apparently
    unable to read the bit where I said that /saving typing/ is a pathetic
    excuse.

    Avoiding or reducing clutter, on the other hand, is often a good thing -
    as long as it does not reduce the important information shown to the reader.

    Thus in C++ you have "using" clauses that let you reduce the need for namespaces in the bits of code where you, the programmer, decide that
    omitting the namespace makes the code clearer. It's an active choice.
    That's a good thing. (C++ has many other ways to abbreviate code and
    hide detail that would otherwise obscure the code - such as "using"
    aliases for complex types, "auto", and references.)

    C++ also has "argument-dependent lookup" - basically, that sees that the argument to the "<<" operator above is in std::, so it automatically
    looks for an appropriate "<<" operator in std:: to avoid having to write "std::cout std::<< x". That does /not/ mean that the operator has been
    pulled into the local namespace - it means the other namespace has been searched because you've already given that namespace (in the argument).


    Clearly I can only speak for my own opinion, but I don't want the
    /language/ to decide that all my symbols will be jumbled into one pile.
    If I have made namespaces, I have done so for a reason - I want to keep
    them somewhat separated and structured. I might /choose/ to hide some
    of that structure in a piece of code if it makes things clearer, but I
    don't want the language to do that by default!



    That seems to be something akin to C++ classes or structs with static
    methods.  But I'm not sure, and certainly not sure how it is relevant.

    You said my namespaces were jumbled. They generally work as people
    expect, other than some different rules on name resolution.

    No, they work as /you/ expect. Not "people". You designed the language
    for one person - you. It would be extraordinary if it did not work the
    way /you/ expect!

    Real programming languages involve a great many people if they are to
    evolve beyond a tiny niche. That way they are influenced by lots of
    opinions, experiences, desires, and use-cases way beyond what any one
    person could ever have. Real languages are always compromises - they
    are rarely "perfect" in anyone's views, but they are good enough in the
    view of many people.

    So the way namespaces work in C++ is something that - by my rough finger-in-the-air estimates - dozens of people were involved in forming
    the plans, hundreds of people would have had a chance to comment and
    complain about if they thought there were better ways to do it, and now millions of people use on a regular basis. C++ namespaces work the way
    those millions of C++ programmers expect - because that's the way they
    work. This does not necessarily mean that C++ namespaces work the way
    they /want/ - that's a very different question. But of all the things
    people find difficult, and all the things people complain about (and
    there are many such things - no one has ever accused C++ of being a
    "perfect" language), the way namespaces work is simply not an issue.

    That suggests that the ratio of people who expect identifiers from
    namespaces to require namespace qualification unless you /explicitly/
    request importing them into the current scope, compared to the people
    who expect namespaces to default to a jumble and overwhelm the current
    scope, is of the order of millions to one.


    Compare for example how filenames are resolved in a file system, when
    both absolute and relative paths are missing. Sometimes it will look in
    a list of special places (eg. using Windows' PATH variable) if not found locally.


    Yes - /sometimes/ file lookup uses some kind of path. That happens for specific cases, using explicitly set path lists. Who would be happy
    with an OS that when they tried to open a non-existent file "test.txt"
    from their current directory in an editor, the system searched the
    entire filesystem and all attached disks? When you use the command
    "tcc", would you be happy with a random choice - or error message -
    because someone else put a different program called "tcc.exe" on a
    network drive somewhere?

    That is how file lookup would appear with your scheme.

    With the way C++ namespaces work, it is pretty much exactly like people
    expect from a filesystem - normally unqualified names are from the
    current scope (like files from the current directory), and if you want
    names from a different namespace you qualify it (like specifying the
    directory explicitly for a file). And for situations where you find it convenient to have a shortcut, C++ provides these (just as filesystems
    provide features user-level like symbolic links and a few common
    shortcuts like PATH).


    You don't agree with my choices, OK.

    No, I don't agree with them. Yes, it is your choice for your language.

    But you choose to talk about your language - so I can tell you why I
    think they are not good design choices. Again, since you seem to forget
    this, I don't in any way think all your design choices are bad. I have
    tried to explain /why/ I think this particular choice is bad, and how
    better alternatives could work.


    Of course tcc won't work - I work with embedded systems, and as I have
    said countless times, your little tools don't target the devices I use.

    In my hardware days I built boards with embedded processors too.


    So presumably you understand the concept of using a compiler that
    generates code for the actual target you want? It should therefore not
    be a surprise that tcc would be useless to me.

    I programmed them with my 'toy' language. Sometimes I didn't have have a compiler, so a couple of times I wrote an assembler for the device. The assembler (obviously, you will consider that a toy) was written in my
    toy language. (One was for 80188, the other was 8035 or 8051.)


    OK.

    My point is that 'toy' implementations /could/ work just as well, and
    here I was able to get working prototypes. (At least, until my boss had
    some new ideas and I moved on to something else.)


    No, toy implementations could /not/ work "just as well" as good tools.
    They may be able to work well enough in limited situations. They may be
    all you've got, or all you can afford, or there may be other overriding factors. I've used weak tools when good ones were ruled out - but when
    I have the choice of good tools or poor ones, I choose good tools. For
    simple little programs, it can make sense to pick the nearest tool -
    something easy and convenient that you are used to. For a serious
    project - perhaps many man-months of work spread over a year and
    supported for a decade or more - you start by looking for the right
    tools for the task. You don't use toys.

    Except for developers working on massive code bases (like Scott),
    developer's computers have effectively unlimited space and unlimited
    computer power. But the target systems usually do not. This applies
    for software that will run on PC's, but especially for small embedded
    systems. A compiler that generates twice as efficient code means I can
    use a cheaper microcontroller with half the flash and half the speed,
    using half the battery power and emitting half the EMI interference. Or
    it can run a motor at twice the speed, or half the error ranges.

    Optimisation in the compiler also means I can write clearer source code, knowing that the compiler will generate good results. I've worked with
    tools where I needed to "manually optimise" code to get good results -
    use pointer arithmetic instead of arrays, shifts and adds instead of multiplies, function-like macros instead of inline functions, and so on.
    It's harder work, uglier, less maintainable, and more error-prone.

    And of course I would much rather find potential problems as soon as
    possible using static error checking, rather than later on during testing.

    Your compiler and tcc don't reach ankle-level to gcc, clang or even MSVC
    for real work. If they actually did work "just as well", and were much
    faster and simpler, then I'd use them. (I'd still use make - no sane
    developer runs compilers manually for real work.)


    I /need/ good optimisations - it's not an option, it's a requirement
    to get fast enough code for the end system to work.  So your toys
    would not be usable even if they supported the right target.

    And I did without an optimising compiler for 20 years. Not that C
    compilers were that much better for a lot of that period, of 82-02.


    That's like some American boosting us how the USA got to the moon using imperial measurements so they don't need metric. You managed /despite/ crippling yourself and your workflow, not because of it. (I do
    understand that good tools were hard to get in those old days - but not
    for the last 20 years.)

      I use C++ as well as
    C - your toys don't support that.  I use C17 (and will move to C23
    when my tools support it) - tcc supports only up to partial C99
    support, and $DEITY only knows what partial C standard your compiler
    handles.

    My C compiler is for my personal use. It will build only a tiny fraction
    of existing code, but will compile 100% of the code I write, or generate.

    So I'm not asking people to use it. But it shows what is possible.


    It doesn't show anything useful is possible. No one else wants to
    compile the limited subset of C that you want, nor do they want a C
    compiler written in some weird private language. Some other people want
    to use or write small C compilers for a variety of reasons - your
    compiler does nothing for them. (And their compilers probably do
    nothing for you.) tcc at least tries to be useful to a wider range of
    users, and has some niche uses.

    There's nothing wrong with writing your own C compiler - or partial C
    compiler. If you find it useful, great. If you enjoyed writing it,
    great. Even if it is useless, it is still a sizeable achievement. I
    have always said as much.

    But it is not an alternative for other people. It is not some kind of
    proof that compilers - real compilers for real work - don't have to be
    large. Your tools are not better in any way that is meaningful to
    anyone else - even if they are ideal for /your/ use.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Thu Dec 5 06:33:39 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Bart <bc@freeuk.com> writes:

    On 04/12/2024 22:58, Keith Thompson wrote:

    Bart <bc@freeuk.com> writes:

    OK, if it's so simple, explain it to me.

    I'll pretend that was a sincere question.

    Let's put it this way: if somebody asked me what the rule was, I
    wouldn't be able to tell them.

    Probably because there's no single rule. As I wrote, "{" and "}"
    are used in different contexts with different meanings. (So are
    "(", ")", ";", and "static".) I have no particular expectation
    that there should be a single rule covering all the cases, just
    because they happen to use the same symbol.

    A reasonable person would have ackowledged that I've at least
    tried to answer your question.

    For the record I appreciate your efforts to answer Bart's C
    questions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Thu Dec 5 07:13:36 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Wed, 4 Dec 2024 21:01:07 +0000
    Bart <bc@freeuk.com> wrote:

    The C language is one of the most quirky ones around full of
    apparently ridiculous things. Why shouldn't you be able to write
    this for example:

    {
    ....
    L:
    }

    This stupid rule means that EVERY label in my generated code
    needs to be written as L:; instead of just L:

    Please don't say the label is only defined to be a prefix to
    another statement. I asking why it was done like that.

    No good reasons. It was a mistake of Committee 35 years ago.

    I don't agree that it was a mistake in the original C standard. The
    charter of the original standardization effort was to define the
    language as it was at the time, not to try to fix it. If "minor
    improvements" were allowed the group would have spent all their
    time arguing about what the language should be and not fulfill the
    primary task. The PL/C group at Cornell made the same observation
    about PL/C relative to PL/I: they decided to implement (a subset
    of) PL/I as is, and not consider any changes, so as not to get lost
    in the swamp of changing the language.

    There are two obvious counterexamples to the above principle, those
    being the void type and function prototypes. My understanding is
    that both of those language features were available in some widely
    used compilers at the time, and they offered significant benefits
    that were not available otherwise. By contrast the value of not
    needing a statement after a label is so far down the list you'd
    need a telescope to see it.

    I don't know why it was not fixed in 3 subsequent iteration.

    Probably because the committee thought they had better things to
    do. I'd much rather have the changes that were introduced in
    C99 and C11 than any time spent on unimportant cosmetic issues
    like needing a semicolon after an end-of-block label.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Thu Dec 5 15:45:19 2024
    On 05.12.2024 12:54, Bart wrote:
    On 05/12/2024 10:59, Janis Papanagnou wrote:
    On 05.12.2024 00:57, Bart wrote:
    On 04/12/2024 22:58, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    OK, if it's so simple, explain it to me.

    I'll pretend that was a sincere question.

    Let's put it this way: if somebody asked me what the rule was, I
    wouldn't be able to tell them.

    If that is true I suggest to read one or two textbooks.

    That answer suggests we're talking at cross-purposes.

    (Always possible.)


    So if the rules really aren't that simple, 100M users of the language
    aren't going to find it any easier but wasting time looking this up in textbooks.

    I probably have a different view on that than you might have.

    What I expect is that programmers, before starting programming,
    learn the language they intend to program in. This is no waste
    but a necessity. (Although in more recent times I observe also
    different habits, with the then expected "quality" of output.)
    Looking things (details?) up if in doubt is also no "waste" of
    time.

    If, OTOH, all you wanted to express is that a cleanly defined,
    coherent language that makes look-ups rare, is better than a
    quirky language with incoherences, many special cases, and a
    lousy syntax, then of course I agree with that (as most folks
    would certainly do).


    That's not going to happen, and it they are casual users of their
    compilers, they WILL write semicolons in the wrong place with no errors reported. Until it bites.

    Semicolons, really, are not the problem - AFAIR, in *none* of
    the languages I was engaged with.


    Fixing the language is always the best solution. Failing that, make
    compilers report extraneous semicolons.

    No, the best solution is a language that has been *designed*
    [in advance] (in the first place).

    [...]

    Both pure separators and pure terminators have issues.

    (Okay, I won't continue on that; I accept that you see or have
    issues with semicolons.)

    [...]

    [ Awk syntax as example ]

    What's the difference between a scripting language and any other?

    For the purpose here the difference for me was the way how and
    where I typically use "scripting" languages and languages that
    are typically compiled respectively.

    My general point is that I think a syntax should not depend on
    layout (e.g. use of whitespace, column-specific symbols and
    semantics, semantics of Tab-indented code, and, the choice of
    line terminations as a lexical token). Syntax should (IMO) be
    expressed in terms of visible tokens. (So that a reformatting
    of source code will not, and IMO should not, change semantics,
    or even produce errors.)

    Scripting language seem often defined in a IMO suboptimal, more
    lax way concerning semicolons. - But I admit, it's certainly
    not a necessity that scripting languages must be more allowing
    than non-scripting languages that are used in other contexts.


    I've always wondered why people think a clean, clear, easy-to-understand syntax is OK for a scripting language, but is no good at all for a
    'REAL' programming language.

    (I don't know where you get that from.)

    The attributes you list are important for all types of programming
    languages. (Would anyone disagree?)

    (But consider Unix shell; its syntax is neither clean, nor clear,
    or easy to understand, let alone its semantics. - I'm programming
    on a daily basis with a Unix shell. I'm used to the syntax but it
    is a pain and especially nothing comforting for newbies. - Also
    in scripting languages, you cannot expect good syntax. I would be
    mollified if newer languages, scripting or else, would at least
    consider the experiences from inappropriate earlier attempts, but
    no.)

    [...]

    I said that my generated code has to use ":;" after each label; it looks >>> weird.

    It's funny that you put such an emphasis on labels. - Jumps to
    labels have academically been long deprecated but, more importantly,
    in my practical work I never had a need to use them (or even think
    or considering to use them). (I suppose it's how one got socialized
    to design and write programs.)

    So you're one of those who never uses 'goto'. OK.

    In fact, yes. But it's not a dogma, if you insinuated that. (I
    might have used it once or twice, maybe in a some specific case,
    but I wouldn't bet on that.) It's just that it turned out to be
    unnecessary to write sophisticated code with 'goto'.

    It's different in my Unix shell programs; here I'm sure that I
    used 'break' (occasionally), 'continue' (rarely), 'break <N>'
    (maybe once or twice).

    In most cases 'goto' (and 'break' in shell) muddy the clearness
    of control flow and (IMO) should be avoided. I happen to avoid
    it just because it never appeared as necessity to even think
    about using it

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Thu Dec 5 16:15:08 2024
    On 05.12.2024 15:00, David Brown wrote:
    [...]

    That's like some American boosting us how the USA got to the moon using imperial measurements so they don't need metric. [...]

    That opens an option for a subthread with a lot jokes, anecdotes, and
    (not so funny) real accidents, concerning colonial vs. metric system.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to BGB on Thu Dec 5 07:16:31 2024
    BGB <cr88192@gmail.com> writes:

    [considering .csv files and how to process them]

    Brings up the thought of how, ASCII has a bunch of control
    characters, but generally only a small number of them are used:
    \r, \n, \t, \b
    \e, \a, \v, \f (sometimes / rarely)

    For CSV, we used ',' (a printable ASCII character) for something
    that (theoretically) could have used \x1E (Record Separator).

    That would have been a horrible decision.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Thu Dec 5 15:43:39 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Wed, 04 Dec 2024 22:48:20 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    David Brown <david.brown@hesbynett.no> writes:

    Is that a "typical" build - or an atypical full clean build?
    =20
    =20
    That was a build that touched a key header file, so maybe
    85% full. A full build adds a minute or two wall time.
    =20
    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    LLVM/clang or gcc?

    gcc, various version from 7.5 through 14.


    Sounds like you can benefit both from faster compiler and from faster
    make utility.

    Perhaps, but 28 seconds isn't really that bad. Particularly compared
    with the systems I used forty years ago :-)

    <snip linker>


    BTW, can you experiment with -O0 ? What speedup does it provide over
    -O2 in the project as big as yours?

    We typically use -O3, except on a couple of source files which
    take over 6 minutes of CPU time to compile, each, when -O3 is
    specified.

    We understand why it takes that long and have long term plans to
    address that by restructuring some auto generated C++ data
    structures.

    But ultimately, the project has well over two millon SLOC and
    almost two thousand source files to compile. It's never going
    to be fast.

    -O0 may improve compile time, but it significantly increases
    run-time of the resulting code (by a factor of three or four).

    The application is a full-system SoC functional simulator. It
    takes three to four minutes to boot linux to the login prompt
    on the simulator when it is built with -O3. Far longer with
    -O0.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Thu Dec 5 15:29:10 2024
    On 05/12/2024 14:00, David Brown wrote:
    On 04/12/2024 22:31, Bart wrote:

    And while you are at it, buy a better screen.  You were apparently
    unable to read the bit where I said that /saving typing/ is a pathetic excuse.

    I can't type. It's not a bad excuse at all. I have also suffered from
    joint problems. (In the 1980s I was sometimes typing while wearing
    woolen gloves to lessen the impact. I haven't needed to now; maybe I've
    slowed down, but I do take more care.)

    You said my namespaces were jumbled. They generally work as people
    expect, other than some different rules on name resolution.

    No, they work as /you/ expect.  Not "people".

    The concept is so simple that is not much about it for anyone to tweak.

    A qualified name looks like this (this also applies to a single identifer):

    A.B.C

    'A' is a top-level name. It is this that the name-resolution in a
    language needs to identify.

    Presumably, in your C and C++ languages, all possible top-level names
    must be directly visible. Only in C++ with 'using namespace' does it
    allow a search for names not directly visible, by looking also in
    certain places.

    This is where the rules diverge a little from what I do. Given 'CHUMMY'
    modules X, Y, Z (which I deliberately choose), then each effectively
    includes 'using namespace' for each of the other two modules.

    I also have a different rule when there is clash between the contents of
    a 'using' namespace, and the set of directly visible names. As I say
    below, I consider the former to be in an outer scope.

    The basics are more or less the same; some details differ. You can't say
    that C++ has the final word on it just because that's the committee
    choice it made, and every other approach must be wrong.

    So my approach is a little more informal, and more convenient. I could
    have gone another way so that instead of writing this:

    pcl_start()
    pcl_end()

    which is allowed instead of full qualifers which would be this:

    pcl.pcl_start()
    pcl.pcl_end()

    I could use your strict approach. Then I'd use a different naming
    scheme, so that it looks like this:

    pcl.start()
    pcl.end()

    This is not that different from the above! But I'd be uneasy about using non-prefixed names within that library. (For one thing, 'start' is a
    special function name; and 'end' is a keyword! There'd be other clashes.)

    In short, you are just quibbling. I probably implemented 90% of what C++
    has, you're trying to make out it's utterly different and unsuitable.

    BTW, once 'A' has been resolved, then .B and .C generally are
    unambigious in my static language (and may need runtime checks in my
    dynamic one, if A is a variable rather then a module or type).

    In C++ however, I suspect that what .B and .C mean may be subject to
    overloads, inheritance, and who knows what else.


      You designed the language
    for one person - you.  It would be extraordinary if it did not work the
    way /you/ expect!

    Yep. And yet, it is not some obscure, exotic monstrosity. It's not that different from most others, and it's not that hard to understand.

      That way they are influenced by lots of
    opinions, experiences, desires, and use-cases way beyond what any one
    person could ever have.

    A shame it didn't work for C!

    So the way namespaces work in C++ is something that - by my rough finger-in-the-air estimates - dozens of people were involved in forming
    the plans, hundreds of people would have had a chance to comment and

    Yeah. Design-by-committee. Just about every feature of C++ is a dog's
    dinner of overblown, over-complex features. C++ doesn't do 'simple'.
    (Look at the 'byte' type for example; it's not just a name for 'u8'!)

    That suggests that the ratio of people who expect identifiers from
    namespaces to require namespace qualification unless you /explicitly/
    request importing them into the current scope, compared to the people
    who expect namespaces to default to a jumble and overwhelm the current
    scope, is of the order of millions to one.

    They're not imported into the current scope, but an outer scope.
    Anything with the same name in the current scope will shadow those imports.

    C and C++ both have block scopes, yes? So the potential is there for
    nested scopes dozens of levels deep.

    Yes - /sometimes/ file lookup uses some kind of path.  That happens for specific cases, using explicitly set path lists.  Who would be happy
    with an OS that when they tried to open a non-existent file "test.txt"
    from their current directory in an editor, the system searched the
    entire filesystem and all attached disks?  When you use the command
    "tcc", would you be happy with a random choice - or error message -
    because someone else put a different program called "tcc.exe" on a
    network drive somewhere?

    That's exactly how Windows works. I think Linux works like that too:
    since tcc.exe is not a local file, and it doesn't use a path, it uses
    special rules to locate it. Somebody could mess about with those rules.

    So, why don't you always have to type:

    /usr/bin/tcc.0.9.28/tcc # or whatever

    instead of just 'tcc'?

    No, I don't agree with them.  Yes, it is your choice for your language.

    But you choose to talk about your language - so I can tell you why I
    think they are not good design choices.

    My design is to allow default 'using namespace'; see above.

    That's ... pretty much it.

    Your compiler and tcc don't reach ankle-level to gcc, clang or even MSVC

    That's good.

    I once had to build a garden gate for my house. I decided to make my
    own, and ended up with a 6' wooden gate which was exactly what I needed.

    If LLVM made gates, theirs would have been 9 miles high. A little
    unwieldy, and probably a hazard for air traffic.

    It doesn't show anything useful is possible.  No one else wants to
    compile the limited subset of C that you want,

    That's not true. Thiago Adams would find it useful for one. Obviously I do.

    Anyone using C an intermediate language would do so. As would anyone
    writing C up to C99.

    nor do they want a C
    compiler written in some weird private language.

    Weird? There's a lot more weirdness in C!

    But it is not an alternative for other people.  It is not some kind of
    proof that compilers - real compilers for real work - don't have to be
    large.

    I suspect your prefered compilers wouldn't even run on a Cray-1
    supercomputer, perhaps not even dozens of them.

    Yet people /were/ running compilers for all sorts of languages on
    machines that weren't as powerful. Professional people writing
    professional software.

    You're effectively calling all those toys.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Waldek Hebisch on Thu Dec 5 16:46:53 2024
    On 05/12/2024 04:11, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 04/12/2024 16:09, Bart wrote:
    On 04/12/2024 09:02, David Brown wrote:
    On 03/12/2024 19:42, Bart wrote:

    Yesterday you tried to give the misleading impression that compiling a
    substantial 200Kloc project only took 1-3 seconds with gcc.


    No, I did not. I said my builds of that project typically take 1-3
    seconds. I believe I was quite clear on the matter.

    Without word "make" it was not clear if you mean full build (say
    after checkout from repository). Frequently people talk about re-making
    when they mean running make after a small edit and reserve build
    for full build. So it was not clear if you claim to have a compile
    farm with few hundred cores (so you can compile all files in parallel).

    I talk about "building" a project when I build the project - produce the relevant output files (typically executables of some sort, appropriately post-processed).

    If I wanted to say a "full clean build", I'd say that. If I wanted to
    include the time taken to check out the code from a repository, or to
    download and install the toolchain, or install the OS on the host PC,
    I'd say that.

    When I am working with code, I edit some files. Then I build the
    project. Sometimes I simply want to do the build - to check for static
    errors, to see the size of code and data (as my targets are usually
    resource limited), etc. Sometimes I want to download it to the target
    and test it or debug it.

    /Why/ would anyone want to do a full clean build of their project?
    There are a number of good reasons - such as checking that everything
    works on a different host computer, or after updating tools, or because
    you have a somewhat limited build setup that can't handle changing
    header usage automatically. Fair enough - but that's not a typical
    build, at least not for me.

    (The fact that I use "make" - far and away the most common build tool -
    is irrelevant. Much the same would apply with any other build tool.)

    Bart is not interested in how much time it takes for people to build
    their projects. He is interested in "proving" that his tools are
    superior because he can run gcc much more slowly than his tools. He
    wants to be able to justify his primitive builds by showing that his
    tools are so fast that he doesn't need build tools or project
    management. (He is wrong on all that, of course - build tools and
    project management is not just about choosing when you need to compile a
    file.) Thus he also insists on single-threaded builds - compiling one
    file at a time, so that he can come up with huge times for running gcc
    on lots of files. This is, of course, madness - multi-core machines
    have been the norm for a couple of decades. My cheap work PC has 14
    cores and 20 threads - I'd be insane to compile one file at a time
    instead of 20 files at a time.


    If I do a full, clean re-compile of the code, it takes about 12 seconds
    or so. But only a fool would do that for their normal builds. Are you
    such a fool? I haven't suggested you are - it's up to you to say if
    that's how you normally build projects.

    If I do a full, clean re-compile /sequentially/, rather than with
    parallel jobs, it would be perhaps 160 seconds. But only a fool would
    do that.

    Well, when I download a project from internt the first (ant frequently
    the only compilation is a full build).

    That is not development, which is the topic here.

    And if build fails, IME
    to is much harder to find problem from log of parallel build.
    So I frequently run full builds sequentially. Of course, I find
    something to do when computer is busy (300sec of computer time
    spent on full build is not worth extra 30 seconds to find trouble
    in parallel log (and for bigger things _both_ times grow so
    conclusion is the same)).


    That does not sound to me like a particularly efficient way of doing
    things. However, it is presumably not something you are doing countless
    times while working. And even then, the build time is only a small
    proportion of the time you spend finding the project, reading its documentation, and other related tasks. It's a one-off cost.

    I gave some timings that showed gcc-O0 taking 50 times longer than tcc,
    and 150 times longer with -O2.

    That is the real picture. Maybe your machine is faster than mine, but I
    doubt it is 100 times faster. (If you don't like my benchmark, then
    provide another in portable C.)

    All this just so you can crap all over the benefits of small, faster,
    simpler tools.

    Your small, fast, simple tools are - as I have said countless times -
    utterly useless to me. Perhaps you find them useful, but I have never
    known any other C programmer who would choose such tools for anything
    but very niche use-cases.

    The real picture is that real developers can use real tools in ways that
    they find convenient. If you can't do that, it's your fault. (I don't
    even believe it is true that you can't do it - you actively /choose/ not
    to.)

    And since compile speed is a non-issue for C compilers under most
    circumstances, compiler size is /definitely/ a non-issue, and
    "simplicity" in this case is just another word for "lacking useful
    features", there are no benefits to your tools.

    I somewhat disagree. You probaly represent opinion of majority of developers. But that leads to uncontrolled runaway complexity and
    bloat.

    You misunderstand.

    The speed of C compilation is a non-issue for almost all C programmers.
    A reason for that is that it /is/ an issue to some - in particular, to
    compiler developers. The gcc developers care about the speed of gcc -
    and because of that, I don't have to care. (To be accurate, they care
    mostly about the speed of C++ compilation, because that is often a lot
    more relevant to developers. C often just gets the benefits as a
    side-effect.)

    You clearly see need to have fast and resonably small code
    on your targets. But there are also machines like Raspberry Pi,
    where normal tools, including compilers can be quite helpful.
    But such machines may have rather tight "disc" space and CPU
    use corresponds to power consumption which preferably should be
    low. So there is some interest and benefits from smaller, more
    efficient tools.

    Raspberry Pi's have no problem at all running native gcc.

    It is certainly true that not all programs need to be small and fast.
    In fact, the great majority of programs do not need to be small and
    fast. Thus for the great majority of programs, C is the wrong language
    to use. You want something with a better balance of developer
    efficiency, features and run-time safety.

    There can, of course, be circumstances where C is the right language
    even though code efficiency is irrelevant - but for most code for which
    C is the best choice, efficiency of the results is important.


    OTOH, people do not want to drop all features. And concerning
    gcc, AFAIK is is actually a compromise for good reason. Some
    other projects are slow and bloated apparenty for no good
    reason. Some time ago I found a text about Netscape mail
    index file. The author (IIRC Jame Zawinsky) explained how
    it fastures ensured small size and fast loading. But in
    later developement it was replaced by some generic DB-like
    solution leadind to huge slowdown and much higher space
    use (apparently new developers were not willing to spent
    a litte time to learn how old code worked). And similar
    examples are quite common.

    And concerning compiler size, I do not know if GCC/clang
    developers care. But cleary Debian developers care,
    they use shared libraries, split debug info to separate
    packages and similar to reduce size.


    The more a program is used, the more important its efficiency is. Yes,
    gcc and clang/llvm developers care about speed. (They don't care much
    about disk space. Few users are bothered about $0.10 worth of disk space.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Thu Dec 5 17:42:01 2024
    On 05/12/2024 15:46, David Brown wrote:
    On 05/12/2024 04:11, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 04/12/2024 16:09, Bart wrote:
    On 04/12/2024 09:02, David Brown wrote:
    On 03/12/2024 19:42, Bart wrote:

    Yesterday you tried to give the misleading impression that compiling a >>>> substantial 200Kloc project only took 1-3 seconds with gcc.


    No, I did not.  I said my builds of that project typically take 1-3
    seconds.  I believe I was quite clear on the matter.

    Without word "make" it was not clear if you mean full build (say
    after checkout from repository).  Frequently people talk about re-making
    when they mean running make after a small edit and reserve build
    for full build.  So it was not clear if you claim to have a compile
    farm with few hundred cores (so you can compile all files in parallel).

    I talk about "building" a project when I build the project - produce the relevant output files (typically executables of some sort, appropriately post-processed).

    If I wanted to say a "full clean build", I'd say that.  If I wanted to include the time taken to check out the code from a repository, or to download and install the toolchain, or install the OS on the host PC,
    I'd say that.

    When I am working with code, I edit some files.  Then I build the
    project.  Sometimes I simply want to do the build - to check for static errors, to see the size of code and data (as my targets are usually
    resource limited), etc.  Sometimes I want to download it to the target
    and test it or debug it.

    /Why/ would anyone want to do a full clean build of their project?

    Suppose your full clean build took, if not 0 seconds, but as close as
    made no difference. WHY would you waste time mucking with partial builds?


    Bart is not interested in how much time it takes for people to build
    their projects.  He is interested in "proving" that his tools are
    superior because he can run gcc much more slowly than his tools.

    It IS slower. And mine isn't the fastest either. On one test from 3-4
    years ago spanning 30-40 language implementatations, there was about
    3000:1 between fastest and slowest expressed as Kloc/sec. My two
    languages were 8 and 4 times slower than the fastest.

    On another more substantial test, the difference was 80000:1 (the slow
    product then - not gcc - has since gotten much better).

    gcc's -O0 and -O3 timings tended to somewhere be in the middle.

    Such tests may expose weaknesses in these compilers that are worth
    looking at. It certainly did in mine.

      He
    wants to be able to justify his primitive builds by showing that his
    tools are so fast that he doesn't need build tools or project
    management.  (He is wrong on all that, of course - build tools and
    project management is not just about choosing when you need to compile a file.)

    You keep saying I'm wrong; I don't often say that you're wrong, but here
    you are because you keep choosing to disregard certain facts.

    One is that a make system DOES do multiple things, but one of those IS
    applying dependency info to decide which modules to incrementally
    compile, when is then linked with existing object files into a binary.

    THIS is exactly what my whole-program compiler takes care of. It doesn't eliminate everything else a make system does, but I don't make use of
    those myself.

    Another is that you refuse to acknowledge genuine use-cases for fast C compilers. A big one is when C is used an intermediate language for a
    compiler. Then it just wants as fast a translation into runnable code as possible. It doesn't need detailed analysis of the C code.

    It would also be nice for that compiler to be simple enough to bundle as
    part of the app. That is not really practical to do with gcc if your
    intention is a reasonably small and tidy implementation, apart from
    edit-run cycles being dominated by the slowness of gcc in producing even indifferent code.

    Such intermediate C may present challenges: it might be very busy. It
    might be generated as one C source file. That shouldn't matter.

    But you seem to be blind to these possibilties, and stubbornly refuse to
    admit that a product like tcc may actually be a good fit here.

    Some options for a backend for a new language might be to interpret the
    result, but even tcc's terrible mcode would run a magnitude faster at least.

      Thus he also insists on single-threaded builds - compiling one
    file at a time, so that he can come up with huge times for running gcc
    on lots of files.  This is, of course, madness - multi-core machines
    have been the norm for a couple of decades.  My cheap work PC has 14
    cores and 20 threads - I'd be insane to compile one file at a time
    instead of 20 files at a time.

    What about someone whose workload is 10 times yours? Their builds will
    take 10 times as long on the same machine. They would be helped by
    faster compilers.

    BTW nothings stops my compiler being run on multiple cores too. I assume
    that is a function of your 'make' program?

    However the non-C one would need to build multiple executables, not
    object files. As a whole-program compiller can't easily be split into
    parallel tasks.

    So I'm looking only at raw compilation speed on one core.

    Car analogy: if you were developing a fast car, and wanted one that
    could do 200 miles in one hour, using 10 different cars each travelling
    at 20mph along a different segment of the route wouldn't be what most
    people had in mind.

    The more a program is used, the more important its efficiency is.  Yes,
    gcc and clang/llvm developers care about speed.  (They don't care much
    about disk space.

    Ha!

      Few users are bothered about $0.10 worth of disk space.)

    And again you fail to get point. Disk space could be free, but that
    doesn't mean a 1GB or 10GB executable is desirable. It would just be
    slow and cumbersome.

    Car analogy #2: supposed a 40-tonne truck cost the same as 1-tonne car.
    Which do you think would be quicker to drive to the supermarket and back?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Thu Dec 5 18:30:20 2024
    Bart <bc@freeuk.com> writes:
    On 05/12/2024 15:46, David Brown wrote:
    On 05/12/2024 04:11, Waldek Hebisch wrote:

      Few users are bothered about $0.10 worth of disk space.)

    And again you fail to get point. Disk space could be free, but that
    doesn't mean a 1GB or 10GB executable is desirable. It would just be
    slow and cumbersome.

    Given that all modern systems load text and data pages from the executable dynamically on the first reference[*], I don't see how executable
    size (much of which is debug and linker metadata such as
    symbol tables) matters at all. Modern SSD's can move data at
    better than 1GB/sec, so 'slow' isn't correct either.

    [*] possibly in clusters, possibly in anticipation.

    $ size bin/sim
    text data bss dec hex filename
    6701963 85728 1861648 8649339 83fa7b bin/sim
    $ ls -l bin/sim
    -rwxr-xr-x 1 user group 7289816 Dec 4 16:48 bin/sim

    Nowhere even near 1GB, even if all the shared objects
    that it is linked to are included (excluding third-party
    shared objects such as libc and others provided by
    the implementation).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Thu Dec 5 19:27:36 2024
    On 05/12/2024 18:30, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 05/12/2024 15:46, David Brown wrote:
    On 05/12/2024 04:11, Waldek Hebisch wrote:

      Few users are bothered about $0.10 worth of disk space.)

    And again you fail to get point. Disk space could be free, but that
    doesn't mean a 1GB or 10GB executable is desirable. It would just be
    slow and cumbersome.

    Given that all modern systems load text and data pages from the executable dynamically on the first reference[*], I don't see how executable
    size (much of which is debug and linker metadata such as
    symbol tables) matters at all. Modern SSD's can move data at
    better than 1GB/sec, so 'slow' isn't correct either.


    So what the hell IS slowing down your build then?

    Since converting C code to native code is something that can be done at 10MB/sec per core. Is your final binary 36GB?

    The whole matter is confusing to me. David Brown says that build speed
    is no problem at all, as it's only a second or two. You post figures of
    13 MINUTES. Which is really an hour on one core.

    Meanwhile DB later admits real clean build times of nearly 3 minutes for
    one core.

    So what I see is that compile times better could be much better but no
    one wants to admit it. Instead people mitigate those times by using
    parallel builds, or being cage about how much they care compiling.

    Effectively brushing the matter under the carpet. I suspect that few
    here want to admit that a fast, streamlined compiler might actually be
    useful!

    BTW you can run a ten-time-faster compiler AND use parallel builds; have
    you thought of that?

    And if tcc can't manage, is there nobody capable of making gcc etc
    faster, or is it just too big a project to streamline?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Thu Dec 5 20:21:35 2024
    Bart <bc@freeuk.com> writes:
    On 05/12/2024 18:30, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 05/12/2024 15:46, David Brown wrote:
    On 05/12/2024 04:11, Waldek Hebisch wrote:

      Few users are bothered about $0.10 worth of disk space.)

    And again you fail to get point. Disk space could be free, but that
    doesn't mean a 1GB or 10GB executable is desirable. It would just be
    slow and cumbersome.

    Given that all modern systems load text and data pages from the executable >> dynamically on the first reference[*], I don't see how executable
    size (much of which is debug and linker metadata such as
    symbol tables) matters at all. Modern SSD's can move data at
    better than 1GB/sec, so 'slow' isn't correct either.


    So what the hell IS slowing down your build then?

    Why do you care? The application size - 2000+ source
    files generating several executables, user documentation
    (troff based) and dozens of shared objects (DLL for
    windoze users) explains the build time. About half
    of the C++ headers are generated based on YAML sources,
    some of them are extremely large (100000+ lines).

    I just did a full build of one of my "toy" projects
    (a mainframe simulator analogous to Hercules) and
    it completed in less than 6 seconds with -j6

    ...
    g++ -g -I../include -I.. -mno-red-zone -fno-strict-aliasing -fno-stack-protector -fno-exceptions -Wall -mtune=native -O2 -c -MMD -o digits.o digits.cpp
    ar cr ../lib/libprocessor.a system.o blt.o memory.o processor.o processor_rd.o index_register.o operand.o misc_ops.o arith_ops.o compare_ops.o branch_ops.o move_ops.o search_ops.o omega_ops.o hardware_call.o time_ops.o environment.o environment_table.o
    kernel_data_area.o ../io/dlps/iocb.o float.o mop.o toggles.o intflags.o digits.o add.o sub.o op_acm.o op_add.o op_and.o op_asp.o op_ate.o op_b2d.o op_bct.o op_brt.o op_brv.o op_brv_reva.o op_bst.o op_cio.o op_cio_reva.o op_cpn.o op_cps.o op_d2b.o op_dec.
    o op_edt.o op_ext.o op_hbk.o op_hbr.o op_hcl.o op_hsh.o op_iad.o op_ias.o op_idl.o op_iio.o op_ild.o op_ils.o op_imi.o op_ims.o op_imu.o op_inc.o op_ioc.o op_ioc_reva.o op_ipc.o op_iss.o op_ist.o op_isu.o op_ker.o op_lix.o op_lok.o op_mls.o op_mop.o op_
    mvc.o op_mvd.o op_mvl.o op_mvr.o op_mvs.o op_mvw.o op_not.o op_ntr.o op_orr.o op_piq.o op_raa.o op_rad.o op_ras.o op_rds.o op_rdt.o op_rdv.o op_ret.o op_rld.o op_rms.o op_rmu.o op_rss.o op_rst.o op_rsu.o op_sde.o op_sea.o op_six.o op_sll.o op_slt.o op_
    smf.o op_spio.o op_sst.o op_srd.o op_stb.o op_stt.o op_sub.o op_sze.o op_trn.o op_tst.o op_ven.o op_whr.o
    make[1]: Leaving directory `/work/ws/vsim/20220509/vsim/processor'
    COMPILE main.cpp
    g++ -g -I./include -I. -mno-red-zone -fno-strict-aliasing -fno-stack-protector -fno-exceptions -Wall -mtune=native -O2 -c -MMD -o main.o main.cpp
    g++ -g -Wl,-E -o vsim main.o ./lib/libmp.a ./lib/libprocessor.a ./lib/libcommon.a -lreadline -lcurses -lpthread -lgmp -ldl
    /bin/true --only-keep-debug vsim vsim.debuginfo
    /bin/true --strip-debug vsim
    /bin/true --add-gnu-debuglink=vsim.debuginfo vsim

    real 0m5.96s
    user 0m28.35s
    sys 0m3.89s

    SLOC Directory SLOC-by-Language (Sorted)
    18670 utilities cpp=16393,ansic=1943,sh=334
    14217 io cpp=14217
    12093 processor cpp=12093
    8054 common cpp=8054
    4513 include cpp=3521,ansic=992
    2675 mp cpp=2675
    1566 data cobol=1440,tcl=126
    678 notes ansic=456,cpp=222
    228 tests ansic=227,sh=1
    156 top_dir cpp=156
    89 pkg sh=89
    0 docs (none)
    0 lib (none)
    0 tapes (none)


    Totals grouped by language (dominant language first):
    cpp: 57331 (91.09%)
    ansic: 3618 (5.75%)
    cobol: 1440 (2.29%)
    sh: 424 (0.67%)
    tcl: 126 (0.20%)

    The real-world application is orders of magnitude
    larger.


    Since converting C code to native code is something that can be done at >10MB/sec per core. Is your final binary 36GB?

    Of course not, I posted the size, it's 7MB.



    The whole matter is confusing to me. David Brown says that build speed
    is no problem at all, as it's only a second or two. You post figures of
    13 MINUTES. Which is really an hour on one core.

    Guess what, David and I working on different applications with different requirements. One of his requirements limits the size of the application
    so that it will fit in the flash/eeprom/ROM available. My requirements
    lead to a much larger application.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Bart on Thu Dec 5 12:39:18 2024
    Bart <bc@freeuk.com> writes:

    If I say I find these quirks of C confusing, people will have
    another go at me.

    People object not because you say some parts of C are confusing but
    because you make them out to be more confusing than they are. These
    things are not that hard to understand. No one has any doubt that
    you could understand them if you made any sort of effort, but you
    don't even try. All you do is complain. If you took even one tenth
    the time you spend complaining on learning how things work then you
    would understand them and could usefully spend the leftover time
    doing something of value. As it is you do nothing but waste
    everyone's time, including your own.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Scott Lurndal on Thu Dec 5 22:30:55 2024
    On Thu, 05 Dec 2024 15:43:39 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:


    Sounds like you can benefit both from faster compiler and from faster
    make utility.

    Perhaps, but 28 seconds isn't really that bad. Particularly compared
    with the systems I used forty years ago :-)


    It is pretty bad. Breaks flow of thought.

    <snip linker>


    BTW, can you experiment with -O0 ? What speedup does it provide over
    -O2 in the project as big as yours?

    We typically use -O3, except on a couple of source files which
    take over 6 minutes of CPU time to compile, each, when -O3 is
    specified.


    For project of that size, I'd say that there is 80% chance that result
    of compilation with -O3 is slower than -O2.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Thu Dec 5 21:46:15 2024
    On 05/12/2024 20:21, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:


    Since converting C code to native code is something that can be done at
    10MB/sec per core. Is your final binary 36GB?

    Of course not, I posted the size, it's 7MB.

    You posted a 7MB size (and an 8MB one), in a post about hypothetical
    1-10GB executables. I didn't realise it was the size of the project that
    took 1 hour of CPU time to build.

    So that's about 2KB/second of CPU time.

    This is about half the speed of my first assembler, that ran on a 2.5MHz
    8-bit processor in 16KB, which could translate assembly to binary at
    about 4KB/second.

    I can't say I'm impressed. Oh, I forgot: you're using 6 cores, to
    effectively achieve 9KB/second. I reckon you could write the output to
    floppy disk, without impacting those 13 minutes too much! Somebody would
    have to keep switching disks though.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Tim Rentsch on Thu Dec 5 21:34:53 2024
    On 05/12/2024 20:39, Tim Rentsch wrote:
    Bart <bc@freeuk.com> writes:

    If I say I find these quirks of C confusing, people will have
    another go at me.

    People object not because you say some parts of C are confusing but
    because you make them out to be more confusing than they are. These
    things are not that hard to understand. No one has any doubt that
    you could understand them if you made any sort of effort, but you
    don't even try. All you do is complain. If you took even one tenth
    the time you spend complaining on learning how things work then you
    would understand them and could usefully spend the leftover time
    doing something of value. As it is you do nothing but waste
    everyone's time, including your own.

    This is a discussion of language design. Not one person trying to
    understand how some feature works. I could learn how X works, but that
    won't help a million others with the same issue.

    I used to write applications. If users said that some things were hard
    to do, I would take that on board, and strive to make them easier, or
    revise the manual to take account of what people had trouble with.

    I wouldn't insult.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Bart on Thu Dec 5 21:55:40 2024
    Bart <bc@freeuk.com> writes:
    On 05/12/2024 20:21, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:


    Since converting C code to native code is something that can be done at
    10MB/sec per core. Is your final binary 36GB?

    Of course not, I posted the size, it's 7MB.

    You posted a 7MB size (and an 8MB one), in a post about hypothetical
    1-10GB executables. I didn't realise it was the size of the project that
    took 1 hour of CPU time to build.

    So that's about 2KB/second of CPU time.

    That is a completely meaningless metric.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Fri Dec 6 00:41:05 2024
    On 05/12/2024 21:55, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:
    On 05/12/2024 20:21, Scott Lurndal wrote:
    Bart <bc@freeuk.com> writes:


    Since converting C code to native code is something that can be done at >>>> 10MB/sec per core. Is your final binary 36GB?

    Of course not, I posted the size, it's 7MB.

    You posted a 7MB size (and an 8MB one), in a post about hypothetical
    1-10GB executables. I didn't realise it was the size of the project that
    took 1 hour of CPU time to build.

    So that's about 2KB/second of CPU time.

    That is a completely meaningless metric.


    Are the figures accurate? If you spend an hour of CPU time and the
    output is a 7MB file, then it /is/ generating 2KB/cpu-second.

    On x64, 7MB of instructions (I don't know the machine of the balance of
    code and data), is very roughly 700Kloc for a language like C. That
    would make the throughput 200 source lines per cpu-second if it was all C.

    Then means it's spending at least 99.9% of the CPU-time doing something
    other than basic C to native code compilation.

    However, you seem happy enough with the process, and don't seem inclined
    to question it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Fri Dec 6 01:20:17 2024
    On 06/12/2024 00:50, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    This is a discussion of language design. Not one person trying to
    understand how some feature works. I could learn how X works, but that
    won't help a million others with the same issue.

    That's great, if there are a million other users who are confused
    about the same things you claim to be confused about, and if you're
    actually trying to help them.

    Except for a couple of things.

    I don't believe there are "a million other users" who are confused
    about, to use a recent example, C's rules about whether a "}" needs
    to be followed by a semicolon. I've seen code with extraneous
    semicolons at file scope, and I mostly blame gcc's lax default
    behavior for that. But I've never heard anyone other than you
    complain about C's rules being intolerably inconsistent.

    And even if those users exist, I don't see you making any effort
    to help them, for example by explaining how C actually works.
    (Though you do manage to provoke some of us into doing that for you.)


    You really think I'm a beginner stumped on some vital question of
    whether I should or should not have use a semicolon in a program I'm
    writing?

    I said I wouldn't be able explain the rules. Otherwise I stumble along
    like everyone else.

    If I catch sight of this at the top of my screen window:

    -------------------------
    }

    ....

    is that } ending some compound statement, or is it missing a ";" because
    it's initialising some data? Or (if I know I'm outside a function), is
    it the end of function definition?

    I wouldn't be stumped for long, but it strikes me as odd that you can't
    tell just by looking.

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that possible?

    Again if you only caught a glimpse like this:

    ----------------
    while (cond);

    then /probably/ it is the last line of a do-while, but it could also
    legally be a while loop with an empty body. (Maybe temporarily empty, or
    the ; is a mistake.)

    How about this:

    do
    {
    ....
    }
    while cond();

    A do-while, but comment out the 'do', and it's a compound statement
    followed by a while loop

    This duality of 'while' bothers me.

    (I can't have repeat-while in my syntax because it doesn't work; 'while'
    is always the start of a new while-loop. So I'm interested in how C
    manages it. But it looks fragile.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Opus@21:1/5 to Bart on Fri Dec 6 02:39:22 2024
    On 04/12/2024 22:01, Bart wrote:
    On 04/12/2024 19:47, Janis Papanagnou wrote:
    On 04.12.2024 13:08, David Brown wrote:

    Sure.  And it is certainly /possible/ to know all the small details of C >>> without ever reading the standards.  But it's quite unlikely.

    The question is (IMO) not so much to know "all" and even "all small"
    details. Even in a language like "C" (that I'd consider to be fairly
    incoherent if compared to other languages' design) you can get all
    "important" language properties (including details) from textbooks.

    If cases where that is different, the standards documents - which
    have their very own special way of being written - would be even
    less comprehensibly as they (inherently) already are. - That said
    from a programmer's POV (not from the language implementors').

    I look into language standards only if I want to confirm/falsify
    an implementation; in this case I'm taking the role of a language
    implementor (not a programmer). Personally I do that anyway only
    rarely, for specific languages only, and just out of academical
    interest.

    [...]
    Bart is an expert at thinking up things in C that confuse him.

    Well, that's an own topic. - Where I was really astonished was the
    statement of being confused about the braces/semicolons, which is
    so fundamental (and primitive) but technically just a detail that
    I'd thought it should be clear


    OK, if it's so simple, explain it to me.

    Apparently the first line here needs a semicolon after }, the second
    doesn't:

      int X[1] = {0};
      void Y() {}

    Similarly here:

      if (x) y;
      if (x) {}

    Why?

    "Because that's what the grammar says" isn't a valid answer.

    The C language is one of the most quirky ones around full of apparently ridiculous things. Why shouldn't you be able to write this for example:

       {
       ....
       L:
       }

    This stupid rule means that EVERY label in my generated code needs to be written as L:; instead of just L:

    Please don't say the label is only defined to be a prefix to another statement. I asking why it was done like that.

    - It's reasonable not to require a semicolon (which is a statement
    termination) to terminate a statement block, which is terminated by the
    closing brace. A semicolon would be redundant.

    - For labels, I agree, but the deeper issue is not that; it's to have
    goto's when better constructs would be the fix.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Fri Dec 6 11:34:11 2024
    On 06/12/2024 02:10, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    while cond();

    A do-while, but comment out the 'do', and it's a compound statement
    followed by a while loop

    You forgot the parentheses around the condition.

    They're there, but in the wrong place.


    This duality of 'while' bothers me.

    Noted as yet another thing that bothers you.

    I take that nothing about C bothers you. Or that you keep it to yourself.

    Have you ever tried to design your own language? Then you might get more interested in these matters and might be more vocal about shortcomings
    in other languages.

    Can you explain briefly just what you're trying to accomplish here?

    Let me turn it around. What are you, or any of the regulars, doing here?

    It's incredibly rare that somebody new comes along with a fresh question
    about C. Few still use usenet. If you want to see actual beginner
    questions about C (and a hundred other matters that would be considered off-topic here), have a glance at a forum like Reddit. I expect there
    are many others.

    You'll be kept busy!

    Anyway, my question stands. Presumably you enjoy the higher level
    discussion about certain matters; so do I. But I also have to spend time battling endless personal attacks because I'm perceived as an upstart
    (even though I'm now receiving my state pension!).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Fri Dec 6 12:28:00 2024
    On 05/12/2024 14:45, Janis Papanagnou wrote:
    On 05.12.2024 12:54, Bart wrote:

    That's not going to happen, and it they are casual users of their
    compilers, they WILL write semicolons in the wrong place with no errors
    reported. Until it bites.

    Semicolons, really, are not the problem - AFAIR, in *none* of
    the languages I was engaged with.

    Not for me either, but for different reasons.

    The first few languages I wrote substantial code in (before I started
    doing my stuff) didn't use semicolons. (That is, Fortran, assembly and
    a machine-oriented language. Assembly did use semicolons for comments;
    that was no problem!)

    My languages require notional semicolon separators but generally you
    don't need to write them in source code.

    In a 37Kloc codebase in my syntax, I counted 67 semicolons. Mainly in
    the odd place I wrote multiple statements on one line.

    In a 39Kloc C codebase, there were 21,500 semicolons.

    This is generated C, so some of those may be following labels! 2000,
    actually, which still leaves 19,500; a lot of semicolons.

    On a preprocessed sql.c test (to remove comments) there were 53,000
    semicolons in 85,000 lines.

    So in C, they are a very big deal, occuring on every other line. The
    lines that don't have one, tend to end in {, or contain only }.

    Another interesting statistic: 98.5% of semicolons in generated code,
    and 94.5% of those in the sql test, coincident with end-of-line.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Fri Dec 6 16:41:34 2024
    On 05/12/2024 16:29, Bart wrote:
    On 05/12/2024 14:00, David Brown wrote:
    On 04/12/2024 22:31, Bart wrote:

    And while you are at it, buy a better screen.  You were apparently
    unable to read the bit where I said that /saving typing/ is a pathetic
    excuse.

    I can't type. It's not a bad excuse at all. I have also suffered from
    joint problems. (In the 1980s I was sometimes typing while wearing
    woolen gloves to lessen the impact. I haven't needed to now; maybe I've slowed down, but I do take more care.)

    Being unable to type, on its own, is not a good excuse - it's an
    essential skill for productive programmers. But having joint problems
    /is/ a good excuse. Three main ways of improving the situation would be getting a better keyboard (perhaps one of these with a split in the
    middle and more comfortable angles), using "stick keys" or other desktop
    tools to aid combination keys, and to use a good IDE and editor and a well-supported language that has structured scopes and identifiers, so
    that predictive input can significantly reduce the characters you have
    to type. The goal of that last part is to reduce the number of
    characters you have to type, rather than the number of characters in the
    source code.


    You said my namespaces were jumbled. They generally work as people
    expect, other than some different rules on name resolution.

    No, they work as /you/ expect.  Not "people".

    The concept is so simple that is not much about it for anyone to tweak.

    "Simple" does not equate to "matching expectations".


    A qualified name looks like this (this also applies to a single identifer):

      A.B.C

    'A' is a top-level name. It is this that the name-resolution in a
    language needs to identify.

    Presumably, in your C and C++ languages, all possible top-level names
    must be directly visible. Only in C++ with 'using namespace' does it
    allow a search for names not directly visible, by looking also in
    certain places.

    There are a variety of additional situations where namespaces and scopes
    are searched in C++. Some are fairly obvious - within a class method definition, other class members are directly visible. Others such as argument-dependent lookup involve some very complicated rules - I'd be surprised if anyone in comp.lang.c++ can give an accurate summary of
    them all without looking up references. (And for your own sanity, I'd
    advise against looking them up yourself!) Without a doubt, these would
    be tough to implement in a compiler. But the point of them is that, as
    far as possible, name lookup "just works" for the programmer as well as
    they might reasonably expect. "Matching expectation" and being
    convenient to the programmer in most cases is certainly /not/ simple.


    This is where the rules diverge a little from what I do. Given 'CHUMMY' modules X, Y, Z (which I deliberately choose), then each effectively
    includes 'using namespace' for each of the other two modules.


    And that's the key flaw. It is not what /I/ would expect, it's not what
    I think many other people would expect, and it is certainly not what I
    would want. If I am writing module X and I want to use symbol "foo"
    from module Y, then I expect to say explicitly that I am using module Y
    (via an "import" or "include" statement), and I expect to say explicitly
    that I want "foo" from module Y (as "Y.foo", "Y::foo", "using Y", "using Y.foo", "from foo import Y", or whatever suits the language).

    When I read a source file in any language, and I see the use of an
    identifier "foo", I want to know where that came from - I want to be
    able to find that out without doubt. If it is written "Y.foo", then
    there is no doubt. If I see "using Y.foo", there is no doubt - but I'd
    prefer that to be local to the function or block. If I see "using Y", I
    know it might be from Y or it might be local to module X, but at least
    it is not in Z or some other unmentioned file. If it is a symbol that
    is used a lot in the module, then maybe it worth a file-scope "using"
    statement of some kind - it will take more effort to figure out where it
    is from, but at least that knowledge will be re-used many times.

    What you have done here is taken something that was close to being very
    useful, and turned it into something that is even worse than C - at
    least in C you have the #include lines, and because everyone knows it
    doesn't have namespaces you often get a clue from identifier names with prefixes.

    You have snatched defeat from the jaws of victory in order to save a
    couple of lines at the start of each file - with the result that your
    language is only suitable for small single-developer programs.


    So my approach is a little more informal, and more convenient.

    "Informal" is a common theme for your language and your tools. And "convenient" means convenient for you alone, not other people, and
    certainly not other people working together. I suppose that is
    reasonable enough since you are the only one using your language and
    tools - why should you bother making something useful for people who
    will never use them? But this is a root cause of why no one thinks your language or your tools would be of any use to them - and why you get so
    much backlash when you try to claim that they are better than other
    languages or tools. Perhaps they are good for /you/, but not for anyone
    else.



      You designed the language for one person - you.  It would be
    extraordinary if it did not work the way /you/ expect!

    Yep. And yet, it is not some obscure, exotic monstrosity. It's not that different from most others, and it's not that hard to understand.

    It /is/ obscure and exotic. That's a given for a home-made one-person
    language - regardless of any similarities with existing languages.
    (Monstrosity or not is in the eye of the beholder.)


      That way they are influenced by lots of opinions, experiences,
    desires, and use-cases way beyond what any one person could ever have.

    A shame it didn't work for C!

    It did.


    So the way namespaces work in C++ is something that - by my rough
    finger-in-the-air estimates - dozens of people were involved in
    forming the plans, hundreds of people would have had a chance to
    comment and

    Yeah. Design-by-committee. Just about every feature of C++ is a dog's
    dinner of overblown, over-complex features. C++ doesn't do 'simple'.
    (Look at the 'byte' type for example; it's not just a name for 'u8'!)


    "Simple" is not a goal for a language. It is not helpful by itself. A
    Turing machine is one of the simplest computing systems around - no one
    would want to write code with that!

    C++ has a lot of complication. Some of it is intentional, and a lot of
    it is a by-product of backwards compatibility - new versions can't re-do
    things with a better syntax or through out old parts. (Remember, it's a
    real language - people can't just change the language and compiler when
    they want to write something a little differently in the source code.)

    And a lot of C++'s complexity is about making it easier to use for the
    majority of the code. Complicated template structures, rvalue
    references, and all the rest make it really difficult to make a good
    "vector" class. But they mean it is possible to make a good vector
    class that other programmers can use - and it is okay if the job is
    difficult for the library developer or other C++ expert if the result is
    that ordinary code can be relatively simple and efficient.

    I have a project where I have written a library for our card, while the customer writes the application, all in C++. In the library I have a
    set of template classes for use with IO pins, including multiple
    inheritance, "curiously recurring template pattern", inline variables,
    and lots of other "advanced" stuff. This all means that the guy writing
    the application code can write "led_red.on();" in a simple, clear manner
    and get the most efficient object code out of it.


    Of course a language that is made to work for a vast number of people
    and a vast range of uses is going to be sub-optimal and overly
    complicated for any given person or any given type of project. And it
    is entirely reasonable to say C++ is trying to do too much - it would be
    better to use different languages in different circumstances.

    But it is still better than a language that is suitable for one person
    and one type of project - unless you happen to be that one person doing
    that one type of project.

    That suggests that the ratio of people who expect identifiers from
    namespaces to require namespace qualification unless you /explicitly/
    request importing them into the current scope, compared to the people
    who expect namespaces to default to a jumble and overwhelm the current
    scope, is of the order of millions to one.

    They're not imported into the current scope, but an outer scope.

    That's not better.

    Anything with the same name in the current scope will shadow those imports.

    C and C++ both have block scopes, yes? So the potential is there for
    nested scopes dozens of levels deep.


    Yes.

    Yes - /sometimes/ file lookup uses some kind of path.  That happens
    for specific cases, using explicitly set path lists.  Who would be
    happy with an OS that when they tried to open a non-existent file
    "test.txt" from their current directory in an editor, the system
    searched the entire filesystem and all attached disks?  When you use
    the command "tcc", would you be happy with a random choice - or error
    message - because someone else put a different program called
    "tcc.exe" on a network drive somewhere?

    That's exactly how Windows works.

    No, it is not. You set PATH to the directories you want to use for
    binaries - the OS does not search the entire disk or random additional
    attached filesystems.

    I think Linux works like that too:
    since tcc.exe is not a local file, and it doesn't use a path, it uses
    special rules to locate it. Somebody could mess about with those rules.

    So, why don't you always have to type:

      /usr/bin/tcc.0.9.28/tcc             # or whatever

    instead of just 'tcc'?

    I explained that in the rest of my post.


    No, I don't agree with them.  Yes, it is your choice for your language.

    But you choose to talk about your language - so I can tell you why I
    think they are not good design choices.

    My design is to allow default 'using namespace'; see above.

    That's ... pretty much it.

    No, your design is to /force/ "using namespace" - whether the programmer
    wants it or not, and without the programmer even identifying the modules
    to import. It's your choice - but it's a bad choice.


    Your compiler and tcc don't reach ankle-level to gcc, clang or even MSVC

    That's good.

    I once had to build a garden gate for my house. I decided to make my
    own, and ended up with a 6' wooden gate which was exactly what I needed.

    If LLVM made gates, theirs would have been 9 miles high. A little
    unwieldy, and probably a hazard for air traffic.

    It doesn't show anything useful is possible.  No one else wants to
    compile the limited subset of C that you want,

    That's not true. Thiago Adams would find it useful for one. Obviously I do.

    Okay, "no one" is an exaggeration. Let's say, less than 0.001% of C programmers would find your tools useful for actually writing code in C
    (rather than for messing around with tools to see what they do).


    Anyone using C an intermediate language would do so. As would anyone
    writing C up to C99.

    nor do they want a C compiler written in some weird private language.

    Weird? There's a lot more weirdness in C!

    But it is not an alternative for other people.  It is not some kind of
    proof that compilers - real compilers for real work - don't have to be
    large.

    I suspect your prefered compilers wouldn't even run on a Cray-1 supercomputer, perhaps not even dozens of them.

    People using Cray-1 computers would have used serious Cray-1 compilers
    in those days. Since no one uses Cray-1 machines now, no modern
    compilers support them. So I really don't get your point. (I believe
    "Cray" is now part of HP, and pretty much all super-computers use gcc or clang/llvm for C these days.)


    Yet people /were/ running compilers for all sorts of languages on
    machines that weren't as powerful. Professional people writing
    professional software.

    You're effectively calling all those toys.


    No, I'm calling tcc and your compiler "toys". Long ago, people used
    simpler tools because simpler tools were all they had. Now we have
    better tools. People only write limited little non-optimising partial C compilers for fun, for learning, for experimentation, or for rare niche
    uses (such as to match their limited little cpu designs). Those are all
    good reasons for doing so. But if you want to develop a project in C
    with a view to producing executables that people will run, you don't use
    a toy when top-range tools are so easily available and do such a better job.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Fri Dec 6 18:49:50 2024
    On 05/12/2024 20:27, Bart wrote:

    Meanwhile DB later admits real clean build times of nearly 3 minutes for
    one core.

    Please don't write like that. You make it look like I was trying to
    hide things and then been forced to admit it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ike Naar@21:1/5 to Bart on Fri Dec 6 18:11:02 2024
    On 2024-12-04, Bart <bc@freeuk.com> wrote:
    The C language is one of the most quirky ones around full of apparently ridiculous things. Why shouldn't you be able to write this for example:

    {
    ....
    L:
    }

    This stupid rule means that EVERY label in my generated code needs to be written as L:; instead of just L:

    Not EVERY label; since you generate the code, you know when the label will be followed by a statement; in which case you don't need to write the semicolon.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Scott Lurndal on Fri Dec 6 19:04:00 2024
    On 04/12/2024 23:48, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 17:55, Scott Lurndal wrote:

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?


    That was a build that touched a key header file, so maybe
    85% full. A full build adds a minute or two wall time.

    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    That sounds like your dependency handling in make is not ideal. Store
    your dependencies in individual files per source file, where both the
    object file and the dependency file itself are dependent on the headers
    used by the C file. (The makefile should also have both the object file
    and the dependency file dependent on the C source file.)

    Thus your build only generates new dependency files when either the C
    source file changes, or any of the headers included (recursively) by
    that C file change. Change a C file, and it's dependencies will be re-calculated - but not the dependencies for anything else. Change a
    header, and you only need to re-calculate the dependencies for the
    source files that actually use it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Fri Dec 6 18:47:20 2024
    On 05/12/2024 18:42, Bart wrote:
    On 05/12/2024 15:46, David Brown wrote:
    On 05/12/2024 04:11, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 04/12/2024 16:09, Bart wrote:
    On 04/12/2024 09:02, David Brown wrote:
    On 03/12/2024 19:42, Bart wrote:

    Yesterday you tried to give the misleading impression that compiling a >>>>> substantial 200Kloc project only took 1-3 seconds with gcc.


    No, I did not.  I said my builds of that project typically take 1-3
    seconds.  I believe I was quite clear on the matter.

    Without word "make" it was not clear if you mean full build (say
    after checkout from repository).  Frequently people talk about re-making >>> when they mean running make after a small edit and reserve build
    for full build.  So it was not clear if you claim to have a compile
    farm with few hundred cores (so you can compile all files in parallel).

    I talk about "building" a project when I build the project - produce
    the relevant output files (typically executables of some sort,
    appropriately post-processed).

    If I wanted to say a "full clean build", I'd say that.  If I wanted to
    include the time taken to check out the code from a repository, or to
    download and install the toolchain, or install the OS on the host PC,
    I'd say that.

    When I am working with code, I edit some files.  Then I build the
    project.  Sometimes I simply want to do the build - to check for
    static errors, to see the size of code and data (as my targets are
    usually resource limited), etc.  Sometimes I want to download it to
    the target and test it or debug it.

    /Why/ would anyone want to do a full clean build of their project?

    Suppose your full clean build took, if not 0 seconds, but as close as
    made no difference. WHY would you waste time mucking with partial builds?


    As Tim said elsewhere, if things were different they wouldn't be the same.

    But I would still use "make" regardless of the speed of compilation.
    And I'd still set up my makefiles to compile files as needed, and not
    when not needed. And I'd still have makefiles that were safe for
    parallel compilation (though it's possible that I'd be lazy and type
    "make" instead of "make -j 20").

    How do I know I would do that? Because that is what I have done in the
    past. It's what I have been doing since I first started programming professionally. It's what I do for assembly projects (though it's a
    long time since I have done a pure assembly project). It's what I've
    done with small C projects that did not take more than a second or so
    for a full clean build.

    I think you have some bizarre idea that it is difficult to have a build
    tool that handles dependency-based compilation or parallel builds. It
    is not. It is a natural feature for pretty much any build tool.
    Optimising the build to get an absolute minimum of unnecessary
    compilations can be an effort, but a basic arrangement of re-compile if
    the C file changes or any header changes is peanuts.

    And I think you also misunderstand a major point of a build tool. It
    describes how the project is build - you use the build tool and its configuration to ensure that you can build the end product correctly, in
    a repeatable manner. Details vary according to need, but it might hold
    the source files, library information, compiler details, flags,
    pre-compilation requirements, post-compilation scripts, configure
    information, installation information, test cases, documentation builds,
    etc. For my work, I usually have very specific choices of the toolchain
    to use - that is detailed in the makefile, along with all the flags.
    After a build, I might take the executable and manipulate it (like
    adding checksums), rename it, pack it up or make it ready for a download
    tool. I might have build goals like "make download", "make test", "make debug", "make release". Putting all this kind of thing in a build tool
    is massively better than just documenting it somehow.

    So I'd use that "make" for all of that, totally regardless of how fast
    the compiler is.


    And I think you forget that for a great many people, the build tool is
    just their IDE. The use MSVC, or Eclipse, or whatever, and do their
    project setup with checkboxes and other options. Building is done by
    choosing "build" from the menu or using a shortcut key, and dependency
    handling is automatic. I prefer to keep my builds independent of any
    IDE, but that's my choice. For people using IDE's for project
    management, it is almost impossible to avoid dependency-based builds -
    you have to go out of your way to get full clean re-builds.

    (And the things I talk about with "make" can be done with cmake, ant,
    bake, or whatever build system you choose to use.)


    Bart is not interested in how much time it takes for people to build
    their projects.  He is interested in "proving" that his tools are
    superior because he can run gcc much more slowly than his tools.

    It IS slower. And mine isn't the fastest either. On one test from 3-4
    years ago spanning 30-40 language implementatations, there was about
    3000:1 between fastest and slowest expressed as Kloc/sec. My two
    languages were 8 and 4 times slower than the fastest.

    For a file that can be compiled by your tools, and also by gcc, then a
    your tool will compile it faster - I don't think anyone doubts that.
    But you put a great deal of effort into trying to show that /using/ gcc
    is slower for project builds - I have demonstrated that this is simply
    not the case. If gcc was as fast as your compiler, it would not
    appreciably change the typical build time for my development, and it
    would not change the way I work or the makefiles I use in any way.

    Please try to understand that.


      He wants to be able to justify his primitive builds by showing that
    his tools are so fast that he doesn't need build tools or project
    management.  (He is wrong on all that, of course - build tools and
    project management is not just about choosing when you need to compile
    a file.)

    You keep saying I'm wrong; I don't often say that you're wrong, but here
    you are because you keep choosing to disregard certain facts.

    You /are/ wrong here - see my explanation above.


    One is that a make system DOES do multiple things, but one of those IS applying dependency info to decide which modules to incrementally
    compile, when is then linked with existing object files into a binary.

    THIS is exactly what my whole-program compiler takes care of. It doesn't eliminate everything else a make system does, but I don't make use of
    those myself.

    Another is that you refuse to acknowledge genuine use-cases for fast C compilers.

    I have yet to see one of significance.

    A big one is when C is used an intermediate language for a
    compiler.

    Why would that be relevant? If you compile language X by first
    transpiling to C, then compiling C, then the time to compile language X
    is the sum of these. A fast or slow C compiler is no more and no less
    relevant here than if you were just compiling C.

    Then it just wants as fast a translation into runnable code as
    possible. It doesn't need detailed analysis of the C code.

    Of course it needs a detailed analysis of the C code if the result is
    intended to be efficient - that's part of the optimisation. And static
    error checking is close to free when you have optimisation enabled anyway.

    I can accept that you might not necessarily be as concerned about
    efficient resulting code. But I don't see any reason why you'd be more concerned about the speed of the C compiler here than you would when
    developing in C.


    It would also be nice for that compiler to be simple enough to bundle as
    part of the app. That is not really practical to do with gcc if your intention is a reasonably small and tidy implementation, apart from
    edit-run cycles being dominated by the slowness of gcc in producing even indifferent code.

    That depends on the application. You are unlikely to have interest in C
    as a scripting language for an application unless it was already a
    C-related application or a really big and powerful system where fast
    plugins are relevant. In those circumstances, you'd probably use the
    library versions of clang/llvm - making your big application bigger.
    (Or if the application was for a sensible OS, it would share an
    installation of the compiler with the rest of the system.) Applications
    that bundle languages for scripting mostly use something like Lua if
    they are small, Python or TCL if they are bigger.


    Such intermediate C may present challenges: it might be very busy. It
    might be generated as one C source file. That shouldn't matter.

    But you seem to be blind to these possibilties, and stubbornly refuse to admit that a product like tcc may actually be a good fit here.


    The discussion here, as I understand it, is primarily about C
    programmers developing programs in C. That is my focus.

    Some options for a backend for a new language might be to interpret the result, but even tcc's terrible mcode would run a magnitude faster at
    least.

      Thus he also insists on single-threaded builds - compiling one
    file at a time, so that he can come up with huge times for running gcc
    on lots of files.  This is, of course, madness - multi-core machines
    have been the norm for a couple of decades.  My cheap work PC has 14
    cores and 20 threads - I'd be insane to compile one file at a time
    instead of 20 files at a time.

    What about someone whose workload is 10 times yours? Their builds will
    take 10 times as long on the same machine. They would be helped by
    faster compilers.


    As I have repeated countless times, of course big builds go faster with
    faster compilers. That is not the point. The point is that development
    of C projects is rarely hampered by the speed of real C compilers.

    My typical builds are 2-3 seconds. If the project was ten times the
    size, typical builds would probably be around 5 seconds. I don't give a
    *beep* how long a full clean build would take, because I don't typically
    do full clean builds.

    If the project was a hundred times bigger, we would have a large
    department working on it at a time and would use distributed builds with
    a common big fast build server, and again the typical build times would
    be short.

    Other aspects of development - such as regression testing or
    simulations, or running extensive cross-module static checking, or
    building LTO links - can take a long time. Sometimes they can take
    /very/ long time. Sometimes you can alleviate that by spending enough
    money on hardware, sometimes even then it is still slow.

    But if your normal builds - the compilation parts - of C code are slow
    enough to be a hinder to your development, you are probably doing
    something wrong. And the solution is to look at what you are doing, and
    figure out how to fix it. Changing to crappy tools is not the answer.


    BTW nothings stops my compiler being run on multiple cores too. I assume
    that is a function of your 'make' program?

    It is a function of using any kind of build system worth its salt. And
    I would be surprised if your compiler couldn't be invoked multiple times simultaneously.


    However the non-C one would need to build multiple executables, not
    object files. As a whole-program compiller can't easily be split into parallel tasks.

    So I'm looking only at raw compilation speed on one core.


    And that is why you end up with meaningless results. You are comparing
    one car going at 200 mph with 1000 buses going at 20 mph when trying to evacuate a city in the path of a tornado. (Sorry, the car analogy is
    really breaking down here.)

    Car analogy: if you were developing a fast car, and wanted one that
    could do 200 miles in one hour, using 10 different cars each travelling
    at 20mph along a different segment of the route wouldn't be what most
    people had in mind.

    The more a program is used, the more important its efficiency is.
    Yes, gcc and clang/llvm developers care about speed.  (They don't care
    much about disk space.

    Ha!

      Few users are bothered about $0.10 worth of disk space.)

    And again you fail to get point. Disk space could be free, but that
    doesn't mean a 1GB or 10GB executable is desirable. It would just be
    slow and cumbersome.


    Get yourself a computer from this century.

    Car analogy #2: supposed a 40-tonne truck cost the same as 1-tonne car.
    Which do you think would be quicker to drive to the supermarket and back?


    In this analogy, gcc is the 40 tonne truck for the heavy work. The car
    to the supermarket is Python - that's good for the quick and simple work.

    There is no place where the home-made go-kart is useful, except perhaps
    for a fun and dangerous ride.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ike Naar@21:1/5 to Bart on Fri Dec 6 19:14:18 2024
    On 2024-12-06, Bart <bc@freeuk.com> wrote:
    My language:

    println =a,=b # 13 characters, 0 shifted

    (And that space is optional!) In C (assume the existence of stdio.h):

    printf("A=%lld B=%f\n",a,b); # ~28 characters, 8 shifted

    Enough said.

    Looks like a cherry-picked example.
    How would this (slightly modified) C statement be notated in your language:

    printf("a:%lld b:%g\n",a,b);

    ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Fri Dec 6 18:41:23 2024
    On 06/12/2024 15:41, David Brown wrote:
    On 05/12/2024 16:29, Bart wrote:
    On 05/12/2024 14:00, David Brown wrote:
    On 04/12/2024 22:31, Bart wrote:

    And while you are at it, buy a better screen.  You were apparently
    unable to read the bit where I said that /saving typing/ is a
    pathetic excuse.

    I can't type. It's not a bad excuse at all. I have also suffered from
    joint problems. (In the 1980s I was sometimes typing while wearing
    woolen gloves to lessen the impact. I haven't needed to now; maybe
    I've slowed down, but I do take more care.)

    Being unable to type, on its own, is not a good excuse - it's an
    essential skill for productive programmers.

    The goal of that last part is to reduce the number of
    characters you have to type, rather than the number of characters in the source code.

    My language:

    println =a,=b # 13 characters, 0 shifted

    (And that space is optional!) In C (assume the existence of stdio.h):

    printf("A=%lld B=%f\n",a,b); # ~28 characters, 8 shifted

    Enough said.

      If I am writing module X and I want to use symbol "foo"
    from module Y, then I expect to say explicitly that I am using module Y
    (via an "import" or "include" statement), and I expect to say explicitly
    that I want "foo" from module Y (as "Y.foo", "Y::foo", "using Y", "using Y.foo", "from foo import Y", or whatever suits the language).

    When I read a source file in any language, and I see the use of an
    identifier "foo", I want to know where that came from - I want to be
    able to find that out without doubt.  If it is written "Y.foo", then
    there is no doubt.  If I see "using Y.foo", there is no doubt - but I'd

    If you used my language, you can type Y.foo if you want. Nothing stops
    you doing that.

    And if you were using it, I can make the ability to omit 'Y.' optional.

    However, you'd need to get used to a language and compiler that is 'whole-program', with a slightly different approach


    You have snatched defeat from the jaws of victory in order to save a
    couple of lines at the start of each file - with the result that your language is only suitable for small single-developer programs.

    It is suitable for a vast number of programs. I'm sure it could be used
    for multi-developer projects too. After all, don't your projects also
    place all project-structure info into /one/ makefile? Which developer
    has editing rights on that file?

    Who decides what the modules are going to be? If one developer decided
    they need a new module, what is the procedure to get that added to the makefile?



    So my approach is a little more informal, and more convenient.

    "Informal" is a common theme for your language and your tools.

    Small, simple, easy, fast, effortless, informal, minimal dependencies, self-contained implementations. Yes, those are aim. And?

    I guess people still use manual screwdrivers instead of power tools?
    Your tools are magnitudes bigger in scope than a powered screwdriver.

    For wiring a plug etc, a power tool is over the top.



      And
    "convenient" means convenient for you alone, not other people, and
    certainly not other people working together.

    You're guessing.

      I suppose that is
    reasonable enough since you are the only one using your language and
    tools - why should you bother making something useful for people who
    will never use them?  But this is a root cause of why no one thinks your language or your tools would be of any use to them - and why you get so
    much backlash when you try to claim that they are better than other
    languages or tools.

    The design IS better in 100 ways, at least compared to C. Other modern,
    higher level languages have 100 things I don't have, don't understand,
    or would find impossible to use.

    However a language at the level of C still appears to be extremely
    popular. I guess people like something that is not so intimidating and
    that they can feel in command of.

    To that end, my language is still relevant. In any case, /I am not
    pushing my language/ or advocating people to ditch C in favour of it.
    Such a task would need to be done by someone else. I'm just using as an
    example of better design, one that as been proven in actual use.

    Actually, I get a kick out of using my private languages which fixes
    nearly everything I find annoying about C.

    And when I do write C, I also get a kick out of using my private C
    compiler, NOT written in C.

    Yep. And yet, it is not some obscure, exotic monstrosity. It's not
    that different from most others, and it's not that hard to understand.

    It /is/ obscure and exotic.

    I guess you haven't seen many exotic/esoteric languages.

    You once described my syntax as clean and easy to understand; what's
    changed?

    No, it is not.  You set PATH to the directories you want to use for
    binaries - the OS does not search the entire disk or random additional attached filesystems.

    PATH is a collection of paths that are searched in turn. There it will
    stop at the first match.

    That's similar to my list of modules that are searched in turn. There it
    will find all matches and report an ambiguity if more than one.

    However, my list is private to my project, while PATH is common to every command prompt and to whatever directory is current. Some programs could
    even manipulate the contents of PATH.


    No, your design is to /force/ "using namespace" - whether the programmer wants it or not, and without the programmer even identifying the modules
    to import.  It's your choice - but it's a bad choice.

    The programmer knows how the language works. They will have chosen the
    modules that are grouped together.

    The alternative is to have 50 modules of a project, where each module
    contains its own subset of 0 to 49 imports. That's up to 950 possible
    imports to maintain across up to 50 files. It sounds a maintenance
    nightmare. A dependency graph would need a pretty big sheet of paper!

    Would it even allow mutual imports? If not then that's another
    nightmare, which is likely to generate lots of extra dummy modules which
    only exist to get around the restriction.

    I'm sorry, but I tried such a scheme, and decided it was awful.



    No, I'm calling tcc and your compiler "toys".

    If something really criticial and imminent depended on your compiling
    and running some C code, and the only compiler to hand was tcc, then
    you'd use it! Either that or write some assembly or key in machine code.

    Then it's not a toy!

    But I'm curious now: would you call any bit of software a toy if it was
    only written with one client in mind?

    Or if it was a highly streamlined and dedicated version of a much
    larger, more general purpose program?

    Do you call the specialist compilers for some of your devices toys
    because they only support one target (and apparently badly sometimes)?

    What about assemblers: would you call a 100KB assembler a toy compared
    with 1MB or 2MB one? There's not much to assembling: if it does the job,
    then what would be toyish about it?

    How about linkers: I could likely write one in 100KB, which turns a
    bunch of .o/.obj files into a binary. What that be a toy?

    I'm really interested now. Those bigger products will have hundreds of
    options. So is it having lots of shiny buttons, and lots of things to
    learn, that would earn your respect, even though the task at hand is
    pretty trivial?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Ike Naar on Fri Dec 6 19:27:42 2024
    On 06/12/2024 19:14, Ike Naar wrote:
    On 2024-12-06, Bart <bc@freeuk.com> wrote:
    My language:

    println =a,=b # 13 characters, 0 shifted

    (And that space is optional!) In C (assume the existence of stdio.h):

    printf("A=%lld B=%f\n",a,b); # ~28 characters, 8 shifted

    Enough said.

    Looks like a cherry-picked example.
    How would this (slightly modified) C statement be notated in your language:

    printf("a:%lld b:%g\n",a,b);

    You mean, with those lower-case labels? Then I'd have to write it like this:

    fprintln "a:# b:#", a, b:"g"

    But I picked on Print because that is the most common temporary
    statement I use; it is written hundreds of times for debugging, but
    rarely persists.

    Then you rarely bother with formatting. With C however, all the T's and
    I's need to be crossed and dotted, even if the line will be deleted a
    minute later. A LOT of fiddly typing. Plus needing to be constantly
    aware of the exact types of the the things being printed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Fri Dec 6 19:20:47 2024
    On 06/12/2024 17:47, David Brown wrote:
    On 05/12/2024 18:42, Bart wrote:

    A big one is when C is used an intermediate language for a compiler.

    Why would that be relevant? If you compile language X by first
    transpiling to C, then compiling C, then the time to compile language X
    is the sum of these. A fast or slow C compiler is no more and no less
    relevant here than if you were just compiling C.

    You don't give do you?!

    If your task to get from A to B was split into two, you'd be happy to do
    the first part by a fast car, then complete the rest of it on a horse
    and cart, for no reason at all?

    After all the journey time is simply the sum of two halves!

    Obviously you'd want both halves to be done as quickly as possible.

    Compiler front-ends can be very fast, so you don't want to hit a brick
    wall on the backend. This is a common complaint of the LLVM backend
    which can take up 90% of compile-time.

    While people may want faster execution than is possibly with an
    interpreter, they don't necessarily need the fastest possible native
    code. ANY native code will be sufficient.

    With a C intermediate, using tcc for the final stage can easily give 10
    times faster throughput than using even gcc-O0.

    If one day they decide they need fast production version, THEN they pass
    it through gcc-O3.

    What IS your problem with that?

    Once the C-generation has been debugged, then there should be nothing
    wrong with the C code that requires detailed analysis.

    Your hatred of tcc (I won't even mention my stuff) is bordering on the irrational.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to David Brown on Fri Dec 6 22:26:54 2024
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 23:48, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 17:55, Scott Lurndal wrote:

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?


    That was a build that touched a key header file, so maybe
    85% full. A full build adds a minute or two wall time.

    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    That sounds like your dependency handling in make is not ideal. Store
    your dependencies in individual files per source file, where both the
    object file and the dependency file itself are dependent on the headers
    used by the C file. (The makefile should also have both the object file
    and the dependency file dependent on the C source file.)

    We use the standard makedepend support built into GCC. It creates
    a .d file for each source file that contains the dependencies
    for that source file.

    Scale matters, (with two thousand+ source and header files, that's a lot
    of 'access', 'read' and 'stat' system calls just to build the dependency
    graph. On NFS filesystems, which we use in most environments, the make
    takes even more time.

    Thus your build only generates new dependency files when either the C
    source file changes, or any of the headers included (recursively) by
    that C file change. Change a C file, and it's dependencies will be >re-calculated - but not the dependencies for anything else. Change a
    header, and you only need to re-calculate the dependencies for the
    source files that actually use it.


    In the case above, over 1000 source files were dependent upon that
    key project-wide header file which had been modified.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Ike Naar on Fri Dec 6 22:30:28 2024
    Ike Naar <ike@sdf.org> writes:
    On 2024-12-06, Bart <bc@freeuk.com> wrote:
    My language:

    println =a,=b # 13 characters, 0 shifted

    (And that space is optional!) In C (assume the existence of stdio.h):

    printf("A=%lld B=%f\n",a,b); # ~28 characters, 8 shifted

    Enough said.

    Looks like a cherry-picked example.
    How would this (slightly modified) C statement be notated in your language:

    printf("a:%lld b:%g\n",a,b);

    ?

    Or

    printf("a:%2$8.8lld b:%1$10.2g",b,a);

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Scott Lurndal on Sat Dec 7 00:30:34 2024
    On 06/12/2024 22:30, Scott Lurndal wrote:
    Ike Naar <ike@sdf.org> writes:
    On 2024-12-06, Bart <bc@freeuk.com> wrote:
    My language:

    println =a,=b # 13 characters, 0 shifted

    (And that space is optional!) In C (assume the existence of stdio.h):

    printf("A=%lld B=%f\n",a,b); # ~28 characters, 8 shifted

    Enough said.

    Looks like a cherry-picked example.
    How would this (slightly modified) C statement be notated in your language: >>
    printf("a:%lld b:%g\n",a,b);

    ?

    Or

    printf("a:%2$8.8lld b:%1$10.2g",b,a);

    In this case I'd just write it like this:

    printf("a:%2$8.8lld b:%1$10.2g",b,a)

    ie. calling printf via an FFI. It's marginally shorter than C since I
    don't need the semicolon.

    However, your attempt to catch me out on something I might not support
    has backfired, since it doesn't work even in C. This program:

    #include <stdio.h>
    int main(void) {
    long long a = 123456789876543210;
    double b=1.0/3;
    printf("a:%2$8.8lld b:%1$10.2g",b,a);
    }

    compiled with gcc 14.1 on Windows, produces:

    a:%2$8.8lld b:%1$10.2g

    On WSL and gcc 9.x it works, sort of. (Matching the label in the format
    string with the $ value and the argument looks confusing.)

    I'd typically do this stuff like this:

    const fmta = "8.8", fmtb = "10.2"

    fprint "a:# b:#", a:fmta, b:fmtb

    Here I don't need to care what the exact types of a and b are. I mean,
    what goes in place of ? here:

    printf("%?", a+b*c);

    Assume only that a, b, c are numeric types, which might be opaque types exported by some header.

    Here's another issue:

    #include <stdio.h>
    int main(void) {
    int i=0;
    printf("%d %d %d", ++i, ++i, ++i);
    }

    3 compilers give me output of 1,2,3; 3,2,1; and 3,3,3.

    If I do 'print ++i, ++i, ++i', it gives me 1,2,3 always. (Because this
    print is not a function call.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sat Dec 7 12:44:21 2024
    On 06.12.2024 13:28, Bart wrote:
    [...]

    The first few languages I wrote substantial code in (before I started
    doing my stuff) didn't use semicolons. (That is, Fortran, assembly and a machine-oriented language. Assembly did use semicolons for comments;
    that was no problem!)

    Re "Fortran" etc., see one of my recent posts about necessity
    of syntax, and depreciation and deprecation of other historic
    formating conventions that carried semantics.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sat Dec 7 12:34:51 2024
    On 06.12.2024 02:20, Bart wrote:
    On 06/12/2024 00:50, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    This is a discussion of language design. Not one person trying to
    understand how some feature works. I could learn how X works, but that
    won't help a million others with the same issue.

    That's great, if there are a million other users who are confused
    about the same things you claim to be confused about, and if you're
    actually trying to help them.

    Except for a couple of things.

    I don't believe there are "a million other users" who are confused
    about, to use a recent example, C's rules about whether a "}" needs
    to be followed by a semicolon. I've seen code with extraneous
    semicolons at file scope, and I mostly blame gcc's lax default
    behavior for that. But I've never heard anyone other than you
    complain about C's rules being intolerably inconsistent.

    And even if those users exist, I don't see you making any effort
    to help them, for example by explaining how C actually works.
    (Though you do manage to provoke some of us into doing that for you.)


    You really think I'm a beginner stumped on some vital question of
    whether I should or should not have use a semicolon in a program I'm
    writing?

    (Why are you making that up? - I see not one person here who would
    see you as beginner. - Although, to be honest, sometimes you behave
    like a restive beginner [unnecessarily], IMO.)


    I said I wouldn't be able explain the rules. Otherwise I stumble along
    like everyone else.

    If I catch sight of this at the top of my screen window:

    -------------------------
    }

    ....

    is that } ending some compound statement, or is it missing a ";" because
    it's initialising some data? Or (if I know I'm outside a function), is
    it the end of function definition?

    Now are you really saying that you are incapable of using an editor
    to get the context of a statement? - Amazing!

    If you see close to the end of a program

    -------------------------[screen boundary]
    return 0;
    }

    would you think that this program is doing nothing but exiting?

    (This sort of argumentation is really getting silly!)


    I wouldn't be stumped for long, but it strikes me as odd that you can't
    tell just by looking.

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that possible?

    A keyword (like 'while') is just a lexical token that can be used in
    different syntactical contexts. (Even with different semantics, if a
    language designer thinks this is a good idea for his case.)

    You may be less confused with using Pascal; it supports different
    keywords for these loops ('while' ... 'do' ...' and 'repeat' ...
    'until' ...), with complementary conditions, though.

    Generally there can be four types of such loops, where the test is
    either done at the beginning or at the end, and whether the condition
    is either positively or negatively formulated.
    while positive-case do ...
    until negative-case do ...
    do ... while positive-case
    do ... until negative-case
    (depending on language with this of similar syntax).

    There's nothing wrong using the same keyword for the same type of
    condition, rather it's good to have it defined that way.


    Again if you only caught a glimpse like this:

    ----------------
    while (cond);

    then /probably/ it is the last line of a do-while, but it could also
    legally be a while loop with an empty body. (Maybe temporarily empty, or
    the ; is a mistake.)

    ...and what do you do in that case? - You complain, you write longish
    posts, and so on. - Why not just position your code on your screen
    with the necessary context and go on. (In Vim that's one keystroke,
    and I suppose in most other editors as well. Or it's a simple mouse
    roll.)


    How about this:

    do
    {
    ....
    }
    while cond();

    A do-while, but comment out the 'do', and it's a compound statement
    followed by a while loop

    I find it more embarrassing that if you comment out _the whole loop_
    that the code *doesn't do anything* and more. </sarcasm>


    This duality of 'while' bothers me.

    Time (for you!) to write your own language.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Sat Dec 7 13:04:20 2024
    On 07/12/2024 11:34, Janis Papanagnou wrote:
    On 06.12.2024 02:20, Bart wrote:

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that possible?

    A keyword (like 'while') is just a lexical token that can be used in different syntactical contexts.

    Is it common to both start and end a statememt with the same keyword?


    (Even with different semantics, if a
    language designer thinks this is a good idea for his case.)

    You may be less confused with using Pascal;

    Now you are demonstrating my point about being treated like a beginner.
    And it is exasperating.

    This is a point of language design. C's approach works - just. But it
    relies on some subtlety. 'while (cond)' both starts a statement, and can
    end a statement:

    do while(cond) do ; while (cond);

    The second 'while' here starts a nested while-loop inside a do-while
    loop. Not confusing? It is to me! I couldn't finish my example as I got
    lost (but as it happens, this is valid code, partly by luck).

    Of course, if you put aside all other matters and concentrate on the
    minutiae of the syntax details, then it is all 'obvious'. I think it
    needs to be a lot more obvious.

    while positive-case do ...
    until negative-case do ...
    do ... while positive-case
    do ... until negative-case
    (depending on language with this of similar syntax).

    There's nothing wrong using the same keyword for the same type of
    condition, rather it's good to have it defined that way.

    The problem here is exactly the same: how do you tell whether the
    'while' in 'do ... while' is ending this 'do'-loop, or starting a nested while-loop?

    You don't think there is an element of ambiguity here?

    Let's take my example again:

    do while(cond) do ; while (cond);

    And make a small tweak:

    do ; while(cond) do ; while (cond);

    It still compiles, it is still valid code. But now it does something
    utterly different. (One is two nested loops, the other is two
    consecutive loops - I think!)

    OK, I get now that people just aren't that bothered about such matters.

    Obviously they aren't language designers.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Bart on Sat Dec 7 06:16:29 2024
    Bart <bc@freeuk.com> writes:

    On 04/12/2024 16:38, Tim Rentsch wrote:

    Ben Bacarisse <ben@bsb.me.uk> writes:

    Bart <bc@freeuk.com> writes:

    On 03/12/2024 11:15, Ben Bacarisse wrote:

    Bart <bc@freeuk.com> writes:
    ...

    If I write this

    int *A, B[10], C(int);

    My compiler tells me that:

    A is a local variable [...]
    B is a local variable [...]
    C is a function with return type of 'i32', taking one
    unnamed parameter of type 'i32'.

    (Interestingly, it places C into module scope, so the same
    declaration can also create names in different scopes!)

    That means your compiler is not compiling standard C. In standard C
    all entities declared locally have block scope, not file scope.

    OK, it can be added to the list of things that make C harder to
    compile.

    On the contrary, it makes C easier to compile, because there is no
    need to check for different cases. There is a single rule that
    applies to all local declarations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Bart on Sat Dec 7 06:51:28 2024
    Bart <bc@freeuk.com> writes:

    In a 39Kloc C codebase, there were 21,500 semicolons.

    This is generated C, so some of those may be following labels!
    2000, actually, which still leaves 19,500; a lot of semicolons.

    On a preprocessed sql.c test (to remove comments) there were
    53,000 semicolons in 85,000 lines.

    So in C, they are a very big deal, occuring on every other line.

    Many years ago I read a book called "How to Lie with Statistics".
    It should be updated to add this reporting as an example.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Bart on Sat Dec 7 06:38:52 2024
    Bart <bc@freeuk.com> writes:

    On 05/12/2024 20:39, Tim Rentsch wrote:

    Bart <bc@freeuk.com> writes:

    If I say I find these quirks of C confusing, people will have
    another go at me.

    People object not because you say some parts of C are confusing but
    because you make them out to be more confusing than they are. These
    things are not that hard to understand. No one has any doubt that
    you could understand them if you made any sort of effort, but you
    don't even try. All you do is complain. If you took even one tenth
    the time you spend complaining on learning how things work then you
    would understand them and could usefully spend the leftover time
    doing something of value. As it is you do nothing but waste
    everyone's time, including your own.

    This is a discussion of language design.

    No, it isn't. Your statement, and my response to it, are both about
    people's behavior. They are not about language design.

    I wouldn't insult.

    None of my statements was meant as an insult. They were meant
    simply as factual observations (or in some cases perhaps hypotheses,
    but in any case statements of fact, not judgments of character).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sat Dec 7 15:36:32 2024
    On 07.12.2024 14:04, Bart wrote:
    On 07/12/2024 11:34, Janis Papanagnou wrote:
    On 06.12.2024 02:20, Bart wrote:

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that
    possible?

    A keyword (like 'while') is just a lexical token that can be used in
    different syntactical contexts.

    Is it common to both start and end a statememt with the same keyword?

    It's at least nothing that surprises (or even annoys) me.



    (Even with different semantics, if a
    language designer thinks this is a good idea for his case.)

    You may be less confused with using Pascal;

    Now you are demonstrating my point about being treated like a beginner.
    And it is exasperating.

    If so then that was unintentionally. - My apologies! - It was merely
    meant as an example of a language that has chosen different keywords
    with complementary conditions, thus somewhat covering both options.
    Personally I'd have preferred to have all four variants (see below)
    available since often I needed a 'repeat' ... 'while' ... logic in
    my programs. (Which incidentally is what "C" supports.)

    So are you now saying that if "C" had 'while (...) ...' and also
    'do ... until (...)' that would not have solved your "problem" here?
    I thought it would have since you complained about a keyword used in
    two control constructs.


    This is a point of language design. C's approach works - just.

    Just fine, I'd say.

    But it relies on some subtlety.

    You seem to see ghosts. There's no subtlety; all is clearly defined,
    and it's a sensible feature, and consistently implemented.

    'while (cond)' both starts a statement, and can
    end a statement:

    do while(cond) do ; while (cond);

    What is this (IMO syntactical wrong "C" code) supposed to do or to
    explain?

    Did you maybe mean do while(cond) ; while (cond); which should
    of course be sensibly formatted to not confuse folks, as in

    do
    while (cond)
    ;
    while (cond);

    so that it's control-flow can easily be understood. If that is still
    confusing you could add braces.


    The second 'while' here starts a nested while-loop inside a do-while
    loop. Not confusing?

    Your (wrong) second 'do' was indeed confusing! - Why did you provide
    a wrong sample to confirm your wrong ideas? - Or is it just your well
    known habit to try to confuse other folks as well my making up stupid
    things?

    It is to me! I couldn't finish my example as I got
    lost (but as it happens, this is valid code, partly by luck).

    It produces errors if I compile your (wrong) code. - What do you thus
    mean by it being "valid code"?


    Of course, if you put aside all other matters and concentrate on the
    minutiae of the syntax details, then it is all 'obvious'. I think it
    needs to be a lot more obvious.

    Most here (and me too) already acknowledged that "C" is not obvious
    to you. (No there's no need to repeat and document that constantly.)


    while positive-case do ...
    until negative-case do ...
    do ... while positive-case
    do ... until negative-case
    (depending on language with this of similar syntax).

    There's nothing wrong using the same keyword for the same type of
    condition, rather it's good to have it defined that way.

    The problem here is exactly the same: how do you tell whether the
    'while' in 'do ... while' is ending this 'do'-loop, or starting a nested while-loop?

    That's called "[unambiguous] _Syntax_". - I don't know about "your
    languages", but all serious languages I know of have such syntaxes.
    And the programmers (of the respective various languages) I met had
    no problems understanding such syntaxes.

    (If you have a problem with perception it might be of help to use
    a pretty printer on "non-obvious" code. If it's rather a matter of understanding the concept then making yourself familiar with syntax
    is more appropriate; certainly better than posting your confusion
    repeatedly and spreading FUD [for potential newbies].)


    You don't think there is an element of ambiguity here?

    There isn't any.


    Let's take my example again:

    By repeating that it doesn't fix _your_ problem.


    do while(cond) do ; while (cond);

    And make a small tweak:

    do ; while(cond) do ; while (cond);

    It still compiles, it is still valid code.

    None of these two examples compile in my environment, and none looks
    like "valid code" to me. - There's a spurious 'do' as already said,
    or a missing ';', depending on the control-logic you intended...

    do while (cond) ; while (cond);

    do ; while (cond); do ; while (cond);

    Did you check that code maybe only (in "your language") with "your
    compiler"?

    But now it does something
    utterly different. (One is two nested loops, the other is two
    consecutive loops - I think!)

    OK, I get now that people just aren't that bothered about such matters.

    (You seem to be living in some parallel fantasy world.)


    Obviously they aren't language designers.

    Huh?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Bart on Sat Dec 7 14:57:17 2024
    On 07/12/2024 13:04, Bart wrote:
    On 07/12/2024 11:34, Janis Papanagnou wrote:
    On 06.12.2024 02:20, Bart wrote:

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that
    possible?

    A keyword (like 'while') is just a lexical token that can be used in
    different syntactical contexts.

    Is it common to both start and end a statememt with the same keyword?


     (Even with different semantics, if a
    language designer thinks this is a good idea for his case.)

    You may be less confused with using Pascal;

    Now you are demonstrating my point about being treated like a beginner.
    And it is exasperating.

    This is a point of language design. C's approach works - just. But it
    relies on some subtlety. 'while (cond)' both starts a statement, and can
    end a statement:

       do while(cond) do ; while (cond);

    The second 'while' here starts a nested while-loop inside a do-while
    loop. Not confusing? It is to me! I couldn't finish my example as I got
    lost (but as it happens, this is valid code, partly by luck).

    Of course, if you put aside all other matters and concentrate on the
    minutiae of the syntax details, then it is all 'obvious'. I think it
    needs to be a lot more obvious.

       while positive-case do ...
       until negative-case do ...
       do ... while positive-case
       do ... until negative-case
    (depending on language with this of similar syntax).

    There's nothing wrong using the same keyword for the same type of
    condition, rather it's good to have it defined that way.

    The problem here is exactly the same: how do you tell whether the
    'while' in 'do ... while' is ending this 'do'-loop, or starting a nested while-loop?

    You don't think there is an element of ambiguity here?

    Let's take my example again:

       do while(cond) do ; while (cond);

    And make a small tweak:

       do ; while(cond) do ; while (cond);

    It still compiles, it is still valid code. But now it does something
    utterly different. (One is two nested loops, the other is two
    consecutive loops - I think!)

    Correction: the versions I tested don't have that 'do' in the middle.
    The two examples need to be written like this to be valid:

    do while (cond) ; while (cond);
    do ; while (cond) ; while (cond);

    So this /is/ two nested loops followed by two consecutive ones. The
    difference is that semicolon.

    In a syntax where newlines may be injecting semicolons, such a subtle distinction is not strong enough. As I originally said, it's fragile.

    Those suggesting that semicolons are unimportant details of syntax in C
    are wrong. They can make a significant difference and contribute to errors:

    for (i=0; i<n; ++i);
    printf("%d\n", i);

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Bart on Sat Dec 7 07:00:44 2024
    Bart <bc@freeuk.com> writes:

    But I also have to spend time battling endless personal attacks
    because I'm perceived as an upstart (even though I'm now receiving
    my state pension!).

    Dictionaries describe upstarts as people who are full of themselves
    and dismissive of others. So if you are perceived as an upstart,
    it's because you are one.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Sat Dec 7 16:28:24 2024
    On 07.12.2024 16:19, Janis Papanagnou wrote:
    On 07.12.2024 15:57, Bart wrote:
    The two examples need to be written like this to be valid:

    do while (cond) ; while (cond);
    do ; while (cond) ; while (cond);

    So this /is/ two nested loops followed by two consecutive ones. The
    difference is that semicolon.

    Someone here already called things like that as "condensed" (or some
    such), meaning that syntax is strict and has few redundancies; small
    changes are meaningful and relevant. (Nothing for sloppy hackers, for
    sure.)

    [...]

    Those suggesting that semicolons are unimportant details of syntax in C
    are wrong. [...]

    I don't recall; who said that?

    Ah, wait. - You might again be confusing things...

    There was discussion of semicolons being a separator in some languages
    and a terminator in other languages. Which is a comparably unimportant
    language design choice. - But once you choose one language or another,
    you have to strictly follow its chosen syntactical rules, of course.
    Do you understand that?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Sat Dec 7 16:19:35 2024
    On 07.12.2024 15:57, Bart wrote:
    The two examples need to be written like this to be valid:

    do while (cond) ; while (cond);
    do ; while (cond) ; while (cond);

    So this /is/ two nested loops followed by two consecutive ones. The difference is that semicolon.

    Someone here already called things like that as "condensed" (or some
    such), meaning that syntax is strict and has few redundancies; small
    changes are meaningful and relevant. (Nothing for sloppy hackers, for
    sure.)

    [...]

    Those suggesting that semicolons are unimportant details of syntax in C
    are wrong. [...]

    I don't recall; who said that?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sat Dec 7 16:57:11 2024
    On 06/12/2024 19:41, Bart wrote:
    On 06/12/2024 15:41, David Brown wrote:
    On 05/12/2024 16:29, Bart wrote:
    On 05/12/2024 14:00, David Brown wrote:
    On 04/12/2024 22:31, Bart wrote:

    And while you are at it, buy a better screen.  You were apparently
    unable to read the bit where I said that /saving typing/ is a
    pathetic excuse.

    I can't type. It's not a bad excuse at all. I have also suffered from
    joint problems. (In the 1980s I was sometimes typing while wearing
    woolen gloves to lessen the impact. I haven't needed to now; maybe
    I've slowed down, but I do take more care.)

    Being unable to type, on its own, is not a good excuse - it's an
    essential skill for productive programmers.

    The goal of that last part is to reduce the number of characters you
    have to type, rather than the number of characters in the source code.

    My language:

      println =a,=b                  # 13 characters, 0 shifted


    Since some of us live in a world with more than one person - indeed,
    more than one country - you might like to know that "=" is shifted on
    many keyboards.

    (And that space is optional!)

    The biggest irritation I have with your style, whether in your language
    or in C, is the lack of space. It's a big key - it's easy to press.
    Good spacing habits (in the broadest sense) is the single biggest factor
    to readability of code, text, hand-writing, and pretty much anything else.

    The language Forth is not known for being easy to read amongst
    non-experts, but one thing it gets right is insisting that there are
    spaces between tokens.

    In C (assume the existence of stdio.h):

      printf("A=%lld B=%f\n",a,b);   # ~28 characters, 8 shifted

    Enough said.

    I don't know what you are getting at, so I don't know if enough has been
    said or not. If you are trying to suggest that the only thing you think
    is important about language syntax is how you print out two variables in
    as few keystrokes as possible, then I suppose you have succeeded in that
    goal, and can therefore rest your case.


      If I am writing module X and I want to use symbol "foo" from module
    Y, then I expect to say explicitly that I am using module Y (via an
    "import" or "include" statement), and I expect to say explicitly that
    I want "foo" from module Y (as "Y.foo", "Y::foo", "using Y", "using
    Y.foo", "from foo import Y", or whatever suits the language).

    When I read a source file in any language, and I see the use of an
    identifier "foo", I want to know where that came from - I want to be
    able to find that out without doubt.  If it is written "Y.foo", then
    there is no doubt.  If I see "using Y.foo", there is no doubt - but I'd

    If you used my language, you can type Y.foo if you want. Nothing stops
    you doing that.


    Look up - you might see the point flying overhead.

    And if you were using it, I can make the ability to omit 'Y.' optional.

    However, you'd need to get used to a language and compiler that is 'whole-program', with a slightly different approach


    You have snatched defeat from the jaws of victory in order to save a
    couple of lines at the start of each file - with the result that your
    language is only suitable for small single-developer programs.

    It is suitable for a vast number of programs. I'm sure it could be used
    for multi-developer projects too. After all, don't your projects also
    place all project-structure info into /one/ makefile? Which developer
    has editing rights on that file?

    People who have something to contribute can change it. Helpfully, files
    are found automatically by make, so changes are rarely needed. (It
    makes perfect sense that all files in the source directories are part of
    the project - it does not make sense that all files in the directories
    are part of the namespace of all other files.)


    Who decides what the modules are going to be? If one developer decided
    they need a new module, what is the procedure to get that added to the makefile?


    They put the file in the appropriate source directory (or add an
    appropriate source directory if needed).


    (I started writing more, but I don't think it would be helpful to anyone.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sat Dec 7 17:06:24 2024
    On 06/12/2024 20:20, Bart wrote:

    On 06/12/2024 17:47, David Brown wrote:
    On 05/12/2024 18:42, Bart wrote:

    A big one is when C is used an intermediate language for a compiler.

    Why would that be relevant?  If you compile language X by first
    transpiling to C, then compiling C, then the time to compile language X
    is the sum of these.  A fast or slow C compiler is no more and no less relevant here than if you were just compiling C.

    You don't give do you?!

    If your task to get from A to B was split into two, you'd be happy to do
    the first part by a fast car, then complete the rest of it on a horse
    and cart, for no reason at all?


    The comparison was between C to object code (with a real compiler) and
    from X to C and then to the object code (using a real compiler). If
    your beliefs were true that gcc (and other proper C compilers) are
    incredibly slow, why would it make any difference if someone is starting
    from X or starting from C? In both cases, compilation would take a long
    time - C compilation speed is neither more nor less important whether
    you are programming in X or C.

    And you are the only one so far who finds gcc to be inconveniently slow.

    Of course we'd all be happy if gcc were faster, but for most people
    working in C, it is usually fast enough. In particular, for /me/ it has
    always been fast enough. I have never felt I had to wait significantly
    for compilation of my own projects. Certainly I have never even
    considered to switching to something inferior - even "gcc -O0" - in
    order to speed up building code.

    (People tend to be much more bothered by the speed of C++ compilation
    rather than C compilation.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Janis Papanagnou on Sat Dec 7 15:33:08 2024
    On 07/12/2024 14:36, Janis Papanagnou wrote:
    On 07.12.2024 14:04, Bart wrote:


    Just fine, I'd say.

    But it relies on some subtlety.

    You seem to see ghosts. There's no subtlety; all is clearly defined,
    and it's a sensible feature, and consistently implemented.

    'while (cond)' both starts a statement, and can
    end a statement:

    do while(cond) do ; while (cond);

    What is this (IMO syntactical wrong "C" code) supposed to do or to
    explain?

    See my follow-up.

    Your (wrong) second 'do' was indeed confusing! - Why did you provide
    a wrong sample to confirm your wrong ideas? - Or is it just your well
    known habit to try to confuse other folks as well my making up stupid
    things?

    You're being aggressive. It was a mistake, that's all. My original
    example was meant to show how it gets confusing, but when I transcribed
    it into an actual program, it seemed to work because I'd left out that 'do'.

    It says something however when I actually believed that that code was
    valid, because the compiler appeared to say so.

    Most here (and me too) already acknowledged that "C" is not obvious
    to you.

    Why is it not possible for to acknowledge that some language design
    patterns may not be as obvious as others?

    According to you, even if some construct can be determined to be
    unambiguous in some convoluted grammar, then it must also be 100%
    obvious to any human reader?

    Is it just to avoid admitting that I might have a point?


    You don't think there is an element of ambiguity here?

    There isn't any.

    So you're a parser and you see this:

    do ... while

    How do you know whether that 'while' starts a new nested loop or
    terminates this one?

    What does it depend on; what property of blocks in the language is
    needed to make it work? What property of statement separators or
    terminators is needed.

    In C, it apparently relies on blocks (that is, the statements in a loop
    body) being only a single statement, as it is in C. So the pattern is this:

    do {...} while ...
    do stmt; while ...
    do ; while ...

    But not however these:

    do {...}; while ...
    do while ... # this can't be the terminating while.

    So it can't work in a syntax which allows N statements in a block:

    do s1; s2; s3; while ...

    Since it can't tell whether that while is the terminator, or is another
    nested loop.

    Now, you could have given a more measured, respectful reply and pointed
    these things out, instead of being condescending and patronising.

    You might also have pointed out that C could have deprecated null
    statements consisting of a single ";", and required the more visible
    "{}", as some compilers can be requested to do. Since such a ";" can
    instroduce very subtle errors that are hard to spot.

    That the option exists suggests that some people do have trouble with
    it. But your attitude appears to be the arrogant one that because it is technically unambiguous, then ANYONE should be able to spot such errors.

    And if they can't then they should spend more time studying manuals,
    choose a different language, or give up coding altogether.

    In your book, it's fine to write expressions like this:

    a + b & c * d == f < g | h ? i ^ j : k && l

    without parentheses, because the C grammar is 100% unambiguous in what
    it means.

    That is really not helpful.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Scott Lurndal on Sat Dec 7 17:17:05 2024
    On 06/12/2024 23:26, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 23:48, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 17:55, Scott Lurndal wrote:

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?


    That was a build that touched a key header file, so maybe
    85% full. A full build adds a minute or two wall time.

    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    That sounds like your dependency handling in make is not ideal. Store
    your dependencies in individual files per source file, where both the
    object file and the dependency file itself are dependent on the headers
    used by the C file. (The makefile should also have both the object file
    and the dependency file dependent on the C source file.)

    We use the standard makedepend support built into GCC. It creates
    a .d file for each source file that contains the dependencies
    for that source file.

    This is part of the makefile macro I use when generating dependency files:

    $(CCDEP) $(combined_cflags) $(2) $(3) -MM -MP \
    -MT $(obj_dir)$(1)$$(@F:%.d=%.o) \
    -MT $(dep_dir)$(1)$$(@F:%.o=%.o) \
    -MF $$@ $$<

    The point is that because the dependency files themselves are also
    targets in these dependency files, they don't need to be re-build unnecessarily.


    Scale matters, (with two thousand+ source and header files, that's a lot
    of 'access', 'read' and 'stat' system calls just to build the dependency graph. On NFS filesystems, which we use in most environments, the make takes even more time.


    If the issue is stat'ing the times for those files in order to check the dependencies, then I understand the bottleneck. But I would not expect
    people to be sharing a source tree on NFS like that - it is certainly
    not the usual way of collaborating on projects.

    Certainly it all sounds like you are doing something seriously
    inefficient. You've only got ten times the number of files that I have,
    but massively slower update builds. On the other hand, it might simply
    be that the way your headers are used, and the type of C++ code you have
    (it is mainly C++, is it not?) mean that individual file compiles are
    much more demanding than on my system.

    Thus your build only generates new dependency files when either the C
    source file changes, or any of the headers included (recursively) by
    that C file change. Change a C file, and it's dependencies will be
    re-calculated - but not the dependencies for anything else. Change a
    header, and you only need to re-calculate the dependencies for the
    source files that actually use it.


    In the case above, over 1000 source files were dependent upon that
    key project-wide header file which had been modified.

    Yes, when that happens there will be a lot of re-compilation. But
    usually that doesn't happen very often.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Tim Rentsch on Sat Dec 7 16:17:11 2024
    On 07/12/2024 15:00, Tim Rentsch wrote:
    Bart <bc@freeuk.com> writes:

    But I also have to spend time battling endless personal attacks
    because I'm perceived as an upstart (even though I'm now receiving
    my state pension!).

    Dictionaries describe upstarts as people who are full of themselves
    and dismissive of others. So if you are perceived as an upstart,
    it's because you are one.

    Implying that somebody is a liar isn't being dismissive?

    Okay....

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Tim Rentsch on Sat Dec 7 16:15:56 2024
    On 07/12/2024 14:51, Tim Rentsch wrote:
    Bart <bc@freeuk.com> writes:

    In a 39Kloc C codebase, there were 21,500 semicolons.

    This is generated C, so some of those may be following labels!
    2000, actually, which still leaves 19,500; a lot of semicolons.

    On a preprocessed sql.c test (to remove comments) there were
    53,000 semicolons in 85,000 lines.

    So in C, they are a very big deal, occuring on every other line.

    Many years ago I read a book called "How to Lie with Statistics".
    It should be updated to add this reporting as an example.

    You're welcome to post your own figures.

    I know your own code will be out of the ordinary as you prefer using
    commas (or ?:) to semicolons, and to write things horizontally rather
    than vertically.

    Here's one of my few programs that I manually wrote in C:

    c:\cx>mcc pid
    Compiling pid.c to pid.exe
    NLINES= 2219
    NSEMIS= 1078
    NSEMISATEOL= 1026

    It is pretty much exactly what I said. One more (not mine):

    c:\cx>mcc deltablue
    Compiling deltablue.c to deltablue.exe
    NLINES= 1558
    NSEMIS= 707
    NSEMISATEOL= 652

    This one is a bit different:

    c:\cx>mcc piet
    Compiling piet.c to piet.exe
    NLINES= 3267
    NSEMIS= 753
    NSEMISATEOL= 680

    Semicolons occur only every 4 lines or so. Hmm, let's try preprocessing,
    then compile the processed source:

    c:\cx>mcc -e piet
    Preprocessing piet.c to piet.i

    c:\cx>mcc piet.i
    Compiling piet.i to piet.exe
    NLINES= 1331
    NSEMIS= 774
    NSEMISATEOL= 719

    Back to normal! I guess there were a lot of #defines, or something. It's difficult to isolate large, external headers from line counts. But
    that's not code that /you/ have to write; yours will be the executable
    code that needs the semicolons!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sat Dec 7 16:52:30 2024
    On 07/12/2024 15:57, David Brown wrote:
    On 06/12/2024 19:41, Bart wrote:

    My language:

       println =a,=b                  # 13 characters, 0 shifted


    Since some of us live in a world with more than one person - indeed,
    more than one country - you might like to know that "=" is shifted on
    many keyboards.

    I want to make my comment both fit on one line, and line up with the
    other, so I had to leave out '(on my keyword)'. I'd hoped that was implied.

    Yes, I design my stuff around a UK English layout. That's what I've used
    for 30 years, since I got my first portable PC. Before that, I either
    had to bring my own keyboard when visiting clients, or try to work with unfamiliar layouts on clients' computers, usually in NL or CH.



    (And that space is optional!)

    The biggest irritation I have with your style, whether in your language
    or in C, is the lack of space.  It's a big key - it's easy to press.

    Spaces were left out to do a fairer comparison. Spaces aren't a big
    deal, they are fairly easy to type, I even left one in in my example
    because it looked too odd otherwise, and I was still ahead anyway.

    Good spacing habits (in the broadest sense) is the single biggest factor
    to readability of code, text, hand-writing, and pretty much anything else.

    The language Forth is not known for being easy to read amongst non-
    experts, but one thing it gets right is insisting that there are spaces between tokens.

    That is misleading. Forth REQUIRES those spaces otherwise it wouldn't
    work; each line would be read as one giant token. It's not because it
    wants to instill good habits.

    If you wrote C in the same style, it would look pretty weird:

    f ( ) ;
    f ( x , y , z ) ;
    ++ p . x ;
    q = ( void ) p ;
    label :
    f ( x , y , z ) ;
    a [ i + 1 ] ;



    In C (assume the existence of stdio.h):

       printf("A=%lld B=%f\n",a,b);   # ~28 characters, 8 shifted

    Enough said.

    I don't know what you are getting at, so I don't know if enough has been
    said or not.  If you are trying to suggest that the only thing you think
    is important about language syntax is how you print out two variables in
    as few keystrokes as possible, then I suppose you have succeeded in that goal, and can therefore rest your case.

    Pretty much everything in C requires more typing and tends to need more punctuation. It is the latter that slows me down.

    Some things may require more characters in my syntax but they are
    unshifted alphabetics which are quick to type. If working with someone
    else's codebase, I'm constantly have to shift case.

    I know this won't cut any ice, as nothing I can possibly write will ever
    make the slightest bit of difference, but in C you write stuff like this:

    void F(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t
    a5, uint32_t a6, uint32_t a7, uint32_t a8) {

    while I would just write:

    proc F(u32 a1, a2, a3, a4, a5, a6, a7, a8) =

    It's night and day.

    (BTW how long does it take to verify that all of those parameters are of
    the same type? This comes from a real example.)

    I'll read the rest of your post at some time in the future, after I've
    had a stiff drink.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sat Dec 7 19:06:09 2024
    On 07/12/2024 17:57, Bart wrote:
    On 07/12/2024 16:17, David Brown wrote:
    On 06/12/2024 23:26, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 23:48, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 04/12/2024 17:55, Scott Lurndal wrote:

    13 minutes by the wall clock, a bit over an hour
    of CPU time.


    Is that a "typical" build - or an atypical full clean build?


    That was a build that touched a key header file, so maybe
    85% full.  A full build adds a minute or two wall time.

    A single source file build (for most source files) takes
    about 28 seconds real, a large portion of that in make as it
    figures out what to rebuild in a project with thousands
    of source files and associated dependencies.

    That sounds like your dependency handling in make is not ideal.  Store >>>> your dependencies in individual files per source file, where both the
    object file and the dependency file itself are dependent on the headers >>>> used by the C file.  (The makefile should also have both the object
    file
    and the dependency file dependent on the C source file.)

    We use the standard makedepend support built into GCC.  It creates
    a .d file for each source file that contains the dependencies
    for that source file.

    This is part of the makefile macro I use when generating dependency
    files:

            $(CCDEP) $(combined_cflags) $(2) $(3) -MM -MP \
                           -MT $(obj_dir)$(1)$$(@F:%.d=%.o) \
                           -MT $(dep_dir)$(1)$$(@F:%.o=%.o) \
                           -MF $$@ $$<

    The point is that because the dependency files themselves are also
    targets in these dependency files, they don't need to be re-build
    unnecessarily.


    Scale matters, (with two thousand+ source and header files, that's a lot >>> of 'access', 'read' and 'stat' system calls just to build the dependency >>> graph.   On NFS filesystems, which we use in most environments, the make >>> takes even more time.


    If the issue is stat'ing the times for those files in order to check
    the dependencies, then I understand the bottleneck.  But I would not
    expect people to be sharing a source tree on NFS like that - it is
    certainly not the usual way of collaborating on projects.

    Certainly it all sounds like you are doing something seriously
    inefficient.  You've only got ten times the number of files that I
    have, but massively slower update builds.

    This is to be lauded. Somebody actually questioning something whether build-times should be that long.

    Somebody other than me, that is.


    There's a big difference, however. I am asking Scott with a view to
    helping him get more efficient use out of the good tools he uses.
    (Scott's been doing this stuff pretty much since the dawn of time, but
    there's still a possibility that there are things he has not thought about.)

    I am not suggesting he switches to crappy tools that might be faster, or boasting that my language is infinitely superior because it compiles
    faster, or whining about C in a C newsgroup, or making strawman
    arguments in an attempt to prove my position.

    I am trying to see if there are ideas that could make his builds faster
    for his convenience - alternatively, I am trying to see if there are
    particular reasons for the extra time his builds take so that I can be
    sure to avoid the same circumstances in my own work.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sat Dec 7 18:58:38 2024
    On 07/12/2024 17:52, Bart wrote:
    On 07/12/2024 15:57, David Brown wrote:
    On 06/12/2024 19:41, Bart wrote:

    My language:

       println =a,=b                  # 13 characters, 0 shifted


    Since some of us live in a world with more than one person - indeed,
    more than one country - you might like to know that "=" is shifted on
    many keyboards.

    I want to make my comment both fit on one line, and line up with the
    other, so I had to leave out '(on my keyword)'. I'd hoped that was implied.

    Sure. I just thought you'd like to know that when you make comparisons
    like this, you do so more subjectively than you might have imagined.



    (And that space is optional!)

    The biggest irritation I have with your style, whether in your
    language or in C, is the lack of space.  It's a big key - it's easy to
    press.

    Spaces were left out to do a fairer comparison. Spaces aren't a big
    deal, they are fairly easy to type, I even left one in in my example
    because it looked too odd otherwise, and I was still ahead anyway.


    Spaces /are/ a big deal.

    Good spacing habits (in the broadest sense) is the single biggest
    factor to readability of code, text, hand-writing, and pretty much
    anything else.

    The language Forth is not known for being easy to read amongst non-
    experts, but one thing it gets right is insisting that there are
    spaces between tokens.

    That is misleading. Forth REQUIRES those spaces otherwise it wouldn't
    work; each line would be read as one giant token. It's not because it
    wants to instill good habits.


    That's fair. But the result is better spacing, even if it is a by-product.

    If you wrote C in the same style, it would look pretty weird:

    Forth doesn't need the parentheses or the semicolons, making it a bit of
    an unfair comparison.


       f ( ) ;
       f ( x , y , z ) ;
       ++ p . x ;
       q = ( void ) p ;
       label :
       f ( x , y , z ) ;
       a [ i + 1 ] ;


    That is just differently bad from "f(x,y,z);" and "q=(void*)p;". Too
    much space is bad spacing, just as too little space is bad spacing (and
    so is inconsistent spacing).


    I know this won't cut any ice, as nothing I can possibly write will ever
    make the slightest bit of difference, but in C you write stuff like this:

    No, in C /I/ don't write anything of the sort - nor do most C
    programmers. And I don't believe you write functions with 8 parameters
    in your language either. At the very least, these would be highly unusual.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sat Dec 7 19:02:05 2024
    On 07/12/2024 17:58, David Brown wrote:
    On 07/12/2024 17:52, Bart wrote:

        f ( ) ;
        f ( x , y , z ) ;
        ++ p . x ;
        q = ( void ) p ;
        label :
        f ( x , y , z ) ;
        a [ i + 1 ] ;


    That is just differently bad from "f(x,y,z);" and "q=(void*)p;".  Too
    much space is bad spacing,

    You specifically praised Forth for requiring spaces between tokens,
    which is exactly what this code has.

    I know this won't cut any ice, as nothing I can possibly write will
    ever make the slightest bit of difference, but in C you write stuff
    like this:

    No, in C /I/ don't write anything of the sort - nor do most C
    programmers.  And I don't believe you write functions with 8 parameters
    in your language either.  At the very least, these would be highly unusual.

    This is the real example it was based on (here using pass-by-reference):

    proc fastidct8(int &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8) =

    That itself was based on some original C which passed an array.

    But because the values in the caller were not always consecutive (they
    were a column of a table), they needed copying into an array first, the function called, then copied back to the array since the function
    changes them.

    Passing individual argument looked more efficient and tidier.

    I'm sure it happens in C that several consecutive parameters have the
    same type, but there is no way to express that without repeating the
    type. Another real example:

    static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)

    At least least this doesn't use a type like 'int32_t' otherwise it would
    be even longer, likely to overflow the line, and would obscure the names
    of the parameters. Just seeing how many there are becomes harder.

    But even this would look far better as:

    static void *stbi__malloc_mad4(int a, b, c, d, add)

    (You can keep the 'int add' to emphasise that the first 4 are meant to
    share the same type, and it's not just coincidence.)

    Don't forget the separate declaration, which repeats the parameters,
    that an exported function might need, as shown here:

    extern int bn_add (Bignum c, Bignum a, Bignum b); # in .h file

    int bn_add (Bignum c, Bignum a, Bignum b) { # in .c file

    'Bignum' is written 6 times. This was ported from this version in my syntax:

    export proc bn_addu(bignum dest, a, b) =

    Here, 'bignum' is written only once. (The 'export' is needed if this
    build into an independent binary, such as a DLL, so that it is exported.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sat Dec 7 22:00:49 2024
    On 07/12/2024 20:02, Bart wrote:
    On 07/12/2024 17:58, David Brown wrote:
    On 07/12/2024 17:52, Bart wrote:

        f ( ) ;
        f ( x , y , z ) ;
        ++ p . x ;
        q = ( void ) p ;
        label :
        f ( x , y , z ) ;
        a [ i + 1 ] ;


    That is just differently bad from "f(x,y,z);" and "q=(void*)p;".  Too
    much space is bad spacing,

    You specifically praised Forth for requiring spaces between tokens,
    which is exactly what this code has.

    The languages are not the same - they have different syntaxes. Forth
    requires good spacing for Forth. C does not require good spacing for C.
    I think that's a shame - I think a lot of C code would be easier to
    read if spaces were required in certain parts of the syntax (but not /everywhere/). Of course I don't think people could agree enough on
    /where/ the spaces should go in order to standardise something like
    that. But for example, a rule that required a space after the comma
    between function arguments and parameters would be a big step forward in legibility of some people's code.

    <snip purely subjective opinion on unrealistic code>

    (And if you want to snip my purely subjective opinion on spacing, I
    won't feel offended.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to David Brown on Sat Dec 7 21:18:31 2024
    On 07/12/2024 21:00, David Brown wrote:

    <snip purely subjective opinion on unrealistic code>

    You mean that /real/ example where a function needed a type written 6
    times instead of once? OK.

    I'd be curious about how you'd write such a function; maybe all your
    functions only have one parameter, or they are always of mixed types.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to David Brown on Sat Dec 7 22:12:34 2024
    David Brown <david.brown@hesbynett.no> writes:
    On 07/12/2024 17:57, Bart wrote:
    On 07/12/2024 16:17, David Brown wrote:
    On 06/12/2024 23:26, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:

    This is to be lauded. Somebody actually questioning something whether
    build-times should be that long.

    Somebody other than me, that is.


    There's a big difference, however. I am asking Scott with a view to
    helping him get more efficient use out of the good tools he uses.
    (Scott's been doing this stuff pretty much since the dawn of time, but >there's still a possibility that there are things he has not thought about.)

    The problem is not the tools. We know exactly what causes the
    slowdown (and it is related to code autogenerated from yaml
    data structure descriptions). The algorithms used to initialize
    internal data structures seriously stress the GCC optimizer. To
    the point that there is a 20:1 difference in compile time
    for a handful of source files (up to 8 minutes in one case)
    between -O0 and -O3.

    Time permitting, the plan is to replace the initial ad-hoc
    design with something both scalable and performant.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Keith Thompson on Sat Dec 7 22:15:42 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Bart <bc@freeuk.com> writes:
    [...]
    Those suggesting that semicolons are unimportant details of syntax in
    C are wrong. They can make a significant difference and contribute to
    errors:

    for (i=0; i<n; ++i);
    printf("%d\n", i);

    Nobody has suggested that "semicolons are unimportant details of syntax
    in C".


    In my experience, semicolons can be confusing for programmers who are
    new to programming, or at least new to a language. I remember "missing >semicolon" being a common error when I was a beginner, but I don't
    remember it being a real issue any time in the last several decades.

    When I was working at the university computer center, as the newest
    hire, I was stuck with manning the debug desk one hour per week during
    their staff meeting.

    Something like 70% of questions were answered by reading the
    compiler error message:

    "Possibly missing semi-colon on previous line."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Bart on Sat Dec 7 23:13:38 2024
    Bart <bc@freeuk.com> writes:

    On 07/12/2024 21:00, David Brown wrote:

    <snip purely subjective opinion on unrealistic code>

    You mean that /real/ example where a function needed a type written 6 times instead of once? OK.

    I've always wondered why prototypes in C did not simply use the existing
    syntax for declarations. After all, it was right there in K&R C, just
    outside the parentheses:

    f(m, n, s)
    int m, n;
    char *s;
    { ... }

    could have become

    f(int m, n; char *s)
    { ... }

    rather than

    f(int m, int n, char *s)
    { ... }

    Does anyone know if there even /was/ a reason?

    OK, I know the declarations were not /always/ there. Implicit int meant
    that one could write

    f(m, n, s)
    char *s;
    { ... }

    but that could also have been preserved by allowing

    f(m, n; char *s)
    { ... }


    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Keith Thompson on Sat Dec 7 22:47:22 2024
    On 07/12/2024 21:38, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    On 07/12/2024 14:36, Janis Papanagnou wrote:
    On 07.12.2024 14:04, Bart wrote:
    Just fine, I'd say.

    But it relies on some subtlety.
    You seem to see ghosts. There's no subtlety; all is clearly defined,
    and it's a sensible feature, and consistently implemented.

    'while (cond)' both starts a statement, and can
    end a statement:

    do while(cond) do ; while (cond);
    What is this (IMO syntactical wrong "C" code) supposed to do or to
    explain?

    See my follow-up.

    Your (wrong) second 'do' was indeed confusing! - Why did you provide
    a wrong sample to confirm your wrong ideas? - Or is it just your well
    known habit to try to confuse other folks as well my making up stupid
    things?

    You're being aggressive. It was a mistake, that's all. My original
    example was meant to show how it gets confusing, but when I
    transcribed it into an actual program, it seemed to work because I'd
    left out that 'do'.

    OK, it was a mistake. Someone pointed it out. And you took offense at
    that for some reason.

    You can point things out politely, especially if you think the mistake
    was inadvertent. Instead there were just snide insinuations:

    - "Why did you ... to confirm your wrong ideas?"
    - "Your well known habit ... to try and confuse...
    - "making up stupid things"



    Suppose you are criticising a thing that someone else has created, a bit
    of software, maybe a language, some CLI, an implementation, whatever.

    How would you feel if you posted some input corner cases, examples that
    could be confusing, or that are error prone, that you feel that are not
    that robust, or harder to than necessary ....

    But everybody not only just dismisses everything you say out of hand, they:

    * Suggest you don't understand the product
    * Tell you to go away and read the manuals
    * Say that nobody else has that problem
    * Say that nobody would write that
    * Accuse you of spreading FUD
    * Call you ignorant...
    * ...stupid...
    * ...a fool...
    * Blatantly accuse you of lying ...

    ... while at same time deny that there exists such a thing as a too-slow compiler - they will always find something that takes even longer, such
    that the compile speed is no longer dominant!

    Plus they will say that it doesn't matter at all how big any program is,
    even 1GB or 10GB. Complete nonsense, and all lies.

    Look, I've had enough. I don't know why it's taken me this long to
    realise how toxic this environment is.

    A few posters such as WH and MS seem to manage to have a civilised
    discussion even when there is disagreement.

    Most everyone else seems to be waging war on everything I say or do, and
    are making endless personal attacks and insinuations. I have to defend
    myself on multiple fronts. To all those: fuck the lot of you.

    If someone needs to say something to me on a technical matter, they can
    raise an issue here: https://github.com/sal55/langs

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Scott Lurndal on Sun Dec 8 11:57:00 2024
    On 07/12/2024 23:12, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 07/12/2024 17:57, Bart wrote:
    On 07/12/2024 16:17, David Brown wrote:
    On 06/12/2024 23:26, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:

    This is to be lauded. Somebody actually questioning something whether
    build-times should be that long.

    Somebody other than me, that is.


    There's a big difference, however. I am asking Scott with a view to
    helping him get more efficient use out of the good tools he uses.
    (Scott's been doing this stuff pretty much since the dawn of time, but
    there's still a possibility that there are things he has not thought about.)

    The problem is not the tools. We know exactly what causes the
    slowdown (and it is related to code autogenerated from yaml
    data structure descriptions). The algorithms used to initialize
    internal data structures seriously stress the GCC optimizer. To
    the point that there is a 20:1 difference in compile time
    for a handful of source files (up to 8 minutes in one case)
    between -O0 and -O3.

    Time permitting, the plan is to replace the initial ad-hoc
    design with something both scalable and performant.

    Ah, okay, that makes sense.

    I think perhaps you wrote something along the lines of "compiling one
    file takes x seconds", which I interpreted as referring to any one file,
    while you meant one file in particular.

    I guess you just try to minimise how often those few nasty files need to
    be compiled.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bart on Sun Dec 8 11:52:58 2024
    On 07/12/2024 22:18, Bart wrote:
    On 07/12/2024 21:00, David Brown wrote:

    <snip purely subjective opinion on unrealistic code>

    You mean that /real/ example where a function needed a type written 6
    times instead of once? OK.

    I'd be curious about how you'd write such a function; maybe all your functions only have one parameter, or they are always of mixed types.

    Having so many parameters in a function is a sign of a bad interface
    design - the more parameters, the poorer the design. Occasionally
    having 6 parameters might be the best choice in a particular case, but
    it is going to be rare - most functions have far fewer. And it's okay
    if things are a bit awkward or harder to write for something that should
    be rare, and is rare in practice.

    The problem is not so much when defining or declaring the function - it
    is when /using/ the function. C does not have named arguments, and it
    is extremely easy for code calling a function of many parameters to mix
    them up (especially if they are the same type).



    I'd have been quite happy if C had a syntax along the lines of

    int foo(int a, b, c, double x, y, z);

    for declaring functions. It can't quite follow the same pattern as for declarations of variables (because then you'd need a semicolon after the
    "c" above), but it would be close.

    But C doesn't have a syntax like that, and the syntax it has is rarely
    an issue for anyone.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Bart on Sun Dec 8 22:52:57 2024
    Bart <bc@freeuk.com> wrote:
    It is suitable for a vast number of programs. I'm sure it could be used
    for multi-developer projects too. After all, don't your projects also
    place all project-structure info into /one/ makefile? Which developer
    has editing rights on that file?

    There are _many_ possible organizations. Rather typical is one
    Makefile _per directory_. Most 'make'-s seem to be able to do
    file inclusion, so you may have a single main Makefile that
    includes whatever pieces are necessary. For example, if somebody
    wanted to add support for your language to gcc, that would need
    creating a subdirectory and putting file called 'Make-lang.in'
    inside. Make-lang.in is essentially Makefile for your language,
    but it is processed to substitute crucial variable and included
    as part of gcc Makefile. Of course, you will need more, but
    this covers Makefile part.

    Who decides what the modules are going to be? If one developer decided
    they need a new module, what is the procedure to get that added to the makefile?

    In open source project normal thing is a patch or a Git pull
    request. This specifies _all_ needed changes, including Makefile-s
    if there is a need for new module it gets added where needed.
    I one "my" project there can be multiple module in a file, so
    a new module may go to existing file (if it is closely related
    to other module in the file) or to a separate file. I also needs
    changes to Makefile.

    The above is technical part. Other is governace of a project.
    If there are multiple developers, then there may be some form
    of review. Or a developer may be declared to be maintainer of
    given part and allowed changes without review. 'gcc' has several
    "global maintainers", they can change each part and approve
    all changes. There are maintainers for specific parts, they
    can modify parts they are resposnible for and approve changes
    there, for other parts they need approval. There are "write
    after approval" people who propose changes but are allowed to
    merge them only after approval from folks in the first two
    groups. There is also a steering body which votes and
    make decision after. Some project use some forms of democracy.
    For example, all developers may be considerd equal, but
    any change need aproval from another developer. In case of
    objections there is a vote. Some projects have a "dictator"
    of "lead developer" who has final say on anything project-related.

    I have no experience in commercial setups, but IIUC normally
    firms have rules and responsible persons. Person responible
    for a project divides work and possibly delegates responsibility.
    Firm or project rules may require review, so that other developer
    looks at changes. There could be design meeting before
    coding.

    The design IS better in 100 ways, at least compared to C. Other modern, higher level languages have 100 things I don't have, don't understand,
    or would find impossible to use.

    However a language at the level of C still appears to be extremely
    popular. I guess people like something that is not so intimidating and
    that they can feel in command of.

    Hmm, the only language at C level that I know and is popular
    is C. Ada, COBOL, Fortran, Modula 2, Pascal, PL/I are languages
    that I consider to be at level similar to C. But AFAIK no of them
    is really popular and in modern time they aim to be higher-level
    than C. Forth is at lower level and really not that popular.

    Can you name a language that is at level of C, is popular and
    is not C?


    No, it is not.  You set PATH to the directories you want to use for
    binaries - the OS does not search the entire disk or random additional
    attached filesystems.

    PATH is a collection of paths that are searched in turn. There it will
    stop at the first match.

    That's similar to my list of modules that are searched in turn. There it
    will find all matches and report an ambiguity if more than one.

    However, my list is private to my project, while PATH is common to every command prompt and to whatever directory is current. Some programs could
    even manipulate the contents of PATH.

    Yes. In particular, depending on need program may put some specific
    directory at start of the PATH or restrict PATH. I asked if you
    can contol visibility in your system, you gave no aswer which for
    me idicate that you can not. Of course, changing PATH is very
    crude (is is essentially equvalent to what Forth is offering),
    most languages have better ways. Do you know how Turbo Pascal
    units worked? Or Modula 2?

    No, your design is to /force/ "using namespace" - whether the programmer
    wants it or not, and without the programmer even identifying the modules
    to import.  It's your choice - but it's a bad choice.

    The programmer knows how the language works. They will have chosen the modules that are grouped together.

    The alternative is to have 50 modules of a project, where each module contains its own subset of 0 to 49 imports. That's up to 950 possible
    imports to maintain across up to 50 files. It sounds a maintenance
    nightmare. A dependency graph would need a pretty big sheet of paper!

    You discard posibility of re-export. Lazy programmer may write
    "utility" module that imports every needed interface and re-exports
    it. And then in each implementation import this single module.
    Compared to your scheme overhead is essentially a single line
    per implemention. Of course, lazy programmer gains nothing
    compared to your scheme. Less lazy programmer may divide modules
    into groups and only import groups that are needed, more lines
    of code but also more control. Or programmer can specify imports
    for each module which usually is not a big deal.

    As as data point, I have system containing more than 1000 modules.
    There are 1064 explicit import statements. Number of needed
    imports is lowered by different features: there is possibility
    of inheritance for interfaces and inheritance of implementation,
    both do import as part of their function. There are also
    calls using qualified name (probably more than 10000 such calls).

    And yes, import statements need maintenance, IME it was not a
    problem as import statements were small part of source. Normally
    I would import a module if I need to use at least twice something
    from the module and usually number of uses were higher.
    And module import tended to change slower than normal code.

    Would it even allow mutual imports? If not then that's another
    nightmare, which is likely to generate lots of extra dummy modules which
    only exist to get around the restriction.

    I'm sorry, but I tried such a scheme, and decided it was awful.

    One can do better than Turbo Pascal or Modula 2. But IME both
    had quite resonable module systems. You may follow Oberon and
    instead of separtate interface text just mark exported things.
    But explictit imports, more precisely programmer ability to
    restrict imports only to those which are explicitely specified
    is essential.

    Turbo Pascal and I think also Modula 2 distinguish import in
    interface form import in implementation. Imports in interface
    part must form a tree (no cycles allowed). Imports in
    implementation part allow arbitrary dependencies. One could
    allow weaker restrictions, for example during compilation you
    may allow patially defined things and only require that there
    are no cycles when you try to fill needed information.
    For example module A could define a type depending on constant
    from module B and module B could define a type depending on
    module A. Compilation of type in A would look up in B which
    would give value of the constant. Similarly, compilation of
    type in B would look up in A. As long as all such chains
    of lookups resoleve without cycles you can compile the whole
    thing. But IME already simpler systems are adequate.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Waldek Hebisch on Mon Dec 9 18:35:57 2024
    On 08.12.2024 23:52, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    It is suitable for a vast number of programs. I'm sure it could be used
    for multi-developer projects too. After all, don't your projects also
    place all project-structure info into /one/ makefile? Which developer
    has editing rights on that file?

    There are _many_ possible organizations. Rather typical is one
    Makefile _per directory_. Most 'make'-s seem to be able to do
    file inclusion, so you may have a single main Makefile that
    includes whatever pieces are necessary. For example, if somebody
    wanted to add support for your language to gcc, that would need
    creating a subdirectory and putting file called 'Make-lang.in'
    inside. Make-lang.in is essentially Makefile for your language,
    but it is processed to substitute crucial variable and included
    as part of gcc Makefile. Of course, you will need more, but
    this covers Makefile part.

    Who decides what the modules are going to be? If one developer decided
    they need a new module, what is the procedure to get that added to the
    makefile?

    In open source project normal thing is a patch or a Git pull
    request. This specifies _all_ needed changes, including Makefile-s
    if there is a need for new module it gets added where needed.
    I one "my" project there can be multiple module in a file, so
    a new module may go to existing file (if it is closely related
    to other module in the file) or to a separate file. I also needs
    changes to Makefile.

    The above is technical part. Other is governace of a project.
    If there are multiple developers, then there may be some form
    of review. Or a developer may be declared to be maintainer of
    given part and allowed changes without review. 'gcc' has several
    "global maintainers", they can change each part and approve
    all changes. There are maintainers for specific parts, they
    can modify parts they are resposnible for and approve changes
    there, for other parts they need approval. There are "write
    after approval" people who propose changes but are allowed to
    merge them only after approval from folks in the first two
    groups. There is also a steering body which votes and
    make decision after. Some project use some forms of democracy.
    For example, all developers may be considerd equal, but
    any change need aproval from another developer. In case of
    objections there is a vote. Some projects have a "dictator"
    of "lead developer" who has final say on anything project-related.

    I have no experience in commercial setups, but IIUC normally
    firms have rules and responsible persons. Person responible
    for a project divides work and possibly delegates responsibility.
    Firm or project rules may require review, so that other developer
    looks at changes. There could be design meeting before
    coding.

    For "commercial setups" it's as you wrote above: "There are _many_
    possible organizations.", so there's no single way to organize
    things. One thing that is common (as far as my [naturally limited]
    observations go) is that they also use tools that support defining
    processes that reflect project structure, responsibilities, and
    software and system design, and its organization. For example we
    had tools that described and managed the software creation process;
    defining a component, defining a [new] release, associating bug
    reports and feature requests to releases, open tracks to implement
    things (bug-fixes/features), fix-records to track the changes, etc.
    and all controlled by a process-framework with dedicated people
    responsible or able to do certain tasks. People could check-in
    source code, documentation, tests. Actions and state transitions
    were bound to access rights (depending on various factors). New
    states were notified to responsible people in the process-chain
    to enable them to do their work based on new project results,
    say to do reviews, or tests, or build a release if preconditions
    are all fulfilled.

    And there's of course also "supplementary tools"; [hierarchical]
    'make' systems for the dependency/creation tasks (libs, docs,
    tests, exes), project management and planning systems for the
    respective tasks. - I'm sure not all of this will be found in
    every commercial project - and, to be honest, I've heard stories
    that I wouldn't think be possible in a professional context! -
    but typically a huge part of what I described was quite standard
    in the commercial contexts I worked in; differences where mainly
    only by the chosen tools, and omissions of some details in the
    process and grade of automation that were considered unnecessary
    in a given context.

    So far just off the top of my head; I'm sure I forgot to mention
    one or the other (maybe even important) element.

    [...]

    However a language at the level of C still appears to be extremely
    popular. I guess people like something that is not so intimidating and
    that they can feel in command of.

    Hmm, the only language at C level that I know and is popular
    is C. Ada, COBOL, Fortran, Modula 2, Pascal, PL/I are languages
    that I consider to be at level similar to C. But AFAIK no of them
    is really popular and in modern time they aim to be higher-level
    than C. Forth is at lower level and really not that popular.

    It seems that Ada and Fortran are still in significant areas in use,
    aren't they?

    (I wouldn't call that "popular", though, because that word has quite
    some [arguable] connotations.)

    [snip rest]

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Bart on Mon Dec 9 19:46:48 2024
    On 07.12.2024 16:33, Bart wrote:
    On 07/12/2024 14:36, Janis Papanagnou wrote:
    On 07.12.2024 14:04, Bart wrote:


    Just fine, I'd say.

    But it relies on some subtlety.

    You seem to see ghosts. There's no subtlety; all is clearly defined,
    and it's a sensible feature, and consistently implemented.

    'while (cond)' both starts a statement, and can
    end a statement:

    do while(cond) do ; while (cond);

    What is this (IMO syntactical wrong "C" code) supposed to do or to
    explain?

    See my follow-up.

    See mine.


    Your (wrong) second 'do' was indeed confusing! - Why did you provide
    a wrong sample to confirm your wrong ideas? - Or is it just your well
    known habit to try to confuse other folks as well my making up stupid
    things?

    You're being aggressive.

    Am I?

    It was a mistake, that's all. My original
    example was meant to show how it gets confusing, but when I transcribed
    it into an actual program, it seemed to work because I'd left out that
    'do'.

    The fact I'm describing here is that you are repeatedly making up
    things, construct unrealistic lunatic samples, and argument based
    on them. There is little difference in whether you made a mistake
    in your sample or not. In other words; you are often the source of
    your confusion, homemade as we say. If you'd have formatted your
    sample in a sensible way (as certainly all other people here would
    have done) you'd instantly have seen your mistake and that the "C"
    syntax structure isn't any problem at all.


    It says something however when I actually believed that that code was
    valid, because the compiler appeared to say so.

    Huh?


    Most here (and me too) already acknowledged that "C" is not obvious
    to you.

    Why is it not possible for to acknowledge that some language design
    patterns may not be as obvious as others?

    "for" what? - You mean, for me, for the audience here?

    Why do you make things up again; of course in most languages some
    language patterns are more obvious than others. (Please leave your
    fantasy world and drop your pipe dreams if you want to seriously
    discuss things here.)


    According to you, even if some construct can be determined to be
    unambiguous in some convoluted grammar, then it must also be 100%
    obvious to any human reader?

    Who said that? - Again you make up things just for your argument.

    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    To what ([hypothetical] "some") grammar are you referring to?

    If you mean the "C" grammar; what, concretely, you find to be
    "convoluted"?

    You postulate it as if the grammar were convoluted; more likely
    it's just your personal problem with understanding formal syntax.

    No one said, that everything is "100% obvious". An unambiguous
    grammar is a precondition for for an understanding, though.

    If you'd have your excerpts and samples formatted in a common
    (non-lunatic) way then it should have been "100% obvious" even
    to you.


    Is it just to avoid admitting that I might have a point?

    (Yet you haven't had one.)



    You don't think there is an element of ambiguity here?

    There isn't any.

    So you're a parser and you see this:

    do ... while

    How do you know whether that 'while' starts a new nested loop or
    terminates this one?

    Because there's the '...' in between that answers that question.


    What does it depend on; what property of blocks in the language is
    needed to make it work? What property of statement separators or
    terminators is needed.

    In C, it apparently relies on blocks (that is, the statements in a loop
    body) being only a single statement, as it is in C. So the pattern is this:

    do {...} while ...
    do stmt; while ...
    do ; while ...

    But not however these:

    do {...}; while ...
    do while ... # this can't be the terminating while.

    So you've got it?


    So it can't work in a syntax which allows N statements in a block:

    do s1; s2; s3; while ...

    Since it can't tell whether that while is the terminator, or is another nested loop.

    All that could be read from the various posts you've got or inferred
    if you'd have spent a minimum of interest (instead of lashing out
    with inappropriate examples, and your personal peculiarities).

    Now, you could have given a more measured, respectful reply and pointed
    these things out, instead of being condescending and patronising.

    You've got all the facts and explanations (including samples) from
    several sides (mine included) here.

    (My patience, if constantly stressed, is of course limited.)


    You might also have pointed out

    I see that many folks here (me included) were and are trying to
    explain things to you that you say would confuse you. - If from
    the manifold replies you cannot see the substance, that's still
    no justification to demand any specific sort of answer. How do
    you think we know which formulation or detail might enlighten
    you, especially given that you are constantly reluctant or even
    unwilling to understand the presented answers.

    that C could have deprecated null
    statements consisting of a single ";",

    Why should I have pointed that out? (It isn't even my opinion.)

    I've even put it in one of the (corrected and reformatted) sample;
    for your convenience, this one:

    do
    while (cond)
    ;
    while (cond);

    That's a clear structure, and the indented single semicolon is IMO
    certainly not worse than

    do
    while (cond) {
    }
    while (cond);

    (which, personally, I find to be inferior concerning readability).
    I'd probably instead choose

    do {
    while (cond)
    ;
    } while (cond);

    But this is anyway just a fragment (of limited value if one wants
    to explain a sensible formatting).

    and required the more visible
    "{}", as some compilers can be requested to do. Since such a ";" can instroduce very subtle errors that are hard to spot.

    You obviously have that problem. - I certainly wouldn't go so far
    extrapolating from you to other people.


    That the option exists suggests that some people do have trouble with
    it.

    What option?

    There's simple statements, and there's blocks of one or more simple
    statements. There's also the empty statement. That's not any special
    option that exists. It's a basic concept, in almost all languages I
    know, to group 0..N statements together, or just write an empty one.

    But your attitude appears to be the arrogant one that because it is technically unambiguous, then ANYONE should be able to spot such errors.

    Bullshit. Stop making up things and, honestly, start considering that
    your attitude might be the problem (and things may clear up for you).


    And if they can't then they should spend more time studying manuals,
    choose a different language, or give up coding altogether.

    If you'd have read (and understood) all replies to you then you'd
    for example learned that it's a Good Thing to read a good textbook
    about any language you use before you start programming with it.
    And if there's anything that you don't understand ask folks (here
    or elsewhere) who do understand; but you should at least spend a
    minimum effort to understand the replies then.

    If you intend to do a new project (and if you are responsible to
    decide in that project context) choose the language most suited.

    And of course you can code what you like without doing anything
    sensible, established ways in your own toy or hobby projects;
    just don't repeatedly and constantly complain about things you
    obviously don't want to learn or understand.


    In your book, it's fine to write expressions like this:

    a + b & c * d == f < g | h ? i ^ j : k && l

    Stop making up things. That doesn't solve any question or issue,
    and you are most certainly wrong in 98% of your imputations.


    without parentheses, because the C grammar is 100% unambiguous in what
    it means.

    (You are a pathological case.)


    That is really not helpful.

    (I don't see anyone [from IT or CS sector] who could help you.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Tue Dec 10 12:10:12 2024
    On 08/12/2024 22:52, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    It is suitable for a vast number of programs. I'm sure it could be used
    for multi-developer projects too. After all, don't your projects also
    place all project-structure info into /one/ makefile? Which developer
    has editing rights on that file?

    There are _many_ possible organizations. Rather typical is one
    Makefile _per directory_. Most 'make'-s seem to be able to do
    file inclusion, so you may have a single main Makefile that
    includes whatever pieces are necessary. For example, if somebody
    wanted to add support for your language to gcc, that would need
    creating a subdirectory and putting file called 'Make-lang.in'
    inside. Make-lang.in is essentially Makefile for your language,
    but it is processed to substitute crucial variable and included
    as part of gcc Makefile. Of course, you will need more, but
    this covers Makefile part.

    Who decides what the modules are going to be? If one developer decided
    they need a new module, what is the procedure to get that added to the
    makefile?

    In open source project normal thing is a patch or a Git pull
    request. This specifies _all_ needed changes, including Makefile-s
    if there is a need for new module it gets added where needed.
    I one "my" project there can be multiple module in a file, so
    a new module may go to existing file (if it is closely related
    to other module in the file) or to a separate file. I also needs
    changes to Makefile.

    The above is technical part. Other is governace of a project.
    If there are multiple developers, then there may be some form
    of review.

    In every such endeavour, you can work at a small scale or on a big,
    industrial scale.

    I generally work on a personal scale.

    For example, there is considerable industry in publishing, manufacturing
    and distributing books. But the author of any one book can work in the
    garden shed with either a word processor, or pen and paper.

    There are similarities also with people creating meals in their own
    kitchen, compared to being a chef in a busy restaurant, or working in
    mass food production. There are other such examples (eg home DIY).

    I've only ever worked in a very small company, and for most of the time
    I worked from home.

    So what I do suits me perfectly. I don't think I'm the only one like
    that either.

    The design IS better in 100 ways, at least compared to C. Other modern,
    higher level languages have 100 things I don't have, don't understand,
    or would find impossible to use.

    However a language at the level of C still appears to be extremely
    popular. I guess people like something that is not so intimidating and
    that they can feel in command of.

    Hmm, the only language at C level that I know and is popular
    is C. Ada, COBOL, Fortran, Modula 2, Pascal, PL/I are languages
    that I consider to be at level similar to C. But AFAIK no of them
    is really popular and in modern time they aim to be higher-level
    than C. Forth is at lower level and really not that popular.

    Can you name a language that is at level of C, is popular and
    is not C?

    No, there is only C at that level that is mainstream. My point is that
    there is still a strong need for such a language, but the only practical
    choice for most people is C.

    But this demand also shows that a language like mine, which I had been
    thinking of abandoning 20+ years ago, is still meaningful. /I/ like to
    use it too.

    The alternative is to have 50 modules of a project, where each module
    contains its own subset of 0 to 49 imports. That's up to 950 possible
    imports to maintain across up to 50 files. It sounds a maintenance
    nightmare. A dependency graph would need a pretty big sheet of paper!

    You discard posibility of re-export. Lazy programmer may write
    "utility" module that imports every needed interface and re-exports
    it. And then in each implementation import this single module.

    My interfaces occur between programs. Then I do have modules that do
    exactly that. For example I have a module called mclib.m that contains
    stuff like this:

    importdll msvcrt = # special name, becomes libc.so.6 on Linux
    func puts(ichar)int32
    end

    'puts' is imported into this module from an external library, and at the
    same time exported to other modules in my program. Elsewhere I can just
    write:

    puts("abc")

    but I can also write X.puts() (if for example puts was part of two
    different DLLs), where X is not 'msvcrt', but is either the name of the containing module, or the name of the containing subprogram.

    (In the case of my puts, it is the latter, so 'msyslib.puts()` also
    works. The name of the imported DLL does not form a namespace in my
    scheme. I can create an alias for that name:

    macro clib = msyslib

    so that I can write 'clib.puts'. These macros have proper scope and can
    be exported. Macro expansion also only applies to top level names.)

    And yes, import statements need maintenance, IME it was not a
    problem as import statements were small part of source. Normally
    I would import a module if I need to use at least twice something
    from the module and usually number of uses were higher.
    And module import tended to change slower than normal code.

    A module scheme simply needs to work. Given that C has no such scheme at
    all, then pretty much anything is an improvement. My current version
    (probably the fourth major overhaul since the 1980s), works fine all my projects.

    Where it doesn't, there are workarounds.

    Would it even allow mutual imports? If not then that's another
    nightmare, which is likely to generate lots of extra dummy modules which
    only exist to get around the restriction.

    I'm sorry, but I tried such a scheme, and decided it was awful.

    One can do better than Turbo Pascal or Modula 2. But IME both
    had quite resonable module systems.

    The only Pascal I used had no modules at all that I remember. All
    programs had to be one giant source file. (I remember seeing the source
    for the Pascal compiler for PDP10, as a 2-3"-thick listing of
    green-lined printout.)

    I'm not sure that Algol68/A68G has modules either; if it does, then I've
    no idea how they work.

    FORTRAN IV programs could at least comprise multiple modules, but they
    were independently compiled then linked, much like C. Interfaces were
    done manually.

    You may follow Oberon and
    instead of separtate interface text just mark exported things.
    But explictit imports, more precisely programmer ability to
    restrict imports only to those which are explicitely specified
    is essential.

    I find Wirth languages now too opinionated, and too strict for my style
    of coding.

    Turbo Pascal and I think also Modula 2 distinguish import in
    interface form import in implementation. Imports in interface
    part must form a tree (no cycles allowed).

    This is exactly what I mean. I had such a scheme too, but I also
    retained the ability to have manual declarations that cut across the
    hierarchy. This was when I still used independent compilation of modules.

    Imports in
    implementation part allow arbitrary dependencies. One could
    allow weaker restrictions, for example during compilation you
    may allow patially defined things and only require that there
    are no cycles when you try to fill needed information.
    For example module A could define a type depending on constant
    from module B and module B could define a type depending on
    module A.

    The problem was this, for independent compilation:

    * For any module, there was the implementation, and its interface

    * For a module A, you wrote the implementation, and the compiler
    generated the interface, or the 'exports file', of exported
    entities

    * If module A imported B, then the compiler would need B's
    interface face in order to compile A

    * This means that B had to be compiled first to create that file

    * But if B also imports A, THEN you had a problem!

    There were also issues when A was updated, then modules importing A need
    to be recompiled.

    Those problems don't exist in my current scheme. Not within the modules
    of any one program. The updating one exists across programs. But I don't
    allow cycles between programs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Tue Dec 10 13:56:35 2024
    On 07/12/2024 16:06, David Brown wrote:
    On 06/12/2024 20:20, Bart wrote:

    If your task to get from A to B was split into two, you'd be happy to
    do the first part by a fast car, then complete the rest of it on a
    horse and cart, for no reason at all?


    The comparison was between C to object code (with a real compiler) and
    from X to C and then to the object code (using a real compiler).  If
    your beliefs were true that gcc (and other proper C compilers) are
    incredibly slow, why would it make any difference if someone is starting
    from X or starting from C?  In both cases, compilation would take a long time - C compilation speed is neither more nor less important whether
    you are programming in X or C.

    You don't appear to get it. If you are writing C by hand, then people
    like you would want to use a more powerful, and therefore slower,
    compiler, that will analyse that C. It can also take care of the many shortcomings in the language.

    But if the C has been machine-generated, that analysis is no longer
    relevant. Then you may just want the fastest and simplest conversion.

    This was the basis of my use-case for a fast and possibly compact compiler.


    And you are the only one so far who finds gcc to be inconveniently slow.

    "Mainstream compilers like Clang and GCC are very slow"

    From:

    https://sbaziotis.com/compilers/common-misconceptions-about-compilers.html

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Tue Dec 10 17:16:35 2024
    On 10/12/2024 14:56, bart wrote:
    On 07/12/2024 16:06, David Brown wrote:
    On 06/12/2024 20:20, Bart wrote:

    If your task to get from A to B was split into two, you'd be happy to
    do the first part by a fast car, then complete the rest of it on a
    horse and cart, for no reason at all?


    The comparison was between C to object code (with a real compiler) and
    from X to C and then to the object code (using a real compiler).  If
    your beliefs were true that gcc (and other proper C compilers) are
    incredibly slow, why would it make any difference if someone is
    starting from X or starting from C?  In both cases, compilation would
    take a long time - C compilation speed is neither more nor less
    important whether you are programming in X or C.

    You don't appear to get it.

    No, /you/ don't get it. I did not say that people using language X
    don't care about the speed of C compilation. I said it doesn't matter
    any more or any less than for people writing C.

    If you are writing C by hand, then people
    like you would want to use a more powerful, and therefore slower,
    compiler, that will analyse that C. It can also take care of the many shortcomings in the language.

    But if the C has been machine-generated, that analysis is no longer
    relevant. Then you may just want the fastest and simplest conversion.


    As I said before, the analysis is needed for good optimisation -
    generating static error checking takes very little extra time when you
    are optimising. And often people using C as an intermediary language
    want optimisation of the C code.

    But maybe sometimes they don't, and maybe they want to prioritise the
    fastest practical compilation speed. Then if a smaller tool is faster
    while still being good enough, then it's a benefit to be smaller and/or
    faster.

    The key issue, however, is "good enough". No one would want to use a C compiler that is small and fast if they are not confident that it
    generates correct results, or if it does not target their processor or
    OS, or does not cope with the third-party libraries and code that they
    want to include.


    This was the basis of my use-case for a fast and possibly compact compiler.


    And you are the only one so far who finds gcc to be inconveniently slow.


    Okay, to be more accurate, you are the only one /here/ who has said they
    find compilation of /C/ (not C++) to be /problematically/ slow using gcc
    or clang.

    Is that better?


    No one has ever denied that they'd be happier if their compiler ran
    faster - what people don't, for the most part, want to do is swap their top-shelf compiler with an inferior one simply because it runs faster.
    (And they even more rarely care about the size on the disk.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Tue Dec 10 20:05:24 2024
    On 10/12/2024 16:16, David Brown wrote:
    On 10/12/2024 14:56, bart wrote:
    On 07/12/2024 16:06, David Brown wrote:
    On 06/12/2024 20:20, Bart wrote:

    If your task to get from A to B was split into two, you'd be happy
    to do the first part by a fast car, then complete the rest of it on
    a horse and cart, for no reason at all?


    The comparison was between C to object code (with a real compiler)
    and from X to C and then to the object code (using a real compiler).
    If your beliefs were true that gcc (and other proper C compilers) are
    incredibly slow, why would it make any difference if someone is
    starting from X or starting from C?  In both cases, compilation would
    take a long time - C compilation speed is neither more nor less
    important whether you are programming in X or C.

    You don't appear to get it.

    No, /you/ don't get it.  I did not say that people using language X
    don't care about the speed of C compilation.  I said it doesn't matter
    any more or any less than for people writing C.

    If you are writing C by hand, then people like you would want to use a
    more powerful, and therefore slower, compiler, that will analyse that
    C. It can also take care of the many shortcomings in the language.

    But if the C has been machine-generated, that analysis is no longer
    relevant. Then you may just want the fastest and simplest conversion.


    As I said before, the analysis is needed for good optimisation -

    And as I said before, optimisation is very often not needed.


    generating static error checking takes very little extra time when you
    are optimising.  And often people using C as an intermediary language
    want optimisation of the C code.

    That's a benefit of it yes, but there's also a cost.

    It depends a lot on how everything works. But if I take an old project
    of mine that uses a C transpiler, and apply it to compiler projects that
    I won't bore you with, I get these timings:

    C compiler: Overall (C compilation) Runtime

    cc 0.17 0.08 1.29 secs
    tcc 0.27 0.18 1.56
    gcc-O0 2.63 2.54 1.34
    gcc-O2 12.6 11.7 0.8
    gcc-O3 16.8 15.9 0.8

    The intermediate C is one file. Transpiling to that C takes 0.09 seconds
    in all cases. 'cc' is my newest C compiler (here beating tcc on 'busy' generated code, but that is not typical).

    The runtime is that of running on my largest test input, an extreme
    test. Most inputs are a fraction of the size but finish too quickly to
    measure easily.

    For comparisons, the timings for my normal compiler, going straight to
    EXE and not via C, are:

    mm 0.9 ---- 1.03

    Using tcc-compiled intermediate C would still give a reasonable
    development experience. Using even gcc-O0 100s of times a day would be
    very annoying, for zero benefit.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to bart on Tue Dec 10 20:12:15 2024
    On 10/12/2024 20:05, bart wrote:
    On 10/12/2024 16:16, David Brown wrote:
    On 10/12/2024 14:56, bart wrote:
    On 07/12/2024 16:06, David Brown wrote:
    On 06/12/2024 20:20, Bart wrote:

    If your task to get from A to B was split into two, you'd be happy
    to do the first part by a fast car, then complete the rest of it on
    a horse and cart, for no reason at all?


    The comparison was between C to object code (with a real compiler)
    and from X to C and then to the object code (using a real compiler).
    If your beliefs were true that gcc (and other proper C compilers)
    are incredibly slow, why would it make any difference if someone is
    starting from X or starting from C?  In both cases, compilation
    would take a long time - C compilation speed is neither more nor
    less important whether you are programming in X or C.

    You don't appear to get it.

    No, /you/ don't get it.  I did not say that people using language X
    don't care about the speed of C compilation.  I said it doesn't matter
    any more or any less than for people writing C.

    If you are writing C by hand, then people like you would want to use
    a more powerful, and therefore slower, compiler, that will analyse
    that C. It can also take care of the many shortcomings in the language.

    But if the C has been machine-generated, that analysis is no longer
    relevant. Then you may just want the fastest and simplest conversion.


    As I said before, the analysis is needed for good optimisation -

    And as I said before, optimisation is very often not needed.


    generating static error checking takes very little extra time when you
    are optimising.  And often people using C as an intermediary language
    want optimisation of the C code.

    That's a benefit of it yes, but there's also a cost.

    It depends a lot on how everything works. But if I take an old project
    of mine that uses a C transpiler, and apply it to compiler projects that
    I won't bore you with, I get these timings:

       C compiler:  Overall  (C compilation) Runtime

       cc           0.17       0.08           1.29   secs
       tcc          0.27       0.18           1.56
       gcc-O0       2.63       2.54           1.34
       gcc-O2      12.6       11.7            0.8
       gcc-O3      16.8       15.9            0.8

    The intermediate C is one file. Transpiling to that C takes 0.09 seconds
    in all cases. 'cc' is my newest C compiler (here beating tcc on 'busy' generated code, but that is not typical).

    The runtime is that of running on my largest test input, an extreme
    test. Most inputs are a fraction of the size but finish too quickly to measure easily.

    For comparisons, the timings for my normal compiler, going straight to
    EXE and not via C, are:

       mm           0.9       ----            1.03

    Using tcc-compiled intermediate C would still give a reasonable
    development experience. Using even gcc-O0 100s of times a day would be
    very annoying, for zero benefit.


    Here are somebody else's results:

    "V compiles ≈80k (Clang backend) and ≈400k (x64 and tcc backends) lines
    of code per second. (Apple M2, no optimization)"

    From: https://vlang.io/

    In this case the benefit appears to be 5x as fast using tcc.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to bart on Tue Dec 10 21:32:31 2024
    On 10/12/2024 20:05, bart wrote:

    For comparisons, the timings for my normal compiler, going straight to
    EXE and not via C, are:

       mm           0.9       ----            1.03

    Yikes, I've just slowed it down by factor of 10! Correct figures are:

    mm 0.09 ---- 1.03

    The 0.09 includes Windows process overheads.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to James Kuyper on Wed Dec 11 01:32:22 2024
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    On 12/4/24 15:55, David Brown wrote:
    On 04/12/2024 16:09, Bart wrote:
    ...
    My remarks have been about the namespace that is created by a module.

    I understand that C++ namespaces can be created in other ways, like
    classes.

    In reference to C++, I have been using the term "namespaces" the way C++
    specifically defines the term "namespace". Perhaps I should have given
    a reference to that in some way - this is comp.lang.c, after all.

    What you are now talking about is what C calls "name spaces" - with a
    space. C++ does not use that term in its standards (at least, not in
    the C++20 standards I have open here) - it does not have a clear name
    for the concept, as far as I have found. (I am not nearly as familiar
    with the C++ standards as I am with the C standards, so if this matters
    then perhaps someone else can chime in.)

    The latest version of the C++ standard that I have is n4860.pdf, dated >2020-03-31. It has two occurrences of the phrase "name space" outside of
    the section that descries differences from C:

    8.2p1: "Labels have their own name space ..."
    15.6p8: "There is one name space for macro names."

    All other C++ identifiers reside in the ordinary name space

    Those three namespaces all exist in C. In addition, each C struct or
    union has a separate name space; C++ does not have the same rule, but >achieves a similar effect by giving those names a distinct scope.

    In C struct, union, and enumation tags have their own namespace, in C++
    they reside in the ordinary name space.

    In C++ they reside in the ordinary name space only if they're not
    part of a named namespace.

    namespace x {
    int y;
    };



    Half of all the differences between C and C++ that result in textually >identical code having different well-defined behavior in each language
    are tied to differences in how name spaces and scopes work. Those
    differences are deeply fundamental, and not easily removed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to David Brown on Tue Dec 10 20:25:12 2024
    On 12/4/24 15:55, David Brown wrote:
    On 04/12/2024 16:09, Bart wrote:
    ...
    My remarks have been about the namespace that is created by a module.

    I understand that C++ namespaces can be created in other ways, like
    classes.

    In reference to C++, I have been using the term "namespaces" the way C++ specifically defines the term "namespace". Perhaps I should have given
    a reference to that in some way - this is comp.lang.c, after all.

    What you are now talking about is what C calls "name spaces" - with a
    space. C++ does not use that term in its standards (at least, not in
    the C++20 standards I have open here) - it does not have a clear name
    for the concept, as far as I have found. (I am not nearly as familiar
    with the C++ standards as I am with the C standards, so if this matters
    then perhaps someone else can chime in.)

    The latest version of the C++ standard that I have is n4860.pdf, dated 2020-03-31. It has two occurrences of the phrase "name space" outside of
    the section that descries differences from C:

    8.2p1: "Labels have their own name space ..."
    15.6p8: "There is one name space for macro names."

    All other C++ identifiers reside in the ordinary name space

    Those three namespaces all exist in C. In addition, each C struct or
    union has a separate name space; C++ does not have the same rule, but
    achieves a similar effect by giving those names a distinct scope.

    In C struct, union, and enumation tags have their own namespace, in C++
    they reside in the ordinary name space.

    Half of all the differences between C and C++ that result in textually identical code having different well-defined behavior in each language
    are tied to differences in how name spaces and scopes work. Those
    differences are deeply fundamental, and not easily removed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Wed Dec 11 02:21:05 2024
    On 09/12/2024 18:46, Janis Papanagnou wrote:
    On 07.12.2024 16:33, Bart wrote:

    You're being aggressive.

    Am I?

    That and more.

    It says something however when I actually believed that that code was
    valid, because the compiler appeared to say so.

    Huh?

    Yes. I've seen enough jaw-dropping examples of C code that turned out to
    be legal, that now I wouldn't be surprised at anything.


    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    You can easily parse a language in an ambiguous syntax. For example, if
    a particular ambiguity is unlikely to arise in practice (maybe it's one
    of your examples that you say nobody would ever write).


    You postulate it as if the grammar were convoluted;

    My opinion is that it is. Especially its propensity for using
    long-winded production terms that look confusingly similar. (Would it
    have killed somebody to make the names more distinct?)

    So you're a parser and you see this:

    do ... while

    How do you know whether that 'while' starts a new nested loop or
    terminates this one?

    Because there's the '...' in between that answers that question.

    Oh, I see. That answers everything! Including having a '...' that
    includes statements starting with 'while'.

    So you've got it?

    It looks like /you/ have now that I've explained it to you.

    My opinion about this feature remains the same, that it was a poor
    design choice. One of dozens of such choices. An unambiguous grammar
    does not by itself make for a good syntax.

    You however seem utterly incapable of criticising C. Could you write an
    article all about its quirks and gotchas and flaws? I doubt it.

    But suppose you do exactly that. What would you then think about those
    who dismissed it and suggested you are simply too stupid to understand
    it or are just deliberately making it out to be a lot worse than it is?

    Take this well-known gotcha:

    int* p, q r;

    You of course would never for one moment think that these were three
    pointers; if you were to write this, it would be because you /wanted/
    the one pointer and two integers!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to David Brown on Wed Dec 11 05:37:15 2024
    David Brown <david.brown@hesbynett.no> wrote:
    On 30/11/2024 18:38, Bart wrote:
    It will at least work with more compiles.


    And why would that matter? No actual developer would care if their code
    can be compiled by your little toy compiler, or even more complete
    little tools like tcc. Code needs to work on the compilers that are
    suitable for the job - compatibility with anything else would just be a
    waste of effort and missing out on useful features that makes the code better.

    You are exagerating and that does not help communication. In this
    group there were at least one serious poster claiming to write code
    depending only on features from older C standard. People like this
    presumably would care if some "toy" compiler discoverd non-compliance. Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    In may coding I use gcc extentions when I feel that there is
    substantial gain. But for significant part of my code I prefer
    to portablility, and that may include avoiding features not
    supported by lesser compilers. I the past tcc was not able
    to compile code which I consider rather ordinary C, and due
    to this and lack of support for my main target I did not use
    tcc. But tcc improved, ATM I do not know if it is good enough
    for me, but it passed initial tests, so I have no reason to
    disregard it.

    BTW: IME "exotic" tools and targets help with finding bugs.
    So even if you do not normally need to compile with some
    compiler it makes sense to check if it works.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ike Naar@21:1/5 to Janis Papanagnou on Wed Dec 11 08:43:00 2024
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    <statement>:
    ...
    <selection-statement>
    ...

    <selection-statement>:
    ...
    if ( <expression> ) <statement>
    if ( <expression> ) <statement> else <statement>
    ...

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    it has two possible parsings:

    if (E1) <statement> else S2

    where <statement> expands to

    if (E2) S1

    or

    if (E1) <statement>

    where <statement> expands to

    if (E2) S1 else S2

    The grammatical ambiguity is resolved by an additional rule in the
    'Semantics' section for selection-statement:

    3 An else is associated with the lexically nearest preceding if that is
    allowed by the syntax.

    gcc -Wall will issue a warning for such an ambiguous statement:

    warning: suggest explicit braces to avoid ambiguous 'else' [-Wdangling-else]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Waldek Hebisch on Wed Dec 11 11:18:56 2024
    On Wed, 11 Dec 2024 05:37:15 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    David Brown <david.brown@hesbynett.no> wrote:
    On 30/11/2024 18:38, Bart wrote:
    It will at least work with more compiles.


    And why would that matter? No actual developer would care if their
    code can be compiled by your little toy compiler, or even more
    complete little tools like tcc. Code needs to work on the
    compilers that are suitable for the job - compatibility with
    anything else would just be a waste of effort and missing out on
    useful features that makes the code better.

    You are exagerating and that does not help communication. In this
    group there were at least one serious poster claiming to write code
    depending only on features from older C standard.

    For some definition of "serious".

    People like this
    presumably would care if some "toy" compiler discoverd non-compliance. Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    In may coding I use gcc extentions when I feel that there is
    substantial gain. But for significant part of my code I prefer
    to portablility, and that may include avoiding features not
    supported by lesser compilers. I the past tcc was not able
    to compile code which I consider rather ordinary C, and due
    to this and lack of support for my main target I did not use
    tcc. But tcc improved, ATM I do not know if it is good enough
    for me, but it passed initial tests, so I have no reason to
    disregard it.

    BTW: IME "exotic" tools and targets help with finding bugs.
    So even if you do not normally need to compile with some
    compiler it makes sense to check if it works.


    I would think that the main reason for David Brown's absence of
    interest in tcc is simply because tcc do not have back ends for
    targets that he cares about.
    In particular, Arm port appears to be abandoned in 2003, so quite
    likely tcc can't generate code that runs on MCUs with ARMv7-M
    architecture that happens to be released first in the same year and
    officially named in the 2004.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Michael S on Wed Dec 11 11:57:40 2024
    On 11/12/2024 09:18, Michael S wrote:
    On Wed, 11 Dec 2024 05:37:15 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    You are exagerating and that does not help communication. In this
    group there were at least one serious poster claiming to write code
    depending only on features from older C standard.

    For some definition of "serious".

    People like this
    presumably would care if some "toy" compiler discoverd non-compliance.
    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    In may coding I use gcc extentions when I feel that there is
    substantial gain. But for significant part of my code I prefer
    to portablility, and that may include avoiding features not
    supported by lesser compilers. I the past tcc was not able
    to compile code which I consider rather ordinary C, and due
    to this and lack of support for my main target I did not use
    tcc. But tcc improved, ATM I do not know if it is good enough
    for me, but it passed initial tests, so I have no reason to
    disregard it.

    BTW: IME "exotic" tools and targets help with finding bugs.
    So even if you do not normally need to compile with some
    compiler it makes sense to check if it works.


    I would think that the main reason for David Brown's absence of
    interest in tcc is simply because tcc do not have back ends for
    targets that he cares about.
    In particular, Arm port appears to be abandoned in 2003, so quite
    likely tcc can't generate code that runs on MCUs with ARMv7-M
    architecture that happens to be released first in the same year and officially named in the 2004.

    I remember running TCC on both RPi1 (2012) and RPi4 (2019). That would
    be ARM32 (some version of ARMv7 I guess; I find ARM model numbers
    bewildering).

    It's possible I also tried TCC in the ARM64 mode of RPi4.

    So it sounds rather unlikely that TCC doesn't support ARM.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Janis Papanagnou on Wed Dec 11 13:59:52 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 07.12.2024 16:33, Bart wrote:

    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    You use different grammar for parsing. As Ike noted C has "dangling
    else" problem, this is well known and silently corrected by parser
    generators (they use different grammar than the one you gave them).

    If take grammar from C standard you will notice that it can not
    parse C regardless of "dangling else" problem. The situation is
    resonably well described by word "disconnected". In C90 grammar
    the is one nonterminal that can not be produced by any grammar rule
    (IIRC this is 'type-name'). If you try to correct the problem by
    adding rule that identifier can be a type name you get grammar that
    does not work with usual tools (I think that this grammar is
    unambiguous, but is quite inconvenient for parsing).

    Usial approach for parsing C uses semantic rules: 'type-name'
    is produced from 'identifier' after symbol-table loopup. But
    the effect is that syntax of C language is not described by the
    grammar from the standard alone.

    One approach that was advocated for C (and I used in different
    context) is superset approach: you write unambigious grammar for
    bigger language which produces resonably similar parse tree.
    Then semantic information + local tree transformations are used
    to reject invalid programs and to transform parse tree.
    So there is unambigious grammar, but this grammar is an artifact
    of parsing process, not the official language grammar.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to bart on Wed Dec 11 14:39:47 2024
    bart <bc@freeuk.com> wrote:
    On 09/12/2024 18:46, Janis Papanagnou wrote:
    On 07.12.2024 16:33, Bart wrote:

    So you're a parser and you see this:

    do ... while

    How do you know whether that 'while' starts a new nested loop or
    terminates this one?

    Because there's the '...' in between that answers that question.

    Oh, I see. That answers everything! Including having a '...' that
    includes statements starting with 'while'.

    C grammar is not LL(1), that is you can not recognize a construct
    looking at its first token. You need the whole construct and
    sometimes also the following token. And there are also well
    known troubles due to type names and "dangling else". So C
    is almost, but not entirely LR(1). But the description, that
    is grammar + extra rules is unambigious, not very complex and
    it is well-known how to parse C with good efficiency. You
    can write confusing code, but the are ways to make it more
    readible.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Wed Dec 11 16:10:04 2024
    On 11/12/2024 10:18, Michael S wrote:

    I would think that the main reason for David Brown's absence of
    interest in tcc is simply because tcc do not have back ends for
    targets that he cares about.
    In particular, Arm port appears to be abandoned in 2003, so quite
    likely tcc can't generate code that runs on MCUs with ARMv7-M
    architecture that happens to be released first in the same year and officially named in the 2004.


    That is definitely the reason why I reject it out of hand for my work,
    yes. It wouldn't matter if it generated code ten times faster than gcc
    using one percent of the compile time - if it doesn't support the target
    you need, it is useless for the job. (Bart never seems to understand
    that issue.)

    I can understand that there was a time when tcc could make sense as a C compiler for a C programmer. But that time is long past, and I have yet
    to see a convincing reason why it should be a realistic choice now for
    more than a few niche uses.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to bart on Wed Dec 11 16:26:08 2024
    On Wed, 11 Dec 2024 11:57:40 +0000
    bart <bc@freeuk.com> wrote:

    On 11/12/2024 09:18, Michael S wrote:
    On Wed, 11 Dec 2024 05:37:15 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    You are exagerating and that does not help communication. In this
    group there were at least one serious poster claiming to write code
    depending only on features from older C standard.

    For some definition of "serious".

    People like this
    presumably would care if some "toy" compiler discoverd
    non-compliance. Concerning tcc, they have explicit endorsment from
    gawk developer: he likes compile speed and says that gawk compiles
    fine using tcc.

    In may coding I use gcc extentions when I feel that there is
    substantial gain. But for significant part of my code I prefer
    to portablility, and that may include avoiding features not
    supported by lesser compilers. I the past tcc was not able
    to compile code which I consider rather ordinary C, and due
    to this and lack of support for my main target I did not use
    tcc. But tcc improved, ATM I do not know if it is good enough
    for me, but it passed initial tests, so I have no reason to
    disregard it.

    BTW: IME "exotic" tools and targets help with finding bugs.
    So even if you do not normally need to compile with some
    compiler it makes sense to check if it works.


    I would think that the main reason for David Brown's absence of
    interest in tcc is simply because tcc do not have back ends for
    targets that he cares about.
    In particular, Arm port appears to be abandoned in 2003, so quite
    likely tcc can't generate code that runs on MCUs with ARMv7-M
    architecture that happens to be released first in the same year and officially named in the 2004.

    I remember running TCC on both RPi1 (2012) and RPi4 (2019). That
    would be ARM32 (some version of ARMv7 I guess; I find ARM model
    numbers bewildering).

    It's possible I also tried TCC in the ARM64 mode of RPi4.


    ARMv7-AR architecture supports both fixed-width encoding (what's
    named A32 in ARMv8 docs) and variable-width encoding (T32 in ARMv8
    docs) a.k.a. Thumb-2
    ARMv7-M on the other hand supports only variable-width encoding.

    RPIi1 is ARM11 which is architecturally ARMv6 (i.e. before T32).
    RPi4 is Cortex-A72 which is architecturally ARMv8-A.
    Both of them can run fixed-width 32-bit encoded (A32) code fine.

    Overwhelming majority of microcontrollers are based on various Cortex-M
    cores (Cortex-M4 is most popular by far) and they can't run such code.


    So it sounds rather unlikely that TCC doesn't support ARM.


    But at least from the little docs that I was able to locate it looks
    likely that it does not support Thumb-2.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Waldek Hebisch on Wed Dec 11 16:03:35 2024
    On 11/12/2024 06:37, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 30/11/2024 18:38, Bart wrote:
    It will at least work with more compiles.


    And why would that matter? No actual developer would care if their code
    can be compiled by your little toy compiler, or even more complete
    little tools like tcc. Code needs to work on the compilers that are
    suitable for the job - compatibility with anything else would just be a
    waste of effort and missing out on useful features that makes the code
    better.

    You are exagerating and that does not help communication.

    That is probably a fair comment.

    But in this case, I don't think it is much of an exaggeration. Most programmers of any language do the work primarily because they are paid
    to do so. I find it highly implausible that someone would pay a
    professional programmer to write code with a view to compatibility with
    tools that are not realistically useful for the task in hand, or the foreseeable future. And for people programming for fun, learning or
    hobby, I can't imagine many pay much attention to supporting rare and
    unusual tools.

    Some people aim to make their code highly portable, even beyond the
    tools they normally use. But that is generally either a matter of
    sticking tightly to a particular C standard or an additional standard
    (such as POSIX). And some types of code can be made to support multiple embedded compilers, which can mean using hooks, macros or similar tricks
    to conveniently support compiler-specific extensions (such as for
    "packing" structs, or inline assembly).

    Who, however, is going to write C code and put effort into making sure
    it is /specifically/ portable to tools like tcc? People interested in benchmarking or otherwise testing C compilers might. There are probably
    a few people who use tcc as their main C compiler (presumably on
    Windows, since *nix users will need good reason to use something other
    than their system compiler, and that typically implies switching to
    something better than their system compiler).

    People write code to work with the tools they use, and tools they expect
    to be used with the code. They don't go out of their way to check compatibility with tools. Thus C code written for Linux systems often
    won't compile with MSVC, and C code written for MSVC often won't compile
    with gcc or clang.

    (Of course plenty of code will coincidentally work fine with tcc - it
    doesn't keep up with modern C standards, but it still tries to be quite conforming and it supports a number of gcc extensions. So if you write
    a C library and stick to C99, for example, then it will likely work fine
    with tcc.)


    Some code generators, including transpilers, support tcc. If the tool
    is intended to be used on Windows then that makes sense since there is
    no default compiler there, and it makes installation easier.


    In this
    group there were at least one serious poster claiming to write code
    depending only on features from older C standard.

    Would that be the person who thinks that after armageddon we will all go
    back to using C90 on mainframes? I'm not sure that individual can be
    taken seriously.

    But certainly there are people who, for good reasons or bad, stick to
    older C standards. If that is of interest to you, then you would want
    to use "gcc -std=c90 -Wpedantic", or similar, to help spot deviations
    from that.

    People like this
    presumably would care if some "toy" compiler discoverd non-compliance.

    Yes, but such compilers are not good tools for that purpose. tcc does
    not in any way attempt to spot deviations from any standard. As far as
    I can tell from its documentation, it supports C89/C90, "many features
    of the new C standard: ISO C99", some gcc extensions, and some of its
    own TinyCC extensions. And there is no flags for controlling these or
    setting "conforming" modes.

    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    Is that so that you can say I am wrong to claim "no one" cares about tcc support, because you have found 1 person who has used it? I admit it -
    "no one" was an exaggeration.


    In may coding I use gcc extentions when I feel that there is
    substantial gain. But for significant part of my code I prefer
    to portablility,

    Sure - I think most of us do that.

    and that may include avoiding features not
    supported by lesser compilers.

    I think very few care about that bit. I'll use a gcc extension if it
    makes a noticeable improvement to the code - making the source code
    nicer in some way, improving static error checking, or improving the
    efficiency of the object code. But I certainly won't avoid a standard C feature just because some lesser compilers might not support it!

    I the past tcc was not able
    to compile code which I consider rather ordinary C, and due
    to this and lack of support for my main target I did not use
    tcc. But tcc improved, ATM I do not know if it is good enough
    for me, but it passed initial tests, so I have no reason to
    disregard it.

    BTW: IME "exotic" tools and targets help with finding bugs.
    So even if you do not normally need to compile with some
    compiler it makes sense to check if it works.


    Using similar quality or better tools can be an aid. Maybe if you are
    not sure about something, you check with both gcc and clang instead of
    just one of them. When using weaker tools (for specific embedded
    targets), I have used gcc as a static error checker in parallel with the
    actual compiler.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ike Naar on Wed Dec 11 16:28:28 2024
    On 11/12/2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    <statement>:
    ...
    <selection-statement>
    ...

    <selection-statement>:
    ...
    if ( <expression> ) <statement>
    if ( <expression> ) <statement> else <statement>
    ...

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    it has two possible parsings:

    if (E1) <statement> else S2

    where <statement> expands to

    if (E2) S1

    or

    if (E1) <statement>

    where <statement> expands to

    if (E2) S1 else S2

    The grammatical ambiguity is resolved by an additional rule in the 'Semantics' section for selection-statement:

    3 An else is associated with the lexically nearest preceding if that is
    allowed by the syntax.


    Given that the resolution is in the "semantics" section rather than the "syntax" section, it might seem like a grammatical ambiguity. But I
    don't think it is, technically - the syntax rules say that the set of
    tokens making up "if (E1) if (E2) S1 else S2" are valid syntax. It is
    up to the semantics to determine what the code will do here. (And the semantics are unambiguous.)

    gcc -Wall will issue a warning for such an ambiguous statement:

    warning: suggest explicit braces to avoid ambiguous 'else' [-Wdangling-else]

    gcc is not warning about ambiguity - it is well specified exactly what
    the code means in the language. It is warning because it might not be
    clear to the human reader and/or programmer.

    Certainly such nested "if" statements without braces can be confusing to people, and they may require extra effort in a parser. But they are not
    an ambiguity in the language.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Wed Dec 11 15:34:24 2024
    On 11/12/2024 14:39, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:
    On 09/12/2024 18:46, Janis Papanagnou wrote:
    On 07.12.2024 16:33, Bart wrote:

    So you're a parser and you see this:

    do ... while

    How do you know whether that 'while' starts a new nested loop or
    terminates this one?

    Because there's the '...' in between that answers that question.

    Oh, I see. That answers everything! Including having a '...' that
    includes statements starting with 'while'.

    C grammar is not LL(1), that is you can not recognize a construct
    looking at its first token. You need the whole construct and
    sometimes also the following token. And there are also well
    known troubles due to type names and "dangling else".

    I can't call it 'context sensitive' because that is a technical term
    with a specific meaning, but it would be a good description.

    You need input from a symbol table in order to parse C, a table that the
    parser needs to maintain as it processes source code. That will tell you whether a particular identifier is a typename or not.

    There are issues also with keywords like 'break'.

    So C
    is almost, but not entirely LR(1). But the description, that
    is grammar + extra rules is unambigious, not very complex and
    it is well-known how to parse C with good efficiency.

    It's harder than it need be. You can go quite a way into a declaration
    before you even know whether it's a function definition, a function declaration, a variable declaration/definition, or even a typedef
    definition, since 'typedef' can appear towards the end of the basetype:

    long const unsigned long int typedef T();

    This defines T as an alias for a function (not a pointer to one) that
    takes no parameters and returns 'const u64'; another quirk that you
    don't see in other languages.

    The trouble with 'while' is that what determines whether a particular
    'while' ends the last 'do' statement, or starts a new while-loop, is too subtle. Even if technically unambiguous, it can be confusing in source
    code, and adding or removing a single semicolon can make a big difference.

    It also relies on a characteristic of C syntax that are not present in
    all languages (allowing a single statement within each branch of body of
    a structured statement), so you wouldn't be able to use such a
    dual-purpose keyword in other quite common languages.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Wed Dec 11 16:15:25 2024
    On 11/12/2024 12:57, bart wrote:
    On 11/12/2024 09:18, Michael S wrote:
    On Wed, 11 Dec 2024 05:37:15 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    You are exagerating and that does not help communication.  In this
    group there were at least one serious poster claiming to write code
    depending only on features from older C standard.

    For some definition of "serious".

    People like this
    presumably would care if some "toy" compiler discoverd non-compliance.
    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    In may coding I use gcc extentions when I feel that there is
    substantial gain.  But for significant part of my code I prefer
    to portablility, and that may include avoiding features not
    supported by lesser compilers.  I the past tcc was not able
    to compile code which I consider rather ordinary C, and due
    to this and lack of support for my main target I did not use
    tcc.  But tcc improved, ATM I do not know if it is good enough
    for me, but it passed initial tests, so I have no reason to
    disregard it.

    BTW: IME "exotic" tools and targets help with finding bugs.
    So even if you do not normally need to compile with some
    compiler it makes sense to check if it works.


    I would think that the main reason for David Brown's absence of
    interest in tcc is simply because tcc do not have back ends for
    targets that he cares about.
    In particular, Arm port appears to be abandoned in 2003, so quite
    likely tcc can't generate code that runs on MCUs with ARMv7-M
    architecture that happens to be released first in the same year and
    officially named in the 2004.

    I remember running TCC on both RPi1 (2012) and RPi4 (2019). That would
    be ARM32 (some version of ARMv7 I guess; I find ARM model numbers bewildering).

    It's possible I also tried TCC in the ARM64 mode of RPi4.

    So it sounds rather unlikely that TCC doesn't support ARM.


    The difference between ARM core generations, architecture numbers, and
    other numberings is not at all easy to follow. There are also different encodings available for the same instruction set, and of course many
    extensions (not quite as many as in the x86 world, but many).

    Suffice it to say that as far as code generation is concerned, the
    Cortex-A devices on the RPi's are completely different from the Cortex-M devices in microcontrollers. It's like comparing the 80286 with the Z80A.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Wed Dec 11 17:46:50 2024
    On 11.12.2024 16:28, David Brown wrote:
    On 11/12/2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    An unambiguous grammar is something quite essential; [...]

    [ dangling-else sample ]

    Given that the resolution is in the "semantics" section rather than the "syntax" section, it might seem like a grammatical ambiguity. But I
    don't think it is, technically - the syntax rules say that the set of
    tokens making up "if (E1) if (E2) S1 else S2" are valid syntax. It is
    up to the semantics to determine what the code will do here. (And the semantics are unambiguous.)

    I'm a bit ambivalent about that. - Yes, technically it's syntax, it's syntactically probably correct, and it has a semantical ambiguity that
    needs to be resolved. All languages with the dangling-else property do
    resolve that. But the syntax could have been defined in a way that such
    that a dangling else cannot appear in the first place. (Not in "C" and descendant languages, of course; that ship has sailed.) - Personally I
    thus appreciate languages with if-then-elif-else-fi sorts of syntaxes.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Wed Dec 11 17:24:25 2024
    On 11.12.2024 03:21, bart wrote:
    On 09/12/2024 18:46, Janis Papanagnou wrote:

    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    You can easily parse a language in an ambiguous syntax. [...]

    Sure; I recall Fortran had such an ambiguity, I think it was in
    context of FOR loops (something with the assignment and commas,
    IIRC). - Whether it's "easily [to] parse" is arguable, though,
    and certainly depends. - But I don't recall to have seen scary
    things like that in any other language I had to do with.

    Experienced language developers wouldn't define an ambiguous
    syntax in the first place. So what do you think your statement
    contributes to desire to have an "unambiguous syntax"?

    I mean, if you get confused by an unambiguous syntaxes already,
    what do you think happens with people if they have to program
    in or understand an ambiguous language!


    You postulate it as if the grammar were convoluted;

    My opinion is that it is. Especially its propensity for using
    long-winded production terms that look confusingly similar. (Would it
    have killed somebody to make the names more distinct?)

    (I won't comment on your opinion.)

    With respect to distinctness of names I thought we had already
    exchanged some words - remember my 'while' and 'until' samples
    from Pascal (that somehow offended you)?

    Concerning "C"; I don't see why you shouldn't name a "positive"
    conditioned control construct consistently(!) as 'while' whether
    it controls a loop entry or a loop exit, and to name a "negative"
    conditioned control construct consistently(!) as 'until'.

    It's beyond me why one wants to replace a semantically consistent
    set like

    'while' positive-case 'do' ...
    'until' negative-case 'do' ...
    'do' ... 'while' positive-case
    'do' ... 'until' negative-case

    by, say,

    'pre_while' positive-case 'do' ...
    'pre_until' negative-case 'do' ...
    'do' ... 'post_while' positive-case
    'do' ... 'post_until' negative-case

    (Feel free to find better names than 'pre_xxx' and 'post_xxx'; it
    wouldn't change the "semantical consistency" argument.)


    So you're a parser and you see this:

    do ... while

    How do you know whether that 'while' starts a new nested loop or
    terminates this one?

    Because there's the '...' in between that answers that question.

    Oh, I see. That answers everything! Including having a '...' that
    includes statements starting with 'while'.

    Yes, the "syntax" is not only an isolated symbol. - Please keep my
    suggestion in mind to consider learning about formal languages and
    grammars. (I think for a compiler writer it should be a given.)

    If you look at symbols like a tokenizer you won't understand what
    any programmer needs to know to understand a language; (besides
    other things) the structure!

    [...]

    My opinion about this feature remains the same, that it was a poor
    design choice. One of dozens of such choices. An unambiguous grammar
    does not by itself make for a good syntax.

    No one said it would.


    You however seem utterly incapable of criticising C.

    I already said that 98% of your imputations are certainly wrong and
    you should just stop that; even if you have no argument, better just
    shut up instead. - In this case, though, there wouldn't even have
    been the need for you to make imputations; my various criticisms on
    the language "C" is quite good documented in this newsgroup.

    I already said that I had a lot of criticism with various languages
    that I'm programming with, but, as oppose to you, I don't complain
    constantly and repeatedly about that. You could also have observed
    that many folks here (also repeatedly) told you that they know about
    the [real] deficiencies of the "C" language.

    Could you write an
    article all about its quirks and gotchas and flaws? I doubt it.

    Of course I could. I could even write articles about pros and cons
    of every language I've made experiences with; on a principal level
    (for example design) and on a practical level. (But why should I?)

    The problem(s) that you have is (are) far beyond what I'd consider
    to be a sensible criticism. But I accept that you have own opinions
    on what's a problem [to you].

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Ike Naar on Wed Dec 11 17:30:51 2024
    On 11.12.2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).

    (The ambiguity [in Fortran] that I mentioned elsethread is a more
    obscure candidate.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Wed Dec 11 17:47:40 2024
    On 11/12/2024 17:30, Janis Papanagnou wrote:
    On 11.12.2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).


    It is easy to avoid in a C-like language - simply require braces on "if" statements, or at the very least, require them when there is an "else"
    clause. Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do. (Or they misinterpret it.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Wed Dec 11 17:51:09 2024
    On 11.12.2024 17:47, David Brown wrote:
    On 11/12/2024 17:30, Janis Papanagnou wrote:
    On 11.12.2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote: >>>> An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).

    It is easy to avoid in a C-like language - simply require braces on "if" statements, or at the very least, require them when there is an "else" clause.

    Yes, sure. But, I can't help, it smells like a workaround.

    Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do. (Or they misinterpret it.)

    Yes, true. (We had that in our standards, too.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Ben Bacarisse on Wed Dec 11 08:52:54 2024
    Ben Bacarisse <ben@bsb.me.uk> writes:

    Bart <bc@freeuk.com> writes:

    On 07/12/2024 21:00, David Brown wrote:

    <snip purely subjective opinion on unrealistic code>

    You mean that /real/ example where a function needed a type written 6 times >> instead of once? OK.

    I've always wondered why prototypes in C did not simply use the existing syntax for declarations. After all, it was right there in K&R C, just outside the parentheses:

    f(m, n, s)
    int m, n;
    char *s;
    { ... }

    could have become

    f(int m, n; char *s)
    { ... }

    rather than

    f(int m, int n, char *s)
    { ... }

    Does anyone know if there even /was/ a reason?

    My speculation follows.

    Prototypes in C came from C++. The language that became C++
    started pretty early, before 1980 IIRC. To add types to function
    parameters it would have been natural to simply add a type before
    the named parameter. Of course to be more flexible a full
    declarator rather than just a type name should be allowed. That
    change should be easy to make in a C grammar and parser. The idea
    of using multi-declarator declarations might not have occurred to
    the pre-C++ language designer(s); or it may have been judged to
    need too much effort or not be necessary (or add enough value).
    Also there is another difference between declarations given in a
    block/file scope and declarations given in a prototype scope: in
    one case the order of declarators doesn't matter but in the other
    case it does. Furthermore there is the question of what to do for
    function declarations, as opposed to definitions, where parameter
    names are not given, but just types.

    Assuming all that was done before the C standardization effort
    really got rolling, which I think is a distinct possibility, the
    most likely decision would be simply to adopt the existing C++
    syntax wholesale, and not consider changing it. Anyway that is my
    guess.

    If the question were being considered anew, I would be inclined to
    come down on the side of keeping the one-parameter-only form, and
    not allowing multiple parameters to share a single type name.
    There doesn't seem to be much benefit in allowing more than one
    declarator per type name; I think the strongest argument is
    syntactic consistency with block/file/struct scope declarations,
    but those contexts aren't quite the same as prototype scope (for
    different reasons in the different cases). If there is no
    significant benefit, simpler is better, and consistency be damned.

    One change I would like to see made, and to have been made, is to
    allow a trailing comma in function declarations, definitions, and
    calls. A smaller change, and a larger benefit, would give a win
    here. At least that is my thinking on the matter.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Wed Dec 11 19:22:49 2024
    On Wed, 11 Dec 2024 16:15:25 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    Suffice it to say that as far as code generation is concerned, the
    Cortex-A devices on the RPi's are completely different from the
    Cortex-M devices in microcontrollers. It's like comparing the 80286
    with the Z80A.


    With exception of RPi1, saying so would be an exaggeration.
    RPi2 through 5 are technically capable to run Thumb2-encoded user level routines.
    May be, mutual incompatibility with MCUs would become true again in the
    next generation of RPi. But more likely it would not happen until RPi7.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Wed Dec 11 17:20:06 2024
    On 11/12/2024 16:51, Janis Papanagnou wrote:
    On 11.12.2024 17:47, David Brown wrote:
    On 11/12/2024 17:30, Janis Papanagnou wrote:
    On 11.12.2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote: >>>>> An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).

    It is easy to avoid in a C-like language - simply require braces on "if"
    statements, or at the very least, require them when there is an "else"
    clause.

    Yes, sure. But, I can't help, it smells like a workaround.

    Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do. (Or they misinterpret it.)

    Yes, true. (We had that in our standards, too.)

    So here you finally acknowledge there may be ambiguity from a human perspective.

    But when I try to make that very point, it's me making up unrealistic
    examples; I'm being deliberately obtuse; I clearly find things confusing
    that no one else has a problem with; or you make snarky comments like this:

    "I mean, if you get confused by an unambiguous syntaxes already,
    what do you think happens with people if they have to program
    in or understand an ambiguous language!"

    It's astonishing how I have to fight across a dozen posts to back up my
    point of view (you even specifically said you didn't recognise my point).

    And yet here: somebody makes that very same point, and you merely say:

    "Yes, true."

    It really is extraordinary.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Wed Dec 11 21:35:06 2024
    On 11/12/2024 18:22, Michael S wrote:
    On Wed, 11 Dec 2024 16:15:25 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    Suffice it to say that as far as code generation is concerned, the
    Cortex-A devices on the RPi's are completely different from the
    Cortex-M devices in microcontrollers. It's like comparing the 80286
    with the Z80A.


    With exception of RPi1, saying so would be an exaggeration.
    RPi2 through 5 are technically capable to run Thumb2-encoded user level routines.

    I did not know that the 64-bit Cortex-A devices could run 32-bit
    Thumb2-encoded instructions. That does reduce the difference somewhat.

    Compilers targeting 64-bit ARM would generate 64-bit (AArch64)
    instructions, which are of course significantly different. But perhaps
    a compiler targeting 32-bit Cortex-A devices might be able to generate
    Thumb2 instructions.

    However, you would not expect binary compatibility between code
    generated for a 32-bit Cortex-M device and a Cortex-A platform, even if
    it supports Thumb2 instructions - you have major differences in the ABI,
    memory layouts, and core features beyond the basic registers.


    May be, mutual incompatibility with MCUs would become true again in the
    next generation of RPi. But more likely it would not happen until RPi7.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Wed Dec 11 21:36:48 2024
    On 11/12/2024 17:51, Janis Papanagnou wrote:
    On 11.12.2024 17:47, David Brown wrote:
    On 11/12/2024 17:30, Janis Papanagnou wrote:
    On 11.12.2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote: >>>>> An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).

    It is easy to avoid in a C-like language - simply require braces on "if"
    statements, or at the very least, require them when there is an "else"
    clause.

    Yes, sure. But, I can't help, it smells like a workaround.

    If C had that requirement, it would not be a workaround - it would be a
    fixed part of the grammar. The current definition of C, with optional
    braces and an extra "semantics" clause seems more like a workaround to me.


    Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do. (Or they misinterpret it.)

    Yes, true. (We had that in our standards, too.)

    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Wed Dec 11 21:46:16 2024
    On 11/12/2024 18:20, bart wrote:
    On 11/12/2024 16:51, Janis Papanagnou wrote:
    On 11.12.2024 17:47, David Brown wrote:
    On 11/12/2024 17:30, Janis Papanagnou wrote:
    On 11.12.2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com>
    wrote:
    An unambiguous grammar is something quite essential; how would you >>>>>> parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

          if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).

    It is easy to avoid in a C-like language - simply require braces on "if" >>> statements, or at the very least, require them when there is an "else"
    clause.

    Yes, sure. But, I can't help, it smells like a workaround.

    Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do.  (Or they misinterpret it.)

    Yes, true. (We had that in our standards, too.)

    So here you finally acknowledge there may be ambiguity from a human perspective.

    I don't think anyone has ever disagreed that you can write "if"
    statements with "else" in C in a way that is confusing or unclear to
    human readers. (But it still has fixed and unambiguous meaning to the compiler.)

    Equally, of course, it is possible to write them in a way that is not
    confusing or unclear at all.

    But there is no ambiguity in the language itself - only possible
    confusions from the way the language could be used. (And since the
    language is well defined here, it doesn't make sense to call it an
    ambiguity at all, even "from a human perspective". Call it unclear,
    confusing, or deceptive code if you like.)

    I don't see that anyone has changed their position on this.


    But when I try to make that very point, it's me making up unrealistic examples; I'm being deliberately obtuse; I clearly find things confusing
    that no one else has a problem with; or you make snarky comments like this:


    Sure.

    We all know it is possible to write unclear and confusing C code.
    There's a whole competition devoted to it!

    But we also all know that most C programmers - like programmers of any
    other language - usually avoid writing code they find unclear. (Clarity
    is quite subjective - a solid proportion of programmers will agree
    roughly on a set of guidelines, but there will be outliers with very
    different positions. This is independent of language.)


    "I mean, if you get confused by an unambiguous syntaxes already,
    what do you think happens with people if they have to program
    in or understand an ambiguous language!"

    It's astonishing how I have to fight across a dozen posts to back up my
    point of view (you even specifically said you didn't recognise my point).

    And yet here: somebody makes that very same point, and you merely say:

    "Yes, true."

    It really is extraordinary.


    It was a totally different point. It is extraordinary that you can't
    see that.

    You claimed the language and its grammar was ambiguous and confusing.
    It is not.

    Others have noted that code written in the language can be confusing,
    and it's best to have standards or guidelines to avoid that. That is true.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to bart on Thu Dec 12 00:03:00 2024
    On Wed, 11 Dec 2024 21:19:54 +0000
    bart <bc@freeuk.com> wrote:


    This also comes up with 'while (cond); {...}'.


    $ cat foo.c
    void foo(int x)
    {
    while (x--);
    bar();
    }

    $ clang-format < foo.c
    void foo(int x) {
    while (x--)
    ;
    bar();
    }

    Do I use clamg-format myself? No, I don't.

    And I don't know why C formatters are generally less popular among C programmers then, for example, go formater among Go programmers or Rust formatter among Rust programmers.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Wed Dec 11 21:19:54 2024
    On 11/12/2024 20:46, David Brown wrote:
    On 11/12/2024 18:20, bart wrote:
    On 11/12/2024 16:51, Janis Papanagnou wrote:
    On 11.12.2024 17:47, David Brown wrote:

    Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do.  (Or they misinterpret it.)

    Yes, true. (We had that in our standards, too.)

    So here you finally acknowledge there may be ambiguity from a human
    perspective.

    I don't think anyone has ever disagreed that you can write "if"
    statements with "else" in C in a way that is confusing or unclear to
    human readers.  (But it still has fixed and unambiguous meaning to the compiler.)

    Equally, of course, it is possible to write them in a way that is not confusing or unclear at all.

    But there is no ambiguity in the language itself - only possible
    confusions from the way the language could be used.  (And since the
    language is well defined here, it doesn't make sense to call it an
    ambiguity at all, even "from a human perspective".  Call it unclear, confusing, or deceptive code if you like.)

    I don't see that anyone has changed their position on this.


    But when I try to make that very point, it's me making up unrealistic
    examples; I'm being deliberately obtuse; I clearly find things
    confusing that no one else has a problem with; or you make snarky
    comments like this:


    Sure.

    We all know it is possible to write unclear and confusing C code.
    There's a whole competition devoted to it!

    But we also all know that most C programmers - like programmers of any
    other language - usually avoid writing code they find unclear.  (Clarity
    is quite subjective - a solid proportion of programmers will agree
    roughly on a set of guidelines, but there will be outliers with very different positions.  This is independent of language.)


    "I mean, if you get confused by an unambiguous syntaxes already,
    what do you think happens with people if they have to program
    in or understand an ambiguous language!"

    It's astonishing how I have to fight across a dozen posts to back up
    my point of view (you even specifically said you didn't recognise my
    point).

    And yet here: somebody makes that very same point, and you merely say:

    "Yes, true."

    It really is extraordinary.


    It was a totally different point.  It is extraordinary that you can't
    see that.

    You claimed the language and its grammar was ambiguous and confusing. It
    is not.

    I don't think so. My main example which followed on from semicolons was
    about 'do while'. I said that, even though the C grammar makes it work,
    that it was fragile: adding or removing a semicolon could radically
    change the meaning.

    This also comes up with 'while (cond); {...}'.

    Here is what I said in one post:

    BC:
    Why is it not possible for to acknowledge that some language design
    patterns may not be as obvious as others?

    According to you, even if some construct can be determined to be
    unambiguous in some convoluted grammar, then it must also be 100%
    obvious to any human reader?

    This is little different from your remark here: "...not because the C
    compiler sees it as ambiguous, but because humans often do. (Or they misinterpret it.)"

    But this was JP's reply:

    JP:
    Who said that? - Again you make up things just for your argument.

    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    To what ([hypothetical] "some") grammar are you referring to?

    If you mean the "C" grammar; what, concretely, you find to be
    "convoluted"?

    You postulate it as if the grammar were convoluted; more likely
    it's just your personal problem with understanding formal syntax.

    No one said, that everything is "100% obvious". An unambiguous
    grammar is a precondition for for an understanding, though.

    If you'd have your excerpts and samples formatted in a common
    (non-lunatic) way then it should have been "100% obvious" even
    to you.

    It then went on:

    BC:
    Is it just to avoid admitting that I might have a point?

    JP:
    (Yet you haven't had one.)

    A totally different attitude, dripping with condescension and contempt, compared to the "Yes, true" that you got.

    He simply cannot admit that I could have a valid point; he must ALWAYS
    turn it around and make it about me personally.

    Is it any wonder that I respond with some heat?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Bart on Wed Dec 11 22:51:48 2024
    Bart <bc@freeuk.com> wrote:
    On 07/12/2024 11:34, Janis Papanagnou wrote:
    On 06.12.2024 02:20, Bart wrote:

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that possible? >>
    A keyword (like 'while') is just a lexical token that can be used in
    different syntactical contexts.

    Is it common to both start and end a statememt with the same keyword?

    Technically, 'do' loop ends in a semicolon. Rule is

    do secondary-block while ( expression ) ;

    with explicit semicolon at the end.

    'while' loop do not have any special symbol marking its end.
    Grammar for 'while' is

    while ( expression ) secondary-block

    and it ends where 'secondary-block' ends which may be a semicolon
    but may be also a brace.

    Concerning "start and end a statememt with the same keyword",
    this is clearly common when statement consist of a single
    symbol, like empty statement in many langages, including C and
    Algol68 (we could split hairs if statment containing no symbols
    like empty statement in Pascal starts and ends in the same keyword).

    If you look at multi-symbol statements, then 'do' and 'while'
    loop are not an example: 'while' loop starts with 'while',
    'do' loop starts in 'do' and AFAICS neither 'while' nor 'do'
    can end a statement.

    (Even with different semantics, if a
    language designer thinks this is a good idea for his case.)

    You may be less confused with using Pascal;

    Now you are demonstrating my point about being treated like a beginner.
    And it is exasperating.

    This is a point of language design. C's approach works - just. But it
    relies on some subtlety. 'while (cond)' both starts a statement, and can
    end a statement:

    do while(cond) do ; while (cond);

    The second 'while' here starts a nested while-loop inside a do-while
    loop. Not confusing? It is to me! I couldn't finish my example as I got
    lost (but as it happens, this is valid code, partly by luck).

    I think it was already noted that this is not a valid C statement.

    do while(cond) ; while (cond);

    is valid, and indeed may be confusing to humans. But people
    would normally write it as

    do {
    while(cond) ;
    } while (cond);

    or even

    do {
    while(cond) {
    ;
    }
    } while (cond);

    to stress that inner loop is "do nothing" loop. In this form
    structure is clear.

    If you want human-oriented rule for parsing badly written code,
    you may notice that body of a C loop can not be syntactually
    empty, you need at least a semicolon. So first 'while'
    after 'do' must start an inner loop.

    Concerning "subtle", note that changing say '*' to '+' can
    signifcantly change parse tree and semantics in almost any
    programming language. Most people are not bothered by this
    and take care when writing/reading operators. Similarly
    C programmers are careful when writing/reading semicolons.

    You can design a laguage with more redundancy. For example
    one of languages that I use has

    if cond then expr1 else expr2 endif

    while cond do expr endwhile

    repeat expr endrepeat

    and similar ('repeat' formally is na infinite loop, but may
    contain inside constructs that exit the loop). But redundancy
    means that language is more wordy. C designers choose a
    compromise, braced C versions still have less non-space
    characters than the above and are quite clear. Of course,
    some people want to save typing braces, C allows that.
    If you skip braces and add meaningful indentation, then
    you again get enough redundancy to easily parse this in
    your head. Disadvantage of indentation alone is that it
    may get out of sync with the code structure, but as noted
    'gcc' can warn about this. Some folks have editor macros
    that automatically insert braces and/or indent code in similar
    situations, then amount of typing is the same.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Thu Dec 12 00:26:39 2024
    On Wed, 11 Dec 2024 21:35:06 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 11/12/2024 18:22, Michael S wrote:
    On Wed, 11 Dec 2024 16:15:25 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    Suffice it to say that as far as code generation is concerned, the
    Cortex-A devices on the RPi's are completely different from the
    Cortex-M devices in microcontrollers. It's like comparing the
    80286 with the Z80A.


    With exception of RPi1, saying so would be an exaggeration.
    RPi2 through 5 are technically capable to run Thumb2-encoded user
    level routines.

    I did not know that the 64-bit Cortex-A devices could run 32-bit Thumb2-encoded instructions. That does reduce the difference
    somewhat.


    Support for T32 in ARMv8-A is optional.
    In practice, majority of "two-digit" Cortex-A devices support it. There
    are only two exceptions - A34 and A65, both rather obscure.
    "Three-digit", i.e. ARMv9 Cortex-A cores are another story. Most of them
    either do not support T32 (and A32) at all, or make it optional for implemetator.
    On the other hand, nearly all Arm Inc. server cores, even those that
    are very closely related to Cortex-A cores, like Neoverse N1 (a variant
    of Cotex-A76) do *not* support aarch32.

    Compilers targeting 64-bit ARM would generate 64-bit (AArch64)
    instructions, which are of course significantly different.

    Understatement detected.

    But
    perhaps a compiler targeting 32-bit Cortex-A devices might be able to generate Thumb2 instructions.


    Majority of compilers are. But it seems that tcc is not.
    Or may be it is. tcc docs are too sparse.

    However, you would not expect binary compatibility between code
    generated for a 32-bit Cortex-M device and a Cortex-A platform, even
    if it supports Thumb2 instructions - you have major differences in
    the ABI, memory layouts, and core features beyond the basic registers.


    There are major difference in floating-point parts of the ABI and in
    everything related to interrupts. But for integer, it looks like the
    T32 ABI is the same.


    May be, mutual incompatibility with MCUs would become true again in
    the next generation of RPi. But more likely it would not happen
    until RPi7.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to bart on Wed Dec 11 23:33:48 2024
    bart <bc@freeuk.com> wrote:
    On 11/12/2024 09:18, Michael S wrote:
    On Wed, 11 Dec 2024 05:37:15 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    I remember running TCC on both RPi1 (2012) and RPi4 (2019). That would
    be ARM32 (some version of ARMv7 I guess; I find ARM model numbers bewildering).

    It's possible I also tried TCC in the ARM64 mode of RPi4.

    So it sounds rather unlikely that TCC doesn't support ARM.

    To add to what Michael S wrote: AFAICS TCC can generate code
    for ARM version 5. This is 32-bit ARM instructions set and
    should work on all reasonably new (sey less than 25 years
    old) non-embedded ARM processors supporting 32-bit instructions.
    TCC can also generate instructions for 64-bit ARM (usually
    called aarch64). AFAICS it does not support Thumb instruction
    set which is used in popular Cortex-M series. Some old
    embedded processors use 32-bit ARM instructions, but
    there are restrictions and chance that tcc compiled code will
    work on embedded processor is not big. And even if it works,
    32-bit instructions give significantly bigger code than
    Thumb encoding, and that on top of bigger code size from
    tcc. So even, if tcc code could work, it is rather unattractive.

    Let me add that MCU-s typically support only a subset of
    ARM/Thumb instructions. For example, still quite popular
    is Cortex-M0. It supports only Thumb1 instructions which
    are quite limited. Basically, if processor supports more
    instructions you want to use additional instructions, as that
    makes code significantly faster. Cortex-M3 and Cortex-M4
    are better, but IIRC still lacks some Thumb instructions
    present in bigger processors. And bigger processors can
    switch between Thumb and 32-bit encoding, while Cortex-M
    is Thumb-only.

    There are now embedded Risc-V processors. But Risc-V can
    be 32-bit or 64-bit. Embedded Risc-V processors are
    32-bit, while IIUC tcc supports only 64-bit Risc-V.
    There are also intermediate-style machines. They support
    64-bit instructions, but have small memory that comfortably
    could be addressed using 32-bit. For such a machine it makes
    sense to use 64-bit instructions, but use 32-bit pointers and
    long. gcc and clang support such mode for Intel/AMD
    processors under name x86_64-x32. It seems that no
    mainstream compiler supports similar mode for Risc-V
    (there is some talk, so maybe one can find some experimental
    support).

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Thu Dec 12 00:02:19 2024
    On 11/12/2024 22:06, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    [...]
    You need input from a symbol table in order to parse C, a table that
    the parser needs to maintain as it processes source code. That will
    tell you whether a particular identifier is a typename or not.

    Yes. (I've mentioned this a number of times.)

    There are issues also with keywords like 'break'.

    What issues?

    I see that the C grammar treats both kinds of 'break' as a jump. I for
    one generate two separate constructs for the two kinds. That requires
    keeping track of the stack of nested switch/while/for/dowhile statements.

    If you're referring to the fact that break can apply either to a loop or
    to a switch, that's a potential source of confusion, but it shouldn't be
    a problem once you're aware of it.

    It can be very much a problem. Suppose you have an if-else chain within
    a loop that contains loop-break. Later you upgrade it to switch. Now it
    no longer jumps to the end of the loop, but the end of the switch.

    Even if aware of it, now you're stuck for getting to the end of the
    loop. It can also happen in reverse when you downgrade a switch to
    if-else. And to a lesser extent when you wrap a case-block containing
    'break' with a loop.

    I don't know why two different keywords weren't used for this instead of
    having to share.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Thu Dec 12 01:14:48 2024
    On 12/12/2024 00:42, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:


    Are you bothered by the fact that "break" applies to all three
    kinds of iteration statements (while, do, for)?

    No. But 'switch' isn't iteration. (In my language, there /is/ a looping
    switch statement. That uses the same loop controls as regular loops.
    Those are not allowed in normal switch.)

    Sure, the fact that "break" is overloaded can be slightly
    inconvenient. So can the fact that "break" only exits the
    *innermost* enclosing loop or switch.

    Using two different keywords (which, to be clear, is unlikely to
    happen in any language called "C") would only solve a small part of
    the problem. What I'd really like to see is a mechanism for "break"
    (or "continue") to apply to a *named* enclosing construct, something
    I've found very useful in other languages that support it. It would
    provide an easy solution to the scenario you mentioned above.

    My experience of multi-level break is that there are two main use-cases:

    * Used in the current loop only (not necessarily the innermost to an
    observer). This is the most common

    * Used to exit the outermost loop

    So to support these, named or even numbered loops are not necessary.
    (Eg. I use 'exit' or 'exit all'.)

    Having named labels do have some advantages, such as being absolute
    while indices are relative. But sometimes you need an absolute reference
    when refactoring and sometimes you want it relative.

    If duplicating within the same function, then you also need to think
    about scope rules for those named labels.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Thu Dec 12 00:52:53 2024
    On 11/12/2024 22:51, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    On 07/12/2024 11:34, Janis Papanagnou wrote:
    On 06.12.2024 02:20, Bart wrote:

    I used to be puzzled by this too: 'while' can both start a while
    statement, and it can delimit a do-while statement. How is that possible? >>>
    A keyword (like 'while') is just a lexical token that can be used in
    different syntactical contexts.

    Is it common to both start and end a statememt with the same keyword?

    Technically, 'do' loop ends in a semicolon.

    A do-loop ends with:

    while (cond);

    A while loop starts with:

    while (cond)

    Sometimes a while loop starts and ends with:

    while (cond);

    Concerning "start and end a statememt with the same keyword",
    this is clearly common when statement consist of a single
    symbol, like empty statement in many langages, including C and
    Algol68

    I think it's uncommon. In Algol68 you both start and end a comment with 'comment', or 'co' or '#', which is a spectacularly bad idea. It's easy
    to get them out of step. Or if looking at an isolated delimiter, you
    can't tell, if in the middle of code, whether it is the beginning or end
    of the comment.

    I think it was already noted that this is not a valid C statement.

    do while(cond) ; while (cond);

    is valid, and indeed may be confusing to humans. But people
    would normally write it as

    do {
    while(cond) ;
    } while (cond);

    That's still pretty confusing! In languages where 'while' doesn't do two
    jobs, you see 'while' and know instantly what it denotes. With C, you
    need to scan outwards from a 'while' to be able to infer from the
    surrounding context whether it is normal while-loop or is part of do-while.

    I consider that undesirable.

    or even

    do {
    while(cond) {
    ;
    }
    } while (cond);

    to stress that inner loop is "do nothing" loop. In this form
    structure is clear.


    If you want human-oriented rule for parsing badly written code,
    you may notice that body of a C loop can not be syntactually
    empty, you need at least a semicolon. So first 'while'
    after 'do' must start an inner loop.

    The inner loop might be this:

    do {
    s1;
    while (cond) {}
    } while (cond);

    Here, it is now the first { that is fragile. But this is a general
    problem in C with braces, when braces are optional. A missing/extra
    brace might be offset by an extra/missing brace later on. That can
    result in a still-valid structure, but the wrong one.

    Concerning "subtle", note that changing say '*' to '+' can
    signifcantly change parse tree and semantics in almost any
    programming language. Most people are not bothered by this
    and take care when writing/reading operators. Similarly
    C programmers are careful when writing/reading semicolons.

    ; and to a lesser extent {} are regarded as punctuation. The problem is
    more in leaving them out or adding extra ones.

    Being generally able to silently make typos is a separate problem that
    occurs everywhere including my language.

    But it is not as sensitive as C is to messing up '; { }' because of
    stricter rules on layout, even though it looks more lax:

    repeat
    s1
    while cond do od
    until cond

    There are no semicolons or braces to get wrong! Extra semicolons are
    either ignored or give a syntax. I can't even get while/repeat confused
    as they use different keywords.



    You can design a laguage with more redundancy. For example
    one of languages that I use has

    if cond then expr1 else expr2 endif

    while cond do expr endwhile

    repeat expr endrepeat

    OK, I should have read this first. Of course, that's already been done.
    C decided to keep its delicate grammar rather than tighten it up.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Janis Papanagnou on Thu Dec 12 02:31:21 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 11.12.2024 16:28, David Brown wrote:
    On 11/12/2024 09:43, Ike Naar wrote:
    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote: >>>>
    An unambiguous grammar is something quite essential; [...]

    [ dangling-else sample ]

    Given that the resolution is in the "semantics" section rather than the
    "syntax" section, it might seem like a grammatical ambiguity. But I
    don't think it is, technically - the syntax rules say that the set of
    tokens making up "if (E1) if (E2) S1 else S2" are valid syntax. It is
    up to the semantics to determine what the code will do here. (And the
    semantics are unambiguous.)

    I'm a bit ambivalent about that. - Yes, technically it's syntax, it's syntactically probably correct, and it has a semantical ambiguity that
    needs to be resolved. All languages with the dangling-else property do resolve that. But the syntax could have been defined in a way that such
    that a dangling else cannot appear in the first place. (Not in "C" and descendant languages, of course; that ship has sailed.)

    Of course nobody is going to retroactively change C standards.
    However, it is well-known how to rewrite grammar so that there
    is no "dangling else" ambiguity in the grammar and resulting
    parse trees are equivalent to parse trees produced by the current
    grammar. Drawback of such rewrite is that grammar is significantly
    bigger, basically most things that can appear iside 'if' must
    come in two versions. Such grammar is harder to understand,
    so most languages make pragmatic choice of using simpler grammar
    + extra rule. And this simpler grammar can be fed into a parser
    generator to get parser which resolves "dangling else" as
    proscribed by the rule and such parser is likely to be smaller
    and more efficient than parser for grammar with conflict
    removed.

    So, while "dangling else" problem is rather fundamental, using
    ambigious grammar is a pragmatic choice.

    The other things that I mentioned (type name trouble) is more
    problematic: trying to fix it leads to grammar that is not
    LR(1). I think that this grammar is unambigious, but it
    would not work with standard parser generators ("dangling else"
    rewrite preserves good propeties of grammar and only affects
    size).

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Thu Dec 12 05:50:00 2024
    On 11.12.2024 18:20, bart wrote:
    On 11/12/2024 16:51, Janis Papanagnou wrote:
    [ dangling else ]

    So here you finally acknowledge there may be ambiguity from a human perspective.

    From a semantical perspective, not from a syntactical. There's rules
    to disambiguate a dangling-else. And there's languages that designed
    a syntax without an inherent semantical ambiguity (that would need to
    be cleared by such rules).

    For (yet another) example; my K&R shows a syntax for expressions like

    expression := binary
    binary := binary + binary
    binary := binary * binary

    An actual expression x = 2 + 3 * 4 would be "ambiguous" (without
    precedence rules).

    A language who would define the grammar using non-terminal symbols
    'factor' and 'term' (for example) could disambiguate the semantics
    (on the syntax level).

    Are you again trying to confuse the matter by speaking about "human perspective"; we spoke about syntax and semantics.

    What you had before was writing syntactical wrong code and claiming
    you were confused. And you deliberately changed the sample syntax
    and expected that it is still code with the same semantics or what?

    There's neither a syntactical nor a semantical ambiguity between a
    while-loop and a do-wile-loop.

    [...]

    (What a waste of time!)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Scott Lurndal on Wed Dec 11 23:38:52 2024
    On 12/10/24 20:32, Scott Lurndal wrote:
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    On 12/4/24 15:55, David Brown wrote:
    On 04/12/2024 16:09, Bart wrote:
    ...
    In C struct, union, and enumation tags have their own namespace, in C++
    they reside in the ordinary name space.

    In C++ they reside in the ordinary name space only if they're not
    part of a named namespace.

    namespace x {
    int y;
    };

    You're confusing name spaces and namespaces.
    Your example does not include any struct, union, or enumeration tags, so
    it's not directly relevant to what I said.
    Because tags name types, the fact that they are in the same namespace as
    other identifiers is most easily shown using typedefs, which are also in
    the ordinary name space.

    The following code is permitted in C, even though both declarations are
    in the same scope, because 'y' is declared in two different name spaces:

    typedef int y;
    struct y { int z;};

    However, in C++ it is not permitted because both occurrences of 'y' are
    in the same name space. That's equally true whether they occur in the
    same named namespace or the same unnamed namespace.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to James Kuyper on Thu Dec 12 06:07:49 2024
    On 12.12.2024 05:38, James Kuyper wrote:
    On 12/10/24 20:32, Scott Lurndal wrote:
    [...]

    You're confusing name spaces and namespaces.

    It became quite obvious that you both were talking at cross purposes.

    Personally I'd colloquially take both those terms as the same thing,
    but I'm not a native speaker. - I'm used to mark tokens 'namespace'
    and write a technical term as "name space" or Name Space and/or
    provide a reference or hint, a "name space" (as defined in ...) -
    to disambiguate that [by syntax and/or semantics]. ;-)

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Thu Dec 12 09:27:05 2024
    On 11/12/2024 23:26, Michael S wrote:
    On Wed, 11 Dec 2024 21:35:06 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 11/12/2024 18:22, Michael S wrote:
    On Wed, 11 Dec 2024 16:15:25 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    Suffice it to say that as far as code generation is concerned, the
    Cortex-A devices on the RPi's are completely different from the
    Cortex-M devices in microcontrollers. It's like comparing the
    80286 with the Z80A.


    With exception of RPi1, saying so would be an exaggeration.
    RPi2 through 5 are technically capable to run Thumb2-encoded user
    level routines.

    I did not know that the 64-bit Cortex-A devices could run 32-bit
    Thumb2-encoded instructions. That does reduce the difference
    somewhat.


    Support for T32 in ARMv8-A is optional.
    In practice, majority of "two-digit" Cortex-A devices support it. There
    are only two exceptions - A34 and A65, both rather obscure.

    Do you have any thoughts on why it is supported at all? Who would use
    it? I can see support for 32-bit ARM code being of interest on 64-bit
    Cortex-A devices for backwards compatibility - you can run old RPi 1
    binaries on an RPi 4, for example. But where would you want to run
    Thumb2 binaries on a 64-bit Cortex-A device - especially when you could
    not do so on 32-bit Cortex-A predecessors.

    "Three-digit", i.e. ARMv9 Cortex-A cores are another story. Most of them either do not support T32 (and A32) at all, or make it optional for implemetator.
    On the other hand, nearly all Arm Inc. server cores, even those that
    are very closely related to Cortex-A cores, like Neoverse N1 (a variant
    of Cotex-A76) do *not* support aarch32.


    OK - thanks for that information. My ARM work has primarily been with
    32-bit Cortex-M devices (so "ARM architectures" like ARMv7-M and
    ARMv8-M). 64-bit microcontrollers are not common, as yet. (There is a
    64-bit version of ARMv8-R, but not of the -M architectures.) Maybe
    we'll be on RISC-V before 64-bit microcontrollers fit the needs of our customers.

    I've used 64-bit Cortex-A devices in embedded Linux systems, but I've
    not needed to consider the details of the architecture as you typically
    use these at a higher level of abstraction (at least for usermode code,
    which is all I have done there).


    Compilers targeting 64-bit ARM would generate 64-bit (AArch64)
    instructions, which are of course significantly different.

    Understatement detected.

    But
    perhaps a compiler targeting 32-bit Cortex-A devices might be able to
    generate Thumb2 instructions.


    Majority of compilers are. But it seems that tcc is not.
    Or may be it is. tcc docs are too sparse.


    I don't think there would be much reason to generate Thumb2 code unless
    it was for running on microcontrollers. So it would be a lot of work
    for a compiler developer for little purpose. I don't know if tcc
    targeted 32-bit ARM or 64-bit ARM. If it is the former, then Thumb2
    would be less effort to implement since it is mostly a different
    encoding of the same instruction set - but it would be of little use
    since (if I understand you correctly) 32-bit Cortex-A devices don't
    support Thumb2. And if tcc supports 64-bit ARM, then the Thumb2
    generation would be much more work since it is a significantly different
    ISA. And again, how many people actually want Thumb2 binaries for their
    64-bit Cortex-A devices?


    However, you would not expect binary compatibility between code
    generated for a 32-bit Cortex-M device and a Cortex-A platform, even
    if it supports Thumb2 instructions - you have major differences in
    the ABI, memory layouts, and core features beyond the basic registers.


    There are major difference in floating-point parts of the ABI and in everything related to interrupts. But for integer, it looks like the
    T32 ABI is the same.

    I'm sure much of it is the same (after all, it is solving the same basic problem), but the details are critical to making things work. As well
    as the points you made, I would guess there are differences to the way
    code and data is addressed - on Linux, you expect dynamic link/loading,
    and typically have some level of indirection so that it can handle address-space randomisation, linking to dynamic libraries, etc. On microcontrollers, code is normally compiled and linked for a fixed
    static memory layout.



    May be, mutual incompatibility with MCUs would become true again in
    the next generation of RPi. But more likely it would not happen
    until RPi7.




    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Thu Dec 12 11:08:05 2024
    On 11/12/2024 23:03, Michael S wrote:
    On Wed, 11 Dec 2024 21:19:54 +0000
    bart <bc@freeuk.com> wrote:


    This also comes up with 'while (cond); {...}'.


    $ cat foo.c
    void foo(int x)
    {
    while (x--);
    bar();
    }

    $ clang-format < foo.c
    void foo(int x) {
    while (x--)
    ;
    bar();
    }

    Do I use clamg-format myself? No, I don't.

    And I don't know why C formatters are generally less popular among C programmers then, for example, go formater among Go programmers or Rust formatter among Rust programmers.



    I suspect that there is a great deal more variation in common styles and formatting amongst C programmers than amongst Go or Rust programmers.
    Part of that is the way people learned the language in the early days.

    When C was new, there were lots of variants of the language, and lots of
    people using it quite independently. They learned from colleagues,
    magazine articles, books, etc. Tools were limited, and you often had a
    choice of writing clear code, or writing something that the tool would
    turn into efficient object code - not both.

    With modern languages like Go and Rust, the internet was well
    established. People learned from common sources - the Rust website, for example. And tools were good from a much earlier stage, so you could
    get the habit of writing clear code rather than learning "tricks" to
    generate efficient results from poor tools.

    So I think C programmers often got set in their ways from much earlier,
    while users of modern languages were more influenced by common sources.
    With less variation in the way code is written, it's a lot easier to
    agree on how code /should/ be written.

    In the C world, if you ask five programmers how the "foo" function
    should be laid out, you'll get ten different answers - people are
    naturally less keen on a formatting tool that generates formats you
    disagree with!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Thu Dec 12 11:48:33 2024
    On 12/12/2024 01:27, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    [...]
    My experience of multi-level break is that there are two main use-cases:

    * Used in the current loop only (not necessarily the innermost to an
    observer). This is the most common

    * Used to exit the outermost loop

    So to support these, named or even numbered loops are not
    necessary. (Eg. I use 'exit' or 'exit all'.)

    I would oppose a change to C that only applied to innermost and
    outermost loops. For one thing, I'm not aware of any other language
    that does this (except perhaps your unnamed one). For another,
    it's easy enough to define a feature that handles any arbitrary
    nesting levels, by applying names (labels) to loops.

    Having named labels do have some advantages, such as being absolute
    while indices are relative. But sometimes you need an absolute
    reference when refactoring and sometimes you want it relative.

    I'm not sure what you mean by "relative". Do you have an example?

    If, say, I have a "break 2" statement (the Bourne shell uses that
    syntax), and I wanted to refactor the code, I'll at least have
    to pay very close attention to the number, and likely change it.
    Is that what you mean by "relative"? If I have "break NAME", it's
    more likely that I won't have to change it. (Disclaimer: I don't
    think I've ever used the "break N" feature of the Bourne shell.)

    Take these two loops:

    loop A: {
    loop B: {
    break A // absolute
    break +1; // relative
    }
    }

    The two breaks in the inner one both break out of the outer loop. The
    relative one uses an index counting outwards.

    Now suppose you add a third loop C in between A and B. Those two breaks
    now do different things: 'break A' is still the outermost, but 'break
    +1' now exist from loop C.

    Sometimes you will want one behaviour and sometimes the other. So you
    can't say one is better. I don't have enough experience of them to say
    (my 'exit' and 'exit all' are effectively both absolute).

    Another issue is when you move or copy a block of code (say those two
    breaks) into another loop. That 'break +1' might be OK, but probably not
    'break A'. (You don't want to break out of an unrelated loop in a
    different part of the function; using 'goto' would allow that.)

    If duplicating within the same function, then you also need to think
    about scope rules for those named labels.

    That's hardly the only case where duplicating code within a function
    can cause conflicts.

    A common proposal is to use existing labels, whose scope is already
    well defined. Labels have *function scope*. You just have to make
    sure that all labels within a function are unique.

    If function-wide label scope is used, then my A and B labels need to be
    unique, so copying code around is harder. If loop scopes are private,
    then you can do this:

    loop A: {
    loop A: {

    which doesn't look useful. It's all a fiddly bit of language design,
    which is why I kept it simple.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Thu Dec 12 12:38:46 2024
    On 12.12.2024 06:35, Keith Thompson wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    [...]
    For (yet another) example; my K&R shows a syntax for expressions like

    expression := binary
    binary := binary + binary
    binary := binary * binary

    That's odd. Is that an exact quotation?

    No, not exact, I abbreviated it; omitted about 25 other operators and
    used another syntax (no ' | '). (Trust me that it hasn't things that
    I called 'factor' and 'term' in my post, which is equivalent to what
    you have formulated below in your copy.) - I'm using a translation of
    something that someone classified as being a "pre-second" edition but
    not quite the first edition. Two references point to 1977 (Prentice
    Hall) and 1978 (Bell Labs). - The text for the "binary" syntax has two
    optional informal columns, the first one has the comment "precedence"
    for some of the variants of "binary" operators. (But it's also just
    titled as "Syntax in Short"; probably presented in a form to make it
    easy to understand without overloading it for purpose of a textbook.)
    It serves the purpose to explain an ambiguous syntax with non-codified precedence and a separate precedence table (but it's not an exact "C"
    syntax description as you'd probably find it in standards documents).


    [...]

    My copy of K&R 1st edition (1978) has, among other things:
    multiplicative-expression:
    additive-expression:

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Thu Dec 12 12:11:11 2024
    On 11/12/2024 16:24, Janis Papanagnou wrote:
    On 11.12.2024 03:21, bart wrote:
    On 09/12/2024 18:46, Janis Papanagnou wrote:

    An unambiguous grammar is something quite essential; how would you
    parse code if it were ambiguous?

    You can easily parse a language in an ambiguous syntax. [...]

    Sure; I recall Fortran had such an ambiguity, I think it was in
    context of FOR loops (something with the assignment and commas,
    IIRC). - Whether it's "easily [to] parse" is arguable, though,
    and certainly depends. - But I don't recall to have seen scary
    things like that in any other language I had to do with.

    Experienced language developers wouldn't define an ambiguous
    syntax in the first place. So what do you think your statement
    contributes to desire to have an "unambiguous syntax"?

    I mean, if you get confused by an unambiguous syntaxes already,
    what do you think happens with people if they have to program
    in or understand an ambiguous language!


    You postulate it as if the grammar were convoluted;

    My opinion is that it is. Especially its propensity for using
    long-winded production terms that look confusingly similar. (Would it
    have killed somebody to make the names more distinct?)

    (I won't comment on your opinion.)

    With respect to distinctness of names I thought we had already
    exchanged some words - remember my 'while' and 'until' samples
    from Pascal (that somehow offended you)?

    The names I'm talking about aren't terminals, they're ones like
    '*declaration' and '*declarator', or 'multiplicative-expression'.

    Concerning "C"; I don't see why you shouldn't name a "positive"
    conditioned control construct consistently(!) as 'while' whether
    it controls a loop entry or a loop exit, and to name a "negative"
    conditioned control construct consistently(!) as 'until'.

    I sometimes use 'when' for positive rather than 'if', and 'until' or
    'unless' for negative.

    (Or just use a 'not' prefix for negative, but for this purposes, it's
    more helpful it having low precedence rather than high, to avoid
    parentheses around the whole thing.)

    One reason for using 'when' in some contexts is when 'if' could appear ambiguous (here I'm talking about my syntax);

    return if x=y # conditional return from procedure
    return if a then b else c fi if x=y # cond ret from function

    I can't tell when 'if' after 'return' is forming a conditional return,
    or is part of the return value. Knowing if this is a function or
    procedure would help, but I considered that not strong enough.

    It is not obvious, and can mask errors: did I want a conditional return,
    but I forgot the return value?

    Instead I use:

    return when x=y
    return if a then b else c fi when x=y
    return unless x=y # reverse logic

    So here I put a little more thought into than just saying it is
    technically unambiguous.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Thu Dec 12 14:13:52 2024
    On Thu, 12 Dec 2024 09:27:05 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 11/12/2024 23:26, Michael S wrote:
    On Wed, 11 Dec 2024 21:35:06 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 11/12/2024 18:22, Michael S wrote:
    On Wed, 11 Dec 2024 16:15:25 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    Suffice it to say that as far as code generation is concerned,
    the Cortex-A devices on the RPi's are completely different from
    the Cortex-M devices in microcontrollers. It's like comparing
    the 80286 with the Z80A.


    With exception of RPi1, saying so would be an exaggeration.
    RPi2 through 5 are technically capable to run Thumb2-encoded user
    level routines.

    I did not know that the 64-bit Cortex-A devices could run 32-bit
    Thumb2-encoded instructions. That does reduce the difference
    somewhat.


    Support for T32 in ARMv8-A is optional.
    In practice, majority of "two-digit" Cortex-A devices support it.
    There are only two exceptions - A34 and A65, both rather obscure.

    Do you have any thoughts on why it is supported at all? Who would
    use it? I can see support for 32-bit ARM code being of interest on
    64-bit Cortex-A devices for backwards compatibility - you can run old
    RPi 1 binaries on an RPi 4, for example. But where would you want to
    run Thumb2 binaries on a 64-bit Cortex-A device - especially when you
    could not do so on 32-bit Cortex-A predecessors.


    Arm Cortex-A9 was very popular for enough time to create significant
    software legacy. And in majority of situations Cortex-A9 runs
    T32-compiled code a little better than an equivalent A32. Also, even
    when A32 and T32 run at approximately the same speed, more compact
    T32 was a natural default choice for developers. At least for
    developers do not care about compatibility with older Arm. Which would constitute nearly all Android devs that were sufficiently
    performance-oriented to write native Arm code in the first place.

    "Three-digit", i.e. ARMv9 Cortex-A cores are another story. Most of
    them either do not support T32 (and A32) at all, or make it
    optional for implemetator.
    On the other hand, nearly all Arm Inc. server cores, even those
    that are very closely related to Cortex-A cores, like Neoverse N1
    (a variant of Cotex-A76) do *not* support aarch32.


    OK - thanks for that information. My ARM work has primarily been
    with 32-bit Cortex-M devices (so "ARM architectures" like ARMv7-M and ARMv8-M). 64-bit microcontrollers are not common, as yet. (There is
    a 64-bit version of ARMv8-R, but not of the -M architectures.) Maybe
    we'll be on RISC-V before 64-bit microcontrollers fit the needs of
    our customers.


    In order to lose "long tail" of microcontrollers and of embedded SOCs to
    RVor to anybody else Arm would have to screw rather badly. Now, I don't
    say that they are incapable of doing so :(
    Or, may be, you are not in "long tail". Outside of it things look
    different.

    I've used 64-bit Cortex-A devices in embedded Linux systems, but I've
    not needed to consider the details of the architecture as you
    typically use these at a higher level of abstraction (at least for
    usermode code, which is all I have done there).


    Compilers targeting 64-bit ARM would generate 64-bit (AArch64)
    instructions, which are of course significantly different.

    Understatement detected.

    But
    perhaps a compiler targeting 32-bit Cortex-A devices might be able
    to generate Thumb2 instructions.


    Majority of compilers are. But it seems that tcc is not.
    Or may be it is. tcc docs are too sparse.


    I don't think there would be much reason to generate Thumb2 code
    unless it was for running on microcontrollers. So it would be a lot
    of work for a compiler developer for little purpose. I don't know if
    tcc targeted 32-bit ARM or 64-bit ARM.

    Both.

    If it is the former, then
    Thumb2 would be less effort to implement since it is mostly a
    different encoding of the same instruction set - but it would be of
    little use since (if I understand you correctly) 32-bit Cortex-A
    devices don't support Thumb2.

    You understand incorrectly.

    And if tcc supports 64-bit ARM, then
    the Thumb2 generation would be much more work since it is a
    significantly different ISA. And again, how many people actually
    want Thumb2 binaries for their 64-bit Cortex-A devices?


    However, you would not expect binary compatibility between code
    generated for a 32-bit Cortex-M device and a Cortex-A platform,
    even if it supports Thumb2 instructions - you have major
    differences in the ABI, memory layouts, and core features beyond
    the basic registers.

    There are major difference in floating-point parts of the ABI and in everything related to interrupts. But for integer, it looks like the
    T32 ABI is the same.

    I'm sure much of it is the same (after all, it is solving the same
    basic problem), but the details are critical to making things work.
    As well as the points you made, I would guess there are differences
    to the way code and data is addressed - on Linux, you expect dynamic link/loading, and typically have some level of indirection so that it
    can handle address-space randomisation, linking to dynamic libraries,
    etc. On microcontrollers, code is normally compiled and linked for a
    fixed static memory layout.


    I don't know what others were considering with regard to you trying tcc.
    My thought was about replacing compiler without touching linker or the
    rest of the tools.



    May be, mutual incompatibility with MCUs would become true again
    in the next generation of RPi. But more likely it would not happen
    until RPi7.





    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Thu Dec 12 12:29:30 2024
    On 12/12/2024 04:50, Janis Papanagnou wrote:
    On 11.12.2024 18:20, bart wrote:
    On 11/12/2024 16:51, Janis Papanagnou wrote:
    [ dangling else ]

    So here you finally acknowledge there may be ambiguity from a human
    perspective.

    From a semantical perspective, not from a syntactical. There's rules
    to disambiguate a dangling-else. And there's languages that designed
    a syntax without an inherent semantical ambiguity (that would need to
    be cleared by such rules).

    For (yet another) example; my K&R shows a syntax for expressions like

    expression := binary
    binary := binary + binary
    binary := binary * binary

    An actual expression x = 2 + 3 * 4 would be "ambiguous" (without precedence rules).

    That doesn't look right to me; what page is that from?

    For a table-driven grammar, I'd write it like this:

    expr = term {op term}*

    term = number etc

    With precedence defined by the grammar, it might be:

    expr = factor {{'+' | '-'} factor}*

    factor = term {{'*' | '/'} term}*

    term = ...

    But it would needed a production (and a production name) for each
    precedence level.


    (What a waste of time!)

    Sorry for wasting your time; I didn't realise I was holding a gun to
    your head.

    But your arrogant attacks on my remarks pretty much forced me to defend
    myself. My time of course isn't valuable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Thu Dec 12 15:03:18 2024
    On 11.12.2024 16:03, David Brown wrote:
    On 11/12/2024 06:37, Waldek Hebisch wrote:

    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    Who was that?

    What I find documented in the GNU Awk package was this:

    _The Tiny C Compiler, 'tcc'_

    This compiler is _very_ fast, but it produces only mediocre code.
    It is capable of compiling 'gawk', and it does so well enough that
    'make check' runs without errors.

    However, in the past the quality has varied, and the maintainer has
    had problems with it. He recommends using it for regular
    development, where fast compiles are important, but rebuilding with
    GCC before doing any commits, in case 'tcc' has missed
    something.(1)

    [...]

    (1) This bit the maintainer once.

    That doesn't quite sound like the GNU Awk folks would think it's a good
    tool or anything even close ("mediocre code", "well enough", "runs
    without errors", "quality has varied", "had problems with it") And that
    it's obviously not trustworthy given the suggestion: "rebuilding with
    GCC before doing any commits".

    And I cannot find any statement that "he likes compile speed", he just
    stated that it is very fast (which seems to just have astonished him).

    Is that so that you can say I am wrong to claim "no one" cares about tcc support, because you have found 1 person who has used it? I admit it -
    "no one" was an exaggeration.

    To be fair, a "project" (like GNU Awk) is more than just one person.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to bart on Thu Dec 12 06:54:23 2024
    bart <bc@freeuk.com> writes:

    On 11/12/2024 14:39, Waldek Hebisch wrote:

    C grammar is not LL(1), that is you can not recognize a construct
    looking at its first token. You need the whole construct and
    sometimes also the following token. And there are also well
    known troubles due to type names and "dangling else".

    I can't call it 'context sensitive' because that is a technical
    term with a specific meaning, [...]

    You could call it context sensitive, because C can be recognized
    as a context-sensitive language. And that includes type names.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Thu Dec 12 14:37:38 2024
    On 12/12/2024 14:03, Janis Papanagnou wrote:
    On 11.12.2024 16:03, David Brown wrote:
    On 11/12/2024 06:37, Waldek Hebisch wrote:

    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    Who was that?

    What I find documented in the GNU Awk package was this:

    _The Tiny C Compiler, 'tcc'_

    This compiler is _very_ fast, but it produces only mediocre code.
    It is capable of compiling 'gawk', and it does so well enough that
    'make check' runs without errors.

    However, in the past the quality has varied, and the maintainer has
    had problems with it. He recommends using it for regular
    development, where fast compiles are important, but rebuilding with
    GCC before doing any commits, in case 'tcc' has missed
    something.(1)

    [...]

    (1) This bit the maintainer once.

    That doesn't quite sound like the GNU Awk folks would think it's a good
    tool or anything even close ("mediocre code", "well enough", "runs
    without errors", "quality has varied", "had problems with it") And that
    it's obviously not trustworthy given the suggestion: "rebuilding with
    GCC before doing any commits".

    This sounds like you imposing your own interpretion, and trying to
    downplay the credibility of TCC.

    And I cannot find any statement that "he likes compile speed", he just
    stated that it is very fast (which seems to just have astonished him).

    This looks like the original source:

    https://www.gnu.org/software/gawk/manual/gawkworkflow/html_node/Compilers.html

    This is what it said just before:

    "Both GCC and clang are highly optimizing compilers that produce good
    code, but are very slow"

    It goes on:

    "There are two other compilers [TCC and PCC] that are faster, but that
    may not produce quite as good code. However, they are both reasonable
    for doing development."

    This is part of what you quoted:

    " He recommends using it for regular development, where fast compiles
    are important"

    So, this source says that gcc/clang are 'very slow'. It says 'fast
    compiles are important'. 'They [TCC/PCC] are reasonable for doing
    development'.

    What it doesn't say is to forget gcc/clang and use only TCC.

    Basically it says what I've been saying all along: use a fast compiler
    for development, and a slow one for production or when you want a more
    in-depth analysis of your code. But everybody says I've no idea what I'm talking about or that I'm the only person on the planet with that view.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to bart on Thu Dec 12 07:01:01 2024
    bart <bc@freeuk.com> writes:

    On 11/12/2024 16:51, Janis Papanagnou wrote:

    On 11.12.2024 17:47, David Brown wrote:

    On 11/12/2024 17:30, Janis Papanagnou wrote:

    On 11.12.2024 09:43, Ike Naar wrote:

    On 2024-12-09, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote: >>>>>
    An unambiguous grammar is something quite essential; how would you >>>>>> parse code if it were ambiguous?

    Here's an ambiguity in the C grammar:

    [...]

    The following selection-statement is grammatically ambiguous:

    if (E1) if (E2) S1 else S2

    Yes, the dangling else is a common ambiguity in many programming
    languages.

    That's why I prefer languages with syntaxes like in Algol 68 or
    Eiffel (for example).

    It is easy to avoid in a C-like language - simply require braces on "if" >>> statements, or at the very least, require them when there is an "else"
    clause.

    Yes, sure. But, I can't help, it smells like a workaround.

    Most C coding standards and style guides make that requirement
    - not because the C compiler sees it as ambiguous, but because humans
    often do. (Or they misinterpret it.)

    Yes, true. (We had that in our standards, too.)

    So here you finally acknowledge there may be ambiguity from a human perspective.

    But when I try to make that very point, it's me [...]

    Duo cum faciunt idem, non est idem.

    - The ancient playwright Terence

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Thu Dec 12 15:56:02 2024
    On 12.12.2024 13:11, bart wrote:
    On 11/12/2024 16:24, Janis Papanagnou wrote:
    [...]

    Concerning "C"; I don't see why you shouldn't name a "positive"
    conditioned control construct consistently(!) as 'while' whether
    it controls a loop entry or a loop exit, and to name a "negative"
    conditioned control construct consistently(!) as 'until'.

    I sometimes use 'when' for positive rather than 'if', and 'until' or
    'unless' for negative.

    Fair enough.

    So you are saying that you'd prefer to use more than one keyword
    for any positive and for any negative conditioned loop to prevent
    you from any confusion?

    My experience on that is that language designers usually try to
    avoid to introduce too many keywords [unnecessarily].


    (Or just use a 'not' prefix for negative, but for this purposes, it's
    more helpful it having low precedence rather than high, to avoid
    parentheses around the whole thing.)

    I'm sure that's the reason why for example Pascal has just two
    loop types (check on entry and exit respectively) and force the
    programmers to just negate the condition when necessary. It's
    not different in "C", with its two loop types, only that it has
    not introduced another keyword (for the same 'while' semantics).

    The parenthesis thing you mention is something that annoys me;
    that's why I'd prefer to have languages with 'while' and 'until'
    controlled loops, both on entry and exit, for flexibility. (But
    I cannot recall I've ever programmed in any language that would
    support that. I'm using what the project standards require, and
    what's available and sensible in projects where I can choose.)

    In Unix shell it's different; you have only "on-entry" checks;

    while ... ; do ... ; done

    until ... ; do ... ; done

    You'll have to "work around" that for conditions-on-exit; e.g.

    while P ; do S ; done ## check on entry

    while S ; P ; do : ; done ## [quasi] check on "exit"

    (with an empty loop block in the latter case). - Folks familiar
    with Algol 68 may have no problems with that form, to others is
    may look unfamiliar or strange.

    Janis


    [...] (here I'm talking about my syntax);

    [snip]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Thu Dec 12 16:20:50 2024
    On 12.12.2024 15:37, bart wrote:
    On 12/12/2024 14:03, Janis Papanagnou wrote:
    On 11.12.2024 16:03, David Brown wrote:
    On 11/12/2024 06:37, Waldek Hebisch wrote:

    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    Who was that?

    What I find documented in the GNU Awk package was this:

    _The Tiny C Compiler, 'tcc'_

    This compiler is _very_ fast, but it produces only mediocre code.
    It is capable of compiling 'gawk', and it does so well enough that
    'make check' runs without errors.

    However, in the past the quality has varied, and the maintainer has
    had problems with it. He recommends using it for regular
    development, where fast compiles are important, but rebuilding with
    GCC before doing any commits, in case 'tcc' has missed
    something.(1)

    [...]

    (1) This bit the maintainer once.

    That doesn't quite sound like the GNU Awk folks would think it's a good
    tool or anything even close ("mediocre code", "well enough", "runs
    without errors", "quality has varied", "had problems with it") And that
    it's obviously not trustworthy given the suggestion: "rebuilding with
    GCC before doing any commits".

    This sounds like you imposing your own interpretion, and trying to
    downplay the credibility of TCC.

    You don't think all these words are a clear indication? - The original
    text you see above is almost just a concatenation of all these negative connoted words. It really doesn't need any own words or interpretation.

    Aren't those original words, experiences, and suggestions clear to you?

    (I have neither a reason nor an agenda to downplay any compiler. - Why
    do you, again, make such imputations that are typically 98% wrong; in
    your case yet even 100% wrong.)


    And I cannot find any statement that "he likes compile speed", he just
    stated that it is very fast (which seems to just have astonished him).

    This looks like the original source:

    [link snipped]

    This webpage contains the same text as the file in the package that I
    quoted; it came from the file ./doc/gawkworkflow.info packaged with
    the GNU Awk tarfile.

    Janis


    This is what it said just before:
    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Thu Dec 12 18:17:07 2024
    On 12/12/2024 15:20, Janis Papanagnou wrote:
    On 12.12.2024 15:37, bart wrote:
    On 12/12/2024 14:03, Janis Papanagnou wrote:
    On 11.12.2024 16:03, David Brown wrote:
    On 11/12/2024 06:37, Waldek Hebisch wrote:

    Concerning tcc, they have explicit endorsment from gawk developer:
    he likes compile speed and says that gawk compiles fine using tcc.

    Who was that?

    What I find documented in the GNU Awk package was this:

    _The Tiny C Compiler, 'tcc'_

    This compiler is _very_ fast, but it produces only mediocre code. >>> It is capable of compiling 'gawk', and it does so well enough that >>> 'make check' runs without errors.

    However, in the past the quality has varied, and the maintainer has >>> had problems with it. He recommends using it for regular
    development, where fast compiles are important, but rebuilding with >>> GCC before doing any commits, in case 'tcc' has missed
    something.(1)

    [...]

    (1) This bit the maintainer once.

    That doesn't quite sound like the GNU Awk folks would think it's a good
    tool or anything even close ("mediocre code", "well enough", "runs
    without errors", "quality has varied", "had problems with it") And that
    it's obviously not trustworthy given the suggestion: "rebuilding with
    GCC before doing any commits".

    This sounds like you imposing your own interpretion, and trying to
    downplay the credibility of TCC.

    You don't think all these words are a clear indication? - The original
    text you see above is almost just a concatenation of all these negative connoted words. It really doesn't need any own words or interpretation.

    That's the point: you've extracted only the negative words to give a
    misleading picture. How about highlighting these as well:

    "very slow" about gcc/lang (from original link)
    "_very_ fast" about tcc (their emphasis)
    "in the past ... /has had/ problems with it" (my emphasis)
    "recommends using it [TCC] for regular development"

    The conclusion from that link is not to dismiss the tool completely but
    to use it in conjunction with a bigger compiler.

    Aren't those original words, experiences, and suggestions clear to you?

    Not when they are extracted out of context in order to reinforce your view.

    (I have neither a reason nor an agenda to downplay any compiler.

    Yet, you clearly are downplaying it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to David Brown on Thu Dec 12 19:30:07 2024
    David Brown <david.brown@hesbynett.no> wrote:
    On 11/12/2024 23:26, Michael S wrote:
    On Wed, 11 Dec 2024 21:35:06 +0100
    David Brown <david.brown@hesbynett.no> wrote:
    I don't think there would be much reason to generate Thumb2 code unless
    it was for running on microcontrollers.

    Code size. I use Armbian (Debian derivative) on Orange Pi PC and
    Orange Pi Zero. That is on Corex-A. Armbian binaries by default
    are compiled as Thumb2. I did not check if any sizeable piece of
    userland uses 32-bit instructions, but binaries using 32-bit
    instructions work fine.

    So it would be a lot of work
    for a compiler developer for little purpose. I don't know if tcc
    targeted 32-bit ARM or 64-bit ARM. If it is the former, then Thumb2
    would be less effort to implement since it is mostly a different
    encoding of the same instruction set - but it would be of little use
    since (if I understand you correctly) 32-bit Cortex-A devices don't
    support Thumb2. And if tcc supports 64-bit ARM, then the Thumb2
    generation would be much more work since it is a significantly different
    ISA. And again, how many people actually want Thumb2 binaries for their 64-bit Cortex-A devices?

    AFAIK normal 64-bit Linux distributions have no support for 32-bit
    code or Thumb code. But one can run 32-bit Linux distribution on
    64-bit Cortex-A and Thumb2 support is part of this capability.
    AFAICS this is mostly about code size and "disc use": Thumb2 gives
    significant savings, but mixing 64-bit code with 32-bit code in
    a single process is problematic and when you require separate
    libraries for 32-bit and 64-bit, then all savings are gone.

    However, you would not expect binary compatibility between code
    generated for a 32-bit Cortex-M device and a Cortex-A platform, even
    if it supports Thumb2 instructions - you have major differences in
    the ABI, memory layouts, and core features beyond the basic registers.


    There are major difference in floating-point parts of the ABI and in
    everything related to interrupts. But for integer, it looks like the
    T32 ABI is the same.

    I'm sure much of it is the same (after all, it is solving the same basic problem), but the details are critical to making things work.

    AFAIK Thumb2 on Cortex-M3 is a subset of Thumb2 on Cortex-A. To
    get best performance you want to use all available instructions,
    so compilers have separate targets.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Thu Dec 12 14:39:09 2024
    On 12/12/24 00:07, Janis Papanagnou wrote:
    On 12.12.2024 05:38, James Kuyper wrote:
    On 12/10/24 20:32, Scott Lurndal wrote:
    [...]

    You're confusing name spaces and namespaces.

    It became quite obvious that you both were talking at cross purposes.

    Personally I'd colloquially take both those terms as the same thing,
    but I'm not a native speaker.

    They are not.
    The C standard does not define the term "name space", relying instead
    upon the general CS definition of the term. However, it has a whole
    section (6.2.3) devoted to listing and explaining the name spaces that
    are relevant to the C language.

    In C++, "namespace" is a both a keyword (listed in 5.11p3) and a piece
    of terminology (defined in 9.8p1) for the feature enabled by that
    keyword. It is clear from those descriptions that a C++ namespace is significantly different thing from a C name space.
    Unlike the C standard, the C++ standard doesn't even bother explaining
    name spaces. It makes only two uses of that term on it's own behalf, in connection with statement labels and macro names - neither usage has any plausible connection with a namespace. There are several occurrences of
    "name space" in the section describing the differences between C and
    C++, which make it clear that both standards are using the same meaning
    for "name space", but that the two languages have a different number of
    name spaces, with different contents.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to James Kuyper on Thu Dec 12 21:27:07 2024
    On 12.12.2024 20:39, James Kuyper wrote:
    On 12/12/24 00:07, Janis Papanagnou wrote:
    On 12.12.2024 05:38, James Kuyper wrote:
    On 12/10/24 20:32, Scott Lurndal wrote:
    [...]

    You're confusing name spaces and namespaces.

    It became quite obvious that you both were talking at cross purposes.

    Personally I'd colloquially take both those terms as the same thing,
    but I'm not a native speaker.

    They are not.
    The C standard does not define the term "name space", relying instead
    upon the general CS definition of the term. However, it has a whole
    section (6.2.3) devoted to listing and explaining the name spaces that
    are relevant to the C language.

    In C++, "namespace" is a both a keyword (listed in 5.11p3) and a piece
    of terminology (defined in 9.8p1) for the feature enabled by that
    keyword. It is clear from those descriptions that a C++ namespace is significantly different thing from a C name space.
    Unlike the C standard, the C++ standard doesn't even bother explaining
    name spaces. It makes only two uses of that term on it's own behalf, in connection with statement labels and macro names - neither usage has any plausible connection with a namespace. There are several occurrences of
    "name space" in the section describing the differences between C and
    C++, which make it clear that both standards are using the same meaning
    for "name space", but that the two languages have a different number of
    name spaces, with different contents.

    You seem to be speaking about terms in different standards while
    I spoke about "colloquially", the meaning of an expression named
    "name space", or "name-space", or "namespace" (whatever is the
    correct writing in English would be; note my hint about native
    speakers). - So, now, have we two been speaking cross-purpose?

    (As far as you are speaking about technical terms with a writing
    that carries (obvious, or not?) semantics my suggestion was just
    to indicate that explicitly to avoid misunderstandings.)

    Note that Scott in his post wrote

    In C++ they reside in the ordinary name space only if they're not
    part of a named namespace.

    which I interpreted as

    In C++ they reside in the ordinary "name space" only if they're not
    part of a named 'namespace'.

    where "name space" would be the [colloquial] name of the concept
    behind the symbol 'namespace'.

    My interpretation of his post was that he wanted to differentiate
    the default 'namespace' from the "named 'namespace'". (And that
    the three types of "Name Spaces" (that you had in mind) were not
    his concern with his remark.)

    Anyway, never mind.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Thu Dec 12 22:18:35 2024
    On 12.12.2024 19:17, bart wrote:
    On 12/12/2024 15:20, Janis Papanagnou wrote:
    [...]

    You don't think all these words are a clear indication? - The original
    text you see above is almost just a concatenation of all these negative
    connoted words. It really doesn't need any own words or interpretation.

    That's the point: you've extracted only the negative words to give a misleading picture.

    If you "concatenate" the significant words and glue them together
    with words to create an English sentence, and both are quite the
    same, what do expect.

    This compiler is , but it produces .
    It is of compiling 'gawk', and it does so that
    'make check' runs .

    However, in the past the , and the maintainer has
    with it. He recommends using it for regular
    development, where fast compiles are , but ,
    in case 'tcc' has .

    I've extracted the words that carry the quality semantics, and the
    result is completely useless.

    Extracting the key-attributes and key-characteristics, and the
    author's valuations drawn from experiences, was done by me for the
    readers convenience - or for (lowbrow?) people who are not willing
    to see or identify those attributes in the text "hidden" between
    all those "meaningless" glue-words.

    Again, just for your argument you make up nonsensical imputations.
    Why - don't - you - stop - that - ?

    How about highlighting these as well:

    (I already told you that I'm *not* *interested* in advocating any
    specific compiler, neither tcc nor gcc or anything else. So I will
    not play your game. - Why don't you make your cat fight with folks
    who are strong proponents or opponents of such tools as you are!)

    I have noted that you have a strong personal affinity to that tool;
    but I don't care. (If anything, I'm astonished about your fanatism.)

    What I did care about was; about whom Waldek spoke when formulating
    "explicit endorsement from gawk developer" - I asked "Who was that?"

    Because I was surprised by his statement and curious where he got
    that idea from. Since the statement I found gave a fairly different
    picture. YMMV. - And since I know Arnold - the head of the GNU Awk
    maintainers - from various public and private conversations, Waldek's interpretation (and yours, of course) irritated me, to say the least.

    My guess is that Waldek had no other source of information, that he
    read (or mis-read, as one likes) exactly the text I quoted, but I'm
    not sure. (Only he can clarify that. Not you, Bart.)

    [...]

    (I have neither a reason nor an agenda to downplay any compiler.

    Yet, you clearly are downplaying it.

    I am not interested in "compiler wars". - Have you some pathological
    problem to accept that, or are you just too stupid to understand it?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Thu Dec 12 22:12:25 2024
    On 12/12/2024 21:18, Janis Papanagnou wrote:
    On 12.12.2024 19:17, bart wrote:
    On 12/12/2024 15:20, Janis Papanagnou wrote:
    [...]

    You don't think all these words are a clear indication? - The original
    text you see above is almost just a concatenation of all these negative
    connoted words. It really doesn't need any own words or interpretation.

    That's the point: you've extracted only the negative words to give a
    misleading picture.

    If you "concatenate" the significant words and glue them together
    with words to create an English sentence, and both are quite the
    same, what do expect.

    This compiler is , but it produces .
    It is of compiling 'gawk', and it does so that
    'make check' runs .

    However, in the past the , and the maintainer has
    with it. He recommends using it for regular
    development, where fast compiles are , but ,
    in case 'tcc' has .

    I've extracted the words that carry the quality semantics, and the
    result is completely useless.

    Extracting the key-attributes and key-characteristics, and the
    author's valuations drawn from experiences, was done by me for the
    readers convenience - or for (lowbrow?) people who are not willing
    to see or identify those attributes in the text "hidden" between
    all those "meaningless" glue-words.

    Again, just for your argument you make up nonsensical imputations.
    Why - don't - you - stop - that - ?

    How about highlighting these as well:

    (I already told you that I'm *not* *interested* in advocating any
    specific compiler, neither tcc nor gcc or anything else. So I will
    not play your game. - Why don't you make your cat fight with folks
    who are strong proponents or opponents of such tools as you are!)

    I have noted that you have a strong personal affinity to that tool;
    but I don't care. (If anything, I'm astonished about your fanatism.)

    What I did care about was; about whom Waldek spoke when formulating
    "explicit endorsement from gawk developer" - I asked "Who was that?"

    Because I was surprised by his statement

    'his' being WH?

    If so, why? Astonished that anyone could find a lesser C compiler useful
    and productive?


    and curious where he got
    that idea from. Since the statement I found gave a fairly different
    picture. YMMV. - And since I know Arnold - the head of the GNU Awk maintainers - from various public and private conversations, Waldek's interpretation (and yours, of course) irritated me, to say the least.

    What you posted seemed to me like an endorsement. Even more so looking
    at the full extract.

    This is why /I/ was suprised that you thought it was trashing TCC.

    My guess is that Waldek had no other source of information, that he
    read (or mis-read, as one likes) exactly the text I quoted, but I'm
    not sure. (Only he can clarify that. Not you, Bart.)

    [...]

    (I have neither a reason nor an agenda to downplay any compiler.

    Yet, you clearly are downplaying it.

    I am not interested in "compiler wars".

    You clearly are. Certainly you seem to have it in for certain compilers:

    "And that it's obviously not trustworthy..."

    - Have you some pathological
    problem to accept that,

    I think the problem might be with you.

    or are you just too stupid to understand it?>

    So, you're calling a stranger 'stupid' because he has a different view
    from you?

    In the Reddit PL forum, which is moderated, one of the forum rules is to
    be civil and respectful. It specifically forbids personal attacks and
    insults.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to David Brown on Thu Dec 12 19:59:10 2024
    On 12/1/24 06:34, David Brown wrote:
    On 30/11/2024 00:44, Keith Thompson wrote:
    ...
    David apparently has a different definition of "totally different types"
    than you do. Since the standard doesn't define that phrase, I suggest
    not wasting time arguing about it.


    "int", "void" and "double" are totally different types in my view.
    "int", "pointer to int", "array of int", "function returning int" all
    have a relation that means I would not describe them as /totally/
    different types - though I would obviously still call them /different/
    types.

    The syntax of C allows one declaration statement to declare multiple identifiers of types related in this way - it does not allow declaration
    of types of /totally/ different types.

    There's a rule I sometimes find useful, when trying to choose a precise definition for a poorly defined term: figure out what statements you'd
    like to say using the term, then define it in such a way as to guarantee
    that those statements are correct.

    In C, a declaration may contain an init-declarator-list, preceded by declaration-specifiers and optionally by an attribute-specifer-sequence (6.7p1). Each of the declarators in the list share the
    declaration-specifiers and the attribute-specifier-sequence (6.7p7). Any
    syntax that's part of a declarator applies to that declarator's identifier.

    Therefore, your statement suggests that two types should be considered
    "totally different types" if they are incompatible in either the declaration-specifiers or the attribute-specifier-sequence. With that definition, 6.7p7 in the standard would guarantee the truth of your
    statement above.

    Does that definition sound suitable?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Thu Dec 12 20:31:20 2024
    On 12/12/24 15:27, Janis Papanagnou wrote:
    On 12.12.2024 20:39, James Kuyper wrote:
    On 12/12/24 00:07, Janis Papanagnou wrote:
    ...
    Personally I'd colloquially take both those terms as the same thing,
    but I'm not a native speaker.

    They are not.
    The C standard does not define the term "name space", relying instead
    upon the general CS definition of the term. However, it has a whole
    section (6.2.3) devoted to listing and explaining the name spaces that
    are relevant to the C language.

    In C++, "namespace" is a both a keyword (listed in 5.11p3) and a piece
    of terminology (defined in 9.8p1) for the feature enabled by that
    keyword. It is clear from those descriptions that a C++ namespace is
    significantly different thing from a C name space.
    Unlike the C standard, the C++ standard doesn't even bother explaining
    name spaces. It makes only two uses of that term on it's own behalf, in
    connection with statement labels and macro names - neither usage has any
    plausible connection with a namespace. There are several occurrences of
    "name space" in the section describing the differences between C and
    C++, which make it clear that both standards are using the same meaning
    for "name space", but that the two languages have a different number of
    name spaces, with different contents.

    You seem to be speaking about terms in different standards while
    I spoke about "colloquially", the meaning of an expression named
    "name space", or "name-space", or "namespace" (whatever is the
    correct writing in English would be; note my hint about native
    speakers). - So, now, have we two been speaking cross-purpose?

    Probably. It is never a good idea to use a term colloquially if that
    term has a well-defined meaning that applies in the relevant context
    which is significantly different from the colloquial meaning. Such usage inevitably results in confusion.

    Note that Scott in his post wrote

    In C++ they reside in the ordinary name space only if they're not
    part of a named namespace.

    which I interpreted as

    In C++ they reside in the ordinary "name space" only if they're not
    part of a named 'namespace'.

    where "name space" would be the [colloquial] name of the concept
    behind the symbol 'namespace'.

    My interpretation of his post was that he wanted to differentiate
    the default 'namespace' from the "named 'namespace'". (And that
    the three types of "Name Spaces" (that you had in mind) were not
    his concern with his remark.)

    That is a true statement about namespaces, and completely irrelevant to anything I was trying to say about name spaces.

    He said that in response to my comment, which was supposed to be:

    "In C struct, union, and enumeration tags have their own name space, in
    C++ they reside in the ordinary name space."

    However, I just noticed that, in my message as I actually posted it, I accidentally replaced the first occurrence of "name space" in that
    sentence with "namespace". Nothing in that sentence was intended to be
    about namespaces; it was entirely about name spaces. Does that clear up
    any confusion?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to James Kuyper on Fri Dec 13 09:13:18 2024
    On 13/12/2024 01:59, James Kuyper wrote:
    On 12/1/24 06:34, David Brown wrote:
    On 30/11/2024 00:44, Keith Thompson wrote:
    ...
    David apparently has a different definition of "totally different types" >>> than you do. Since the standard doesn't define that phrase, I suggest
    not wasting time arguing about it.


    "int", "void" and "double" are totally different types in my view.
    "int", "pointer to int", "array of int", "function returning int" all
    have a relation that means I would not describe them as /totally/
    different types - though I would obviously still call them /different/
    types.

    The syntax of C allows one declaration statement to declare multiple
    identifiers of types related in this way - it does not allow declaration
    of types of /totally/ different types.

    There's a rule I sometimes find useful, when trying to choose a precise definition for a poorly defined term: figure out what statements you'd
    like to say using the term, then define it in such a way as to guarantee
    that those statements are correct.

    In C, a declaration may contain an init-declarator-list, preceded by declaration-specifiers and optionally by an attribute-specifer-sequence (6.7p1). Each of the declarators in the list share the
    declaration-specifiers and the attribute-specifier-sequence (6.7p7). Any syntax that's part of a declarator applies to that declarator's identifier.

    Therefore, your statement suggests that two types should be considered "totally different types" if they are incompatible in either the declaration-specifiers or the attribute-specifier-sequence. With that definition, 6.7p7 in the standard would guarantee the truth of your
    statement above.

    Does that definition sound suitable?

    That definition sounds correct, yes, but also completely useless. It
    leads directly to a tautology - you can declare two things in the same declaration in C if you are allowed to declare them in the same
    declaration in C. I was simply trying to give such "things" can't have /totally/ different types, but need types that are in a certain way
    related. I didn't go into the details of how they had to be related,
    because it should have been obvious that those details are precisely
    what the C standard says in the section about declarations.

    It turns out that my comments there did not really help much - most C programmers already understand this stuff, and the poster who says he
    finds it all confusing likes to view every explanation as more confusing.

    So I think this is best dropped.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to James Kuyper on Fri Dec 13 14:10:17 2024
    On 13.12.2024 02:31, James Kuyper wrote:
    On 12/12/24 15:27, Janis Papanagnou wrote:
    [...]
    Note that Scott in his post wrote

    In C++ they reside in the ordinary name space only if they're not
    part of a named namespace.

    which I interpreted as

    In C++ they reside in the ordinary "name space" only if they're not
    part of a named 'namespace'.

    where "name space" would be the [colloquial] name of the concept
    behind the symbol 'namespace'.

    My interpretation of his post was that he wanted to differentiate
    the default 'namespace' from the "named 'namespace'". (And that
    the three types of "Name Spaces" (that you had in mind) were not
    his concern with his remark.)

    That is a true statement about namespaces, and completely irrelevant to anything I was trying to say about name spaces.

    He said that in response to my comment, which was supposed to be:

    "In C struct, union, and enumeration tags have their own name space, in
    C++ they reside in the ordinary name space."

    I understand that initially you might have not used the most
    accurate [standards-] term; that was not my point. I merely
    wanted to point out that [as to my reading] Scott wanted to
    make a different clarification (IMO a nit-pick, if you want);
    to extend your explanation (of ordinary unnamed] 'namespace's
    by mentioning named 'namespace's). Whether you wanted to say
    "name space" or whether you meant 'namespace'. - That was all;
    no deeper thought, no principal disagreement. :-)

    (But it's also possible I misinterpreted Scott's intention.)

    I anyway shouldn't have bothered to make any comment on that
    in the first place, I admit. It's minor, of little relevance.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Janis Papanagnou on Fri Dec 13 13:47:21 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 13.12.2024 02:31, James Kuyper wrote:
    On 12/12/24 15:27, Janis Papanagnou wrote:
    [...]
    Note that Scott in his post wrote

    In C++ they reside in the ordinary name space only if they're not
    part of a named namespace.

    which I interpreted as

    In C++ they reside in the ordinary "name space" only if they're not
    part of a named 'namespace'.

    where "name space" would be the [colloquial] name of the concept
    behind the symbol 'namespace'.

    My interpretation of his post was that he wanted to differentiate
    the default 'namespace' from the "named 'namespace'". (And that
    the three types of "Name Spaces" (that you had in mind) were not
    his concern with his remark.)

    That is a true statement about namespaces, and completely irrelevant to
    anything I was trying to say about name spaces.

    He said that in response to my comment, which was supposed to be:

    "In C struct, union, and enumeration tags have their own name space, in
    C++ they reside in the ordinary name space."

    I understand that initially you might have not used the most
    accurate [standards-] term; that was not my point. I merely
    wanted to point out that [as to my reading] Scott wanted to
    make a different clarification (IMO a nit-pick, if you want);
    to extend your explanation (of ordinary unnamed] 'namespace's
    by mentioning named 'namespace's). Whether you wanted to say
    "name space" or whether you meant 'namespace'. - That was all;
    no deeper thought, no principal disagreement. :-)

    (But it's also possible I misinterpreted Scott's intention.)

    You interpreted it correctly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Janis Papanagnou on Fri Dec 13 14:20:04 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    What I did care about was; about whom Waldek spoke when formulating
    "explicit endorsement from gawk developer" - I asked "Who was that?"

    Because I was surprised by his statement and curious where he got
    that idea from. Since the statement I found gave a fairly different
    picture. YMMV. - And since I know Arnold - the head of the GNU Awk maintainers - from various public and private conversations, Waldek's interpretation (and yours, of course) irritated me, to say the least.

    You can ask Arnold what he meant. I saw reasonably recent post
    by him implying the he is still using tcc. And a seqence of
    posts from 2013, where he reported problem with tcc and later
    wrote that new version (containing fixes) works to compile
    gawk. His messages indicated that he cared about compile
    speed and considerd tcc to be fast.

    From message about to tinycc-devel dated 'Sun, 06 Jan 2013':

    : It is quite fast, which is a significant pleasure compared to
    : gcc or clang.

    There he reports problems, later message confirms that changes
    to tcc fixed the them.

    Let me summarize facts as I see them:
    - he used tcc to develop gawk
    - he said that tcc can be used to compile gawk
    - he complained about speed of gcc/clang and noted that tcc is fast.
    If that is not an endorsement, than what is?

    Concerning statement that you found, "mediocre code", I think
    this is about speed of generated code. If I would write
    about tcc I would use different words to make is clearer,
    but this is fair warning for people who want to install
    and use gawk. For me testing using gcc before commit sounds
    like common sense. Still, the snippet says "He recommends
    using it for regular development". He could say "I do not
    recommend using tcc", or "use at your own risk".

    Concerning fairly different picture, I do not know what
    "in the past the quality has varied" means. If that means
    that there are reccuring troubles after 2013 fixes, than
    this somewhat spoils the picture. If that is about what was
    before 2013, then this sounds like reasonble disclaimer.

    Anyway, the point was about using 'tcc' for developement
    and clearly Aharon Robbins was serious about using 'tcc'
    for developing 'gawk'. He reported problems to 'tcc'
    developers and AFAICS the problems got fixed (Googler finds
    messages from 2013 but no later reports of troubles).

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Waldek Hebisch on Fri Dec 13 17:29:19 2024
    On 13/12/2024 15:20, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    What I did care about was; about whom Waldek spoke when formulating
    "explicit endorsement from gawk developer" - I asked "Who was that?"

    Because I was surprised by his statement and curious where he got
    that idea from. Since the statement I found gave a fairly different
    picture. YMMV. - And since I know Arnold - the head of the GNU Awk
    maintainers - from various public and private conversations, Waldek's
    interpretation (and yours, of course) irritated me, to say the least.

    You can ask Arnold what he meant. I saw reasonably recent post
    by him implying the he is still using tcc. And a seqence of
    posts from 2013, where he reported problem with tcc and later
    wrote that new version (containing fixes) works to compile
    gawk. His messages indicated that he cared about compile
    speed and considerd tcc to be fast.

    From message about to tinycc-devel dated 'Sun, 06 Jan 2013':

    : It is quite fast, which is a significant pleasure compared to
    : gcc or clang.

    There he reports problems, later message confirms that changes
    to tcc fixed the them.

    Let me summarize facts as I see them:
    - he used tcc to develop gawk

    I don't see that from what you have written here. Perhaps it is true,
    but unless I have missed something, you haven't given evidence of that.
    Note that "used tcc /while/ developing gawk" is not at all the same
    thing as "used tcc /to/ develop gawk". The tools you use to develop
    something are your main tools that help you produce good, working code.
    gcc is the tool he uses for get correct code - tcc is merely for quick turnaround testing. (Again, let me stress that it is possible that he
    did use tcc as a main compiler during development, but I don't think you
    have shown that.)

    - he said that tcc can be used to compile gawk

    Yes.

    - he complained about speed of gcc/clang and noted that tcc is fast.

    He said that tcc is "quite fast", faster than gcc or clang, and that he
    liked that it was fast. That is not the same thing as a direct
    complaint about the speed of gcc or clang - though clearly he would have
    been happier if those compilers had been faster. (And we all would be
    happier if they were faster - even those of us who find gcc fast enough
    for our needs.)

    If that is not an endorsement, than what is?


    It is saying that tcc is a tool you can use to compile gawk, and praise
    of its speed relative to gcc and clang. An endorsement would be saying
    that it is the compiler he likes to use or recommends using.

    If I write a program and say it can run on Linux or Windows, that is not
    an endorsement for Windows. Even if I say it will run a lot faster and smoother on Windows, it is still not an endorsement - perhaps there are
    other aspects that I consider more important and which work better on
    Linux (say, stability of the program, or the ability to handle bigger
    data sets). And even if I say the program runs best under Windows, I am
    not endorsing Windows for anything other than the use of that program.

    Again, perhaps he /does/ prefer tcc - either specifically for building
    tcc (rather than developing it), specifically for developing it, or in
    general for all his compilation needs. But you haven't shown that, and
    I don't get that impression from a "it can be compiled faster with tcc" comment.

    (As an aside, who would ever compile gawk, other than the developers and
    people building *nix distributions - who would all be using gcc or clang
    for the job? How much weight should we give the compiler endorsement of
    one guy who maintains an old project, and for which almost all users use pre-compiled binaries build using a different compiler?)

    Concerning statement that you found, "mediocre code", I think
    this is about speed of generated code. If I would write
    about tcc I would use different words to make is clearer,
    but this is fair warning for people who want to install
    and use gawk. For me testing using gcc before commit sounds
    like common sense. Still, the snippet says "He recommends
    using it for regular development". He could say "I do not
    recommend using tcc", or "use at your own risk".

    Concerning fairly different picture, I do not know what
    "in the past the quality has varied" means. If that means
    that there are reccuring troubles after 2013 fixes, than
    this somewhat spoils the picture. If that is about what was
    before 2013, then this sounds like reasonble disclaimer.

    I would take that to mean that because of previous known problems, he
    does not entirely trust the compiler's correctness now, and worries
    about current unknown bugs.


    Anyway, the point was about using 'tcc' for developement
    and clearly Aharon Robbins was serious about using 'tcc'
    for developing 'gawk'. He reported problems to 'tcc'
    developers and AFAICS the problems got fixed (Googler finds
    messages from 2013 but no later reports of troubles).


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Fri Dec 13 18:26:17 2024
    On 13.12.2024 17:29, David Brown wrote:
    On 13/12/2024 15:20, Waldek Hebisch wrote:
    [...]

    Since all I wanted is to know where you got your impression from,
    Waldek, my question is (yet) fully answered. - Thanks.

    I'm also glad that David had already thoroughly replied to your
    post and I'm alleviated from that burden. As got obvious he read
    (and interpreted) the quoted statement in exactly the same way as
    I did. - Thanks as well.

    [...]

    (As an aside, who would ever compile gawk, other than the developers and people building *nix distributions - who would all be using gcc or clang
    for the job? [...]

    I'm a bit puzzled about that statement. - I certainly compile the
    GNU Awk source from the tar-file whenever I get my hands on a new
    version (including beta-test versions).

    I haven't looked into the package makefile but I suppose it will
    use the "cc" that is standard on my system (which is a 'gcc').

    (It requires literally not more than a nett minute (to download &
    unpack & configure & make & install) on my old and rusty Linux box.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Fri Dec 13 12:24:41 2024
    On 12/13/24 08:10, Janis Papanagnou wrote:
    On 13.12.2024 02:31, James Kuyper wrote:
    ...
    He said that in response to my comment, which was supposed to be:

    "In C struct, union, and enumeration tags have their own name space, in
    C++ they reside in the ordinary name space."

    I understand that initially you might have not used the most
    accurate [standards-] term; that was not my point. I merely
    wanted to point out that [as to my reading] Scott wanted to
    make a different clarification (IMO a nit-pick, if you want);
    to extend your explanation (of ordinary unnamed] 'namespace's
    by mentioning named 'namespace's).

    I made an incorrect comment about the tag "namespace" which would have
    been a correct comment if I had instead used "name space". He responded
    with an incorrect comment about the "ordinary name space", which would
    have been correct (but irrelevant) if it had instead been about the
    "unnamed name space". I'd be happier about the subsequent discussion if
    I were sure that both of you understand that those are two different,
    unrelated things.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Fri Dec 13 18:42:01 2024
    On 13/12/2024 18:26, Janis Papanagnou wrote:
    On 13.12.2024 17:29, David Brown wrote:
    On 13/12/2024 15:20, Waldek Hebisch wrote:
    [...]

    Since all I wanted is to know where you got your impression from,
    Waldek, my question is (yet) fully answered. - Thanks.

    I'm also glad that David had already thoroughly replied to your
    post and I'm alleviated from that burden. As got obvious he read
    (and interpreted) the quoted statement in exactly the same way as
    I did. - Thanks as well.

    [...]

    (As an aside, who would ever compile gawk, other than the developers and
    people building *nix distributions - who would all be using gcc or clang
    for the job? [...]

    I'm a bit puzzled about that statement. - I certainly compile the
    GNU Awk source from the tar-file whenever I get my hands on a new
    version (including beta-test versions).


    Okay, I guess that answers my question - there /are/ some people who
    compile it from source on a regular basis.

    But I suspect that for a tool like gawk, that would be rare - for most
    people who use gawk, it usually makes little difference if they use a
    version from last month or last century, so they will use whatever their distribution provides. (I guess people who use source-based Linux
    distros will compile it on their own machine, but they too will
    generally use gcc or clang for that.)

    You are clearly far more of a gawk user than I am - do you think many
    people actively (as distinct from, say, a general update on a
    source-based Linux distro) download the source and compile it themselves?

    I haven't looked into the package makefile but I suppose it will
    use the "cc" that is standard on my system (which is a 'gcc').

    (It requires literally not more than a nett minute (to download &
    unpack & configure & make & install) on my old and rusty Linux box.)

    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Fri Dec 13 17:41:29 2024
    On 13/12/2024 16:29, David Brown wrote:
    On 13/12/2024 15:20, Waldek Hebisch wrote:

    - he complained about speed of gcc/clang and noted that tcc is fast.

    He said that tcc is "quite fast", faster than gcc or clang, and that he
    liked that it was fast.  That is not the same thing as a direct
    complaint about the speed of gcc or clang


    This is the link I found: https://www.gnu.org/software/gawk/manual/gawkworkflow/html_node/Compilers.html

    It includes these remarks:

    "Both GCC and clang are highly optimizing compilers that produce good
    code, but are very slow. There are two other compilers that are faster,
    but that may not produce quite as good code. However, they are both
    reasonable for doing development.

    The Tiny C Compiler, tcc

    This compiler is very fast, but it produces only mediocre code. It is
    capable of compiling gawk, and it does so well enough that ‘make check’ runs without errors."

    So GCC/clang are described as "very slow", while Tiny C is "very fast".

    It also suggests that TCC is "reasonable" for development.

    - though clearly he would have
    been happier if those compilers had been faster.  (And we all would be happier if they were faster - even those of us who find gcc fast enough
    for our needs.)

    If that is not an endorsement, than what is?


    It is saying that tcc is a tool you can use to compile gawk, and praise
    of its speed relative to gcc and clang.  An endorsement would be saying
    that it is the compiler he likes to use or recommends using.

    My link includes also this:

    "He recommends using it for regular development, where fast compiles are important, but rebuilding with GCC before doing any commits"

    How often are commits done relative to development builds? I assume they
    are less frequent here than recompiling, for the remark to make sense.

    So, it does sound like tcc is prefered for most compiles.

    It certainly paints, to me, a positive view of TCC rather than the
    negative one that you are JP seem to be intent on, even though the
    latter strongly claims to be 100% impartial, while accusing me of making
    things up.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Fri Dec 13 19:16:02 2024
    On 13.12.2024 18:42, David Brown wrote:
    On 13/12/2024 18:26, Janis Papanagnou wrote:
    On 13.12.2024 17:29, David Brown wrote:

    (As an aside, who would ever compile gawk, other than the developers and >>> people building *nix distributions - who would all be using gcc or clang >>> for the job? [...]

    I'm a bit puzzled about that statement. - I certainly compile the
    GNU Awk source from the tar-file whenever I get my hands on a new
    version (including beta-test versions).

    Okay, I guess that answers my question - there /are/ some people who
    compile it from source on a regular basis.

    But I suspect that for a tool like gawk, that would be rare - for most
    people who use gawk, it usually makes little difference if they use a
    version from last month or last century, so they will use whatever their distribution provides.

    Sorry, I cannot speak for "most people" since I have no idea how many
    people, in the first place, are using it at all. I just know there's
    a community of enthusiasts (myself included; so I'm biased).

    Therefore I wouldn't make any assessment about users' habits.

    My comment implied to be careful about such assessments. - You know
    there's some people that would even write their own compiler if all
    the existing ones don't please them. I think compiling a tool from
    source - given how simple that is and how fast it can be done - is
    by far more "normal" than that and not uncommon as far as I can see.

    (I guess people who use source-based Linux
    distros will compile it on their own machine, but they too will
    generally use gcc or clang for that.)

    Just to be clear; I'm not compiling all my Linux from scratch. It's
    just a couple of specific packages or specific versions of packages
    that I download as source and compile myself. - Beside the tools
    where I want a quick access to them it's (for example) also tools
    that aren't [officially or else] supported any more. The standard
    incantations (configure/make/install) makes it simple - of course
    only if that is supported by the respective tools; quality varies.


    You are clearly far more of a gawk user than I am - do you think many
    people actively (as distinct from, say, a general update on a
    source-based Linux distro) download the source and compile it themselves?

    Franky, I have no idea.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to David Brown on Fri Dec 13 14:13:47 2024
    On 12/13/24 03:13, David Brown wrote:
    On 13/12/2024 01:59, James Kuyper wrote:
    On 12/1/24 06:34, David Brown wrote:
    ...
    "int", "void" and "double" are totally different types in my view.
    "int", "pointer to int", "array of int", "function returning int" all
    have a relation that means I would not describe them as /totally/
    different types - though I would obviously still call them /different/
    types.

    The syntax of C allows one declaration statement to declare multiple
    identifiers of types related in this way - it does not allow declaration >>> of types of /totally/ different types.

    There's a rule I sometimes find useful, when trying to choose a precise
    definition for a poorly defined term: figure out what statements you'd
    like to say using the term, then define it in such a way as to guarantee
    that those statements are correct.

    In C, a declaration may contain an init-declarator-list, preceded by
    declaration-specifiers and optionally by an attribute-specifer-sequence
    (6.7p1). Each of the declarators in the list share the
    declaration-specifiers and the attribute-specifier-sequence (6.7p7). Any
    syntax that's part of a declarator applies to that declarator's
    identifier.

    Therefore, your statement suggests that two types should be considered
    "totally different types" if they are incompatible in either the
    declaration-specifiers or the attribute-specifier-sequence. With that
    definition, 6.7p7 in the standard would guarantee the truth of your
    statement above.

    Does that definition sound suitable?

    That definition sounds correct, yes, but also completely useless. It
    leads directly to a tautology - you can declare two things in the same declaration in C if you are allowed to declare them in the same
    declaration in C.

    No, it does not constitute a tautology. It leads you to a precise
    specification of what kinds of differences they are allowed to have
    while declaring them in the same declaration. To be specific, a
    declaration's declaration specifiers and attribute specifier sequence
    define a common type that is shared by all of that declaration's
    declarators. The individual declarators can define their identifiers as identifying a pointer to the common type, an array of the common type,
    or a function returning that common type - and that's it. All other
    aspects of the C type system will, if changed, result in a "totally
    different type".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to David Brown on Sat Dec 14 04:36:15 2024
    David Brown <david.brown@hesbynett.no> wrote:
    On 13/12/2024 15:20, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    What I did care about was; about whom Waldek spoke when formulating
    "explicit endorsement from gawk developer" - I asked "Who was that?"

    Because I was surprised by his statement and curious where he got
    that idea from. Since the statement I found gave a fairly different
    picture. YMMV. - And since I know Arnold - the head of the GNU Awk
    maintainers - from various public and private conversations, Waldek's
    interpretation (and yours, of course) irritated me, to say the least.

    You can ask Arnold what he meant. I saw reasonably recent post
    by him implying the he is still using tcc. And a seqence of
    posts from 2013, where he reported problem with tcc and later
    wrote that new version (containing fixes) works to compile
    gawk. His messages indicated that he cared about compile
    speed and considerd tcc to be fast.

    From message about to tinycc-devel dated 'Sun, 06 Jan 2013':

    : It is quite fast, which is a significant pleasure compared to
    : gcc or clang.

    There he reports problems, later message confirms that changes
    to tcc fixed the them.

    Let me summarize facts as I see them:
    - he used tcc to develop gawk

    I don't see that from what you have written here. Perhaps it is true,
    but unless I have missed something, you haven't given evidence of that.
    Note that "used tcc /while/ developing gawk" is not at all the same
    thing as "used tcc /to/ develop gawk". The tools you use to develop something are your main tools that help you produce good, working code.
    gcc is the tool he uses for get correct code - tcc is merely for quick turnaround testing.

    I do not get what distinction you want to make. If somebody listens
    to music while coding, then "while" looks appropriate. I develop
    a project intending to support compilation by compiler A, B, C, D, E
    (that is 5 different compilers), most developement happens using
    compiler A, but there are pieces of code specific to other compilers,
    which where developed using appropriate compiler. From time to time
    I run test to verify that using each compiler produces expected
    results. It is fair to say that I do small part of developement
    using other compilers, but I would say that I use them _to_ develop
    the project. It does not matter that they are not my main compiler.

    Concerning statements about tcc, blurb that Janis quoted literally
    says 'using tcc for developement'. And my reading of the whole
    blurb is that he was 'using tcc for developement' (there is more
    statements on the net, but I do not think it makes sense for me
    to dig them, this should be enough). I am not a native English
    speaker, but for me 'using X for developement of Y' and 'using X
    to develop Y' are synonyms, with second being shorter than the
    first, while in first skipping Y is more natural.

    (Again, let me stress that it is possible that he
    did use tcc as a main compiler during development, but I don't think you
    have shown that.)

    - he said that tcc can be used to compile gawk

    Yes.

    - he complained about speed of gcc/clang and noted that tcc is fast.

    He said that tcc is "quite fast", faster than gcc or clang, and that he
    liked that it was fast. That is not the same thing as a direct
    complaint about the speed of gcc or clang

    Janis snipped that part containing the complaint. Janis claimed that
    complaint does not mean that he liked speed of 'tcc', that is why
    I specifically quoted part where he said the he liked the speed.

    - though clearly he would have
    been happier if those compilers had been faster. (And we all would be happier if they were faster - even those of us who find gcc fast enough
    for our needs.)

    If that is not an endorsement, than what is?


    It is saying that tcc is a tool you can use to compile gawk, and praise
    of its speed relative to gcc and clang. An endorsement would be saying
    that it is the compiler he likes to use or recommends using.

    If I write a program and say it can run on Linux or Windows, that is not
    an endorsement for Windows.

    I would take is as an endorsement for "running the program on Windows".

    Anyway, you wrote:
    : No actual developer would care if their code can be compiled by your
    : little toy compiler, or even more complete little tools like tcc.

    Gawk developers disprove "no actual developer would care if their
    code can be compiled by tcc". A little grep search discoverd few
    tcc-specific lines added to configure machinery. Google search
    discoverd more projects, I did not try to find how many other
    project cared and how much, but clearly taken literally
    'no actual developer' is false (which you admited in another
    message). It is possible that 'majority of actual developers'
    do not care about tcc, I have no hard data, but my feeling is that
    developers caring abut tcc are not so small minority.
    For me this is quite different from "no actual developer".
    Even in non-literal reading IMO "no actual developer"
    exagerates smallness of this group.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Sat Dec 14 12:24:20 2024
    On 14/12/2024 04:36, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 13/12/2024 15:20, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    What I did care about was; about whom Waldek spoke when formulating
    "explicit endorsement from gawk developer" - I asked "Who was that?"

    Because I was surprised by his statement and curious where he got
    that idea from. Since the statement I found gave a fairly different
    picture. YMMV. - And since I know Arnold - the head of the GNU Awk
    maintainers - from various public and private conversations, Waldek's
    interpretation (and yours, of course) irritated me, to say the least.

    You can ask Arnold what he meant. I saw reasonably recent post
    by him implying the he is still using tcc. And a seqence of
    posts from 2013, where he reported problem with tcc and later
    wrote that new version (containing fixes) works to compile
    gawk. His messages indicated that he cared about compile
    speed and considerd tcc to be fast.

    From message about to tinycc-devel dated 'Sun, 06 Jan 2013':

    : It is quite fast, which is a significant pleasure compared to
    : gcc or clang.

    There he reports problems, later message confirms that changes
    to tcc fixed the them.

    Let me summarize facts as I see them:
    - he used tcc to develop gawk

    I don't see that from what you have written here. Perhaps it is true,
    but unless I have missed something, you haven't given evidence of that.
    Note that "used tcc /while/ developing gawk" is not at all the same
    thing as "used tcc /to/ develop gawk". The tools you use to develop
    something are your main tools that help you produce good, working code.
    gcc is the tool he uses for get correct code - tcc is merely for quick
    turnaround testing.

    I do not get what distinction you want to make. If somebody listens
    to music while coding, then "while" looks appropriate. I develop
    a project intending to support compilation by compiler A, B, C, D, E
    (that is 5 different compilers), most developement happens using
    compiler A, but there are pieces of code specific to other compilers,
    which where developed using appropriate compiler. From time to time
    I run test to verify that using each compiler produces expected
    results. It is fair to say that I do small part of developement
    using other compilers, but I would say that I use them _to_ develop
    the project. It does not matter that they are not my main compiler.

    Concerning statements about tcc, blurb that Janis quoted literally
    says 'using tcc for developement'. And my reading of the whole
    blurb is that he was 'using tcc for developement' (there is more
    statements on the net, but I do not think it makes sense for me
    to dig them, this should be enough). I am not a native English
    speaker, but for me 'using X for developement of Y' and 'using X
    to develop Y' are synonyms, with second being shorter than the
    first, while in first skipping Y is more natural.

    (Again, let me stress that it is possible that he
    did use tcc as a main compiler during development, but I don't think you
    have shown that.)

    - he said that tcc can be used to compile gawk

    Yes.

    - he complained about speed of gcc/clang and noted that tcc is fast.

    He said that tcc is "quite fast", faster than gcc or clang, and that he
    liked that it was fast. That is not the same thing as a direct
    complaint about the speed of gcc or clang

    Janis snipped that part containing the complaint. Janis claimed that complaint does not mean that he liked speed of 'tcc', that is why
    I specifically quoted part where he said the he liked the speed.

    - though clearly he would have
    been happier if those compilers had been faster. (And we all would be
    happier if they were faster - even those of us who find gcc fast enough
    for our needs.)

    If that is not an endorsement, than what is?


    It is saying that tcc is a tool you can use to compile gawk, and praise
    of its speed relative to gcc and clang. An endorsement would be saying
    that it is the compiler he likes to use or recommends using.

    If I write a program and say it can run on Linux or Windows, that is not
    an endorsement for Windows.

    I would take is as an endorsement for "running the program on Windows".

    Anyway, you wrote:
    : No actual developer would care if their code can be compiled by your
    : little toy compiler, or even more complete little tools like tcc.

    Gawk developers disprove "no actual developer would care if their
    code can be compiled by tcc". A little grep search discoverd few tcc-specific lines added to configure machinery. Google search
    discoverd more projects, I did not try to find how many other
    project cared and how much, but clearly taken literally
    'no actual developer' is false (which you admited in another
    message). It is possible that 'majority of actual developers'
    do not care about tcc, I have no hard data, but my feeling is that
    developers caring abut tcc are not so small minority.
    For me this is quite different from "no actual developer".
    Even in non-literal reading IMO "no actual developer"
    exagerates smallness of this group.


    Both JP and DB are clutching at straws.

    I really don't know why they so against the concept of a fast,
    streamlined compiler that cuts some corners. It's not as though there
    were some decree where you must choose either compiler A or B; you can
    use both!

    Clearly some people (obviously not those two) think the trade-offs are worthwhile. And they know how to mix-and-match A and B to be most
    productive.

    Personally I've also found some problems with TCC in building some
    programs, eg. missing bits in headers, or sometimes some mysterious error.

    I run TCC in order to compare compilation speed, and to that end I will sometimes tweak things (eg. I used my version of windows.h, or compiled preprocessed C in order to avoid a mire of conditional blocks which try
    and which determine which compile is running, and get it wrong).

    Once a program has compiled, I don't remember bugs in TCC's code; it's
    just a bit slower.

    (BTW when I tried to build TCC from source using gcc-O3, I found the
    resulting compiler even faster than the pre-build binaries! I found that
    a bit scary so I test only with binaries as supplied.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to bart on Sat Dec 14 13:47:57 2024
    bart <bc@freeuk.com> wrote:
    On 14/12/2024 04:36, Waldek Hebisch wrote:
    David Brown <david.brown@hesbynett.no> wrote:
    On 13/12/2024 15:20, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:


    Personally I've also found some problems with TCC in building some
    programs, eg. missing bits in headers, or sometimes some mysterious error.

    On my machine tcc installs the following headers:

    float.h stdarg.h stdbool.h stdnoreturn.h tcclib.h varargs.h stdalign.h stdatomic.h stddef.h tccdefs.h tgmath.h

    AFAICS the rest is taken from the system. I am not sure if tcc
    can handle all system headers, but it handled several most popular
    ones.

    I run TCC in order to compare compilation speed, and to that end I will sometimes tweak things (eg. I used my version of windows.h, or compiled preprocessed C in order to avoid a mire of conditional blocks which try
    and which determine which compile is running, and get it wrong).

    Once a program has compiled, I don't remember bugs in TCC's code; it's
    just a bit slower.

    (BTW when I tried to build TCC from source using gcc-O3, I found the resulting compiler even faster than the pre-build binaries! I found that
    a bit scary so I test only with binaries as supplied.)

    I compiled my from sources. Concerning "scary", there are many
    factors affecting observed speed. Some can be classified as
    measurement errors, some are actual difference in speed,
    some inbetween (what about programs A and B, where at fixed
    clock frequency A is faster, but OS/CPU reliably runs B at
    higher clock frequency, giving it better measured time).
    So, it is a bit scary to do measurements, one needs care to
    properly interpret the results. OTOH I find pretty normal
    that there are speed differences. I do not know your gcc
    settings, but one possible difference is that pre-build binary
    should run on wide variety of machines, with possibly suboptimal
    speed on your machine, while locally compiled one may be
    taylored to your machine. Or whoever created pr-build binary
    did not bother to specify -O3. Or some weird semi-random factor
    may cause observed result.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Bart on Sat Dec 14 20:17:49 2024
    Bart <bc@freeuk.com> wrote:

    OK, if it's so simple, explain it to me.

    Apparently the first line here needs a semicolon after }, the second
    doesn't:

    int X[1] = {0};
    void Y() {}

    Similarly here:

    if (x) y;
    if (x) {}

    Why?

    "Because that's what the grammar says" isn't a valid answer.

    In first approximation, for some constructs it is clear where
    the end is, so no need for semicolon, for some other semicolon
    is needed to mark the end. This rule does no work in all cases,
    for example 'continue' and 'break' are keywords and defining
    corresponding statements without semicolon would lead to
    no ambiguity. Similarly in case of 'goto'. 'return' is
    more tricky, but is seems that one could define it without
    semicolon. But here probably consistency won: 'break',
    'contunue', 'goto' statement, 'return' statement are perceived
    as simple statements and are covered by informal rule
    "simple statement needs terminationg semicolon". '{}'
    is a compound statement, hence not a simple statement.
    Similarly, 'if' is a complex statement, and needs no semicolon
    on its own. As you noted without terminating semicolon do-while
    loop would be ambigious, so it needs semicolon. I do
    not have example for declarations, but I suspect that defining
    then without semicolon would be ambigious. Function
    _definition_ is anambigious without terminating semicolon,
    so why put is there.

    Concerning "grammar says it", grammar for C90 from which one
    can generate working parser has 74 nonterminals. You could
    change some rules and still get working parser for a different
    language. So in this sense part of grammar is purely
    arbitrary. But other changes would lead to grammar that
    fails to work. If you look at rules you will see
    substantial similarities between some rules, so grammar
    is really simpler than what size alone would would suggest.
    So, having working and sane (that is relatively simple)
    grammar puts restrictions on the language, some changes
    simply do not fit. Some changes would lead to completely
    different language, that was not an option for C, as
    very first versions were intentionaly similar to earlier
    languages and later there was a body of existing programs
    and programmers.

    You write about confusion. I think that what you present
    grammarians would call "garden paths", that is perceiving/
    trying to make up different rules than grammar rules. In
    your 'if' example you ignore simple thing: 'if' needs no
    terminator on its own. It is null statement that needs
    terminating semicolon, and "empty" compound statement that
    does not need a terminator. Null statement and compound
    statement are quite different, in particular without
    semicolon you would not know that null statement is there,
    while compound statement can be easily recognized without
    need for terminator. There is no special rule for "if with
    null statement", if it were you would get needlessly complex
    grammar.

    In the first pair, one line is a declaration, another is
    function definition. Again, quite different constructs,
    one needing terminator, other not needing it.

    Garden paths are common in natural language and people
    cope quite well. So for normal (even beginer)
    programmers garden paths are not a real problem: you get
    confused once, learn the right way and go on. In many
    cases learning is unconcious, you simply get used to
    the way code is written, and when you make mistakes
    compiler tells you that there is an error, so you
    correct it.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Sat Dec 14 21:34:38 2024
    On 14/12/2024 20:17, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:

    OK, if it's so simple, explain it to me.

    Apparently the first line here needs a semicolon after }, the second
    doesn't:

    int X[1] = {0};
    void Y() {}

    Similarly here:

    if (x) y;
    if (x) {}

    Why?

    "Because that's what the grammar says" isn't a valid answer.

    In first approximation, for some constructs it is clear where
    the end is, so no need for semicolon, for some other semicolon
    is needed to mark the end. This rule does no work in all cases,
    for example 'continue' and 'break' are keywords and defining
    corresponding statements without semicolon would lead to
    no ambiguity. Similarly in case of 'goto'. 'return' is
    more tricky, but is seems that one could define it without
    semicolon. But here probably consistency won: 'break',
    'contunue', 'goto' statement, 'return' statement are perceived
    as simple statements and are covered by informal rule
    "simple statement needs terminationg semicolon". '{}'
    is a compound statement, hence not a simple statement.
    Similarly, 'if' is a complex statement, and needs no semicolon
    on its own. As you noted without terminating semicolon do-while
    loop would be ambigious, so it needs semicolon. I do
    not have example for declarations, but I suspect that defining
    then without semicolon would be ambigious. Function
    _definition_ is anambigious without terminating semicolon,
    so why put is there.

    For the same reason that f(1 2 3) might be unambiguous, as usually it's
    written f(1, 2, 3).

    Actually, since C likes to declare/define lists of things where other
    languages don't allow them, such as:

    typedef int T, U, *V;

    struct tag {int x;} a, b, c;

    enum {red, green} blue, yellow;

    I couldn't quite see why you can't do the same with functions:

    int F(void){return 1;}, G(void){return 2;}



    Concerning "grammar says it", grammar for C90 from which one
    can generate working parser has 74 nonterminals. You could
    change some rules and still get working parser for a different
    language. So in this sense part of grammar is purely
    arbitrary. But other changes would lead to grammar that
    fails to work. If you look at rules you will see
    substantial similarities between some rules, so grammar
    is really simpler than what size alone would would suggest.
    So, having working and sane (that is relatively simple)
    grammar puts restrictions on the language, some changes
    simply do not fit. Some changes would lead to completely
    different language, that was not an option for C, as
    very first versions were intentionaly similar to earlier
    languages and later there was a body of existing programs
    and programmers.

    You write about confusion. I think that what you present
    grammarians would call "garden paths", that is perceiving/
    trying to make up different rules than grammar rules. In
    your 'if' example you ignore simple thing: 'if' needs no
    terminator on its own.

    Now that you mention it, why not? In:

    if (c) s1; else s2;

    s1 and s2 are statements, but so is the whole if-else construct; why
    doesn't that need its own terminator?

    This is legal in C: {}{}{}{}.

    As I said, I wouldn't be able to explain it.

    It is null statement that needs
    terminating semicolon, and "empty" compound statement that
    does not need a terminator. Null statement and compound
    statement are quite different, in particular without
    semicolon you would not know that null statement is there,

    Identifying the end of /some/ statements shouldn't mean not needing
    terminators in those cases. It needs to be a consistent rule.


    while compound statement can be easily recognized without
    need for terminator. There is no special rule for "if with
    null statement", if it were you would get needlessly complex
    grammar.

    In the first pair, one line is a declaration, another is
    function definition. Again, quite different constructs,
    one needing terminator, other not needing it.

    Garden paths are common in natural language and people
    cope quite well. So for normal (even beginer)
    programmers garden paths are not a real problem: you get
    confused once, learn the right way and go on. In many
    cases learning is unconcious, you simply get used to
    the way code is written, and when you make mistakes
    compiler tells you that there is an error, so you
    correct it.

    But the exact rules remain fuzzy.

    I wondered if my syntaxes are any better. There, first it is necessary
    to consider programs written on one line, since auto-semicolon-insertion
    would confuse matters.

    Then, notionally, declarations, definitions, expressions and statements
    are all separated with a semicolon.

    In some cases, because I haven't been rigorous, one can be missed out,
    and it still works. But that would be an oversight in the parser. (And
    usually, the two parts would be separated by a newline, which turns into
    a semicolon.)

    The rule in the language (and in the grammar if I had one) is clear:

    if c then s1 else s2 fi

    Here no ";" are needed, as at each level of statement, there is only one expression or statement; nothing to separate. Here:

    if c;d then s1;s2 else s2;s3 fi; if e then s4 fi

    that ";" in "fi;" is needed to separate this statement from the next,
    even though you could probably figure out that the statement ends there.

    (Note the "c;d" is not an error.) Another example with function defs,
    although I never write them like this:

    proc F = end; proc G = end

    So, in this language, it is clear and consistent. Explaining why the
    multi-line version can leave the semicolons out is harder:

    if c
    d
    then
    s1
    s2
    else
    s2
    s3
    fi
    if
    e
    then
    s4
    fi

    (If I was going to attempt a formal grammar, I'd try and make semicolon injection part of the lexer. Then the parser would always see the
    semicolons it needs.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Sat Dec 14 22:37:00 2024
    On 14/12/2024 22:22, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    On 14/12/2024 20:17, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    [...]
    For the same reason that f(1 2 3) might be unambiguous, as usually
    it's written f(1, 2, 3).

    Actually, since C likes to declare/define lists of things where other
    languages don't allow them, such as:

    typedef int T, U, *V;

    struct tag {int x;} a, b, c;

    enum {red, green} blue, yellow;

    I couldn't quite see why you can't do the same with functions:

    int F(void){return 1;}, G(void){return 2;}

    Those are function *definitions*. Declarations, including function declarations, can be bundled :

    int F(void), G(void); // not suggesting this is good style

    Definitions that are not declarations, such as function definitions,
    cannot.

    I thought you liked consistency.

    Consistency would mean function definitions could be 'bundled' too.

    If the language allowed function definitions to be bundled, you could
    write something like :

    int F(void) {
    // 30 lines of code
    }, G(void) {
    // 50 lines of code
    }

    Is that what you want?

    I don't care about it. I just wondered why not since such lists are
    allowed elsewhere.

    [...]

    Now that you mention it, why not? In:

    if (c) s1; else s2;

    s1 and s2 are statements, but so is the whole if-else construct; why
    doesn't that need its own terminator?

    Because if it did, you'd need multiple semicolons at the end of nested statements. Is that what you want?

    No of course not. But I'm trying to shed light on the odd rules in
    language; this one is starting to look like a hack:

    S1; S2; S3;

    where:

    #define S1 if (c) a;
    #define S2 if (c) {a;}
    #define S3 if (c) a

    The end result is:

    if (c) a;; if (c) {a;}; if (c) a;

    It's messy. Also, is the semicolon considered part of the statement, or
    is it administered by whoever is assembling the statements within the
    bigger picture?

    Because in that case, they are not needed in S1, but the one after S2's expansion will still be superfluous.






    You seem to be pretending that there's some principle that all
    statements should be terminated by semicolons. There is no such
    principle, and there are multiple kinds of statements that don't
    require a trailing semicolon.

    This is legal in C: {}{}{}{}.

    As I said, I wouldn't be able to explain it.

    I could explain it to you, but I can't understand it for you.

    [...]

    Identifying the end of /some/ statements shouldn't mean not needing
    terminators in those cases. It needs to be a consistent rule.

    Why? C's grammar is unambiguous. Given reasonable code layout, most C programmers don't have any problems determining where statements end.
    With your "consistent rule", if you had 5 nested statements (if, for,
    while, etc.), you'd have to terminate the entire construct at least 5 semicolons.

    Is that really what you want?

    As I said, the whole thing is starting to look like a hack just so you
    /don't/ end up with sequences of semicolons.

    [...]

    But the exact rules remain fuzzy.

    The exact rules are not fuzzy. They're unambiguous, and they work much better than you're willing to acknowledge.

    [discussion of your personal language snipped]

    <example of what a more consistent syntax looks like snipped>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Sat Dec 14 23:14:58 2024
    On 14/12/2024 22:54, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    On 14/12/2024 22:22, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    On 14/12/2024 20:17, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    [...]
    For the same reason that f(1 2 3) might be unambiguous, as usually
    it's written f(1, 2, 3).

    Actually, since C likes to declare/define lists of things where other
    languages don't allow them, such as:

    typedef int T, U, *V;

    struct tag {int x;} a, b, c;

    enum {red, green} blue, yellow;

    I couldn't quite see why you can't do the same with functions:

    int F(void){return 1;}, G(void){return 2;}
    Those are function *definitions*. Declarations, including function
    declarations, can be bundled :
    int F(void), G(void); // not suggesting this is good style
    Definitions that are not declarations, such as function definitions,
    cannot.
    I thought you liked consistency.

    Consistency would mean function definitions could be 'bundled' too.

    Declarations can be bundled. Function definitions cannot.

    More generally, some things can be bundled, and other things cannot.

    The existing rules are consistent.

    What else do you think should be able to be bundled? Macro definitions? Include directives?

    #include <stdio.h>, <stddef.h>; // ???

    The preprocessor is a separate, strictly line-oriented language.
    Arguably with better syntax than C itself:

    #if
    #if
    #endif
    #else
    #endif

    No dangling else here! And ... no semicolons.

    C is not 100% consistent and orthogonal. It was never intended to be.
    Every here knows that it isn't. If you want Lisp, whose syntax rules
    are simpler than C's, you know where to find it.

    Google "foolish consistency".

    If the language allowed function definitions to be bundled
    [...]
    I don't care about it.

    Excellent. Then let's drop it.

    I was idly speculating in my reply to WH. There was no need to get involved.

    It just seems to be the case that here:

    A B C D E F G

    Where each letter represents a declaration, statement, etc, there is no
    simple way of working out where any semicolons would go, whether
    inbetween or also at the end. You'd each to examine each each one, and
    also consider whether each already ends with a semicolon.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Wed Dec 18 16:04:06 2024
    On 12/12/24 06:38, Janis Papanagnou wrote:
    On 12.12.2024 06:35, Keith Thompson wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    [...]
    For (yet another) example; my K&R shows a syntax for expressions like

    expression := binary
    binary := binary + binary
    binary := binary * binary

    That's odd. Is that an exact quotation?

    No, not exact, I abbreviated it; omitted about 25 other operators and
    used another syntax (no ' | '). (Trust me that it hasn't things that
    I called 'factor' and 'term' in my post, which is equivalent to what
    you have formulated below in your copy.) - I'm using a translation of something that someone classified as being a "pre-second" edition but
    not quite the first edition. Two references point to 1977 (Prentice
    Hall) and 1978 (Bell Labs). - The text for the "binary" syntax has two optional informal columns, the first one has the comment "precedence"
    for some of the variants of "binary" operators. (But it's also just
    titled as "Syntax in Short"; probably presented in a form to make it
    easy to understand without overloading it for purpose of a textbook.)
    It serves the purpose to explain an ambiguous syntax with non-codified precedence and a separate precedence table (but it's not an exact "C"
    syntax description as you'd probably find it in standards documents).

    My copy of K&R 1st edition has nothing remotely resembling that. I
    cannot find "binary" as an element of the grammar anywhere. There are 16 grammar rules for "expression". The one that comes closest is
    "expression binop expression", where binop is one of C's 19 binary
    operators, divided into 12 different priority levels.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to James Kuyper on Thu Dec 19 01:35:38 2024
    On 18.12.2024 22:04, James Kuyper wrote:
    On 12/12/24 06:38, Janis Papanagnou wrote:
    [...]

    My copy of K&R 1st edition has nothing remotely resembling that.

    I think someone here already mentioned that the English version
    looks different compared to the translation I've in my bookshelf.
    (So I am not sure what your post is actually intending.[*])

    (But that's anyway unimportant to the point I made; that you can
    define semantical information like the precedence separately or
    by syntax.[**])

    Janis

    PS: FYI; Some of your posts, James, arrive also in my mailbox.

    [*] I've put (if you're interested) a scan of that page uploaded
    here: http://volatile.gridbug.de/KR_syntax-rotated90.pdf
    (But similar syntaxes for expressions can be found also in other
    programming languages' contexts; see below.)

    [**] There's various levels of abstraction possible. For example
    - describe expressions in- or semi-formally (e.g. in Bolsky/Korn)
    - describe them without precedence semantics ("K&R DE version")
    - reflect operator precedence in syntax (quite typical)
    - allow extensions/change of operators and precedence (Algol 68)
    (Sometimes there's no clear line; e.g. part of the definitions
    for expressions in Bolsky/Korn are like in the "K&R DE version",
    and the precedence is defined by the order they are listed.)

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Thu Dec 19 06:39:44 2024
    On 12/18/24 19:35, Janis Papanagnou wrote:
    On 18.12.2024 22:04, James Kuyper wrote:
    On 12/12/24 06:38, Janis Papanagnou wrote:
    [...]

    My copy of K&R 1st edition has nothing remotely resembling that.

    I think someone here already mentioned that the English version
    looks different compared to the translation I've in my bookshelf.
    (So I am not sure what your post is actually intending.[*])> (But that's anyway unimportant to the point I made; that you can
    define semantical information like the precedence separately or
    by syntax.[**])

    Janis

    PS: FYI; Some of your posts, James, arrive also in my mailbox.

    Yes, as I've explained before, in April, 2021, Thunderbird changed from
    having a Reply button that sends the response to the newsgroup, to
    having a Followup button that does the same thing, and a Reply button
    that sends the response by e-mail to the author. I spent a couple of
    decades learning to hit the Reply button, and at 66 years of age, after
    three years, I'm still finding it difficult to unlearn that habit,
    though I've made some progress.
    [*] I've put (if you're interested) a scan of that page uploaded
    here: http://volatile.gridbug.de/KR_syntax-rotated90.pdf
    (But similar syntaxes for expressions can be found also in other
    programming languages' contexts; see below.)


    It's not just that it "looks different". It is substantially different
    from the First Edition, which had "expression binop expression" as one
    of the rules for expression, with a precedence table for binop. It is
    also substantially different from the second edition, which closely
    matched C89, with a separate grammar production for each level of
    precedence. Nor does it look like a plausible intermediate step between
    those formulations, which is roughly how you described it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to James Kuyper on Thu Dec 19 14:58:24 2024
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 12/12/24 06:38, Janis Papanagnou wrote:
    On 12.12.2024 06:35, Keith Thompson wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    [...]
    For (yet another) example; my K&R shows a syntax for expressions like

    expression := binary
    binary := binary + binary
    binary := binary * binary

    That's odd. Is that an exact quotation?

    No, not exact, I abbreviated it; omitted about 25 other operators and
    used another syntax (no ' | '). (Trust me that it hasn't things that
    I called 'factor' and 'term' in my post, which is equivalent to what
    you have formulated below in your copy.) - I'm using a translation of
    something that someone classified as being a "pre-second" edition but
    not quite the first edition. Two references point to 1977 (Prentice
    Hall) and 1978 (Bell Labs). - The text for the "binary" syntax has two
    optional informal columns, the first one has the comment "precedence"
    for some of the variants of "binary" operators. (But it's also just
    titled as "Syntax in Short"; probably presented in a form to make it
    easy to understand without overloading it for purpose of a textbook.)
    It serves the purpose to explain an ambiguous syntax with non-codified
    precedence and a separate precedence table (but it's not an exact "C"
    syntax description as you'd probably find it in standards documents).

    My copy of K&R 1st edition has nothing remotely resembling that. I
    cannot find "binary" as an element of the grammar anywhere. There are 16 grammar rules for "expression". The one that comes closest is
    "expression binop expression", where binop is one of C's 19 binary
    operators, divided into 12 different priority levels.

    Apparently translators took freedom to make various changes.
    Polish translation of 1st edition has rules with translated
    names for nontermials. There are 17 rules for expressions,
    one of which contains binary operator. Text following this
    listens 18 binary operators, divided into 10 priority levels.
    Translators claimed that they removed inaccuracies, but
    probably planted extra confusion by having extra rule for
    comma operator and relating priority of assignment operators
    and other operators.

    BTW: Polish translators also changed examples for K&R style
    to Allman style...

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Mon Dec 23 16:02:26 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Wed, 11 Dec 2024 21:19:54 +0000
    bart <bc@freeuk.com> wrote:

    This also comes up with 'while (cond); {...}'.

    $ cat foo.c
    void foo(int x)
    {
    while (x--);
    bar();
    }

    $ clang-format < foo.c
    void foo(int x) {
    while (x--)
    ;
    bar();
    }

    Do I use clamg-format myself? No, I don't.

    And I don't know why C formatters are generally less popular among C programmers then, for example, go formater among Go programmers or Rust formatter among Rust programmers.

    I don't have any experience with Go formatters or Rust formatters.
    My experience with C formatters is that they format too much; in
    some ways they help, but in other ways they interfere with choices
    that are incidental to the high-level adjustments desired. It
    would be nice to see a code formatter that respects low-level
    choices while adjusting high-level format rules. To say this
    another way, the formatting that is done is too rigid - the tool
    always adjusts everything, instead of adjusting only those aspects
    that are needed to fix the high-level transgressions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)