r3 el sucesor de r4

47 views
Skip to first unread message

Pablo Hugo Reda

unread,
Sep 28, 2018, 11:13:23 PM9/28/18
to reda4
Para probarlo  y comentar.

en DESARROLLO

https://rawgit.com/r3www/r3/master/index.html


Pablo Hugo Reda

unread,
Jan 3, 2019, 10:20:12 AM1/3/19
to reda4
Suspendi el desarrollo en js por bien de mi salud. Y comencé con la generacion de codigo para r3.

El compilador se divide en pasadas.

1era pasada: carga en memoria el archivo a compilar, la primera posicion de esta memoria esta indicada con #src 
recorre y carga a continuacion cada include que necesita generando la lista ordenada por las llamadas.
Contar la cantidad de definiciones, 

* falta *
definir con comentarios algun tipo de indicacion a compilador para ajustar, por ejemplo, el destino (x86, x64, ARM, WEB, etc), formas de IO, graficos, DOM, camara, joy, teclado, etc

Una vez terminada esta pasada se tiene en memoria los fuentes que se necesitan, y la cantidad de palabras definidas en todo este codigo.


eas lab

unread,
Jan 4, 2019, 7:48:27 AM1/4/19
to re...@googlegroups.com
I previously read that the latest version omitts COLORED syntax.
Then I saw a video of some <reda> usage;
where it was obvious from the operator's speed that s/he was very fluent.
Syntax HiLiting or coloring is a MASSIVE help for users who only use the
particular system occasionally.
Of course there is a tendency to minimise, abreviate, abreviate.
But that prevents entry of new users.
If there is a path from "use by beginners" to "version for fluent users",
that's OK. But I won't be spending time on r3/r4 which has no syntax-coloring.
> --
> Has recibido este mensaje porque estás suscrito al grupo "reda4" de Grupos
> de Google.
> Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes,
> envía un correo electrónico a reda4+un...@googlegroups.com.
> Para obtener más opciones, visita https://groups.google.com/d/optout.
>

Pablo Hugo Reda

unread,
Jan 4, 2019, 7:58:44 AM1/4/19
to reda4
Welcome

Syntax Coloring is part of the IDE, not the lang !
Is very easy coloring code in r3/r4 for the nature of prefix.
r3 have the code for coloring but not link in ACE editor.



Pablo Hugo Reda

unread,
Jan 4, 2019, 10:33:00 AM1/4/19
to reda4
Cuando se ejecuto la pasada 1 esta en memoria todo el código necesario para compilar, con el orden en las variables

#:inc )( $fff
#:inc> 'inc

La pasada 2 se encarga de tokenizar todo el código ademas de construir el diccionario de palabras.
Ambas estructuras de acomodan en memoria gracias al calculo de cantidad de token requeridos y definiciones que se calcularon en la pasada anterior.
En este momento estoy registrando también los bloques de codigo con el calculo de significado, WHILE o IF segun esten el condicional adentro o afuera del bloque.

Si esta pasada es exitosa, o sea, no retorna error, ya tenemos en memoria el programa entero tokenizado.




Pablo Hugo Reda

unread,
Feb 22, 2019, 6:30:36 PM2/22/19
to reda4
La 3ra pasada del compilador se encarga de calcular el flujo de ejecucion estatico.


Esta es una de las grandes diferencias con el forth, r4 y r3 al ser lenguajes compilados, es posible calcular que partes de codigo va a ser ejecutado o las variables que son usadas.

El algoritmo utiliza la memoria libre como pila.
Pone primero en pila la palabra de booteo ":", la marca como visitada y empieza a recorrer en forma recursiva, marcando y llamado cada palabra definida.

Si es una definicion de datos, todas las palabras son direcciones.
Si es codigo, pueden aparecer palabras y direcciones.

Cuando una palabra es llamada como direccion se marca en un flag en el diccionario, esto sirve para saver si una variable se modifica o no (si no se usa su direccion no se puede modificar) y es posible calcular si es una constante.

Al final del reccorrido, quedan marcadas todas las palabras que se utilizaros, se puede saber cuales son codigo y variables no utilizadas.


Pablo Hugo Reda

