Moteur de calcul pour tableur minimal en WebAssembly

Moteur de calcul WebAssembly simple pour tableur minimal, supportant addition et soustraction entre cellules avec interface JavaScript intégrée.

Brève Introduction

Moteur de calcul pour tableur minimal en WebAssembly (wasm)
DESCRIPTION :
Un moteur de calcul simple pour un tableur minimal, écrit en WebAssembly (WASM). Le moteur prend en charge des cellules avec des valeurs numériques et des formules de base d'addition et de soustraction entre cellules. Le code est prêt à l'emploi et commenté en italien.

NOTES SUPPLÉMENTAIRES :
Cet exemple est un moteur de calcul basique, pas un tableur complet. Il ne supporte que les formules d'addition et de soustraction entre cellules avec des références simples. Il est utile comme base pour des extensions futures.

EXPLICATIONS :
- Le module WebAssembly est écrit en WAT, un format textuel lisible pour WASM.
- Les cellules sont représentées comme un tableau de valeurs entières, avec des formules codées sous forme de chaînes passées depuis JavaScript.
- La fonction principale 'calcola_cella' prend un indice de cellule et calcule la valeur en résolvant les formules éventuelles.
- L'analyse des formules est très simple : seuls '+' et '-' et les références de cellules comme 'A1', 'B2' sont reconnus.
- L'interface JavaScript s'occupe de convertir les formules en paramètres numériques et de gérer la mémoire partagée avec WASM.

Code d'Exemple : wasm

;; 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)
)
×
×
×
Veux-tu régénérer la réponse ?
×
Exporter le chat
Choisissez le format d'export
⏳ Generazione PDF in corso…
Allegati
×
⚠️ Vous êtes sur le point de fermer le chat et de passer au générateur d’images. Si vous n’êtes pas connecté, vous perdrez notre conversation. Confirmez-vous ?
👁 Tu consultes une discussion partagée en mode temporaire. Elle ne sera pas enregistrée.
💬
×
Prompts enregistrés
×
Note privée
×
Étiquette
×
Rechercher dans toutes les discussions
×
Vos insights
Analyse en cours…
×
Préférences IA
Nom de l'assistant 30
Longueur des réponses
Modèle IA
Réponses structurées
Inclure des exemples
Utiliser des emojis
Guide-moi, ne résous pas Des indices et des questions plutôt que la réponse toute faite
Plus de réglages →
×
Partager cette discussion
Toute personne ouvrant ce lien pourra consulter la discussion ou l'ajouter à son profil comme discussion personnelle.
⚠️ Attention : les pièces jointes de la discussion seront également partagées. Qui l'ajoutera recevra une copie des fichiers dans son dossier.
Discussion partagée
Quelqu'un a partagé une discussion avec toi. Veux-tu seulement la consulter ou l'ajouter à tes discussions ?
⚠️ Attention : les pièces jointes de la discussion seront également partagées. Qui l'ajoutera recevra une copie des fichiers dans son dossier.
×

📌 Messages enregistrés

Chargement...

×

Historique des discussions

programmes-exemples · HISTORIQUE DU CHAT

Chargement...

Préférences IA

×
  • 🟢 BasiqueRéponses rapides et essentielles pour étudier
  • 🔵 MoyenQualité supérieure pour étude et programmation
  • 🟣 AvancéRaisonnement complexe et analyses détaillées
Expliquer les étapes

Exemple Complet

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>

Qu'est-ce qu'il faut ?

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.

Sujets Similaires

Bonjour WebAssembly : votre premier module minimal
Exemple minimal de module WebAssembly en WAT exportant une fonction somma pour additionner deux entiers, idéal pour débutants en WebAssembly.
Affichage d’un message avec WebAssembly et JavaScript
Exemple simple montrant comment afficher un message avec WebAssembly et JavaScript, idéal pour débutants, sans dépendances externes.
Somme de deux nombres en WebAssembly
Exemple complet en WebAssembly pour additionner deux nombres entiers avec un module WAT simple, idéal pour débutants en WebAssembly.
Mini calculatrice d’addition en WebAssembly
Mini calculatrice d’addition en WebAssembly : additionnez deux entiers avec un code WAT simple, compilable et exécutable dans tout environnement WebAssembly.
Retour d’une constante depuis un module WebAssembly
Exemple simple de module WebAssembly en WAT exportant une fonction retournant une constante entière, avec intégration JavaScript expliquée.
Conversion simple int → float en WebAssembly
Exemple simple de conversion d’un entier en float 32 bits en WebAssembly avec code WAT et JavaScript, idéal pour débutants en wasm.
Fonction de multiplication de base en WebAssembly
Exemple complet d’une fonction WebAssembly en WAT qui multiplie deux entiers 32 bits, avec commentaires en italien pour débutants.
Appeler une fonction WebAssembly depuis JavaScript
Exemple simple pour appeler une fonction WebAssembly (WASM) depuis JavaScript, additionnant deux entiers avec explications détaillées pour débutants.