arudradey commited on
Commit
cab2a73
Β·
verified Β·
1 Parent(s): 61f1636

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -58
app.py CHANGED
@@ -4,90 +4,102 @@ import subprocess
4
  import shutil
5
  import numpy as np
6
  from PIL import Image
 
7
 
8
  # 1. Setup Persistent Paths
9
  SAVE_DIR = "/data"
10
  EMCC_DIR = os.path.join(SAVE_DIR, "emsdk")
11
  if not os.path.exists(SAVE_DIR): os.makedirs(SAVE_DIR, exist_ok=True)
12
 
13
- # 2. Function to ensure Emscripten exists in the bucket
 
 
 
 
14
  def ensure_compiler():
15
- # If already installed in bucket, just return the path
16
  emcc_path = os.path.join(EMCC_DIR, "upstream/emscripten/emcc")
17
- if os.path.exists(emcc_path):
18
- return emcc_path
19
-
20
- print("Installing Portable Emscripten to Bucket (One-time setup)...")
21
  try:
22
- # Clone EMSDK into the persistent bucket
23
  subprocess.run(["git", "clone", "https://github.com/emscripten-core/emsdk.git", EMCC_DIR], check=True)
24
  subprocess.run([os.path.join(EMCC_DIR, "emsdk"), "install", "latest"], check=True)
25
  subprocess.run([os.path.join(EMCC_DIR, "emsdk"), "activate", "latest"], check=True)
26
  return emcc_path
27
- except Exception as e:
28
- return f"Error installing compiler: {e}"
29
 
30
- def compile_c_logic(c_code, filename):
31
- if not filename or not c_code: return "❌ Filename/Code required."
32
-
33
- # Ensure compiler is ready
34
  emcc_path = ensure_compiler()
35
  if "Error" in emcc_path: return emcc_path
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- base_name = filename.split('.')[0]
38
- c_file = os.path.join("/tmp", f"{base_name}.c")
39
- out_js = os.path.join("/tmp", f"{base_name}.js")
40
- out_wasm = os.path.join("/tmp", f"{base_name}.wasm")
41
- final_wasm = os.path.join(SAVE_DIR, f"{base_name}.wasm")
42
-
43
- with open(c_file, "w") as f: f.write(c_code)
44
-
45
  try:
46
- # Run compiler from the bucket path
47
- result = subprocess.run(
48
- [emcc_path, c_file, "-s", "WASM=1", "-o", out_js],
49
- capture_output=True, text=True, timeout=60
50
- )
51
-
52
- if result.returncode != 0: return f"❌ Compiler Error:\n{result.stderr}"
53
-
54
- if os.path.exists(out_wasm):
55
- shutil.move(out_wasm, final_wasm)
56
- return f"βœ… Success! Compiled to: {final_wasm}"
57
- return "❌ WASM not generated."
58
  except Exception as e:
59
- return f"❌ System Error: {str(e)}"
60
 
61
- # --- WASM TO IMAGE LOGIC ---
62
- def render_wasm(wasm_filename):
63
- if not wasm_filename: return None, "❌ Select a file."
64
- path = os.path.join(SAVE_DIR, wasm_filename)
65
- with open(path, "rb") as f: data = f.read()
66
-
67
  arr = np.frombuffer(data, dtype=np.uint8)
68
  canvas = np.zeros(1920 * 1080, dtype=np.uint8)
69
- size = min(len(arr), 1920 * 1080)
70
- canvas[:size] = arr[:size]
71
-
72
- img = Image.fromarray(canvas.reshape((1080, 1920)), mode='L')
73
- return img, f"βœ… Rendered {len(arr)} bytes to 1080p"
74
 
75
- # --- GRADIO UI ---
76
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
77
- gr.Markdown("# πŸ› οΈ LCPU Persistent Forge")
78
 
79
- with gr.Tab("1. Compiler"):
80
- name = gr.Textbox(label="Filename", value="logic")
81
- code = gr.TextArea(label="C Code", value="int add(int a, int b) { return a + b; }", lines=5)
82
- btn = gr.Button("πŸš€ Build WASM")
83
- stat = gr.Textbox(label="Status")
84
- btn.click(compile_c_logic, [code, name], stat)
85
 
86
- with gr.Tab("2. Visualizer"):
87
- files = gr.Dropdown(label="WASM Files", choices=[f for f in os.listdir(SAVE_DIR) if f.endswith('.wasm')])
88
- v_btn = gr.Button("🎨 Render")
89
- disp = gr.Image()
90
- v_btn.click(render_wasm, files, [disp, stat])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  if __name__ == "__main__":
93
  demo.launch()
 
4
  import shutil
5
  import numpy as np
6
  from PIL import Image
7
+ import pywasm # Add this to your requirements.txt
8
 
9
  # 1. Setup Persistent Paths
10
  SAVE_DIR = "/data"
11
  EMCC_DIR = os.path.join(SAVE_DIR, "emsdk")
12
  if not os.path.exists(SAVE_DIR): os.makedirs(SAVE_DIR, exist_ok=True)
13
 
14
+ # Helper to get fresh file lists
15
+ def get_wasm_files():
16
+ return [f for f in os.listdir(SAVE_DIR) if f.endswith('.wasm')]
17
+
18
+ # --- COMPILER LOGIC ---
19
  def ensure_compiler():
 