unread,
Feb 23, 2019, 10:43:14 AM2/23/19
to reda4
Cuarta pasada del compilador, quizas pueda unirse a la tercera pero como no esta todo terminado lo dejo asi por ahora.


Lo que voy a hacer aqui es calcular la profundidad del uso de la pila en cada palabra, lo necesito para simular la pila mientras busque si puedo reemplazar las celdas de la pila con registros del asm.
En esta etapa solo calculo esta profundidad en las palabras que se usan.
Las variables son recorridas para clasificarlas en lo que contienen, puede ser un valor, una direccion de codigo, una direccion de datos, un lista de numeros o direcciones, un buffer, etc.
Las palabra con codigo son recorridas calculando el uso de la pila:
Para este calculo encontre la siguiente solucion:
Por cada palabra definida tengo dos valores, el uso de la pila y el delta de la pila, asi

DUP usa el tope de la pila y agrega una celda entonces USO sera 1 y DELTA sera +1
DROP usa el tope de la pila (porque lo va a quitar) y el delta sera -1
+ usa 2 valores de la pila y quita el tope -1

Esta informacion se guarda en el diccionario por cada palabra junto con algunas banderas (flags) sobre caracteristicas de las definiciones.

Hay que tener en cuenta las estructuras de control, ya que la pila tiene un comportamiento particular.

un IF "?? (  ..)" puede terminar con FIN ";" y el estado de la pila sera el estado final de la pila, la otra rama del flujo de ejecucion debe continuar como si no entrase en el bloque.

un WHILE "( .. ??  )" sale con la pila en el estado donde se ejecuta el condicional.

Para esto se mantiene una pila de estado de la pila, la palabra ( apila el estado y la palabra ) desapila este estado, esto produce el resultado requerido en el IF.
En el caso que se encuentre un condicional que corresponda a un while lo que hara es quitar el estado de pila que esta y poner el estado actual.
Se utiliza el diccionario que cuando se llama a una palabra con el calculo de USADA y DELTA que se guardo anteriormente.

Se guarda el nivel de palabra, esta idea consiste en marcar las definiciones de codigo con nivel 1 cuando solamente utiliza palabra de base, con nivel 2 cuando utiliza palabras de base y de nivel 1 y asi sucesivamente. 

Todabia no hay ningun control de este calculo pero es posible encontrar muchos errores en la definicion, por ejemplo, que la pila tenga diferentes tamaños de pila en bloques o en diferentes finales. Esto es motivo de diseño del lenguaje, forth no tiene este tipo de limitaciones, r4 tampoco pero creo que es conveniente limitar este comportamiento en post de un lenguaje menos problematico.

En r3 tome la decision de no permitir cambios en la pila R entre palabras, aqui puede detectarse este caso.


 

Pablo Hugo Reda

unread,
Feb 26, 2019, 2:47:10 PM2/26/19
to reda4
Una vez que corrieron las 4 pasadas tenemos en memoria:

- Todo el codigo fuente necesario para compilar el programa
- Todo el codigo tokenizado
- La indicacion de los bloques 
- El diccionario lleno con el total de definiciones e informacion adicional de cada palabra.

La generacion del codigo se divide en dos partes, la definicion de datos y la compilacion de codigo:

La definicion de datos:

Fuente:

Este palabra recorre dos veces el diccionario:

primero todas las palabras que son codigo y que tienen llamadas (que son usadas), se buscan los string constantes y se les asigna un numero consecutivo

por ejemplo:


:decirhola "hola" print ;


Si esta palabra es usada, el string "hola" sera generado en la definicion de datos como


str1 db
"hola",0


Como el recorrido en la generacion de codigo es unico, el valor asignado sera el correcto cuando se compile,en, por ejemplo:


mov eax
,str1


Una vez que se generaron todos los strings, se procede al segundo recorrido del diccionario.
Tomando solamente las variables que tengan llamadas y que no sean constantes (se haya usado su direccion) 
por ejemplo


#variable 33



genera la siguiente definicion


W0 dd
33



Notar aqui que las palabras son reemplazadas por W+nro de palabra, esto evita los caracteres ilegales para el ensamblador, en este caso el FASM.
Aqui esta construida la logica de las difirentes formas de generar datos, por ejemplo el * que reserva lugares


