Introduction

Ce didacticiel est destiné aux utilisateurs maîtrisant la programmation en C ou C++, ainsi que l'architecture de la Simple Virtual Machine.

Dans ce didacticiel, vous allez découvrir la notion de variable Simple Virtual Machine.

Le temps de lecture de ce didacticiel est estimé à 25 minutes.

Mise en place

Pour commencer, créez le canevas de l'extension dans le fichier variables.svm_plugin en utilisant ce code :

PLUGIN variables

DEFINE

INSTRUCTION variables.repeat INT STR -> STR
%{
%}

INSTRUCTION variables.set VALUE
%{
%}

INSTRUCTION variables.get -> VALUE
%{
%}

INSTRUCTION variables.print -> STR
%{
%}

INSTRUCTION variables.reset
%{
%}

Un premier constat

Modifiez le fichier d'extension pour ajouter l'implémentation de la première instruction :

PLUGIN variables

DEFINE

INSTRUCTION variables.repeat INT STR -> STR
%{
	SVM_Value_Integer vi = ::svm_parameter_value_get(svm,argv[0]);
	long long int i = ::svm_value_integer_get(svm,vi);
	SVM_Value_String vs = ::svm_parameter_value_get(svm,argv[1]);
	SVM_String s = ::svm_value_string_get(svm,vs);
	std::string rs(s.string,s.size);
	std::string r;
	if(i<0)
	{
		::svm_processor_current_raise_error_internal__raw(svm,FAILURE,"Invalid repetition");
	}
	for(size_t ii=0 ; ii<i ; ++ii)
	{
		r += rs;
	}
	SVM_Value_String vsres = ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
	return vsres;
%}

INSTRUCTION variables.set VALUE
%{
%}

INSTRUCTION variables.get -> VALUE
%{
%}

INSTRUCTION variables.print -> STR
%{
%}

INSTRUCTION variables.reset
%{
%}

Ici, l'implémentation est volontairement détaillée, en remplaçant les macros du générateur d'extension par leur contenu.

A y regarder de plus près, nous pouvons constater que :

Dans le fichier d'interface programmatique, on trouve ces définitions :

Ces pointeurs sont non seulement retournés par l'interface, mais aussi consommés en tant que paramètres de fonctions de l'interface. De plus, lorsque la fonction svm_processor_current_raise_error_internal__raw interrompt brutalement l'exécution de l'instruction, ces pointeurs ne semblent pas provoquer de fuite mémoire (ce qui peut être vérifié en exécutant la machine avec l'utilitaire valgrind).

Ces pointeurs sont en réalité liés aux valeurs qu'ils représentent, mais celles-ci sont conservées par la machine virtuelle dans l'environnement d'exécution de l'instruction. Ces pointeurs, jouant le rôle de clef pour retrouver les valeurs dans l'environnement, sont des variables Simple Virtual Machine.

Portée des variables SVM

Portée locale

Modifiez le fichier d'extension pour ajouter une variable Simple Virtual Machine en statique et l'implémentation des instructions set, get et print :

PLUGIN variables

code:
%{
	SVM_Value _value = nullptr;
%}

DEFINE

INSTRUCTION variables.repeat INT STR -> STR
%{
	SVM_Value_Integer vi = ::svm_parameter_value_get(svm,argv[0]);
	long long int i = ::svm_value_integer_get(svm,vi);
	SVM_Value_String vs = ::svm_parameter_value_get(svm,argv[1]);
	SVM_String s = ::svm_value_string_get(svm,vs);
	std::string rs(s.string,s.size);
	std::string r;
	if(i<0)
	{
		::svm_processor_current_raise_error_internal__raw(svm,FAILURE,"Invalid repetition");
	}
	for(size_t ii=0 ; ii<i ; ++ii)
	{
		r += rs;
	}
	SVM_Value_String vsres = ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
	return vsres;
%}

INSTRUCTION variables.set VALUE
%{
	_value = ::svm_parameter_value_get(svm,argv[0]);
%}

INSTRUCTION variables.get -> VALUE
%{
	return _value;
%}

INSTRUCTION variables.print -> STR
%{
	SVM_String s = ::svm_value_print(svm,_value);
	return NEW_VALUE(string,s);
%}

INSTRUCTION variables.reset
%{
%}

Puis générez l'extension et compilez la. Enfin, crééz un fichier exécutable variables.svm avec ce code :

#!/usr/bin/env svm
LOG
PLUGIN "svmcom.so"
LOCAL PLUGIN "svmpluginvariables/libsvmvariables.so"
PROCESS "variables"
	CODE "main" INLINE
		:memory INT/i, STR/s
		:variables.set 17
		:variables.print -> &s
		:com.message @&s
	END
END

Cette application utilise la valeur statique de l'extension pour réaliser une action. Lancez l'application :

./variables.svm
### Simple Virtual Machine 12345 : PROCESS variables | 2023-01-01 00:00:00 GMT #######################################################################
Kernel interrupted: @(main, line 3) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 3) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

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

