Skip to content
Snippets Groups Projects
Commit 79e5fdc0 authored by Ammar Ahmed's avatar Ammar Ahmed :speech_balloon:
Browse files

all modules connected except database

parents ece18edd fa64557e
No related branches found
No related tags found
No related merge requests found
Showing
with 738 additions and 1 deletion
.DS_Store .DS_Store
# Goland IDE
*.iml
*.ipr
*.iws
.idea/
/build/
/dist/
/out/
# Golang
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# env file
.env
\ No newline at end of file
package main
import (
"fmt"
"llama/compiler"
displayindicator "llama/display-indicator"
"llama/extraction"
ollamaimplementation "llama/ollama-implementation"
"llama/promptlist"
)
func main() {
//reader := bufio.NewReader(os.Stdin)
var conversationContext []int // Variable to store conversation context
//fmt.Print("Enter your prompt (or type 'exit' to quit): ")
//userPrompt, _ := reader.ReadString('\n')
//userPrompt = strings.TrimSpace(userPrompt)
promptList := promptlist.PromptList()
fmt.Println(promptList)
var userPrompt = ""
for i := range promptList {
fmt.Println(promptList[i])
userPrompt = promptList[i]
//if userPrompt == "exit" {
// fmt.Println("Exiting the program.")
// break
//}
for {
if userPrompt == "exit" {
fmt.Println("Exiting the program.")
break
}
var modifiedPrompt = userPrompt + extraction.GoPrompt
fmt.Println("Prompt received. Generating response...")
// Start a go routine to display a waiting indicator while the response is being generated
done := make(chan bool)
go displayindicator.DisplayLoadingIndicator(done)
// Generate response using Ollama API, passing the context
response, updatedContext, err := ollamaimplementation.GetOllamaResponse(modifiedPrompt, conversationContext)
// Signal the waiting indicator to stop
done <- true
if err != nil {
fmt.Println("Error generating response:", err)
continue
}
// Update the conversation context with the response
conversationContext = updatedContext
generatedCode, err_extract := extraction.Extract(response) // Handle error with string
if err_extract != nil {
fmt.Printf("The LLM gave a improper string in response: %v", response)
userPrompt = "exit"
continue
}
fmt.Println("Ollama's response:", generatedCode)
output, err := compiler.CompileStringToGo(generatedCode)
if err != nil {
userPrompt = output + "\nFollowing are the errors, please fix the code. Write it again, and write only source code along with same test cases with no further explanation. The format should be ```rust <yourcode + testcases> ```"
} else {
fmt.Printf("Compiled successfully. Here is the output: %v", output)
userPrompt = "exit"
}
}
}
}
func promptList() {
panic("unimplemented")
}
write a code that ads 1 and 1,
make a output with numbers from 1 to 10,
make a output with prime numbers from 1 to 20,
make a bubble sort and input to run it from main
\ No newline at end of file
package promptlist
import (
"fmt"
"io"
"os"
"strings"
)
func PromptList() []string {
promptText, err := os.Open("promptlist/promptList.txt")
if err != nil {
fmt.Println("Error opening file", err)
}
text, err := io.ReadAll(promptText)
if err != nil {
fmt.Println("Error reading file:", err)
return nil
}
prompt := string(text)
promptList := strings.Split(prompt, ",")
fmt.Print(promptList)
return promptList
}
package compiler
import (
"log"
"os"
"os/exec"
"strings"
)
const TempOutputDir = "tempOutput/"
const TempModuleName = "tempModule"
type Language string
// Supported languages
const (
Go Language = "go"
Rust Language = "rust"
)
type OS string
// Supported OS
const (
Windows OS = "windows"
Linux OS = "linux"
MacOS OS = "darwin" // Darwin is the kernel of macOS
)
// TODO: I want to make an interface for a compilable language, so that we can add more languages in the future
// TODO: The cmd might also be an interface or a struct, so that it can build itself based on the platform and language
// TODO: A cleanup and panic might be needed in setup because if it panics the temp folders should be removed
// TODO: I am not sure that the setup should panic, maybe it should return an error instead so its easier to clean up
type Compiler struct {
OS OS
Language Language
languageEnv ILanguageEnvironment
SourceCode string
Filename string
cmdPrefix string // For example "cmd /c" on Windows
Dependencies []string
tempOutputDir string
}
type ICompiler interface {
Compile() (string, error)
}
type ILanguageEnvironment interface {
SetupEnvironment(cmdPrefix string, dependencies []string)
CheckCompileErrors(filename string, language Language, cmdPrefix string) (string, error)
WriteCodeToFile(filename, sourceCode string) error
RunPipeline(c *Compiler) (string, error)
}
type GoEnvironment struct {
}
func (ge *GoEnvironment) RunPipeline(c *Compiler) (string, error) {
srcCodeFilename := TempOutputDir + appendSuffix(c.Filename, c.Language)
//compiledFilename := TempOutputDir + c.Filename
// Write the source code to a file first, because it determines the dependencies for "go mod tidy"
err := c.languageEnv.WriteCodeToFile(srcCodeFilename, c.SourceCode)
if err != nil {
log.Fatalf("Error writing source code to file: %v", err)
}
// Sets up go environment with go mod and go mod tidy
c.languageEnv.SetupEnvironment(c.cmdPrefix, c.Dependencies)
// CheckCompileErrors the code
return c.languageEnv.CheckCompileErrors(c.Filename, c.Language, c.cmdPrefix)
}
// SetupEnvironment initializes the go environment by creating a go module and running go mod tidy. Panics if it fails.
// Go modules are used to manage dependencies in go projects.
func (ge *GoEnvironment) SetupEnvironment(cmdPrefix string, _ []string) {
// One string
cmdString := cmdPrefix + " go mod init " + TempModuleName + " && go mod tidy"
// Split the string into a slice
cmdSlice := strings.Fields(cmdString) // Fields splits the strings around each instance of one or more consecutive white space characters
// Make the command
cmd := exec.Command(cmdSlice[0], cmdSlice[1:]...)
// Set its target directory
cmd.Dir = TempOutputDir
// Execute the command
err := cmd.Run()
if err != nil {
removeTempFolders(TempOutputDir)
log.Fatalf("Error initializing go module: %v", err)
}
}
func (ge *GoEnvironment) CheckCompileErrors(filename string, language Language, cmdPrefix string) (string, error) {
srcCodeFilename := appendSuffix(filename, language)
compiledFilename := filename
cmdString := cmdPrefix + " go build -o " + compiledFilename + " " + srcCodeFilename
cmdSlice := strings.Fields(cmdString) // Fields splits the string on white space of variable length
cmd := exec.Command(cmdSlice[0], cmdSlice[1:]...)
cmd.Dir = TempOutputDir
output, err := cmd.CombinedOutput()
return string(output), err
}
func (ge *GoEnvironment) WriteCodeToFile(filename, sourceCode string) error {
return os.WriteFile(filename, []byte(sourceCode), 0644)
}
func InitCompiler(OS OS, language Language, sourceCode string, filename string, dependencies ...string) ICompiler {
compiler := &Compiler{}
compiler.OS = OS
compiler.Language = language
compiler.SourceCode = sourceCode
compiler.Filename = filename
compiler.Dependencies = dependencies
compiler.cmdPrefix = getOsPrefix(OS)
compiler.languageEnv = getLanguageEnv(language)
return compiler
}
func getOsPrefix(OS OS) string {
// Set the cmd prefix based on the platform
switch OS {
case Windows:
return "cmd /c "
case Linux, MacOS:
return ""
default:
panic("Unsupported platform")
}
}
func getLanguageEnv(language Language) ILanguageEnvironment {
switch language {
case Go:
return &GoEnvironment{}
case Rust:
return &RustEnvironment{}
default:
panic("Unsupported language")
}
}
type RustEnvironment struct {
}
func (re *RustEnvironment) RunPipeline(c *Compiler) (string, error) {
srcCodeFilename := TempOutputDir + appendSuffix(c.Filename, c.Language)
//compiledFilename := TempOutputDir + c.Filename
// SetupEnvironment either Go or Rust environment, should be an interface method
c.languageEnv.SetupEnvironment(c.cmdPrefix, c.Dependencies)
// Write the source code to a file
err := c.languageEnv.WriteCodeToFile(srcCodeFilename, c.SourceCode)
if err != nil {
log.Fatalf("Error writing source code to file: %v", err)
}
// CheckCompileErrors the code
return c.languageEnv.CheckCompileErrors(c.Filename, c.Language, c.cmdPrefix)
}
// SetupEnvironment initializes the rust environment by creating a cargo project and adding dependencies. Panics if it fails.
func (re *RustEnvironment) SetupEnvironment(cmdPrefix string, dependencies []string) {
// Initialize the rust cargo project--------------------------------------------------------------------------------
// Command to initialize a cargo project
cmdString := cmdPrefix + " cargo init --bin"
// Split the string into a slice
cmdSlice := strings.Fields(cmdString)
// Make the command
cmd := exec.Command(cmdSlice[0], cmdSlice[1:]...)
// Set its target directory
cmd.Dir = TempOutputDir
// Execute the command
err := cmd.Run()
if err != nil {
log.Fatalf("Error initializing rust project: %v", err)
}
// Update rust dependencies in cargo.toml file using cargo add (cargo-edit)-----------------------------------------
if len(dependencies) == 0 {
return
}
addCommand := cmdPrefix + " cargo add"
addSlice := strings.Fields(addCommand)
addSlice = append(addSlice, dependencies...)
cmd = exec.Command(addSlice[0], addSlice[1:]...)
cmd.Dir = TempOutputDir
err = cmd.Run()
if err != nil {
log.Fatalf("Error adding dependencies: %v", err)
}
}
// CheckCompileErrors checks the code for errors using cargo check. Returns the output and an error.
// Cargo check does not produce an executable, it only checks the code for errors.
// It also does not need a filename, because it checks the whole cargo project.
func (re *RustEnvironment) CheckCompileErrors(_ string, _ Language, cmdPrefix string) (string, error) {
cmdString := cmdPrefix + " cargo check"
cmdSlice := strings.Fields(cmdString)
cmd := exec.Command(cmdSlice[0], cmdSlice[1:]...)
cmd.Dir = TempOutputDir
output, err := cmd.CombinedOutput()
return string(output), err
}
func (re *RustEnvironment) WriteCodeToFile(_, sourceCode string) error {
srcCodeFilename := TempOutputDir + "src/" + appendSuffix("main.rs", Rust) // Rust source code file is always named main.rs
return os.WriteFile(srcCodeFilename, []byte(sourceCode), 0644)
}
/*
Compile compiles the source code and returns the output and an error.
The compiler pipeline
1. Set up OS and Language
2. Set up the temp folders
3. Write the source code to a file
4. SetupEnvironment the code
5. Return the output and error
*/
func (c *Compiler) Compile() (string, error) {
// Set up temp folders
setupTempFolders(TempOutputDir)
defer removeTempFolders(TempOutputDir)
// CheckCompileErrors the code
return c.languageEnv.RunPipeline(c)
}
// appendSuffix appends the suffix to the filename if it is not already there depending on the language, panics if the language is not supported
func appendSuffix(filename string, language Language) string {
suffix := ""
switch language {
case Go:
suffix = ".go"
case Rust:
suffix = ".rs"
default:
panic("Unsupported language")
}
// We check if the filename already has the suffix, if not we append it
if !strings.HasSuffix(filename, suffix) {
filename += suffix
}
return filename
}
// setupTempFolders creates the temp output directory for compiled files, panics if it fails
func setupTempFolders(tempOutputDir string) {
// 0777 are the permissions for the directory, everyone can read, write and execute
err := os.MkdirAll(tempOutputDir, os.ModePerm)
if err != nil {
panic("Error creating temp output directory:\n\n" + err.Error())
}
}
// removeTempFolders removes the temp output directory for compiled files, panics if it fails
func removeTempFolders(tempOutputDir string) {
err := os.RemoveAll(tempOutputDir)
if err != nil {
panic("Error removing temp output directory:\n\n" + err.Error())
}
}
package go_compiler
import (
"compiler"
"runtime"
)
// Deprecated: Use `go_compiler_v2.NewGoCompiler` instead
//
// CompileStringToGo tries to compile a string of go code to a go executable, and returns the compiler output and an error.
// The function does not produce any executables, since they are deleted after the function ends.
func CompileStringToGo(code string, filename string) (string, error) {
// Get the platform
OS := runtime.GOOS
// SetupEnvironment
return compiler.InitCompiler(compiler.OS(OS), compiler.Go, code, filename).Compile()
}
package go_compiler
import (
"os"
"testing"
)
func TestCompileStringToGo(t *testing.T) {
tests := []struct {
filename string
shouldCompile bool
}{
{
filename: "should_compile",
shouldCompile: true,
},
{
filename: "should_not_compile",
shouldCompile: false,
},
{
filename: "should_compile_with_standard_library_dependencies",
shouldCompile: true,
},
{
filename: "should_compile_with_external_dependencies",
shouldCompile: true,
},
}
for _, test := range tests {
t.Run(test.filename, func(t *testing.T) {
// Read the code from the file
code, err := os.ReadFile(test.filename)
output, err := CompileStringToGo(string(code), test.filename)
if err != nil && test.shouldCompile {
t.Errorf("Expected the code to compile, but got an error: %v", err)
} else if err == nil && !test.shouldCompile {
t.Errorf("Expected the code to not compile, but got no error")
}
// Check if the output is empty when the code shouldn't compile
if output == "" && !test.shouldCompile {
t.Errorf("Expected compiler error output, but got none")
}
})
}
}
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
\ No newline at end of file
// These are dependencies that are **NOT** part of the standard library
package main
import (
"fmt"
"golang.org/x/net/http2"
"golang.org/x/crypto/bcrypt"
"net/http"
)
func main() {
// Setting up a simple HTTP/2 server
srv := &http.Server{
Addr: ":8080",
}
// Register a simple handler
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// Hashing a password
password := "mysecretpassword"
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
http.Error(w, "Could not hash password", http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Hashed Password: %s\n", hashedPassword)
})
// Enable HTTP/2
http2.ConfigureServer(srv, nil)
// Start the server
fmt.Println("Starting server on https://localhost:8080")
if err := srv.ListenAndServeTLS("server.crt", "server.key"); err != nil {
fmt.Println("Error starting server:", err)
}
}
// These are dependencies that are part of the standard library
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// Seed the random number generator
rand.Seed(time.Now().UnixNano())
// Generate a random number between 1 and 100
randomNum := rand.Intn(100) + 1 // rand.Intn(100) generates a number from 0 to 99
// Print the random number
fmt.Println("Random Number:", randomNum)
}
\ No newline at end of file
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
}
\ No newline at end of file
module compiler
go 1.23
\ No newline at end of file
package rust_compiler
import (
"compiler"
"runtime"
)
// Deprecated: Use `rust_compiler_v2.NewRustCompiler` instead
//
// CompileStringToRust compiles a string of go code to a rust executable
func CompileStringToRust(code string, filename string, dependencies ...string) (string, error) {
// Get the platform
OS := runtime.GOOS
// SetupEnvironment
return compiler.InitCompiler(compiler.OS(OS), compiler.Rust, code, filename, dependencies...).Compile()
}
package rust_compiler
import (
"os"
"testing"
)
func TestCompileStringToRust(t *testing.T) {
tests := []struct {
filename string
shouldCompile bool
dependencies []string
}{
{
filename: "should_compile",
shouldCompile: true,
dependencies: nil,
},
{
filename: "should_not_compile",
shouldCompile: false,
dependencies: nil,
},
{
filename: "should_compile_with_dependencies",
shouldCompile: true,
dependencies: []string{"rand", "colored"},
},
}
for _, test := range tests {
t.Run(test.filename, func(t *testing.T) {
// Read the code from the file
code, err := os.ReadFile(test.filename)
output, err := CompileStringToRust(string(code), "main.rs", test.dependencies...)
if err != nil && test.shouldCompile {
t.Errorf("Expected the code to compile, but got an error: %v", err)
} else if err == nil && !test.shouldCompile {
t.Errorf("Expected the code to not compile, but got no error")
}
// Check if the output is empty when the code shouldn't compile
if output == "" && !test.shouldCompile {
t.Errorf("Expected compiler error output, but got none")
}
})
}
}
fn main() {
println!("Hello, Should Compile :)");
}
\ No newline at end of file
use rand::Rng; // Import the Rng trait from the rand crate
use colored::*; // Import colored for terminal text coloring
fn main() {
// Create a random number generator
let mut rng = rand::thread_rng();
// Generate a random number between 1 and 100
let random_number = rng.gen_range(1..=100); // Inclusive range
// Print the random number in green
println!("Random number between 1 and 100: {}", random_number.to_string().green());
}
\ No newline at end of file
fn main()
println!("Hello, Should Not Compile :(")
}
\ No newline at end of file
package consts
const TempOutputDir = "tempOutput/"
module compiler_V2
go 1.23
\ No newline at end of file
package go_compiler_v2
import (
"compiler_V2/consts"
"compiler_V2/utils"
"os"
"regexp"
)
const fileName = "main.go"
const testFileName = "main_test.go"
type GoCompiler struct{}
// NewGoCompiler creates a new GoCompiler
func NewGoCompiler() *GoCompiler {
return &GoCompiler{}
}
// CheckCompileErrors takes Go source code and checks for compile errors.
//
// The dependencies are handled automatically by go mod and go tidy.
//
// NOTE: Make sure you have an up-to-date Go installed on the system
//
// Returns the output of the compilation and an error if any
func (gb *GoCompiler) CheckCompileErrors(srcCode []byte) ([]byte, error) {
// Make temp folders
utils.SetupTempFolders(consts.TempOutputDir)
defer utils.RemoveTempFolders(consts.TempOutputDir)
// Create regex to extract test functions from srcCode
re := regexp.MustCompile(`(?m)^func\s+(Test\w+)\s*\(t\s+\*testing\.T\)\s*{[\s\S]*?^}`)
// Get all test functions from srcCode
testFunctions := re.FindAllString(string(srcCode), -1)
// Remove the test code from the main code
nonTestContent := re.ReplaceAllString(string(srcCode), "")
// Write code to main file
err := os.WriteFile(consts.TempOutputDir+fileName, []byte(nonTestContent), 0644)
if err != nil {
return nil, err
}
// Construct the content for the _test.go file.
testFileContent := "package main\n\n"
for _, match := range testFunctions {
testFileContent += match + "\n\n"
}
// Write code to test file, we need this since the tests are in the same file as the code
err2 := os.WriteFile(consts.TempOutputDir+testFileName, []byte(testFileContent), 0644)
if err2 != nil {
return nil, err2
}
// Init go mod, tidy (for dependencies) and goimports (for imports)
cmdString := "go mod init tempOutput && go mod tidy && goimports -w ."
// Run go build
cmdString += " && go build -o main " + fileName
// Run tests
cmdString += " && go test -v "
cmd := utils.MakeCommand(cmdString)
cmd.Dir = consts.TempOutputDir
return cmd.CombinedOutput()
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment