# Introduction

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

Dans ce didacticiel, vous allez exécuter du code importé.

Le temps de lecture de ce didacticiel est estimé à 15 minutes si l'écriture basique du code, les sauts et les fonctions ont été abordés.

# Mise en place

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

    #!/usr/bin/env svm
    DESCRIPTION
    Libraries example
    END
    LOG
    DEBUG "Libraries" STYLE "default"
    PLUGIN "svmcom.so"
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    		:memory STR/source
    		""":com.message 1
                       :shutdown
                    :label l
                       :com.message 2
                       :return
                    :label s
                       :com.message 3
                       :return
                    """ -> &source
    	END
    END

# Bibliothèques

## Depuis une chaine

Observez le code fourni. La chaine de caractères définie dans le code a deux spécificités :

- elle est définie sur plusieurs lignes, encadrée par des triples double-quotes,
- son contenu est du code valide pour la machine virtuelle.

Modifiez le code pour obtenir :

    #!/usr/bin/env svm
    DESCRIPTION
    Libraries example
    END
    LOG
    DEBUG "Libraries" STYLE "default"
    PLUGIN "svmcom.so"
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    		:memory STR/source, LIB/library
    		""":com.message 1
                       :shutdown
                    :label l
                       :com.message 2
                       :return
                    :label s
                       :com.message 3
                       :return
                    """ -> &source
    		:library "lib" @&source -> &library
    	END
    END

Lancez l'application en mode débugueur. La fenêtre mémoire à la fin de l'exécution contient :

Libraries
Memory - K main - P application

Address | Type | Value
--- | --- | ---
&0 | STR | ":com.message 1\n\t\t :shutdown\n\t\t:label l\n\t\t :com.message 2\n\t\t :return\n\t\t:label s\n\t\t :com.message 3\n\t\t :return\n\t\t"
&1 | LIB | <lib:2>

Alias | Pointer
--- | ---
library | &1*1
source | &0*1

Address:
Display
Aliases
P
Focus
Back
Clear

La mémoire contient deux adresses. La première contient sans surprise la chaine avec le texte source.

