PB code assistant compiler tool

Everything else that doesn't fall into one of the other PB categories.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

PB code assistant compiler tool

Post by idle »

A proof of concept using a compiler driver and mistral.ai codestral to correct syntax errors and generate proceedures

A PB code assistant could facilitate
Syntax corrections [x]
Documentation
Debugging
Fill in the middle [x]
Code generation

Added FIM (fill in the middle)
you need to add the FIM macro to the top of your code for the instructions

Code: Select all

Macro FIM(query) 
  ;FIM query 
EndMacro    
And an example, trying to get inlinec and asm working with an odd instruction

Code: Select all

EnableExplicit 
Macro FIM(query) 
  ;FIM query 
EndMacro   

Procedure foo() 
  gg.s = "hello foo"
  PrintN(gg) 
EndProcedure   

Structure m128
  StructureUnion
    a.a[16]
    u.u[8] 
    l.l[4]
    q.q[2]
  EndStructureUnion
EndStructure   

FIM("please write bswap128 using the m128 Structure with both inline c using __builtin_bswap64 And inline Asm For x86 And x64" + 
    "using appropriate CompilerIf CompilerElse statements For c backend and for x86 and x64 asm versions eg #PB_Compiler_Backend = #PB_Backend_C, " +
    "and #PB_Compiler_Processor=#PB_Processor_x64. use intel format asm with ! to denote inline asm, use movbe instruction for swap" +
    "variables in inline c are prefixed with v_ like !v_h = __builtin_bswap64(v_h); asm variables preceeded by p.v_ eg !mov [p.v_l],rax")
Procedure bswap128(*m.m128)  
    
  Protected h.q = *m\q[1] 
  Protected l.q = *m\q[0]  
  
  
  !movbe edx,[p.v_h]
  !movbe eax,[p.v_h+ 4]
  !mov [p.v_h], dword eax 
  !mov [p.v_h+4], dword edx 
  !movbe edx,[p.v_l]
  !movbe eax,[p.v_l + 4]
  !mov [p.v_l], dword eax 
  !mov [p.v_l+4], dword edx 
  
  *m\q[1] = l 
  *m\q[0] = h 
    
EndProcedure 


gg.s = "hello World"
x.i = @gg & $ffff 

