Introduction

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

Dans ce didacticiel, vous allez utiliser les instructions provenant d'extensions.

Le temps de lecture de ce didacticiel est estimé à 20 minutes si l'écriture d'application simple a été abordée.

Mise en place

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

#!/usr/bin/env svm
DESCRIPTION
Plugin instructions example
END
LOG
DEBUG "Plugin instructions" STYLE "default"
PROCESS "application"
	CODE "main" INLINE
	END
END

Utiliser une instruction extension

Il y a deux catégories d'instructions disponibles : les instructions internes de la machine virtuelle, et les instructions des extensions de la machine virtuelle.

Charger l'extension dans la machine

Avant de pouvoir utiliser une instruction extension, il faut indiquer à la machine virtuelle de charger l'extension avant de lancer l'application.

Modifiez le code pour ajouter des extensions :

#!/usr/bin/env svm
DESCRIPTION
Plugin instructions example
END
LOG
DEBUG "Plugin instructions" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
	END
END

Lancez l'application en mode débugueur, et ouvrez depuis le menu principal la fenêtre "Plugins" et filtrez sur les instructions :

Plugin instructions
Main menu
Breakpoints
Machine
Schedulers
Processes
Kernels
Events
Plugins
Windows list
Plugins
Definitions
TYPE com.device
STRUCT com.file
STRUCT com.tcp
STRUCT com.terminal
SYSTEM WAITING INSTRUCTION com.command com.device . * -> VALUE ?
INSTRUCTION com.equal com.device 2 -> BLN
WAITING INSTRUCTION com.idle ( ( > | < ( PEP | { PEP [ VALUE KEYWORD ] * } ) ? : protocol ) : mode PTR + : device_arrays ) + -> PTR : active_device
INSTRUCTION com.message [ 'STDOUT' 'STDERR' ] ? VALUE +
SYSTEM WAITING INSTRUCTION com.open PEP : device_type . * : parameters -> com.device
WAITING INSTRUCTION com.prompt ( [ 'STDOUT' 'STDERR' ] ? STR ) : prompt ? [ 'STR' 'INT' ] : output_type -> [ STR INT ]
WAITING INSTRUCTION com.read com.device PEP : protocol [ VALUE KEYWORD ] * : parameters -> STR ?
WAITING INSTRUCTION com.write com.device VALUE *
INSTRUCTION int.add ( INT INT + | PTR ) -> INT
INSTRUCTION int.cmp INT [ < > = <> <= => ] INT -> BLN
INSTRUCTION int.div INT INT -> INT
INSTRUCTION int.mod INT INT -> INT
INSTRUCTION int.mul ( INT INT + | PTR ) -> INT
INSTRUCTION int.parse STR -> INT
INSTRUCTION int.print INT ( [ 'OCT' 'DEC' 'HEX' ] INT ) ? -> STR
INSTRUCTION int.rand 'DICE' ? INT : limit -> INT
INSTRUCTION int.sub INT INT -> INT
FUNCTION com.device STRUCT -> com.device ?
FUNCTION com.device_file_close $com.file -> BLN
FUNCTION com.device_file_command $com.file . * -> VALUE ?
FUNCTION com.device_file_open [ < > <> >> ] STR [ 'EXEC' 'PRIV' ] * -> $com.file
FUNCTION com.device_file_print $com.file -> STR
FUNCTION com.device_file_read $com.file -> STR ?
FUNCTION com.device_file_write $com.file STR
FUNCTION com.device_tcp_close $com.tcp -> BLN
FUNCTION com.device_tcp_command $com.tcp . * -> VALUE ?
FUNCTION com.device_tcp_idle $com.tcp MUTABLE INT MUTABLE INT MUTABLE INT
FUNCTION com.device_tcp_open [ < > ] STR [ STR INT ] -> $com.tcp
FUNCTION com.device_tcp_print $com.tcp -> STR
FUNCTION com.device_tcp_read $com.tcp -> STR ?
FUNCTION com.device_tcp_write $com.tcp STR
FUNCTION com.device_terminal_close $com.terminal -> BLN
FUNCTION com.device_terminal_command $com.terminal . * -> VALUE ?
FUNCTION com.device_terminal_idle $com.terminal MUTABLE INT MUTABLE INT MUTABLE INT
FUNCTION com.device_terminal_open [ 'STDIN' 'STDOUT' 'STDERR' ] -> $com.terminal
FUNCTION com.device_terminal_print $com.terminal -> STR
FUNCTION com.device_terminal_read $com.terminal -> STR ?
FUNCTION com.device_terminal_write $com.terminal STR
FUNCTION com.protocol_all STR BLN : eof -> INT ?
FUNCTION com.protocol_available STR BLN : eof -> INT ?
FUNCTION com.protocol_line STR BLN : eof STR ? -> INT ?
FUNCTION com.protocol_size STR BLN : eof INT -> INT ?
INTERRUPTION com.interrupted
in
Filter

