Interprêter son propre code
Publié : dim. mai 01, 2011 11:15 pm
Ce tutoriel sera principalement théorique et portera sur interprétation de son propre langage.
Vous vous demanderez peut être quel est le but? Et bien il permet, par exemple d'offrir une manière plus abordable (pour les event makers par exemple) d'utiliser des composantes scriptées. Un des exemple le plus connu dans la communauté francophone est par exemple, l'Event Language développé par Avygeil et Roys qui admet sa propre syntaxe.
Pour mon module de QuickSave, il existe une syntaxe alternative. Par exemple, au lieu de faire Appeler Script> Quicksave::save(1) qui sauvegardera la partie sur le slot 1, il est possibel de faire Appeler Script> Save in 1, bien que la différence est minime, elle permet de faire une petite abstraction de la couche script au profit d'une syntaxe plus verbeuse.
Mais comment mettre ce genre de petit raccourci en oeuvre? Nous allons nous intéresser a la première méthode.
De la méta-programmation
Concrètement la méta programmation nous permet de décrire un comportement ou un autre langage durant cet explication, nous ne ferons que de la méta programmation. Une des fonction qui devrait venir aux scripteurs en premier lieu, lorsqu'ils pensent à méta programmation est la fonction Eval qui permet d'interpréter une chaine de texte comme du code ruby. Par exemple, cette commande: affichera une alerte avec le contenu de la constante LOL. Les plus perspicaces auront compris que c'est cette commande qui sera appelé lorsqu'on fait appel à une commande "Appeler Script" ou par exemple a une condition Si_Script.
Modifier notre commande événement
Une des solutions les plus primaire vise à parler de commandes et non de langage défini par une syntaxe précise. Pour effectuer des "customs commande", il va falloir modifier notre commande "Appeler script".
Pour ce faire, nous allons analyser son comportement:
C'est donc ce que nous allons faire.
Nous allons créer une méthode:
Dans notre if, nous allons donc mettre une commande. Je me permet de rebondir sur mon script de Quicksave (ou Quicksave::save(x)) sera l'exemple.
Nous allons établir une syntaxe pour que Save in X sauve dans le slot X.
Pour cela, nous allons utiliser un regex. rappellons que l'opérateur de test d'un regex sera =~.
(le cours ne portant pas sur les regex's, je ne m'attarderai pas sur sa construction)
Et voila, notre méthode peut interpréter le cas ou on lui demande une sauvegarde. Le role du split est de faire une découpe de la chaine. Complétons cette méthode en modifiant les autres méthodes du module Quicksave:
etc.
Comme vous pouvez le voir, cet interpréteur rapide est facile a mettre en place et il suffit de remplacer, dans la commande_355 le eval(script) par custom_eval(script).
Pour pousser le vice plus loin, il est aussi possible de modifier les conditions pour qu'elles fassent référence a notre interpréteur en modifiant la ligne 638 de note Game_Interpreter.
Pistes de recherches pour la suite
Cette publication était relativement courte et facile a mettre en place, cependant, il serait intéressant de réfléchir a un vrai langage au sein de Rm respectant sa propre syntaxe.
Pour aller plus loin, il serait amusant de s'intéresser aux automates non déterministes nous permettant, pourquoi pas, d'interpréter, au sein de notre commande Appeller un script, un langage respectant la logique Ruby mais à la syntaxte abordable à n'importe quel Event Maker, ayant de l'urticaire à la prononciation du mot RGSS.
Merci de m'avoir lu. Bien à vous, NUKI.
Vous vous demanderez peut être quel est le but? Et bien il permet, par exemple d'offrir une manière plus abordable (pour les event makers par exemple) d'utiliser des composantes scriptées. Un des exemple le plus connu dans la communauté francophone est par exemple, l'Event Language développé par Avygeil et Roys qui admet sa propre syntaxe.
Pour mon module de QuickSave, il existe une syntaxe alternative. Par exemple, au lieu de faire Appeler Script> Quicksave::save(1) qui sauvegardera la partie sur le slot 1, il est possibel de faire Appeler Script> Save in 1, bien que la différence est minime, elle permet de faire une petite abstraction de la couche script au profit d'une syntaxe plus verbeuse.
Mais comment mettre ce genre de petit raccourci en oeuvre? Nous allons nous intéresser a la première méthode.
De la méta-programmation
Concrètement la méta programmation nous permet de décrire un comportement ou un autre langage durant cet explication, nous ne ferons que de la méta programmation. Une des fonction qui devrait venir aux scripteurs en premier lieu, lorsqu'ils pensent à méta programmation est la fonction Eval qui permet d'interpréter une chaine de texte comme du code ruby. Par exemple, cette commande:
Code : Tout sélectionner
eval("print LOL")
Modifier notre commande événement
Une des solutions les plus primaire vise à parler de commandes et non de langage défini par une syntaxe précise. Pour effectuer des "customs commande", il va falloir modifier notre commande "Appeler script".
Pour ce faire, nous allons analyser son comportement:
La commande Appeler script correspond à la commande_355, elle se trouve dans game Interpreter. Nous voyosn que, a la fin de la méthode, on évalue une variable script qui correspond donc à une chaine de texte. A ce stade, il suffirait donc de remplacer le eval(script) par un custom_eval(script).def command_355
script = @list[@index].parameters[0] + "\n"
loop do
if @list[@index+1].code == 655 # Second line of script and after
script += @list[@index+1].parameters[0] + "\n"
else
break
end
@index += 1
end
eval(script)
return true
end
C'est donc ce que nous allons faire.
Nous allons créer une méthode:
Code : Tout sélectionner
def custom_eval(script)
if(commande_1)
#Executer la commande 1
else
eval(script)
end
end
Nous allons établir une syntaxe pour que Save in X sauve dans le slot X.
Pour cela, nous allons utiliser un regex. rappellons que l'opérateur de test d'un regex sera =~.
(le cours ne portant pas sur les regex's, je ne m'attarderai pas sur sa construction)
Code : Tout sélectionner
def custom_eval(script)
if(script =~ /^Save in [0-9]$/ )
evaluation = script.split(" in ")
Quicksave::save(evaluation[1].to_i)
else
eval(script)
end
end
Code : Tout sélectionner
def custom_eval(script)
if(script =~ /^Save in [0-9]$/ )
evaluation = script.split(" in ")
Quicksave::save(evaluation[1].to_i)
elsif(script =~ /^Load from [0-9]$/ )
evaluation = script.split(" from ")
Quicksave::load(evaluation[1].to_i)
else
eval(script)
end
end
Comme vous pouvez le voir, cet interpréteur rapide est facile a mettre en place et il suffit de remplacer, dans la commande_355 le eval(script) par custom_eval(script).
Pour pousser le vice plus loin, il est aussi possible de modifier les conditions pour qu'elles fassent référence a notre interpréteur en modifiant la ligne 638 de note Game_Interpreter.
Pistes de recherches pour la suite
Cette publication était relativement courte et facile a mettre en place, cependant, il serait intéressant de réfléchir a un vrai langage au sein de Rm respectant sa propre syntaxe.
Pour aller plus loin, il serait amusant de s'intéresser aux automates non déterministes nous permettant, pourquoi pas, d'interpréter, au sein de notre commande Appeller un script, un langage respectant la logique Ruby mais à la syntaxte abordable à n'importe quel Event Maker, ayant de l'urticaire à la prononciation du mot RGSS.
Merci de m'avoir lu. Bien à vous, NUKI.