20
  emcc_path = os.path.join(EMCC_DIR, "upstream/emscripten/emcc")
21
+ if os.path.exists(emcc_path): return emcc_path
 
 
 
22
  try:
 
23
  subprocess.run(["git", "clone", "https://github.com/emscripten-core/emsdk.git", EMCC_DIR], check=True)
24
  subprocess.run([os.path.join(EMCC_DIR, "emsdk"), "install", "latest"], check=True)
25
  subprocess.run([os.path.join(EMCC_DIR, "emsdk"), "activate", "latest"], check=True)
26
  return emcc_path
27
+ except Exception as e: return f"Error: {e}"
 
28
 
29
+ def compile_c(c_code, filename):
30
+ if not filename: return "❌ Need name."
 
 
31
  emcc_path = ensure_compiler()
32
  if "Error" in emcc_path: return emcc_path
33
+
34
+ base = filename.split('.')[0]
35
+ c_f, out_js, out_wasm = f"/tmp/{base}.c", f"/tmp/{base}.js", f"/tmp/{base}.wasm"
36
+ with open(c_f, "w") as f: f.write(c_code)
37
+
38
+ try:
39
+ # Exporting functions so they are callable by the runner
40
+ res = subprocess.run([emcc_path, c_f, "-s", "WASM=1", "-s", "EXPORTED_FUNCTIONS=['_main']", "-o", out_js], capture_output=True, text=True)
41
+ if res.returncode != 0: return f"❌ {res.stderr}"
42
+ shutil.move(out_wasm, os.path.join(SAVE_DIR, f"{base}.wasm"))
43
+ return f"βœ… Compiled {base}.wasm"
44
+ except Exception as e: return f"❌ {e}"
45
 
46
+ # --- WASM RUNNER (The New "Execution" Tab) ---
47
+ def run_wasm_func(wasm_file, func_name, args):
48
+ if not wasm_file: return "Select a file."
49
+ path = os.path.join(SAVE_DIR, wasm_file)
 
 
 
 
50
  try:
51
+ runtime = pywasm.load(path)
52
+ # Parse comma-separated args: "5, 10" -> [5, 10]
53
+ arg_list = [int(x.strip()) for x in args.split(",")] if args else []
54
+ result = runtime.exec(func_name, arg_list)
55
+ return f"Result: {result}"
 
 
 
 
 
 
 
56
  except Exception as e:
57
+ return f"Error running {func_name}: {e}"
58
 
59
+ # --- VISUALIZER ---
60
+ def render_wasm(wasm_file):
61
+ if not wasm_file: return None, "Select a file."
62
+ with open(os.path.join(SAVE_DIR, wasm_file), "rb") as f: data = f.read()
 
 
63
  arr = np.frombuffer(data, dtype=np.uint8)
64
  canvas = np.zeros(1920 * 1080, dtype=np.uint8)
65
+ canvas[:min(len(arr), 1920*1080)] = arr[:min(len(arr), 1920*1080)]
66
+ return Image.fromarray(canvas.reshape((1080, 1920)), mode='L'), "Rendered."
 
 
 
67
 
68
+ # --- UI ---
69
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
70
+ gr.Markdown("# πŸ› οΈ LCPU: Forge, Run & Visualize")
71
 
72
+ with gr.Tab("1. Forge"):
73
+ name = gr.Textbox(label="WASM Name", value="math_logic")
74
+ code = gr.TextArea(label="C Code", value='int add(int a, int b) { return a + b; }', lines=6)
75
+ comp_btn = gr.Button("πŸš€ Build")
76
+ status = gr.Textbox(label="Log")
 
77
 
78
+ with gr.Tab("2. Runner"):
79
+ with gr.Row():
80
+ run_select = gr.Dropdown(label="Select WASM", choices=get_wasm_files())
81
+ refresh_run = gr.Button("πŸ”„", variant="secondary")
82
+ func_input = gr.Textbox(label="Function Name", value="add")
83
+ args_input = gr.Textbox(label="Arguments (comma separated)", placeholder="5, 10")
84
+ run_btn = gr.Button("⚑ Execute WASM")
85
+ run_out = gr.Textbox(label="Output")
86
+
87
+ with gr.Tab("3. Visualizer"):
88
+ with gr.Row():
89
+ vis_select = gr.Dropdown(label="Select WASM", choices=get_wasm_files())
90
+ refresh_vis = gr.Button("πŸ”„", variant="secondary")
91
+ render_btn = gr.Button("🎨 Render 1080p")
92
+ img_out = gr.Image()
93
+
94
+ # Event Logic
95
+ comp_btn.click(compile_c, [code, name], status)
96
+
97
+ # Live Refresh Logic
98
+ refresh_run.click(lambda: gr.Dropdown(choices=get_wasm_files()), outputs=run_select)
99
+ refresh_vis.click(lambda: gr.Dropdown(choices=get_wasm_files()), outputs=vis_select)
100
+
101
+ run_btn.click(run_wasm_func, [run_select, func_input, args_input], run_out)
102
+ render_btn.click(render_wasm, vis_select, [img_out, status])
103
 
104
  if __name__ == "__main__":
105
  demo.launch()