#buffer * 1024



genera


W1 rb
1024


Esta etapa no es especialmente complicada, y la mayoria de los compiladores construidos para r4 utilizan casi el mismo codigo.

Hago una especial indicacion que esta familia de lenguajes recomienda utilizar el mapa de memoria que se genera en el codigo y por lo tanto no modifica la posicion de las variables, con esto es posible saber que una direccion de variable puede ser limite de otra y cosas por el estilo.
Por lo tanto no se alinea la memoria entre variables ni se reordena.




Pablo Hugo Reda

unread,
Mar 4, 2019, 5:08:38 PM3/4/19
to reda4
Hasta aqui fue todo el desarrollo en el compilador que puede avanzar sin mayores complicaciones, el uso de cada pasada en el nuevo compilador de r3 fue casi copiar y usar de lo que habia hecho hasta el momento.

Lo que sigue a continuacion es la busqueda de realizar un compilador que genere codigo muy optimizado.

Escribo esta bitacora mientras exploro la mejor forma de obtener este codigo.

La compilacion directar se inificiente ya que la mayor parte del tiempo esta apilado y despilando valores que pudieran estar en registros.

Entonces en este punto la forma de compilar en tratar de simular la pila con la utilizacion de registros.

La generacion de codigo se produce en:


Aqui, para cada palabra a compilar genero en un buffer el codigo, de esta manera puedo realizar cambios en el codigo antes de generarlo, por ejemplo:

Ya realizados:


* Convertir un variable en constante, transformando el codigo de variables en el mismo numero que representa.

#cte 4
:ej cte * ;

genera

:ej 4 * ;


* Convertir multiplicacion por potencias de 2 en corrimientos.

:ej 4 * ;

genera

:ej 2 << ;


* Convertir divisiones por constantes en inversos multiplicativos.

:ej 10 / ;

genera

:ej $66666667 $22 32 - *>> ;

 
* Realizar calculos con constantes en vez de compilarlos.

:ej 3 4 + ;

genera

:ej 7 ;


Todavia no implementados (al dia de hoy)


* Copiar codigo INLINE, cuando sea posible o deseable

:ej var 2 + ;
:ej2  2 ej * ;

genera

:ej2 2 var 2 + * ;


* Utilizar las definiciones que solamente retornen resultados y que no utilicen memoria, cuando los parametros son constantes,

:ej 1 2 min ;

genera, suponiendo que esta definida con codigo min

:ej 1 ;


Esta compilacion a buffer es una transformacion que no es especifica de cada procesador.
:r4 ya posee muchas de estas optimizaciones.



Pablo Hugo Reda

unread,
Mar 9, 2019, 5:49:15 PM3/9/19
to reda4
Decidi no complicar el compilador por ahora y tomar un camino mas simple pero menos potente en el resultado.

La compilacion de r3 puede hacerce con una correspondencia 1 a 1 entre codigo asm y codigo r3, pero, la mayor parte del tiempo se estan apilando y desapilando valores.
Lo que tratare de hacer es mantener una pila virtual y tratar de resolver cuando pasarla a la pila real o mantenerla en registros de manera conservadora primero.

Pablo Hugo Reda

unread,
Mar 18, 2019, 9:20:08 PM3/18/19
to reda4
El paso mas interesante y todabia en desarrollo es la generación de código.

Como resumen de lo que obtuve hasta el momento puedo decir que mientras mas registros use, mas rápido va a ser el código, ya que no tendrá que ir a memoria y volver cuando lo necesite.

En esto esta muy relacionado con la especificacion del código como RPN. El programador puede darse cuenta cuando un valor se obtiene y cuando se deja de usar, va a tratar de generarlo u obtenerlo una vez, usarlo en todos los lugares posibles, y finalmente descartarlo o grabarlo en donde corresponda.

Este seguimiento, muchas veces genera una reestructuracion en el código para conseguir que este valor no este cargandose y grabandose en varios puntos, por ejemplo en los sistemas de partículas, cuando se procesa una partícula va a ser mas optimo solamente cargar una vez a registros los parámetros, calcular, dibujar y finalmente grabar el estado.

Reply all
Reply to author
Forward
0 new messages