Cours Lua

Lua plusieurs VM système pour la domotique Gratuitement


Télécharger Lua plusieurs VM système pour la domotique Gratuitement

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


Lua plusieurs VM système pour la domotique

...

2-b. Les conventions lexicales

Les noms en Lua (également appelé identificateurs), peuvent être n'importe quelle chaîne de lettres, chiffres et caractères de soulignement ne commençant pas par un chiffre.

Les mots-clés mentionnés ci-dessous, sont réservés et ne peuvent donc pas être utilisés en tant que noms.

and break do else elseif end false for if in local nil not repeat then return true or

until while function

Lua est un langage sensible à la casse : and est un mot réservé, mais And et AND étant différents sont donc valides.

Par convention, les noms commençant par un caractère de soulignement suivi par des lettres capitales (comme _VERSION) sont réservés aux variables globales internes, utilisées par Lua.

Les chaînes littérales peuvent être délimitées par des apostrophes (') ou des guillemets (") et peuvent contenir les séquences d'échappement suivantes :

  • "\a" (cloche) ;
  • "\b" (backspace) ;
  • "\f" (saut de page) ;
  • "\n" (saut de ligne) ;
  • "\r" (retour chariot) ;
  • "\t" (tabulation horizontale) ;
  • "\v" (onglet vertical) ;
  • "\\" (barre oblique inverse) ;
  • '\"' (guillemet anglais) ;
  • "\'" (apostrophe).

Une constante numérique, peut être écrite avec une partie optionnelle décimale et un exposant optionnel décimal.

Lua accepte également les constantes entières hexadécimales, en les préfixant avec 0x. Voici quelques exemples de constantes numériques valides : 3 - 3,0 - 3,1416 - 314.16e-2 - 0x56 - 0xff - 0.31416E1

Un petit commentaire commence par : -- ici le petit commentaire.

Un grand commentaire commence par : -- [[ici le grand commentaire]]

2-c. Les types et les valeurs

Lua est un langage à typage dynamique.

Ce qui signifie que les variables n'ont pas de type, contrairement aux valeurs qui elles sont typées.

Il n'existe pas de définition de type en Lua. Toutes les valeurs soutiennent leur propre type.

Avec Lua, toutes les valeurs sont des « first-class values w. (valeurs de première classe). Ce qui signifie que toutes les valeurs peuvent être stockées dans des variables, passées comme arguments à d'autres fonctions, et retournées comme résultat.

Il existe huit types de base en Lua : nil, boolean, number, string, function, userdata, thread, table.

  • nil, dont le type de valeur est rien, a la propriété principale d'être différent de toute autre valeur et représente généralement l'absence d'une valeur.
  • boolean, dont les seules valeurs possibles sont false et true. Les deux types nil et false représentent ce qui est faux. Toute autre valeur est considérée comme vraie (true).
  • number, représente un chiffre ou un nombre réel, en double précision à virgule flottante.
  • string, est une table de caractères. Lua est « 8-bit clean » : les chaînes de caractères peuvent contenir n'importe quel caractère 8-bit, y compris "\0" (qui signifie la fin d'une chaîne).
  • function, Lua peut appeler et manipuler des fonctions écrites en Lua et des fonctions écrites en C.
  • userdata, est fourni pour permettre à des données C arbitraires, d'être stockées dans des variables Lua. Ce type correspond à un bloc de mémoire brut et n'a pas d'opération prédéfinie dans Lua, à l'exception d'affectation et de test d'identité. Toutefois, en utilisant les méta-tables, le programmeur peut définir certaines opérations pour les valeurs d'userdata. Les valeurs d'userdata ne peuvent pas être créés ou modifiées directement avec Lua, il faut passer par l'intermédiaire de l'API C. Cela garantit l'intégrité des données détenues par le programme hôte.
  • thread, représente des « threads » indépendants de l'exécution qui sont utilisés pour mettre en œuvre des « coroutines ». Ne confondez pas les thread de Lua avec les « threads » du système d'exploitation. Lua soutient les « coroutines » sur tous les systèmes, même ceux qui ne supportent pas les « threads ».
  • table , ce type met en œuvre des tables associatives, qui peuvent être indexées non seulement avec des nombres, mais aussi avec des valeurs quelconques, sauf nil. Les tables peuvent être hétérogènes, autrement dit, elles peuvent contenir des valeurs de tous types, à l'exception nil. Les tables sont les seules données mécaniquement structurées en Lua. Elles peuvent être utilisées pour représenter des tables ordinaires, des tables de symboles, de jeux, de livres, de graphiques, d'arbres, etc. Pour déclarer les enregistrements, Lua utilise le nom du champ comme index ; a.name est une façon plus simple d'écrire a["nom"] et a exactement la même signification. Il existe plusieurs méthodes pratiques pour créer des tables. (Voir à ce sujet, le chapitre consacré aux tables. )