La seconde est de type `LIB` (pour "library" en anglais) et contient le code compilé de la bibliothèque. La valeur est représentée par le nom de la bibliothèque (donné en premier argument de l'instruction `:library`) suivi d'un identifiant généré par la machine, le tout entre chevrons.

## Depuis un fichier

Prenez le contenu de la chaine et mettez le à part dans un fichier non exécutable lib.svm, puis modifiez le code :

    #!/usr/bin/env svm
    DESCRIPTION
    Libraries example
    END
    LOG
    DEBUG "Libraries" STYLE "default"
    PLUGIN "svmcom.so"
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    		:memory com.device/file, STR/source, LIB/library
    		:com.open com.file < "lib.svm" -> &file
    		:com.read @&file com.all -> &source
    		:library "lib" @&source -> &library
    		[ ] -> file
    	END
    END

Lancez l'application en mode débugueur. A la fin de l'exécution du code, vous devez obtenir sensiblement la même fenêtre mémoire :

Libraries
Memory - K main - P application

Address | Type | Value
--- | --- | ---
&0 | com.device |
&1 | STR | "\t:com.message 1\n\t:shutdown\n:label l\n\t:com.message 2\n\t:return\n:label s\n\t:com.message 3\n\t:return\n"
&2 | LIB | <lib:2>

Alias | Pointer
--- | ---
file | &0*1
library | &2*1
source | &1*1

Address:
Display
Aliases
P
Focus
Back
Clear

Cet extrait de code permet de morceler l'application en plusieurs fichiers, ou d'importer du code écrit par d'autres personnes.

- Une chaine contenant du code machine peut être compilée avec l'instruction `:library chaine_nom_bibliotheque chaine_code_source`.
- Les bibliothèques ainsi compilées peuvent être écrites en mémoire.

## Utilisation de la bibliothèque

Maintenant que l'on a la bibliothèque enregistrée dans la mémoire, il est temps d'appeller le code via un saut ou un appel de fonction.

Revenez au fichier précédent, puis modifiez le code pour obtenir :

    #!/usr/bin/env svm
    DESCRIPTION
    Libraries example
    END
    LOG
    DEBUG "Libraries" STYLE "default"
    PLUGIN "svmcom.so"
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    		:memory STR/source, LIB/library
    		""":com.message 1
                       :shutdown
                    :label l
                       :com.message 2
                       :return
                    :label s
                       :com.message 3
                       :return
                    """ -> &source
    		:library "lib" @&source -> &library
    		:call s P
    	END
    END

Puis lancez l'application :

    ./bibliotheques.svm
    Boot error: Process application has invalid code: @(main, line 13) Label s is not defined in code main.

Et cela ne fonctionne pas ! En effet, l'appel vers l'étiquette "s" ne peut aboutir que si elle est définie dans le code de base "main" et non dans le code compilé "lib". Pour atteindre le code contenu dans "lib", il faudra un nouveau concept : les symboles.

# Symboles

## Utilisation

Modifiez le code :

    #!/usr/bin/env svm
    DESCRIPTION
    Libraries example
    END
    LOG
    DEBUG "Libraries" STYLE "default"
    PLUGIN "svmcom.so"
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    		:memory STR/source, LIB/library
    		""":com.message 1
                       :shutdown
                    :label l
                       :com.message 2
                       :return
                    :label s
                       :com.message 3
                       :return
                    """ -> &source
    		:library "lib" @&source -> &library
    		:call $(@&library/"s") P
    	END
    END

Lancez l'application :

    ./bibliotheques.svm
    ### Simple Virtual Machine 1234 : PROCESS application | 2023-01-01 00:00:00 GMT ######################################################################
    Kernel interrupted: @(main, line 13) Interruption FAILURE not handled: Symbol s is not defined in code lib.

    Core dump:
    Kernel:
    State: I, transmit_interruption, interrupted @(main, line 13) Interruption FAILURE not handled: Symbol s is not defined in code lib.

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

    Code at <main:1/4>:
         :debug BREAK       # <0> @(main, line 1)
         :memory STR/source , LIB/library   # <1> @(main, line 2)
         """:com.message 1\n\t\t   :shutdown\n\t\t:label l\n\t\t   :com.message 2\n\t\t   :return\n\t\t:label s\n\t\t   :com.message 3\n\t\t   :return\n\t\t""" -> &source  # <2> @(main, lines 3-11)
         :library "lib" @&source -> &library        # <3> @(main, line 12)
    ====== HERE ======
         :call $(@&library/"s") P   # <4> @(main, line 13)
    ==================
     Labels:
     Symbols:

    Memory:
      &0: STR ":com.message 1\n\t\t   :shutdown\n\t\t:label l\n\t\t   :com.message 2\n\t\t   :return\n\t\t:label s\n\t\t   :com.message 3\n\t\t   :return\n\t\t"
      &1: LIB <lib:2>
     Aliases:
      library -> &1*1
      source -> &0*1
     Free space:

    ### Simple Virtual Machine 1234 : SYSTEM | 2023-01-01 00:00:00 GMT ###################################################################################
    Process application interrupted: @(main, line 13) Interruption FAILURE not handled: Symbol s is not defined in code lib.

La cible de l'appel a été modifiée et contient maintenant une référence sur le code de la bibliothèque et une étiquette de la bibliothèque.

Cependant, les étiquettes comme "l" et "s" dans une bibliothèque ne peuvent pas être appellées depuis une instruction placée dans un autre code que cette bibliothèque.

## Déclaration

Modifiez le code pour changer "s" :

    #!/usr/bin/env svm
    DESCRIPTION
    Libraries example
    END
    LOG
    DEBUG "Libraries" STYLE "default"
    PLUGIN "svmcom.so"
    PROCESS "application"
    	CODE "main" INLINE
    		:debug BREAK
    		:memory STR/source, LIB/library
    		""":com.message 1
                       :shutdown
                    :label l
                       :com.message 2
                       :return
                    :symbol s
                       :com.message 3
                       :return
                    """ -> &source
    		:library "lib" @&source -> &library
    		:call $(@&library/"s") P
    		:goto $(@&library/)
    	END
    END

Puis lancez l'application :

    ./bibliotheques.svm
    3
    1

Cette fois-ci, l'appel est bien réalisé. Le saut ajouté à la suite de l'appel fonctionne également, et exécute le code "lib" à partir de la première instruction.

Vous pouvez lancer l'application en mode débugueur. Lors de l'exécution de la fonction "s", les fenêtres du processeur et des codes ressemblent à :

Libraries
Processor - K main - P application
State:
Next instruction: <lib:2/5>
Current instruction: <lib:2/4>
Code
Current memory: &0*0
Allocated memory:
Defined aliases:
Local interruptions:
Cascaded local interruptions:
Flags:
Cascaded flags:
Return stack:
State:
Next instruction: <main:1/5>
Current instruction: <main:1/4>
Code
Current memory: &0*0
Allocated memory: &0*2
Defined aliases: library source
Local interruptions:
Cascaded local interruptions:
Flags:
Cascaded flags:
Global interruptions:
Waiting interruptions:
Code lib - K main - P application

    :com.message 1
    :shutdown
    :label l
    :com.message 2
    :return
    :symbol s
    :com.message 3
    :return

Auto-scroll to
Current
with
above
Display
=Code main - K main - P application

    :debug BREAK
    :memory STR/source , LIB/library
    """:com.message 1
    		   :shutdown
    		:label l
    		   :com.message 2
    		   :return
    		:symbol s
    		   :com.message 3
    		   :return
    		""" -> &source
    :library "lib" @&source -> &library
    :call $(@&library/"s") P
    :goto $(@&library/)

Auto-scroll to
Current
with
above
Display

Entre l'état du processeur et la pile de retour, vous retrouvez la référence aux deux codes "main" et "lib".

En jouant l'application instruction par instruction, vous pouvez constater comment l'exécution passe d'un code à l'autre.

- Un symbole est placé dans le code comme une étiquette : `:symbol nom_symbole`.
- Une étiquette est locale et ne peut être atteinte que depuis un saut ou un appel de fonction placé dans le même code. Un symbole est global et peut être atteint depuis un saut ou un appel de fonction placé dans n'importe quel code de l'application.
- Pour réaliser un saut ou un appel de fonction, un symbole s'écrit :
  - `$(bibliotheque/chaine_symbole)` pour atteindre un symbole nommé dans une bibliothèque donnée,
  - `$(bibliotheque/)` pour atteindre la première instruction de la bibliothèque donnée,
  - `$chaine_symbole` pour atteindre un symbole nommé du code courant.

# Conclusion

Vous venez de voir comment intégrer du code depuis plusieurs sources au sein d'une application.

Cette capacité de la machine permet de constituer des applications en intégrant des modules écrits en langage machine.

Dans certaines circonstances, cela permet aussi d'exécuter du code généré par du code.