jueves, 7 de marzo de 2024

Implementación de S"

La palabra S" (s-quote) sirva para almacenar un string constante en el heap, retornando la dirección del primer caracter y el largo, tal cual lo hace COUNT

Cuando el intérprete encuentra

s" hola chao"

genera la siguiente estructura en memoria :

                salto sobre_string
largo_string:   9
inicio_string:  h
                o
                ...
                a
                o             
sobre_string:   cargar dir_string 
                cargar largo_string

No hay instrucción de retorno, pues la palabra ha sido puesta en línea (inlining).

Este ejemplo tonto es una palabra que crea un string con una expresión ( 1 1 + ). El string se entrega al intérprete, que lo ejecuta, imprimiendo el resultado.

: x
s" 1 1 + " evaluate . ;

Y asi luce en memoria:

>: x s" 1 1 + " evaluate . ;

>see x
 a94  a9c     ; Salto sobre el string a la dirección a9c.
 a95  6       ; Largo del string.
 a96  31      ; 1
 a97  20      ; espacio
 a98  31      ; 1
 a99  20      ; espacio
 a9a  2b      ; +
 a9b  20      ; espacio
 a9c  8a96    ; Carga el stack con 0xa96, dir comienzo string
 a9d  8006    ; Carga el stack con 6, el largo.
 a9e  4037    ; Llamada a EVALUATE.
 a9f  93c     ; Llamada a . (imprime tope del stack)
 aa0  608c    ; return

Implementación

: s"
    0x22 word     \ El contenido del texto
    dup @ 1+      \ ( -- addr largo+1 )
    here swap     \ ( -- addr here largo+1 )
    2dup + 1+ ,   \ Salto sobre el contenido del string
    dup allot
    swap 1+ swap  \ Correr el comienzo para hacer espacio al jump
    2dup >r >r    \ ( -- addr here largo+1 : R -- largo+1 here )
    cmove         \ ( --  : R -- largo+1 here )
    r>
    1+
    dup 0x7FFF invert or ,
    r>
    1-
    dup 0x7FFF invert or ,
    swap
    ; immediate

Nota: Una celda con el bit superior en 1 es una instrucción que carga en el stack el contenido de los bits 14-0. Para transformar un valor (6, por ejemplo) en una instrucción de carga, hay que poner el bit 15 en uno. La secuencia 

0x7FFF invert

produce el valor 0x8000, y luego or con el valor deseado resulta en la instrucción de carga (en este caso, 0x8006) que se grabara en memoria. 


No hay comentarios.:

Publicar un comentario