Code at <main:1/2>:
     :memory INT/i , STR/s      # <0> @(main, line 1)
     :variables.set 17  # <1> @(main, line 2)
====== HERE ======
     :variables.print -> &s     # <2> @(main, line 3)
==================
     :com.message @&s   # <3> @(main, line 4)
 Labels:
 Symbols:


Memory:
  &0: INT
  &1: STR
 Aliases:
  i -> &0*1
  s -> &1*1
 Free space:



### Simple Virtual Machine 12345 : SYSTEM | 2023-01-01 00:00:00 GMT ##################################################################################
Process variables interrupted: @(main, line 3) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.


Et là, une erreur pour le moins étrange apparaît ! Dans l'instruction print, la fonction de l'interface svm_value_print ne reconnaît plus la variable "_value".

Et pour cause, par défaut, une variable n'est valable que dans le bloc de code où elle est définie : la variable Simple Virtual Machine est ici locale (au bloc de code).

En particulier, cela signifie que la valeur associée peut être détruite à la sortie de l'instruction : il n'est donc pas nécessaire de supprimer les variables Simple Virtual Machine lorsque celles-ci ne sont utilisées que dans le bloc de code où elles sont définies, en C ou en C++.

Portée globale

Modifiez à nouveau le code de l'extension :

PLUGIN variables

code:
%{
	SVM_Value _value = nullptr;
%}

DEFINE

INSTRUCTION variables.repeat INT STR -> STR
%{
	SVM_Value_Integer vi = ::svm_parameter_value_get(svm,argv[0]);
	long long int i = ::svm_value_integer_get(svm,vi);
	SVM_Value_String vs = ::svm_parameter_value_get(svm,argv[1]);
	SVM_String s = ::svm_value_string_get(svm,vs);
	std::string rs(s.string,s.size);
	std::string r;
	if(i<0)
	{
		::svm_processor_current_raise_error_internal__raw(svm,FAILURE,"Invalid repetition");
	}
	for(size_t ii=0 ; ii<i ; ++ii)
	{
		r += rs;
	}
	SVM_Value_String vsres = ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
	return vsres;
%}

INSTRUCTION variables.set VALUE
%{
	_value = ::svm_parameter_value_get(svm,argv[0]);
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.get -> VALUE
%{
	return _value;
%}

INSTRUCTION variables.print -> STR
%{
	SVM_String s = ::svm_value_print(svm,_value);
	return NEW_VALUE(string,s);
%}

INSTRUCTION variables.reset
%{
	::svm_variable_scope_set_local(svm,_value);
%}

Puis regénérez l'extension et recompilez la. Modifiez également le fichier variables.svm pour obtenir :

#!/usr/bin/env svm
LOG
PLUGIN "svmcom.so"
LOCAL PLUGIN "svmpluginvariables/libsvmvariables.so"
PROCESS "variables"
	CODE "main" INLINE
		:memory INT/i, STR/s
		:variables.set 17
		:variables.print -> &s
		:com.message "print: " @&s
		:variables.get -> &i
		:com.message "get: " @&i
		:variables.reset
		:variables.print -> &s
		:com.message "print: " @&s
	END
END

Lancez maintenant l'application :

./variables.svm
print: 17
get: 17
### Simple Virtual Machine 1234 : PROCESS variables | 2023-01-01 00:00:00 GMT ########################################################################
Kernel interrupted: @(main, line 8) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 8) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Processor:
 State:
   Next instruction: <main:1/8> (Current one: <main:1/7>)
   Current memory  : &0*0
   Allocated memory: &0*2
   Aliases         : i s
   Flags           :
   Cascaded flags  :
   Local interruption handlers:
   Cascaded local interruption handlers:
 Saved states:
 Global interruption handlers:

