• Macro issue...

    From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Tue Sep 16 16:45:15 2025
    From Newsgroup: comp.lang.c++

    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)
    }


    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

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From wij@wyniijj5@gmail.com to comp.lang.c++ on Wed Sep 17 12:01:31 2025
    From Newsgroup: comp.lang.c++

    On Tue, 2025-09-16 at 16:45 -0700, 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 {

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

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

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

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


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


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

    -a-a-a-a-a-a-a-a {

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

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

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

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

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

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

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

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

    -a-a-a-a return 0;
    }
    ______________________________________


    Fwiw, I get an output of:

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


    1000 REM ct_init
    1010-a-a-a-a PRINT "ct_init"
    1020 RETURN


    __________________________
    Complete! Well, time to test the
    generated AppleSoft BASIC
    ---- snippet of class Spu manpage https://sourceforge.net/projects/cscall/ SYNOPSIS
    Except POD types, C structures, all types are declared in namespace Wy.
    #include <CSCall/Sct.h>
    Spu is an object oriented model (class) of Turing Machine that acts like
    a general purpose CPU-based computing machine to provide semantics for
    computing languages (for programming or for program communication). AprCE
    plications are both theoretical and practical.
    The main differences of Spu and general purpose CPU (or TM) is that Spu
    has no -|register-| nor -|flag-| (which, along with others, can be simurCE
    lated), Spu has only a tape and a stack. The tape is initially empty.
    Every object (referred to as tape variable or cell) in the tape is allorCE
    cated via instruction Alloc and identified by a continuous index number.
    Tape variable can be any C++ type, including Spu.
    The instructions of Spu are application definable because they are
    wildly varying from different purposes. Except necessary few, about >30
    instructions are defined for convenience for common usage, see manpage
    Wy.Sct(3wy).
    Documentation following omits the scope name Wy::Sct for each occurrence
    of Spu for clarity.
    ...[cut]
    ----------
    Spu can be used conveniently and efficiently for **ALL** interpreting languages.
    (Of course, some may be less so than the other)
    The following example simulates a piece of assembly (you can design any-aset of instructions you like). Tests are in C++, you need to write parser for the real interpreting language.
    /* Copyright is licensed by GNU LGPL, see file COPYING. by I.J.Wang 2025

    Spu program: Convert string to upper case and dump
    Build: g++ s_tut3.cpp -lwy
    */
    #include <Wy.stdio.h>
    #include "CSCall/Sct.h"
    using namespace Wy;
    using namespace Wy::Sct;
    void t0() {
    Errno r;
    Spu spu;
    // Set Spu program that converts "hello12\n" to upper case
    //
    spu.add_instr( new Alloc<char>()); // 0 (allocate a char object)
    spu.add_instr( new Alloc<char>()); // 1
    spu.add_instr( new Alloc<char>()); // 2
    spu.add_instr( new Alloc<char>()); // 3
    spu.add_instr( new Alloc<char>()); // 4
    spu.add_instr( new Alloc<char>()); // 5
    spu.add_instr( new Alloc<char>()); // 6
    spu.add_instr( new Alloc<char>()); // 7
    spu.add_instr( new Alloc<char>()); // 8
    spu.add_instr( new Alloc<char>()); // 9
    spu.add_instr( new Mov<char,char>(TpVar(0),'h')); // set value of obj
    spu.add_instr( new Mov<char,char>(TpVar(1),'e'));
    spu.add_instr( new Mov<char,char>(TpVar(2),'l'));
    spu.add_instr( new Mov<char,char>(TpVar(3),'l'));
    spu.add_instr( new Mov<char,char>(TpVar(4),'o'));
    spu.add_instr( new Mov<char,char>(TpVar(5),'1'));
    spu.add_instr( new Mov<char,char>(TpVar(6),'2'));
    spu.add_instr( new Mov<char,char>(TpVar(7),'\n'));
    spu.add_instr( new Mov<char,char>(TpVar(8),0));
    spu.add_instr( new Alloc<VarPtr>()); // alloc a 'pointer' arg
    spu.add_instr( new Mov<VarPtr,char>(TpVar(-1),0)); // set arg=0
    spu.add_instr( new Call(Label(&&to_upper)) ); // call the funcion
    spu.add_instr( new Free<VarPtr>() ); // free arg
    spu.add_instr( new Fin(0) ); // exit(0) to caller
    // to_upper is a function that convert Obj(-1) pointed 'string' to uppercase
    // and dump it (to cout)
    to_upper:; SPU_INSTR_LAB(spu,&&to_upper);
    spu.add_instr( new Jmp(Label(&&ck_nxt)) );
    ck_char:; SPU_INSTR_LAB(spu,&&ck_char);
    spu.add_instr( new Jb<char>( TpVar(-1), 'a', Label(&&print_char)));
    spu.add_instr( new Ja<char>( TpVar(-1), 'z', Label(&&print_char)));
    spu.add_instr( new Sub<char,char>(TpVar(-1),32)); // to upper
    print_char:; SPU_INSTR_LAB(spu,&&print_char);
    spu.add_instr( new Dump<char>( TpVar(-1) ));
    spu.add_instr( new Inc<VarPtr>( TpVar(-1) )); // point to next object
    ck_nxt:; SPU_INSTR_LAB(spu,&&ck_nxt);
    spu.add_instr( new Jnz<char>( TpVar(-1), Label(&&ck_char)) );
    spu.add_instr( new Ret() );
    // Note: If implemented, 'the real assembly' would look much better
    if((r=fix_label(spu))!=Ok) {
    WY_THROW(r);
    }
    for(size_t i=0; i<spu.program.size(); ++i) { // print the program src
    cout << '(' << i << ") "
    << spu.program[i]->notation() << WY_ENDL;
    }
    // Note: If non-memcpy-able classes were allocated (not in the above program),
    // we need to Free them
    if((r=spu.run( InstrIdx(0) ))!=Ok) {
    WY_THROW(r);
    }
    };
    int main(int argc, const char* argv[])
    try {
    t0();
    cout << "OK" WY_ENDL;
    return 0;
    }
    catch(const Errno& e) {
    cerr << wrd(e) << WY_ENDL;
    return -1; // e.c_errno();
    }
    catch(...) {
    cerr << "main() caught(...)" WY_ENDL;
    throw;
    };
    ------
    []$ g++ s_tut3.cpp -lwy
    []$ ./a.out
    (0) Wy::Sct::Alloc<char>()
    (1) Wy::Sct::Alloc<char>()
    (2) Wy::Sct::Alloc<char>()
    (3) Wy::Sct::Alloc<char>()
    (4) Wy::Sct::Alloc<char>()
    (5) Wy::Sct::Alloc<char>()
    (6) Wy::Sct::Alloc<char>()
    (7) Wy::Sct::Alloc<char>()
    (8) Wy::Sct::Alloc<char>()
    (9) Wy::Sct::Alloc<char>()
    (10) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(0),104)
    (11) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(1),101)
    (12) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(2),108)
    (13) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(3),108)
    (14) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(4),111)
    (15) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(5),49)
    (16) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(6),50)
    (17) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(7),10)
    (18) Wy::Sct::Mov<char, char>(Wy::Sct::TpVar(8),0)
    (19) Wy::Sct::Alloc<Wy::Sct::VarPtr>()
    (20) Wy::Sct::Mov<Wy::Sct::VarPtr, char>(Wy::Sct::TpVar(-1),0)
    (21) Wy::Sct::Call(Wy::Sct::InstrIdx(24))
    (22) Wy::Sct::Free<Wy::Sct::VarPtr>()
    (23) Wy::Sct::Fin(0)
    (24) Wy::Sct::Jmp(Wy::Sct::InstrIdx(30))
    (25) Wy::Sct::Jb<char>(Wy::Sct::TpVar(-1),97,Wy::Sct::InstrIdx(28))
    (26) Wy::Sct::Ja<char>(Wy::Sct::TpVar(-1),122,Wy::Sct::InstrIdx(28))
    (27) Wy::Sct::Sub<char, char>(Wy::Sct::TpVar(-1),32)
    (28) Wy::Sct::Dump<char>(Wy::Sct::TpVar(-1))
    (29) Wy::Sct::Inc<Wy::Sct::VarPtr>(Wy::Sct::TpVar(-1))
    (30) Wy::Sct::Jnz<char>(Wy::Sct::TpVar(-1),Wy::Sct::InstrIdx(25))
    (31) Wy::Sct::Ret()
    HELLO12
    OK
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Wed Sep 17 14:43:06 2025
    From Newsgroup: comp.lang.c++

    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 {

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

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

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

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


    -a-a-a #define CT_ASB_GOSUB(mp_pc0, mp_pc1, mp_indent) \
    -a-a-a-a-a-a-a 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()
    {
    -a-a-a {
    -a-a-a-a-a-a-a std::cout << "ctBasic testing 123... :^)\n";
    -a-a-a-a-a-a-a std::cout << "__________________________\n";

    -a-a-a-a-a-a-a {

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

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

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

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

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

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

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

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

    -a-a-a return 0;
    }
    ______________________________________


    Fwiw, I get an output of:

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


    1000 REM ct_init
    1010-a-a-a-a PRINT "ct_init"
    1020 RETURN


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


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Wed Sep 17 12:58:54 2025
    From Newsgroup: comp.lang.c++

    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 {

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

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

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

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


    -a-a-a-a #define CT_ASB_GOSUB(mp_pc0, mp_pc1, mp_indent) \
    -a-a-a-a-a-a-a-a 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:

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


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

    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?

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Thu Sep 18 13:28:37 2025
    From Newsgroup: comp.lang.c++

    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 {

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

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

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

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


    -a-a-a-a #define CT_ASB_GOSUB(mp_pc0, mp_pc1, mp_indent) \
    -a-a-a-a-a-a-a-a 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:

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


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

    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
    {
    -a-a-a ct_basic::program_counter& PC = pc1;

    -a-a-a unsigned long xxx = 42;


    -a-a-a CT_ASB_LINE(PC, "REM ct_init");
    -a-a-a CT_ASB_LINE(PC, "-a-a-a PRINT \"ct_init\"");
    -a-a-a CT_ASB_LINE(PC, "-a-a-a X = " << xxx);
    -a-a-a CT_ASB_LINE(PC, "-a-a-a PRINT \"from C++: X = \"; X");
    -a-a-a 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!
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Thu Sep 18 11:57:29 2025
    From Newsgroup: comp.lang.c++

    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:
    [...]
    -a-a-a-a CT_ASB_LINE(PC, "REM ct_init");
    -a-a-a-a CT_ASB_LINE(PC, "-a-a-a PRINT \"ct_init\"");
    -a-a-a-a CT_ASB_LINE(PC, "-a-a-a X = " << xxx);
    -a-a-a-a CT_ASB_LINE(PC, "-a-a-a PRINT \"from C++: X = \"; X");
    -a-a-a-a 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:
    [...]

    Seems to work okay. I need to test it against something that builds one
    of my more "complex" test programs.


    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, "-a-a-a X = ", xxx);

    instead of former

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

    One less character to type, yay!

    ROFL! Yay! and no Macros. Thanks. :^)

    I think it should work fine, no time right now to test it right now.
    Will get back to you. It's funny. Programming BASIC in this C++ "realm"
    is easier than typing it into a Apple iie prompt. lol.

    The only reason why I made this "thing" to begin with is to help me port
    my n-ary vector field to AppleSoft BASIC, and run the sucker. I wanted
    to show that the algo is portable. :^)
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Thu Sep 18 23:41:17 2025
    From Newsgroup: comp.lang.c++

    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! :^)

    Fwiw, here is some of my AppleSoft BASIC code I generated with it. A
    recursive von Koch fractal renderer. Getting the recursion right was a
    bit tricky, but it works fine.

    https://pastebin.com/raw/Effeg8cK
    (raw pastebin link, no ads and shit)



    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Sat Sep 20 10:03:34 2025
    From Newsgroup: comp.lang.c++

    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!
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From red floyd@no.spam.here@its.invalid to comp.lang.c++ on Sat Sep 20 13:10:29 2025
    From Newsgroup: comp.lang.c++

    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';
    }

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Sun Sep 21 10:42:20 2025
    From Newsgroup: comp.lang.c++

    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)
    {
    -a-a-a (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.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Mon Sep 22 22:14:35 2025
    From Newsgroup: comp.lang.c++

    On 9/20/2025 1: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)
    {
    -a-a-a (std::cout << ... << args) << '\n';
    }


    Thanks! Did not know about this either. Folds... Humm... Thanks again.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Tue Sep 23 19:50:07 2025
    From Newsgroup: comp.lang.c++

    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!

    :^D Fwiw, I found an inefficacy in my BASIC code. I should be rendering
    one line, not all of the damn segments! One call vs four... Sigh.
    Finding interesting shit in the generate code is fun. ;^)

    Retro?
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Wed Sep 24 13:18:40 2025
    From Newsgroup: comp.lang.c++

    On 9/23/2025 7:50 PM, Chris M. Thomasson wrote:
    [...]
    :^D Fwiw, I found an inefficacy in my BASIC code.

    I meant inefficiency, god damn typos! Shit man. It still creates the
    fractal, but it should only be using one call to my ct_plot_line
    function in the generated BASIC code recursion. Makes it go faster for
    sure. I think I should create a hash list keyed on function name so I
    can lookup a name and get its line number.

    Strange. Trying to improve my C++ code that generates 1977 code? ;^)
    rofl. Anyway. well, lol. Or even look up a line number and get a
    function name if the line number is a target for a GOSUB. Shit like
    that. lol.


    I should be rendering
    one line, not all of the damn segments! One call vs four... Sigh.
    Finding interesting shit in the generate code is fun. ;^)

    Retro?

    --- Synchronet 3.21a-Linux NewsLink 1.2