GPT-4 is amazing

Started by Theo Gottwald, July 07, 2023, 07:44:15 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

Before i start let me add that the difference between GPT 3.5 - which is free - and GPT-4 which is paid is really large. This picture may not be totally accurate but GPT-4 can really help in debugging, pretty-printing, code-conversion, it will make repeating tasks for you. While GPT 3.5 is more a toy in that case and will not be of much help in coding -yet it can help with rewriting the manual.

GPTDiff.jpg

So if you want an coding assistant you need to get GPT-4 and this means you pay $20 to Open AI - which is what i do.

Or you buy it here and do "Pay per type":

Open Playground



Here is my prompt:
I want you to act as a software developer. I will provide some code enclosed in ## and you will check it line by line for mistakes. Before we start make a list with the important things that you will check for. The code will be Powerbasic. Please confirm you understand and ask if you have questions.
Please only show me errors and a improved version.

Following some Subprogramms, first my original version and second the "improved Version" using GPT4.

Original my programming style:
' GetVitualDesktop-Rect-Size or Workarea-Size, if wa=1 then result is size of workarea
'
SUB WR_CV(BYREF xs AS LONG, BYREF ys AS LONG,OPT BYVAL wa AS LONG)
 LOCAL T01,T03,T04,T05,T06 AS LONG
 LOCAL r AS rect
 IF (wa<>0) THEN  GOTO war
 T01=GetSystemMetrics(%SM_CMONITORS)
 xs=MAX&(GetSystemMetrics(%SM_CXFULLSCREEN),GetSystemMetrics(%SM_XVIRTUALSCREEN))
 ys=MAX&(GetSystemMetrics(%SM_CYFULLSCREEN),GetSystemMetrics(%SM_YVIRTUALSCREEN))
 SELECT CASE AS LONG T01
    CASE 0,1:xs=GetSystemMetrics(%SM_CXFULLSCREEN):ys=GetSystemMetrics(%SM_CYFULLSCREEN):GOTO enx
    CASE 2,3:xs=0:FOR T03=1 TO T01:WR_CZ(T03,T04,T05,T06):ys=MIN&(ys,T05):xs=xs+T04:NEXT T03
    CASE ELSE
      GOTO enx
    END SELECT
    IF (xs>0) AND (ys>0) THEN GOTO enx
    war:
    SystemParametersInfo %SPI_GETWORKAREA, 0, r, 0:WR_MM(r,xs,ys):GOTO enx
 enx:
END SUB

Here is what i got, i think its more like the public programming style, not Pierre but Jose-like.

' GetVirtualDesktopSize - Retrieves the size of the virtual desktop or work area.
' screenWidth - The width of the virtual desktop or work area.
' screenHeight - The height of the virtual desktop or work area.
' isWorkArea - Optional parameter. If set to 1, the function returns the size of the work area instead of the virtual desktop.
SUB GetVirtualDesktopSize(BYREF screenWidth AS LONG, BYREF screenHeight AS LONG, OPTIONAL BYVAL isWorkArea AS LONG)
    LOCAL monitorCount, i, WIDTH, height, temp AS LONG
    LOCAL workArea AS RECT

    IF isWorkArea <> 0 THEN
        ' Get work area size
        SystemParametersInfo %SPI_GETWORKAREA, 0, workArea, 0
        screenWidth = workArea.nRight - workArea.nLeft
        screenHeight = workArea.nBottom - workArea.nTop
        EXIT SUB
    END IF

    ' Get the number of monitors
    monitorCount = GetSystemMetrics(%SM_CMONITORS)

    ' Get the size of the virtual desktop
    SELECT CASE monitorCount
        CASE 0, 1
            screenWidth = GetSystemMetrics(%SM_CXFULLSCREEN)
            screenHeight = GetSystemMetrics(%SM_CYFULLSCREEN)
        CASE 2, 3
            screenWidth = 0
            screenHeight = GetSystemMetrics(%SM_CYFULLSCREEN)
            FOR i = 1 TO monitorCount
                ' Assuming WR_CZ is a function that gets monitor dimensions
                WR_CZ(i, WIDTH, height, temp)
                screenHeight = MIN(screenHeight, height)
                screenWidth = screenWidth + WIDTH
            NEXT i
        CASE ELSE
            ' Handle other cases or errors
    END SELECT
END SUB                       

Here is another Sample, see how GPT-4 even assumes what certain Macros will do.
Besides some criticism on my near to perfect Coding style :-)


Orginal Code:
##
SUB WR_CW(BYVAL T01 AS LONG,BYVAL T02 AS LONG,BYVAL T03 AS LONG,BYVAL T04 AS LONG,BYVAL T05 AS LONG)
 REGISTER x AS LONG,y AS LONG
 LOCAL r AS rect
 LOCAL xs,ys AS LONG
 IF (GetWindowRect(T01,r)=0) THEN GOTO enx
 WR_MI(r,x,y,xs,ys)
 IF T02=-1 THEN T02=x
 IF T03=-1 THEN T03=y
 IF T04=-1 THEN T04=xs
 IF T05=-1 THEN T05=ys
 MoveWindow T01,T02,T03,T04,T05,%True
 enx:
END SUB
##

Follows the rewritten Code:

In the provided code, there are several areas that can be improved for clarity, maintainability, and best practices:

The comments at the top are missing. It's good practice to include a brief description of what the subroutine does.

The variable names T01, T02, T03, T04, T05, xs, and ys are not very descriptive. It's good practice to use meaningful names for variables and parameters.

The use of GOTO is generally discouraged as it can make the code less readable and harder to maintain. It's better to use structured control statements like IF, ELSE, etc.

The subroutine lacks error handling. It's good practice to include error handling to deal with unexpected situations.

The use of WR_MI function is unclear. Make sure it is defined somewhere in the code.

Here's an improved version of the subroutine:

' MoveWindowToPosition - Moves and resizes a window.
' hWnd - Handle to the window to be moved.
' xPos - The new x-coordinate of the window.
' yPos - The new y-coordinate of the window.
' width - The new width of the window.
' height - The new height of the window.
' Note: Passing -1 for xPos, yPos, width, or height will keep the current value.
SUB MoveWindowToPosition(BYVAL hWnd AS LONG, BYVAL xPos AS LONG, BYVAL yPos AS LONG, BYVAL width AS LONG, BYVAL height AS LONG)
    LOCAL windowRect AS RECT
    LOCAL currentX, currentY, currentWidth, currentHeight AS LONG
   
    ' Get the current position and size of the window
    IF GetWindowRect(hWnd, windowRect) = 0 THEN
        ' Handle error
        EXIT SUB
    END IF
   
    ' Assuming WR_MI is a function that gets window dimensions
    WR_MI(windowRect, currentX, currentY, currentWidth, currentHeight)
   
    ' Set the new position and size
    IF xPos = -1 THEN xPos = currentX
    IF yPos = -1 THEN yPos = currentY
    IF width = -1 THEN width = currentWidth
    IF height = -1 THEN height = currentHeight
   
    ' Move the window
    MoveWindow hWnd, xPos, yPos, width, height, %True
END SUB

Changes made:

Added a descriptive comment at the top explaining what the subroutine does.
Changed the parameter and variable names to be more descriptive.
Replaced the GOTO statement with structured control statements.
Added error handling.
Assumed WR_MI is a function that gets window dimensions (it should be defined elsewhere in the code).

Ok, now lets give him ASM-Code.


FUNCTION BMBinSearch(BYREF U01 AS STRING,BYREF U02 AS STRING,OPT BYVAL startpos AS LONG) AS LONG
 #REGISTER NONE

 LOCAL  lpSource AS LONG
 LOCAL  srcLngth AS LONG
 LOCAL  lpSubStr AS LONG
 LOCAL  subLngth AS LONG

      lpSource=STRPTR(U01):srcLngth=LEN(lpSource)
      lpSubStr=STRPTR(U02):subLngth=LEN(lpSubStr)

      LOCAL eLen    AS DWORD
      LOCAL cval    AS DWORD
      LOCAL shift_table AS STRING * 1024

      ! cmp subLngth, 1
      ! jg OKsize
      ! mov eax, -2                ; string too short, must be > 1
      ! jmp Cleanup
    OKsize:

      ! mov esi, lpSource
      ! add esi, srcLngth
      ! sub esi, subLngth
      ! mov eLen, esi            ; set Exit Length

    ' ----------------------------------------
    ' load shift table with value in subLngth
    ' ----------------------------------------
      ! mov ecx, 256
      ! mov eax, subLngth
      ! lea edi, shift_table
      ! rep stosd

    ' ----------------------------------------------
    ' load decending count values into shift table
    ' ----------------------------------------------
      ! mov ecx, subLngth          ; SubString length in ECX
      ! dec ecx                    ; correct for zero based index
      ! mov esi, lpSubStr          ; address of SubString in ESI
      ! lea edi, shift_table

      ! xor eax, eax

    Write_Shift_Chars:
      ! mov al, [esi]              ; get the character
      ! inc esi
      ! mov [edi+eax*4], ecx        ; write shift for each character
      ! dec ecx                    ; to ascii location in table
      ! jnz Write_Shift_Chars

    ' -----------------------------
    ' set up for main compare loop
    ' -----------------------------
      ! mov ecx, subLngth
      ! dec ecx
      ! mov cval, ecx

      ! mov esi, lpSource
      ! mov edi, lpSubStr
      ! add esi, startpos          ; add starting position

      ! mov edx, subLngth          ; pattern length in edx

      ! jmp Cmp_Loop

  ' *********************** Loop Code ***************************

    Set_Suffix_Shift:
      ! add eax, ecx                ; add CMP count
      ! sub eax, cval              ; sub loop count
      ! cmp eax, 0                  ; test eax for zero
      ! jg  Add_Suffix_Shift
      ! mov eax, 1                  ; minimum shift is 1

    Add_Suffix_Shift:
      ! add esi, eax                ; add suffix shift

    Pre_Cmp:
      ! cmp esi, eLen              ; test exit length
      ! ja  No_Match
      ! xor eax, eax                ; reset EAX
      ! mov ecx, cval              ; reset counter in compare loop

    Cmp_Loop:
      ! mov al, [esi+ecx]
      ! cmp al, [edi+ecx]          ; cmp characters in ESI / EDI
      ! jne Get_Shift              ; if not equal, get next shift
      ! dec ecx
      ! jns Cmp_Loop

      ! jmp XMatch

    Get_Shift:
      ! mov eax, shift_table[eax*4] ; get char shift value
      ! cmp eax, edx                ; is eax pattern length ?
      ! jne Set_Suffix_Shift        ; if not, jump to Calc_Suffix_Shift
      ! lea esi, [esi+ecx+1]        ; add bad char shift
      ! jmp Pre_Cmp

  ' ***************************************************************

    XMatch:
      ! sub esi, lpSource          ; sub source from ESI
      ! mov eax, esi                ; put length in eax
      ! jmp Cleanup

    No_Match:
      ! mov eax, -1                ; set value for no match

    Cleanup:

      ! mov FUNCTION, eax

  END FUNCTION
                                               

