Skip to content

Commit

Permalink
expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
dlopezalvas committed Jul 22, 2024
1 parent ae6d720 commit 77233a4
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 84 deletions.
81 changes: 2 additions & 79 deletions src/components/challengeView/SceneButtons/Execute.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { Button } from "@mui/material"
import { workspaceToCode } from "../../blockly/blockly"
//@ts-ignore
import Interpreter from 'js-interpreter'
//@ts-ignore
import beautify from 'js-beautify'
import { scene } from "../Scene/scene"
import { scene } from "../scene"
import { interpreterFactory } from "./interpreter-factory"

export const ExecuteButton = () => {

Expand All @@ -21,12 +17,10 @@ export const ExecuteButton = () => {
const executeInterpreter = (interpreter: any) => {
try {
moreToExecute = interpreter.run();
console.log("Mas para ejecutar: ", moreToExecute)
} catch (e) {
console.log(e);
reject(e);
}

if (moreToExecute) {
setTimeout(executeInterpreter, 10, interpreter)
} else {
Expand All @@ -41,74 +35,3 @@ export const ExecuteButton = () => {
return <Button variant="contained" color="success" onClick={handleExcecute}>{"Ejecutar"}</Button>

}

class InterpreterFactory {
createInterpreter(): any { ///TODO tipo
console.log(this.wrappedCode())
return new Interpreter(this.wrappedCode(), (interpreter: any, scope: any) => {
return this.init(interpreter, scope);
})
}

init(interpreter: any, scope: any): any {
interpreter.setProperty(scope, 'out_hacer', interpreter.createAsyncFunction(this.do_wrapper));
interpreter.setProperty(scope, 'highlightBlock', interpreter.createNativeFunction(this.highlightBlock));
}


/**
* Generates the function "out_hacer", which will be called in the interpreter
*
* This method will chain two behaviours to simplify the use of async functions. It
* will add the behaviour that represents the action the user wants to do wih the actor,
* and then it will add another behaviour to indicate the async task finished.
*
* For example, if the code calls the function "hacer" this way:
*
* hacer("Saltar", {});
*
* hacer("Caminar", {pasos: 20});
*
* Internally, the function will make the actor first jump ("Saltar") and then walk
* ("caminar") 20 steps ("pasos").
*
* @param behaviour
* @param params
* @param callback
*/
do_wrapper(behaviour: any, params: any, callback: any) {
const actor = scene.sceneActor()
params = params ? params.toString() : '';
params = JSON.parse(params);
var behaviourClass = scene.behaviourClass(behaviour ? behaviour.toString() : '')

if (typeof params.receptor === 'string') {
params.receptor = scene.sceneReceptor(params.receptor)
}

actor.hacer_luego(behaviourClass, params);
actor.hacer_luego(scene.behaviourClass('LlamarCallback'), { callback });
};

highlightBlock(id: string){
console.log(id)
}

wrappedCode(): string {
return beautify.js(`
var actor_id = 'demo'; // se asume el actor receptor de la escena.
function hacer(id, comportamiento, params) {
out_hacer(comportamiento, JSON.stringify(params));
}
function main() {
${workspaceToCode()}
}
main();
`);
}
}

export const interpreterFactory = new InterpreterFactory()
86 changes: 86 additions & 0 deletions src/components/challengeView/SceneButtons/interpreter-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { workspaceToCode } from "../../blockly/blockly"
//@ts-ignore
import Interpreter from 'js-interpreter'
//@ts-ignore
import beautify from 'js-beautify'
import { scene } from "../scene"


class InterpreterFactory {
createInterpreter(): any { ///TODO tipo
console.log(this.wrappedCode())
return new Interpreter(this.wrappedCode(), (interpreter: any, scope: any) => {
return this.init(interpreter, scope);
})
}

init(interpreter: any, scope: any): any {
interpreter.setProperty(scope, 'out_hacer', interpreter.createAsyncFunction(this.doWrapper))
interpreter.setProperty(scope, 'highlightBlock', interpreter.createNativeFunction(this.highlightBlock))
interpreter.setProperty(scope, 'evaluar', interpreter.createNativeFunction(this.evaluateWrapper))
}

/**
* Generates the function "out_hacer", which will be called in the interpreter
*
* This method will chain two behaviours to simplify the use of async functions. It
* will add the behaviour that represents the action the user wants to do wih the actor,
* and then it will add another behaviour to indicate the async task finished.
*
* For example, if the code calls the function "hacer" this way:
*
* hacer("Saltar", {});
*
* hacer("Caminar", {pasos: 20});
*
* Internally, the function will make the actor first jump ("Saltar") and then walk
* ("caminar") 20 steps ("pasos").
*
* @param behaviour
* @param params
* @param callback
*/
doWrapper(behaviour: any, params: any, callback: any) {
const actor = scene.sceneActor()
params = JSON.parse(params ? params.toString() : '')
var behaviourClass = scene.behaviourClass(behaviour ? behaviour.toString() : '')

if (typeof params.receptor === 'string') {
params.receptor = scene.sceneReceptor(params.receptor)
}

actor.hacer_luego(behaviourClass, params);
actor.hacer_luego(scene.behaviourClass('LlamarCallback'), { callback });
};

highlightBlock(id: string) {
console.log(id) //TODO
}

/**
* This is the code that executes with an expression (sensor, operation, etc)
* @param expression
* @returns
*/
evaluateWrapper(expression: any) {
return scene.evaluateExpression(expression ? expression.toString() : '')
}

wrappedCode(): string {
return beautify.js(`
var actor_id = 'demo'; // se asume el actor receptor de la escena.
function hacer(id, comportamiento, params) {
out_hacer(comportamiento, JSON.stringify(params));
}
function main() {
${workspaceToCode()}
}
main();
`);
}
}

export const interpreterFactory = new InterpreterFactory()
2 changes: 1 addition & 1 deletion src/components/challengeView/SceneView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Challenge } from "../../staticData/challenges"
import { PBCard } from "../PBCard"
import { scene } from "./Scene/scene"
import { scene } from "./scene"
import { useMediaQuery } from "@mui/material"
import { useThemeContext } from "../../theme/ThemeContext"
import { useState } from "react"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { adaptURL } from "../../../scriptLoader";
import { Challenge } from "../../../staticData/challenges";
import { adaptURL } from "../../scriptLoader";
import { Challenge } from "../../staticData/challenges";

class Scene {
iframe(): HTMLIFrameElement {
Expand Down Expand Up @@ -42,11 +42,11 @@ class Scene {
})
}

listenToIframeMessages() {
listenToIframeMessages() {
window.addEventListener("message", (event) => {
// exercises post error messages in the form { tipo: "error", error: object }
// where object can be any error or { name: "ActividadError", message: "description"}
if(event.data.tipo === "error")
if (event.data.tipo === "error")
console.log(`Pilasweb execution ended with error: ${JSON.stringify(event.data.error)}`)
})
}
Expand Down Expand Up @@ -107,6 +107,17 @@ class Scene {
comportamiento;
`)
}

evaluateExpression(expression: string) {
return this.eval(`
try {
var value = pilas.escena_actual().automata.${expression}
} catch (e) {
pilas.escena_actual().errorHandler.handle(e);
}
value`)
}
}

export const scene = new Scene()

0 comments on commit 77233a4

Please sign in to comment.