Upsilon porté sur ti nspire (en test)
Posté: 22 Mai 2023, 14:59
(J'ouvre ce fil pour ne pas polluer celui du portage d'Upsilon sur les Casio Graph 90).
Upsilon est un fork du système Epsilon des calculatrices Numworks, réalisé à partir de Omega, lui-même issu de la dernière version modifiable et redistribuable (pour un usage non commercial) d'Epsilon (15.5). Historiquement, le premier portage de Upsilon sur TI Nspire (monochrome) a été fait par Kerry Shen en janvier 2023 (https://github.com/UpsilonNumworks/Upsilon/pull/131), mais il n'a pas finalisé son portage. Heath l'a utilisé comme modèle pour faire un portage sur Casio Graph 90, et je suis parti du modèle du portage sur Casio pour en faire un sur TI Nspire CX/CX2 (je n'avais pas trouvé trace du portage de Kerry Shen).
Je viens de mettre à jour mon port d'Upsilon pour les Nspire CX et CX2
https://www-fourier.univ-grenoble-alpes.fr/~parisse/ti/upsilon.tns
avec un prototype de persistance à tester. Par persistance, je veux dire que d'une exécution à l'autre une bonne partie des données sont conservées, par exemple les scripts Python, mais aussi (et c'est nouveau) les données de l'application fonction ou suites, ce qui est quand même plus pratique si on veut réellement utiliser cet environnement. L'historique des calculs n'est pas préservé (en tout cas pour le moment). Le fichier de persistance s'appelle nwstore.nws.tns.
A terme, on devrait pouvoir échanger ce type de fichiers entre différents portages de Upsilon, ce qui permettrait de cloner un environnement complet de résolution de problèmes entre des calculatrices de marques différentes: Casio Graph 90/FXCG50, TI Nspire tous modèles, Numworks (non verrouillées, sauf si Numworks décide d'adopter un stockage compatible). Il ne serait plus nécessaire pour un prof de recommander un unique modèle d'un constructeur, il suffirait de donner une liste de modèles compatibles.
Pour utiliser upsilon.tns, pas besoin d'aller plus loin, copiez-le sur votre Nspire et lancez le après avoir activé ndless.
Ce qui suit est technique et s'adresse aux développeurs qui auront peut-être des suggestions.
Le problème de la persistance des données d'une exécution à l'autre est que Numworks stocke les expressions avec un format binaire qui dépend de la position en mémoire des fonctions comme sin/cos/+/*, etc. Or d'une exécution à une autre, ces adresses varient sur la TI Nspire (ça dépend de l'état de la mémoire au moment du lancement de upsilon.tns) et aussi d'une marque de calculatrice à une autre. Pour contourner le problème, je me suis dit qu'il suffisait de stocker les expressions au format texte dans le scriptstore et utiliser le parser quand on a besoin de les relire dans le scriptstore. Sauf que ce n'est pas si simple à mettre en oeuvre, en tout cas pour moi qui ai des habitudes de codage radicalement différentes de celles de Epsilon. Le premier écueil que j'ai rencontré c'est que la variable dépendante (x dans une fonction f(x), n dans une suite u_n) est "imprimé" comme caractère 0x1 par Epsilon et inversement il faut utiliser cette "variable" dans une chaine à parser, si on utilise 'x' ou 'n' ça ne marche pas. Le deuxième problème fut la mise à jour au bon endroit dans le scriptstore des variables (par exemple pour la valeur initiale u0 d'une suite et l'expression de u(n+1) en fonction de u(n)), les fonctions d'Epsilon sont à mon avis difficiles à localiser avec des espaces de noms imbriqués à plusieurs niveaux et ultra-protégées (avec des membres protégés et privés, impossible à appeler si on se refuse à modifier des header), et je n'ai pas trouvé de petit texte pour se repérer dans le code de Poincare et des apps.
Pour l'instant j'ai résolu le premier problème de la variable dépendante en identifiant l'extension du nom de record, si c'est .func je dois gérer les x, si c'est .seq je dois gérer les n. Pour le deuxième problème, j'ai cherché longtemps sans succès, pour finalement aboutir à une solution qui semble marcher: appeler la fonction de stockage originelle de Numworks, et une fois qu'elle est stockée on réécrit dessus la version "string" de l'enregistrement (qui est plus courte).
Ca donne une construction fragile qui demande à être validée par des tests.
Les modifs du source correspondantes sont dans les fichiers apps/shared/expression_model.cpp et poincare/src/expression.cpp (+un ajout de paramètre dans poincare/include/poincare/expression.h) dans des #ifdef STRING_STORAGE, cf. l'archive
https://www-fourier.univ-grenoble-alpes.fr/~parisse/ti/upsilon_changes.tgz
Upsilon est un fork du système Epsilon des calculatrices Numworks, réalisé à partir de Omega, lui-même issu de la dernière version modifiable et redistribuable (pour un usage non commercial) d'Epsilon (15.5). Historiquement, le premier portage de Upsilon sur TI Nspire (monochrome) a été fait par Kerry Shen en janvier 2023 (https://github.com/UpsilonNumworks/Upsilon/pull/131), mais il n'a pas finalisé son portage. Heath l'a utilisé comme modèle pour faire un portage sur Casio Graph 90, et je suis parti du modèle du portage sur Casio pour en faire un sur TI Nspire CX/CX2 (je n'avais pas trouvé trace du portage de Kerry Shen).
Je viens de mettre à jour mon port d'Upsilon pour les Nspire CX et CX2
https://www-fourier.univ-grenoble-alpes.fr/~parisse/ti/upsilon.tns
avec un prototype de persistance à tester. Par persistance, je veux dire que d'une exécution à l'autre une bonne partie des données sont conservées, par exemple les scripts Python, mais aussi (et c'est nouveau) les données de l'application fonction ou suites, ce qui est quand même plus pratique si on veut réellement utiliser cet environnement. L'historique des calculs n'est pas préservé (en tout cas pour le moment). Le fichier de persistance s'appelle nwstore.nws.tns.
A terme, on devrait pouvoir échanger ce type de fichiers entre différents portages de Upsilon, ce qui permettrait de cloner un environnement complet de résolution de problèmes entre des calculatrices de marques différentes: Casio Graph 90/FXCG50, TI Nspire tous modèles, Numworks (non verrouillées, sauf si Numworks décide d'adopter un stockage compatible). Il ne serait plus nécessaire pour un prof de recommander un unique modèle d'un constructeur, il suffirait de donner une liste de modèles compatibles.
Pour utiliser upsilon.tns, pas besoin d'aller plus loin, copiez-le sur votre Nspire et lancez le après avoir activé ndless.
Ce qui suit est technique et s'adresse aux développeurs qui auront peut-être des suggestions.
Le problème de la persistance des données d'une exécution à l'autre est que Numworks stocke les expressions avec un format binaire qui dépend de la position en mémoire des fonctions comme sin/cos/+/*, etc. Or d'une exécution à une autre, ces adresses varient sur la TI Nspire (ça dépend de l'état de la mémoire au moment du lancement de upsilon.tns) et aussi d'une marque de calculatrice à une autre. Pour contourner le problème, je me suis dit qu'il suffisait de stocker les expressions au format texte dans le scriptstore et utiliser le parser quand on a besoin de les relire dans le scriptstore. Sauf que ce n'est pas si simple à mettre en oeuvre, en tout cas pour moi qui ai des habitudes de codage radicalement différentes de celles de Epsilon. Le premier écueil que j'ai rencontré c'est que la variable dépendante (x dans une fonction f(x), n dans une suite u_n) est "imprimé" comme caractère 0x1 par Epsilon et inversement il faut utiliser cette "variable" dans une chaine à parser, si on utilise 'x' ou 'n' ça ne marche pas. Le deuxième problème fut la mise à jour au bon endroit dans le scriptstore des variables (par exemple pour la valeur initiale u0 d'une suite et l'expression de u(n+1) en fonction de u(n)), les fonctions d'Epsilon sont à mon avis difficiles à localiser avec des espaces de noms imbriqués à plusieurs niveaux et ultra-protégées (avec des membres protégés et privés, impossible à appeler si on se refuse à modifier des header), et je n'ai pas trouvé de petit texte pour se repérer dans le code de Poincare et des apps.
Pour l'instant j'ai résolu le premier problème de la variable dépendante en identifiant l'extension du nom de record, si c'est .func je dois gérer les x, si c'est .seq je dois gérer les n. Pour le deuxième problème, j'ai cherché longtemps sans succès, pour finalement aboutir à une solution qui semble marcher: appeler la fonction de stockage originelle de Numworks, et une fois qu'elle est stockée on réécrit dessus la version "string" de l'enregistrement (qui est plus courte).
Ca donne une construction fragile qui demande à être validée par des tests.
Les modifs du source correspondantes sont dans les fichiers apps/shared/expression_model.cpp et poincare/src/expression.cpp (+un ajout de paramètre dans poincare/include/poincare/expression.h) dans des #ifdef STRING_STORAGE, cf. l'archive
https://www-fourier.univ-grenoble-alpes.fr/~parisse/ti/upsilon_changes.tgz