So here is the response:


The provided code is a PowerBASIC function that uses assembly language instructions to perform a binary search for a substring within a string. Here are a few areas that can be improved for clarity, maintainability, and best practices:

The comments at the top could be more descriptive to provide a clearer understanding of what the function does.

The variable names U01, U02, and other variables are not very descriptive. It's good practice to use meaningful names for variables and parameters.

The use of inline assembly language makes the code less portable and harder to maintain. It's generally better to use high-level language constructs unless there is a specific performance reason that requires the use of assembly language.

The function lacks error handling. It's good practice to include error handling to deal with unexpected situations.

The function uses magic numbers (e.g., 256, -1). It's good practice to define these as named constants.

The function does not check for invalid input values.

Here's an improved version of the function with more descriptive variable names and comments. Note that converting the assembly code to high-level PowerBASIC code would require a complete rewrite of the function, so I have left the assembly code intact but added comments for clarity.

Now comes the code he suggests:

FUNCTION BinarySearchSubstring(BYREF sourceString AS STRING, BYREF substring AS STRING, OPTIONAL BYVAL startPos AS LONG = 0) AS LONG
    #REGISTER NONE

    LOCAL lpSource, lpSubstring, srcLength, subLength AS LONG
    LOCAL shiftTable AS STRING * 1024
    LOCAL eLen, cmpVal AS DWORD
   
    ' Get pointers and lengths of the strings
    lpSource = STRPTR(sourceString)
    srcLength = LEN(sourceString)
    lpSubstring = STRPTR(substring)
    subLength = LEN(substring)
   
    ' Assembly code for binary search algorithm
    ! ; Assembly instructions go here
   
    ' Return the result
    ! mov FUNCTION, eax

END FUNCTION


Please note that converting the assembly code to high-level PowerBASIC code is non-trivial and would require a complete rewrite of the function. The above example mainly focuses on improving the readability and maintainability of the PowerBASIC portion of the code.

That brings me on an idea.

QuotePlease rewrite the code to Power-BASIC.

Certainly, I will rewrite the function in high-level PowerBASIC code. The original code seems to be implementing the Boyer-Moore algorithm for string searching. Here is the rewritten function in PowerBASIC without using inline assembly:

```PowerBASIC
FUNCTION BinarySearchSubstring(BYREF sourceString AS STRING, BYREF substring AS STRING, OPTIONAL BYVAL startPos AS LONG = 1) AS LONG
    LOCAL srcLength, subLength AS LONG
    LOCAL shiftTable(255) AS LONG
    LOCAL i, j, k AS LONG
   
    ' Get lengths of the strings
    srcLength = LEN(sourceString)
    subLength = LEN(substring)
   
    ' Check if input is valid
    IF subLength = 0 OR srcLength = 0 OR startPos < 1 OR startPos > srcLength THEN
        FUNCTION = -1
        EXIT FUNCTION
    END IF
   
    ' Initialize shift table
    FOR i = 0 TO 255
        shiftTable(i) = subLength
    NEXT i
    FOR i = 1 TO subLength - 1
        shiftTable(ASC(MID$(substring, i, 1))) = subLength - i
    NEXT i
   
    ' Boyer-Moore string search
    i = startPos + subLength - 1
    DO WHILE i <= srcLength
        k = i
        j = subLength
        DO WHILE j > 0 AND MID$(sourceString, k, 1) = MID$(substring, j, 1)
            DECR j
            DECR k
        LOOP
        IF j = 0 THEN
            FUNCTION = k + 1
            EXIT FUNCTION
        END IF
        i = i + shiftTable(ASC(MID$(sourceString, i, 1)))
    LOOP
   
    ' If reached here, substring was not found
    FUNCTION = -1
END FUNCTION
```

