rgera/compiler_project
0
1import ast2import gradio as gr3from PIL import Image4import io5import networkx as nx6import matplotlib.pyplot as plt7import copy8import google.generativeai as genai9import os10from dotenv import load_dotenv11import speech_recognition as sr12import numpy as np13import wave14import tempfile15 16load_dotenv()17# Configure Gemini API18genai.configure(api_key=os.getenv('GEMINI_API_KEY'))19model = genai.GenerativeModel('gemini-1.5-flash')20 21def generate_code(prompt: str):22 try:23 response = model.generate_content(24 f"Write Python code for this requirement: {prompt}. "25 "Only return the code without any explanation."26 )27 generated_code = response.text.strip()28 # Try parsing the generated code to verify it's valid Python29 30 generated_code = generated_code[9:-3]31 32 ast.parse(generated_code) #temporarily 33 return "Code generated successfully!", generated_code34 except Exception as e:35 return f"Error: {str(e)}", ""36 37def transcribe_audio(audio):38 if audio is None:39 return "Error: No audio provided", ""40 41 recognizer = sr.Recognizer()42 try:43 # Handle different audio input formats44 if isinstance(audio, str):45 # Direct file path46 with sr.AudioFile(audio) as source:47 audio_data = recognizer.record(source)48 else:49 # Convert numpy array to WAV file50 sample_rate, y = audio51 with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_audio:52 with wave.open(temp_audio.name, 'wb') as wf:53 wf.setnchannels(1)54 wf.setsampwidth(2)55 wf.setframerate(sample_rate)56 wf.writeframes((y * 32767).astype(np.int16).tobytes())57 58 with sr.AudioFile(temp_audio.name) as source:59 audio_data = recognizer.record(source)60 61 text = recognizer.recognize_google(audio_data)62 return "Transcription successful!", text63 except Exception as e:64 return f"Error in transcription: {str(e)}", ""65 66def process_voice_to_code(audio_path):67 status, transcribed_text = transcribe_audio(audio_path)68 if "Error" in status:69 return status, ""70 return generate_code(transcribed_text)71 72# Step 1: Convert AST to NetworkX73def visualize_ast(code: str):74 try:75 tree = ast.parse(code)76 except SyntaxError as e:77 return f"Syntax Error: {e}", None78 79 G = nx.DiGraph()80 81 def get_node_label(node):82 if isinstance(node, ast.Name):83 return f"{type(node).__name__}\nid: {node.id}"84 elif isinstance(node, ast.Constant):85 return f"{type(node).__name__}\nvalue: {node.value}"86 elif isinstance(node, ast.FunctionDef):87 return f"{type(node).__name__}\nname: {node.name}"88 elif isinstance(node, ast.ClassDef):89 return f"{type(node).__name__}\nname: {node.name}"90 elif isinstance(node, ast.Call):91 return f"{type(node).__name__}"92 else:93 return type(node).__name__94 95 def add_nodes_edges(node, parent_id=None, edge_label=""):96 node_id = id(node)97 G.add_node(node_id, label=get_node_label(node))98 if parent_id is not None:99 G.add_edge(parent_id, node_id, label=edge_label)100 101 for field, value in ast.iter_fields(node):102 if isinstance(value, ast.AST):103 add_nodes_edges(value, node_id, field)104 elif isinstance(value, list):105 for item in value:106 if isinstance(item, ast.AST):107 add_nodes_edges(item, node_id, field)108 109 add_nodes_edges(tree)110 111 plt.figure(figsize=(15, 10))112 pos = nx.kamada_kawai_layout(G) # Better layout for hierarchical structures113 114 # Draw edges with labels115 nx.draw_networkx_edges(G, pos, edge_color='gray', arrows=True, arrowsize=20)116 edge_labels = nx.get_edge_attributes(G, 'label')117 nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=8)118 119 # Draw nodes with custom style120 nx.draw_networkx_nodes(G, pos, node_color='lightblue', 121 node_size=2500, alpha=0.9)122 123 # Add node labels with better formatting124 labels = nx.get_node_attributes(G, 'label')125 nx.draw_networkx_labels(G, pos, labels, font_size=8)126 127 plt.title("Abstract Syntax Tree Visualization")128 129 # Save to buffer with higher DPI for better quality130 buf = io.BytesIO()131 plt.savefig(buf, format='png', bbox_inches='tight', dpi=200)132 plt.close()133 buf.seek(0)134 image = Image.open(buf)135 136 return "AST Generated Successfully", image137 138# Step 2: Data Flow Analysis139def analyze_dataflow(code: str):140 try:141 tree = ast.parse(code)142 except SyntaxError as e:143 return f"Syntax Error: {e}", None144 145 146 DFG = nx.DiGraph()147 variables = {} # Track variable definitions and uses148 149 class DataFlowVisitor(ast.NodeVisitor):150 def visit_Assign(self, node):151 for target in node.targets:152 if isinstance(target, ast.Name):153 var_name = target.id154 def_id = f"def_{var_name}_{id(node)}"155 DFG.add_node(def_id, label=f"Define\n{var_name}", type="def")156 variables[var_name] = variables.get(var_name, []) + [def_id]157 self.generic_visit(node)158 159 def visit_Name(self, node):160 if isinstance(node.ctx, ast.Load):161 var_name = node.id162 use_id = f"use_{var_name}_{id(node)}"163 DFG.add_node(use_id, label=f"Use\n{var_name}", type="use")164 # Add edges from all previous definitions165 if var_name in variables:166 for def_id in variables[var_name]:167 DFG.add_edge(def_id, use_id)168 169 DataFlowVisitor().visit(tree)170 171 if not DFG.nodes():172 return "No data flow to analyze", None173 174 plt.figure(figsize=(15, 10))175 pos = nx.spring_layout(DFG, k=2) # More spread out layout176 177 # Draw nodes with different colors for def/use178 def_nodes = [n for n, d in DFG.nodes(data=True) if d.get('type') == 'def']179 use_nodes = [n for n, d in DFG.nodes(data=True) if d.get('type') == 'use']180 181 nx.draw_networkx_nodes(DFG, pos, nodelist=def_nodes, node_color='lightgreen', 182 node_size=3000, alpha=0.9)183 nx.draw_networkx_nodes(DFG, pos, nodelist=use_nodes, node_color='lightblue',184 node_size=3000, alpha=0.9)185 186 # Draw edges and labels187 nx.draw_networkx_edges(DFG, pos, edge_color='gray', arrows=True, arrowsize=20)188 labels = nx.get_node_attributes(DFG, 'label')189 nx.draw_networkx_labels(DFG, pos, labels, font_size=10)190 191 plt.title("Data Flow Graph")192 193 buf = io.BytesIO()194 plt.savefig(buf, format='png', bbox_inches='tight', dpi=200)195 plt.close()196 buf.seek(0)197 image = Image.open(buf)198 199 return "Data Flow Analysis Complete", image200 201# Step 3: Optimization Analysis202def analyze_optimizations(code: str):203 try:204 tree = ast.parse(code)205 except SyntaxError as e:206 return f"Syntax Error: {e}", None207 208 CFG = nx.DiGraph()209 constants = {}210 dead_code = set()211 212 class OptimizationVisitor(ast.NodeVisitor):213 def __init__(self):214 self.current_block = 0215 self.last_block = 0216 217 def new_block(self):218 self.last_block = self.current_block219 self.current_block += 1220 return self.current_block221 222 def visit_Assign(self, node):223 if isinstance(node.value, ast.Constant):224 constants[id(node)] = node.value.value225 226 block_id = f"B{self.current_block}"227 label = ast.unparse(node)228 CFG.add_node(block_id, label=label, type='assign')229 230 if self.last_block >= 0:231 CFG.add_edge(f"B{self.last_block}", block_id)232 233 # Mark as dead code if value is never used234 if isinstance(node.targets[0], ast.Name):235 var_name = node.targets[0].id236 if not any(isinstance(n, ast.Name) and n.id == var_name 237 for n in ast.walk(tree) if isinstance(n, ast.Name) 238 and isinstance(n.ctx, ast.Load)):239 dead_code.add(block_id)240 241 self.generic_visit(node)242 243 OptimizationVisitor().visit(tree)244 245 plt.figure(figsize=(15, 10))246 pos = nx.spring_layout(CFG, k=2)247 248 # Draw nodes with different colors based on optimization opportunities249 regular_nodes = [n for n in CFG.nodes() if n not in dead_code]250 dead_nodes = list(dead_code)251 252 # Draw regular nodes253 nx.draw_networkx_nodes(CFG, pos, nodelist=regular_nodes, 254 node_color='lightblue', node_size=3000)255 # Draw dead code nodes256 nx.draw_networkx_nodes(CFG, pos, nodelist=dead_nodes,257 node_color='salmon', node_size=3000)258 259 # Draw edges and labels260 nx.draw_networkx_edges(CFG, pos, edge_color='gray', arrows=True, arrowsize=20)261 labels = nx.get_node_attributes(CFG, 'label')262 nx.draw_networkx_labels(CFG, pos, labels, font_size=10)263 264 # Add legend265 plt.plot([], [], 'o', color='salmon', label='Dead Code')266 plt.plot([], [], 'o', color='lightblue', label='Active Code')267 plt.legend()268 269 plt.title("Control Flow Graph with Optimization Opportunities")270 271 buf = io.BytesIO()272 plt.savefig(buf, format='png', bbox_inches='tight', dpi=200)273 plt.close()274 buf.seek(0)275 image = Image.open(buf)276 277 # Prepare optimization summary278 summary = []279 if dead_code:280 summary.append(f"Found {len(dead_code)} dead code block(s)")281 if constants:282 summary.append(f"Found {len(constants)} constant propagation opportunities")283 284 return "\n".join(summary) if summary else "No optimization opportunities found", image285 286# Step 4: Gradio Interface287with gr.Blocks() as demo:288 gr.Markdown("## 🧠 Python Code Analysis Visualizer")289 290 with gr.Tabs():291 with gr.TabItem("AST Visualization"):292 with gr.Row():293 ast_code_input = gr.Code(label="Enter Python Code", language="python")294 ast_output = gr.Image(label="AST Visualization")295 ast_status = gr.Textbox(label="Status")296 ast_btn = gr.Button("Visualize AST")297 298 with gr.TabItem("Data Flow Analysis"):299 with gr.Row():300 dfg_code_input = gr.Code(label="Enter Python Code", language="python")301 dfg_output = gr.Image(label="Data Flow Graph")302 dfg_status = gr.Textbox(label="Status")303 dfg_btn = gr.Button("Analyze Data Flow")304 305 with gr.TabItem("Optimization Analysis"):306 with gr.Row():307 opt_code_input = gr.Code(label="Enter Python Code", language="python")308 opt_output = gr.Image(label="Optimization Visualization")309 opt_status = gr.Textbox(label="Optimization Opportunities")310 opt_btn = gr.Button("Analyze Optimizations")311 312 with gr.TabItem("Natural Language to Code"):313 with gr.Row():314 with gr.Column():315 prompt_input = gr.Textbox(316 label="Enter your requirement in natural language",317 placeholder="e.g., write a function to calculate fibonacci series"318 )319 audio_input = gr.Audio(320 sources=["microphone"],321 type="numpy",322 label="Or speak your requirement"323 )324 with gr.Column():325 code_output = gr.Code(326 label="Generated Code",327 language="python"328 )329 gen_status = gr.Textbox(label="Status")330 with gr.Row():331 generate_btn = gr.Button("Generate from Text")332 voice_btn = gr.Button("Generate from Voice")333 334 ast_btn.click(visualize_ast, inputs=ast_code_input, outputs=[ast_status, ast_output])335 dfg_btn.click(analyze_dataflow, inputs=dfg_code_input, outputs=[dfg_status, dfg_output])336 opt_btn.click(analyze_optimizations, inputs=opt_code_input, outputs=[opt_status, opt_output])337 generate_btn.click(338 generate_code,339 inputs=prompt_input,340 outputs=[gen_status, code_output]341 )342 voice_btn.click(343 process_voice_to_code,344 inputs=audio_input,345 outputs=[gen_status, code_output]346 )347 348demo.launch()349 