Les tables, les fonctions, les threads, et les userdatas sont considérés comme des objets.

Les variables ne peuvent donc pas contenir ces valeurs en tant que telles, mais seulement des références à ces valeurs.

Les affectations, le passage de paramètres et les fonctions sont toujours manipulés par les références à ces valeurs et ces opérations n'impliquent aucune forme de copie.

La fonction type () retourne une chaîne, décrivant le type d'une valeur donnée. 2-d. La coercition

Lua permet une conversion automatique entre chaînes de caractères et valeurs numériques au moment de l'exécution.

Toute opération arithmétique appliquée à une chaîne de caractères tente de convertir cette chaîne en un chiffre, suivant les règles de conversion habituelles.

Inversement, chaque fois qu'un chiffre ou un nombre est utilisé lorsqu'une chaîne est prévue, ce dernier est converti en une chaîne dans un format raisonnable.

Pour un contrôle complet, sur la façon dont les chiffres et les nombres sont convertis en chaînes, utiliser la fonction string.format() de la bibliothèque sur les chaînes de caractères.

2-e. Les « chuncks » et les blocs 2-e-1. Les chunks

L'unité d'exécution de Lua est appelé « chunk ».

Et un « chunk », n'est ni plus ni moins qu'un morceau de code.

Un morceau de code, représente une séquence d'instructions qui sont exécutées séquentiellement.

Chaque séquence, peut être éventuellement suivie d'un point-virgule ( ;).

Ce n'est absolument pas une obligation, vous faites comme vous le sentez. Avec ou sans, c'est pareil ... sauf sur une même ligne où le point virgule est OBLIGATOIRE pour séparer deux séquences.

Lua gère un morceau de code comme le corps d'une fonction anonyme avec un nombre variable d'arguments.

En tant que tel, des « chunks » peuvent recevoir des variables locales, des arguments et des valeurs de retour.

Un « chunk » peut être stocké dans un fichier ou dans une chaîne de caractères à l'intérieur du programme hôte.

Pour exécuter un « chunk », Lua pré-compile premièrement le « chunk » en instructions pour la machine virtuelle, puis exécute le code compilé avec un interpréteur.

2-e-2. Les blocs



Un bloc est constitué d'une liste de déclarations.

Syntaxiquement, un bloc est équivalent à un « chunk ».

Un bloc peut être explicitement délimitée pour produire une seule déclaration, par exemple : do ... bloc ... end

Les blocs explicites sont utiles pour contrôler la portée de déclaration des variables. Ils sont aussi parfois utilisés pour ajouter un return ou un break dans le milieu d'un autre bloc.

La notion de blocest importante, car c'est elle qui détermine la portée des variables locales. Vous y reviendrez lorsque vous aborderez les variables. Et n'oubliez pas qu'un bloc peut aussi contenir un ou plusieurs autres blocs, qui peuvent aussi contenir d'autres blocs ...

Mais en attendant, et pour peut-être mieux fixer les esprits, voici quelques exemples :

do ... bloc ... end

function nomFonction() ... bloc ... end for ... bloc ... end if condition then ... bloc ... end while ... bloc ... end

repeat ... bloc ... until

2-f. Les opérateurs arithmétiques