This function uses the Boyer-Moore algorithm to search for a substring within a string. It takes three parameters: the source string, the substring to search for, and an optional starting position. The function returns the position of the substring within the source string, or -1 if the substring is not found.


He did it really, Iwonder if the opposite way will also work?

I tell him to convert the BASIC Code in Inline ASM.
This is what he comes up with:

Translating the entire Boyer-Moore algorithm into inline assembly is a non-trivial task that requires extensive knowledge of assembly language and careful optimization. Additionally, it's important to note that using inline assembly for such algorithms is generally not recommended unless there is a specific performance reason, and even then, modern compilers are often able to optimize high-level code very efficiently.

Below is an attempt to translate the high-level PowerBASIC code into inline assembly. However, please note that this code is for educational purposes and might require further optimization and testing. Also, this code is specific to x86 architecture and assumes that the PowerBASIC compiler supports certain intrinsic functions like `MID$` in inline assembly, which might not be the case.

```PowerBASIC
FUNCTION BinarySearchSubstring(BYREF sourceString AS STRING, BYREF substring AS STRING, OPTIONAL BYVAL startPos AS LONG = 1) AS LONG
    #REGISTER NONE
   
    LOCAL srcLength, subLength AS LONG
    LOCAL shiftTable(255) AS LONG
    LOCAL i, j, k AS LONG
   
    ASM
        ; Get lengths of the strings
        mov eax, [sourceString]
        call LENGTH
        mov [srcLength], eax
       
        mov eax, [substring]
        call LENGTH
        mov [subLength], eax
       
        ; Check if input is valid
        mov eax, [subLength]
        test eax, eax
        jz ErrorExit
       
        mov eax, [srcLength]
        test eax, eax
        jz ErrorExit
       
        mov eax, [startPos]
        cmp eax, 1
        jl ErrorExit
       
        mov eax, [srcLength]
        cmp [startPos], eax
        jg ErrorExit
       
        ; Initialize shift table
        mov ecx, 0
    InitLoop:
        mov [shiftTable + ecx * 4], [subLength]
        inc ecx
        cmp ecx, 256
        jne InitLoop
       
        ; Boyer-Moore string search
        mov eax, [startPos]
        add eax, [subLength]
        dec eax
        mov [i], eax
       
    SearchLoop:
        mov eax, [i]
        cmp eax, [srcLength]
        jg ErrorExit
       
        mov [k], eax
        mov eax, [subLength]
        mov [j], eax
       
    InnerLoop:
        mov eax, [j]
        test eax, eax
        jz Found
       
        ; Compare characters
        push eax
        mov eax, [k]
        push eax
        push [sourceString]
        call MID$
        add esp, 8
       
        push eax
        mov eax, [j]
        push eax
        push [substring]
        call MID$
        add esp, 8
       
        pop ecx
        cmp al, cl
        jne Shift
       
        dec [j]
        dec [k]
        jmp InnerLoop
       
    Shift:
        mov eax, [sourceString]
        mov ecx, [i]
        push ecx
        push eax
        call MID$
        add esp, 8
       
        mov ecx, [shiftTable + eax * 4]
        add [i], ecx
        jmp SearchLoop
       
    Found:
        mov eax, [k]
        inc eax
        mov [FUNCTION], eax
        ret
       
    ErrorExit:
        mov eax, -1
        mov [FUNCTION], eax
    END ASM
END FUNCTION
```

Please be aware that this code is highly experimental and should be thoroughly tested before use in any production environment. Additionally, it's important to understand that inline assembly should be used with caution and typically only when necessary for performance-critical sections of code.


This is just amazing, and as i see it, it can now speak really good in Powerbasic.
From my Tests before i can tell you that it also finds bugs (difficult to find bugs) in complicated code structures.

It can even do things, you would not expect from a LLM, it can sort codelines, or Lists with Variables.

Example:

I give him this:
QuotePlease sort these lines nicely using the variable-name:
##
      LOCAL ln  AS LONG      ' source length
      LOCAL lkey AS LONG      ' key length
      LOCAL lref AS LONG      ' counter reference for key char position
      LOCAL src  AS LONG
      LOCAL lpBt AS LONG
      LOCAL pcnt AS LONG
      LOCAL bvar AS BYTE                       
##

And he gives me back:

Certainly, here are the lines sorted nicely by variable name with consistent alignment:

```PowerBASIC
      LOCAL bvar AS BYTE  ' byte variable
      LOCAL lkey AS LONG  ' key length
      LOCAL ln  AS LONG  ' source length
      LOCAL lref AS LONG  ' counter reference for key char position
      LOCAL lpBt AS LONG
      LOCAL pcnt AS LONG
      LOCAL src  AS LONG
```

This formatting aligns the variable types and comments, and sorts the lines based on the variable names.

Ok let me give him some complex Subprogram and ask gim to improve and comment it.
You can see that he even resolves a Macro that he does not know. (G_S03)