Cette liste contient toutes les instructions apportées par les extensions "svmcom.so" et "svmint.so". Elles augmentent les capacités de traitement de la machine virtuelle et sont essentielles pour écrire une application.

Appeller des instructions extension

Modifiez le code pour ajouter des instructions d'extension :

#!/usr/bin/env svm
DESCRIPTION
Plugin instructions example
END
LOG
DEBUG "Plugin instructions" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
PROCESS "application"
	CODE "main" INLINE
		:memory INT/a, INT/b, INT/r
		:debug BREAK
		:com.prompt "a" INT -> &a
		:com.prompt "b" INT -> &b
		:int.add @&a @&b -> &r
		:int.mod @&r 10 -> &r
		:com.message "r: " @&r
	END
END

Dans ce code, à part l'instruction :memory, toutes les instructions proviennent des deux extensions ajoutées précédemment. Cherchez dans la liste des instructions celles présentes dans le code.

Lancez les deux commandes suivantes dans un terminal pour accéder à la documentation des deux extensions :

man svm_plugin_com
man svm_plugin_int

Lancez l'application pour confirmer le comportement :

./instructions.svm
a: 12
b: 5
r: 7

Comprendre le prototype d'une instruction extension

Nom de l'instruction

Dans le code, vous pouvez remarquer deux catégories d'instructions :

  1. Les instructions telles que :memory sans caractère point (.) qui sont les quelques instructions internes de la machine virtuelle. Ces instructions sont implémentées directement dans la machine et sont toujours accessibles.
  2. Les instructions telles que :int.add avec un caractère point (.) qui sont les instructions définies dans les extensions de la machine virtuelle. Ces instructions sont implémentées à l'extérieur de la machine (dans des fichiers .so) par des utilisateurs avancés et sont chargées à la demande au démarrage de la machine.

Ici, c'est cette seconde catégorie qui nous intéresse.

Arguments de l'instruction

Les instructions extension, comme les instructions internes, acceptent des arguments. Dans le code de la machine virtuelle, ces arguments sont une liste placée après le nom de l'instruction :

Remplacez le code de l'application par :

#!/usr/bin/env svm
DESCRIPTION
Plugin instructions example
END
LOG
DEBUG "Plugin instructions" STYLE "default"
PLUGIN "svmcom.so"
PLUGIN "svmint.so"
PROCESS "application"
	CODE "main" INLINE
		:memory INT*5/array, INT/result1, INT/result2, INT/result3, BLN/test
		[ 1 , 3 , 5 , 7 , 9  ] -> array
		:debug BREAK
		:int.add 12 5 -> &result1
		:int.add 12 5 3 2 -> &result2
		:int.add array -> &result3
		:int.cmp @&result2 < @&result3 -> &test
		:com.message @&result1 " " @&result2 " " @&result3 " -> " @&test
	END
END

Lancez cette application :

./instructions.svm
17 22 25 -> TRUE

Maintenant, constatez que :

En regardant dans la fenêtre des extensions du débugueur, vous pouvez trouver les prototypes de ces instructions :

La page de manuel de la machine virtuelle (que vous pouvez ouvrir avec la commande man svm dans le terminal, et dans laquelle vous pouvez chercher le texte "regular expression") contient toutes les clefs pour déchiffrer et interpréter ces expressions rationnelles d'arguments.

Valeur de retour

Quand le prototype contient une flèche vers la droite (comme l'instruction d'affectation), cela signifie que l'instruction renvoie une valeur.

Cette expression rationnelle est limitée à une seule valeur, qui peut être optionnelle pour indiquer que la valeur renvoyée peut être nulle : si une telle valeur nulle est écrite à une certaine adresse, cette adresse devient non initialisée.

Conclusion

Vous venez de voir comment intégrer à votre code les instructions implémentées dans les extensions.

Ces instructions offrent une grande souplesse dans leur utilisation, et confère à la machine virtuelle une grande variabilité dans ses capacités.

De plus, les instructions extension peuvent réaliser des choses extrêmement complexes : le langage de la machine virtuelle devient un langage bas niveau (langage machine avec des paradigmes simples) avec des instructions de haut niveau (avec des paradigmes complexes). C'est ainsi qu'il est possible de réaliser des applications complexes en très peu d'instructions, offrant à la fois versatilité et compacité des applications.