# Introduction

Ce didacticiel est destiné aux nouveaux utilisateurs de la Simple Virtual Machine.

Dans ce didacticiel, vous allez utiliser les pointeurs comme des tableaux.

Le temps de lecture de ce didacticiel est estimé à 20 minutes si les adresses mémoire et les pointeurs ont déjà été abordés.

# Mise en place

Pour commencer, créez le canevas de l'application dans le fichier exécutable tableau.svm en utilisant ce code :

    #!/usr/bin/env svm
    DESCRIPTION
    Array example
    END
    LOG
    DEBUG "Array" STYLE "default"
    PLUGIN "svmcom.so"
    PLUGIN "svmint.so"
    PLUGIN "svmstr.so"
    OPTION -s MULTIPLE STR array
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    	END
    	MEMORY array
    END

# Une autre interprétation des pointeurs

Lancez l'application en mode débugueur avec ces options :

    ./tableau.svm -s a -s b -s c -s d -s e -d 8080

Puis ouvrez le débugueur et affichez la mémoire. Enfin, mettez en surbrillance la zone mémoire du pointeur "array" :

Array
Memory - K main - P application

Address | Type | Value
--- | --- | ---
&0 | STR | "a"
&1 | STR | "b"
&2 | STR | "c"
&3 | STR | "d"
&4 | STR | "e"

Alias | Pointer
--- | ---
array | &0*5

Address:
Display
Aliases
P
Focus
Back
Clear

Le pointeur lié à l'alias "array" permet, comme vu précédemment, de référencer plusieurs valeurs.

Ces valeurs sont placées dans la mémoire à des adresses contigües et peuvent être vues comme des valeurs mises dans un tableau. En effet :

- la taille du pointeur correspond à la taille du tableau, à savoir le nombre de valeurs du tableau,
- l'opérateur qui calcule une adresse intra-pointeur à partir de la position dans le pointeur est aussi une opération d'accès aux valeurs du tableau par indice.

# Parcours de tableau

L'interêt principal d'un tableau est de pouvoir facilement appliquer les mêmes opérations sur toutes les valeurs d'un tableau.

La première étape consiste à créer une adresse avec un entier, qui servira d'indice dans le tableau. Pour cela, ajoutez ce code :

    #!/usr/bin/env svm
    DESCRIPTION
    Array example
    END
    LOG
    DEBUG "Array" STYLE "default"
    PLUGIN "svmcom.so"
    PLUGIN "svmint.so"
    PLUGIN "svmstr.so"
    OPTION -s MULTIPLE STR array
    PROCESS "application"
    	CODE "main" INLINE
    		:memory INT/index
    		0 -> &index
    		:debug BREAK
    		:com.message @(array/@&index)
    	END
    	MEMORY array
    END

L'application ainsi modifiée peut être lancée avec les mêmes options sans le débugueur :

    ./tableau.svm -s a -s b -s c -s d -s e

Elle affiche alors :

    a

Si vous la lancez dans le débugueur, vous devez voir dans la mémoire l'alias "index" défini avec sa première adresse ayant la valeur 0. Ainsi, l'application a lu la première valeur du tableau "array".

## Modification de l'indice

Pour modifier l'indice, modifiez le code pour obtenir :

    #!/usr/bin/env svm
    DESCRIPTION
    Array example
    END
    LOG
    DEBUG "Array" STYLE "default"
    PLUGIN "svmcom.so"
    PLUGIN "svmint.so"
    PLUGIN "svmstr.so"
    OPTION -s MULTIPLE STR array
    PROCESS "application"
    	CODE "main" INLINE
    		:memory INT/index
    		0 -> &index
    		:debug BREAK
    		:com.message @(array/@&index)
    		:shift &index
    		:com.message @(array/@&index)
    	END
    	MEMORY array
    END

Une fois lancée, l'application toujours lancée avec les mêmes options affiche :

    a
    b

Cette fois, les deux premières valeurs du tableau ont été affichées par deux instructions rigoureusement identiques.

L'instruction `:shift` est celle qui modifie l'indice du tableau, en ajoutant 1 à l'entier stocké en mémoire à l'adresse `&index`.

L'instruction `:shift` modifie un entier stocké en mémoire, en indiquant à quelle adresse il se trouve.

- Par défaut, l'entier est augmenté de 1.
- Il est possible de préciser une autre valeur en l'intercalant entre l'instruction et l'adresse : `:shift valeur adresse`.

## Condition de non-dépassement