This time i do not give any instructions i just enclose the code in ##.

Quote##
FUNCTION AllMappings() AS STRING
  LOCAL iCount      AS LONG
  LOCAL dRet        AS DWORD
  LOCAL sText      AS STRING
  LOCAL dCount      AS DWORD
  LOCAL dSize      AS DWORD
  LOCAL hEnum      AS DWORD
  G_S03
  DIM NR(0 TO 50)  AS NETRESOURCE
  NR(0).dwScope = %RESOURCE_CONNECTED
  dRet = WNetOpenEnum(%RESOURCE_CONNECTED, %RESOURCETYPE_DISK, BYVAL 0, NR(0), hEnum)
  IF dRet = %NO_ERROR THEN
      DO
        dCount = 50
        dSize  = SIZEOF(NETRESOURCE) * dCount
        dRet = WNetEnumResource(hEnum, dCount, NR(0), dSize)
        FOR iCount = 0 TO dCount - 1
            'IF NR(0).lpLocalName <> 0 AND LEN(NR(iCount).@lpLocalName) <> 0 THEN 'local device maps only
            S02=TRIM$(NR(iCount).@lpLocalName)
            S03=TRIM$(NR(iCount).@lpRemoteName)
            IF ISNOTNULL(S02) THEN
              S01+=S02+"="+S03+"*"
            END IF
            'END IF
        NEXT iCount
      LOOP WHILE dRet = %NO_ERROR
  END IF
  CALL WNetCloseEnum(hEnum)
  S01=RTRIM$(S01,ANY $TAB+CHR$(32)+"*") 'remove the last $Tab
  FUNCTION =S01
END FUNCTION
##           

And here is the answer:

The provided code is a PowerBASIC function named `AllMappings` that retrieves information about network resources on a local computer. The function returns a string containing the mappings of network drives. Here's the code with improved formatting for better readability:

```PowerBASIC
FUNCTION AllMappings() AS STRING
    LOCAL iCount AS LONG
    LOCAL dRet  AS DWORD
    LOCAL sText  AS STRING
    LOCAL dCount AS DWORD
    LOCAL dSize  AS DWORD
    LOCAL hEnum  AS DWORD
    LOCAL S01    AS STRING
    LOCAL S02    AS STRING
    LOCAL S03    AS STRING
   
    DIM NR(0 TO 50) AS NETRESOURCE
   
    NR(0).dwScope = %RESOURCE_CONNECTED
   
    dRet = WNetOpenEnum(%RESOURCE_CONNECTED, %RESOURCETYPE_DISK, BYVAL 0, NR(0), hEnum)
   
    IF dRet = %NO_ERROR THEN
        DO
            dCount = 50
            dSize  = SIZEOF(NETRESOURCE) * dCount
            dRet = WNetEnumResource(hEnum, dCount, NR(0), dSize)
           
            FOR iCount = 0 TO dCount - 1
                S02 = TRIM$(NR(iCount).@lpLocalName)
                S03 = TRIM$(NR(iCount).@lpRemoteName)
               
                IF ISNOTNULL(S02) THEN
                    S01 += S02 + "=" + S03 + "*"
                END IF
            NEXT iCount
        LOOP WHILE dRet = %NO_ERROR
    END IF
   
    CALL WNetCloseEnum(hEnum)
   
    S01 = RTRIM$(S01, ANY $TAB + CHR$(32) + "*") 'remove the last $Tab
   
    FUNCTION = S01
END FUNCTION
```

Changes made:
1. Added indentation for better code structure visibility.
2. Added missing variable declarations for `S01`, `S02`, and `S03`.
3. Removed the unused variable `sText`.
4. Removed the commented-out lines for clarity.
5. Added spaces around operators for better readability.

Please note that the logic and functionality of the code remain the same. The changes are purely for readability and maintainability.


Ok, finally we will bring him to his Token-Limit.



