Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <html>
- <head>
- <title>Intento JS interprete? </title>
- <style type="text/css" media="screen">
- #big {
- background: #000000;
- width: 100px;
- height: 100px;
- position: relative;
- }
- #-codigo {
- position: relative;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- height: 250px;
- }
- /*<![CDATA[*/
- .content-columns {
- /* Setting relative positioning allows for
- absolute positioning for sub-classes */
- position: relative;
- padding-top: 1em;
- }
- .content-column-left {
- /* Value for IE/Win; will be overwritten for other browsers */
- width: 47%;
- padding-right: 3%;
- float: left;
- padding-bottom: 2em;
- }
- .content-column-left hr {
- display: none;
- }
- .content-column-right {
- /* Values for IE/Win; will be overwritten for other browsers */
- width: 47%;
- padding-left: 3%;
- float: left;
- padding-bottom: 2em;
- }
- .content-columns>.content-column-left, .content-columns>.content-column-right {
- /* Non-IE/Win */
- }
- img {
- border: 2px solid #fff;
- padding: 2px;
- margin: 2px;
- }
- a:hover img {
- border: 2px solid #f50;
- }
- /*]]>*/
- </style>
- <script type="text/javascript">
- /* Contacto afperrens@gmail.com */
- /* Observaciones previas; Para que funcione correctamente, el
- navegador deberia estar al 100% de zoom, y preferiblemente no
- deberian llamarse varias veces las funciones de setteo inicial
- aunque ya estan cubiertos esos casos en el codigo
- VARIABLES GLOBALES QUE SE SETTEAN PREFERIBLEMENTE EN MAIN
- variables que no pueden ser pasadas por parametro */
- var globalCampo;
- // puede que haya dos robots?
- var globalRobot;
- // ancho de las calles, para cambiar en caso de ser necesario, solo
- // tocar esta (no tiene que ser un numero primo):
- var globalSideBlock = 11;
- // donde se guardan todos los comandos globales
- var globalCom;
- // FUNCIONES DEL ROBOT
- function drawRobot(campo){
- if(document.getElementById("ROBOT") == null){
- // Se genero Robot?, si no, continuo
- // todas las ordenes que recibe de movimientos empiezan
- // en una coordenada y luego dependiendo de la posicion
- // se puede mover hacia arriba, abajo, izquierda o derecha
- // siempre de a 10px; Para los movimientos de izquerda
- // a derecha, solo se puede girar abajo o arriba si la
- // posicion es multiplo de 20 o 0, lo mismo sucede con
- // los movimientos de izquierda a derecha cuando se este
- // moviendo de arriba hacia abajo
- var robot = drawObjeto(campo,"#AAAAAA");
- robot.id = "ROBOT";
- robot.style.left = "0px";
- robot.style.top = "0px";
- robot.style.color = "#222DDD";
- robot.style.fontSize = "8px";
- robot.textContent = "R";
- // creo una variable para saber la orientacion del robot
- // del 1 al 4, por default 1
- robot.orientacion = 1;
- // ENERGIA DEL ROBOT, arranca con 100
- robot.energia = 100;
- return robot;
- } else {
- // por alguna extraña y misteriosa razon, javascript retorna
- // un return aunque este dentro de un if que no se cumpla
- // por mas redundante que parezca este else, es la unica
- // manera de evitar un error si se llama dos veces la funcion
- return globalRobot;
- }
- }
- function moverRobot(robot,alertas){
- // alertas determina si se avisa cuando colisiona o se cae, 1 true 0 false
- // trabaja con el ROBOT que se definio anteriormente y dentro de campo
- if(robot.energia != 0){ // tiene energia?
- if(robot.orientacion == 1 && ((parseInt(robot.style.top)%(globalSideBlock*2) == 0) || (parseInt(robot.style.top) == 0)) ){
- robot.style.left = (parseInt(robot.style.left) + globalSideBlock).toString() + "px";
- }
- if(robot.orientacion == 2 && ((parseInt(robot.style.left)%(globalSideBlock*2) == 0) || (parseInt(robot.style.left) == 0)) ){
- robot.style.top = (parseInt(robot.style.top) + globalSideBlock).toString() + "px";
- }
- if(robot.orientacion == 3 && ((parseInt(robot.style.top)%(globalSideBlock*2) == 0) || (parseInt(robot.style.top) == 0)) ){
- robot.style.left = (parseInt(robot.style.left) - globalSideBlock).toString() + "px";
- }
- if(robot.orientacion == 4 && ((parseInt(robot.style.left)%(globalSideBlock*2) == 0) || (parseInt(robot.style.left) == 0)) ){
- robot.style.top = (parseInt(robot.style.top) - globalSideBlock).toString() + "px";
- }
- // se cayo?
- if(cayoRobot(robot) && alertas){
- alert("[El robot se cayo del campo]\n## Colocandolo en posicion inicial \n" +
- "## Restaurando orientacion a derecha \n" +
- "## -10 de energia");
- robot.energia -= 10;
- }
- // colisiono?
- var col = colisionRobot(robot);
- if(col && alertas){
- alert("el robot ha colisionado con " + col);
- }
- // si no sucedio ningun error, se retorna true
- return 1;
- } else {
- // alerta obligatoria
- alert("ROBOT se ha quedado sin energia");
- return 0;
- }
- }
- function cayoRobot(robot){
- if(!((0 <= parseInt(robot.style.top)) && (parseInt(robot.style.top) < parseInt(globalCampo.style.height))) ||
- !((0 <= parseInt(robot.style.left)) && (parseInt(robot.style.left) < parseInt(globalCampo.style.width)))){
- // por alguna razon, Javascript no puede evaluar correctamente la condicion
- // (0 > parseInt(globalRobot.style.left) < parseInt(globalCampo.style.width)) retornando solo
- // el valor de la primera sentencia
- robot.style.top = 0;
- robot.style.left = 0;
- robot.orientacion = 1;
- // si esto sucede, se debe retornar false
- return 1;
- } else {
- return 0;
- }
- }
- function colisionaraRobot(robot){
- /* no tengo ganas de escribir todo de nuevo, aparte reutilizamos codigo.
- Esta funcion se adelanta un movimiento y determina si al frente de el
- tiene un objeto a colisionar */
- moverRobot(robot,0);
- var col = colisionRobot(robot);
- if(col != robot.id){
- return col;
- } else {
- return 0;
- }
- // vuelvo a poner al robot apuntando al mismo lugar, en el mismo lugar
- cambiarOrientacion(robot);
- cambiarOrientacion(robot);
- moverRobot(robot);
- cambiarOrientacion(robot);
- cambiarOrientacion(robot);
- }
- function colisionRobot(robot){
- /* obtengo la posicion del robot y de alli obtengo el elemento
- que hay ahi con elementFromPoint, si no es robot es un objeto
- y lo retorno */
- var elemento = document.elementFromPoint(getPosition(robot).x,getPosition(robot).y)
- /* EN FIREFOX SI NO ESTA LA PANTALLA EN 100% NO PUEDE CORRECTAMENTE
- UBICAR LA POSICION DEL OBJETO Y POR LO TANTO NO COLISIONA
- NI MAS, NI MENOS % DE VISUALIZACION */
- if(elemento.id != robot.id){
- /* si no es robot, retorno el elemento, y que la funcion de
- arriba gestione si le resta energia o no */
- return elemento.id
- } else {
- return 0;
- }
- }
- function cambiarOrientacion(robot){
- if(robot.orientacion == 4) robot.orientacion = 1;
- else robot.orientacion += 1;
- }
- // FUNCIONES GENERALES (CAMPO Y OTRAS)
- function drawCampo(campo,xIt,yIt){
- if(document.getElementById("CAMPO") == null){
- /* Se genero campo?, si no, continuo
- dibuja el mapa
- xIt e yIt determina la cantidad de cuadras
- el tamaño en pixeles es 10 (primera calle) + 20* cantidad
- de cuadras que estoy recibiendo */
- campo.style.position = "relative";
- campo.style.height = (globalSideBlock + ((globalSideBlock*2) * yIt)).toString() + "px";
- campo.yIt = yIt; // cantidad de cuadras verticales
- campo.style.width = (globalSideBlock + ((globalSideBlock*2) * xIt)).toString() + "px";
- campo.xIt = xIt; // cantidad de cuadras horizontales
- campo.style.background = "#000000";
- campo.style.color = "#FFFFFF";
- var x;
- var y = -(globalSideBlock);
- for(var dyIt = 1; dyIt <= yIt; ++dyIt){
- y = y + globalSideBlock*2;
- x = -(globalSideBlock);
- for(var dxIt = 1; dxIt <= xIt; ++ dxIt){
- var miniCaja = drawObjeto(campo,"#FFFCCC");
- x = x + globalSideBlock*2;
- miniCaja.style.left = x.toString() + 'px';
- miniCaja.style.top = y.toString() + 'px';
- }
- }
- // para no volver a dibujar el campo si se lo llama dos veces
- campo.id = "CAMPO";
- return campo;
- } else {
- /*por alguna extraña y misteriosa razon, javascript retorna
- un return aunque este dentro de un if que no se cumpla
- por mas redundante que parezca este else, es la unica
- manera de evitar un error si se llama dos veces la funcion */
- return globalCampo;
- }
- }
- function drawObstaculo(campo){
- /* cantidad de obstaculos entre 1 y 10
- * tipo= 1: solo obstaculos, 2: solo energia, 3: ambos (NOT YET) */
- var cantidad = Math.round(Math.random()*100);
- for(var i = 1; i<=cantidad; ++i){
- var obstaculo = drawObjeto(campo,"#444FFF");
- /* para que no pisen la posicion original del robot
- * se inicia en 10 */
- obstaculo.id = "OBSTACULO";
- obstaculo.style.left = getPosicionAleatoria(globalSideBlock,campo.xIt).toString() + "px";
- obstaculo.style.top = getPosicionAleatoria(globalSideBlock,campo.yIt).toString() + "px";
- }
- return cantidad;
- }
- function getPosicionAleatoria(min, max) {
- /* Genera numero de pixel que siempre cae en la esquina de una calle
- * **********************************************************
- * Nos llevamos mal, pero a veces coqueteo con la matematica:
- * N = (((0,aleatorio) * (max-min) + min) / lado) * lado
- * **********************************************************/
- max = ((globalSideBlock*2) * max) // lo transformo a pixeles reales
- var random = Math.round((Math.random() * (max-min) + min) / globalSideBlock) * globalSideBlock;
- if(!(random % (globalSideBlock*2) == 0)) random += globalSideBlock; // sumo Lado px
- return random;
- }
- function drawObjeto(campo,color){
- /* todos los objetos como las cuadras, el robot o los obstculos
- * son iguales, luego si quieren ser transparentes y contener una
- * letra da igual, ESTA PROPIEDAD SE REPITE! */
- var objeto = document.createElement("div");
- objeto.style.background = color;
- objeto.style.width = globalSideBlock.toString() + "px";
- objeto.style.height = globalSideBlock.toString() + "px";
- campo.appendChild(objeto);
- objeto.style.position = "absolute";
- return objeto;
- }
- function getPosition(element) {
- // codigo sacado de // source of this code
- // http://www.kirupa.com/html5/get_element_position_using_javascript.htm
- // author: Kirupa Chinnathambi
- var xPosition = 0;
- var yPosition = 0;
- while(element) {
- xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
- yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
- element = element.offsetParent;
- }
- return { x: xPosition, y: yPosition };
- }
- /* FUNCIONES PARA LA INTERPRETACION DEL CODIGO
- * No se puede modificar un string pasado a una funcion por que siempre
- * se pasa por valor, hay que crear una funcion dentro de string para que
- * se permita la utilizacion de la funcion getWord */
- function parseToArray(str){
- /* convierte el str y sus separaciones en espacios y nuevas lineas en
- un arreglo, ¿Se puede hacer un arreglo tipo bag de elementos
- separadores? */
- var ret = []; // El array principal que contiene todos los datos
- var arr = []; // Array con todas las palabras
- var pila = [[],[]]; // Array que contiene las etiquetas
- var i = 0;
- var subI = -1;
- while(i < str.length){
- ++subI;
- arr[subI] = ""; // inicializo en vacio
- while(str[i] == " " ||
- str[i] == "\n"){ ++i; }
- // avanzo i hasta que no haya mas vacios
- while(str[i] != " " &&
- str[i] != "\n" &&
- i < str.length){
- arr[subI] += str[i++];
- }
- if(arr[subI][arr[subI].length - 1] == ":"){
- /* agrego las etiquetas antes que el resto de la interpretacion
- del codigo, de esta manera, puede hacerse interpretacion de
- codigo con saltos hacia etiquetas todavia no declaradas durante
- la interpretacion */
- pila[0].push(arr[subI].substr(0,arr[subI].length - 1));
- // en el 0 pongo el nombre para poder buscar
- pila[1].push(subI);
- // en el 1 pongo la instruccion que debe empezar
- }
- }
- ret[0] = arr;
- ret[1] = pila;
- return ret;
- }
- function interprete(str){
- // SIN TERMINAR
- // primero llama a la funcion que parsea el contenido
- var parseo = parseToArray(str);
- var arr = parseo[0];
- // el interprete lo que hace es tomar el arreglo de elementos
- // e ir interpretandolos a medida que van llegando
- var pila = parseo[1];
- // donde se guardan las iteraciones, puntos de llamadas y variables
- var ultOp;
- // valor numerico de la ultima operacion realizada
- for(var i = 0; i <= arr.length; ++i){
- switch(arr[i]){
- case "move":
- case "MOVE":
- // mover; mueve al robot
- moverRobot(globalRobot,1);
- break;
- case "orie":
- case "ORIE":
- // orientacion; cambia de orientacion
- cambiarOrientacion(globalRobot);
- break;
- case "call":
- case "CALL":
- // call; llama a una etiqueta
- if(++i < arr.length){
- // compruebo que exista el siguiente elemento
- i = pila[1][pila[0].indexOf(arr[i])];
- if (i == -1){ alert("ALERTA: No se encontro la etiqueta " + arr[i]); }
- // retorno el numero donde se debe empezar a ejecutar
- } else { alert("ERROR: CALL precisa de un argumento"); }
- break;
- case "nada":
- case "NADA":
- // como NOP de ASM, este comando no hace nada
- break;
- /* case "goto":
- case "GOTO":
- // goto: salta a una instruccion especifica
- if(++i < arr.length){
- // compruebo que exista el siguiente elemento
- i = parseInt(arr[i]);
- // hago que vaya a la posicion numerica indicada
- }
- break; */
- case "ente":
- case "ENTE":
- // entero: genera espacio para un entero POSITIVO
- if(++i < arr.length){
- pila[0].push(arr[i].substring(0,arr[i].indexOf(",")));
- // apilo el nombre de la variable
- pila[1].push(parseInt(arr[i].substring(arr[i].indexOf(",") + 1)));
- // apilo el valor de la variable
- }
- break;
- case "char":
- case "char":
- // char: genera espacio para un caracter
- if(++i < arr.length){
- pila[0].push(arr[i].substring(0,arr[i].indexOf(",")));
- // apilo el nombre de la variable
- pila[1].push(arr[i].substring(arr[i].indexOf(",") + 1));
- // apilo el valor de la variable
- }
- break;
- case "stri":
- case "STRI":
- // String: genera espacio para una cadena de caracteres
- // NO FUNCIONA BIEN
- if(++i < arr.length){
- pila[0].push(arr[i].substring(0,arr[i].indexOf(",")));
- // agrego lo que tenga despues de la coma en esta parte
- var aux = arr[i].substring(arr[i].indexOf(",") + 1);
- var fin = 0;
- while(i < arr.length && !fin){
- // si no contiene ; lo agrego entero
- if(arr[++i].indexOf(";") != -1){
- // si contiene ; solo agrego lo anterior
- aux += " " + arr[i].substring(0,arr[i].indexOf(";"));
- fin = 1;
- } else {
- //alert(arr[i]);
- aux += " " + arr[i];
- //alert("q " + aux);
- }
- }
- pila[1].push(aux);
- //alert(aux);
- }
- break;
- case "decr":
- case "DECR":
- // decrementar: decrementa en 1 el valor de la variable entera
- if(++i < arr.length){
- pila[1][pila[0].indexOf(arr[i])] -= 1;
- ultOp = pila[1][pila[0].indexOf(arr[i])];
- }
- break;
- case "incr":
- case "INCR":
- // incrementar: incrementa en 1 el valor de la variable entera
- if(++i < arr.length){
- pila[1][pila[0].indexOf(arr[i])] += 1;
- ultOp = pila[1][pila[0].indexOf(arr[i])];
- }
- break;
- case "jnz":
- case "JNZ":
- // JumpNoZero: salta si la ultima operacion NO dio cero
- if(ultOp != 0 && ++i < arr.length){
- i = pila[1][pila[0].indexOf(arr[i])];
- }
- break;
- case "jz":
- case "JZ":
- // JumpZero: salta si la ultima operacion DIO cero
- if(ultOp == 0 && ++i < arr.length){
- i = pila[1][pila[0].indexOf(arr[i])];
- }
- break;
- case "jmp":
- case "JMP":
- // JUMP: salto incondicional
- if(++i < arr.length){
- i = pila[1][pila[0].indexOf(arr[i])];
- }
- case "suma":
- case "SUMA":
- // suma: suma dos variables y guarda el resultado en el primero
- if(++i < arr.length){
- pila[1][pila[0].indexOf(arr[i].substring(0,arr[i].indexOf(",")))] += pila[1][pila[0].indexOf(arr[i].substring(arr[i].indexOf(",")+1))];
- }
- break;
- case "rest":
- case "REST":
- // Resta: resta dos variables y guarda el resultado en el primero
- if(++i < arr.length){
- pila[1][pila[0].indexOf(arr[i].substring(0,arr[i].indexOf(",")))] -= pila[1][pila[0].indexOf(arr[i].substring(arr[i].indexOf(",")+1))];
- }
- break;
- case "comp":
- case "COMP":
- // Comparacion: si las dos variables son iguales, pone en la
- // variable ultima Operacion el numero cero
- if(++i < arr.length){
- if(pila[1][pila[0].indexOf(arr[i].substring(0,arr[i].indexOf(",")))] ==
- pila[1][pila[0].indexOf(arr[i].substring(arr[i].indexOf(",")+1))]){
- ultOp = 0;
- }
- }
- break;
- case "mens":
- case "MENS":
- // Mensaje: Mustra el contenido de la variable en un alert
- if(++i < arr.length){
- alert(pila[1][pila[0].indexOf(arr[i])]);
- }
- break;
- case "halt":
- case "HALT":
- // HALT: interrumpe todas las operaciones y vacia el
- // array de instrucciones
- pila = [[],[]];
- arr = "";
- alert("fin de instrucciones");
- break;
- default:
- // aqui va todo lo que no es fijo o algun regEx;
- /*if(arr[i][arr[i].length - 1] == ":"){
- // llamado para etiqueta, hecho desde el parseo
- pila[0].push(arr[i].substr(0,arr[i].length - 1));
- // en el 0 pongo el nombre para poder buscar
- pila[1].push(i);
- // en el 1 pongo la instruccion que debe empezar
- }*/
- break;
- }
- }
- // retorno el arreglo con caracteres por si lo necesito despues
- return parseo;
- }
- function main(contenedor){
- // todo lo primero que debe ejecutarse y declararse
- globalCampo = drawCampo(contenedor,20,10);
- globalRobot = drawRobot(contenedor);
- var obstaculos = drawObstaculo(globalCampo);
- }
- </script>
- </head>
- <body onload="javascript:main(document.getElementById('big'));">
- <div class="content">
- <div class="content-columns">
- <div class="content-column-left">
- <textarea id="codigo">
- ente a,-2
- f: incr a
- jnz f
- orie
- orie
- move
- halt</textarea>
- <br>
- <input type="button" id="boton" value="parse code" onclick="javascript:globalCom = interprete(document.getElementById('codigo').value);" />
- <input type="button" id="boton" value="cambiar orientacion" onclick="javascript:cambiarOrientacion(globalRobot);" />
- <input type="button" id="boton" value="mover" onclick="javascript:moverRobot(globalRobot,1);" />
- <input type="button" id="boton" value="generar obstaculos" onclick="javascript:drawObstaculo(globalCampo);" />
- </div>
- <div class="content-column-right">
- <div id="big"></div>
- </div>
- </div>
- </div>
- Intento de simulador de "bajo nivel" (practicando javascript);<br>
- El objetivo (si se terminaba) era poder tener una forma mas visual de <br>
- abstraccion a bajo nivel tipo ensamblador controlando un "robot"<br>
- (visualizado como el cuadrado con la R adentro) por una "ciudad" <br>
- con obstaculos, para ofrecer una alternativa rapida a quien quiera <br>
- practicar este tipo de programacion sin tener que interpretar todo un <br>
- set de instrucciones y tener que descargar y "romper" varias veces el ensamblador <br>
- Se que hay varios sacrilegios en este codigo, pero es de prueba! sepa entender :)
- <br><br>
- contacto: afperrens@gmail.com
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement