Update app.py
Browse files
app.py
CHANGED
|
@@ -2,72 +2,133 @@ import gradio as gr
|
|
| 2 |
import os
|
| 3 |
import subprocess
|
| 4 |
import shutil
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
#
|
| 7 |
SAVE_DIR = "/data"
|
| 8 |
if not os.path.exists(SAVE_DIR):
|
| 9 |
os.makedirs(SAVE_DIR, exist_ok=True)
|
| 10 |
|
|
|
|
| 11 |
def compile_c_logic(c_code, filename):
|
| 12 |
if not filename or not c_code:
|
| 13 |
return "β Error: Filename and C code are required."
|
| 14 |
|
| 15 |
-
#
|
| 16 |
base_name = filename.split('.')[0]
|
| 17 |
c_file_path = os.path.join("/tmp", f"{base_name}.c")
|
| 18 |
-
wasm_output_path = os.path.join(SAVE_DIR, f"{base_name}.wasm")
|
| 19 |
|
| 20 |
-
#
|
| 21 |
with open(c_file_path, "w") as f:
|
| 22 |
f.write(c_code)
|
| 23 |
|
| 24 |
-
# 2. Run Emscripten (emcc)
|
| 25 |
-
# Note: Hugging Face runs on Linux, so we call emcc directly
|
| 26 |
try:
|
| 27 |
-
# -s WASM=1 tells it to produce a .wasm file
|
| 28 |
-
# -o name.js is required by emcc to generate the .wasm
|
| 29 |
temp_js = os.path.join("/tmp", f"{base_name}.js")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
result = subprocess.run(
|
| 31 |
-
[
|
| 32 |
-
capture_output=True, text=True
|
| 33 |
)
|
| 34 |
|
| 35 |
if result.returncode != 0:
|
| 36 |
return f"β Compilation Error:\n{result.stderr}"
|
| 37 |
|
| 38 |
-
#
|
| 39 |
-
temp_wasm = os.path.join("/tmp", f"{base_name}.wasm")
|
| 40 |
if os.path.exists(temp_wasm):
|
| 41 |
-
shutil.move(temp_wasm,
|
| 42 |
-
return f"β
Success! Compiled to: {
|
| 43 |
else:
|
| 44 |
return "β Error: .wasm file was not generated."
|
| 45 |
|
| 46 |
except Exception as e:
|
| 47 |
-
return f"β System Error: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
|
|
|
| 53 |
with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
|
| 54 |
-
gr.Markdown("# π οΈ LCPU:
|
| 55 |
|
| 56 |
-
with gr.Tab("C-to-WASM
|
| 57 |
-
gr.Markdown("### Write C logic and compile to Binary Pixels")
|
| 58 |
with gr.Row():
|
| 59 |
-
|
| 60 |
-
|
| 61 |
compile_btn = gr.Button("π Compile to WASM", variant="primary")
|
| 62 |
-
|
| 63 |
|
| 64 |
-
with gr.Tab("
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
if __name__ == "__main__":
|
| 73 |
demo.launch()
|
|
|
|
| 2 |
import os
|
| 3 |
import subprocess
|
| 4 |
import shutil
|
| 5 |
+
import numpy as np
|
| 6 |
+
from PIL import Image
|
| 7 |
|
| 8 |
+
# 1. Configuration & Paths
|
| 9 |
SAVE_DIR = "/data"
|
| 10 |
if not os.path.exists(SAVE_DIR):
|
| 11 |
os.makedirs(SAVE_DIR, exist_ok=True)
|
| 12 |
|
| 13 |
+
# 2. Compiler Logic
|
| 14 |
def compile_c_logic(c_code, filename):
|
| 15 |
if not filename or not c_code:
|
| 16 |
return "β Error: Filename and C code are required."
|
| 17 |
|
| 18 |
+
# Strip extensions for processing
|
| 19 |
base_name = filename.split('.')[0]
|
| 20 |
c_file_path = os.path.join("/tmp", f"{base_name}.c")
|
|
|
|
| 21 |
|
| 22 |
+
# Write the C code to /tmp
|
| 23 |
with open(c_file_path, "w") as f:
|
| 24 |
f.write(c_code)
|
| 25 |
|
|
|
|
|
|
|
| 26 |
try:
|
|
|
|
|
|
|
| 27 |
temp_js = os.path.join("/tmp", f"{base_name}.js")
|
| 28 |
+
temp_wasm = os.path.join("/tmp", f"{base_name}.wasm")
|
| 29 |
+
dest_wasm = os.path.join(SAVE_DIR, f"{base_name}.wasm")
|
| 30 |
+
|
| 31 |
+
# We use 'emcc' directly. If packages.txt is processed, it should be in PATH.
|
| 32 |
+
# If it fails, we try calling it via its common absolute path.
|
| 33 |
+
compiler_cmd = "emcc"
|
| 34 |
+
|
| 35 |
result = subprocess.run(
|
| 36 |
+
[compiler_cmd, c_file_path, "-s", "WASM=1", "-o", temp_js],
|
| 37 |
+
capture_output=True, text=True, timeout=30
|
| 38 |
)
|
| 39 |
|
| 40 |
if result.returncode != 0:
|
| 41 |
return f"β Compilation Error:\n{result.stderr}"
|
| 42 |
|
| 43 |
+
# Move generated .wasm to persistent storage
|
|
|
|
| 44 |
if os.path.exists(temp_wasm):
|
| 45 |
+
shutil.move(temp_wasm, dest_wasm)
|
| 46 |
+
return f"β
Success! Compiled to: {dest_wasm}\n\nConsole:\n{result.stdout}"
|
| 47 |
else:
|
| 48 |
return "β Error: .wasm file was not generated."
|
| 49 |
|
| 50 |
except Exception as e:
|
| 51 |
+
return f"β System Error: {str(e)}\n(Check if 'emscripten' is in packages.txt)"
|
| 52 |
+
|
| 53 |
+
# 3. WASM to 1080p Image Logic
|
| 54 |
+
def generate_wasm_canvas(wasm_filename):
|
| 55 |
+
if not wasm_filename:
|
| 56 |
+
return None, "β Select a WASM file first."
|
| 57 |
+
|
| 58 |
+
path = os.path.join(SAVE_DIR, wasm_filename)
|
| 59 |
+
|
| 60 |
+
with open(path, "rb") as f:
|
| 61 |
+
binary_data = f.read()
|
| 62 |
+
|
| 63 |
+
data_array = np.frombuffer(binary_data, dtype=np.uint8)
|
| 64 |
+
canvas_size = 1920 * 1080
|
| 65 |
+
|
| 66 |
+
# Padding/Truncating to fit 1080p exactly
|
| 67 |
+
if len(data_array) < canvas_size:
|
| 68 |
+
padded = np.zeros(canvas_size, dtype=np.uint8)
|
| 69 |
+
padded[:len(data_array)] = data_array
|
| 70 |
+
data_array = padded
|
| 71 |
+
else:
|
| 72 |
+
data_array = data_array[:canvas_size]
|
| 73 |
+
|
| 74 |
+
img_array = data_array.reshape((1080, 1920))
|
| 75 |
+
img = Image.fromarray(img_array, mode='L')
|
| 76 |
+
|
| 77 |
+
output_png_name = wasm_filename.replace(".wasm", ".png")
|
| 78 |
+
output_png_path = os.path.join(SAVE_DIR, output_png_name)
|
| 79 |
+
img.save(output_png_path)
|
| 80 |
+
|
| 81 |
+
return img, f"β
Generated 1080p Canvas: {output_png_name}"
|
| 82 |
+
|
| 83 |
+
# 4. File Management Logic
|
| 84 |
+
def refresh_list():
|
| 85 |
+
files = os.listdir(SAVE_DIR)
|
| 86 |
+
wasm_files = [f for f in files if f.endswith('.wasm')]
|
| 87 |
+
all_files = files
|
| 88 |
+
return gr.Dropdown(choices=wasm_files), gr.Dropdown(choices=all_files)
|
| 89 |
|
| 90 |
+
def delete_file(filename):
|
| 91 |
+
if not filename: return "β No file selected.", refresh_list()[1]
|
| 92 |
+
try:
|
| 93 |
+
os.remove(os.path.join(SAVE_DIR, filename))
|
| 94 |
+
return f"ποΈ Deleted {filename}", refresh_list()[1]
|
| 95 |
+
except Exception as e:
|
| 96 |
+
return f"β Error: {str(e)}", refresh_list()[1]
|
| 97 |
|
| 98 |
+
# 5. UI Layout
|
| 99 |
with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
|
| 100 |
+
gr.Markdown("# π οΈ LCPU: Arithmetic-to-Spatial Engine")
|
| 101 |
|
| 102 |
+
with gr.Tab("1. C-to-WASM Forge"):
|
|
|
|
| 103 |
with gr.Row():
|
| 104 |
+
wasm_name = gr.Textbox(label="Output Name", placeholder="adder_logic")
|
| 105 |
+
c_code = gr.TextArea(label="C Source Code", placeholder="int add(int a, int b) { return a + b; }", lines=8)
|
| 106 |
compile_btn = gr.Button("π Compile to WASM", variant="primary")
|
| 107 |
+
comp_status = gr.Textbox(label="Compiler Output")
|
| 108 |
|
| 109 |
+
with gr.Tab("2. Spatial Visualizer"):
|
| 110 |
+
wasm_select = gr.Dropdown(label="Select WASM from Bucket", choices=[f for f in os.listdir(SAVE_DIR) if f.endswith('.wasm')])
|
| 111 |
+
render_btn = gr.Button("π¨ Render to 1080p Canvas", variant="primary")
|
| 112 |
+
canvas_display = gr.Image(label="1080p Logic Map")
|
| 113 |
+
render_status = gr.Textbox(label="Render Status")
|
| 114 |
|
| 115 |
+
with gr.Tab("3. Bucket Manager"):
|
| 116 |
+
all_files_list = gr.Dropdown(label="All Files in /data", choices=os.listdir(SAVE_DIR))
|
| 117 |
+
with gr.Row():
|
| 118 |
+
ref_btn = gr.Button("π Refresh List")
|
| 119 |
+
del_btn = gr.Button("ποΈ Delete Selected", variant="stop")
|
| 120 |
+
status_box = gr.Textbox(label="Action Status")
|
| 121 |
+
|
| 122 |
+
# Interactions
|
| 123 |
+
compile_btn.click(fn=compile_c_logic, inputs=[c_code, wasm_name], outputs=comp_status)
|
| 124 |
+
|
| 125 |
+
render_btn.click(fn=generate_wasm_canvas, inputs=wasm_select, outputs=[canvas_display, render_status])
|
| 126 |
+
|
| 127 |
+
del_btn.click(fn=delete_file, inputs=all_files_list, outputs=[status_box, all_files_list])
|
| 128 |
+
|
| 129 |
+
ref_btn.click(fn=lambda: (gr.Dropdown(choices=[f for f in os.listdir(SAVE_DIR) if f.endswith('.wasm')]),
|
| 130 |
+
gr.Dropdown(choices=os.listdir(SAVE_DIR))),
|
| 131 |
+
outputs=[wasm_select, all_files_list])
|
| 132 |
|
| 133 |
if __name__ == "__main__":
|
| 134 |
demo.launch()
|