Code at <main:1/7>:
     :memory INT/i , STR/s      # <0> @(main, line 1)
     :variables.set 17  # <1> @(main, line 2)
     :variables.print -> &s     # <2> @(main, line 3)
     :com.message "print: " @&s # <3> @(main, line 4)
     :variables.get -> &i       # <4> @(main, line 5)
     :com.message "get: " @&i   # <5> @(main, line 6)
     :variables.reset   # <6> @(main, line 7)
====== HERE ======
     :variables.print -> &s     # <7> @(main, line 8)
==================
     :com.message "print: " @&s # <8> @(main, line 9)
 Labels:
 Symbols:


Memory:
  &0: INT 17
  &1: STR "17"
 Aliases:
  i -> &0*1
  s -> &1*1
 Free space:



### Simple Virtual Machine 1234 : SYSTEM | 2023-01-01 00:00:00 GMT ###################################################################################
Process variables interrupted: @(main, line 8) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Observez attentivement où est générée l'erreur cette fois : après l'appel à l'instruction reset. Cependant, les deux premières lignes du résultat montrent que la variable était maintenant connue des instructions get et print !

L'appel à la fonction svm_variable_scope_set_global a permis de changer la portée de la variable Simple Virtual Machine et la rendre visible aux autres blocs de code présents dans l'extension : la variable Simple Virtual Machine est devenue globale.

Avec l'appel à la fonction svm_variable_scope_set_local, la variable redevient locale au bloc de code où cette fonction de l'interface programmatique est appellée.

Suppression immédiate

Dans certains cas, il peut être important de révoquer immédiatement une variable Simple Virtual Machine, sans attendre la fin du bloc de code.

Modifiez le code de l'extension :

PLUGIN variables

code:
%{
	SVM_Value _value = nullptr;
%}

DEFINE

INSTRUCTION variables.repeat INT STR -> STR
%{
	SVM_Value_Integer vi = ::svm_parameter_value_get(svm,argv[0]);
	long long int i = ::svm_value_integer_get(svm,vi);
	SVM_Value_String vs = ::svm_parameter_value_get(svm,argv[1]);
	SVM_String s = ::svm_value_string_get(svm,vs);
	std::string rs(s.string,s.size);
	std::string r;
	if(i<0)
	{
		::svm_processor_current_raise_error_internal__raw(svm,FAILURE,"Invalid repetition");
	}
	for(size_t ii=0 ; ii<i ; ++ii)
	{
		r += rs;
	}
	SVM_Value_String vsres = ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
	return vsres;
%}

INSTRUCTION variables.set VALUE
%{
	_value = ::svm_parameter_value_get(svm,argv[0]);
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.get -> VALUE
%{
	return _value;
%}

INSTRUCTION variables.print -> STR
%{
	SVM_String s = ::svm_value_print(svm,_value);
	return NEW_VALUE(string,s);
%}

INSTRUCTION variables.reset
%{
	::svm_variable_delete(svm,_value);
	SVM_String s = ::svm_value_print(svm,_value);
%}

Puis regénérez l'extension et recompilez la. Lancez maintenant l'application :

./variables.svm
print: 17
get: 17
### Simple Virtual Machine 1234 : PROCESS variables | 2023-01-01 00:00:00 GMT ########################################################################
Kernel interrupted: @(main, line 7) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 7) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Processor:
 State:
   Next instruction: <main:1/7> (Current one: <main:1/6>)
   Current memory  : &0*0
   Allocated memory: &0*2
   Aliases         : i s
   Flags           :
   Cascaded flags  :
   Local interruption handlers:
   Cascaded local interruption handlers:
 Saved states:
 Global interruption handlers:

Code at <main:1/6>:
     :memory INT/i , STR/s      # <0> @(main, line 1)
     :variables.set 17  # <1> @(main, line 2)
     :variables.print -> &s     # <2> @(main, line 3)
     :com.message "print: " @&s # <3> @(main, line 4)
     :variables.get -> &i       # <4> @(main, line 5)
     :com.message "get: " @&i   # <5> @(main, line 6)
