11import { useState } from "react" ;
22import { Editor } from "./Editor" ;
3- import { exec } from "./api" ;
3+ import { exec , disassemble } from "./api" ;
44import { Analytics } from "@vercel/analytics/react"
55import "./styles.css" ;
66
7- import {
8- Panel ,
9- PanelGroup ,
10- PanelResizeHandle ,
11- } from "react-resizable-panels" ;
7+ import { Panel , PanelGroup , PanelResizeHandle } from "react-resizable-panels" ;
128
139const PlayIcon = ( ) => (
14- < svg
15- viewBox = "0 0 24 24"
16- fill = "currentColor"
17- style = { { marginRight : "8px" , height : "16px" , width : "16px" } }
18- >
10+ < svg viewBox = "0 0 24 24" fill = "currentColor" style = { { marginRight : 8 , height : 16 , width : 16 } } >
1911 < path d = "M8 5v14l11-7z" />
2012 </ svg >
2113) ;
2214
23-
2415export default function App ( ) {
2516 const [ code , setCode ] = useState ( 'print("Hello, Tundra!")' ) ;
2617 const [ output , setOutput ] = useState ( "" ) ;
18+ const [ bytecode , setBytecode ] = useState ( "" ) ;
2719 const [ isRunning , setIsRunning ] = useState ( false ) ;
2820
2921 const runCode = async ( ) => {
3022 setIsRunning ( true ) ;
3123 setOutput ( "⏳ running…" ) ;
24+ setBytecode ( "⏳ compiling…" ) ;
3225 try {
33- const { stdout, stderr } = await exec ( code ) ;
34- setOutput ( stderr || stdout ) ;
26+ const [ execRes , disRes ] = await Promise . all ( [ exec ( code ) , disassemble ( code ) ] ) ;
27+ setOutput ( execRes . stderr || execRes . stdout ) ;
28+ setBytecode ( disRes . stderr || disRes . bytecode ) ;
3529 } catch ( error ) {
3630 setOutput ( `Failed to connect to executor: ${ error } ` ) ;
31+ setBytecode ( "" ) ;
3732 } finally {
3833 setIsRunning ( false ) ;
3934 }
4035 } ;
4136
37+ const wikiUrl = import . meta. env . VITE_WIKI_URL ?? "https://aayush-tripathi.github.io/tundra/" ;
38+
4239 return (
4340 < div style = { { height : "100vh" , display : "flex" , flexDirection : "column" } } >
4441 { /* Header / Toolbar */ }
45- < header style = { { display : "flex" , alignItems : "center" , padding : "8px" , borderBottom : "1px solid #30363d" } } >
46- < img
47- src = "/tundra_base_logo.png"
48- alt = "Tundra Logo"
49- className = "logo"
50- />
51- < h1 style = { { fontSize : "1.1rem" , fontWeight : 600 , marginRight : "1rem" } } >
52- Tundra Playground
53- </ h1 >
42+ < header style = { { display : "flex" , alignItems : "center" , gap : 12 , padding : 8 , borderBottom : "1px solid #30363d" } } >
43+ < img src = "/tundra_base_logo.png" alt = "Tundra Logo" className = "logo" />
44+ < h1 style = { { fontSize : "1.1rem" , fontWeight : 600 , marginRight : "auto" } } > Tundra Playground</ h1 >
45+
46+ < a href = { wikiUrl } target = "_blank" rel = "noreferrer" className = "wiki-button" > Wiki</ a >
47+
5448 < button onClick = { runCode } disabled = { isRunning } className = "run-button" >
55- < PlayIcon />
56- Run
49+ < PlayIcon /> Run
5750 </ button >
5851 </ header >
5952
@@ -62,23 +55,39 @@ export default function App() {
6255 < Panel defaultSize = { 65 } minSize = { 20 } >
6356 < Editor code = { code } setCode = { setCode } />
6457 </ Panel >
65-
66- < PanelResizeHandle className = "resize-handle" >
67- < div className = "resize-handle-bar" />
68- </ PanelResizeHandle >
58+
59+ < PanelResizeHandle className = "resize-handle" > < div className = "resize-handle-bar" /> </ PanelResizeHandle >
6960
7061 < Panel defaultSize = { 35 } minSize = { 10 } >
71- < div style = { { height : "100%" , display : "flex" , flexDirection : "column" } } >
72- < div style = { { padding : "8px" , borderBottom : "1px solid #30363d" , backgroundColor : "#161b22" } } >
73- < h2 style = { { margin : 0 , fontSize : "0.9rem" , fontWeight : 600 } } > Output</ h2 >
74- </ div >
75- < pre style = { { flex : 1 , margin : 0 , padding : "12px" , fontFamily : "monospace" , whiteSpace : "pre-wrap" , overflow : "auto" } } >
76- { output }
77- </ pre >
78- </ div >
62+ { /* Output | Bytecode */ }
63+ < PanelGroup direction = "horizontal" style = { { height : "100%" } } >
64+ < Panel defaultSize = { 50 } minSize = { 10 } >
65+ < div style = { { height : "100%" , display : "flex" , flexDirection : "column" } } >
66+ < div style = { { padding : 8 , borderBottom : "1px solid #30363d" , backgroundColor : "#161b22" } } >
67+ < h2 style = { { margin : 0 , fontSize : "0.9rem" , fontWeight : 600 } } > Output</ h2 >
68+ </ div >
69+ < pre style = { { flex : 1 , margin : 0 , padding : 12 , fontFamily : "monospace" , whiteSpace : "pre-wrap" , overflow : "auto" } } >
70+ { output }
71+ </ pre >
72+ </ div >
73+ </ Panel >
74+
75+ < PanelResizeHandle className = "resize-handle vertical" > < div className = "resize-handle-bar" /> </ PanelResizeHandle >
76+
77+ < Panel defaultSize = { 50 } minSize = { 10 } >
78+ < div style = { { height : "100%" , display : "flex" , flexDirection : "column" } } >
79+ < div style = { { padding : 8 , borderBottom : "1px solid #30363d" , backgroundColor : "#161b22" } } >
80+ < h2 style = { { margin : 0 , fontSize : "0.9rem" , fontWeight : 600 } } > Bytecode</ h2 >
81+ </ div >
82+ < pre style = { { flex : 1 , margin : 0 , padding : 12 , fontFamily : "monospace" , whiteSpace : "pre" , overflow : "auto" } } >
83+ { bytecode }
84+ </ pre >
85+ </ div >
86+ </ Panel >
87+ </ PanelGroup >
7988 </ Panel >
8089 </ PanelGroup >
8190 < Analytics />
8291 </ div >
8392 ) ;
84- }
93+ }
0 commit comments