File size: 11,958 Bytes
26e8fd1
 
 
 
 
 
 
 
 
 
 
09df9bf
 
 
 
 
 
26e8fd1
 
aa7ba89
 
26e8fd1
 
9e3f762
26e8fd1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aef3edd
26e8fd1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3bf373
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# Gradio UI
import re
import gradio as gr
import tempfile
import os
from openai import OpenAI
from dotenv import load_dotenv
import subprocess
import shutil
from timeit import default_timer as timer

def install_rust():
    subprocess.run("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y", shell=True)
    subprocess.run("source $HOME/.cargo/env", shell=True)

install_rust()

# Load environment variables

os.environ['PATH'] += f':{os.path.expanduser("~/.cargo/bin")}'

load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY')
OPENAI_MODEL = "gpt-4o"

# TranslateCode and ExecuteCode class implementations

class TranslateCode:
    def __init__(self, openai_client, model):
        self.openai = openai_client
        self.model = model

    def user_prompt_for(self, python, lang_select):
        user_prompt = f"Rewrite this Python code in {lang_select} with the fastest possible implementation that produces identical output in the least time. "
        user_prompt += f"Respond only with {lang_select} code; do not explain your work; only return {lang_select} code. "
        user_prompt += "Pay attention to number types to ensure no int overflows. Remember to include all necessary dependencies and libraries.\n\n"
        user_prompt += "If translating to Rust, make sure to include the necessary packages and crates."
        user_prompt += python
        return user_prompt

    def messages_for(self, python, lang_select):
        # System message for OpenAI API
        system_message = "You are an assistant that reimplements Python code in high performance code for a Windows PC. "
        system_message += "Respond only with code; do not provide any explanations. "
        system_message += "The response needs to produce an identical output in the fastest possible time."

        return [
            {"role": "system", "content": system_message},
            {"role": "user", "content": self.user_prompt_for(python, lang_select)}
        ]

    def translate_code(self, code_file, lang_select):
        stream = self.openai.chat.completions.create(model=self.model, messages=self.messages_for(code_file, lang_select), stream=True)
        code = ""
        for chunk in stream:
            fragment = chunk.choices[0].delta.content or ""
            code += fragment
        pattern = r"```(c|cpp|rust|javascript)\n"
        code = re.sub(pattern, "", code).replace("```", "")
        return code


class ExecuteCode:
    def __init__(self, translator):
        self.translator = translator

    def extract_dependencies(self, code):
        try:
            dependency_pattern = r"""
            (?:use\s+(?!std::)[a-zA-Z_][a-zA-Z0-9_]*::|extern\s+crate\s+(?!std)[a-zA-Z_][a-zA-Z0-9_]*);?
            |
            \#include\s*<([a-zA-Z_][a-zA-Z0-9_/.]*)>
            |
            (?:import\s+.*\s+from\s+['"]([a-zA-Z_][a-zA-Z0-9_/.]*)['"]
            |require\s*\(\s*['"]([a-zA-Z_][a-zA-Z0-9_/.]*)['"]\s*\))
        """
            matches = re.findall(dependency_pattern, code, re.VERBOSE)
            dependencies = [match for match in matches if any(match)]
            return dependencies if matches else []
        except re.error as e:
            raise ValueError(f"Regex error while extracting dependencies: {e}")

    def execute_code(self, code_file, lang_select):
        if lang_select == "Rust":
            rust_code = self.translator.translate_code(code_file, lang_select)
            try:
                dependencies = self.extract_dependencies(rust_code)
                temp_dir = tempfile.mkdtemp()
                src_dir = os.path.join(temp_dir, "src")
                os.makedirs(src_dir, exist_ok=True)
                cargo_toml = f"""
                [package]
                name = "temp_project"
                version = "0.1.0"
                edition = "2021"

                [dependencies]
            """
                for dependency in dependencies:
                    crate = dependency[0]
                    cargo_toml += f"{crate} = \"*\"\n"
                with open(os.path.join(temp_dir, "Cargo.toml"), "w") as f:
                    f.write(cargo_toml)
                main_rs_path = os.path.join(src_dir, "main.rs")
                with open(main_rs_path, "w", encoding="utf-8") as f:
                    f.write(rust_code)
                cargo_build = subprocess.run(["cargo", "build", "--release"],
                                                cwd=temp_dir,
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.PIPE,
                                                text=True)
                if cargo_build.returncode != 0:
                    return f"Cargo build failed:\n{cargo_build.stderr}", 0
                executable_path = os.path.join(temp_dir, "target", "release", "temp_project")
                start_time = timer()
                run_result = subprocess.run([executable_path],
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.PIPE,
                                            text=True)
                end_time = timer()
                execution_time = end_time - start_time
                if run_result.returncode != 0:
                    print(f"Execution failed: {run_result.stderr}")
                return run_result.stdout, execution_time
            finally:
                if temp_dir:
                    shutil.rmtree(temp_dir, ignore_errors=True)
        elif lang_select in ["C", "C++"]:
            code = self.translator.translate_code(code_file, lang_select)
            with tempfile.TemporaryDirectory() as temp_dir:
                file_extension = "c" if lang_select == "C" else "cpp"
                file_path = os.path.join(temp_dir, f"translated_code.{file_extension}")
                with open(file_path, "w") as f:
                    f.write(code)
                executable_path = os.path.join(temp_dir, "translated_code")
                compiler = "gcc" if lang_select == "C" else "g++"
                compile_result = subprocess.run([compiler, file_path, "-o", executable_path],
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.PIPE,
                                                text=True)
                if compile_result.returncode != 0:
                    return f"Compilation failed:\n{compile_result.stderr}", 0
                start_time = timer()
                run_result = subprocess.run([executable_path],
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.PIPE,
                                            text=True)
                end_time = timer()
                execution_time = end_time - start_time
                return run_result.stdout, execution_time
        elif lang_select == "Javascript":
            js_code = self.translator.translate_code(code_file, lang_select)
            with tempfile.NamedTemporaryFile(suffix='.js', delete=False) as js_file:
                js_file.write(js_code.encode("utf-8"))
                js_file.flush()
                js_file_path = js_file.name
            try:
                start_time = timer()
                run_result = subprocess.run(["node", js_file_path],
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.PIPE,
                                            text=True)
                end_time = timer()
                execution_time = end_time - start_time
                return run_result.stdout, execution_time
            finally:
                os.remove(js_file_path)
        else:
            return "Language not supported", 0


