@@ -2,122 +2,84 @@ import React, { useState, useEffect, useRef, useMemo } from 'react'
22import { generatePlanetLanguage } from "../language/generator/generatePlanetLanguage" ;
33import { parseAlien } from "../language/parse/parseAlien" ;
44import { 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" ;
85import { validateAlienSource } from "../language/validate/validateAlienSource" ;
96
107const OutputComponent = ( ) => {
118 const [ code , setCode ] = useState ( "" )
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-
9+ const [ output , setOutput ] = useState ( "" )
10+ const [ translatedPython , setTranslatedPython ] = useState ( "" ) ;
11+ const [ pyodideReady , setPyodideReady ] = useState ( false )
12+ const pyodideRef = useRef < any > ( null )
13+ const outputExpected = "5"
2714
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- }
15+ // Use a fixed seed for this level for now
16+ const lang = useMemo ( ( ) => generatePlanetLanguage ( 2 ) , [ ] ) ;
17+
18+ useEffect ( ( ) => {
19+ const loadPyodide = async ( ) => {
20+ // @ts -ignore
21+ pyodideRef . current = await window . loadPyodide ( )
22+ setPyodideReady ( true )
23+ }
24+ loadPyodide ( )
25+ } , [ ] )
26+
27+ const runCode = async ( ) => {
28+ if ( ! pyodideRef . current ) return
29+ if ( ! pyodideRef . current ) return ;
30+
31+ const validation = validateAlienSource ( code , lang ) ;
32+
33+ if ( ! validation . isValid ) {
34+ setTranslatedPython ( "" ) ;
35+ setOutput (
36+ validation . issues
37+ . map (
38+ ( issue ) =>
39+ `Line ${ issue . line } , Col ${ issue . column } : ${ issue . message } ` ,
40+ )
41+ . join ( "\n" ) ,
42+ ) ;
43+ return ;
44+ }
45+ try {
46+ // 1. Alien -> AST
47+ const ast = parseAlien ( code , lang ) ;
48+ console . log ( ast ) ;
49+ // 2. AST -> Python
50+ const pythonCode = renderPython ( ast ) ;
51+ setTranslatedPython ( pythonCode ) ;
52+
53+
54+ // 3. Reset stdout
55+ await pyodideRef . current . runPythonAsync ( `
56+ import sys, io
57+ sys.stdout = io.StringIO()
58+ ` ) ;
59+
60+ // 4. Run translated Python
61+ await pyodideRef . current . runPythonAsync ( pythonCode ) ;
62+
63+ // 5. Get output
64+ const result = await pyodideRef . current . runPythonAsync ( `sys.stdout.getvalue()` ) ;
65+ setOutput ( String ( result ) ) ;
66+ } catch ( err : any ) {
67+ setOutput ( err ?. message ?? String ( err ) ) ;
68+ }
69+ } ;
70+
71+ const handleKeyDown = ( e : React . KeyboardEvent < HTMLTextAreaElement > ) => {
72+ if ( e . key === "Tab" ) {
73+ e . preventDefault ( )
74+ const el = e . target as HTMLTextAreaElement
75+ const { selectionStart, selectionEnd } = el
76+ const newValue = code . slice ( 0 , selectionStart ) + " " + code . slice ( selectionEnd )
77+ setCode ( newValue )
78+ requestAnimationFrame ( ( ) => {
79+ el . selectionStart = el . selectionEnd = selectionStart + 4
80+ } )
12081 }
82+ }
12183
12284 return (
12385 < div className = "flex-1 p-3 flex flex-col gap-3" >
0 commit comments