Lua soutient les opérateurs arithmétiques habituels :Les opérateurs logiques sont : and, or et not.

  • Les opérateurs arithmétiques sont :
  • les binaires :

o + (addition),

o - (soustraction),

o * (multiplication),

o / (division),

o % (modulo),

o ^ (élévation) ;

  • et l'unaire :
  • - (négation).

Si les opérandes sont des chiffres ou de nombres (ou des chaînes de caractères qui peuvent être convertis en nombres), alors toutes les opérations ont le sens usuel.

Élévation, fonctionne pour tout exposant. Par exemple, x^(-0,5) calcule l'inverse de la racine carrée de x.

Modulo est défini comme suit : a % b == a - math.floor(a/b)*b.

C'est le reste d'une division, qui arrondit le quotient vers moins l'infini.

2-g. Les opérateurs relationnels Les opérateurs relationnels en Lua sont :

== égal

~= différent de

< plus petit que

> plus grand que

<= plus petit que ou égal

>= plus grand que ou égal

Le résultat de ces opérateurs est toujours true ou false.

L'égalité == (deux fois le signe égal) compare d'abord le type de ses opérandes. Si les types sont différents, alors le résultat sera false.

Les valeurs nombres et chaînes sont comparées selon la méthode habituelle.

Les objets (tables, userdata, threads, et fonctions) sont comparés par référence. Deux objets sont considérés comme égaux, uniquement s'ils ont le même objet.

Chaque fois que vous créez un nouvel objet (table, userdata, thread, ou fonction), il est automatiquement différent de n'importe quel autre objet existant.

Vous pouvez changer la façon dont Lua compare les tables et userdatas en utilisant la méta-méthode « eq ». (Voir à ce sujet, le chapitre consacré aux métatables.)

La coercition ne peut pas s'appliquer aux comparaisons d'égalité. Ainsi, "0" == 0 s'évaluera à false, et t[0] et t["0"] représentent deux entrées différentes d'une table.

L'opérateur ~=, (différent de) est exactement la négation de l'égalité ==. Les opérateurs fonctionnent de la façon suivante :

  • si les deux arguments sont des nombres, alors ils sont comparés en tant que tels ;
  • dans le cas contraire, si les deux arguments sont des chaînes, alors leurs valeurs sont comparées en fonction de la localisation en cours ;
  • sinon, Lua essaie d'appeler le « lt » ou « le » de la méta-méthode. (Voir à ce sujet, le chapitre consacré aux métatables.) ;
  • une comparaison a > b est traduite en b < a et a >= b est traduite en b <= a.

2-h. Les opérateurs logiques

Les opérateurs logiques sont and, or, et not. (Qui font aussi partie des mots réservés.)

Comme les structures de contrôle (if, while, etc.), tous les opérateurs logiques considèrent à la fois false et nil comme faux et tout le reste comme vrai.

L'opérateur de négation not retourne toujours false ou true.

L'opérateur de conjonction and retourne son premier argument si cette valeur est false ou nil, ou son second argument dans le cas contraire.

L'opérateur de disjonction or retourne son premier argument si cette valeur est différente de nil et false, ou son second argument dans le cas contraire.

Les deux opérateurs and et or utilisent un raccourci d'évaluation.

C'est-à-dire que le second opérande est évalué uniquement si nécessaire.

Voici quelques exemples :

10 or 20 --> 10

10 or error() --> 10

nil or "a" --> "a"

nil and 10 --> nil

false and error() --> false

false and nil --> false

false or nil --> nil

10 and 20 --> 20

2-i. L'opérateur « length »

L'opérateur length est représenté par l'opérateur unaire # (dièse).

La longueur d'une chaîne de caractères correspond à son nombre d'octets qui est, au sens habituel la longueur de la chaîne où chaque caractère est un octet.

La longueur d'une table t est définie comme étant tout indice entier n, tel que t[n] ne soit pas nil et que t[n+1] soit nil. En outre, si t[1] est nil, alors n est égal à zéro.

Pour une table régulière, où toutes les valeurs non-nil ont des clés de 1 à n, alors sa longueur sera exactement la valeur du dernier indice n.

