mirror of
https://github.com/Z3Prover/z3
synced 2026-01-20 09:13:20 +00:00
retire genaisrc
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
65429963d1
commit
93c409c279
18 changed files with 0 additions and 7733 deletions
1
genaisrc/.gitattributes
vendored
1
genaisrc/.gitattributes
vendored
|
|
@ -1 +0,0 @@
|
|||
genaiscript.d.ts -diff merge=ours linguist-generated
|
||||
4
genaisrc/.gitignore
vendored
4
genaisrc/.gitignore
vendored
|
|
@ -1,4 +0,0 @@
|
|||
# auto-generated
|
||||
genaiscript.d.ts
|
||||
tsconfig.json
|
||||
jsconfig.json
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
|
||||
def("FILE", env.files)
|
||||
|
||||
def("ERR", "/home/nbjorner/z3/src/nlsat/nlsat_simple_checker.cpp: In member function ‘bool nlsat::simple_checker::imp::Endpoint::operator==(const nlsat::simple_checker::imp::Endpoint&) const’:\
|
||||
/home/nbjorner/z3/src/nlsat/nlsat_simple_checker.cpp:63:82: warning: C++20 says that these are ambiguous, even though the second is reversed:\
|
||||
63 | if (!m_inf && !rhs.m_inf && m_open == rhs.m_open && m_val == rhs.m_val) {\
|
||||
| ^~~~~\
|
||||
In file included from /home/nbjorner/z3/src/util/mpz.h:26,\
|
||||
from /home/nbjorner/z3/src/util/mpq.h:21,\
|
||||
from /home/nbjorner/z3/src/util/rational.h:21,\
|
||||
from /home/nbjorner/z3/src/math/polynomial/algebraic_numbers.h:21,\
|
||||
from /home/nbjorner/z3/src/nlsat/nlsat_simple_checker.h:20,\
|
||||
from /home/nbjorner/z3/src/nlsat/nlsat_simple_checker.cpp:1:\
|
||||
/home/nbjorner/z3/src/util/scoped_numeral.h:96:17: note: candidate 1: ‘bool operator==(const _scoped_numeral<algebraic_numbers::manager>&, const _scoped_numeral<algebraic_numbers::manager>::numeral&)’\
|
||||
96 | friend bool operator==(_scoped_numeral const & a, numeral const & b) {\
|
||||
| ^~~~~~~~\
|
||||
/home/nbjorner/z3/src/util/scoped_numeral.h:96:17: note: candidate 2: ‘bool operator==(const _scoped_numeral<algebraic_numbers::manager>&, const _scoped_numeral<algebraic_numbers::manager>::numeral&)’ (reversed)")
|
||||
|
||||
$`You are an expert C++ programmer.
|
||||
Your task is to fix the compilation bug reported in the error message ERR.
|
||||
How should FILE be changed to fix the error message?`
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
script({
|
||||
tools: ["agent_z3"],
|
||||
})
|
||||
|
||||
$`Solve the following problems using Z3:
|
||||
|
||||
The Zhang family has 6 children: Harry, Hermione, Ron, Fred, George, and Ginny.
|
||||
The cost of taking Harry is $1200, Hermione is $1650, Ron is $750, Fred is $800,
|
||||
George is $800, and Ginny is $1500. Which children should the couple take to minimize
|
||||
the total cost of taking the children? They can take up to four children on the upcoming trip.
|
||||
|
||||
Ginny is the youngest, so the Zhang family will definitely take her.
|
||||
|
||||
If the couple takes Harry, they will not take Fred because Harry does not get along with him.
|
||||
|
||||
If the couple takes Harry, they will not take George because Harry does not get along with him.
|
||||
|
||||
If they take George, they must also take Fred.
|
||||
|
||||
If they take George, they must also take Hermione.
|
||||
|
||||
Even though it will cost them a lot of money, the Zhang family has decided to take at least three children.
|
||||
|
||||
The SMTLIB2 formula must not contain forall or exists.
|
||||
Use the Z3 command "minimize" to instruct the solver to minimize the cost of taking the children.
|
||||
use the Z3 command "(check-sat)" to check if the formula is satisfiable.
|
||||
`
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
Twenty golfers wish to play in foursomes for 5 days. Is it possible for each golfer to play no more
|
||||
than once with any other golfer?
|
||||
|
||||
Use SMTLIB2 to formulate the problem as a quantifier free formula over linear integer arithmetic,
|
||||
also known as QF_LIA.
|
||||
|
||||
For every golfer and for every day assign a slot.
|
||||
The golfers are numbered from 1 to 20 and the days are numbered from 1 to 5.
|
||||
Express the problem as a set of integer variables, where each variable represents a golfer's slot on a given day.
|
||||
The variables should be named as follows: golfer_1_day_1, golfer_1_day_2, ..., golfer_20_day_5.
|
||||
|
||||
*/
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
|
||||
script({
|
||||
title: "Invoke LLM completion for code snippets",
|
||||
})
|
||||
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
|
||||
async function runCodePrompt(role, message, code) {
|
||||
const answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("ROLE", role);
|
||||
_.def("REQUEST", message);
|
||||
_.def("CODE", code);
|
||||
_.$`Your role is <ROLE>.
|
||||
The request is given by <REQUEST>
|
||||
original code snippet:
|
||||
<CODE>.`
|
||||
}
|
||||
)
|
||||
console.log(answer.text);
|
||||
return answer.text;
|
||||
}
|
||||
|
||||
async function invokeLLMCompletion(code, prefix) {
|
||||
|
||||
let role = `You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.`;
|
||||
|
||||
let userMessage = `Please complete the provided C/C++ code to ensure it is compilable and executable.
|
||||
Return only the fully modified code while preserving the original logic.
|
||||
Add any necessary stubs, infer data types, and make essential changes to enable
|
||||
successful compilation and execution. Avoid unnecessary code additions.
|
||||
Ensure the final code is robust, secure, and adheres to best practices.`;
|
||||
|
||||
return runCodePrompt(role, userMessage, code);
|
||||
}
|
||||
|
||||
async function invokeLLMAnalyzer(code, inputFilename, funcName) {
|
||||
// Define the llm role
|
||||
let role =
|
||||
`You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.`;
|
||||
|
||||
// Define the message to send
|
||||
let userMessage =
|
||||
`Please analyze the provided C/C++ code and identify any potential issues, bugs, or opportunities for performance improvement. For each observation:
|
||||
|
||||
- Clearly describe the issue or inefficiency.
|
||||
- Explain the reasoning behind the problem or performance bottleneck.
|
||||
- Suggest specific code changes or optimizations, including code examples where applicable.
|
||||
- Ensure recommendations follow best practices for efficiency, maintainability, and correctness.
|
||||
|
||||
At the end of the analysis, provide a detailed report in **Markdown format** summarizing:
|
||||
|
||||
1. **Identified Issues and Their Impact:**
|
||||
- Description of each issue and its potential consequences.
|
||||
|
||||
2. **Suggested Fixes (with Code Examples):**
|
||||
- Detailed code snippets showing the recommended improvements.
|
||||
|
||||
3. **Performance Improvement Recommendations:**
|
||||
- Explanation of optimizations and their expected benefits.
|
||||
|
||||
4. **Additional Insights or Best Practices:**
|
||||
- Suggestions to further enhance the code's quality and maintainability.`;
|
||||
|
||||
return runCodePrompt(role, userMessage, code);
|
||||
}
|
||||
|
||||
async function createGitUpdateRequest(src_directory : string, filename : string, modifiedCode : string) {
|
||||
// extract relative path from filename after slice_directory, extract function and source file name.
|
||||
// Relative path: code_slices\ast\sls\orig_sls_smt_solver.cpp_updt_params.cpp file name: orig_sls_smt.cpp
|
||||
const regex = /code_slices\\(.*)\\([^_]*)_(.*)\.cpp_(.*)\.cpp/;
|
||||
const match = filename.match(regex);
|
||||
if (!match) {
|
||||
console.log(`Filename does not match expected pattern: ${filename}`);
|
||||
return "";
|
||||
}
|
||||
const [_, relative_path, prefix, fileName, funcName] = match;
|
||||
|
||||
console.log(`Relative path: ${relative_path} file name: ${fileName}.cpp`);
|
||||
|
||||
const srcFilePath = path.join(src_directory, relative_path, fileName + ".cpp");
|
||||
const srcFileContent = await workspace.readText(srcFilePath);
|
||||
|
||||
let role =
|
||||
`You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.`;
|
||||
|
||||
const answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("ROLE", role);
|
||||
_.def("SOURCE", srcFileContent);
|
||||
_.def("REVIEW", modifiedCode);
|
||||
_.def("FUNCTION", funcName);
|
||||
_.$`Your role is <ROLE>.
|
||||
Please create a well-formed git patch based on the source code given in
|
||||
<SOURCE>
|
||||
A code analysis is for the method or function <FUNCTION>.
|
||||
The analysis is he following:
|
||||
<REVIEW>`
|
||||
}
|
||||
)
|
||||
console.log(answer.text);
|
||||
return answer.text;
|
||||
}
|
||||
|
||||
const input_directory = "code_slices";
|
||||
const output_directory = "code_slices_analyzed";
|
||||
const src_directory = "src";
|
||||
const code_slice_files = await workspace.findFiles("code_slices/**/*.cpp");
|
||||
|
||||
let count = 0;
|
||||
for (const file of code_slice_files) {
|
||||
if (path.extname(file.filename) === '.cpp') {
|
||||
console.log(`Processing file: ${file.filename}`);
|
||||
|
||||
const regex = /(.*)_(.*)\.cpp_(.*)\.cpp/;
|
||||
const match = file.filename.match(regex);
|
||||
|
||||
if (!match) {
|
||||
console.log(`Filename does not match expected pattern: ${file.filename}`);
|
||||
continue;
|
||||
}
|
||||
const [_, prefix, fileName, funcName] = match;
|
||||
|
||||
const content = file.content;
|
||||
const answer1 = await invokeLLMCompletion(content, fileName);
|
||||
const answer2 = await invokeLLMAnalyzer(answer1, fileName, funcName);
|
||||
const outputFilePath = path.join(output_directory, fileName + "_" + funcName + ".md");
|
||||
await workspace.writeText(outputFilePath, answer2);
|
||||
const answer3 = await createGitUpdateRequest(src_directory, file.filename, answer2);
|
||||
const outputFilePath2 = path.join(output_directory, fileName + "_" + funcName + ".patch");
|
||||
await workspace.writeText(outputFilePath2, answer3);
|
||||
++count;
|
||||
if (count > 3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
|
||||
script({
|
||||
title: "Invoke LLM code update",
|
||||
})
|
||||
|
||||
|
||||
async function runCodePrompt(role, message, code) {
|
||||
const answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("ROLE", role);
|
||||
_.def("REQUEST", message);
|
||||
_.def("CODE", code);
|
||||
_.$`Your role is <ROLE>.
|
||||
The request is given by <REQUEST>
|
||||
original code:
|
||||
<CODE>.`
|
||||
}
|
||||
)
|
||||
console.log(answer.text);
|
||||
return answer.text;
|
||||
}
|
||||
|
||||
async function invokeLLMUpdate(code, inputFile) {
|
||||
|
||||
let role = `You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.`;
|
||||
|
||||
let userMessage = `Please modify the original code to ensure that it enforces the following:
|
||||
- do not use pointer arithmetic for the updates.
|
||||
- do not introduce uses of std::vector.
|
||||
- only make replacements that are compatible with the ones listed below.
|
||||
- add white space between operators:
|
||||
For example:
|
||||
i=0
|
||||
by
|
||||
i = 0
|
||||
For example
|
||||
a+b
|
||||
by
|
||||
a + b
|
||||
- remove brackets around single statements:
|
||||
For example:
|
||||
{ break; }
|
||||
by
|
||||
break;
|
||||
- replaces uses of for loops using begin(), end() iterator patterns by C++21 style for loops
|
||||
For example replace
|
||||
for (auto it = x.begin(), end = x.end(); it != end; ++it)
|
||||
by
|
||||
for (auto & e : x)
|
||||
|
||||
For example, replace
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
expr* arg = a->get_arg(i);
|
||||
...
|
||||
}
|
||||
by
|
||||
for (auto arg : *a) {
|
||||
...
|
||||
}
|
||||
`;
|
||||
|
||||
return runCodePrompt(role, userMessage, code);
|
||||
}
|
||||
|
||||
|
||||
const inputFile = env.files[0];
|
||||
const file = await workspace.readText(inputFile);
|
||||
const answer = await invokeLLMUpdate(file.content, inputFile);
|
||||
// Extract the code from the answer by removing ```cpp and ```:
|
||||
let code = answer.replace(/```cpp/g, "").replace(/```/g, "");
|
||||
const outputFile = inputFile.filename + ".patch";
|
||||
await workspace.writeText(outputFile, code);
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
script({
|
||||
tools: ["agent_fs", "agent_git", "agent_github"],
|
||||
})
|
||||
|
||||
const {
|
||||
workflow = "latest failed",
|
||||
failure_run_id = "latest",
|
||||
branch = await git.defaultBranch(),
|
||||
} = env.vars
|
||||
|
||||
$`Investigate the status of the ${workflow} workflow and identify the root cause of the failure of run ${failure_run_id} in branch ${branch}.
|
||||
|
||||
- Correlate the failure with the relevant commits, pull requests or issues.
|
||||
- Compare the source code between the failed run commit and the last successful run commit before that run.
|
||||
|
||||
In your report, include html links to the relevant runs, commits, pull requests or issues.
|
||||
`
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/**
|
||||
* Script to automate the git commit process with AI-generated commit messages.
|
||||
* It checks for staged changes, generates a commit message, and prompts the user to review or edit the message before committing.
|
||||
*/
|
||||
|
||||
script({
|
||||
title: "git commit message",
|
||||
description: "Generate a commit message for all staged changes",
|
||||
})
|
||||
|
||||
// Check for staged changes and stage all changes if none are staged
|
||||
const diff = await git.diff({
|
||||
staged: true,
|
||||
askStageOnEmpty: true,
|
||||
})
|
||||
|
||||
// If no staged changes are found, cancel the script with a message
|
||||
if (!diff) cancel("no staged changes")
|
||||
|
||||
// Display the diff of staged changes in the console
|
||||
console.log(diff)
|
||||
|
||||
// chunk if case of massive diff
|
||||
const chunks = await tokenizers.chunk(diff, { chunkSize: 10000 })
|
||||
if (chunks.length > 1)
|
||||
console.log(`staged changes chunked into ${chunks.length} parts`)
|
||||
|
||||
let choice
|
||||
let message
|
||||
do {
|
||||
// Generate a conventional commit message based on the staged changes diff
|
||||
message = ""
|
||||
for (const chunk of chunks) {
|
||||
const res = await runPrompt(
|
||||
(_) => {
|
||||
_.def("GIT_DIFF", chunk, {
|
||||
maxTokens: 10000,
|
||||
language: "diff",
|
||||
detectPromptInjection: "available",
|
||||
})
|
||||
_.$`Generate a git conventional commit message that summarizes the changes in GIT_DIFF.
|
||||
|
||||
<type>: <description>
|
||||
|
||||
- <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||
- <description> is a short, imperative present-tense description of the change
|
||||
- GIT_DIFF is generated by "git diff"
|
||||
- do NOT use markdown syntax
|
||||
- do NOT add quotes, single quote or code blocks
|
||||
- keep it short, 1 line only, maximum 50 characters
|
||||
- follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification
|
||||
- do NOT confuse delete lines starting with '-' and add lines starting with '+'
|
||||
`
|
||||
},
|
||||
{
|
||||
model: "large", // Specifies the LLM model to use for message generation
|
||||
label: "generate commit message", // Label for the prompt task
|
||||
system: [
|
||||
"system.assistant",
|
||||
"system.safety_jailbreak",
|
||||
"system.safety_harmful_content",
|
||||
"system.safety_validate_harmful_content",
|
||||
],
|
||||
}
|
||||
)
|
||||
if (res.error) throw res.error
|
||||
message += res.text + "\n"
|
||||
}
|
||||
|
||||
// since we've concatenated the chunks, let's compress it back into a single sentence again
|
||||
if (chunks.length > 1) {
|
||||
const res =
|
||||
await prompt`Generate a git conventional commit message that summarizes the COMMIT_MESSAGES.
|
||||
|
||||
<type>: <description>
|
||||
|
||||
- <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||
- <description> is a short, imperative present-tense description of the change
|
||||
- do NOT use markdown syntax
|
||||
- do NOT add quotes or code blocks
|
||||
- keep it short, 1 line only, maximum 50 characters
|
||||
- use gitmoji
|
||||
- follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification
|
||||
- do NOT confuse delete lines starting with '-' and add lines starting with '+'
|
||||
- do NOT respond anything else than the commit message
|
||||
|
||||
COMMIT_MESSAGES:
|
||||
${message}
|
||||
`.options({
|
||||
model: "large",
|
||||
label: "summarize chunk commit messages",
|
||||
system: [
|
||||
"system.assistant",
|
||||
"system.safety_jailbreak",
|
||||
"system.safety_harmful_content",
|
||||
"system.safety_validate_harmful_content",
|
||||
],
|
||||
})
|
||||
if (res.error) throw res.error
|
||||
message = res.text
|
||||
}
|
||||
|
||||
message = message?.trim()
|
||||
if (!message) {
|
||||
console.log(
|
||||
"No commit message generated, did you configure the LLM model?"
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
// Prompt user to accept, edit, or regenerate the commit message
|
||||
choice = await host.select(message, [
|
||||
{
|
||||
value: "commit",
|
||||
description: "accept message and commit",
|
||||
},
|
||||
{
|
||||
value: "edit",
|
||||
description: "edit message and commit",
|
||||
},
|
||||
{
|
||||
value: "regenerate",
|
||||
description: "regenerate message",
|
||||
},
|
||||
])
|
||||
|
||||
// Handle user's choice for commit message
|
||||
if (choice === "edit") {
|
||||
message = await host.input("Edit commit message", {
|
||||
required: true,
|
||||
})
|
||||
choice = "commit"
|
||||
}
|
||||
// If user chooses to commit, execute the git commit and optionally push changes
|
||||
if (choice === "commit" && message) {
|
||||
console.log(await git.exec(["commit", "-m", message]))
|
||||
if (await host.confirm("Push changes?", { default: true }))
|
||||
console.log(await git.exec("push"))
|
||||
break
|
||||
}
|
||||
} while (choice !== "commit")
|
||||
|
||||
6800
genaisrc/genaiscript.d.ts
vendored
6800
genaisrc/genaiscript.d.ts
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +0,0 @@
|
|||
script({
|
||||
title: "Merge optimizations function changes for a C++ file"
|
||||
})
|
||||
|
||||
import { mergeFunctions } from "./myai.genai.mts";
|
||||
const inputFile = env.files[0];
|
||||
let new_code = await mergeFunctions(inputFile);
|
||||
await workspace.writeText(inputFile.filename + ".opt.cpp", new_code);
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
function function_name_from_code(code: string) {
|
||||
let name = code.split('(')[0].trim();
|
||||
name = name
|
||||
.replace(/::/g, '_')
|
||||
.replace(/ /g, '_')
|
||||
.replace(/\*/g, '');
|
||||
return name;
|
||||
}
|
||||
|
||||
function tree_sitter_get_functions(captures: QueryCapture[], code: string) {
|
||||
return captures.map(({ name, node }) => ({
|
||||
code: node.text,
|
||||
start: node.startIndex,
|
||||
end: node.endIndex,
|
||||
name: function_name_from_code(node.text)
|
||||
}));
|
||||
}
|
||||
|
||||
function output_name_from_file(inputFile: WorkspaceFile, name: string) {
|
||||
let outputFile = "slice_" + path.basename(inputFile.filename) + name + ".cpp";
|
||||
return path.join("code_slices", outputFile);
|
||||
}
|
||||
|
||||
export async function splitFunctions(inputFile: WorkspaceFile) {
|
||||
const { captures: functions } = await parsers.code(
|
||||
inputFile,
|
||||
`(function_definition) @function`
|
||||
);
|
||||
return tree_sitter_get_functions(functions, inputFile.content);
|
||||
}
|
||||
|
||||
|
||||
export async function saveFunctions(inputFile: WorkspaceFile, funs: { code: string, name: string }[]) {
|
||||
for (const fun of funs) {
|
||||
let name = function_name_from_code(fun.code);
|
||||
console.log(name);
|
||||
let outputFile = output_name_from_file(inputFile, name);
|
||||
await workspace.writeText(outputFile, `//Extracted ${name} in ${inputFile.filename}\n${fun.code}\n\n`);
|
||||
}
|
||||
}
|
||||
|
||||
// given a source file <src>
|
||||
// list files in code_slice directory based on that name with extension opt
|
||||
// replace functions in src by the corresponding ones in the opt files.
|
||||
// Save into <dst>
|
||||
|
||||
async function parseOptFunctions(inputFile: WorkspaceFile) {
|
||||
const modifiedFunctions = "slice_" + path.basename(inputFile.filename) + "*.opt";
|
||||
console.log(modifiedFunctions);
|
||||
const directory_path = path.join("code_slices", modifiedFunctions);
|
||||
const files = await workspace.findFiles(directory_path);
|
||||
let modifiedFunctionsList = [];
|
||||
for (const file of files) {
|
||||
console.log(file.filename);
|
||||
const code = file.content.match(/```cpp([\s\S]*?)```/);
|
||||
if (!code) {
|
||||
continue;
|
||||
}
|
||||
const modifiedFunction = code[1];
|
||||
modifiedFunctionsList.push(modifiedFunction);
|
||||
}
|
||||
return modifiedFunctionsList;
|
||||
}
|
||||
|
||||
import * as fs from 'fs';
|
||||
|
||||
export async function mergeModifiedFunction(code: string, funs: { code: string, name: string }[], new_code: string) {
|
||||
let name = function_name_from_code(new_code);
|
||||
let fun = funs.find(f => f.name === name);
|
||||
if (fun) {
|
||||
console.log("Updated function: " + name);
|
||||
code = code.replace(fun.code, new_code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
class ShellOutputRef {
|
||||
shellOutput: ShellOutput;
|
||||
}
|
||||
|
||||
async function canCompileCode(inputFile: WorkspaceFile, new_code: string, result: ShellOutputRef) {
|
||||
|
||||
//
|
||||
// move input file to a temp file
|
||||
// move code to the inputFile.filename
|
||||
// invoke ninja in the build directory: ninja -b build
|
||||
// move the temp file back to the original file
|
||||
// return true iff it succeeded
|
||||
//
|
||||
|
||||
let tempFile = inputFile.filename + ".tmp";
|
||||
let old_code = inputFile.content;
|
||||
await workspace.writeText(tempFile, old_code);
|
||||
await workspace.writeText(inputFile.filename, new_code);
|
||||
result.shellOutput = await host.exec(`cmd /k "C:/Program\ Files/Microsoft\ Visual\ Studio/2022/Enterprise/Common7/Tools/VsDevCmd.bat" -arch=x64 & ninja`, { cwd: "build" });
|
||||
await workspace.writeText(inputFile.filename, old_code);
|
||||
console.log(result.shellOutput.stdout);
|
||||
console.log(result.shellOutput.stderr);
|
||||
let has_failed = result.shellOutput.stdout.search("failed");
|
||||
if (has_failed != -1) {
|
||||
console.log("Failed to compile");
|
||||
return false;
|
||||
}
|
||||
if (result.shellOutput.exitCode == 0) {
|
||||
await workspace.writeText(tempFile, new_code);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function llmFixCompilerErrors(inputFile: WorkspaceFile, new_code: string, result: ShellOutput) {
|
||||
let answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("CODE", new_code);
|
||||
_.def("OUTPUT", result.stderr + result.stdout);
|
||||
_.$`You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.
|
||||
|
||||
Please modify the original code in <CODE> to ensure that it compiles without any errors.
|
||||
The compiler produced the output <OUTPUT> when building <CODE>.
|
||||
`
|
||||
}, {
|
||||
system: [],
|
||||
systemSafety: false
|
||||
}
|
||||
);
|
||||
let new_code_input = answer.text;
|
||||
let match_new_code = new_code_input.match(/```cpp([\s\S]*?)```/);
|
||||
if (!match_new_code) {
|
||||
console.log("Invalid new code");
|
||||
return new_code;
|
||||
}
|
||||
return match_new_code[1];
|
||||
}
|
||||
|
||||
export async function mergeCompileFunction(inputFile: WorkspaceFile, code: string, funs: { code: string, name: string }[], new_code_input: string) {
|
||||
let match_new_code = new_code_input.match(/```cpp([\s\S]*?)```/);
|
||||
if (!match_new_code) {
|
||||
console.log("Invalid new code");
|
||||
return code;
|
||||
}
|
||||
let new_code = match_new_code[1];
|
||||
let retry_count = 0;
|
||||
|
||||
while (retry_count < 2) {
|
||||
let name = function_name_from_code(new_code);
|
||||
let fun = funs.find(f => f.name == name);
|
||||
|
||||
if (!fun) {
|
||||
console.log(`Function name '${name}' not found`);
|
||||
console.log("Available functions: ");
|
||||
for (const fun of funs)
|
||||
console.log("'" + fun.name + "'");
|
||||
console.log(new_code);
|
||||
return code;
|
||||
}
|
||||
console.log("Updated function: " + name);
|
||||
let modified_code = code.replace(fun.code, new_code);
|
||||
if (code == modified_code) {
|
||||
console.log("No change in function: " + name);
|
||||
return code;
|
||||
}
|
||||
let result = new ShellOutputRef();
|
||||
let canCompile = await canCompileCode(inputFile, modified_code, result);
|
||||
console.log("Can compile: " + canCompile);
|
||||
if (canCompile)
|
||||
return modified_code;
|
||||
if (retry_count > 0)
|
||||
break;
|
||||
retry_count++;
|
||||
new_code = await llmFixCompilerErrors(inputFile, new_code, result.shellOutput);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
export async function mergeFunctionsFromList(inputCode: string, funs: { code: string, name: string }[], modifiedFunctionList: string[]) {
|
||||
let code = inputCode;
|
||||
for (const new_code of modifiedFunctionList)
|
||||
code = await mergeModifiedFunction(code, funs, new_code);
|
||||
return code;
|
||||
}
|
||||
|
||||
export async function mergeFunctions(inputFile: WorkspaceFile) {
|
||||
let funs = await splitFunctions(inputFile);
|
||||
let modifiedFunctionList = await parseOptFunctions(inputFile);
|
||||
return mergeFunctionsFromList(inputFile.content, funs, modifiedFunctionList);
|
||||
}
|
||||
|
||||
export async function invokeLLMOpt(code: string) {
|
||||
const answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("CODE", code);
|
||||
_.$`You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.
|
||||
|
||||
Please modify the original code in <CODE> to ensure that it uses best practices for optimal code execution.
|
||||
|
||||
- do use for loops of the form for (auto const& x : container) { ... } instead of for (it = container.begin(); it != container.end(); ++it) { ... }.
|
||||
- do not use assert. Instead use SASSERT.
|
||||
- do not change function signatures.
|
||||
- do not use std::vector.
|
||||
- do not add new comments.
|
||||
- do not split functions into multiple functions.`
|
||||
}, {
|
||||
system: [],
|
||||
systemSafety: false
|
||||
}
|
||||
);
|
||||
return answer.text;
|
||||
}
|
||||
|
||||
export async function invokeLLMClassInvariant(header : string, code : string) {
|
||||
const answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("HEADER", header);
|
||||
_.def("CODE", code);
|
||||
_.$`You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.
|
||||
|
||||
Please create class invariant methods for the classes used in <CODE>.
|
||||
The signature of the class invariant methods should be 'bool well_formed()'.
|
||||
If the code already has class invariant methods, please do not add new ones.
|
||||
Create only code for the class invariant methods and optionally auxiliary helper functions.
|
||||
|
||||
In addition, for each method, provide pre and post conditions.
|
||||
A precondition is an assertion that must be true before the method is called.
|
||||
Similarly, a postcondition is an assertion that must be true after the method is called.
|
||||
Include the well_formed() method in the pre and post conditions if it should be included.
|
||||
`
|
||||
}, {
|
||||
system: [],
|
||||
systemSafety: false
|
||||
}
|
||||
);
|
||||
return answer.text;
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
|
||||
script({
|
||||
title: "Invoke LLM code update",
|
||||
files: "src/muz/spacer/spacer_qe_project.cpp"
|
||||
})
|
||||
|
||||
|
||||
async function invokeLLMUpdate(code) {
|
||||
const answer = await runPrompt(
|
||||
(_) => {
|
||||
_.def("CODE", code);
|
||||
_.$`
|
||||
You are a highly experienced compiler engineer with over 20 years of expertise,
|
||||
specializing in C and C++ programming. Your deep knowledge of best coding practices
|
||||
and software engineering principles enables you to produce robust, efficient, and
|
||||
maintainable code in any scenario.
|
||||
|
||||
Please modify the original code in <CODE> to ensure that it enforces the following:
|
||||
- do not use pointer arithmetic.
|
||||
- do not introduce uses of std::vector.
|
||||
- do not remove comments from the code.
|
||||
- do not replace for loops over unsigned by for loops over 'auto'.
|
||||
- keep comments in the same place. Please.
|
||||
- only make replacements that are compatible with the ones listed next:
|
||||
- add white space between operators:
|
||||
For example:
|
||||
i=0
|
||||
by
|
||||
i = 0
|
||||
For example
|
||||
a+b
|
||||
by
|
||||
a + b
|
||||
- remove brackets around single statements:
|
||||
For example:
|
||||
{ break; }
|
||||
by
|
||||
break;
|
||||
for example replace:
|
||||
else {
|
||||
result = 0;
|
||||
}
|
||||
by
|
||||
else
|
||||
result = 0;
|
||||
for example replace:
|
||||
if (a) {
|
||||
result = 0;
|
||||
}
|
||||
by
|
||||
if (a)
|
||||
result = 0;
|
||||
- start else statements on a new line.
|
||||
- replaces uses of for loops using begin(), end() iterator patterns by C++21 style for loops
|
||||
For example replace
|
||||
for (auto it = x.begin(), end = x.end(); it != end; ++it)
|
||||
by
|
||||
for (auto e : x)
|
||||
or
|
||||
for (auto const& e : x)
|
||||
|
||||
For example, replace
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
expr* arg = a->get_arg(i);
|
||||
...
|
||||
}
|
||||
by
|
||||
for (auto arg : *a) {
|
||||
...
|
||||
}
|
||||
`
|
||||
}, {
|
||||
system: [],
|
||||
systemSafety: false
|
||||
}
|
||||
)
|
||||
console.log(answer.text);
|
||||
return answer.text;
|
||||
}
|
||||
|
||||
|
||||
const inputFile = env.files[0];
|
||||
const file = await workspace.readText(inputFile);
|
||||
const answer = await invokeLLMUpdate(file.content);
|
||||
// Extract the code from the answer by removing ```cpp and ```:
|
||||
let code = answer.replace(/```cpp/g, "").replace(/```/g, "");
|
||||
const outputFile = inputFile.filename + ".patch";
|
||||
await workspace.writeText(outputFile, code);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
script({
|
||||
title: "Invoke LLM code optimization",
|
||||
files: "code_slices/muz/spacer/orig_spacer_antiunify.cpp_anti_unifier.cpp"
|
||||
})
|
||||
|
||||
import { invokeLLMOpt } from "./myai.genai.mts";
|
||||
|
||||
let file = env.files[0];
|
||||
let answer = await invokeLLMOpt(file);
|
||||
const outputFile = file.filename + ".opt";
|
||||
await workspace.writeText(outputFile, answer);
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
script({
|
||||
title: "optimize functions in a file",
|
||||
files: "src/muz/spacer/spacer_qe_project.cpp"
|
||||
})
|
||||
|
||||
import { splitFunctions, invokeLLMOpt, mergeFunctionsFromList, mergeCompileFunction} from "./myai.genai.mts";
|
||||
|
||||
const inputFile = env.files[0];
|
||||
let funs = await splitFunctions(inputFile);
|
||||
let new_code = inputFile.content;
|
||||
for (const fun of funs) {
|
||||
if (fun.code.length < 200) // don't sweat the small stuff
|
||||
continue;
|
||||
let answer = await invokeLLMOpt(fun.code);
|
||||
if (answer)
|
||||
new_code = await mergeCompileFunction(inputFile, new_code, funs, answer);
|
||||
}
|
||||
|
||||
await workspace.writeText(inputFile.filename + ".opt.cpp", new_code);
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
script({
|
||||
title: "Pull Request Descriptor",
|
||||
description: "Generate a description for the current pull request",
|
||||
systemSafety: true,
|
||||
parameters: {
|
||||
base: "",
|
||||
},
|
||||
})
|
||||
const { dbg, vars } = env
|
||||
const base = vars.base || (await git.defaultBranch())
|
||||
const changes = await git.diff({
|
||||
base,
|
||||
llmify: true,
|
||||
})
|
||||
if (!changes) cancel("No changes found in the pull request")
|
||||
dbg(`changes: %s`, changes)
|
||||
const gitDiff = def("GIT_DIFF", changes, {
|
||||
language: "diff",
|
||||
maxTokens: 14000,
|
||||
detectPromptInjection: "available",
|
||||
})
|
||||
$`## Task
|
||||
|
||||
You are an expert code reviewer with great English technical writing skills.
|
||||
|
||||
Your task is to generate a high level summary of the changes in ${gitDiff} for a pull request in a way that a software engineer will understand.
|
||||
This description will be used as the pull request description.
|
||||
|
||||
## Instructions
|
||||
|
||||
- do NOT explain that GIT_DIFF displays changes in the codebase
|
||||
- try to extract the intent of the changes, don't focus on the details
|
||||
- use bullet points to list the changes
|
||||
- use gitmojis to make the description more engaging
|
||||
- focus on the most important changes
|
||||
- do not try to fix issues, only describe the changes
|
||||
- ignore comments about imports (like added, remove, changed, etc.)`
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
script({
|
||||
title: "optimize functions in a file",
|
||||
files: "src/muz/spacer/spacer_qe_project.cpp"
|
||||
})
|
||||
|
||||
import { invokeLLMClassInvariant} from "./myai.genai.mts";
|
||||
|
||||
const headerFile = env.files[0];
|
||||
const cppFile = env.files[1];
|
||||
let answer = await invokeLLMClassInvariant(headerFile.content, cppFile.content);
|
||||
|
||||
await workspace.writeText(headerFile.filename + ".spec.md", answer);
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
script({
|
||||
title: "Extract functions from files using treesitter",
|
||||
files: "src/muz/spacer/spacer_qe_project.cpp"
|
||||
})
|
||||
|
||||
function get_functions(captures : QueryCapture[], code : string) {
|
||||
return captures.map(({ name, node }) => ({
|
||||
code : node.text
|
||||
}))
|
||||
}
|
||||
|
||||
const inputFile = env.files[0];
|
||||
|
||||
|
||||
const { captures: functions } = await parsers.code(
|
||||
inputFile,
|
||||
`(function_definition) @function`
|
||||
);
|
||||
|
||||
|
||||
let funs = get_functions(functions, inputFile.content);
|
||||
|
||||
for (const fun of funs) {
|
||||
// todo put files in a different directory
|
||||
let name = fun.code.split('(')[0].trim();
|
||||
name = name
|
||||
.replace(/::/g, '_')
|
||||
.replace(/ /g, '_')
|
||||
.replace(/\*/g, '');
|
||||
console.log(name);
|
||||
let outputFile = "slice_" + path.basename(inputFile.filename) + name + ".cpp";
|
||||
outputFile = path.join("code_slices", outputFile);
|
||||
|
||||
await workspace.writeText(outputFile, `//Extracted ${name} in ${inputFile.filename}\n${fun.code}\n\n`);
|
||||
}
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"ES2024"
|
||||
],
|
||||
"target": "ES2024",
|
||||
"module": "NodeNext",
|
||||
"moduleDetection": "force",
|
||||
"moduleResolution": "nodenext",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"resolveJsonModule": true,
|
||||
"erasableSyntaxOnly": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.mjs",
|
||||
"**/*.mts",
|
||||
"./genaiscript.d.ts"
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue