Moteur de calcul WebAssembly simple pour tableur minimal, supportant addition et soustraction entre cellules avec interface JavaScript intégrée.
;; Moteur de calcul pour tableur minimal
;; Supporte les cellules avec valeurs numériques ou formules d'addition/soustraction
(module
;; Mémoire pour chaînes et données
(memory (export "memoria") 1)
;; Table pour fonctions (non utilisée mais requise par WASI)
(table 0 anyfunc)
;; Fonction pour convertir code ASCII des lettres en indice de colonne (A=0, B=1, ...)
(func $colonna_da_char (param $c i32) (result i32)
local.get $c
i32.const 65 ;; 'A'
i32.sub
)
;; Fonction pour convertir référence de cellule type 'A1' en indice de cellule (ligne*10 + colonne)
;; Suppose un maximum de 10 colonnes et 10 lignes pour simplifier
(func $indice_cella (param $ptr i32) (result i32)
;; ptr pointe vers chaîne ASCII 'A1' terminée par 0
(local $col i32)
(local $row i32)
(local $c i32)
;; Lire colonne
local.get $ptr
i32.load8_u
call $colonna_da_char
local.set $col
;; Lire ligne (supposons un chiffre)
local.get $ptr
i32.const 1
i32.add
i32.load8_u
i32.const 48 ;; '0'
i32.sub
local.set $row
;; Calculer indice = ligne * 10 + colonne
local.get $row
i32.const 10
i32.mul
local.get $col
i32.add
)
;; Tableau de cellules : 100 cellules (10x10), valeurs entières
(global $celle (mut i32) (i32.const 0)) ;; pointeur base tableau cellules
;; Fonction pour initialiser tableau cellules (offset mémoire 1024)
(func $init_celle
(global.set $celle (i32.const 1024))
;; Initialiser toutes à zéro
(local $i i32)
(local.set $i (i32.const 0))
(block
(loop
local.get $i
i32.const 100
i32.ge_s
br_if 1
global.get $celle
local.get $i
i32.const 4
i32.mul
i32.add
i32.const 0
i32.store
local.get $i
i32.const 1
i32.add
local.set $i
br 0
)
)
)
;; Fonction pour définir valeur cellule (indice, valeur)
(func (export "imposta_valore") (param $indice i32) (param $valore i32)
global.get $celle
local.get $indice
i32.const 4
i32.mul
i32.add
local.get $valore
i32.store
)
;; Fonction pour obtenir valeur cellule (indice)
(func (export "leggi_valore") (param $indice i32) (result i32)
global.get $celle
local.get $indice
i32.const 4
i32.mul
i32.add
i32.load
)
;; Fonction pour calculer valeur cellule avec formule simple
;; Formule passée comme chaîne en mémoire (ptr, len)
;; Supporte seulement formules du type '=A1+B2' ou '=A1-B2'
(func (export "calcola_cella") (param $formula_ptr i32) (param $formula_len i32) (result i32)
(local $pos i32)
(local $carattere i32)
(local $stato i32)
(local $val1 i32)
(local $val2 i32)
(local $op i32) ;; 1 = +, 2 = -
(local $ref_ptr i32)
(local $ref_len i32)
;; État 0 : attente '='
;; État 1 : lecture première cellule
;; État 2 : lecture opérateur
;; État 3 : lecture deuxième cellule
local.set $pos (i32.const 0)
local.set $stato (i32.const 0)
(block $fine
(loop $loop
local.get $pos
local.get $formula_len
i32.ge_u
br_if $fine
local.get $formula_ptr
local.get $pos
i32.add
i32.load8_u
local.set $carattere
;; Changement d'état
local.get $stato
i32.const 0
i32.eq
if
;; Doit être '='
local.get $carattere
i32.const 61 ;; '='
i32.ne
if
;; Formule invalide, retourne 0
i32.const 0
return
end
local.set $stato (i32.const 1)
else
local.get $stato
i32.const 1
i32.eq
if
;; Lecture première cellule (deux caractères)
;; Sauvegarder ptr et len
local.get $formula_ptr
local.get $pos
i32.add
local.set $ref_ptr
local.get $pos
i32.const 2
i32.add
local.set $pos
local.get $ref_ptr
local.get $pos
i32.sub
local.set $ref_len
;; Calculer indice cellule
local.get $ref_ptr
call $indice_cella
local.set $val1
local.set $stato (i32.const 2)
br $loop
end
local.get $stato
i32.const 2
i32.eq
if
;; Lecture opérateur
local.get $carattere
i32.const 43 ;; '+'
i32.eq
if
i32.const 1
local.set $op
else
local.get $carattere
i32.const 45 ;; '-'
i32.eq
if
i32.const 2
local.set $op
else
;; Opérateur invalide
i32.const 0
return
end
end
local.set $stato (i32.const 3)
end
local.get $stato
i32.const 3
i32.eq
if
;; Lecture deuxième cellule (deux caractères)
local.get $formula_ptr
local.get $pos
i32.add
local.set $ref_ptr
local.get $pos
i32.const 2
i32.add
local.set $pos
local.get $ref_ptr
local.get $pos
i32.sub
local.set $ref_len
;; Calculer indice cellule
local.get $ref_ptr
call $indice_cella
local.set $val2
br $fine
end
end
local.get $pos
i32.const 1
i32.add
local.set $pos
br $loop
)
)
;; Maintenant calculer val1 op val2
local.get $op
i32.const 1
i32.eq
if
local.get $val1
local.get $val2
i32.add
return
end
local.get $op
i32.const 2
i32.eq
if
local.get $val1
local.get $val2
i32.sub
return
end
;; Si aucun opérateur valide, retourne 0
i32.const 0
)
;; Fonction de démarrage pour initialiser les cellules
(start $init_celle)
)html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Exemple complet de recherche linéaire et binaire en WebAssembly</title>
</head>
<body>
<h1>Recherche linéaire et binaire en WebAssembly</h1>
<p id="result-linear"></p>
<p id="result-binary"></p>
<script>
// Le module WebAssembly sous forme de texte (WAT) tel que fourni
const wasmCode = `(module
;; Définition de la mémoire linéaire : 1 page = 64KiB
(memory (export "memory") 1)
;; Fonction linear_search :
;; Paramètres : i32 ptr_array, i32 length, i32 target
;; Retourne : i32 indice ou -1 si non trouvé
(func (export "linear_search") (param $ptr i32) (param $len i32) (param $target i32) (result i32)
(local $i i32) ;; indice courant
(local $val i32) ;; valeur lue
(local.set $i (i32.const 0))
(block $exit
(loop $loop
;; Si i >= len, sortir
(br_if $exit (i32.ge_u (local.get $i) (local.get $len)))
;; Charger la valeur depuis la mémoire : ptr + i*4 (4 octets par i32)
(local.set $val
(i32.load
(i32.add (local.get $ptr) (i32.mul (local.get $i) (i32.const 4)))
)
)
;; Comparer avec target
(if (i32.eq (local.get $val) (local.get $target))
(then
;; Trouvé, retourner l'indice
(return (local.get $i))
)
)
;; Incrémenter i
(local.set $i (i32.add (local.get $i) (i32.const 1)))
(br $loop)
)
)
;; Non trouvé, retourner -1
(i32.const -1)
)
;; Fonction binary_search :
;; Paramètres : i32 ptr_array, i32 length, i32 target
;; Retourne : i32 indice ou -1 si non trouvé
(func (export "binary_search") (param $ptr i32) (param $len i32) (param $target i32) (result i32)
(local $low i32)
(local $high i32)
(local $mid i32)
(local $val i32)
(local.set $low (i32.const 0))
(local.set $high (i32.sub (local.get $len) (i32.const 1)))
(block $exit
(loop $loop
;; Si low > high, sortir
(br_if $exit (i32.gt_u (local.get $low) (local.get $high)))
;; mid = (low + high) / 2
(local.set $mid
(i32.div_u
(i32.add (local.get $low) (local.get $high))
(i32.const 2)
)
)
;; val = array[mid]
(local.set $val
(i32.load
(i32.add (local.get $ptr) (i32.mul (local.get $mid) (i32.const 4)))
)
)
;; Comparer val avec target
(if (i32.eq (local.get $val) (local.get $target))
(then
;; Trouvé, retourner mid
(return (local.get $mid))
)
)
(if (i32.lt_u (local.get $val) (local.get $target))
(then
;; target est plus grand, chercher dans la moitié supérieure
(local.set $low (i32.add (local.get $mid) (i32.const 1)))
)
(else
;; target est plus petit, chercher dans la moitié inférieure
(local.set $high (i32.sub (local.get $mid) (i32.const 1)))
)
)
(br $loop)
)
)
;; Non trouvé
(i32.const -1)
)
)`;
// Fonction utilitaire pour compiler le module WAT en WebAssembly
async function compileWasm(wat) {
// Utilisation de wabt.js pour convertir WAT en binaire
if (typeof wabt === 'undefined') {
throw new Error('La bibliothèque wabt.js est requise pour compiler WAT en WebAssembly.');
}
const wabtModule = wabt.parseWat('module.wat', wat);
const { buffer } = wabtModule.toBinary({});
return await WebAssembly.instantiate(buffer);
}
// Exemple complet d'utilisation
(async () => {
// Charger wabt.js depuis CDN pour convertir WAT en wasm
const wabtScript = document.createElement('script');
wabtScript.src = 'https://cdn.jsdelivr.net/npm/wabt@1.0.47/index.js';
document.head.appendChild(wabtScript);
await new Promise(resolve => wabtScript.onload = resolve);
// Compiler et instancier le module
const wasmInstance = await compileWasm(wasmCode);
const { linear_search, binary_search, memory } = wasmInstance.instance.exports;
// Préparer un tableau typé dans la mémoire WebAssembly
const array = new Int32Array(memory.buffer, 0, 10);
// Remplir le tableau trié pour la recherche binaire
array.set([3, 6, 8, 12, 14, 17, 25, 29, 31, 42]);
const length = 10;
const target = 17;
// Appeler la recherche linéaire
const indexLinear = linear_search(0, length, target);
// Appeler la recherche binaire
const indexBinary = binary_search(0, length, target);
// Afficher les résultats
document.getElementById('result-linear').textContent = `Recherche linéaire: l'élément ${target} est à l'indice ${indexLinear}`;
document.getElementById('result-binary').textContent = `Recherche binaire: l'élément ${target} est à l'indice ${indexBinary}`;
})();
</script>
</body>
</html>Module WebAssembly écrit en WAT (WebAssembly Text Format).
Fonction d'analyse et de calcul d'expressions simples (addition et soustraction) entre cellules.
Tableau de cellules avec valeurs numériques ou formules (ex. 'A1', 'B2', '=A1+B2').
Configuration logicielle : compilation via wat2wasm (WebAssembly Binary Toolkit).
Interface JavaScript pour charger le module WASM et passer les données.
Aucun matériel externe requis (pas d'Arduino).
Dépendances logicielles : Node.js ou navigateur moderne avec support WebAssembly.
Configuration : le module expose des fonctions pour définir des valeurs et calculer des cellules.