OpenConsole("test")
PrintN(gg.s)
foo()
Inpu()
CloseConsole(


This is set up as a compiler tool but if you want to run in debug mode comment out line 314
file$ = ProgramParameter() and set it to a source file that's got errors in it


To use as a compiler tool set the Arguments to %FILE and then set a shortcut like ALT + F5

When it runs it will compile the code with a syntax check pass the error onto the ai along with the code then the compiler will check it again and if successful compile it with debugger and run it, and output the corrected code to checkcode.pb and open it in the IDE on windows.

Code: Select all

EnableExplicit

;if you only want to test use this 
#Userkey$ = "idletestkey" 
#CHATURL$ = "https://atomicwebserver.com/v1/chat/pbcode"

;if you want to try more get your own key
;#Userkey$ = "your mistral api key" 
;#CHATURL$ = "https://api.mistral.ai/v1/chat/completions" 

Global compiler,inputcode$,outputcode$,chaterror$ 

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  #Compiler = #PB_Compiler_Home + "compilers\pbcompiler.exe"
CompilerElse
  #Compiler = #PB_Compiler_Home + "compilers/pbcompiler"
CompilerEndIf

Procedure StartCompiler()
  Protected cmd$, result
  Protected temp$ = GetTemporaryDirectory()
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    cmd$ = "/STANDBY"
  CompilerElse
    cmd$ = "-sb"
  CompilerEndIf
  
  result = RunProgram(#Compiler, cmd$, temp$, #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
  ProcedureReturn result
EndProcedure

Procedure StopCompiler(compiler)
  Protected cmd$
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    cmd$ = "END"
  CompilerElse
    cmd$ = "END"
  CompilerEndIf
  
  WriteProgramStringN(compiler, cmd$)
  WaitProgram(compiler, 5000)
  CloseProgram(compiler)
EndProcedure

Procedure SendCompilerCommand(compiler, command$)
  If ProgramRunning(compiler)
    WriteProgramStringN(compiler, command$)
  EndIf
EndProcedure

Procedure.s GetCompilerOutput(compiler)
  If AvailableProgramOutput(compiler)
    ProcedureReturn ReadProgramString(compiler)
  EndIf
EndProcedure

Procedure WaitCompilerReady(compiler)
  Protected out$
  
  While out$ <> "READY" And Left(out$, 5) <> "ERROR"
    out$ = GetCompilerOutput(compiler)
  Wend
EndProcedure

Procedure.s CheckSyntax(compiler, code$, bProgress = 0)
  Protected temp$ = GetTemporaryDirectory()
  Protected source$ = temp$ + "checkcode"
  Protected out$, error$
  Protected fn = CreateFile(-1, source$ + ".pb")
  
  If fn
    WriteString(fn, code$, #PB_UTF8)
    CloseFile(fn)
    SendCompilerCommand(Compiler, "SOURCE" + Chr(9) + source$ + ".pb")
    SendCompilerCommand(Compiler, "TARGET" + Chr(9) + source$ + ".exe")
    SendCompilerCommand(Compiler, "COMPILE" + Chr(9) + "PROGRESS" + Chr(9) + "SYNTAX")
    
    While out$ <> "SUCCESS" And Left(out$, 5) <> "ERROR"
      out$ = GetCompilerOutput(compiler)
      
      If out$ <> ""
        If bProgress
          PrintN(out$)
        EndIf
      EndIf
    Wend
    
    If Left(out$, 5) = "ERROR"
      While out$ <> "OUTPUT" + #TAB$ + "COMPLETE"
        out$ = GetCompilerOutput(compiler)
        
        If (out$ <> "" And Left(out$, 6) <> "OUTPUT")
          error$ + out$
          
          If bProgress
            PrintN(out$)
          EndIf
        EndIf
      Wend
      out$ = error$
    EndIf
    ReplaceString(out$,Chr(9),Chr(32),#PB_String_InPlace)  
    
    ProcedureReturn out$
  EndIf
EndProcedure

Procedure CompileWithDebug(compiler, code$, bProgress = 0)
  Protected out$,prog,Output$
  Protected temp$ = GetTemporaryDirectory()
  Protected source$ = temp$ + "checkcode"
  Protected fn = CreateFile(-1, source$ + ".pb")
  
  If fn
    If Not FindString(code$,"EnableExplicit") 
      WriteStringN(fn,"EnableExplicit") 
    EndIf   
    WriteStringN(fn,"Calldebugger")
    WriteString(fn, code$, #PB_UTF8)
    CloseFile(fn)
    SendCompilerCommand(Compiler, "SOURCE" + Chr(9) + source$ + ".pb")
    SendCompilerCommand(Compiler, "TARGET" + Chr(9) + source$ + ".exe")
    SendCompilerCommand(Compiler, "COMPILE" + Chr(9) + "PROGRESS" + Chr(9) + "DEBUGGER" + Chr(9) +"PURIFIER")
    
    While out$ <> "SUCCESS" And Left(out$, 5) <> "ERROR"
      out$ = GetCompilerOutput(compiler)
      
      If out$ <> ""
        If bProgress
          PrintN(out$)
        EndIf
      EndIf
    Wend
    
    If out$ = "SUCCESS"
      RunProgram(#PB_Compiler_Home+"compilers/PBDebugger.exe", source$+".exe","")
      RunProgram(source$ + ".pb")
    EndIf
    
  EndIf
EndProcedure

Procedure.s RequestInstruct(instruction$,request$) 
  Protected input$,out$,status$,HttpRequest 
  Protected NewMap header.s() 
  
  request$ = EscapeString(request$,#PB_String_EscapeJSON)   
  
  header("Content-Type") = "application/json" 
  header("Accept") = "application/json" 
  header("Expect") = ""
  header("Authorization") = "Bearer " + #Userkey$
  
  input$ = "{ " +
          ~"\"model\": \"codestral-latest\"," +     
          ~"\"temperature\": 0.1," +
          ~"\"top_p\": 1," + 
          ~"\"max_tokens\": 65536," +
          ~"\"messages\": [{\"role\": \"user\", \"content\":\"" + instruction$ + " " + request$ +
          ~"\"" + "}]}" 
  
  HttpRequest = HTTPRequest(#PB_HTTP_Post,#CHATURL$,Input$,0,header())  
  If HttpRequest
    Status$ = HTTPInfo(HTTPRequest, #PB_HTTP_StatusCode)
    If status$ = "200" 
      out$ = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
      PrintN(out$)
    Else 
      PrintN("ERROR: " + HTTPInfo(HTTPRequest, #PB_HTTP_ErrorMessage) + " [" + HTTPInfo(HTTPRequest, #PB_HTTP_StatusCode) + "]")
      chaterror$ = status$ + " " + HTTPInfo(HTTPRequest, #PB_HTTP_Response)
    EndIf   
    FinishHTTP(HTTPRequest)
  Else
    chaterror$ = "failed to connect" 
  EndIf
  
  ProcedureReturn out$ 
  
EndProcedure  

Procedure.s ExtractContent(JSON_Response$) 
  Protected pos,epos,code$ 
  pos = FindString(JSON_Response$,"content")
  If pos 
    pos + 10
    epos = FindString(JSON_Response$,"}",pos+1) -1 
    
    code$ = Mid(JSON_Response$,pos,epos-pos) 
    code$ = UnescapeString(code$,#PB_String_EscapeJSON) 
    
    Debug code$
  EndIf 
  code$ = RemoveString(code$,"```")
  ProcedureReturn code$ 
  
EndProcedure   

Procedure.s CorrectSyntax(compiler,code$) 
  
  Protected UserInstruction$,JSON_Response$,return_message$
  Protected pass 
  
  return_message$ = CheckSyntax(compiler, code$)
  
  PrintN(return_message$ )
  
  If Left(return_message$,7) = "MESSAGE"
       
    While return_message$ <> "SUCCESS"
      If pass > 4 
        MessageRequester("code check", code$, #PB_MessageRequester_Info)
        Break
      Else
        pass + 1
      EndIf
      UserInstruction$ = "Fix the following code for the PureBasic language. use purebasic syntax only do not define variables with 'as' use purebasic types or structures if given." +
                         "Only return the complete repaired code, with no extra comments, do not move Align keyword if found to a new line. If you Encounter EnableExplicit " + 
                         "try To Define the variables within the scope using either Global Or Protected " + 
                         "if a variable is only found in a Procedure and not within the global scope use Protected, make sure to use the variable type." +
                         "Keep the original formatting: do not add the word purebasic to the code, do not process lines with comments denoted by ; at the start but add them back in. Here is the error message followed by the code: " + return_message$
      
      JSON_Response$ = RequestInstruct(UserInstruction$,code$)
      PrintN(JSON_Response$  )
      If JSON_Response$ <> ""  
        code$ = ExtractContent(JSON_Response$)
        PrintN(code$)
        return_message$ = CheckSyntax(compiler, code$)
      Else 
        MessageRequester("code check", chaterror$, #PB_MessageRequester_Info)
        Break
      EndIf   
    Wend 
    
    PrintN(return_message$ )
    
    If return_message$ = "SUCCESS" 
      ProcedureReturn code$ 
    Else 
      ProcedureReturn "" 
    EndIf 
    
  Else 
    ProcedureReturn code$
  EndIf 
  
EndProcedure   

Procedure.s FIM(compiler,List lcode.s()) 
  
  Protected code$ 
  Protected fim$,instruction$,inst$,JSON_Response$  
  Protected pos,state  
  
  ForEach lcode.s() 
    Debug lcode() 
    pos = FindString(lcode(),"FIM") 
    If pos > 0
      If FindString(lcode(),"FIM(query)") = 0 And FindString(lcode(),";FIM query") = 0 
        state = 1 
        instruction$ + lcode() 
      EndIf   
    EndIf   
    If state > 0 
      pos = FindString(lcode(),"Procedure") 
      If pos > 0
        If Not FindString(lcode(),"EndProcedure") 
          state = 2 
        EndIf   
      EndIf    
      pos = FindString(lcode(),"EndProcedure") 
      If pos > 0
        state=3 
      EndIf 
    EndIf 
    
    If state = 0 
      code$ + lcode() + #LF$
    ElseIf state = 1 
      code$ + ";" + lcode() + #LF$
      instruction$ + lcode() + #LF$
    ElseIf state = 2  
     
      fim$ + lcode() + #LF$
    ElseIf state = 3 
       fim$ + lcode() + #LF$
       
      inst$ = EscapeString("do not add any comentary just fill in the PureBasic code with the following instruction between the named Procedure and Endprocedue at the end of the code here is the instruction " + instruction$ + " here is the body of code for reference ",#PB_String_EscapeJSON) 
       
      JSON_Response$  = RequestInstruct(inst$,code$+fim$)      
      If JSON_Response$ <> ""  
        code$ = ExtractContent(JSON_Response$)
        PrintN(code$)
      EndIf   
          
      state = 0     
    EndIf   
    
  Next   
  
  ProcedureReturn code$ 
    
EndProcedure   

Global code$ ,File$,fn
Define NewList lcode.s()

OpenConsole()

compiler = StartCompiler()

If compiler
  
  file$ = ProgramParameter()
  ;file$ = "C:\Users\idle\AppData\Local\Temp\check.pb"
  PrintN(file$) 
  
  If FileSize(file$) >= 0
       
    fn = ReadFile(-1, file$)
    If fn 
      While Not Eof(fn)  
        AddElement(lcode())
        lcode() = ReadString(fn,#PB_UTF8) 
      Wend   
    EndIf
    
    code$ = FIM(compiler,lcode())
    
    PrintN(code$)     
       
    outputcode$ = CorrectSyntax(compiler,code$)
    PrintN(outputcode$) 
    
    If outputcode$ <> "" 
      CompileWithDebug(compiler, outputcode$, 1)
      StopCompiler(compiler)
    EndIf
  Else 
    MessageRequester("code check", "couldn't start compiler", #PB_MessageRequester_Info)
    End 
  EndIf   
  
EndIf
Input() 
CloseConsole()

User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: PB code assistant compiler tool

Post by Caronte3D »

Wow! Nice!
I like it, the response is faster enough, time to experiment 8)
Thanks! :wink:
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

Caronte3D wrote: Mon Jun 09, 2025 8:43 am Wow! Nice!
I like it, the response is faster enough, time to experiment 8)
Thanks! :wink:
Yes but it's still buggy.

Pbcompiler only returns the 1st syntax error. The llm will try to correct the lot but it doesn't know how to declare variables if they're not declared.

It certainly has potential and for me being a severe dyslexic, I usually hit F5 half a dozen times before a successful compile.
User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: PB code assistant compiler tool

Post by Caronte3D »

I don't care to much about syntax correction, but instead, I like the idea of select a code part (i.e. a procedure) and let the AI to solve some incorrect behaviour in her logic :wink:
Anyway the AI is a must and PB should take this train from the beginning.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

Yes I think it would be a good thing to look into and its also something Fred could potentialy benefit from financially while providing a benefit to the community.
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: PB code assistant compiler tool

Post by dige »

@Idle: Thank you for sharing this with us. This is a great idea. This could become the “KillerApp” tool for the IDE :D
I hadn't tested Mistral before. The first impression is already impressive.
"Daddy, I'll run faster, then it is not so far..."
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: PB code assistant compiler tool

Post by Fred »

I'm curious to see how it can be properly integrated in the IDE
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

@Dige
Yes it would be quite cool to have, it's code generation isn't exactly stella compared to Claude which can even tackle inline c and asm but I think Codestral has potential but it really needs more training on PB, which could be done via the documentation (it doesn't appear to be trained on the pb documentation) but there are a still a lot of hoops to jump through to build a fine tuned model and it also has a cost, though it's only 2$ a month to store the fine tuned model but then I don't know if that model can be shared or who retains the rights to it...

@Fred
No idea yet but the logical path is to develop it as a series of IDE tools to take advantage of the Api while its free to use and get it working through the compiler chain first.

Syntax checking is should be easy enough but I don't know if it retains the code from the previous pass yet so you wouldn't have to feed it the whole code when the compiler halts on the next error it encounters, if it retains the context then you can just pass the compiler message and insert the result into the source. Though when you ask it to correct the syntax it does the whole document in one go but it needs better prompting to declare variables if EnableExplicit is used and will probably take some time to do. It was returning the checked code in python comments for crying out loud! :x

Debugging I haven't actually considered yet, though I'm thinking it can be done in much the same way, though it probably won't be much help if a source is threaded. it's more to validate the code.

Fill in the middle and code generation, could be passed on as a selection using a comment that serves as both the prompt and documentation of the function.

Generation well just pop up a prompt box ask it to do the code insert at current location and run it through the chain to correct it rinse and repeat.

I don't really know if mistral.ai platform is the ideal solution, but I think it could be a good fit for Fred if he wanted to bolt Ai into Purebasic and he could retain some control of the product and also generate an additional revenue stream which would otherwise go directly to "all your data belongs to us mega corp" I see that as a Win/Win. if he gets to clip the ticket.

It's defiantly possible to make a fine tuned model iteratively based on Codestral and while it appears you can feed it github repos I don't think that means pb source code, it really needs a specific format with prompts and explanations of the code in jsonl format. And it's costs $4 per job and $2 a month for storage. The PB documentation would of course be a good place to start and then overtime code can be added with the explanations and prompts used to generate the code. Embeddings can be plain code but then that's just an archive it can query with NLP and fetch from though that would be useful, there's a lot of code on the French and German forums that's not here and if it was all available to us more the better but obviously you want the code to be good which is the whole point of validating the code via compiling it rather than scraping the forums.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

updated 1st post to try and get it to define variables and also running in standalone debugger.
injecting EnableExplicit if not found and CallDebugger at the top of the code so it can be stepped through
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

updates 1st post so you can use it directly for now via atomicwebserver
or direct to mistral with your own key.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

fixed bug with http request to server
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

added fill in the middle using a macro FIM so it's easier to read the instruction

use it like this

Code: Select all

EnableExplicit 
Macro FIM(query) 
  ;FIM query 
EndMacro   

Structure m128
  StructureUnion
    a.a[16]
    u.u[8] 
    l.l[4]
    q.q[2]
  EndStructureUnion
EndStructure   

FIM("please write bswap128 using the m128 Structure with both inline c using __builtin_bswap64 And inline Asm For x86 And x64" + 
    "using appropriate CompilerIf CompilerElse statements For c backend and for x86 and x64 asm versions eg #PB_Compiler_Backend = #PB_Backend_C, " +
    "and #PB_Compiler_Processor=#PB_Processor_x64. use intel format asm with ! to denote inline asm, use movbe instruction for swap" +
    "variables in inline c are prefixed with v_ like !v_h = __builtin_bswap64(v_h); asm variables preceeded by p.v_ eg !mov [p.v_l],rax")
Procedure bswap128(*m.m128)  
    
  Protected h.q = *m\q[1] 
  Protected l.q = *m\q[0]  
    
  *m\q[1] = l 
  *m\q[0] = h 
    
EndProcedure 
don't expect stella results.
User avatar
JHPJHP
Addict
Addict
Posts: 2251
Joined: Sat Oct 09, 2010 3:47 am

Re: PB code assistant compiler tool

Post by JHPJHP »

Hi idle,

This is fantastic.

So many of the computer and phone apps I use now have an AI option, which is quickly becoming invaluable, why should PureBasic be any different? If anything, AI code assistance is already a big part of the culture, bringing it directly to the IDE seems like an obvious next step.

I hope this continues to move forward with growing support from the community; remember, everything great started a little buggy.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: PB code assistant compiler tool

Post by Caronte3D »

+1
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PB code assistant compiler tool

Post by idle »

JHPJHP wrote: Sun Jun 15, 2025 3:52 pm Hi idle,

This is fantastic.

So many of the computer and phone apps I use now have an AI option, which is quickly becoming invaluable, why should PureBasic be any different? If anything, AI code assistance is already a big part of the culture, bringing it directly to the IDE seems like an obvious next step.

I hope this continues to move forward with growing support from the community; remember, everything great started a little buggy.
Thanks and yes I think we need it built into the ide but it will take some time to work out.
I still have to check it with multiple FIM()
The question is does the AI retain a context window that looks up the context from your api key or would you have to keep the connection open instead of closing it after every request and if that's the case can you ignore FinishHTTP(HTTPRequest) and reuse it?

It seems a bit silly sending all the code to a point to give it context of a function which uses a structure at the top of your code but if it retained that it would really help reduce the processing.
Post Reply