• Re: transpiling to low level C

    From Lawrence D'Oliveiro@21:1/5 to Thiago Adams on Sun Dec 15 04:31:07 2024
    On Sun, 15 Dec 2024 00:05:13 -0300, Thiago Adams wrote:

    - Use C as an intermediate language to feed a backend (any C compiler
    can act as the backend).
    The backend can then focus solely on code generation.

    Would this be for architectures not already covered by LLVM?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Thiago Adams on Sun Dec 15 11:28:45 2024
    On 15/12/2024 03:05, Thiago Adams wrote:

    I am working on a C backend that generates simple C code.

    You can test it here:
    http://thradams.com/cake/playground.html

    Objective
    - Shift all the complexity of the C compiler to the frontend.
      Why? This approach simplifies having one frontend and multiple backends. - Use C as an intermediate language to feed a backend (any C compiler
    can act as the backend).
      The backend can then focus solely on code generation.
    - Code is not portable

    Removed C89 Features
    - Preprocessor
    - sizeof

    If I try:

    printf("%zu\n", sizeof(void*));

    it turns into:

    printf("%zu\n", 4U);

    Presumably this translator will only target 32-bit systems even if run
    on a 64-bit one?

    (My own C transpiler goes the other way and generates 'C64', requiring a
    64-bit compiler. Earlier versions made it optional, but the output was
    then either C32 or C64; if someone else compiled it, they'd have to
    choose the right compiler option.)

    I don't know if that "%zu" format will be an issue.



    - typedef
    - enum
    - Constant expressions (the final result is precomputed during earlier stages)
    - const
    - I may also remove switch.

    You can do that. But it can also slow down certain programs. (TCC 0.9.26 generated seqential tests for switch, but on one benchmark that relied
    on it heavily, its code was slower than my dynamic interpreter.)

    If you think this might be too hard to compile later, you can choose to
    do the same. (As for parsing switch, you'd need to do that anyway,
    either in the transpiler, or the backend compiler.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Bonita Montero on Sun Dec 15 21:32:11 2024
    On 15/12/2024 19:08, Bonita Montero wrote:
    C++ is more readable because is is magnitudes more expressive than C.
    You can easily write a C++-statement that would hunddres of lines in
    C (imagines specializing a unordered_map by hand). Making a language
    less expressive makes it even less readable, and that's also true for
    your reduced C.


    That's not really the point of it. This reduced C is used as an
    intermediate language for a compiler target. It will not usually be
    read, or maintained.

    An intermediate language needs to at a lower level than the source language.

    And for this project, it needs to be compilable by any C89 compiler.

    Generating C++ would be quite useless.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Thiago Adams on Sun Dec 15 22:22:09 2024
    On Sun, 15 Dec 2024 07:44:34 -0300, Thiago Adams wrote:

    I also think LLVM is too big.

    How about QBE, then <https://c9x.me/compile/>.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to BGB on Mon Dec 16 10:36:04 2024
    On 16/12/2024 00:53, BGB wrote:
    On 12/15/2024 3:32 PM, bart wrote:
    On 15/12/2024 19:08, Bonita Montero wrote:
    C++ is more readable because is is magnitudes more expressive than C.
    You can easily write a C++-statement that would hunddres of lines in
    C (imagines specializing a unordered_map by hand). Making a language
    less expressive makes it even less readable, and that's also true for
    your reduced C.


    That's not really the point of it. This reduced C is used as an
    intermediate language for a compiler target. It will not usually be
    read, or maintained.

    An intermediate language needs to at a lower level than the source
    language.

    And for this project, it needs to be compilable by any C89 compiler.

    Generating C++ would be quite useless.


    As an IL, even C is a little overkill, unless turned into a restricted
    subset (say, along similar lines to GCC's GIMPLE).


    Have either you or Thiago looked at C-- as an alternative? I don't know
    how practical it would be.

    <https://en.wikipedia.org/wiki/C-->

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to BGB on Mon Dec 16 11:46:16 2024
    On 16/12/2024 07:02, BGB wrote:
    On 12/15/2024 5:22 PM, Thiago Adams wrote:
    Em 12/15/2024 7:22 PM, Lawrence D'Oliveiro escreveu:
    On Sun, 15 Dec 2024 07:44:34 -0300, Thiago Adams wrote:

    I also think LLVM is too big.

    How about QBE, then <https://c9x.me/compile/>.

    QBE is just for linux and it does not generate code directly. C is
    everywhere.
    But I am reading QBE docs to see what is necessary in a IL.


    I agree that both LLVM and GCC are too big.

    I've just been working on a new backend which can be shared between
    different projects. It can be built into a standalone library, which has
    a size from 70KB to 180KB (x64 target), depending on output options.
    (30K of that is my language's std library.)

    The 70KB product interprets only. The full one can also generate
    EXE/DLL/OBJ files, my private MX format, ASM source, IL source (when
    code has been generated via its API), or it can run programs directly as
    native code (when not interpreting the IL!).

    It's several magnitudes smaller in scale than LLVM, and can be compiled
    from source in 0.06 seconds:

    c:\px>tm mm6 -opt pcl -dll
    Compiling pcl.m to pcl.dll
    TM: 0.06

    c:\px>dir pcl.dll
    16/12/2024 11:38 175,616 pcl.dll


    I am not sure the minimum size of a usable C compiler, my current
    estimate is probably somewhere in the area of 50-100 kLOC.

    My current compiler is a bit bigger than this, and my own past attempt
    to implement a C compiler in under 30k lines had failed.

    Mine, for quite a large subset (that can compile Lua and sqlite3 for
    example), is between 180KB and 290KB. That's roughly 20 to 30Kloc,
    assuming that one line of code maps to approx 10 bytes of x64 code.

    The 18KB version is to interpret only; the 290K is 'fully loaded' (see
    above). But usually my C standard headers are embedded, adding 40KB. (I
    no longer embed windows.h; that's a massive 600KB.

    But, people write all sorts of much smaller C compilers, obviously with
    some compromises. The smallest I remember is one fitting into a 512-byte boot-loader.

    If I were to estimate a feature set for a 3AC IL:
      Basic UNARY and BINARY operators;
        Also COMPARE and similar;
      Load and Store Index operators;
        With support for an immediate index;
      GOTO
      IF-GOTO
      CALL (with a list of argument variables and a target variable).

    The IL I mentioned above isn't that small. There are about 150
    instructions. Probably half could be dispensed with (eg. 'MIN/MAX' ops,
    or in-place MUL), but then the functionality needs to be provided by
    other means. And as I showed, the resulting backend isn't that huge.

    It uses a stack-model, and IL code looks ugly. I'd also developed a 3AC
    IL that looked gorgeous, like a mini-HLL, but that was just too hard to
    work with, even though such a model is similar to SSA which is very popular.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to BGB on Mon Dec 16 18:12:40 2024
    On 16.12.2024 00:53, BGB wrote:
    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Mon Dec 16 18:37:08 2024
    On 16/12/2024 17:12, Janis Papanagnou wrote:
    On 16.12.2024 00:53, BGB wrote:
    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    You would do away with just about the simplest feature of any language,
    and insist users emulate intra-function branching via function calls?

    I'd like to see your design of IL that doesn't have branching! I guess
    it would also need closures and/or continuations. I suspect you either
    don't quite understand what an IL is for, or forgot that's what this is
    about.

    An IL is typically lower level than the source language, while higher
    level than a native code target which makes it easier to generate code
    for. A functional IL would make it harder than assembly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to BGB on Mon Dec 16 19:44:59 2024
    On Mon, 16 Dec 2024 01:02:41 -0600, BGB wrote:

    I agree that both LLVM and GCC are too big.

    And yet LLVM is used heavily in many specialist applications.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Mon Dec 16 21:39:54 2024
    On 16.12.2024 19:37, bart wrote:
    On 16/12/2024 17:12, Janis Papanagnou wrote:
    On 16.12.2024 00:53, BGB wrote:
    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    You would do away with just about the simplest feature of any language,
    and insist users emulate intra-function branching via function calls?

    Why are you, yet again, and still, making up nonsensical suppositions!


    I'd like to see your design of IL that doesn't have branching! I guess
    it would also need closures and/or continuations. I suspect you either
    don't quite understand what an IL is for, or forgot that's what this is about.

    Why are you, yet again, and still, making up nonsensical suppositions!

    I wasn't commenting on any "IL", nor on any "emulation". I also didn't
    restrict my view to any specific machine model (as you have obviously
    been doing).

    You can still see what I was commenting on in the single sentence that
    I quoted in my post. (No more and no less.) - If you have anything to
    say (without any nonsensical suppositions), concerning the quote and
    my response, feel free to make another try.


    An IL is typically lower level than the source language, while higher
    level than a native code target which makes it easier to generate code
    for. A functional IL would make it harder than assembly.

    If you want to talk about "IL" or "assembly" search another target for discussing your ideas.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to BGB on Mon Dec 16 21:23:08 2024
    On Sun, 15 Dec 2024 17:53:30 -0600, BGB wrote:

    As an IL, even C is a little overkill, unless turned into a restricted
    subset ...

    Why not use WASM as your IL?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bonita Montero on Mon Dec 16 21:22:31 2024
    On Sun, 15 Dec 2024 20:08:53 +0100, Bonita Montero wrote:

    C++ is more readable because is is magnitudes more expressive than C.

    And it is certainly more surprising than C. Often unpleasantly so.

    You can easily write a C++-statement that would hunddres of lines in C

    Yes, but *which* hundreds of lines, exactly, would be the correct C
    equivalent?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Mon Dec 16 23:36:03 2024
    On 16/12/2024 21:59, Keith Thompson wrote:
    BGB <cr88192@gmail.com> writes:
    [...]
    If I were to estimate a feature set for a 3AC IL:
    Basic UNARY and BINARY operators;
    Also COMPARE and similar;
    Load and Store Index operators;
    With support for an immediate index;
    GOTO
    IF-GOTO
    CALL (with a list of argument variables and a target variable).

    One doesn't need any higher-level control flow constructs.
    [...]

    Have you looked at C-- (cminusminus)?

    https://en.wikipedia.org/wiki/C--

    I looked at it perhaps 15 years ago. I got the impression it was dead.

    According to your link (which might be broken, the "--" could be missing
    when clicked), it was discontinued in 2013, and the only form of it
    exists inside GHC, which uses various special backends specific to that product:

    "GHC backends are responsible for further transforming C-- into
    executable code, via LLVM IR, slow C, or directly through the built-in
    native backend"

    I can't see that is available as a general purpose ready-to-use backend
    for other languages, and for the targets that people might want (eg. x64
    for Win64).

    Or if there was, how practical it might be, in terms of compile-speed,
    code quality, output options etc. If it has to be fed to LLVM, then you
    might as well use LLVM directly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Mon Dec 16 23:26:22 2024
    On 16/12/2024 20:39, Janis Papanagnou wrote:
    On 16.12.2024 19:37, bart wrote:
    On 16/12/2024 17:12, Janis Papanagnou wrote:
    On 16.12.2024 00:53, BGB wrote:
    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    You would do away with just about the simplest feature of any language,
    and insist users emulate intra-function branching via function calls?

    Why are you, yet again, and still, making up nonsensical suppositions!


    I'd like to see your design of IL that doesn't have branching! I guess
    it would also need closures and/or continuations. I suspect you either
    don't quite understand what an IL is for, or forgot that's what this is
    about.

    Why are you, yet again, and still, making up nonsensical suppositions!

    I wasn't commenting on any "IL",

    The subthread was about ILs.

    nor on any "emulation". I also didn't
    restrict my view to any specific machine model (as you have obviously
    been doing).

    You can still see what I was commenting on in the single sentence that
    I quoted in my post. (No more and no less.) - If you have anything to
    say (without any nonsensical suppositions), concerning the quote and
    my response, feel free to make another try.

    In that case I've no idea what you were trying to say.

    When somebody says that 'goto' can emulate any control structure, then
    clearly some of them need to be conditional; that is implied.

    Your reply suggested they you can do away with 'goto', and use recursive functions, in a scenario where no other control structures need exist.

    OK, if this is not for an IL, then it's not a language I would care for
    either. Why tie one hand behind your back for no good reason?

    If you want to talk about "IL" or "assembly" search another target for discussing your ideas.


    So what was your proposal about?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lawrence D'Oliveiro on Tue Dec 17 11:16:58 2024
    On Mon, 16 Dec 2024 21:23:08 -0000 (UTC)
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sun, 15 Dec 2024 17:53:30 -0600, BGB wrote:

    As an IL, even C is a little overkill, unless turned into a
    restricted subset ...

    Why not use WASM as your IL?

    Because he is DIY character.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Tue Dec 17 12:04:29 2024
    On 16/12/2024 21:23, Lawrence D'Oliveiro wrote:
    On Sun, 15 Dec 2024 17:53:30 -0600, BGB wrote:

    As an IL, even C is a little overkill, unless turned into a restricted
    subset ...

    Why not use WASM as your IL?

    Have you tried it? I mean, directly generating WASM from a compiler
    front-end, not just using somebody else's tool to do so.

    WASM is a stack-based language, but one that supposedly doesn't even
    have branching, although there is a 'br' statement, with some restrictions.

    Information about it is quite elusive; it took me 5 minutes to even get examples of what it looks like (and I've seen it before).

    C can apparently compile to WASM via Clang, so I tried this program:

    void F(void) {
    int i=0;
    while (i<10000) ++i;
    }

    which compiled to 128 lines of WASM (technically, some form of 'WAT', as
    WASM is a binary format). The 60 lines correspondoing to F are shown
    below, and below that, is my own stack IL code.

    So, what do you with your WASM/WAT program once generated? I've no idea,
    except that WASM is inextricably typed up with with browsers and with JavaScript, in which I have no interest.

    With C, you run a compiler; with ASM, an assembler; these formats are
    well understood.

    You can appreciate that it can be easier to devise your own format and
    your own tools that you understand 100%.




    --------------------------------------
    F: # @F
    .functype F () -> ()
    .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
    i32, i32
    # %bb.0:
    global.get __stack_pointer
    local.set 0
    i32.const 16
    local.set 1
    local.get 0
    local.get 1
    i32.sub
    local.set 2
    i32.const 0
    local.set 3
    local.get 2
    local.get 3
    i32.store 12
    .LBB0_1: # =>This Inner Loop Header: Depth=1
    block
    loop # label1:
    local.get 2
    i32.load 12
    local.set 4
    i32.const 10000
    local.set 5
    local.get 4
    local.set 6
    local.get 5
    local.set 7
    local.get 6
    local.get 7
    i32.lt_s
    local.set 8
    i32.const 1
    local.set 9
    local.get 8
    local.get 9
    i32.and
    local.set 10
    local.get 10
    i32.eqz
    br_if 1 # 1: down to label0
    # %bb.2: # in Loop: Header=BB0_1 Depth=1
    local.get 2
    i32.load 12
    local.set 11
    i32.const 1
    local.set 12
    local.get 11
    local.get 12
    i32.add
    local.set 13
    local.get 2
    local.get 13
    i32.store 12
    br 0 # 0: up to label1 .LBB0_3:
    end_loop
    end_block # label0:
    return
    end_function

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

    proc F::
    local i32 i.1
    load i32 0
    store i32 i.1
    jump #2
    #4:
    load u64 &i.1
    incrto i32 /1
    #2:
    load i32 i.1
    load i32 10000
    jumplt i32 #4
    #3:
    #1:
    retproc
    endproc

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Tue Dec 17 16:17:37 2024
    On 17/12/2024 01:19, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    [SNIP]
    In that case I've no idea what you were trying to say.

    When somebody says that 'goto' can emulate any control structure, then
    clearly some of them need to be conditional; that is implied.

    Your reply suggested they you can do away with 'goto', and use
    recursive functions, in a scenario where no other control structures
    need exist.

    OK, if this is not for an IL, then it's not a language I would care
    for either. Why tie one hand behind your back for no good reason?

    I read Janis's post. I saw a suggestion that certain constructs are *theoretically* unnecessary. I saw no suggestion of any advocacy for
    such an approach.

    """
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.
    """

    This doesn't actually make much sense. So 'goto' is necessary, but
    'goto' *is*?

    If you try to extract any meaning, it is that any control flow can be
    expressed either with 'goto' or with 'recursive functions'.

    This is what I picked up on. Who on earth would eschew 'goto' and use
    such a disproportionately more complex and inefficient method like
    recursive functions?

    How would you even express an arbitrary goto from random point X in a
    function to random point Y, which may be inside differently nested
    blocks, via a recursive function?

    If this is suppposed to be theoretically possible, then neither do you
    need a compiler OR a computer to run any program! Pencil and paper will
    work.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Tue Dec 17 18:18:27 2024
    On 17.12.2024 17:17, bart wrote:
    On 17/12/2024 01:19, Keith Thompson wrote:
    [...]

    """
    [...] but it isn't strictly *necessary*. [...]
    """

    This doesn't actually make much sense. So 'goto' is necessary, but
    'goto' *is*?

    Have you issues with reading? ("isn't" is not "is", and Keith's "[*theoretically*] unnecessary" is not "necessary".)


    If you try to extract any meaning, it is that any control flow can be expressed either with 'goto' or with 'recursive functions'.

    It's actually the other way round; you can specify functionality
    using Recursive Functions, only a subset of these functions can
    be expressed with simple loops by algorithmic transformations.[*]

    (Of course you *could* thus also take an approach the other way
    round, i.e. from an imperative 'while' to a recursive function,
    but yet, beyond your [wrong] suppositions, no one was suggesting
    that.)

    [...]

    (I snipped the irrelevant rest that you made up in your confusion
    of not knowing.)

    Janis

    [*] I had started to write a longer post to explain that in detail
    to you, though when I saw Keith's terse post I thought that should
    suffice. - Alas, no. So all I want to suggest is to read up things
    yourself. I'd suggest books from F.L.Bauer ("Algorithmic Language
    and Program Development", for example), or from H.Partsch on that
    topic; e.g. "Specification and Transformation of Programs".
    (You may come back after reading, in case you are still puzzled.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Tue Dec 17 18:29:37 2024
    On 17.12.2024 00:26, bart wrote:
    On 16/12/2024 20:39, Janis Papanagnou wrote:

    I wasn't commenting on any "IL",

    The subthread was about ILs.

    You obviously missed that I wasn't quoting anything else from this
    subthread but the one isolated statement I replied to (which also
    wasn't a part of a larger paragraph but standing alone on its own).

    (That's why I think it's good style to strip to the essentials one
    intends to reply to and don't assume (or refer) to any unspoken or
    unquoted parts of a thread; keep posts self-contained! YMMV. That
    will also keep potential confusions and misunderstandings small.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Thiago Adams on Tue Dec 17 18:37:47 2024
    On 17/12/2024 18:16, Thiago Adams wrote:


    also remove structs changing by unsigned char [] and cast parts of it to access members.

    I think this the lower level possible in c.

    This is what I do in my IL, where structs are just fixed blocks of so
    many bytes.

    But there are some things to consider:

    * A struct may still need alignment corresponding to the strictest
    alignment among the members. (Any padding between members and at the end
    should already be taken care of.)

    I use an alignment based on overall size, so a 40-byte struct is assumed
    to have an 64-bit max alignment, but it may only need 16-bit alignment.
    That is harmless, but it can be fixed with some extra metadata.

    With a C char[], you can choose to use a short[] array for example
    (obviously of half the length) to signal that it needs 16-bit alignment.


    * Some machine ABIs, like SYS V for 64 bits, may need to know the
    internal layout of structs when they are passed 'by value'.

    If reduced down to char[], this info will be missing.

    I ignore this because I only target Win64 ABI. It only comes up in SYS
    V, when calling functions across an FFI, and when the API uses value
    structs, which is uncommon. And also makes I can't make head or tail of
    the rules.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to bart on Tue Dec 17 18:46:00 2024
    bart <bc@freeuk.com> wrote:

    If you try to extract any meaning, it is that any control flow can be expressed either with 'goto' or with 'recursive functions'.

    This is what I picked up on. Who on earth would eschew 'goto' and use
    such a disproportionately more complex and inefficient method like
    recursive functions?

    Due to silly conding standard? Or in language that does not have
    'goto'.

    How would you even express an arbitrary goto from random point X in a function to random point Y, which may be inside differently nested
    blocks, via a recursive function?

    AFAICS in C main limitation is that you either pass all variables
    as parameters (ugly and verbose) or use only global variables
    (much worse than 'goto'). The following silly example shows
    that 'if' can be simulated using array of function pointers and
    indirect calls:

    static int bar(int a) {
    return a + 1;
    }

    static int baz(int a) {
    return 2*a;
    }

    int
    silly(int a) {
    int (*t[2])(int) = {bar, baz};
    return (*t[!!(a > 3)])(a);
    }

    If you compile it with 'gcc -S -O2' you can see that actually there
    are no function calls in generated code (but generated code is clearly
    crappy). However, needed optimication is really simple, so
    in principle any compiler could do better. OTOH code like
    this is rare in practice, so probably compiler writers did not
    bother.

    In similar way one can simulate dense C 'switch'.

    Main point is that function call at the end of say 'F' to function
    'G' which retruns in the same way as 'F' can be compiled to some
    stack shuffling + goto (this is called 'tail call optimization').

    IIUC at least some Scheme and ML compilers keep calls in intermediate
    level representation (both have no 'goto') and convert them to
    jumps only when emiting machine code.

    Similar thing was used by one disassembly system: it generated "high
    level code" by converting all jumps in machine code to function
    calls. Later the result was cleaned up by transformations, in
    particular recursion elimination.

    Of course, for orginal purpose of this thread replacing 'if' by
    indirect calls is useless

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Tue Dec 17 19:45:49 2024
    On 17/12/2024 19:40, Lawrence D'Oliveiro wrote:
    On Tue, 17 Dec 2024 12:04:29 +0000, bart wrote:

    Information about it is quite elusive ...

    Did you try the usual place for Web-related stuff?

    <https://developer.mozilla.org/en-US/docs/WebAssembly>

    That's all at the wrong level, eg:

    "When you've written code in C/C++, you can then compile it into Wasm
    using a tool like Emscripten"

    It's not aimed at people /implementing/ such a tool.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Thiago Adams on Tue Dec 17 19:42:51 2024
    On 17/12/2024 19:07, Thiago Adams wrote:
    Em 12/17/2024 3:37 PM, bart escreveu:
    On 17/12/2024 18:16, Thiago Adams wrote:


    also remove structs changing by unsigned char [] and cast parts of it
    to access members.

    I think this the lower level possible in c.

    This is what I do in my IL, where structs are just fixed blocks of so
    many bytes.


    How do you do with struct parameters?



    In the IL they are always passed notionally by value. This side of the
    IL (that is, the frontend compile that generates IL), knows nothing
    about the target, such as ABI details.

    (In practice, some things are known, like the word size of the target,
    since that can change characteristics of the source language, like the
    size of 'int' or of 'void*'. It also needs to assume, or request from
    the backend, argument evaluation order, although my IL can reverse order
    if necessary.)

    It is the backend, on the other size of the IL, that needs to deal with
    those details.

    That can include making copies of structs that the ABI says are passed
    by value. But when targeting SYS V ABI (which I haven't attempted yet),
    it may need to know the internal layout of a struct.

    You can however do experiments with using SYS V on Linux (must be 64 bits):

    * Create test structs with, say, int32 or int64 elements

    * Write a test function where such a struct is passed by value, and
    then return a modified copy

    * Rerun the test using a version of the function where a char[] version
    of the struct is passed and returned, and which contains the member
    access casts you suggested

    * See if it gives the same results.

    You might need a union of the two structs, or use memcpy to transfer
    contents, before and after calling the test function.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Tue Dec 17 19:40:53 2024
    On Tue, 17 Dec 2024 12:04:29 +0000, bart wrote:

    Information about it is quite elusive ...

    Did you try the usual place for Web-related stuff?

    <https://developer.mozilla.org/en-US/docs/WebAssembly>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Tue Dec 17 22:45:14 2024
    On 17/12/2024 18:46, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:

    If you try to extract any meaning, it is that any control flow can be
    expressed either with 'goto' or with 'recursive functions'.

    This is what I picked up on. Who on earth would eschew 'goto' and use
    such a disproportionately more complex and inefficient method like
    recursive functions?

    Due to silly conding standard? Or in language that does not have
    'goto'.

    It was suggested that 'theoretically', 'goto' could be replaced by
    recursive function calls.

    Whether still within the context of a language with no other control
    flow instructions, is not known. The suggester also chose not to share
    examples of how it would work.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Tue Dec 17 22:55:53 2024
    On 17/12/2024 22:25, Lawrence D'Oliveiro wrote:
    On Tue, 17 Dec 2024 19:45:49 +0000, bart wrote:

    On 17/12/2024 19:40, Lawrence D'Oliveiro wrote:

    On Tue, 17 Dec 2024 12:04:29 +0000, bart wrote:

    Information about it is quite elusive ...

    Did you try the usual place for Web-related stuff?

    <https://developer.mozilla.org/en-US/docs/WebAssembly>

    It's not aimed at people /implementing/ such a tool.

    It is aimed at those capable of following the links to relevant specs.

    It also a pretty terrible link. Trying to extract useful info a snippet
    at a time is like pulling teeth. Here I was merely after an example of
    WASM textual format.

    WASM is somewhat like LLVM in that there the docs are so extensive that
    they become impossible.

    Show me (I assume you know all about it) how to write Hello, World in
    WAT format, and what tool I need to download and use to run it. On Windows.

    I can do it with my IL in half a page.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Tue Dec 17 22:25:44 2024
    On Tue, 17 Dec 2024 19:45:49 +0000, bart wrote:

    On 17/12/2024 19:40, Lawrence D'Oliveiro wrote:

    On Tue, 17 Dec 2024 12:04:29 +0000, bart wrote:

    Information about it is quite elusive ...

    Did you try the usual place for Web-related stuff?

    <https://developer.mozilla.org/en-US/docs/WebAssembly>

    It's not aimed at people /implementing/ such a tool.

    It is aimed at those capable of following the links to relevant specs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to bart on Wed Dec 18 00:23:12 2024
    bart <bc@freeuk.com> wrote:
    On 17/12/2024 18:46, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:

    If you try to extract any meaning, it is that any control flow can be
    expressed either with 'goto' or with 'recursive functions'.

    This is what I picked up on. Who on earth would eschew 'goto' and use
    such a disproportionately more complex and inefficient method like
    recursive functions?

    Due to silly conding standard? Or in language that does not have
    'goto'.

    It was suggested that 'theoretically', 'goto' could be replaced by
    recursive function calls.

    Whether still within the context of a language with no other control
    flow instructions, is not known. The suggester also chose not to share examples of how it would work.

    The example I gave (and you snipped) was supposed to explain how
    the technique works, but it seems that it is not enough. So
    let us look at another example. Start from ordinary C code that
    only uses global variables (this is not strictly necessary, but
    let as make such assumption for simplicity):

    int n;
    int * a;
    int b;
    int i;

    ...
    /* Simple search loop */
    for(i = 0; i < n; i++) {
    if (a[i] == b) {
    break;
    }
    }

    First, express flow control using only conditional and unconditional
    jump:

    l0:
    i = 0;
    goto l3;
    l1:
    int c1 = a[i] == b;
    if (c1) {
    goto l4;
    } else {
    goto l2;
    }
    l2:
    i++;
    l3:
    int c2 = i < n;
    if (c2) {
    goto l1;
    } else {
    goto l4;
    }
    l4:
    ;

    Note, I introduced more jumps than strictly necessary, so that
    hunks between labels end either in conditional or unconditional
    jump.

    Next, replace each hunk staring in a label, up to (but not
    including) next label, by a new function. Replace final jumps
    by function calls, for conditional jumps using the same trick
    as in previous 'silly' example:

    int n;
    int * a;
    int b;
    int i;

    void l2(void);
    void l3(void);
    void l4(void);

    void l0(void) {
    i = 0;
    l3();
    }

    void l1(void) {
    void (*(t[2]))(void) = {l4, l2};
    int c1 = a[i] == b;
    (*(t[c1]))();
    }

    void l2(void) {
    i++;
    l3();
    }

    void l3(void) {
    void (*(t[]))(void) = {l1, l4};
    int c2 = i < n;
    (*(t[c2]))();
    }

    void l4(void) {
    }

    Note: 'l4' is different than other functions, intead of calling
    something it returns, ensuring that the sequence of calls
    eventually terminate.

    I hope that principles are clear now. If you compile this
    with gcc at -O2 you will see that there are no calls
    in generated code, only jumps. Slightly better code is
    generated by clang. Note that generated code uses stack
    only for final return.

    BTW: you can see that currently tcc do not support this
    coding style, that is code generated by tcc dully performs
    all calls leading possibly to stack overflow and to
    lower performance. Code generated by tcc from "jumpy"
    version looks slightly worse than code generated by
    clang from version using calls.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Waldek Hebisch on Wed Dec 18 01:24:42 2024
    On 18/12/2024 00:23, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:
    On 17/12/2024 18:46, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:

    If you try to extract any meaning, it is that any control flow can be
    expressed either with 'goto' or with 'recursive functions'.

    This is what I picked up on. Who on earth would eschew 'goto' and use
    such a disproportionately more complex and inefficient method like
    recursive functions?

    Due to silly conding standard? Or in language that does not have
    'goto'.

    It was suggested that 'theoretically', 'goto' could be replaced by
    recursive function calls.

    Whether still within the context of a language with no other control
    flow instructions, is not known. The suggester also chose not to share
    examples of how it would work.

    The example I gave (and you snipped) was supposed to explain how
    the technique works, but it seems that it is not enough.

    It showed how to do conditional code without explicit branching. It
    didn't seem to me to cover arbitrary gotos, or where recursion comes
    into it.

    (Actually I implemented it in my two languages to compare performance to 'straight' versions, however my test called silly() lots of times so it
    wasn't a good test.)

    So
    let us look at another example. Start from ordinary C code that
    only uses global variables (this is not strictly necessary, but
    let as make such assumption for simplicity):

    int n;
    int * a;
    int b;
    int i;

    ...
    /* Simple search loop */
    for(i = 0; i < n; i++) {
    if (a[i] == b) {
    break;
    }
    }

    First, express flow control using only conditional and unconditional
    jump:

    l0:
    i = 0;
    goto l3;
    l1:
    int c1 = a[i] == b;
    if (c1) {
    goto l4;
    } else {
    goto l2;
    }
    l2:
    i++;
    l3:
    int c2 = i < n;
    if (c2) {
    goto l1;
    } else {
    goto l4;
    }
    l4:
    ;

    Note, I introduced more jumps than strictly necessary, so that
    hunks between labels end either in conditional or unconditional
    jump.

    Next, replace each hunk staring in a label, up to (but not
    including) next label, by a new function. Replace final jumps
    by function calls, for conditional jumps using the same trick
    as in previous 'silly' example:

    int n;
    int * a;
    int b;
    int i;

    void l2(void);
    void l3(void);
    void l4(void);

    void l0(void) {
    i = 0;
    l3();
    }

    void l1(void) {
    void (*(t[2]))(void) = {l4, l2};
    int c1 = a[i] == b;
    (*(t[c1]))();
    }

    void l2(void) {
    i++;
    l3();
    }

    void l3(void) {
    void (*(t[]))(void) = {l1, l4};
    int c2 = i < n;
    (*(t[c2]))();
    }

    void l4(void) {
    }

    Note: 'l4' is different than other functions, intead of calling
    something it returns, ensuring that the sequence of calls
    eventually terminate.

    OK thanks for this. I tried to duplicate it based on this starting point:

    #include <stdio.h>

    int n=6;
    int a[]={10,20,30,40,50,60};
    int b=30;
    int i;

    int main(void) {
    for(i = 0; i < n; i++) {
    printf("%d\n",a[i]);
    if (a[i] == b) {
    break;
    }
    }
    }

    This prints 10 20 30 as it is. But the version with the function calls
    showed only '10'. If I swapped '{l1, l4}' in l3(), then I got '10 10 20'.

    I didn't spend too long to debug it further. I will take your word that
    this works. (I tried 3 compilers all with the same results, including TCC.)

    I don't fully understand it; what I got was that you first produce
    linear code with labels. Each span between labels is turned into a
    function. To 'step into' label L, or jump to L, I have to do L().

    There would still be lots of questions (even ignoring the problems of
    accessing locals), like what the return path is, or how an early return
    would work (also returning a value). Or what kind of pressure the stack
    would be under.

    It looks like a crude form of threaded code (which, when I use that,
    never returns, and it doesn't use a stack either).

    I've seen enough to know that it would be last kind of IL I would choose (unless it was the last IL left in the world - then maybe).

    There is also the oddity that eliminating a simple kind of branching
    relies on more elaborate branching: call and return mechanisms.

    More interesting and more practical would be replacing call/return by
    'goto'! (It would need to support label pointers or indirect jumps,
    unless runtime code modification was allowed.)


    (my test)
    --------------------------
    #include <stdio.h>

    int n=6;
    int a[]={10,20,30,40,50,60};
    int b=30;
    int i;

    void k2(void);
    void k3(void);
    void k4(void);

    void k0(void) {
    i = 0;
    k3();
    }

    void k1(void) {
    void (*(t[2]))(void) = {k4, k2};
    printf("%d\n",a[i]);
    int c1 = a[i] == b;
    (*(t[c1]))();
    }

    void k2(void) {
    i++;
    // k3();
    }

    void k3(void) {
    void (*(t[]))(void) = {k4, k1};
    int c2 = i < n;
    (*(t[c2]))();
    }

    void k4(void) {
    }

    int main(void) {
    k0();
    k1();
    k2();
    k3();
    k4();
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to bart on Wed Dec 18 03:51:17 2024
    bart <bc@freeuk.com> wrote:
    On 18/12/2024 00:23, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:
    On 17/12/2024 18:46, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:

    If you try to extract any meaning, it is that any control flow can be >>>>> expressed either with 'goto' or with 'recursive functions'.

    This is what I picked up on. Who on earth would eschew 'goto' and use >>>>> such a disproportionately more complex and inefficient method like
    recursive functions?

    Due to silly conding standard? Or in language that does not have
    'goto'.

    It was suggested that 'theoretically', 'goto' could be replaced by
    recursive function calls.

    Whether still within the context of a language with no other control
    flow instructions, is not known. The suggester also chose not to share
    examples of how it would work.

    The example I gave (and you snipped) was supposed to explain how
    the technique works, but it seems that it is not enough.

    It showed how to do conditional code without explicit branching. It
    didn't seem to me to cover arbitrary gotos, or where recursion comes
    into it.

    (Actually I implemented it in my two languages to compare performance to 'straight' versions, however my test called silly() lots of times so it wasn't a good test.)

    So
    let us look at another example. Start from ordinary C code that
    only uses global variables (this is not strictly necessary, but
    let as make such assumption for simplicity):

    int n;
    int * a;
    int b;
    int i;

    ...
    /* Simple search loop */
    for(i = 0; i < n; i++) {
    if (a[i] == b) {
    break;
    }
    }

    First, express flow control using only conditional and unconditional
    jump:

    l0:
    i = 0;
    goto l3;
    l1:
    int c1 = a[i] == b;
    if (c1) {
    goto l4;
    } else {
    goto l2;
    }
    l2:
    i++;
    l3:
    int c2 = i < n;
    if (c2) {
    goto l1;
    } else {
    goto l4;
    }
    l4:
    ;

    Note, I introduced more jumps than strictly necessary, so that
    hunks between labels end either in conditional or unconditional
    jump.

    Next, replace each hunk staring in a label, up to (but not
    including) next label, by a new function. Replace final jumps
    by function calls, for conditional jumps using the same trick
    as in previous 'silly' example:

    int n;
    int * a;
    int b;
    int i;

    void l2(void);
    void l3(void);
    void l4(void);

    void l0(void) {
    i = 0;
    l3();
    }

    void l1(void) {
    void (*(t[2]))(void) = {l4, l2};
    ^^^^^^^
    Should be
    l2, l4
    int c1 = a[i] == b;
    (*(t[c1]))();
    }

    void l2(void) {
    i++;
    l3();
    }

    void l3(void) {
    void (*(t[]))(void) = {l1, l4};
    ^^^^^^
    l4, l2
    int c2 = i < n;
    (*(t[c2]))();
    }

    void l4(void) {
    }

    Note: 'l4' is different than other functions, intead of calling
    something it returns, ensuring that the sequence of calls
    eventually terminate.

    OK thanks for this. I tried to duplicate it based on this starting point:

    #include <stdio.h>

    int n=6;
    int a[]={10,20,30,40,50,60};
    int b=30;
    int i;

    int main(void) {
    for(i = 0; i < n; i++) {
    printf("%d\n",a[i]);
    if (a[i] == b) {
    break;
    }
    }
    }

    This prints 10 20 30 as it is. But the version with the function calls
    showed only '10'. If I swapped '{l1, l4}' in l3(), then I got '10 10 20'.

    Sorry, there was a thinko: 1 is true and this is the second element
    of the array, while I was thinking that the first one is true branch
    and second is false branch.

    I didn't spend too long to debug it further. I will take your word that
    this works. (I tried 3 compilers all with the same results, including TCC.)

    I don't fully understand it; what I got was that you first produce
    linear code with labels. Each span between labels is turned into a
    function. To 'step into' label L, or jump to L, I have to do L().

    Yes.

    There would still be lots of questions (even ignoring the problems of accessing locals), like what the return path is, or how an early return
    would work (also returning a value). Or what kind of pressure the stack
    would be under.

    OK, you take a function F, it has some arguments and local variables.
    And some retrun type. You create "entry function" to take the
    same arguments as F and has the same return type as F. You tranform
    body as above, but now each new function has the same return type
    as F and arguments are arguments of original function + extra arguments,
    one for each local variable of F. In "entry function" you call
    function corresponding to first label passing it arguments and
    initial values of local variables of F. In each subseqent call
    you pass argument and values around so that they are available
    in each new function. And the call is an argument to return
    statement. When you want to return you simply return value,
    without performing a call.

    Stack use depend on optimizations in your compiler. With small
    effort compiler can recognize that it will return value (possibly
    void) from a call and replace such call by stack+register
    shuffling + jump. Actually when there is return value, you
    have something like

    return lx(a0, a1, ..., ak);

    which is easy to recognize due to 'return' keyword. One also
    need to check that types agree (C automatically applies integer
    convertions, but such convertions may produce real code, so in
    such case one needs normal call). In void case one need to
    check that there the call is textually last thing or that
    it is followed by return statement. Stack+register
    shuffling may require some code before control transfer, but
    call can be replaced by jump.

    So, if compiler has tail call optimization, then there is no
    more stack use than maximum needed by any of the functions.

    Note: I described general transformation, partially to show
    that 'if' is _not_ needed. But similar style is used to
    write code by hand. In hand written code people do not
    bother with transforming 'if', which makes tail call
    optimization a bit more complicated. OTOH, unlike rather
    ugly code produced by mechanical transformation, hand
    written code depending on tail call optimization may be quite
    nice and readible. There is potential trouble: sometimes
    author thinks that a call is a tail call, but compiler
    disagrees, leading to lower efficiency.

    Of course, when compiler do not have tail call optimization,
    then stack use may be quite high.

    It looks like a crude form of threaded code (which, when I use that,
    never returns, and it doesn't use a stack either).

    IMO it is quite different than what I know as threaded code.

    I've seen enough to know that it would be last kind of IL I would choose (unless it was the last IL left in the world - then maybe).

    There is also the oddity that eliminating a simple kind of branching
    relies on more elaborate branching: call and return mechanisms.

    One motivation for eliminating 'goto' is that it is not easy to
    say what effect 'goto' has on variables. I mean, variables keep
    ther values, but when you may arrive to given point from several
    places than values of variables depend on place that control came
    from, and this may be hard to analyze. In a sense functions have
    the same problem, but there is well-developed technique to reason
    about function calls. So both jumps and function calls are
    hard to analyze, but eliminating jumps allows re-use of work
    done for functions.

    More interesting and more practical would be replacing call/return by
    'goto'! (It would need to support label pointers or indirect jumps,
    unless runtime code modification was allowed.)

    The point is that calls are strictly more powerful than jumps
    (you get parameter passing and local variables).

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Wed Dec 18 05:55:31 2024
    On Tue, 17 Dec 2024 22:55:53 +0000, bart wrote:

    On 17/12/2024 22:25, Lawrence D'Oliveiro wrote:

    On Tue, 17 Dec 2024 19:45:49 +0000, bart wrote:

    It's not aimed at people /implementing/ such a tool.

    It is aimed at those capable of following the links to relevant specs.

    It also a pretty terrible link.

    Did you see this link <https://developer.mozilla.org/en-US/docs/WebAssembly/Reference>? Lots of examples from there.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to BGB on Wed Dec 18 12:08:24 2024
    On 17/12/2024 18:51, BGB wrote:
    On 12/17/2024 6:04 AM, bart wrote:

    C can apparently compile to WASM via Clang, so I tried this program:

      void F(void) {
         int i=0;
         while (i<10000) ++i;
      }

    which compiled to 128 lines of WASM (technically, some form of 'WAT',
    as WASM is a binary format). The 60 lines correspondoing to F are
    shown below, and below that, is my own stack IL code.

    I'm not even sure what format that code is in, as WAT is supposed to use S-expressions. The generated code is flat. It differs in other ways from examples of WAT.

    Hmm... It looks like the WASM example is already trying to follow SSA
    rules, then mapped to a stack IL... Not necessarily the best way to do
    it IMO.

    I hadn't considered that SSA could be represented in stack form.

    But couldn't each push be converted to an assignment to a fresh
    variable, and the same with pop?

    As for Phi functions, the only similar thing I encounter (but could be mistaken), is when there is a choice of paths to yield a value (such as
    (c ? a : b) in C; my language has several such constructs).

    With stack code, the result conveniently ends up on top of the stack
    whichever path is taken, which is a big advantage. Unless you then have
    to convert that to register code, and need to ensure the values end up
    in the same register when the control paths join up again.


    But, yeah, in BGBCC I am also using a stack-based IL (RIL), which
    follows rules more in a similar category to .NET CIL (in that, stack
    items carry type, and the stack is generally fully emptied on branch).


    In my IL, labels are identified with a LABEL opcode (with an immediate),
    and things like branches work by having the branch target and label
    having the same immediate (label ID).

    So, you jump to label L123, and the label looks like:

    L123:

    I think that is pretty standard! But it sounds like you use a very tight encoding for bytecode, while mine uses a 32-byte descriptor for each IL instruction.

    (One quibble with labels is whether a label definition occupies an
    actual IL instruction. With my IL used as a backend for static
    languages, it does. And there can be clusters of labels at the same spot.

    With dynamic bytecode designed for interpretation, it doesn't. It uses a different structure. This means labels don't need to be 'executed' when encountered.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Wed Dec 18 17:19:01 2024
    On 17.12.2024 21:13, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    [...]

    [...]
    (Janis, please correct me if I'm mistaken.)

    I think it couldn't have been explained clearer. - Thanks.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Waldek Hebisch on Wed Dec 18 17:26:49 2024
    On 17.12.2024 19:46, Waldek Hebisch wrote:
    bart <bc@freeuk.com> wrote:
    [...]

    [ ponderings about where recursive functions might be used ]

    Due to silly conding standard? Or in language that does not have
    'goto'.

    (I'd rule out the "coding standards" hypothesis.)

    Languages without 'goto', I suppose, would either have other control
    constructs ('while', etc.) to formulate in an imperative style, or
    be of the Functional Programming Languages type.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to BGB on Wed Dec 18 23:37:11 2024
    On 18/12/2024 18:50, BGB wrote:
    On 12/18/2024 6:08 AM, bart wrote:

    With stack code, the result conveniently ends up on top of the stack
    whichever path is taken, which is a big advantage. Unless you then
    have to convert that to register code, and need to ensure the values
    end up in the same register when the control paths join up again.


    With JVM, the rule was that all paths landing at the same label need to
    have the same stack depth and same types.

    With .NET, the rule was that the stack was always empty, any merging
    would need to be done using variables.


    BGBCC is sorta mixed:
    In most cases, it follows the .NET rule;
    A special-case exception exists mostly for implementing the ?: operation (which in turn has special stack operations to signal its use).

    BEGINU  // start a ?: operator
    L0:
    ...  //one case
    SETU
    JMP L2
    L1:
    ... //other case
    SETU
    JMP L2
    ENDU
    L2:


    This is a bit of wonk,

    Well, this is pretty much what I do in stack code. I consider it impure,
    as in needing artificial hints, but also the simplest solution.

    I use opcodes STARTMX, RESETMX, ENDMX. They are no-ops when the IL is interpreted. But during the linear scan needed during code generation,
    where it has to keep track of the IL's operand stack, RESETMX will reset
    the stack too.

    (As mentioned, I have a lot more constructs that can yield N values not
    just two. Apart from N-way select, if-else, switch-when and case-when statements can also return values.)

    if I were designing it now, would likely do it
    the same as .NET, and use temporary variables.

    In 3AC then it's easy, all paths write to the same temporary.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Thu Dec 19 00:32:47 2024
    On 18/12/2024 05:55, Lawrence D'Oliveiro wrote:
    On Tue, 17 Dec 2024 22:55:53 +0000, bart wrote:

    On 17/12/2024 22:25, Lawrence D'Oliveiro wrote:

    On Tue, 17 Dec 2024 19:45:49 +0000, bart wrote:

    It's not aimed at people /implementing/ such a tool.

    It is aimed at those capable of following the links to relevant specs.

    It also a pretty terrible link.

    Did you see this link <https://developer.mozilla.org/en-US/docs/WebAssembly/Reference>? Lots of examples from there.

    I promised a example of Hello World using my IL, and how to process and
    run it, in half a page. This is it for Windows :

    ------------------------------------
    Paste the indented code into a file hello.pcl:

    addlib "msvcrt"
    extproc puts

    proc main:::
    setcall i32 /1
    load u64 "Hello World!"
    setarg u64 /1
    callf i32 /1 &puts
    unload i32
    load i32 0
    stop
    retproc
    endproc

    Download the pc.exe file here: https://github.com/sal55/langs/blob/master/pc.exe, which is a 65KB file (UPX-compressed from 180KB). (Advice to navigate AV not included here.)

    At a command prompt with both files present, type:

    pc -r hello

    This will convert it to x64 code and run it. Use 'pc' by itself to see
    the 6 other processing options.
    ------------------------------------

    So 20 non-blank lines. It would be nice if an equally simple example
    existed for WASM/WAT, or if people who suggested that choice could post
    a link to such an example /that/ works on Windows.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to BGB on Thu Dec 19 00:35:41 2024
    On 19/12/2024 00:27, BGB wrote:
    On 12/18/2024 1:43 PM, Thiago Adams wrote:
    Em 12/18/2024 3:51 PM, BGB escreveu:

    I took a different approach:
    In the backend IR stage, structs are essentially treated as
    references to the structure.

    A local structure may be "initialized" via an IR operation, in which
    point it will be assigned storage in the stack frame, and the
    reference will be initialized to the storage area for the structure.

    Most operations will pass them by reference.

    Assigning a struct will essentially be turned into a struct-copy
    operation (using the same mechanism as inline memcpy).

    But what happens with calling a external C function that has a struct
    X as parameter? (not pointer to struct)


    In my ABI, if larger than 16 bytes, it is passed by reference (as a
    pointer in a register or on the stack), callee is responsible for
    copying it somewhere else if needed.

    For struct return, a pointer to return the struct into is provided by
    the caller, and the callee copies the returned struct into this address.

    If the caller ignores the return value, the caller provides a dummy
    buffer for the return value.

    If no prototype is provided... well, most likely the program crashes or similar.

    So, in effect, the by-value semantics are mostly faked by the compiler.


    It is roughly similar to the handling of C array types, which in this
    case are also seen as a combination of a hidden pointer to the data, and
    the backing data (the array's contents). The code-generator mostly
    operates in terms of this hidden pointer.


    By-Value Structs smaller than 16 bytes are passed as-if they were a 64
    or 128 bit integer type (as a single register or as a register pair,
    with a layout matching their in-memory representation).

    ...


    But, yeah, at the IL level, one could potentially eliminate structs and arrays as a separate construct, and instead have bare pointers and a
    generic "reserve a blob of bytes in the frame and initialize this
    pointer to point to it" operator (with the business end of this operator happening in the function prolog).

    The problem with this, that I mentioned elsewhere, is how well it would
    work with SYS V ABI, since the rules for structs are complex, and
    apparently recursive.

    Having just a block of bytes might not be enough.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to BGB on Thu Dec 19 11:27:03 2024
    On 19/12/2024 05:46, BGB wrote:
    On 12/18/2024 6:35 PM, bart wrote:
    On 19/12/2024 00:27, BGB wrote:

    By-Value Structs smaller than 16 bytes are passed as-if they were a
    64 or 128 bit integer type (as a single register or as a register
    pair, with a layout matching their in-memory representation).

    ...


    But, yeah, at the IL level, one could potentially eliminate structs
    and arrays as a separate construct, and instead have bare pointers
    and a generic "reserve a blob of bytes in the frame and initialize
    this pointer to point to it" operator (with the business end of this
    operator happening in the function prolog).

    The problem with this, that I mentioned elsewhere, is how well it
    would work with SYS V ABI, since the rules for structs are complex,
    and apparently recursive.

    Having just a block of bytes might not be enough.

    In my case, I am not bothering with the SysV style ABI's (well, along
    with there not being any x86 or x86-64 target...).

    I'd imagine it's worse with ARM targets as there are so many more
    registers to try and deconstruct structs into.


    For my ISA, it is a custom ABI, but follows mostly similar rules to some
    of the other "Microsoft style" ABIs (where, I have noted that across
    multiple targets, MS tools have tended to use similar ABI designs).

    When you do your own thing, it's easy.

    In the 1980s, I didn't need to worry about call conventions used for
    other software, since there /was/ no other software! I had to write
    everything, save for the odd calls to DOS which used some form of SYSCALL.

    Then, arrays and structs were actually passed and returned by value (not
    via hidden references), by copying the data to and from the stack.

    However, I don't recall ever using the feature, as I considered it
    efficient. I always used explicit references in my code.

    For my compiler targeting RISC-V, it uses a variation of RV's ABI rules. Argument passing is basically similar, but struct pass/return is
    different; and it passes floating-point values in GPRs (and, in my own
    ISA, all floating-point values use GPRs, as there are no FPU registers; though FPU registers do exist for RISC-V).

    Supporting C's variadic functions, which is needed for many languages
    when calling C across an FFI, usually requires different rules. On Win64
    ABI for example, by passing low variadic arguments in both GPRs and FPU registers.

    /Implementing/ variadic functions (which only occurs if implementing C)
    is another headache if it has to work with the ABI (which can be assumed
    for a non-static function).

    I barely have a working solution for Win64 ABI, which needs to be done
    via stdarg.h, but wouldn't have a clue how to do it for SYS V.

    (Even Win64 has problems, as it assumes a downward-growing stack; in my
    IL interpreter, the stack grows upwards!)

    Not likely a huge issue as one is unlikely to use ELF and PE/COFF in the
    same program.


    For the "OS" that runs on my CPU core, it is natively using PE/COFF, but

    That's interesting: you deliberately used one of the most complex file
    formats around, when you could have devised your own?

    I did exactly that at a period when my generated DLLs were buggy for
    some reason (it turned out to be two reasons). I created a simple
    dynamic library format of my own. Then I found the same format worked
    also for executables.

    But I needed a loader program to run them, as Windows obviously didn't understand the format. Such a program can be written in 800 lines of C,
    and can dynamically libraries in both my format, and proper DLLs (not
    the buggy ones I generated!).

    A hello-world program is under 300 bytes compared with 2 or
    2.5KB of EXE. And the format is portable to Linux, so no need to
    generate ELF (but I haven't tried). Plus the format might be transparent
    to AV software (haven't tried that either).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Janis Papanagnou on Fri Dec 20 17:28:29 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to BGB on Sat Dec 21 05:34:07 2024
    On Tue, 17 Dec 2024 13:07:44 -0600, BGB wrote:

    Every variable may only be assigned once ...

    Note this only applies to registers.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Tim Rentsch on Sat Dec 21 21:31:24 2024
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    (Unless you just wanted to say that in some HLL abstraction like
    'printf("Hello world!\n")' there's no [visible] conditional branch.
    Likewise in a 'ClearAccumulator' machine instruction, or the like.)

    The comparisons and predicates are one key function (not any specific
    branch construct, whether on HLL level, assembler level, or with the (elementary but most powerful) Turing Machine). Comparisons inherently
    result in predicates which is what controls program execution).

    So your statement asks for some explanation at least.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Janis Papanagnou on Sat Dec 21 13:51:27 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    (Unless you just wanted to say that in some HLL abstraction like 'printf("Hello world!\n")' there's no [visible] conditional branch.
    Likewise in a 'ClearAccumulator' machine instruction, or the like.)

    The comparisons and predicates are one key function (not any specific
    branch construct, whether on HLL level, assembler level, or with the (elementary but most powerful) Turing Machine). Comparisons inherently result in predicates which is what controls program execution).

    So your statement asks for some explanation at least.

    Start with C - any of C90, C99, C11.

    Take away the short-circuiting operators - &&, ||, ?:.

    Take away all statement types that involve intra-function transfer
    of control: goto, break, continue, if, for, while, switch, do/while.
    Might as well take away statement labels too.

    Take away setjmp and longjmp.

    Rule out programs with undefined behavior.

    The language that is left is still Turing complete.

    Proof: exercise for the reader.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Sun Dec 22 00:20:32 2024
    On Sat, 21 Dec 2024 21:31:24 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    So your statement asks for some explanation at least.

    Janis


    I would guess that Tim worked as CS professor for several dozens years.
    And it shows.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Sun Dec 22 01:13:07 2024
    On 21.12.2024 23:20, Michael S wrote:
    On Sat, 21 Dec 2024 21:31:24 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    So your statement asks for some explanation at least.

    I would guess that Tim worked as CS professor for several dozens years.
    And it shows.

    Ranks and titles are, per se, no guarantee. I'm not impressed; I've
    seen all sorts/qualities of professors. YMMV.

    If that is true (that he was one) I'm wondering why we observe so
    often that he posts statements here and doesn't care to explain it.
    At least the many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Sun Dec 22 02:18:51 2024
    On Sun, 22 Dec 2024 01:13:07 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 23:20, Michael S wrote:
    On Sat, 21 Dec 2024 21:31:24 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    So your statement asks for some explanation at least.

    I would guess that Tim worked as CS professor for several dozens
    years. And it shows.

    Ranks and titles are, per se, no guarantee. I'm not impressed; I've
    seen all sorts/qualities of professors. YMMV.

    If that is true (that he was one) I'm wondering why we observe so
    often that he posts statements here and doesn't care to explain it.
    At least the many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him).

    Janis


    It seems, you didn't understand me. (Ogh, it is contagious ;-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Sun Dec 22 01:39:49 2024
    On 22.12.2024 01:18, Michael S wrote:
    On Sun, 22 Dec 2024 01:13:07 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 23:20, Michael S wrote:
    On Sat, 21 Dec 2024 21:31:24 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    So your statement asks for some explanation at least.

    I would guess that Tim worked as CS professor for several dozens
    years. And it shows.

    Ranks and titles are, per se, no guarantee. I'm not impressed; I've
    seen all sorts/qualities of professors. YMMV.

    If that is true (that he was one) I'm wondering why we observe so
    often that he posts statements here and doesn't care to explain it.
    At least the many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him).

    It seems, you didn't understand me. (Ogh, it is contagious ;-)

    I'm sorry, no. - I certainly took it literally - as I do (at first)
    with most people and their statements (until I get to know better).

    If it was meant sarcastically or anything, I'd appreciate a smiley
    or something like that. (It certainly wasn't obvious to me.)

    If it was meant serious and I completely missed the point - which
    may also happen occasionally - I'd appreciate a pointer.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Tim Rentsch on Sun Dec 22 01:22:01 2024
    On 21.12.2024 22:51, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    (Unless you just wanted to say that in some HLL abstraction like
    'printf("Hello world!\n")' there's no [visible] conditional branch.
    Likewise in a 'ClearAccumulator' machine instruction, or the like.)

    The comparisons and predicates are one key function (not any specific
    branch construct, whether on HLL level, assembler level, or with the
    (elementary but most powerful) Turing Machine). Comparisons inherently
    result in predicates which is what controls program execution).

    So your statement asks for some explanation at least.

    Start with C - any of C90, C99, C11.

    Take away the short-circuiting operators - &&, ||, ?:.

    Take away all statement types that involve intra-function transfer
    of control: goto, break, continue, if, for, while, switch, do/while.
    Might as well take away statement labels too.

    Take away setjmp and longjmp.

    And also things like the above mentioned 'printf()' that most certainly
    implies an iteration over the format string checking for it's '\0'-end.
    And so on, and so on. - What will be left as "language".

    Would you be able to formulate functionality of the class of Recursive Functions (languages class of a Turing Machine with Chomsky-0 grammar).


    Rule out programs with undefined behavior.

    The language that is left is still Turing complete.

    Is it? - But wouldn't that be just the argument I mentioned above; that
    a, say, 'ClearAccumulator' machine statement wouldn't contain any jump?

    Proof: exercise for the reader.

    (Typical sort of your reply.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Sun Dec 22 03:04:51 2024
    On Sun, 22 Dec 2024 01:39:49 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 22.12.2024 01:18, Michael S wrote:
    On Sun, 22 Dec 2024 01:13:07 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 23:20, Michael S wrote:
    On Sat, 21 Dec 2024 21:31:24 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    So your statement asks for some explanation at least.

    I would guess that Tim worked as CS professor for several dozens
    years. And it shows.

    Ranks and titles are, per se, no guarantee. I'm not impressed; I've
    seen all sorts/qualities of professors. YMMV.

    If that is true (that he was one) I'm wondering why we observe so
    often that he posts statements here and doesn't care to explain it.
    At least the many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him).

    It seems, you didn't understand me. (Ogh, it is contagious ;-)

    I'm sorry, no. - I certainly took it literally - as I do (at first)
    with most people and their statements (until I get to know better).

    If it was meant sarcastically or anything, I'd appreciate a smiley
    or something like that. (It certainly wasn't obvious to me.)

    If it was meant serious and I completely missed the point - which
    may also happen occasionally - I'd appreciate a pointer.

    Janis



    Part of the answer is in your previous response.
    You wrote: "many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him)". You essentially admitted that not all good professors behave like that.

    There is more than one school of teaching. One school believes that
    students learn from explanations and exercises. Other school believes
    that students learn best when provided with bare basics and then asked
    to figure out the rest by themselves. There is also the third school
    that believes that student don't really learn anything before they try
    to explain it to somebody else.

    You make an impression of one that received basics of CS. Probably, 40
    or so years ago, but still you have to know basic facts. Unlike me, for example.
    So, Tim expects that you will be able to utilizes his hints. And that
    it would lead to much better understanding on your part then if he
    feeds you by teaspoon.
    That is one part. Another part is that he is annoyed by your tone.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Sun Dec 22 03:06:54 2024
    On 22.12.2024 02:04, Michael S wrote:
    [...]

    Part of the answer is in your previous response.
    You wrote: "many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him)". You essentially admitted that not all good professors behave like that.

    Oh, what I meant to express was different; that good professors
    *would* explain it (only bad ones wouldn't).

    (At least that was my experience; and not only covering the CS
    domain, BTW.)

    [ "schools of teaching" stuff snipped ]

    You make an impression of one that received basics of CS. Probably, 40
    or so years ago, but still you have to know basic facts. Unlike me, for example.
    So, Tim expects that you will be able to utilizes his hints.

    The point [repeatedly] stated (also by others here) was that
    he more often than not just provides no information but simple
    arbitrary statements of opinion.

    *Especially* if folks here that are discussing CS stuff have 40
    or 50 years experience, as you say, with academical and practical
    background one would think that a non-substantial "kindergarten"
    statement is then effectively just an offense (or likely part of
    a arrogant [professorial?] behavior).

    And that
    it would lead to much better understanding on your part then if he
    feeds you by teaspoon.

    Which he doesn't do.

    Moreover, given that many of the folks here obviously *do* have
    a solid background (or at least years long IT or CS experiences)
    should, IMO, be a motivation to try to explain any arguable point
    if one really cares about the topic. (Unless some habit, maybe of
    being an inerrant authority, prevents one from such.)

    Myself I'm at least trying to explain knowledges and backup by
    experiences, not just throw short phrases into the pool.

    That is one part. Another part is that he is annoyed by your tone.

    (And I'm annoyed by his. But, anyway, his posting tone is that
    same in most of his responses to folks here, not just to me.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Michael S on Sat Dec 21 22:17:20 2024
    On 12/21/24 20:04, Michael S wrote:
    ...
    There is more than one school of teaching. One school believes that
    students learn from explanations and exercises. Other school believes
    that students learn best when provided with bare basics and then asked
    to figure out the rest by themselves.

    I personally believe that Tim generally thinks there's a justification
    for what he says, and that we'd be better off figuring it out ourselves.
    I also know, from the rare occasions when he's been convinced to provide
    his justification, that I often don't consider his justification valid. However, he says things that seem to be unjustified so often, I can't
    help wondering if he doesn't occasionally say things he realizes are unjustified (either at the time, or as the result of subsequent
    discussion), and withholds his justifications in order to hide the fact
    that he knows he was wrong. Probably not, but I keep wondering.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Janis Papanagnou on Sun Dec 22 06:01:52 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    Or try to figure out how to do this knowing that C has function
    pointers.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Waldek Hebisch on Sun Dec 22 11:22:51 2024
    On Sun, 22 Dec 2024 06:01:52 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via
    goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    Considering that Janis replied to your post I find a possibility that
    he did not look at it unlikely. Although not completely impossible.


    Or try to figure out how to do this knowing that C has function
    pointers.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Michael S on Sun Dec 22 11:35:53 2024
    On 22/12/2024 09:22, Michael S wrote:
    On Sun, 22 Dec 2024 06:01:52 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via
    goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    Considering that Janis replied to your post I find a possibility that
    he did not look at it unlikely. Although not completely impossible.

    He only replied to the first remark. And summarised the rest with:

    "[ ponderings about where recursive functions might be used ]"

    (18-Dec, 16:26 GMT)

    I don't think JP does details, and I've struggled to find posts where he
    writes actual code. His replies to mine have mostly been about trying to
    beat me over the head.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Janis Papanagnou on Sun Dec 22 14:19:13 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    I don't want to speak for Tim, but as far as I am concerned, it all
    boils down to what you take to be a model of (effective) computation.
    In some purely theoretical sense, models like the pure lambda calculus
    and combinator calculus are "complete" and they have no specific
    conditional "branches".

    Going into detail (such as examples of making a "choice" in pure lambda calculus) are way off topic here.

    This is exactly what comp.theory should be used for, so I will cross
    post there and set the followup-to header. comp.theory has been trashed
    by cranks but maybe a topical post will help it a but.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Ben Bacarisse on Sun Dec 22 15:30:30 2024
    Ben Bacarisse <ben@bsb.me.uk> writes:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    I don't want to speak for Tim, but as far as I am concerned, it all
    boils down to what you take to be a model of (effective) computation.
    In some purely theoretical sense, models like the pure lambda calculus
    and combinator calculus are "complete" and they have no specific
    conditional "branches".

    Going into detail (such as examples of making a "choice" in pure lambda calculus) are way off topic here.

    This is exactly what comp.theory should be used for, so I will cross
    post there and set the followup-to header. comp.theory has been trashed
    by cranks but maybe a topical post will help it a but.

    I see from a post I had not read before replying that Tim's point was
    very much focused on C. Given that theory is off topic here (and
    comp.theory is a mess) there is probably no point in trying to
    discussing the more general point.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Waldek Hebisch on Sun Dec 22 10:38:11 2024
    antispam@fricas.org (Waldek Hebisch) writes:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts [...]

    What makes you think I didn't?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to James Kuyper on Sun Dec 22 19:51:13 2024
    On 22.12.2024 04:17, James Kuyper wrote:
    On 12/21/24 20:04, Michael S wrote:
    ...
    There is more than one school of teaching. One school believes that
    students learn from explanations and exercises. Other school believes
    that students learn best when provided with bare basics and then asked
    to figure out the rest by themselves.

    In context of this newsgroup where my impression is that there's a lot
    of years long IT/CS experienced and quite old people discussing topics
    the explanatory "model" of "schools of teaching" is anyway completely inappropriate; there's not "one _teacher_ [who knows almost all]" and
    "all the rest are [ignorant] _pupils_" that need to be "guided" (in
    one way or the other). Not saying anything substantial on a topic can
    certainly be perceived as some rhetorical move but it's surely not any
    sort of teaching-didactics [of whatever "school of teaching"]).


    I personally believe that Tim generally thinks there's a justification
    for what he says, and that we'd be better off figuring it out ourselves.

    (My impression is that he often says something on a topic where he has
    no deeper knowledge, but is pretending to know by not saying anything substantial.)

    I also know, from the rare occasions when he's been convinced to provide
    his justification, that I often don't consider his justification valid. However, he says things that seem to be unjustified so often, I can't
    help wondering if he doesn't occasionally say things he realizes are unjustified (either at the time, or as the result of subsequent
    discussion), and withholds his justifications in order to hide the fact
    that he knows he was wrong. Probably not, but I keep wondering.

    (This matches with my observations and I drew a similar conclusion.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Tim Rentsch on Sun Dec 22 19:44:49 2024
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    antispam@fricas.org (Waldek Hebisch) writes:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto. >>>>>
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts [...]

    What makes you think I didn't?

    I made the same claim as you earlier and gave examples. You
    did not acknowledge my posts. Why? For me most natural
    explanation is that you did not read them.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Waldek Hebisch on Sun Dec 22 20:41:44 2024
    On 22.12.2024 07:01, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    I'm not sure but may have just skimmed over your "C" example if it
    wasn't of interest to the point I tried to make (at that stage).

    Or try to figure out how to do this knowing that C has function
    pointers.

    I will retry to explain what I tried to say... - very simply put...

    There's "Recursive Functions" and the Turing Machines "equivalent".
    The "Recursive Functions" is the most powerful class of algorithms.
    Formal Recursive Functions are formally defined in terms of abstract mathematical formulated properties; one of these [three properties]
    are the "Test Sets". (Here I can already stop.)

    But since we're not in a theoretical CS newsgroup I'd just wanted
    to see an example of some common, say, mathematical function and
    see it implemented without 'if' and 'goto' or recursion. - Take a
    simple one, say, fac(n) = n! , the factorial function. I know how
    I can implement that with 'if' and recursion, and I know how I can
    implement that with 'while' (or 'goto').

    If I re-inspect your example upthread - I hope it was the one you
    wanted to refer to - I see that you have removed the 'if' symbol
    but not the conditional, the test function; there's still the
    predicate (the "Test Set") present in form of 'int c2 = i < n',
    and it's there in the original code, in the goto transformed code,
    and in the function-pointer code. And you cannot get rid of that.

    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Janis Papanagnou on Sun Dec 22 21:45:14 2024
    On 2024-12-21, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    In a functional langauge, we can make a decision by, for instance,
    putting two lambdas into an array A, and then calling A[0] or A[1],
    where the index 0 or 1 is comes from some Boolean result.

    The only reason we have a control construct like if(A, X, Y) where X
    is only evaluated if A is true, otherwise Y, is that X and Y
    have side effects.

    If X and Y don't have side effects, then if(A, X, Y) can be an ordinary function whose arguments are strictly evaluated.

    Moreover, if we give the functional language lazy evaluation semantics,
    then anyway we get the behavior that Y is not evaluated if A is true,
    and that lazy evaluation model can be used as the basis for sneaking
    effects into the functional language and conctrolling them.

    Anyway, Turing calculation by primitive recursion does not require
    conditional branching. Just perhaps an if function which returns
    either its second or third argument based on the truth value of
    its first argument.

    For instance, in certain C preprocessor tricks, conditional expansion
    is achieved by such macros.

    When we run the following through the GNU C preprocessor (e.g. by pasting
    into gcc -E -x c -p -):

    #define TRUE_SELECT_TRUE(X) X
    #define TRUE_SELECT_FALSE(X)

    #define FALSE_SELECT_TRUE(X)
    #define FALSE_SELECT_FALSE(X) X

    #define SELECT_TRUE(X) X
    #define SELECT_FALSE(X)

    #define PASTE(X, Y) X ## Y

    #define IF(A, B, C) PASTE(TRUE_SELECT_, A)(B) PASTE(FALSE_SELECT_, A)(C)

    #define FOO TRUE
    #define BAR FALSE

    IF(FOO, foo is true, foo is false)
    IF(BAR, bar is true, bar is false)

    We get these tokens:

    foo is true
    bar is false

    Yet, macro expansion has no conditionals. The preprocessing language has
    #if and #ifdef, but we didn't use those. Just expansion of computed names.

    This is an example of not strictly needing conditionals to achieve
    conditional evaluation or expansion: an IF(A, B, C) operator that
    yields B or C depending on the truth of A, and so forth.

    John MacCarthy (Lisp inventor) wrote himself such an IF function
    in Fortran, in a program for calculating chess moves. It evaluated
    both the B and C expressions, and so it wasn't a proper imperative
    conditional, but it didn't matter.


    --
    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 Michael S@21:1/5 to Janis Papanagnou on Mon Dec 23 00:20:48 2024
    On Sun, 22 Dec 2024 20:41:44 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 22.12.2024 07:01, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via
    goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    I'm not sure but may have just skimmed over your "C" example if it
    wasn't of interest to the point I tried to make (at that stage).

    Or try to figure out how to do this knowing that C has function
    pointers.

    I will retry to explain what I tried to say... - very simply put...

    There's "Recursive Functions" and the Turing Machines "equivalent".
    The "Recursive Functions" is the most powerful class of algorithms.
    Formal Recursive Functions are formally defined in terms of abstract mathematical formulated properties; one of these [three properties]
    are the "Test Sets". (Here I can already stop.)

    But since we're not in a theoretical CS newsgroup I'd just wanted
    to see an example of some common, say, mathematical function and
    see it implemented without 'if' and 'goto' or recursion. - Take a
    simple one, say, fac(n) = n! , the factorial function. I know how
    I can implement that with 'if' and recursion, and I know how I can
    implement that with 'while' (or 'goto').

    If I re-inspect your example upthread - I hope it was the one you
    wanted to refer to - I see that you have removed the 'if' symbol
    but not the conditional, the test function; there's still the
    predicate (the "Test Set") present in form of 'int c2 = i < n',
    and it's there in the original code, in the goto transformed code,
    and in the function-pointer code. And you cannot get rid of that.

    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    Janis



    You make no sense. I am starting to suspect that the reason for it
    is ignorance rather than mere stubbornness.

    https://godbolt.org/z/EKo5rrYce
    Show me conditional branch in the right pane.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to BGB on Sat Dec 28 09:24:16 2024
    BGB <cr88192@gmail.com> writes:

    On 12/23/2024 3:18 PM, Tim Rentsch wrote:

    Michael S <already5chosen@yahoo.com> writes:

    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    And Tim did not rule out using the standard library,

    Are you sure?

    I explicitly called out setjmp and longjmp as being excluded.
    Based on that, it's reasonable to infer the rest of the
    standard library is allowed.

    Furthermore I don't think it matters. Except for a very small
    set of functions -- eg, fopen, fgetc, fputc, malloc, free --
    everything else in the standard library either isn't important
    for Turing Completeness or can be synthesized from the base
    set. The functionality of fprintf(), for example, can be
    implemented on top of fputc and non-library language features.

    If I were to choose a set of primitive functions, probably:
    malloc/free and/or realloc
    could define, say:
    malloc(sz) => realloc(NULL, sz)
    free(ptr) => realloc(ptr, 0)
    Maybe _msize and _mtag/..., but this is non-standard.
    With _msize, can implement realloc on top of malloc/free.

    For basic IO:
    fopen, fclose, fseek, fread, fwrite

    printf could be implemented on top of vsnprintf and fputs
    fputs can be implemented on top of fwrite (via strlen).
    With a temporary buffer buffer being used for the printed string.

    Most of these aren't needed. I think everything can be
    done using only fopen, fclose, fgetc, fputc, and feof.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to BGB on Sat Dec 28 09:20:23 2024
    BGB <cr88192@gmail.com> writes:

    On 12/23/2024 1:43 AM, David Brown wrote:

    On 23/12/2024 03:41, Waldek Hebisch wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    The comments I made here, in two responses to postings of yours,
    were not statements of opinion but statements of fact.

    They are opinions _about facts_, or if you prefer, opinion
    about truth value of some statements.

    You can program in C without the "normal" conditional statements or
    expressions. You can make an array of two (or more) function
    pointers and select between them using your controlling expression,
    and that should be sufficient for conditionals. (There may be other
    methods too.)

    So as far as I can see, Tim gave statements of fact, not opinion.

    Jumping back in:
    That one can do this seems obvious enough;
    Downside, as I see it, is that there is no current or likely
    processor hardware where this is likely to be performance
    competitive with the more traditional if-goto mechanism [...]

    Irrelevant to the issue being discussed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Waldek Hebisch on Sat Jan 4 12:12:15 2025
    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    The comments I made here, in two responses to postings of yours,
    were not statements of opinion but statements of fact.

    They are opinions _about facts_, or if you prefer, opinion
    about truth value of some statements.

    They are
    no more statements of opinion than a statement about whether the
    Riemann Hypothesis is true is a statement of opinion. Someone
    might wonder whether an assertion "The Riemann Hypothesis is
    true" is true or false, but it is still a matter of fact, not a
    matter of opinion.

    It is reasobable to assume that you do not know if Riemann Hypothesis
    is true or false. So if you say "Riemann Hypothesis is true",
    this is just your opinion. I am not a native English speaker
    but I believed that "statements of opinion" means just that:
    person does not know the truth, but makes a statement.

    A statement of opinion is a statement concerning a subjective
    question, such as "Do cats make better pets than dogs?" A
    statement of opinion isn't ever right or wrong or true or false,
    it merely expresses an individual point of view. Most statements
    that have a word like "should" or "good" or "bad" or "better",
    etc., are statements of opinion. That can change if the
    qualifying words are given precise and objective definitions, but
    in most cases they have not been.

    A statement of fact is a statement concerning an objective question,
    such as "Is every even number greater than 4 the sum of two prime
    numbers?". A statement of fact can be right or wrong or true or
    false, even if it isn't known at the present time which of those is
    the case. The statement "Four colors suffice to color any planar
    map such that adjacent regions do not have the same color" is a
    statement of fact, both now and 60 years ago before the statement
    had been proven. Both P==NP and P!=NP are statements of fact, even
    though one of them must certainly be false; the key property is
    that they are objective statements, subject to falsification. If I
    say "The Earth is flat", that is a statement of fact, even though
    the statement is false.

    In any case, my statements about a particular subset of C being
    Turing Complete were statements of fact, and also true statements.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Waldek Hebisch on Sat Jan 4 11:18:07 2025
    antispam@fricas.org (Waldek Hebisch) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    antispam@fricas.org (Waldek Hebisch) writes:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto. >>>>>>
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts [...]

    What makes you think I didn't?

    I made the same claim as you earlier and gave examples. You
    did not acknowledge my posts. Why? For me most natural
    explanation is that you did not read them.

    You should revise your inference heuristics. There are any
    number of reasons why I might not have referred to your
    comments. Furthermore your conclusion is incorrect.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Kaz Kylheku on Sun Dec 22 23:22:36 2024
    On 22/12/2024 21:45, Kaz Kylheku wrote:
    On 2024-12-21, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    In a functional langauge, we can make a decision by, for instance,
    putting two lambdas into an array A, and then calling A[0] or A[1],
    where the index 0 or 1 is comes from some Boolean result.

    The only reason we have a control construct like if(A, X, Y) where X
    is only evaluated if A is true, otherwise Y, is that X and Y
    have side effects.

    If X and Y don't have side effects, then if(A, X, Y) can be an ordinary function whose arguments are strictly evaluated.

    Moreover, if we give the functional language lazy evaluation semantics,
    then anyway we get the behavior that Y is not evaluated if A is true,
    and that lazy evaluation model can be used as the basis for sneaking
    effects into the functional language and conctrolling them.

    Anyway, Turing calculation by primitive recursion does not require conditional branching. Just perhaps an if function which returns
    either its second or third argument based on the truth value of
    its first argument.

    For instance, in certain C preprocessor tricks, conditional expansion
    is achieved by such macros.

    When we run the following through the GNU C preprocessor (e.g. by pasting into gcc -E -x c -p -):

    #define TRUE_SELECT_TRUE(X) X
    #define TRUE_SELECT_FALSE(X)

    #define FALSE_SELECT_TRUE(X)
    #define FALSE_SELECT_FALSE(X) X

    #define SELECT_TRUE(X) X
    #define SELECT_FALSE(X)

    #define PASTE(X, Y) X ## Y

    #define IF(A, B, C) PASTE(TRUE_SELECT_, A)(B) PASTE(FALSE_SELECT_, A)(C)

    #define FOO TRUE
    #define BAR FALSE

    IF(FOO, foo is true, foo is false)
    IF(BAR, bar is true, bar is false)

    We get these tokens:

    foo is true
    bar is false


    So, how long did it take to debug? (I've no idea how it works. If I
    change all TRUE/FALSE to BART/LISA respectively, it still gives the same output. I'm not sure how germane such an example is.)


    Yet, macro expansion has no conditionals. The preprocessing language has
    #if and #ifdef, but we didn't use those. Just expansion of computed names.

    This is an example of not strictly needing conditionals to achieve conditional evaluation or expansion: an IF(A, B, C) operator that
    yields B or C depending on the truth of A, and so forth.

    John MacCarthy (Lisp inventor) wrote himself such an IF function
    in Fortran, in a program for calculating chess moves. It evaluated
    both the B and C expressions, and so it wasn't a proper imperative conditional, but it didn't matter.

    You mean like this one:

    int IF(int c, int a, int b) {
    return a*!!c + b*!c;
    }

    I think most languages can manage that. I guess there was a reason
    McCarthy needed it rather than use Fortran's existing IF statement,
    other than, being the Lisp guy, that was how his mind worked.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Janis Papanagnou on Sun Dec 22 23:29:50 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 22.12.2024 07:01, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto. >>>>>
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    I'm not sure but may have just skimmed over your "C" example if it
    wasn't of interest to the point I tried to make (at that stage).

    Or try to figure out how to do this knowing that C has function
    pointers.

    I will retry to explain what I tried to say... - very simply put...

    There's "Recursive Functions" and the Turing Machines "equivalent".
    The "Recursive Functions" is the most powerful class of algorithms.
    Formal Recursive Functions are formally defined in terms of abstract mathematical formulated properties; one of these [three properties]
    are the "Test Sets". (Here I can already stop.)

    Classic definition uses some number of base functions, some
    number of base conditions, conditional definitions and
    "minimum operator". "Minimum operator" given a (possibly
    partially defined) function f and l computes smallest n such that
    f(k, l) is defined for k=0,1,...,n and f(n, l) = 0 and is undefined
    otherwise. Some texts require minimum to be effective, that
    is f should be total and for each l there should be n >= 0 such
    that f(n, l) = 0. Clearly "minimum operator" is equvalent to
    'while' loop. IIRC, if instead of "minimum operator" you only
    recursion, then resulting class of functions is strictly smaller.
    So assuming that I remember correctly, in framework of recursive
    functions claim that conditianals and recursion give Turing
    completness is false, one needs some "programming" constructs.

    Anyway, using recursion you clearly need some way to stop it. If you
    restrict yourself to eagerly evaluated total integer valued functions
    only, then clearly there is no way to stop recursion. But if
    you have different system like lambda calculus or C, then there
    are ways to stop recursion that are quite different than 'if'
    or tertiary operator.

    But since we're not in a theoretical CS newsgroup I'd just wanted
    to see an example of some common, say, mathematical function and
    see it implemented without 'if' and 'goto' or recursion.

    To be clear: I need recursion in general. I do not need 'if'
    to stop recursion.

    - Take a
    simple one, say, fac(n) = n! , the factorial function. I know how
    I can implement that with 'if' and recursion, and I know how I can
    implement that with 'while' (or 'goto').

    If I re-inspect your example upthread - I hope it was the one you
    wanted to refer to - I see that you have removed the 'if' symbol
    but not the conditional, the test function; there's still the
    predicate (the "Test Set") present in form of 'int c2 = i < n',

    You failed to see that this is on ordinary total function: it
    evaluates both arguments and produces a value. If I take the
    following C function:

    int lt(int a, int b) {
    return (a < b);
    }

    and compile it using 'gcc -O -S' I get:

    lt:
    .LFB0:
    .cfi_startproc
    cmpl %esi, %edi
    setl %al
    movzbl %al, %eax
    ret

    As you can see the only control transfer there is 'ret' at the
    end of the function. 'if' and C ternary oprators are quite
    different, you can not implement them as ordinary functions
    (some special case can be optimized to jumpless code, but not
    in general).

    and it's there in the original code, in the goto transformed code,
    and in the function-pointer code. And you cannot get rid of that.

    I can, but for something like factorial code would be quite
    ugly. One can implement reasonable Turing machine emulator
    using just integer and function pointer arrays, array accesses
    and assignments, direct and indirect funcction calls.

    By reasonable I mean that as long as Turning machine stays
    in part of tape modeled as C array emulator and Turing machine
    would move in step. Stop in Turing machine would exit emulator.
    Only when Turing machine exceeds memory of C program, C program
    would exhibit undefined behaviour. If you allow yourself also
    C arithmetic operators (crucualy '/' and '%'), then you can
    stop execution.

    If you assume C implementation with infinite memory such that
    'malloc' newer fails, then instead of array you can use
    doubly linked list which gets extended when Turing machine
    tries to get outside allocated space.

    IIUC such infinite C implementation would exhibit undefined
    behaviour as C standard requires finite bound on integers and
    injective cast from from pointers to some integer type.

    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    Wrong, one can use properties of C23 division (actually,
    what is needed division and remainder by a fixed positive
    number, say 3).

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    One point that I wanted to make is that programming languages are
    different than theory of integer functions, in particular programming constructs may be surprisingly powerful. For example, there was
    a theorem about some special concurrecy problem saying that
    desired mutial exclusion can not be done by binary semaphores.
    David Parnas showed that it in fact can be solved using arrays
    of binary semaphores. The theorem had unstated assumption that
    only scalar semaphore variables are in use. Of course, once you eliminate
    all useful constructs from a language, then one can not do anything
    is such a language (as a joke David Parnas defined such a language).

    Second point was that function calls in tail position are quite similar
    to goto, and in case of indirect calls they can do job of 'if' or 'switch'.
    So if you consider elimination of 'if' (or 'goto') as a cheat, the
    cheat is in using function calls, and not in predicates.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to bart on Sun Dec 22 23:47:25 2024
    On 2024-12-22, bart <bc@freeuk.com> wrote:
    On 22/12/2024 21:45, Kaz Kylheku wrote:
    On 2024-12-21, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto. >>>>>
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    In a functional langauge, we can make a decision by, for instance,
    putting two lambdas into an array A, and then calling A[0] or A[1],
    where the index 0 or 1 is comes from some Boolean result.

    The only reason we have a control construct like if(A, X, Y) where X
    is only evaluated if A is true, otherwise Y, is that X and Y
    have side effects.

    If X and Y don't have side effects, then if(A, X, Y) can be an ordinary
    function whose arguments are strictly evaluated.

    Moreover, if we give the functional language lazy evaluation semantics,
    then anyway we get the behavior that Y is not evaluated if A is true,
    and that lazy evaluation model can be used as the basis for sneaking
    effects into the functional language and conctrolling them.

    Anyway, Turing calculation by primitive recursion does not require
    conditional branching. Just perhaps an if function which returns
    either its second or third argument based on the truth value of
    its first argument.

    For instance, in certain C preprocessor tricks, conditional expansion
    is achieved by such macros.

    When we run the following through the GNU C preprocessor (e.g. by pasting
    into gcc -E -x c -p -):

    #define TRUE_SELECT_TRUE(X) X
    #define TRUE_SELECT_FALSE(X)

    #define FALSE_SELECT_TRUE(X)
    #define FALSE_SELECT_FALSE(X) X

    #define SELECT_TRUE(X) X
    #define SELECT_FALSE(X)

    #define PASTE(X, Y) X ## Y

    #define IF(A, B, C) PASTE(TRUE_SELECT_, A)(B) PASTE(FALSE_SELECT_, A)(C) >>
    #define FOO TRUE
    #define BAR FALSE

    IF(FOO, foo is true, foo is false)
    IF(BAR, bar is true, bar is false)

    We get these tokens:

    foo is true
    bar is false


    So, how long did it take to debug? (I've no idea how it works. If I

    I typed it out right in the middle of my article and piped it out to
    gcc, iterating a few times. I made a few silly mistakes in IF, mostly
    due to referencing the wrong A, B, C.

    Also, the SELECT_TRUE and SELECT_FALSE macros are dead code; not used.

    change all TRUE/FALSE to BART/LISA respectively, it still gives the same output. I'm not sure how germane such an example is.)

    If you rename consistently, it will work. But it's not hygienic in that
    since the solution relies on calculated identifiers, you have to change TRUE_SELECT_TRUE to TRUE_SELECT_BART.

    How it works is very simmple in that PASTE(TRUE_SELECT_, A) calculates TRUE_SELECT_TRUE or TRUE_SELECT_FALSE depending on whether A contains
    TRUE or FALSE. Then the argument list (B) is combined with this
    calculated name, resulting in a macro call to TRUE_SELECT_TRUE(B) or TRUE_SELECT_FALSE(B) with the value of B as an argument.
    If the former is used, then it expands to B; if the latter, then to
    nothing.

    One of the two PASTE calls in the expansion of IF() produces tokens, and
    the other nothing. The two results are catenated together into one token sequence, so we get the result of whichever one is nonempty.

    --
    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 Tim Rentsch@21:1/5 to Janis Papanagnou on Sun Dec 22 17:39:52 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 22.12.2024 02:04, Michael S wrote:

    [...]

    Part of the answer is in your previous response.
    You wrote: "many _good_ professors I met in my life typically were
    keen to explain their theses, statements, or knowledge (instead of
    dragging that out of him)". You essentially admitted that not all good
    professors behave like that.

    Oh, what I meant to express was different; that good professors
    *would* explain it (only bad ones wouldn't).

    (At least that was my experience; and not only covering the CS
    domain, BTW.)

    [ "schools of teaching" stuff snipped ]

    You make an impression of one that received basics of CS. Probably, 40
    or so years ago, but still you have to know basic facts. Unlike me, for
    example.
    So, Tim expects that you will be able to utilizes his hints.

    The point [repeatedly] stated (also by others here) was that
    he more often than not just provides no information but simple
    arbitrary statements of opinion.

    The comments I made here, in two responses to postings of yours,
    were not statements of opinion but statements of fact. They are
    no more statements of opinion than a statement about whether the
    Riemann Hypothesis is true is a statement of opinion. Someone
    might wonder whether an assertion "The Riemann Hypothesis is
    true" is true or false, but it is still a matter of fact, not a
    matter of opinion.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to BGB on Mon Dec 23 02:08:46 2024
    On Wed, 18 Dec 2024 23:46:21 -0600, BGB wrote:

    ... (what debug mechanisms I have, effectively lack any symbols
    for things inside "ld-linux.so"'s domain).

    nm -D /lib/ld-linux.so.2

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Kaz Kylheku on Sun Dec 22 17:22:01 2024
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    On 2024-12-21, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via
    goto.

    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    In a functional langauge, we can make a decision by, for instance,
    putting two lambdas into an array A, and then calling A[0] or A[1],
    where the index 0 or 1 is comes from some Boolean result.

    The only reason we have a control construct like if(A, X, Y) where X
    is only evaluated if A is true, otherwise Y, is that X and Y
    have side effects.

    If X and Y don't have side effects, then if(A, X, Y) can be an ordinary function whose arguments are strictly evaluated.

    Moreover, if we give the functional language lazy evaluation
    semantics, then anyway we get the behavior that Y is not evaluated
    if A is true, and that lazy evaluation model can be used as the
    basis for sneaking effects into the functional language and
    conctrolling them.

    Anyway, Turing calculation by primitive recursion does not require conditional branching. Just perhaps an if function which returns
    either its second or third argument based on the truth value of its
    first argument.

    For instance, in certain C preprocessor tricks, conditional
    expansion is achieved by such macros.

    When we run the following through the GNU C preprocessor (e.g. by
    pasting into gcc -E -x c -p -):

    #define TRUE_SELECT_TRUE(X) X
    #define TRUE_SELECT_FALSE(X)

    #define FALSE_SELECT_TRUE(X)
    #define FALSE_SELECT_FALSE(X) X

    #define SELECT_TRUE(X) X
    #define SELECT_FALSE(X)

    #define PASTE(X, Y) X ## Y

    #define IF(A, B, C) PASTE(TRUE_SELECT_, A)(B) PASTE(FALSE_SELECT_, A)(C)

    #define FOO TRUE
    #define BAR FALSE

    IF(FOO, foo is true, foo is false)
    IF(BAR, bar is true, bar is false)

    We get these tokens:

    foo is true
    bar is false

    Yet, macro expansion has no conditionals. The preprocessing
    language has #if and #ifdef, but we didn't use those. Just
    expansion of computed names.

    Nice example.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Waldek Hebisch@21:1/5 to Tim Rentsch on Mon Dec 23 02:41:10 2024
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    The comments I made here, in two responses to postings of yours,
    were not statements of opinion but statements of fact.

    They are opinions _about facts_, or if you prefer, opinion
    about truth value of some statements.

    They are
    no more statements of opinion than a statement about whether the
    Riemann Hypothesis is true is a statement of opinion. Someone
    might wonder whether an assertion "The Riemann Hypothesis is
    true" is true or false, but it is still a matter of fact, not a
    matter of opinion.

    It is reasobable to assume that you do not know if Riemann Hypothesis
    is true or false. So if you say "Riemann Hypothesis is true",
    this is just your opinion. I am not a native English speaker
    but I believed that "statements of opinion" means just that:
    person does not know the truth, but makes a statement.

    --
    Waldek Hebisch

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Waldek Hebisch on Mon Dec 23 08:43:07 2024
    On 23/12/2024 03:41, Waldek Hebisch wrote:
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    The comments I made here, in two responses to postings of yours,
    were not statements of opinion but statements of fact.

    They are opinions _about facts_, or if you prefer, opinion
    about truth value of some statements.

    You can program in C without the "normal" conditional statements or expressions. You can make an array of two (or more) function pointers
    and select between them using your controlling expression, and that
    should be sufficient for conditionals. (There may be other methods too.)

    So as far as I can see, Tim gave statements of fact, not opinion.

    You can say that Tim's posts were patronising, arrogant, and irritating.
    /That/ would be an opinion - a /justified/ opinion because it is
    backed up in the evidence of these posts and corroborating evidence from previous posts and discussions from Tim. But without some kind of
    precise definition of the terms involved and a robust and repeatable
    method of classification, it could not be called "fact".

    You could say that Tim's posts were intended to be annoying, or you
    could say that he has refused to give an answer to how C can be used
    without the "normal" conditionals because he realises he was wrong in
    his posts and won't admit it. That would be /unjustified/ opinion - or "speculation" - because we have no way of knowing his motives or
    anything more than what he wrote in his posts.


    You could, quite fairly, characterise Tim's posts as unjustified
    statements of fact - because he has stated his claim as fact, but has
    given no justification or reasoning, and it is not something that is
    obvious or well-known to people.


    They are
    no more statements of opinion than a statement about whether the
    Riemann Hypothesis is true is a statement of opinion. Someone
    might wonder whether an assertion "The Riemann Hypothesis is
    true" is true or false, but it is still a matter of fact, not a
    matter of opinion.

    It is reasobable to assume that you do not know if Riemann Hypothesis
    is true or false.

    I think if anyone knew the truth of falsity of the Riemann Hypothesis -
    i.e., they had a proof one way or the other - we'd have heard about it!

    So if you say "Riemann Hypothesis is true",
    this is just your opinion.

    No, that would not be an opinion. It would be an unjustified claim. "I /believe/ the Riemann Hypothesis is true" is an opinion.

    I am not a native English speaker
    but I believed that "statements of opinion" means just that:
    person does not know the truth, but makes a statement.


    No, an opinion is a personal preference or judgement. That's very
    different from not knowing about something factual. If I say "the
    number 17 will turn up in next week's lottery numbers", that's not an
    opinion, it's a claim about facts. It's an unjustified claim, since I
    don't know if it is true or not, but it's not an opinion.

    It is not always clear when something is a fact or not, and whether a
    statement is a justified statement of fact, an unjustified statement of
    fact (i.e., it might happen to be true, but you have not presented
    evidence of it), a justified opinion, or an unjustified opinion. I'm
    sure there's a philosophy group on Usenet somewhere, but I doubt if cross-posting there would lead to any clarification!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Mon Dec 23 09:46:46 2024
    On 22/12/2024 20:41, Janis Papanagnou wrote:
    On 22.12.2024 07:01, Waldek Hebisch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 21.12.2024 02:28, Tim Rentsch wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto. >>>>>
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    I'm not sure but may have just skimmed over your "C" example if it
    wasn't of interest to the point I tried to make (at that stage).

    Or try to figure out how to do this knowing that C has function
    pointers.

    I will retry to explain what I tried to say... - very simply put...

    There's "Recursive Functions" and the Turing Machines "equivalent".
    The "Recursive Functions" is the most powerful class of algorithms.
    Formal Recursive Functions are formally defined in terms of abstract mathematical formulated properties; one of these [three properties]
    are the "Test Sets". (Here I can already stop.)

    But since we're not in a theoretical CS newsgroup I'd just wanted
    to see an example of some common, say, mathematical function and
    see it implemented without 'if' and 'goto' or recursion. - Take a
    simple one, say, fac(n) = n! , the factorial function. I know how
    I can implement that with 'if' and recursion, and I know how I can
    implement that with 'while' (or 'goto').

    If I re-inspect your example upthread - I hope it was the one you
    wanted to refer to - I see that you have removed the 'if' symbol
    but not the conditional, the test function; there's still the
    predicate (the "Test Set") present in form of 'int c2 = i < n',
    and it's there in the original code, in the goto transformed code,
    and in the function-pointer code. And you cannot get rid of that.

    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.


    You are adding more restrictions than Tim had given.

    We all know that for most non-trivial algorithms you need some kind of repetition (loops, recursion, etc.) and some way to end that repetition.
    No one is claiming otherwise.

    Tim ruled out &&, ||, ?:, goto, break, continue, if, for, while, switch,
    do, labels, setjmp and longjmp.

    He didn't rule out recursion, or the relational operators, or any other
    part of C.


    int fact(int n);

    int fact_zero(int n) {
    return 1;
    }

    int n_fact_n1(int n) {
    return n * fact(n - 1);
    }

    int fact(int n) {
    return (int (*[])(int)){ fact_zero, n_fact_n1 }[(bool) n](n);
    }


    There are additional fun things that can be done using different
    operators. For an unsigned integer "n" that is not big enough to wrap,
    "(n + 2) / (n + 1) - 1" evaluates "(n == 0)".

    And Tim did not rule out using the standard library, which would surely
    open up new possibilities.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Tim Rentsch on Sun Jan 5 11:18:03 2025
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    A statement of fact is a statement concerning an objective question,
    such as "Is every even number greater than 4 the sum of two prime
    numbers?". A statement of fact can be right or wrong or true or
    false, even if it isn't known at the present time which of those is
    the case. The statement "Four colors suffice to color any planar
    map such that adjacent regions do not have the same color" is a
    statement of fact, both now and 60 years ago before the statement
    had been proven. Both P==NP and P!=NP are statements of fact, even
    though one of them must certainly be false; the key property is
    that they are objective statements, subject to falsification. If I
    say "The Earth is flat", that is a statement of fact, even though
    the statement is false.

    I think you go too far. The word "fact" is not neutral as far as its
    truth is concerned, and writing "a statement of fact" does not
    significantly change that. Most dictionaries define a fact as something
    that is true (or at least supported by currently available evidence).
    One online essay[1] concludes that

    "A statement of fact is one that has objective content and is
    well-supported by the available evidence."

    [1] https://philosophersmag.com/the-fact-opinion-distinction/

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Ben Bacarisse on Sun Jan 5 12:04:41 2025
    On 1/5/25 06:18, Ben Bacarisse wrote:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    A statement of fact is a statement concerning an objective question,
    such as "Is every even number greater than 4 the sum of two prime
    numbers?". A statement of fact can be right or wrong or true or
    false, even if it isn't known at the present time which of those is
    the case. The statement "Four colors suffice to color any planar
    map such that adjacent regions do not have the same color" is a
    statement of fact, both now and 60 years ago before the statement
    had been proven. Both P==NP and P!=NP are statements of fact, even
    though one of them must certainly be false; the key property is
    that they are objective statements, subject to falsification. If I
    say "The Earth is flat", that is a statement of fact, even though
    the statement is false.

    I think you go too far. The word "fact" is not neutral as far as its
    truth is concerned, and writing "a statement of fact" does not
    significantly change that. Most dictionaries define a fact as something
    that is true (or at least supported by currently available evidence).
    One online essay[1] concludes that

    "A statement of fact is one that has objective content and is
    well-supported by the available evidence."

    [1] https://philosophersmag.com/the-fact-opinion-distinction/

    In US constitutional law, there is the concept of "False statements of
    fact". The distinction is important in that context because they have
    less protection under the First Amendment than true statements of fact.
    They still have some protection, but not if they are defamatory, false advertising, or commercial speech.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Mon Dec 23 11:35:56 2024
    On 23/12/2024 08:46, David Brown wrote:

    Tim ruled out &&, ||, ?:, goto, break, continue, if, for, while, switch,
    do, labels, setjmp and longjmp.

    He didn't rule out recursion, or the relational operators, or any other
    part of C.


    int fact(int n);

    int fact_zero(int n) {
            return 1;
    }

    int n_fact_n1(int n) {
            return n * fact(n - 1);
    }

    int fact(int n) {
            return (int (*[])(int)){ fact_zero, n_fact_n1 }[(bool) n](n); }


    There are additional fun things that can be done using different
    operators.  For an unsigned integer "n" that is not big enough to wrap,
    "(n + 2) / (n + 1) - 1"  evaluates "(n == 0)".

    Isn't this just !n ? I don't think "!" was ruled out. This would also
    work for negative n.

    And Tim did not rule out using the standard library, which would surely
    open up new possibilities.

    printf (not sprintf) would be reasonable here to show results. Anything
    else could be considered cheating.

    The original context was a small subset of C that can be used to
    represent a larger subset.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Mon Dec 23 13:40:08 2024
    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    And Tim did not rule out using the standard library,


    Are you sure?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Mon Dec 23 13:24:14 2024
    On 23/12/2024 12:40, Michael S wrote:
    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:


    And Tim did not rule out using the standard library,


    Are you sure?


    Fairly sure, yes.

    But if you think I missed something, please say.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Mon Dec 23 13:18:46 2024
    On 23/12/2024 12:35, bart wrote:
    On 23/12/2024 08:46, David Brown wrote:

    Tim ruled out &&, ||, ?:, goto, break, continue, if, for, while,
    switch, do, labels, setjmp and longjmp.

    He didn't rule out recursion, or the relational operators, or any
    other part of C.


    int fact(int n);

    int fact_zero(int n) {
             return 1;
    }

    int n_fact_n1(int n) {
             return n * fact(n - 1);
    }

    int fact(int n) {
             return (int (*[])(int)){ fact_zero, n_fact_n1 }[(bool) n](n);
    }


    There are additional fun things that can be done using different
    operators.  For an unsigned integer "n" that is not big enough to
    wrap, "(n + 2) / (n + 1) - 1"  evaluates "(n == 0)".

    Isn't this just !n ? I don't think "!" was ruled out. This would also
    work for negative n.

    Sure. It was merely another example of something you could use, if you
    had ruled out simpler things (like the conversion to bool that I used,
    or the ! operator that you suggest).



    And Tim did not rule out using the standard library, which would
    surely open up new possibilities.

    printf (not sprintf) would be reasonable here to show results. Anything
    else could be considered cheating.


    No, I would not say so - as long as the standard library is not ruled
    out, it is part of C. But I think you could reasonably argue that
    allowing the standard library makes this whole pointless exercise even
    more pointless!

    The original context was a small subset of C that can be used to
    represent a larger subset.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Scott Lurndal on Mon Dec 23 15:51:24 2024
    On 23/12/2024 15:41, Scott Lurndal wrote:
    Michael S <already5chosen@yahoo.com> writes:
    On Sun, 22 Dec 2024 20:41:44 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:



    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed
    function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    Janis



    You make no sense. I am starting to suspect that the reason for it
    is ignorance rather than mere stubbornness.

    https://godbolt.org/z/EKo5rrYce
    Show me conditional branch in the right pane.


    The 'C' in 'CSET' is short for conditional. Because
    the branch is folded into the compare doesn't mean it
    isn't there.

    That's just a mnemomic, which doesn't exist in the x86 version.

    Anyway, 'w0' seems to be set either way, and the program counter will
    point to the same instruction in each case too.

    So there's no branching at this level of code, unless you consider
    stepping PC to the next instruction to be a jump.

    How is it 'folded into' the compare anyway? Are they not two independent instructions?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Mon Dec 23 15:41:40 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Sun, 22 Dec 2024 20:41:44 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:



    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed
    function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    Janis



    You make no sense. I am starting to suspect that the reason for it
    is ignorance rather than mere stubbornness.

    https://godbolt.org/z/EKo5rrYce
    Show me conditional branch in the right pane.


    The 'C' in 'CSET' is short for conditional. Because
    the branch is folded into the compare doesn't mean it
    isn't there.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Scott Lurndal on Mon Dec 23 18:05:48 2024
    On Mon, 23 Dec 2024 15:41:40 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Sun, 22 Dec 2024 20:41:44 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:



    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed
    function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    Janis



    You make no sense. I am starting to suspect that the reason for it
    is ignorance rather than mere stubbornness.

    https://godbolt.org/z/EKo5rrYce
    Show me conditional branch in the right pane.


    The 'C' in 'CSET' is short for conditional. Because
    the branch is folded into the compare doesn't mean it
    isn't there.

    No, branch is not "folded". It is absent. CSET is an ALU operation.
    The logical-arithmetic nature of comparison operator is even more
    pronounced in code that gcc generates for POWER
    https://godbolt.org/z/8Gs9s6nEo

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Mon Dec 23 13:02:02 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Sat, 21 Dec 2024 21:31:24 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    So your statement asks for some explanation at least.

    I would guess that Tim worked as CS professor for several dozens years.
    And it shows.

    I'm not sure whether to feel flattered or insulted. ;)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Janis Papanagnou on Mon Dec 23 14:00:38 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 22.12.2024 07:01, Waldek Hebisch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 21.12.2024 02:28, Tim Rentsch wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 16.12.2024 00:53, BGB wrote:

    [...]

    Pretty much all higher level control flow can be expressed via goto. >>>>>
    A 'goto' may be used but it isn't strictly *necessary*. What *is*
    necessary, though, that is an 'if' (some conditional branch), and
    either 'goto' or recursive functions.

    Conditional branches, including 'if', '?:', etc., are not strictly
    necessary either.

    No? - Can you give an example of your statement?

    Look at example that I posted (apparently neither you nor Tim
    looked at my posts where I explained in detail how to translate
    goto program (with conditional jumps) into program that contains
    no goto and no conditional jumps).

    I'm not sure but may have just skimmed over your "C" example if it
    wasn't of interest to the point I tried to make (at that stage).

    Or try to figure out how to do this knowing that C has function
    pointers.

    I will retry to explain what I tried to say... - very simply put...

    There's "Recursive Functions" and the Turing Machines "equivalent".
    The "Recursive Functions" is the most powerful class of algorithms.
    Formal Recursive Functions are formally defined in terms of abstract mathematical formulated properties; one of these [three properties]
    are the "Test Sets". (Here I can already stop.)

    But since we're not in a theoretical CS newsgroup I'd just wanted
    to see an example of some common, say, mathematical function and
    see it implemented without 'if' and 'goto' or recursion. - Take a
    simple one, say, fac(n) = n! , the factorial function. I know how
    I can implement that with 'if' and recursion, and I know how I can
    implement that with 'while' (or 'goto').

    If I re-inspect your example upthread - I hope it was the one you
    wanted to refer to - I see that you have removed the 'if' symbol
    but not the conditional, the test function; there's still the
    predicate (the "Test Set") present in form of 'int c2 = i < n',
    and it's there in the original code, in the goto transformed code,
    and in the function-pointer code. And you cannot get rid of that.

    Are you sure about that?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Mon Dec 23 13:18:24 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    And Tim did not rule out using the standard library,

    Are you sure?

    I explicitly called out setjmp and longjmp as being excluded.
    Based on that, it's reasonable to infer the rest of the
    standard library is allowed.

    Furthermore I don't think it matters. Except for a very small
    set of functions -- eg, fopen, fgetc, fputc, malloc, free --
    everything else in the standard library either isn't important
    for Turing Completeness or can be synthesized from the base
    set. The functionality of fprintf(), for example, can be
    implemented on top of fputc and non-library language features.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Mon Dec 23 14:05:55 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    Michael S <already5chosen@yahoo.com> writes:

    On Sun, 22 Dec 2024 20:41:44 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:



    Whether you have the test in an 'if', or in a ternary '?:', or
    use it through a bool-int coercion as integer index to an indexed
    function[-pointer] table; it's a conditional branch based on the
    ("Test Set") predicate i<n. You showed in your example how to get
    rid of the 'if' symbol, but you could - as expected - not get rid
    of the actual test that is the substance of a conditional branch.

    I think that is what is to expect by the theory and the essence of
    the point I tried to make.

    You make no sense. I am starting to suspect that the reason for it
    is ignorance rather than mere stubbornness.

    https://godbolt.org/z/EKo5rrYce
    Show me conditional branch in the right pane.

    The 'C' in 'CSET' is short for conditional. Because
    the branch is folded into the compare doesn't mean it
    isn't there.

    It's a moot point because relational operators and equality
    operators can be synthesized out of bitwise and arithmetic
    operators.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Tim Rentsch on Tue Dec 24 00:41:23 2024
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Michael S <already5chosen@yahoo.com> writes:

    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    And Tim did not rule out using the standard library,

    Are you sure?

    I explicitly called out setjmp and longjmp as being excluded.
    Based on that, it's reasonable to infer the rest of the
    standard library is allowed.

    Furthermore I don't think it matters.

    Hmm... I'm puzzled. Where does the unbounded store come from without
    I/O? Do you take "C is Turing complete" to mean that there is a
    theoretically possible implementation of C sufficient for any given
    problem instance (rather than for any given problem)? That's not how
    different models are usually compared, and I think it would run into
    some rather odd theoretical problems.

    There is a somewhat informal version of "C (with the restrictions you
    have stated) is Turing complete" which just means "you can do anything
    you want provided you don't hit an implementation limit".

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Ben Bacarisse on Mon Dec 23 20:55:04 2024
    Ben Bacarisse <ben@bsb.me.uk> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Michael S <already5chosen@yahoo.com> writes:

    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    And Tim did not rule out using the standard library,

    Are you sure?

    I explicitly called out setjmp and longjmp as being excluded.
    Based on that, it's reasonable to infer the rest of the
    standard library is allowed.

    Furthermore I don't think it matters.

    Hmm... I'm puzzled. Where does the unbounded store come from without
    I/O? Do you take "C is Turing complete" to mean that there is a theoretically possible implementation of C sufficient for any given
    problem instance (rather than for any given problem)? That's not how different models are usually compared, and I think it would run into
    some rather odd theoretical problems.

    Sorry, it seems my comment was misleading. I thought it was
    apparent from the rest of my paragraph (not shown in your excerpt)
    that my statement was meant as "Furthermore I don't think it matters
    if _most_ of the standard library is excluded." There had been a
    mention of printf as being infringing (which in my view is silly,
    but never mind that), so I wanted to point out that most of the
    standard library is irrelevant, including in particular [f]printf.

    There is a somewhat informal version of "C (with the restrictions you
    have stated) is Turing complete" which just means "you can do anything
    you want provided you don't hit an implementation limit".

    Yes, I'm familiar with that, and I knowingly glossed over the
    distinction, because I think it's customary, when talking about
    Turing Completeness relative to conventional programming languages,
    to ignore the finiteness of conventional language models. I should
    have known better with you in the audience. You got me! :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to BGB on Tue Dec 31 04:57:58 2024
    BGB <cr88192@gmail.com> writes:

    On 12/28/2024 11:24 AM, Tim Rentsch wrote:

    BGB <cr88192@gmail.com> writes:

    On 12/23/2024 3:18 PM, Tim Rentsch wrote:

    Michael S <already5chosen@yahoo.com> writes:

    On Mon, 23 Dec 2024 09:46:46 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    And Tim did not rule out using the standard library,

    Are you sure?

    I explicitly called out setjmp and longjmp as being excluded.
    Based on that, it's reasonable to infer the rest of the
    standard library is allowed.

    Furthermore I don't think it matters. Except for a very small
    set of functions -- eg, fopen, fgetc, fputc, malloc, free --
    everything else in the standard library either isn't important
    for Turing Completeness or can be synthesized from the base
    set. The functionality of fprintf(), for example, can be
    implemented on top of fputc and non-library language features.

    If I were to choose a set of primitive functions, probably:
    malloc/free and/or realloc
    could define, say:
    malloc(sz) => realloc(NULL, sz)
    free(ptr) => realloc(ptr, 0)
    Maybe _msize and _mtag/..., but this is non-standard.
    With _msize, can implement realloc on top of malloc/free.

    For basic IO:
    fopen, fclose, fseek, fread, fwrite

    printf could be implemented on top of vsnprintf and fputs
    fputs can be implemented on top of fwrite (via strlen).
    With a temporary buffer buffer being used for the printed string.

    Most of these aren't needed. I think everything can be
    done using only fopen, fclose, fgetc, fputc, and feof.

    If you only have fgetc and fputc, IO speeds are going to be
    unacceptably slow for non-trivial file sizes.

    Once again, any performance concerns are not relevant to the
    matter under discussion.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rosario19@21:1/5 to All on Thu Dec 26 13:16:57 2024
    On Mon, 16 Dec 2024 21:22:31 -0000 (UTC), Lawrence D'Oliveiro <>
    wrote:

    On Sun, 15 Dec 2024 20:08:53 +0100, Bonita Montero wrote:

    C++ is more readable because is is magnitudes more expressive than C.

    my position is all is based from the more easy instructions both for
    cpu and human, if goto

    someone says that is better ifcall, but for me is not much readable,
    it is worse than ifgoto

    And it is certainly more surprising than C. Often unpleasantly so.

    You can easily write a C++-statement that would hunddres of lines in C

    Yes, but *which* hundreds of lines, exactly, would be the correct C >equivalent?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)