Skip to content

Commit a689ce0

Browse files
committed
trying to merge
1 parent 24e2c21 commit a689ce0

2 files changed

Lines changed: 120 additions & 51 deletions

File tree

src/components/LevelComponent.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
import React, { useState, useEffect, useRef, useMemo } from "react";
2-
import { generatePlanetLanguage } from "../language/generator/generatePlanetLanguage";
3-
import { parseAlien } from "../language/parse/parseAlien";
4-
import { renderPython } from "../language/render/renderPython";
5-
import { renderAlien } from "../language/render/renderAlien";
6-
import { parsePythonWithTreeSitter } from "../language/parse/parsePythonWithTreeSitter";
7-
import type { ProgramNode } from "../language/types";
8-
import { validateAlienSource } from "../language/validate/validateAlienSource";
92
import OutputComponent from './OutputComponent'
103
import InfoComponent from './InfoComponent'
114

@@ -122,11 +115,11 @@ sys.stdout = io.StringIO()
122115
}
123116

124117
return (
125-
<div className="w-screen h-screen flex gap-10 p-4 font-mono overflow-hidden">
126-
<div className="flex gap-4 p-4 w-6/7 mx-auto">
118+
//<div className="w-screen h-screen flex gap-10 p-4 font-mono overflow-hidden">
119+
// <div className="flex gap-4 p-4 w-6/7 mx-auto">
127120

128-
<div className="flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3">
129-
<InfoComponent />
121+
// <div className="flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3">
122+
// <InfoComponent />
130123
<div className="w-screen h-screen flex gap-4 p-4 bg-[#0a0f2e] font-mono overflow-hidden">
131124

132125
{/* Left panel */}

src/components/OutputComponent.tsx

Lines changed: 116 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,123 @@
1-
import React, { useState, useEffect, useRef } from 'react'
1+
import React, { useState, useEffect, useRef, useMemo } from 'react'
2+
import { generatePlanetLanguage } from "../language/generator/generatePlanetLanguage";
3+
import { parseAlien } from "../language/parse/parseAlien";
4+
import { renderPython } from "../language/render/renderPython";
5+
import { renderAlien } from "../language/render/renderAlien";
6+
import { parsePythonWithTreeSitter } from "../language/parse/parsePythonWithTreeSitter";
7+
import type { ProgramNode } from "../language/types";
8+
import { validateAlienSource } from "../language/validate/validateAlienSource";
29

310
const OutputComponent = () => {
411
const [code, setCode] = useState("")
5-
const [output, setOutput] = useState("")
6-
const [pyodideReady, setPyodideReady] = useState(false)
7-
const pyodideRef = useRef<any>(null)
8-
const outputExpected = "5"
9-
useEffect(() => {
10-
const loadPyodide = async () => {
11-
// @ts-ignore
12-
pyodideRef.current = await window.loadPyodide()
13-
setPyodideReady(true)
12+
const [output, setOutput] = useState("")
13+
const [translatedPython, setTranslatedPython] = useState("");
14+
const [exampleAst, setExampleAst] = useState<ProgramNode | null>(null);
15+
const [exampleAlien, setExampleAlien] = useState("");
16+
const [exampleError, setExampleError] = useState("");
17+
const [pyodideReady, setPyodideReady] = useState(false)
18+
const pyodideRef = useRef<any>(null)
19+
const sourcePython = `
20+
nums = [1,2,3]
21+
sum = 0
22+
for i in nums:
23+
sum += i
24+
print(sum)
25+
`.trim();
26+
27+
28+
// Use a fixed seed for this level for now
29+
const lang = useMemo(() => generatePlanetLanguage(2), []);
30+
31+
useEffect(() => {
32+
const loadPyodide = async () => {
33+
// @ts-ignore
34+
pyodideRef.current = await window.loadPyodide()
35+
setPyodideReady(true)
36+
}
37+
loadPyodide()
38+
}, [])
39+
40+
useEffect(() => {
41+
let cancelled = false;
42+
43+
const parseExample = async () => {
44+
try {
45+
setExampleError("");
46+
47+
const ast = await parsePythonWithTreeSitter(sourcePython);
48+
if (cancelled) return;
49+
50+
setExampleAst(ast);
51+
setExampleAlien(renderAlien(ast, lang));
52+
} catch (err) {
53+
if (cancelled) return;
54+
setExampleError(err instanceof Error ? err.message : String(err));
55+
}
56+
};
57+
58+
parseExample();
59+
60+
return () => {
61+
cancelled = true;
62+
};
63+
}, [sourcePython, lang]);
64+
65+
const runCode = async () => {
66+
if (!pyodideRef.current) return
67+
if (!pyodideRef.current) return;
68+
69+
const validation = validateAlienSource(code, lang);
70+
71+
if (!validation.isValid) {
72+
setTranslatedPython("");
73+
setOutput(
74+
validation.issues
75+
.map(
76+
(issue) =>
77+
`Line ${issue.line}, Col ${issue.column}: ${issue.message}`,
78+
)
79+
.join("\n"),
80+
);
81+
return;
82+
}
83+
try {
84+
// 1. Alien -> AST
85+
const ast = parseAlien(code, lang);
86+
console.log(ast);
87+
// 2. AST -> Python
88+
const pythonCode = renderPython(ast);
89+
setTranslatedPython(pythonCode);
90+
91+
92+
// 3. Reset stdout
93+
await pyodideRef.current.runPythonAsync(`
94+
import sys, io
95+
sys.stdout = io.StringIO()
96+
`);
97+
98+
// 4. Run translated Python
99+
await pyodideRef.current.runPythonAsync(pythonCode);
100+
101+
// 5. Get output
102+
const result = await pyodideRef.current.runPythonAsync(`sys.stdout.getvalue()`);
103+
setOutput(String(result));
104+
} catch (err: any) {
105+
setOutput(err?.message ?? String(err));
106+
}
107+
};
108+
109+
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
110+
if (e.key === "Tab") {
111+
e.preventDefault()
112+
const el = e.target as HTMLTextAreaElement
113+
const { selectionStart, selectionEnd } = el
114+
const newValue = code.slice(0, selectionStart) + " " + code.slice(selectionEnd)
115+
setCode(newValue)
116+
requestAnimationFrame(() => {
117+
el.selectionStart = el.selectionEnd = selectionStart + 4
118+
})
119+
}
14120
}
15-
loadPyodide()
16-
}, [])
17-
18-
const runCode = async () => {
19-
if (!pyodideRef.current) return
20-
await pyodideRef.current.runPythonAsync(`
21-
import sys, io
22-
sys.stdout = io.StringIO()
23-
`)
24-
try {
25-
await pyodideRef.current.runPythonAsync(code)
26-
const result = await pyodideRef.current.runPythonAsync(`sys.stdout.getvalue()`)
27-
setOutput(result)
28-
} catch (err: any) {
29-
setOutput(err.message)
30-
}
31-
}
32-
33-
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
34-
if (e.key === "Tab") {
35-
e.preventDefault()
36-
const el = e.target as HTMLTextAreaElement
37-
const { selectionStart, selectionEnd } = el
38-
const newValue = code.slice(0, selectionStart) + " " + code.slice(selectionEnd)
39-
setCode(newValue)
40-
requestAnimationFrame(() => {
41-
el.selectionStart = el.selectionEnd = selectionStart + 4
42-
})
43-
}
44-
}
45121

46122
return (
47123
<div className="flex-1 p-3 flex flex-col gap-3">

0 commit comments

Comments
 (0)