• Re: Macro issue...

    From Paavo Helde@3:633/10 to Chris M. Thomasson on Wed Sep 17 14:43:06 2025
    From: eesnimi@osa.pri.ee

    On 9/17/2025 2:45 AM, Chris M. Thomasson wrote:
    Humm... Actually, is this use of my macro(s), CT_ASB_*, okay for this
    little code example I wrote to "help" me write AppleSoft BASIC? Can you
    run it, is the code Kosher, so to speak, well, does it work for you or not...? Any undefined behavior in my macro? The macros seem a bit
    hackish, but they seem to work okay for now: ______________________________________
    #include <iostream>
    #include <sstream>


    // Macro kosher? Seems to be...
    namespace ct_basic {

        struct program_counter {
            unsigned long m_origin;
            unsigned long m_cur;
            unsigned long m_inc;
            std::stringstream m_prog;

            program_counter(
                unsigned long cur = 0,
                unsigned long inc = 10
            ) : m_origin(cur), m_cur(cur), m_inc(inc) {
            }

            void line(std::stringstream const& line0) {
                m_prog << m_cur << " " << line0.str() << std::endl;
                m_cur += m_inc;
            }
        };

        #define CT_ASB_LINE(mp_pc, mp_x) \
            { \
                std::stringstream line0; \
                line0 << mp_x; \
                (mp_pc).line(line0); \
            }


        #define CT_ASB_GOSUB(mp_pc0, mp_pc1, mp_indent) \
            CT_ASB_LINE(mp_pc0, mp_indent "GOSUB " << mp_pc1.m_origin)
    }

    Why macros? My Copilot rewrote them as functions, apparently with no
    loss of functionality:

    void CT_ASB_LINE(program_counter& mp_pc, const std::string& mp_x)
    {
    std::stringstream line0;
    line0 << mp_x;
    (mp_pc).line(line0);
    }


    void CT_ASB_GOSUB(program_counter& mp_pc0, program_counter& mp_pc1,
    const std::string& mp_indent)
    {
    CT_ASB_LINE(mp_pc0, mp_indent + "GOSUB " + std::to_string(mp_pc1.m_origin));
    }

    Coming to think about that, why stringstreams at all? In my experience
    just growing a std::string by appending to it is both simpler and faster.



    int
    main()
    {
        {
            std::cout << "ctBasic testing 123... :^)\n";
            std::cout << "__________________________\n";

            {

                ct_basic::program_counter pc0(100);
                ct_basic::program_counter pc1(1000);

                // ct_main
                {
                    ct_basic::program_counter& PC = pc0;

                    CT_ASB_LINE(PC, "REM ct_main");
                    CT_ASB_LINE(PC, "    PRINT \"ct_main\"");
                    CT_ASB_GOSUB(PC, pc1, "    ");
                    CT_ASB_LINE(PC, "END");
                }

                // ct_init
                {
                    ct_basic::program_counter& PC = pc1;

                    CT_ASB_LINE(PC, "REM ct_init");
                    CT_ASB_LINE(PC, "    PRINT \"ct_init\"");
                    CT_ASB_LINE(PC, "RETURN");
                }

                std::cout << pc0.m_prog.str() << "\n\n";
                std::cout << pc1.m_prog.str() << "\n\n";
            }

            std::cout << "__________________________\n";
        }

        std::cout << "Complete! Well, time to test the\n";
        std::cout << "generated AppleSoft BASIC";

        return 0;
    }
    ______________________________________


    Fwiw, I get an output of:

    ctBasic testing 123... :^)
    __________________________
    100 REM ct_main
    110     PRINT "ct_main"
    120     GOSUB 1000
    130 END


    1000 REM ct_init
    1010     PRINT "ct_init"
    1020 RETURN


    __________________________
    Complete! Well, time to test the
    generated AppleSoft BASIC


    --- SoupGate-Linux v1.05
    * Origin: Dragon's Lair ---:- FidoNet<>Usenet Gateway -:--- (3:633/10)
  • From Paavo Helde@3:633/10 to Chris M. Thomasson on Thu Sep 18 13:28:37 2025
    From: eesnimi@osa.pri.ee

    On 9/17/2025 10:58 PM, Chris M. Thomasson wrote:
    On 9/17/2025 4:43 AM, Paavo Helde wrote:
    On 9/17/2025 2:45 AM, Chris M. Thomasson wrote:
    Humm... Actually, is this use of my macro(s), CT_ASB_*, okay for this
    little code example I wrote to "help" me write AppleSoft BASIC? Can
    you run it, is the code Kosher, so to speak, well, does it work for
    you or not...? Any undefined behavior in my macro? The macros seem a
    bit hackish, but they seem to work okay for now:
    ______________________________________
    #include <iostream>
    #include <sstream>


    // Macro kosher? Seems to be...
    namespace ct_basic {

         struct program_counter {
             unsigned long m_origin;
             unsigned long m_cur;
             unsigned long m_inc;
             std::stringstream m_prog;

             program_counter(
                 unsigned long cur = 0,
                 unsigned long inc = 10
             ) : m_origin(cur), m_cur(cur), m_inc(inc) {
             }

             void line(std::stringstream const& line0) {
                 m_prog << m_cur << " " << line0.str() << std::endl;
                 m_cur += m_inc;
             }
         };

         #define CT_ASB_LINE(mp_pc, mp_x) \
             { \
                 std::stringstream line0; \
                 line0 << mp_x; \
                 (mp_pc).line(line0); \
             }


         #define CT_ASB_GOSUB(mp_pc0, mp_pc1, mp_indent) \
             CT_ASB_LINE(mp_pc0, mp_indent "GOSUB " << mp_pc1.m_origin) >>> }

    Why macros? My Copilot rewrote them as functions, apparently with no
    loss of functionality:

        void CT_ASB_LINE(program_counter& mp_pc, const std::string& mp_x)
        {
            std::stringstream line0;
            line0 << mp_x;
            (mp_pc).line(line0);
        }


        void CT_ASB_GOSUB(program_counter& mp_pc0, program_counter&
    mp_pc1, const std::string& mp_indent)
        {
            CT_ASB_LINE(mp_pc0, mp_indent + "GOSUB " +
    std::to_string(mp_pc1.m_origin));
        }

    Coming to think about that, why stringstreams at all? In my experience
    just growing a std::string by appending to it is both simpler and faster.

    Hummm. I need to try them, thanks. Wrt stringstreams, I want to be able
    to do shit like this, say:
    ______________________
    // ct_init
    {
        ct_basic::program_counter& PC = pc1;

        unsigned long xxx = 42;


        CT_ASB_LINE(PC, "REM ct_init");
        CT_ASB_LINE(PC, "    PRINT \"ct_init\"");
        CT_ASB_LINE(PC, "    X = " << xxx);
        CT_ASB_LINE(PC, "    PRINT \"from C++: X = \"; X");
        CT_ASB_LINE(PC, "RETURN");
    }
    ______________________

    See the difference? I have to try to compile it using the copilot code.
    Let me try... Nope, does not work, errors for sure. The macros sure seem
    to work. Unless I am missing something?


    I believe you want something like this:

    template<typename T>
    void CT_ASB_ADD(std::stringstream& line, const T& mp_x)
    {
    line << mp_x << " ";
    }

    template<typename T, typename... Args>
    void CT_ASB_ADD(std::stringstream& line, const T& mp_x, const
    Args&... args)
    {
    CT_ASB_ADD(line, mp_x);
    CT_ASB_ADD(line, args...);
    }

    template<typename... Args>
    void CT_ASB_LINE(program_counter& mp_pc, const Args&... args)
    {
    std::stringstream line0;
    CT_ASB_ADD(line0, args...);
    (mp_pc).line(line0);
    }

    Now you can call it with comma, instead of obscure << which would only
    make sense if you know the macro details:

    CT_ASB_LINE(PC, " X = ", xxx);

    instead of former

    CT_ASB_LINE(PC, " X = " << xxx);

    One less character to type, yay!

    --- SoupGate-Linux v1.05
    * Origin: Dragon's Lair ---:- FidoNet<>Usenet Gateway -:--- (3:633/10)
  • From Paavo Helde@3:633/10 to Chris M. Thomasson on Sat Sep 20 10:03:34 2025
    From: eesnimi@osa.pri.ee

    On 9/19/2025 9:41 AM, Chris M. Thomasson wrote:
    On 9/18/2025 3:28 AM, Paavo Helde wrote:
    On 9/17/2025 10:58 PM, Chris M. Thomasson wrote:
    On 9/17/2025 4:43 AM, Paavo Helde wrote:
    On 9/17/2025 2:45 AM, Chris M. Thomasson wrote:
    Humm... Actually, is this use of my macro(s), CT_ASB_*, okay for
    this little code example I wrote to "help" me write AppleSoft
    BASIC? Can you run it, is the code Kosher, so to speak, well, does
    it work for you or not...? Any undefined behavior in my macro? The
    macros seem a bit hackish, but they seem to work okay for now:
    ______________________________________
    [...]
    One less character to type, yay!

    :^D It works like a charm. Thanks Paavo! :^)


    Good to hear! C++ variadic templates from 2011 generating AppleSoft
    BASIC from 1977, why not!

    --- SoupGate-Linux v1.05
    * Origin: Dragon's Lair ---:- FidoNet<>Usenet Gateway -:--- (3:633/10)
  • From red floyd@3:633/10 to Paavo Helde on Sat Sep 20 13:10:29 2025
    From: no.spam.here@its.invalid

    On 9/20/2025 12:03 AM, Paavo Helde wrote:
    On 9/19/2025 9:41 AM, Chris M. Thomasson wrote:
    On 9/18/2025 3:28 AM, Paavo Helde wrote:
    On 9/17/2025 10:58 PM, Chris M. Thomasson wrote:
    On 9/17/2025 4:43 AM, Paavo Helde wrote:
    On 9/17/2025 2:45 AM, Chris M. Thomasson wrote:
    Humm... Actually, is this use of my macro(s), CT_ASB_*, okay for
    this little code example I wrote to "help" me write AppleSoft
    BASIC? Can you run it, is the code Kosher, so to speak, well, does >>>>>> it work for you or not...? Any undefined behavior in my macro? The >>>>>> macros seem a bit hackish, but they seem to work okay for now:
    ______________________________________
    [...]
    One less character to type, yay!

    :^D It works like a charm. Thanks Paavo! :^)


    Good to hear! C++ variadic templates from 2011 generating AppleSoft
    BASIC from 1977, why not!

    In C++17, you can use Folds to reduce that to a single template.

    template<typename... Args>
    void printer(Args&&... args)
    {
    (std::cout << ... << args) << '\n';
    }

    --- SoupGate-Linux v1.05
    * Origin: Dragon's Lair ---:- FidoNet<>Usenet Gateway -:--- (3:633/10)
  • From Paavo Helde@3:633/10 to red floyd on Sun Sep 21 10:42:20 2025
    From: eesnimi@osa.pri.ee

    On 9/20/2025 11:10 PM, red floyd wrote:
    On 9/20/2025 12:03 AM, Paavo Helde wrote:
    On 9/19/2025 9:41 AM, Chris M. Thomasson wrote:
    On 9/18/2025 3:28 AM, Paavo Helde wrote:
    On 9/17/2025 10:58 PM, Chris M. Thomasson wrote:
    On 9/17/2025 4:43 AM, Paavo Helde wrote:
    On 9/17/2025 2:45 AM, Chris M. Thomasson wrote:
    Humm... Actually, is this use of my macro(s), CT_ASB_*, okay for >>>>>>> this little code example I wrote to "help" me write AppleSoft
    BASIC? Can you run it, is the code Kosher, so to speak, well,
    does it work for you or not...? Any undefined behavior in my
    macro? The macros seem a bit hackish, but they seem to work okay >>>>>>> for now:
    ______________________________________
    [...]
    One less character to type, yay!

    :^D It works like a charm. Thanks Paavo! :^)


    Good to hear! C++ variadic templates from 2011 generating AppleSoft
    BASIC from 1977, why not!

    In C++17, you can use Folds to reduce that to a single template.

    template<typename... Args>
    void printer(Args&&... args)
    {
        (std::cout << ... << args) << '\n';
    }


    Thanks, I was not aware this trick!

    My first thought was that this seems way too simple and readable for
    C++. And I was right, it looks like something as trivial as adding a
    space between arguments would complicate this solution so much that it
    does not look cleaner any more than the previous two overloads.

    --- SoupGate-Linux v1.05
    * Origin: Dragon's Lair ---:- FidoNet<>Usenet Gateway -:--- (3:633/10)