====== HERE ======
     :variables.reset   # <6> @(main, line 7)
==================
     :variables.print -> &s     # <7> @(main, line 8)
     :com.message "print: " @&s # <8> @(main, line 9)
 Labels:
 Symbols:


Memory:
  &0: INT 17
  &1: STR "17"
 Aliases:
  i -> &0*1
  s -> &1*1
 Free space:



### Simple Virtual Machine 1234 : SYSTEM | 2023-01-01 00:00:00 GMT ###################################################################################
Process variables interrupted: @(main, line 7) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Cette fois, l'erreur apparaît bien directement dans l'instruction reset, après l'appel à la fonction svm_variable_delete. La variable a bien été supprimée, et la valeur correspondante également si la machine virtuelle ne la référence plus par ailleurs.

Variables SVM partagées

Transformation en variable partagée

Les fonctions qui changent la portée d'une variable Simple Virtual Machine ne fonctionnent bien que lorsqu'une seule entité gère la portée d'une variable. En effet, les appels à ces fonctions sont idempotents par défaut : cela signifie qu'un seul appel à la fonction svm_variable_scope_set_local changera la portée d'une variable même si plusieurs appels à svm_variable_scope_set_global ont été faits sur cette variable.

Modifiez le code de l'extension pour obtenir :

PLUGIN variables

code:
%{
	SVM_Value _value = nullptr;
%}

DEFINE