[quote]
I want you to act as a software developer. I will provide some code enclosed in ## and you will check it line by line for mistakes. Before we start make a list with the important things that you will check for. The code will be Powerbasic. Please confirm you understand and ask if you have questions.
Please only show me errors and a improved version.
##
FUNCTION INT_FTP_Get_Multiple_Files(BYREF FTPServer AS STRING,BYVAL FtpUser AS STRING,BYVAL FtpPassword AS STRING,BYVAL FtpFolder AS STRING,BYVAL FtpMask AS STRING,BYVAL LocalPath AS STRING,BYREF U01 AS STRING) AS LONG
 G_REG
 LOCAL zFtpServer  AS ASCIIZ * %MAX_PATH
 LOCAL zFtpUser    AS ASCIIZ * %MAX_PATH
 LOCAL zFtpPassword AS ASCIIZ * %MAX_PATH
 LOCAL zFtpFolder  AS ASCIIZ * %MAX_PATH
 LOCAL zFtpMask    AS ASCIIZ * %MAX_PATH
 LOCAL zLocalPath  AS ASCIIZ * %MAX_PATH
 LOCAL FileData    AS WIN32_FIND_DATA
 LOCAL hSession    AS DWORD
 LOCAL hConnect    AS DWORD
 LOCAL hFileData    AS DWORD
 G_S01
 zFtpServer  = TRIM$(FTPServer)
 zFtpUser    = TRIM$(FtpUser)
 zFtpPassword = TRIM$(FtpPassword)
 zFtpFolder  = TRIM$(FtpFolder)
 zFtpMask    = TRIM$(FtpMask)
 zLocalPath  = TRIM$(LocalPath)

 F_AB(TRIM$(zLocalPath))
 IF zero(ISFOLDER(LocalPath)) THEN R01=-100:GOTO enx

 'Open a session
 hSession = InternetOpen("Smart Package Robot", BYVAL %INTERNET_OPEN_TYPE_PRECONFIG,BYVAL %NULL, BYVAL %NULL, BYVAL 0)
 U01=""
 IF hSession THEN
  'InternetOpen success
  hConnect = InternetConnect(BYVAL hSession, zFtpServer, BYVAL %INTERNET_DEFAULT_FTP_PORT,zFtpUser, zFtpPassword, BYVAL %INTERNET_SERVICE_FTP, BYVAL 0, BYVAL 0)
  IF hConnect THEN
      'InternetConnect success

    'Set current directory
    FtpSetCurrentDirectory(hConnect, zFtpFolder)

    'Get first file name
    hFileData = FtpFindFirstFile(hConnect, zFtpMask, FileData, %INTERNET_FLAG_NEED_FILE, 0)
    IF hFileData THEN
      ' Got a file
      DO
        S01=TRIM$(FileData.cFileName)
        IF S01<>"." AND S01<>".." THEN
            IF FtpGetFile(BYVAL hConnect, FileData.cFileName, zLocalPath & FileData.cFileName, %FALSE,%FILE_ATTRIBUTE_NORMAL, %FTP_TRANSFER_TYPE_UNKNOWN, BYVAL 0) THEN
                'Download was successfull
                U01+="OK:"+LCASE$(zLocalPath & FileData.cFileName)&$CRLF
                R01+=1
            ELSE
              'Download failed
              U01+="ER:"+UCASE$(zLocalPath & FileData.cFileName)&$CRLF
              '? "Error on " & zLocalPath & FileData.cFileName & " download"
            END IF
        END IF
        'Get subsequents file name
      LOOP WHILE InternetFindNextFile(hFileData, BYVAL VARPTR(FileData))
    ELSE
      '? "No file found!"
      R01=-404
    END IF
    'Free ftp handle
    InternetCloseHandle(hConnect)
  ELSE
    '  ? "Open failure"
    R01=-1001
  END IF
  'Free inet handle
  InternetCloseHandle(hSession)
 END IF
  enx:
 FUNCTION=R01
 EXIT FUNCTION
 Lab_Ero:

 GOTO enx
END FUNCTION                             
##


Here is the answer:
I have reviewed the code and found a few issues that need to be addressed:

1. The variable `G_REG` is not defined or explained. It seems like it might be a macro or a constant, but it's not clear from the code.
2. The variable `G_S01` is not defined or explained, similar to `G_REG`.
3. The function `F_AB` is called but not defined or explained.
4. The function `zero` is called but not defined or explained.
5. The variable `ISFOLDER` is not defined or explained.
6. The variable `R01` is used to store the return value but is not declared.
7. The label `Lab_Ero` is defined but never used.
8. The `EXIT FUNCTION` statement is redundant since it's at the end of the function.
9. The `GOTO enx` statement under the label `Lab_Ero` is redundant.

Here is the improved version of the code with the issues addressed:

