jueves, 29 de septiembre de 2022

Primeros cambios en el interior PSeInt

Ya comenté que iba a ir refactorizando muy de a poco el horrible código de pseint. Se podría decir que hay tres grandes objetivos: unificar algoritmos repetidos, eliminar todo el estado global, y separar/independizar los más posible las etapas del proceso de análisis e interpretación. Veamos cómo y para qué.

 

Todo esto empieza, de los muchos módulos, por el que llamo pseint o "el verdadero intérprete", el que realmente analiza e interpreta el código.

Esquema de los diferentes módulos y sus funciones tomado de un post viejo
(falta todo lo relacionado a los ejercicios autocontenidos, que se agregó después).

Empecemos por el problema de la repetición de código. En este módulo había mucho código repetido, y que se repite también en otros módulos. Pseint primero analiza que la sintaxis sea correcta, y luego lo ejecuta. Para facilitar ese análisis, primero se normaliza el pseudocódigo, luego se verifica si cada instrucción tiene la forma y las partes que debe tener. El resultado, si no hay errores, es un nuevo código, con un formato mucho más estricto y con ciertas garantías de correctitud, que lo hará mucho más fácil de analizar.

La etapa de ejecución partía de ese nuevo código, y a medida que lo iba ejecutando iba realizando un segundo análisis para interpretarlo. Ese segundo análisis implicaba averiguar otra vez cosas que ya había averiguado el primero, como qué instrucción hay en cada linea, hasta dónde llega un bucle, o por ej en un Escribir de dónde hasta dónde va cada expresión a mostrar. Entonces, si bien no es código repetido en el sentido de copy-paste, sí ocurre que se vuelven a resolver cosas que ya se habían resuelto antes.

Ya logré eliminar esta repetición haciendo que el primer análisis guarde los detalles en estructuras ad-hoc para cada instrucción, en lugar de solo strings normalizados.

 Imagen tomada de otro post viejo, donde intentaba explicar cómo iba a pensar
la nueva arquitectura para una reescritura desde cero que nunca pude completar.
Aquí se ven las etapas básicas del intérprete y cómo otros módulos aprovechan cada una.

Pero ese segundo análisis está también en otros módulos. Por ej, para exportar a otros lenguajes, pseint verifica la sintaxis y guarda el código normalizado, para que psexport lo tome como entrada. Entonces, para entender ese código normalizado, psexport tiene que hacer más o menos lo mismo que hacía pseint para ejecutar. De forma similar funciona, por ej, psdraw, que también parte del código normalizado.

Todas estas soluciones diferentes a casi el mismo problema poco se parecen y nada reutilizan unas de las otras. Es obvio que hay que unificarlas. Espero que luego de algunas correcciones más, la de pseint sea una buena base para todas las demás.


De esta explicación también se deduce que en pseint hay al menos dos o tres etapas: digamos que normalización, comprobación de sintaxis, y ejecución. Las 2 primeras estaban muy acopladas, pero ya las separé. Y cuanto más siga separando (si las 3 etapas se convierten en 10 mejor), más podré reutilizar en los otros módulos. Por ej, si en una pausa del paso a paso quiero evaluar una inspección, primero tengo que normalizarla.

De igual forma, las primeras etapas se pueden reutilizar en el editor para marcar los errores en tiempo real, resaltar los bloque lógicos, llenar el panel de variables y funciones, colorear la sintaxis, mejorar el autocompletado, etc. Y estoy mencionando cosas que en alguna medida ya tengo en el editor, pero que casi no comparten código. Mejorar esto también facilitará la introducción de funcionalidades nuevas.


Y otra vez se hizo largo el post, así que dejo el detalle de los otros dos problemas para otra ocasión. Pero el primero, al menos en pseint, ya está casi resuelto, y el 2do ya está empezado. Muuuy lentamente, pero esta vez el cambio avanza.

2 comentarios:

  1. Hola, códigos muy extensos y que manejen cadenas de caracteres para simular una UI textual se pone muy lento al ejecutarse, pienso que se podría crear un kernel alternativo no tan flexible, esto es por ejemplo eliminar formas coloquiales y diversas opciones de configuración, por ej. iniciar indexación en 0 o en 1, etc. pienso que esto el resta potencia por tantas verificaciones que debe hacer mientras se ejecuta, un modo normalizado alternativo daría pie a que se pueda interpretar un código en otros lenguajes (brasilero, catalán, gallego, ...) y muchos mas estudiantes a nivel terráqueo lo utilizarían

    ResponderEliminar