Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
qb64pe's translation of .bas to .cpp ?
#6
(01-21-2026, 12:27 PM)Fifi Wrote:
(01-21-2026, 10:57 AM)SMcNeill Wrote: Qb64pe.bas
Hi SMcNeill,

Yes, I do assume it's in qb64pe.bas, but there are so few comments that I don't know where to look.

BTW, I've never seen such a long source code with so few comments, and I give the developers my two thumbs up for maintaining and improving this program!

So, could you tell me the line number in qb64pe.bas where the Basic keyword translator begins? 

For example, where can I find the translation of QB64PE keywords, such as "Print" or "Input," etc., into their C++ equivalents? 

Is there, for instance, a conversion table listing all the QB64 keywords and their respective C++ translations?

Just out of curiosity.

Cheers.
Fifi

It's.... the whole thing.  And all the subdirectories and help files all added in as well.   For example, if you want PRINT, do a search for:

 firstelement$ = "PRINT"

Code: (Select All)
                If firstelement$ = "PRINT" Then 'file print
                    If n > 1 Then
                        If getelement$(a$, 2) = "#" Then
                            xfileprint a$, ca$, n
                            If Error_Happened Then GoTo errmes
                            l$ = tlayout$
                            layoutdone = 1: If Len(layout$) Then layout$ = layout$ + sp + l$ Else layout$ = l$
                            GoTo finishedline
                        End If '#
                    End If 'n>1
                End If '"print"

                If firstelement$ = "PRINT" Or firstelement$ = "LPRINT" Then
                    If secondelement$ <> "USING" Then 'check to see if we need to auto-add semicolons
                        elementon = 2
                        redosemi:
                        For i = elementon To n - 1
                            nextchar$ = getelement$(a$, i + 1)
                            If nextchar$ <> ";" And nextchar$ <> "," And nextchar$ <> "+" And nextchar$ <> ")" Then
                                temp1$ = getelement$(a$, i)
                                beginpoint = InStr(beginpoint, temp1$, Chr$(34))
                                endpoint = InStr(beginpoint + 1, temp1$, Chr$(34) + ",")
                                If beginpoint <> 0 And endpoint <> 0 Then 'if we have both positions
                                    'Quote without semicolon check (like PRINT "abc"123)
                                    textlength = endpoint - beginpoint - 1
                                    textvalue$ = Mid$(temp1$, endpoint + 2, Len(_ToStr$(textlength)))
                                    If Val(textvalue$) = textlength Then
                                        insertelements a$, i, ";"
                                        insertelements ca$, i, ";"
                                        n = n + 1
                                        elementon = i + 2 'just an easy way to reduce redundant calls to the routine
                                        GoTo redosemi
                                    End If
                                End If
                                If temp1$ <> "USING" Then
                                    If Left$(LTrim$(nextchar$), 1) = Chr$(34) Then
                                        If temp1$ <> ";" And temp1$ <> "," And temp1$ <> "+" And temp1$ <> "(" Then
                                            insertelements a$, i, ";"
                                            insertelements ca$, i, ";"
                                            n = n + 1
                                            elementon = i + 2 'just an easy way to reduce redundant calls to the routine
                                            GoTo redosemi
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If

                    xprint a$, ca$, n
                    If Error_Happened Then GoTo errmes
                    l$ = tlayout$
                    layoutdone = 1: If Len(layout$) Then layout$ = layout$ + sp + l$ Else layout$ = l$
                    GoTo finishedline
                End If

Then you can see that if you're dealing with a file being printed, the first IF deals with that and sends off the translation to:                              xfileprint a$, ca$, n

For the screen printing, that's done in the next statement and it gets handed off to                      xprint a$, ca$, n

If you want to look at xprint, here it is:

Code: (Select All)
Sub xprint (a$, ca$, n)
    u$ = _ToStr$(uniquenumber)

    l$ = SCase$("Print")
    If Asc(a$) = 76 Then lp = 1: lp$ = "l": l$ = SCase$("LPrint"): WriteBufLine MainTxtBuf, "tab_LPRINT=1;": SetDependency DEPENDENCY_PRINTER '"L"

    'PRINT USING?
    If n >= 2 Then
        If getelement(a$, 2) = "USING" Then
            'get format string
            i = 3
            pujump:
            l$ = l$ + sp + SCase$("Using")
            e$ = "": b = 0: puformat$ = ""
            For i = i To n
                a2$ = getelement(ca$, i)
                If a2$ = "(" Then b = b + 1
                If a2$ = ")" Then b = b - 1
                If b = 0 Then
                    If a2$ = "," Then Give_Error "Expected PRINT USING formatstring ; ...": Exit Sub
                    If a2$ = ";" Then
                        e$ = fixoperationorder$(e$)
                        If Error_Happened Then Exit Sub
                        l$ = l$ + sp + tlayout$ + sp2 + ";"
                        e$ = evaluate(e$, typ)
                        If Error_Happened Then Exit Sub
                        If (typ And ISREFERENCE) Then e$ = refer(e$, typ, 0)
                        If Error_Happened Then Exit Sub
                        If (typ And ISSTRING) = 0 Then Give_Error "Expected PRINT USING formatstring ; ...": Exit Sub
                        puformat$ = e$
                        Exit For
                    End If ';
                End If 'b
                If Len(e$) Then e$ = e$ + sp + a2$ Else e$ = a2$
            Next
            If puformat$ = "" Then Give_Error "Expected PRINT USING formatstring ; ...": Exit Sub
            If i = n Then Give_Error "Expected PRINT USING formatstring ; ...": Exit Sub
            'create build string
            If TQBSset = 0 Then
                WriteBufLine MainTxtBuf, "tqbs=qbs_new(0,0);"
            Else
                WriteBufLine MainTxtBuf, "qbs_set(tqbs,qbs_new_txt_len(" + Chr$(34) + Chr$(34) + ",0));"
            End If
            'set format start/index variable
            WriteBufLine MainTxtBuf, "tmp_long=0;" 'scan format from beginning


            'create string to hold format in for multiple references
            puf$ = "print_using_format" + u$
            If subfunc = "" Then
                WriteBufLine DataTxtBuf, "static qbs *" + puf$ + ";"
            Else
                WriteBufLine DataTxtBuf, "qbs *" + puf$ + ";"
            End If
            WriteBufLine MainTxtBuf, puf$ + "=qbs_new(0,0); qbs_set(" + puf$ + "," + puformat$ + ");"
            WriteBufLine MainTxtBuf, "if (is_error_pending()) goto skip_pu" + u$ + ";"

            'print expressions
            b = 0
            e$ = ""
            last = 0
            For i = i + 1 To n
                a2$ = getelement(ca$, i)
                If a2$ = "(" Then b = b + 1
                If a2$ = ")" Then b = b - 1
                If b = 0 Then
                    If a2$ = ";" Or a2$ = "," Then
                        printulast:
                        e$ = fixoperationorder$(e$)
                        If Error_Happened Then Exit Sub
                        If last Then l$ = l$ + sp + tlayout$ Else l$ = l$ + sp + tlayout$ + sp2 + a2$
                        e$ = evaluate(e$, typ)
                        If Error_Happened Then Exit Sub
                        If (typ And ISREFERENCE) Then e$ = refer(e$, typ, 0)
                        If Error_Happened Then Exit Sub
                        If typ And ISSTRING Then

                            If Left$(e$, 9) = "func_tab(" Or Left$(e$, 9) = "func_spc(" Then

                                'TAB/SPC exception
                                'note: position in format-string must be maintained
                                '-print any string up until now
                                WriteBufLine MainTxtBuf, "qbs_" + lp$ + "print(tqbs,0);"
                                '-print e$
                                WriteBufLine MainTxtBuf, "qbs_set(tqbs," + e$ + ");"
                                WriteBufLine MainTxtBuf, "if (is_error_pending()) goto skip_pu" + u$ + ";"
                                If lp Then WriteBufLine MainTxtBuf, "lprint_makefit(tqbs);" Else WriteBufLine MainTxtBuf, "makefit(tqbs);"
                                WriteBufLine MainTxtBuf, "qbs_" + lp$ + "print(tqbs,0);"
                                '-set length of tqbs to 0
                                WriteBufLine MainTxtBuf, "tqbs->len=0;"

                            Else

                                'regular string
                                WriteBufLine MainTxtBuf, "tmp_long=print_using(" + puf$ + ",tmp_long,tqbs," + e$ + ");"

                            End If



                        Else 'not a string
                            If typ And ISFLOAT Then
                                If (typ And 511) = 32 Then WriteBufLine MainTxtBuf, "tmp_long=print_using_single(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                                If (typ And 511) = 64 Then WriteBufLine MainTxtBuf, "tmp_long=print_using_double(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                                If (typ And 511) > 64 Then WriteBufLine MainTxtBuf, "tmp_long=print_using_float(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            Else
                                If ((typ And 511) = 64) And (typ And ISUNSIGNED) <> 0 Then
                                    WriteBufLine MainTxtBuf, "tmp_long=print_using_uinteger64(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                                Else
                                    WriteBufLine MainTxtBuf, "tmp_long=print_using_integer64(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                                End If
                            End If
                        End If 'string/not string
                        WriteBufLine MainTxtBuf, "if (is_error_pending()) goto skip_pu" + u$ + ";"
                        e$ = ""
                        If last Then Exit For
                        GoTo printunext
                    End If
                End If
                If Len(e$) Then e$ = e$ + sp + a2$ Else e$ = a2$
                printunext:
            Next
            If e$ <> "" Then a2$ = "": last = 1: GoTo printulast
            WriteBufLine MainTxtBuf, "skip_pu" + u$ + ":"
            'check for errors
            WriteBufLine MainTxtBuf, "if (is_error_pending()){"
            WriteBufLine MainTxtBuf, "g_tmp_long=new_error; new_error=0; qbs_" + lp$ + "print(tqbs,0); new_error=g_tmp_long;"
            WriteBufLine MainTxtBuf, "}else{"
            If a2$ = "," Or a2$ = ";" Then nl = 0 Else nl = 1 'note: a2$ is set to the last element of a$
            WriteBufLine MainTxtBuf, "qbs_" + lp$ + "print(tqbs," + _ToStr$(nl) + ");"
            WriteBufLine MainTxtBuf, "}"
            WriteBufLine MainTxtBuf, "qbs_free(tqbs);"
            WriteBufLine MainTxtBuf, "qbs_free(" + puf$ + ");"
            WriteBufLine MainTxtBuf, "skip" + u$ + ":"
            WriteBufLine MainTxtBuf, cleanupstringprocessingcall$ + "0);"
            If lp Then WriteBufLine MainTxtBuf, "tab_LPRINT=0;"
            tlayout$ = l$
            Exit Sub
        End If
    End If
    'end of print using code

    b = 0
    e$ = ""
    last = 0
    WriteBufLine MainTxtBuf, "tqbs=qbs_new(0,0);" 'initialize the temp string
    TQBSset = -1 'set the temporary flag so we don't create a temp string twice, in case USING comes after something
    For i = 2 To n
        a2$ = getelement(ca$, i)
        If a2$ = "(" Then b = b + 1
        If a2$ = ")" Then b = b - 1
        If b = 0 Then
            If a2$ = ";" Or a2$ = "," Or UCase$(a2$) = "USING" Then
                printlast:

                If UCase$(a2$) = "USING" Then
                    If e$ <> "" Then gotopu = 1 Else i = i + 1: GoTo pujump
                End If

                If Len(e$) Then
                    ebak$ = e$
                    pnrtnum = 0
                    printnumber:
                    e$ = fixoperationorder$(e$)
                    If Error_Happened Then Exit Sub
                    If pnrtnum = 0 Then
                        If last Then l$ = l$ + sp + tlayout$ Else l$ = l$ + sp + tlayout$ + sp2 + a2$
                    End If
                    e$ = evaluate(e$, typ)
                    If Error_Happened Then Exit Sub
                    If (typ And ISSTRING) = 0 Then
                        'not a string expression!
                        e$ = "STR$" + sp + "(" + sp + ebak$ + sp + ")" + sp + "+" + sp + Chr$(34) + " " + Chr$(34)
                        pnrtnum = 1
                        GoTo printnumber
                    End If
                    If (typ And ISREFERENCE) Then e$ = refer(e$, typ, 0)
                    If Error_Happened Then Exit Sub
                    WriteBufLine MainTxtBuf, "qbs_set(tqbs," + e$ + ");"
                    WriteBufLine MainTxtBuf, "if (is_error_pending()) goto skip" + u$ + ";"
                    If lp Then WriteBufLine MainTxtBuf, "lprint_makefit(tqbs);" Else WriteBufLine MainTxtBuf, "makefit(tqbs);"
                    WriteBufLine MainTxtBuf, "qbs_" + lp$ + "print(tqbs,0);"
                Else
                    If a2$ = "," Then l$ = l$ + sp + a2$
                    If a2$ = ";" Then
                        If Right$(l$, 1) <> ";" Then l$ = l$ + sp + a2$ 'concat ;; to ;
                    End If
                End If 'len(e$)
                If a2$ = "," Then WriteBufLine MainTxtBuf, "tab();"
                e$ = ""

                If gotopu Then i = i + 1: GoTo pujump

                If last Then
                    WriteBufLine MainTxtBuf, "qbs_" + lp$ + "print(nothingstring,1);" 'go to new line
                    Exit For
                End If

                GoTo printnext
            End If 'a2$
        End If 'b=0

        If Len(e$) Then e$ = e$ + sp + a2$ Else e$ = a2$
        printnext:
    Next
    If Len(e$) Then a2$ = "": last = 1: GoTo printlast
    If n = 1 Then WriteBufLine MainTxtBuf, "qbs_" + lp$ + "print(nothingstring,1);"
    WriteBufLine MainTxtBuf, "skip" + u$ + ":"
    WriteBufLine MainTxtBuf, "qbs_free(tqbs);"
    WriteBufLine MainTxtBuf, cleanupstringprocessingcall$ + "0);"
    If lp Then WriteBufLine MainTxtBuf, "tab_LPRINT=0;"
    tlayout$ = l$
End Sub

As you can see, it does a ton of WriteBufLine calls -- those are where the translation is taking place and it's writing to the translation buffer, which it only saves to disk before actually compiling to reduce wear and tear on any SSD drives.

If you look in subs_functions.bas, you'll see where a lot of the commands that can be almost directly processed are located.  These are all handled via QB64PE's own internal language/syntax, which takes a bit to learn and sort out.

Code: (Select All)
    clearid
    id.n = "Sin"
    id.subfunc = 1
    id.callname = "std::sin"
    id.args = 1
    id.arg = MKL$(FLOATTYPE - ISPOINTER)
    id.ret = FLOATTYPE - ISPOINTER
    id.hr_syntax = "SIN(radian_angle!)"
    regid

    clearid
    id.n = "Cos"
    id.subfunc = 1
    id.callname = "std::cos"
    id.args = 1
    id.arg = MKL$(FLOATTYPE - ISPOINTER)
    id.ret = FLOATTYPE - ISPOINTER
    id.hr_syntax = "COS(radian_angle!)"
    regid

    clearid
    id.n = "Tan"
    id.subfunc = 1
    id.callname = "std::tan"
    id.args = 1
    id.arg = MKL$(FLOATTYPE - ISPOINTER)
    id.ret = FLOATTYPE - ISPOINTER
    id.hr_syntax = "TAN(radian_angle!)"
    regid

    clearid
    id.n = "Atn"
    id.subfunc = 1
    id.callname = "std::atan"
    id.args = 1
    id.arg = MKL$(FLOATTYPE - ISPOINTER)
    id.ret = FLOATTYPE - ISPOINTER
    id.hr_syntax = "ATN(tangent!)"
    regid

id.n is the QB64 keyword name.
id.subfunc tells us if it's a SUB or FUNCTION and whether to expect a return value or not.
id.callname is the C-translated name which you'll find in libqb.cpp or one of the subfolders there.
id.args is the number of parameters which we're going to pass
id.arg is the type of parameters we're passing
id.ret is the type of value we're getting back
id.hr_syntax is the help row syntax which shows up as you're typing to help you remember what the command's syntax is quickly.
regid then registers that command for processing.

So you type ATN(.1), it gets translated to std:atan(1).

So not only are you looking in qb64pe.bas, but also in libqb.cpp and all the subfolders attached to it, to process your single line translation.

It's the whole thing, scattered in 50 different areas, and all working together to process each command independently.
Reply


Messages In This Thread
qb64pe's translation of .bas to .cpp ? - by Fifi - 01-20-2026, 04:37 AM
RE: qb64pe's translation of .bas to .cpp ? - by SMcNeill - 01-21-2026, 01:11 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  QB64PE Excel-type spreadsheet supporting formulas and QB64PE macros? madscijr 33 1,564 01-30-2026, 12:28 AM
Last Post: madscijr
  Compile error when .bas name is same as a directory (linux) Dav 3 782 10-18-2024, 03:32 PM
Last Post: Kernelpanic
  My latest acheivement: PETE.BAS Pete 14 2,524 12-28-2022, 02:03 PM
Last Post: OldMoses

Forum Jump:


Users browsing this thread: 1 Guest(s)