def process_code(python_code: str, target_language: str):
    """Process the uploaded Python code and return both original and translated outputs"""
    # Initialize components
    openai_client = OpenAI()
    translator = TranslateCode(openai_client, OPENAI_MODEL)
    executor = ExecuteCode(translator)
    
    # Run Python code
    python_output = ""
    python_time = 0
    try:
        with tempfile.NamedTemporaryFile(delete=False, suffix=".py") as temp_py_file:
            temp_py_file.write(python_code.encode('utf-8'))
            temp_py_file_path = temp_py_file.name
        
        start_time = timer()
        result = subprocess.run(["python", temp_py_file_path], 
                              capture_output=True, 
                              text=True)
        end_time = timer()
        
        python_output = result.stdout if result.returncode == 0 else result.stderr
        python_time = end_time - start_time
    except Exception as e:
        python_output = str(e)
    finally:
        if 'temp_py_file_path' in locals() and os.path.exists(temp_py_file_path):
            os.remove(temp_py_file_path)

    # Translate and run the code
    translated_code = translator.translate_code(python_code, target_language)
    translated_output, translated_time = executor.execute_code(translated_code, target_language)

    # Format the outputs
    python_output = python_output.replace("Â", "")
    translated_output = translated_output.replace("Â", "")
    python_result = f"Output:\n{python_output}\nExecution time: {python_time:.4f} seconds"
    translated_result = f"Output:\n{translated_output}\nExecution time: {translated_time:.4f} seconds"

    return python_code, translated_code, python_result, translated_result

def create_gradio_interface():
    with gr.Blocks(title="SyntaxShift: Code Translator") as interface:
        gr.Markdown("# SyntaxShift: Code Translator")
        gr.Markdown("It's like Google Translate, but for code. Upload a Python file or paste Python code to translate it to C, C++, Rust, or Javascript, and run the code.")
        
        with gr.Row():
            with gr.Column():
                python_code = gr.Code(
                    label="Python Code",
                    language="python",
                    lines=20
                )
                target_language = gr.Dropdown(
                    choices=["C", "C++", "Rust", "Javascript"],
                    label="Target Language",
                    value="C"
                )
                translate_button = gr.Button("Translate and Run")
            
        with gr.Row():
            with gr.Column():
                translated_code = gr.Code(
                    label="Translated Code",
                    language="python",  # This will update dynamically
                    lines=20
                )
        
        with gr.Row():
            with gr.Column():
                python_output = gr.Textbox(
                    label="Python Execution Result",
                    lines=5
                )
            with gr.Column():
                translated_output = gr.Textbox(
                    label="Translated Code Execution Result",
                    lines=5
                )

        # Update language display based on selection
        def update_language(lang):
            lang_map = {
                "C": "c",
                "C++": "cpp",
                "Rust": "rust",
                "Javascript": "javascript"
            }
            return {"language": lang_map[lang]}

        target_language.change(
            fn=update_language,
            inputs=[target_language],
            outputs=[translated_code]
        )

        # Main translation and execution flow
        translate_button.click(
            fn=process_code,
            inputs=[python_code, target_language],
            outputs=[python_code, translated_code, python_output, translated_output]
        )

    return interface

if __name__ == "__main__":
    demo = create_gradio_interface()
    demo.launch()