Si la table a des « trous » (c'est-à-dire des valeurs nil comprises entre d'autres valeurs non¬nil), alors #t pourrait être l'un des indices qui précède directement une valeur nil. (Ce serait alors cette dernière valeur nil qui pourrait être considérée comme la fin du tableau.)

Un programme peut modifier le comportement de l'opérateur length par n'importe quelle valeur, par le biais des chaînes de méta-méthodes. (Voir à ce sujet, le chapitre consacré aux métatables.)

local string = "Lua: Mode d'emploi." local long = #string

print(long) --> 19

Y compris les espaces, les deux points (:), l'apostrophe (') et le point (.).

2-j. L'ordre de priorité des opérateurs

La priorité des opérateurs suit l'ordre établi ci-dessus, de la plus petite à la plus grande priorité.



Bien évidement, vous pouvez utiliser des parenthèses pour modifier la préséance d'une expression.

La concaténation (..) et l'élévation (A), sont des opérateurs associatifs à droite. Tous les autres opérateurs binaires, sont associatifs à gauche.

2-k. La concaténation

L'opérateur de concaténation de chaînes de caractères dans Lua, est représenté par deux points (..).

Si les deux opérandes sont des nombres, alors ils sont convertis en chaînes de caractères. Si un des opérandes est un nombre, il est converti en chaîne de caractères.

Et si les deux opérandes sont des chaînes, alors ils n'ont pas besoin de conversion.

Sinon, le « concat » de la méta-méthode est appelé. (Voir à ce sujet, le chapitre consacré aux métatables.)

string = "Lua:" string2 = "Mode"

string3 = "d'emploi."

nb = 2011

stringA = string1.." "..string2

stringB = " "..string3.." Novembre "..nb print(stringA..stringB)

--> Lua: Mode d'emploi. Novembre 2011

Bien, ceci étant dit, vous allez enfin pouvoir entrer dans le vif du sujet et vous pencher sérieusement sur la façon d'utiliser ce langage.

La première ligne de code que tape sur son ordinateur un programmeur est très certainement celle qui va permettre d'initialiser une ou plusieurs variables.

Car aucun programme ne peut tourner, s'il n'a pas au moins une variable déclarée ! Mais une variable, c'est quoi ?

  1. Les variables

3-a. Une variable, c'est quoi ?