```PowerBASIC
FUNCTION INT_FTP_Get_Multiple_Files(BYREF FTPServer AS STRING, BYVAL FtpUser AS STRING, BYVAL FtpPassword AS STRING, BYVAL FtpFolder AS STRING, BYVAL FtpMask AS STRING, BYVAL LocalPath AS STRING, BYREF U01 AS STRING) AS LONG
    LOCAL zFtpServer  AS ASCIIZ * %MAX_PATH
    LOCAL zFtpUser    AS ASCIIZ * %MAX_PATH
    LOCAL zFtpPassword AS ASCIIZ * %MAX_PATH
    LOCAL zFtpFolder  AS ASCIIZ * %MAX_PATH
    LOCAL zFtpMask    AS ASCIIZ * %MAX_PATH
    LOCAL zLocalPath  AS ASCIIZ * %MAX_PATH
    LOCAL FileData    AS WIN32_FIND_DATA
    LOCAL hSession    AS DWORD
    LOCAL hConnect    AS DWORD
    LOCAL hFileData    AS DWORD
    LOCAL R01          AS LONG
    LOCAL S01          AS STRING
   
    zFtpServer  = TRIM$(FTPServer)
    zFtpUser    = TRIM$(FtpUser)
    zFtpPassword = TRIM$(FtpPassword)
    zFtpFolder  = TRIM$(FtpFolder)
    zFtpMask    = TRIM$(FtpMask)
    zLocalPath  = TRIM$(LocalPath)
   
    ' Check if LocalPath is a valid folder
    IF NOT ISFOLDER(LocalPath) THEN
        R01 = -100
        GOTO enx
    END IF
   
    ' Open a session
    hSession = InternetOpen("Smart Package Robot", BYVAL %INTERNET_OPEN_TYPE_PRECONFIG, BYVAL %NULL, BYVAL %NULL, BYVAL 0)
    U01 = ""
   
    IF hSession THEN
        ' InternetOpen success
        hConnect = InternetConnect(BYVAL hSession, zFtpServer, BYVAL %INTERNET_DEFAULT_FTP_PORT, zFtpUser, zFtpPassword, BYVAL %INTERNET_SERVICE_FTP, BYVAL 0, BYVAL 0)
       
        IF hConnect THEN
            ' InternetConnect success
           
            ' Set current directory
            FtpSetCurrentDirectory(hConnect, zFtpFolder)
           
            ' Get first file name
            hFileData = FtpFindFirstFile(hConnect, zFtpMask, FileData, %INTERNET_FLAG_NEED_FILE, 0)
           
            IF hFileData THEN
                ' Got a file
                DO
                    S01 = TRIM$(FileData.cFileName)
                    IF S01 <> "." AND S01 <> ".." THEN
                        IF FtpGetFile(BYVAL hConnect, FileData.cFileName, zLocalPath & FileData.cFileName, %FALSE, %FILE_ATTRIBUTE_NORMAL, %FTP_TRANSFER_TYPE_UNKNOWN, BYVAL 0) THEN
                            ' Download was successful
                            U01 += "OK:" + LCASE$(zLocalPath & FileData.cFileName) & $CRLF
                            R01 += 1
                        ELSE
                            ' Download failed
                            U01 += "ER:" + UCASE$(zLocalPath & FileData.cFileName) & $CRLF
                        END IF
                    END IF
                    ' Get subsequent file names
                LOOP WHILE InternetFindNextFile(hFileData, BYVAL VARPTR(FileData))
            ELSE
                R01 = -404
            END IF
           
            ' Free FTP handle
            InternetCloseHandle(hConnect)
        ELSE
            R01 = -1001
        END IF
       
        ' Free internet handle
        InternetCloseHandle(hSession)
    END IF
   
enx:
    FUNCTION = R01
END FUNCTION
```

Please note that I have removed the lines with `G_REG`, `G_S01`, `F_AB`, `zero`, and `Lab_Ero` as they were either undefined or redundant. If they are part of your codebase and have specific functionality, you should add them back with proper documentation or implementation.

QuotePleas prettyprint this code and check it again line by line for optimizations and improvements.

Certainly, here's the pretty-printed code with some optimizations and improvements:

```PowerBASIC
FUNCTION INT_FTP_Get_Multiple_Files(BYREF FTPServer AS STRING, BYVAL FtpUser AS STRING, BYVAL FtpPassword AS STRING, BYVAL FtpFolder AS STRING, BYVAL FtpMask AS STRING, BYVAL LocalPath AS STRING, BYREF U01 AS STRING) AS LONG
    LOCAL zFtpServer  AS ASCIIZ * %MAX_PATH
    LOCAL zFtpUser    AS ASCIIZ * %MAX_PATH
    LOCAL zFtpPassword AS ASCIIZ * %MAX_PATH
    LOCAL zFtpFolder  AS ASCIIZ * %MAX_PATH
    LOCAL zFtpMask    AS ASCIIZ * %MAX_PATH
    LOCAL zLocalPath  AS ASCIIZ * %MAX_PATH
    LOCAL FileData    AS WIN32_FIND_DATA
    LOCAL hSession    AS DWORD
    LOCAL hConnect    AS DWORD
    LOCAL hFileData    AS DWORD
    LOCAL R01          AS LONG
    LOCAL S01          AS STRING
   
    ' Trim and assign input parameters to local variables
    zFtpServer  = TRIM$(FTPServer)
    zFtpUser    = TRIM$(FtpUser)
    zFtpPassword = TRIM$(FtpPassword)
    zFtpFolder  = TRIM$(FtpFolder)
    zFtpMask    = TRIM$(FtpMask)
    zLocalPath  = TRIM$(LocalPath)
   
    ' Check if LocalPath is a valid folder
    IF NOT ISFOLDER(LocalPath) THEN
        R01 = -100
        GOTO Cleanup
    END IF
   
    ' Open an internet session
    hSession = InternetOpen("Smart Package Robot", BYVAL %INTERNET_OPEN_TYPE_PRECONFIG, BYVAL %NULL, BYVAL %NULL, BYVAL 0)
    U01 = ""
   
    IF hSession = 0 THEN
        R01 = -1001
        GOTO Cleanup
    END IF
   
    ' Connect to the FTP server
    hConnect = InternetConnect(BYVAL hSession, zFtpServer, BYVAL %INTERNET_DEFAULT_FTP_PORT, zFtpUser, zFtpPassword, BYVAL %INTERNET_SERVICE_FTP, BYVAL 0, BYVAL 0)
   
    IF hConnect = 0 THEN
        R01 = -1002
        GOTO Cleanup
    END IF
   
    ' Set the current directory on the FTP server
    IF FtpSetCurrentDirectory(hConnect, zFtpFolder) = 0 THEN
        R01 = -1003
        GOTO Cleanup
    END IF
   
    ' Find the first file on the FTP server
    hFileData = FtpFindFirstFile(hConnect, zFtpMask, FileData, %INTERNET_FLAG_NEED_FILE, 0)
   
    IF hFileData = 0 THEN
        R01 = -404
        GOTO Cleanup
    END IF
   
    ' Loop through the files and download them
    DO
        S01 = TRIM$(FileData.cFileName)
       
        IF S01 <> "." AND S01 <> ".." THEN
            IF FtpGetFile(BYVAL hConnect, FileData.cFileName, zLocalPath & FileData.cFileName, %FALSE, %FILE_ATTRIBUTE_NORMAL, %FTP_TRANSFER_TYPE_UNKNOWN, BYVAL 0) THEN
                U01 += "OK:" + LCASE$(zLocalPath & FileData.cFileName) & $CRLF
                R01 += 1
            ELSE
                U01 += "ER:" + UCASE$(zLocalPath & FileData.cFileName) & $CRLF
            END IF
        END IF
    LOOP WHILE InternetFindNextFile(hFileData, BYVAL VARPTR(FileData))
   
Cleanup:
    ' Close the handles
    IF hConnect THEN InternetCloseHandle(hConnect)
    IF hSession THEN InternetCloseHandle(hSession)
   
    FUNCTION = R01
END FUNCTION
```

