arudradey commited on
Commit
46f7f75
Β·
verified Β·
1 Parent(s): cab2a73

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -50
app.py CHANGED
@@ -4,102 +4,141 @@ import subprocess
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()
 
4
  import shutil
5
  import numpy as np
6
  from PIL import Image
7
+ import pywasm
8
 
9
+ # 1. Configuration & Persistent Paths
10
  SAVE_DIR = "/data"
11
  EMCC_DIR = os.path.join(SAVE_DIR, "emsdk")
12
+ if not os.path.exists(SAVE_DIR):
13
+ os.makedirs(SAVE_DIR, exist_ok=True)
14
 
 
15
  def get_wasm_files():
16
+ """Helper to list current WASM files in the bucket"""
17
+ if not os.path.exists(SAVE_DIR): return []
18
  return [f for f in os.listdir(SAVE_DIR) if f.endswith('.wasm')]
19
 
20
+ # 2. Compiler Logic (The Forge)
21
  def ensure_compiler():
22
+ """Checks for Emscripten in the bucket, installs if missing"""
23
  emcc_path = os.path.join(EMCC_DIR, "upstream/emscripten/emcc")
24
+ if os.path.exists(emcc_path):
25
+ return emcc_path
26
  try:
27
+ print("Installing Emscripten to bucket...")
28
  subprocess.run(["git", "clone", "https://github.com/emscripten-core/emsdk.git", EMCC_DIR], check=True)
29
  subprocess.run([os.path.join(EMCC_DIR, "emsdk"), "install", "latest"], check=True)
30
  subprocess.run([os.path.join(EMCC_DIR, "emsdk"), "activate", "latest"], check=True)
31
  return emcc_path
32
+ except Exception as e:
33
+ return f"Error: {str(e)}"
34
 
35
  def compile_c(c_code, filename):
36
+ if not filename: return "❌ Error: Please provide a filename."
37
  emcc_path = ensure_compiler()
38
  if "Error" in emcc_path: return emcc_path
39
 
40
  base = filename.split('.')[0]
41
+ c_f = f"/tmp/{base}.c"
42
+ out_wasm = f"/tmp/{base}.wasm"
43
+ dest_wasm = os.path.join(SAVE_DIR, f"{base}.wasm")
44
+
45
+ with open(c_f, "w") as f:
46
+ f.write(c_code)
47
 
48
  try:
49
+ # STANDALONE_WASM + --no-entry creates a pure binary module for the Runner
50
+ res = subprocess.run([
51
+ emcc_path, c_f,
52
+ "-s", "WASM=1",
53
+ "-s", "STANDALONE_WASM",
54
+ "--no-entry",
55
+ "-o", out_wasm
56
+ ], capture_output=True, text=True, timeout=60)
57
+
58
+ if res.returncode != 0:
59
+ return f"❌ Compiler Error:\n{res.stderr}"
60
+
61
+ if os.path.exists(out_wasm):
62
+ shutil.move(out_wasm, dest_wasm)
63
+ return f"βœ… Successfully Forged: {base}.wasm"
64
+ return "❌ Error: WASM file generation failed."
65
+ except Exception as e:
66
+ return f"❌ System Error: {str(e)}"
67
 
68
+ # 3. Execution Logic (The Runner)
69
  def run_wasm_func(wasm_file, func_name, args):
70
+ if not wasm_file: return "❌ Select a WASM file."
71
  path = os.path.join(SAVE_DIR, wasm_file)
72
  try:
73
+ # Fixed: Using load_module for modern pywasm versions
74
+ runtime = pywasm.load_module(path)
75
+
76
+ # Parse comma-separated numbers
77
  arg_list = [int(x.strip()) for x in args.split(",")] if args else []
78
+
79
+ # Emscripten prefixes C functions with an underscore
80
+ try:
81
+ result = runtime.exec(func_name, arg_list)
82
+ except:
83
+ result = runtime.exec(f"_{func_name}", arg_list)
84
+
85
+ return f"Execution Successful!\nResult: {result}"
86
  except Exception as e:
87
+ return f"❌ Runner Error: {str(e)}"
88
 
89
+ # 4. Visualizer Logic
90
  def render_wasm(wasm_file):
91
+ if not wasm_file: return None, "❌ Select a file."
92
+ path = os.path.join(SAVE_DIR, wasm_file)
93
+
94
+ with open(path, "rb") as f:
95
+ data = f.read()
96
+
97
+ # Map binary to 1080p Grid
98
  arr = np.frombuffer(data, dtype=np.uint8)
99
  canvas = np.zeros(1920 * 1080, dtype=np.uint8)
100
+ size = min(len(arr), 1920 * 1080)
101
+ canvas[:size] = arr[:size]
102
+
103
+ img = Image.fromarray(canvas.reshape((1080, 1920)), mode='L')
104
+ return img, f"Visualizing {len(data)} bytes of logic."
105
 
106
+ # 5. Gradio Interface Layout
107
  with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
108
+ gr.Markdown("# πŸ› οΈ LCPU: Spatial Arithmetic Forge")
109
 
110
+ with gr.Tab("1. The Forge (C to WASM)"):
111
+ with gr.Row():
112
+ wasm_name = gr.Textbox(label="Output Filename", value="math_logic")
113
+ c_code_input = gr.TextArea(label="C Code Source", value='int add(int a, int b) {\n return a + b;\n}', lines=8)
114
+ compile_btn = gr.Button("πŸš€ Build Binary", variant="primary")
115
+ forge_status = gr.Textbox(label="Forge Output")
116
 
117
+ with gr.Tab("2. The Runner (Execution)"):
118
  with gr.Row():
119
+ run_select = gr.Dropdown(label="Select Binary", choices=get_wasm_files())
120
  refresh_run = gr.Button("πŸ”„", variant="secondary")
121
+ f_name = gr.Textbox(label="Function Name", value="add")
122
+ args_in = gr.Textbox(label="Arguments (e.g. 10, 20)", placeholder="5, 5")
123
+ run_btn = gr.Button("⚑ Run Logic", variant="primary")
124
+ run_output = gr.Textbox(label="Output Result")
125
 
126
+ with gr.Tab("3. The Visualizer (Spatial Canvas)"):
127
  with gr.Row():
128
+ vis_select = gr.Dropdown(label="Select Binary", choices=get_wasm_files())
129
  refresh_vis = gr.Button("πŸ”„", variant="secondary")
130
+ render_btn = gr.Button("🎨 Map to 1080p", variant="primary")
131
+ canvas_img = gr.Image(label="Logic Texture")
132
+ vis_status = gr.Textbox(label="Canvas Status")
133
 
134
+ # Wire up the events
135
+ compile_btn.click(compile_c, [c_code_input, wasm_name], forge_status)
136
 
 
137
  refresh_run.click(lambda: gr.Dropdown(choices=get_wasm_files()), outputs=run_select)
138
  refresh_vis.click(lambda: gr.Dropdown(choices=get_wasm_files()), outputs=vis_select)
139
 
140
+ run_btn.click(run_wasm_func, [run_select, f_name, args_in], run_output)
141
+ render_btn.click(render_wasm, vis_select, [canvas_img, vis_status])
142
 
143
  if __name__ == "__main__":
144
  demo.launch()