Si on tient à parcourir tout le tableau en s'adaptant à sa taille avec le même code, il faut inclure un saut. Modifiez le code :

    #!/usr/bin/env svm
    DESCRIPTION
    Array example
    END
    LOG
    DEBUG "Array" STYLE "default"
    PLUGIN "svmcom.so"
    PLUGIN "svmint.so"
    PLUGIN "svmstr.so"
    OPTION -s MULTIPLE STR array
    PROCESS "application"
    	CODE "main" INLINE
    		:memory INT/index
    		0 -> &index
    		:debug BREAK
    	:label array
    		:com.message @(array/@&index)
    		:shift &index
    		:goto array
    	END
    	MEMORY array
    END

Et relancez une nouvelle fois (en mode débugueur à votre convenance) avec les mêmes options. On obtient :

    a
    b
    c
    d
    e
    ### Simple Virtual Machine 1234 : PROCESS application | 2023-01-01 00:00:00 GMT ######################################################################
    Kernel interrupted: @(main, line 5) Interruption MEMORY not handled: Index 5 is outside pointer &0*5.

    Core dump:
    Kernel:
    State: I, transmit_interruption, interrupted @(main, line 5) Interruption MEMORY not handled: Index 5 is outside pointer &0*5.

    Processor:
     State:
       Next instruction: <main:1/4> (Current one: <main:1/3>)
       Current memory  : &0*0
       Allocated memory: &5*1
       Aliases         : index
       Flags           :
       Cascaded flags  :
       Local interruption handlers:
       Cascaded local interruption handlers:
     Saved states:
     Global interruption handlers:

    Code at <main:1/3>:
         :memory INT/index  # <0> @(main, line 1)
         0 -> &index        # <1> @(main, line 2)
         :debug BREAK       # <2> @(main, line 3)
      :label array
    ====== HERE ======
         :com.message @(array/@&index)      # <3> @(main, line 5)
    ==================
         :shift &index      # <4> @(main, line 6)
         :goto array        # <5> @(main, line 7)
     Labels:
      array -> <3>
     Symbols:

    Memory:
      &0: STR "a"
      &1: STR "b"
      &2: STR "c"
      &3: STR "d"
      &4: STR "e"
      &5: INT 5
     Aliases:
      array -> &0*5
      index -> &5*1
     Free space:

    ### Simple Virtual Machine 1234 : SYSTEM | 2023-01-01 00:00:00 GMT ###################################################################################
    Process application interrupted: @(main, line 5) Interruption MEMORY not handled: Index 5 is outside pointer &0*5.

Au début, chaque valeur du tableau est bien écrite sur une ligne. Seulement, on obtient également à la fin une erreur. En effet, on boucle indéfiniment en augmentant l'indice et il finit par désigner une adresse qui se trouve hors du tableau : il faut pouvoir s'arrêter avant.

Modifiez le code ainsi :

    #!/usr/bin/env svm
    DESCRIPTION
    Array example
    END
    LOG
    DEBUG "Array" STYLE "default"
    PLUGIN "svmcom.so"
    PLUGIN "svmint.so"
    PLUGIN "svmstr.so"
    OPTION -s MULTIPLE STR array
    PROCESS "application"
    	CODE "main" INLINE
    		:memory INT/index
    		0 -> &index
    		:debug BREAK
    	:label array
    		:com.message @(array/@&index)
    		:shift &index
    		:goto array :when @&index IN array
    	END
    	MEMORY array
    END

Relancez une dernière fois l'application avec les mêmes options. Cette fois, on obtient :

    a
    b
    c
    d
    e

Ce que vous venez d'ajouter au code rend l'instruction de saut conditionnelle : elle s'exécute tant que la condition ajoutée est vraie.

- Une instruction de saut peut être exécutée sous condition, en postfixant l'instruction par `:when` suivi d'une condition :
  - lorsque la condition est vraie, l'instruction de saut est exécutée,
  - lorsque la condition est fausse, l'exécution se poursuit après l'instruction de saut.
- Pour exécuter l'instruction quand la condition est fausse, il suffit de remplacer `:when` par `:unless`.
- La condition `indice IN pointeur` est vraie si l'indice est entre zéro et la taille du pointeur moins un. Cela signifie que l'opérateur `(pointeur/indice)` ne génèrera pas d'erreur.

# Conclusion

Vous venez de voir comment utiliser un pointeur de la machine virtuelle comme tableau de valeurs.

Les outils d'incrémentation et de saut conditionnel permettent de réaliser le même traitement sur toutes les valeurs d'un pointeur.