Une variable est un emplacement mémoire dans lequel on va ranger des données. (Par exemple, les tiroirs d'une commode, empilés les uns sur les autres.)

Chaque emplacement mémoire (tiroir donc) possède une adresse qui lui est propre et dans lequel vous ne pouvez ranger que 8 bits.

Adresses sur 32 bits Valeurs sur 8 bits

0000 ... 0000 01011001

0000 ... 0001 11010111

0000 ... 0010 00101110

Pour pouvoir ranger plus que 8 bits, il faudra utiliser plusieurs emplacements mémoires, sachant que le nombre d'emplacements est fonction du nombre d'adresses disponibles qui dépend du CPU et de l'OS.

Pour valoriser 16 bits, on utilisera 2 cases mémoires sur la même adresse, 3 pour 24 bits et 4 cases mémoires pour mémoriser par exemple, une adresse de 32 bits ...

Adresses sur 32 bits Valeurs sur 8 bits

0000 ... 0000 01011001

  11010111

0000 ... 0001 00101110

  11100101

  00111011

 Afin de permettre un suivi et une reconnaissance de ces variables, vous allez leur donner un nom.

(Comme un étiquetage de chaque tiroir.)

maVariable = x

Lua utilise la non-valeur nil , pour représenter une absence de valeur. (Un tiroir vide sera égal à nil .)

Dans l'exemple suivant, la variable maVariable n' est pas encore définie. Elle n'a donc aucune valeur et l'emplacement mémoire pourra ainsi être récupérée par le « garbage collector (3) » .

maVariable = nil

En principe vous n'aurez pas à le faire, mais si toutefois vous devez annuler une variable, il vous suffira de la valoriser à nil . (Ou plus exactement de la non-valoriser !)

3-b. Global ou local ?

En Lua, il existe deux sortes de variables :

-- La variable globale, qui n'a pas besoin d'être déclarée.

nomVariable = la valeur que l'on veut lui affecter.

-- La variable locale, qui se déclare de la façon suivante :

local nomVariable = la valeur que l'on veut lui affecter.

Toute variable est supposée être globale, sauf si explicitement elle a été déclarée en tant que locale.

La variable globale existe pour l' ensemble du programme, alors que la variable locale n'existe qu'à l' intérieur de l'environnement dans lequel elle a été créée.

Avant sa première affectation, la valeur d'une variable, est égale à nil .

Toujours utiliser, autant que faire se peut, les variables locales. Ces dernières occupent moins de place en mémoire et sont plus rapides.

3-c. Affectation

Comment affecter une valeur à une variable ?

Vous choisissez une lettre ou plusieurs, écrit en CAPITALES ou en minuscules, peu importe, du moment qu'il ne commence pas par un chiffre.

local b1 sera valable, alors que local 1b sera rejeté, tout comme sera rejeté toute variable utilisant un « mot-clé », tel que définis ci-dessous :

and break do else elseif end false for if in local nil not repeat then return true or

until while function

Et rappelez-vous aussi que Lua est sensible à la casse , ce qui signifie que si and est un mot réservé et donc interdit, rien ne vous empêche d'utiliser And ou AND ou aNd, qui sont eux différents et donc valides.

Sachez aussi que, par convention, les noms commençant par un caractère de soulignement suivi par des lettres capitales (comme _VERSION ) sont réservés aux variables globales internes, utilisées par Lua.

Et que généralement, les lettres CAPITALES sont réservées pour les valeurs constantes. (Q ui sont des « variables w qui ne varient pas ! )

Affectation simple :

local x = 25 ;

local y = "bananes" ;

Affectation multiple :

local x, y = 25, "banane";

local x, y, z, w = 25, "banane", "2012", longueur ;

x aura pour valeur le nombre 25 ;

y aura pour valeur la chaîne "banane" ;

z aura pour valeur la chaîne "2012" ;

et w aura pour valeur la variable longueur.

Tout peut être déclaré comme variable : Un nom, une fonction, une table ...

Déclaration d'une table :  local nomTable = {} ;

Déclaration d'une fonction :  local function NomFonction() ... end ;

Déclaration d'un chiffre :  local x = 235 ;

Déclaration d'un nom :  local x = "poubelle" ;

Déclaration d'une chaîne de caractères :  local x = "La cigale ayant chanté tout l'été ... " ;

Déclaration d'une constante :  local CECI_EST_UNE_VARIABLE_FIXE = 123456 ;

etc.

3-d. La portée lexicale



Lua est un langage à portée lexicale.

Il est important d'avoir toujours à l'esprit cette notion de portée lexicale et de bien comprendre où commence et où se termine la portée d'une variable, faute de quoi ... c' est le plantage assuré !

La portée d'une variable, commence juste après la première déclaration de la variable à l'intérieur d'un bloc et dure jusqu'à la fin de ce bloc.

Un bloc, est un ensemble d'instructions sur plusieurs lignes.

Une fonction, une boucle for, while, do, etc. constitue un bloc et toute déclaration d'une variable à l'intérieure d'un bloc, appartient à ce bloc.

Un petit exemple :

x = 10 -- ceci est une variable globale

do -- déclaration d'un nouveau bloc

local x = x -- initialisation d'une nouvelle variable 'x'

-- MAIS cette fois ci "local" en reprenant la -- première valeur de x global. (10)

print("1: "..x) --> 1: 10

x = x + 1

do -- déclaration d'un autre bloc à l'intérieure du premier

local x = x + 1 -- encore une autre variable 'x' ...

-- mais locale au deuxième bloc

print("2: "..x) --> 2: 12

end

print("3: "..x) --> 3: 11

end

print("4: "..x) --> 4: 10

La variable x est maintenant sortie des deux blocs, ( les variables locales n'existent plus)  , elle retrouve donc sa première valeur : x = 10

Et il ne faut pas oublier que chaque exécution d'une déclaration qui redéfinit une variable locale crée automatiquement « une nouvelle variable locale ».

Prenez l'exemple suivant :

a = {} -- déclaration d'une table 'a'

local x = 20 -- déclaration d'une variable locale 'x'

for i = 1, 10 do

local y = 0 -- déclaration d'une nouvelle variable locale -- et interne à la boucle for ... end a[i] = function() y = y + 1; return x + y end

print("i = "..i.." (x + y) = "..x + y)

end

Les tables et les fonctions seront expliquées plus loin.

Mais pour le moment, il faut simplement comprendre que la boucle tourne 10 fois, ce qui

représente dix instances de la fonction anonyme .

Chaque boucle, va utiliser une nouvelle variable y , tandis que toutes partagent le même x . La variable i prendra + 1 à chaque tour, normal, mais x + y sera toujours égal à 20 du fait que y redevient local à chaque tour et donc = 0.

Il est très important de bien comprendre cette notion de portée lexicale et de bien saisir que chaque variable locale n'est définie et n'existe que dans le bloc qui la contient.

3-e. Le typage

Un aspect important avec les variables de Lua, concerne le typage ... ou plus exactement l'absence de typage. 

Dans beaucoup de langages vous devez définir le type de variable que le programme devra utiliser : int, short, long, double, etc.

Avec Lua il n' en est RIEN.  Ce n'est pas la variable qui est typée, mais la valeur .

Lua est un langage à typage dynamique . Ce qui signifie que vous ne devez pas indiquer

le type de valeur que devra contenir la variable.

La variable connaîtra son type en fonction de la valeur ou de l'objet qui lui aura été assigné.

local x = 123 -- x est un nombre

local x = "123" -- x est une chaîne de caractères

local x = {} -- x est une table

Chaque type de variable est défini en fonction de ce que vous lui mettez dedans ...

  • si vous y mettez une fonction le type de la variable seraune function ;
  • si vous y mettez un boolean (true ou false) le type de la variable sera boolean ;
  • si vous y mettez nil , le type de la variable sera nil ;
  • etc.

Vous ne pourrez bien sûr comparer ou additionner éventuellement que des variables de types identiques.

Il peut donc être nécessaire de vérifier le type d'une variable avant de procéder à une quelconque manipulation.

Et pour ce faire, il existe une fonction de base intitulée type ().

print(type(nomVariable)) -- retourne le type de nomVariable

3-f. À retenir

  1. une variable est un emplacement mémoire ;
  2. on donne un nom à une variable et une valeur : maVariable = 0 ;
  3. on la définit en tant que globale ou locale ;
  4. nil indique une variable vide ;
  5. pour une affectation simple : x = 25 ;
  6. pour une affectation multiple : x, y, z = 10, "abc", 322 ;
  7. la portée lexicale est à l'intérieur du bloc qui a créé la variable ;
  8. il existe huit « types » de base : nil, boolean, number, string, userdata, function, thread, et table ;
  9. Lua est un langage à typage dynamique. Il n'y a pas de type à l'initialisation d'une variable et la variable adopte le type de la valeur qu'elle détient ;
  10. type(maVariable) --> donne le type de, maVariable.
  11. Les structures de contrôle

4-a. Égal (=) ou bien égal (==) ?

Avant de voir (ou revoir ?) le sujet sur les boucles et les structures de contrôle, il me semble indispensable d'effectuer un petit rappel sur la signification exacte du signe égal, afin d'éviter de nombreux plantages.

x=2 --> indique que vous transférez la valeur 2 dans la variable x. x==25 --> signifie que la variable x est égale à 25.

if x == 25 then y = 2 end

Ceci peut paraître simpliste, mais croyez-moi, ce n'est pas anodin. 4-b. Qu'est-ce qu'une « condition » d'exécution ?

Pour expliquer ce que sont « les structures de contrôle », le mot condition sera plusieurs fois utilisé, comme dans les exemples suivants :

if condition then ... on exécute ... end while condition do ... on exécute ... end

repeat instruction until condition



192