INSTRUCTION variables.set VALUE
%{
	_value = ::svm_parameter_value_get(svm,argv[0]);
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.get -> VALUE
%{
	return _value;
%}

INSTRUCTION variables.print -> STR
%{
	SVM_String s = ::svm_value_print(svm,_value);
	return NEW_VALUE(string,s);
%}

INSTRUCTION variables.global
%{
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.local
%{
	::svm_variable_scope_set_local(svm,_value);
%}

Regénérez et recompilez l'extension, puis modifiez à nouveau le fichier variables.svm pour obtenir :

#!/usr/bin/env svm
LOG
PLUGIN "svmcom.so"
LOCAL PLUGIN "svmpluginvariables/libsvmvariables.so"
PROCESS "variables"
	CODE "main" INLINE
		:memory INT/i, STR/s
		:variables.set 17
		:variables.print -> &s
		:com.message "print 1: " @&s
		:variables.global
		:variables.print -> &s
		:com.message "print 2: " @&s
		:variables.global
		:variables.print -> &s
		:com.message "print 3: " @&s
		:variables.local
		:variables.print -> &s
		:com.message "print 4: " @&s
	END
END

Enfin, lancez l'application et observez à quel moment l'interruption est levée :

./variables.svm
print 1: 17
print 2: 17
print 3: 17
### Simple Virtual Machine 12345 : PROCESS variables | 2023-01-01 00:00:00 GMT #######################################################################
Kernel interrupted: @(main, line 12) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 12) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Processor:
 State:
   Next instruction: <main:1/12> (Current one: <main:1/11>)
   Current memory  : &0*0
   Allocated memory: &0*2
   Aliases         : i s
   Flags           :
   Cascaded flags  :
   Local interruption handlers:
   Cascaded local interruption handlers:
 Saved states:
 Global interruption handlers:

Code at <main:1/11>:
     :memory INT/i , STR/s      # <0> @(main, line 1)
     :variables.set 17  # <1> @(main, line 2)
     :variables.print -> &s     # <2> @(main, line 3)
     :com.message "print 1: " @&s       # <3> @(main, line 4)
     :variables.global  # <4> @(main, line 5)
     :variables.print -> &s     # <5> @(main, line 6)
     :com.message "print 2: " @&s       # <6> @(main, line 7)
     :variables.global  # <7> @(main, line 8)
     :variables.print -> &s     # <8> @(main, line 9)
     :com.message "print 3: " @&s       # <9> @(main, line 10)
     :variables.local   # <10> @(main, line 11)
====== HERE ======
     :variables.print -> &s     # <11> @(main, line 12)
==================
     :com.message "print 4: " @&s       # <12> @(main, line 13)
 Labels:
 Symbols:


Memory:
  &0: INT
  &1: STR "17"
 Aliases:
  i -> &0*1
  s -> &1*1
 Free space:



### Simple Virtual Machine 12345 : SYSTEM | 2023-01-01 00:00:00 GMT ##################################################################################
Process variables interrupted: @(main, line 12) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Un seul appel à la fonction svm_variable_scope_set_local a suffit à rendre la variable locale, alors que plusieurs appels à la fonction svm_variable_scope_set_global ont été réalisés.

Cela peut poser problème lorsque plusieurs entités veulent contrôler de manière indépendante la portée d'une variable : la variable doit être marquée comme partagée. Dans ce cas, il faudra un nombre équivalent d'appels à la fonction svm_variable_scope_set_local au nombre d'appels à la fonction svm_variable_scope_set_global pour que la variable redevienne locale.

Modifiez le code de l'extension :

PLUGIN variables

code:
%{
	SVM_Value _value = nullptr;
%}

DEFINE

INSTRUCTION variables.set VALUE
%{
	_value = ::svm_parameter_value_get(svm,argv[0]);
	::svm_variable_scope_set_shared(svm,_value);
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.get -> VALUE
%{
	return _value;
%}

INSTRUCTION variables.print -> STR
%{
	SVM_String s = ::svm_value_print(svm,_value);
	return NEW_VALUE(string,s);
%}

INSTRUCTION variables.global
%{
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.local
%{
	::svm_variable_scope_set_local(svm,_value);
%}

Regénérez et recompilez l'extension, puis modifiez à nouveau le fichier variables.svm pour obtenir :

#!/usr/bin/env svm
LOG
PLUGIN "svmcom.so"
LOCAL PLUGIN "svmpluginvariables/libsvmvariables.so"
PROCESS "variables"
	CODE "main" INLINE
		:memory INT/i, STR/s
		:variables.set 17
		:variables.print -> &s
		:com.message "print 1: " @&s
		:variables.global
		:variables.print -> &s
		:com.message "print 2: " @&s
		:variables.global
		:variables.print -> &s
		:com.message "print 3: " @&s
		:variables.local
		:variables.print -> &s
		:com.message "print 4: " @&s
		:variables.local
		:variables.print -> &s
		:com.message "print 5: " @&s
		:variables.local
		:variables.print -> &s
		:com.message "print 6: " @&s
		:variables.local
		:variables.print -> &s
		:com.message "print 7: " @&s
	END
END

Et relancez l'application :

./variables.svm
print 1: 17
print 2: 17
print 3: 17
print 4: 17
print 5: 17
### Simple Virtual Machine 12345 : PROCESS variables | 2023-01-01 00:00:00 GMT #######################################################################
Kernel interrupted: @(main, line 18) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Core dump:
Kernel:
State: I, transmit_interruption, interrupted @(main, line 18) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Processor:
 State:
   Next instruction: <main:1/18> (Current one: <main:1/17>)
   Current memory  : &0*0
   Allocated memory: &0*2
   Aliases         : i s
   Flags           :
   Cascaded flags  :
   Local interruption handlers:
   Cascaded local interruption handlers:
 Saved states:
 Global interruption handlers:

Code at <main:1/17>:
     :memory INT/i , STR/s      # <0> @(main, line 1)
     :variables.set 17  # <1> @(main, line 2)
     :variables.print -> &s     # <2> @(main, line 3)
     :com.message "print 1: " @&s       # <3> @(main, line 4)
     :variables.global  # <4> @(main, line 5)
     :variables.print -> &s     # <5> @(main, line 6)
     :com.message "print 2: " @&s       # <6> @(main, line 7)
     :variables.global  # <7> @(main, line 8)
     :variables.print -> &s     # <8> @(main, line 9)
     :com.message "print 3: " @&s       # <9> @(main, line 10)
     :variables.local   # <10> @(main, line 11)
     :variables.print -> &s     # <11> @(main, line 12)
     :com.message "print 4: " @&s       # <12> @(main, line 13)
     :variables.local   # <13> @(main, line 14)
     :variables.print -> &s     # <14> @(main, line 15)
     :com.message "print 5: " @&s       # <15> @(main, line 16)
     :variables.local   # <16> @(main, line 17)
====== HERE ======
     :variables.print -> &s     # <17> @(main, line 18)
==================
     :com.message "print 6: " @&s       # <18> @(main, line 19)
     :variables.local   # <19> @(main, line 20)
     :variables.print -> &s     # <20> @(main, line 21)
     :com.message "print 7: " @&s       # <21> @(main, line 22)
 Labels:
 Symbols:


Memory:
  &0: INT
  &1: STR "17"
 Aliases:
  i -> &0*1
  s -> &1*1
 Free space:



### Simple Virtual Machine 12345 : SYSTEM | 2023-01-01 00:00:00 GMT ##################################################################################
Process variables interrupted: @(main, line 18) Interruption FAILURE not handled: Invalid call to API function svm_value_print: value is not a value.

Cette fois, trois appels à la fonction svm_variable_scope_set_local ont été nécessaires pour rendre à nouveau la variable locale.

Test de portée

Parfois, certaines opérations (comme des libérations de ressources) ne doivent être entreprises que lorsqu'une variable redevient locale. Or, la fonction svm_variable_scope_set_local ne précise pas la portée de la variable.

Le test de portée peut être réalisé grâce à la fonction svm_variable_scope_is_local.

Modifiez le code de l'extension :

PLUGIN variables

code:
%{
	SVM_Value _value = nullptr;
%}

DEFINE

INSTRUCTION variables.set VALUE
%{
	_value = ::svm_parameter_value_get(svm,argv[0]);
	::svm_variable_scope_set_shared(svm,_value);
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.get -> VALUE
%{
	return _value;
%}

INSTRUCTION variables.print -> STR
%{
	SVM_String s = ::svm_value_print(svm,_value);
	return NEW_VALUE(string,s);
%}

INSTRUCTION variables.global
%{
	::svm_variable_scope_set_global(svm,_value);
%}

INSTRUCTION variables.local -> BLN
%{
	::svm_variable_scope_set_local(svm,_value);
	return NEW_VALUE(boolean,::svm_variable_scope_is_local(svm,_value));
%}

Regénérez et recompilez l'extension une dernière fois, puis modifiez enfin le fichier variables.svm pour obtenir :

#!/usr/bin/env svm
LOG
PLUGIN "svmcom.so"
LOCAL PLUGIN "svmpluginvariables/libsvmvariables.so"
PROCESS "variables"
	CODE "main" INLINE
		:memory INT/i, STR/s, BLN/b
		:variables.set 17
		:variables.print -> &s
		:com.message "print 1: " @&s
		:variables.global
		:variables.print -> &s
		:com.message "print 2: " @&s
		:variables.global
		:variables.print -> &s
		:com.message "print 3: " @&s
		:variables.local -> &b
		:shutdown :when @&b TRUE
		:variables.print -> &s
		:com.message "print 4: " @&s
		:variables.local -> &b
		:shutdown :when @&b TRUE
		:variables.print -> &s
		:com.message "print 5: " @&s
		:variables.local -> &b
		:shutdown :when @&b TRUE
		:variables.print -> &s
		:com.message "print 6: " @&s
		:variables.local -> &b
		:shutdown :when @&b TRUE
		:variables.print -> &s
		:com.message "print 7: " @&s
	END
END

Lancez l'application :

./variables.svm
print 1: 17
print 2: 17
print 3: 17
print 4: 17
print 5: 17

L'application arrête le processeur lorsque la variable redevient locale, évitant l'interruption.

Conclusion

Vous venez de voir les variables Simple Virtual Machine permettant d'accéder aux valeurs de la machine virtuelle depuis le code des extensions.

L'interêt principal des variables Simple Virtual Machine est la suppression automatique des valeurs une fois qu'elles ne sont plus nécessaires, que ce soit en C ou en C++.

Cependant, ce confort d'utilisation vient avec une complexité qui se manifeste lorsqu'une variable a une portée qui dépasse le bloc de code où elle est définie.

La maîtrise de la portée des variables peut sembler être un peu tel un casse-tête au départ, mais la plupart des utilisations de variables globales suivent des schémas simples qui seront présentés dans des didacticiels ultérieurs.