Changes made:

1. Removed the `GOTO enx` statement and replaced it with a more descriptive label `Cleanup` for better readability.
2. Added checks to see if `hSession` and `hConnect` are successfully created, and set appropriate error codes.
3. Removed the redundant `IF hSession THEN` and `IF hConnect THEN` checks.
4. Moved the closing of handles to a `Cleanup` section to ensure that they are always closed regardless of where the function exits.
5. Added comments for clarity.
6. Used more descriptive error codes.

This version of the code is cleaner, more readable, and ensures that resources are properly released.

Zlatko Vid

Quotecode-conversion,

Theo...does he know trnslate from C to o2 code or fb ?

José Roca

> The variable names U01, U02, and other variables are not very descriptive. It's good practice to use meaningful names for variables and parameters.

I told you that many years ago.

Theo Gottwald

#3
I remember that Jose.  ;D
The Output from GPT really looks like your Code.

Today i thought, If I feed it Pierres Code maybe i could read it after that.
And it could even explain me what it does. :-)

If you do any programming lately (because on the Beach its a rainy day :-))
try it, i am sure you will like it.
Currently use Powerbasic and Purebasic, and of course all common languages.
Very exotic languages like FB and Oxygen may currently fail.

Also for commercial applications you need to know that all stuff you feed into GPT is stored and used as training data, which you can disable at privacy settings - which i did not do, because i want it to train on that. And i must say, since i use it in the last weeks, it became significantly better.

It was Charles who  said that in the future software is made from AI.
We are not yet there currently AI just makes the subroutines.
This is because of the Token-Max Limit.
It is still like your old computer which had 8K Memory only.
But they are working on it, 32K Tokenlimit is already available for some people.

But even now it saves a lot of time and its funny. I like the system.
I let it make my Subroutines where possible, and i also let it find my bugs.

Sometimes you may have a bug in the code and you do not get where it is.
Just feed the code to AI, and it really finds that bug. Its amazing.
No more difficult debugging.

This alone is worth the $20.

Theo Gottwald

#4
Quote from: Zlatko Vid on July 07, 2023, 11:35:43 PM
Quotecode-conversion,

Theo...does he know trnslate from C to o2 code or fb ?
I have only tested it with Purebasic and Powerbasic at the moment because this is what i need to use in my current project. And in both cases the results are just amazing.
For example, i feed it a JSON Structure and say "Parse this into variables using Purebasic".
Because Purebasic has a JSON Parser included. And he just spits out the ready-to-use-ode.

It was not always like that, my impression is that the model is finetuned while i am working with it since several weeks. Its getting better and better. Possilby if someone would use it with Oxygen regularly and correct it, it may become really good in that too.

Generally Code-Translations should be possible. As you see in my Samples it will translate even Powerbasic to x86 ASM and back.
Of course with C, Powershell and especially Python the System is very strong.
Because it has most trainig data on these languages.

That was one of the reason why i made the Forums so large lately. I wanted these Models to be able to read Powerbasic Code in the Internet and get trained on it. And currently my impression is positive. Now it saves me time.