Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » B2C : Convertisseur Basic en C
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

B2C : Convertisseur Basic en C

Posté le 02/07/2016 11:24

Mon nouveau projet est donc de faire un convertisseur basic -> C

Ce serait possible parce que toutes les fonctions du basic sont transposables en C (même les gotos), par exemple Locate(x, y, str) est remplacé par locate(x,y);Print(str), F-line remplacé par ML_line(), etc.

Par contre là où ça diffère de AldeBasicLib c'est que ce sera un convertisseur total. Par exemple si le programme voit "Mat M" il génèrera une matrice M adéquate. Le but étant de lancer le programme, de sélectionner un .g1r, et d'avoir un fichier .c prêt à compiler.

Cela pourrait être utile pour les gros jeux qui prennent toutes la mémoire principale et qui seraient mieux en C (je pense à CloneLab, Arkenstone, peut être Calcraft...)

Utilisation
Nécessite : Java, le SDK casio (ou un truc permettant de compiler des addins)

Clonez le repo http://git.planet-casio.com/Zezombye/B2C/ et exécutez B2C.java en remplaçant les arguments si besoin.
À noter que B2C n'étant pas fini, il est très probable que le programme que vous essayez de convertir vous fasse plein d'erreurs, que ce soit de B2C ou du SDK.

Programmes basic déjà convertis
NOTE: Ces programmes sont compatibles SH3. Si vous voulez les tester, convertissez les en SH4 si besoin !
Je n'ai absolument rien changé dans ces programmes (à part l'icône et le nom) donc le code est celui qu'on obtient avec B2C.

Démineur de Cakeisalie5 : http://www.mediafire.com/file/z6t5jmfh72wfnag/DEMNR.G1A (original)
Puissance 4 de Zezombye : http://www.mediafire.com/file/i1ucweo66ibjy67/PUISS4.G1A (original)

Fonctions actuellement implémentées :

- Commentaires
- Gotos&Lbls (heureusement que ça marche exactement de la même façon en C qu'en basic)
- If, Then, Else, IfEnd, ⇒
- Do, LpWhile
- While, WhileEnd
- For, To, Step, Next
- Prog, Return, Break, Stop
- Locate
- GetKey
- -> (assignement de variable/matrice/liste/dim)
- Dim, Mat, List
- L'opérateur '~'
- Variables A-Z, r, theta, Ans
- Opérateurs de calcul : + (unaire et binaire), - (unaire et binaire), *, /, ^, sqrt, racine n-ième
- Multiplication implicite (normalement)
- Opérateurs de comparaison : <, >, ≤, ≥, =, ≠
- Opérateurs logiques : And, Not, Or, Xor
- Ran# (fonction de la libc), RanInt# (par l'interpréteur casio actuellement, à changer)
- Int
- Fill(), ClrMat, ClrText
- Str, StrCmp, StrInv, StrJoin, StrLeft, StrRight, StrLen, StrLwr, StrUpr, StrMid, StrRotate, StrSrc, StrShift

Fonctions à implémenter :
- Nombres complexes
- Fonctions graphiques
- Gestion des pictures et captures
- Sauvegarde des variables

Note : les 3 fonctions suivantes ne seront pas implémentées fidèlement, il n'y aura qu'une implémentation rudimentaire.
- Les strings sans assignement (écrire "TEST" puis une nouvelle ligne)
- La fonction disp (◢)
- L'opérateur ?-> pour l'input de l'utilisateur

Fonctions qui ne seront peut être pas implémentées :
- L'écriture d'un nombre via la console (par exemple écrire "2+3" comme seule instruction affiche "5" sur l'interpréteur basic, mais il est difficile de savoir s'il faut l'afficher ou seulement la mettre dans Ans)

Comment B2C optimise le programme (autre qu'en compilant au lieu d'interpréter) par rapport à Casio

- Les opérations sont implémentées (enfin pour l'instant il n'y a que l'addition et la soustraction pour les nombres non complexes) nativement au lieu de passer par l'interpréteur; ainsi, additionner 10000x des nombres prend 1.5s pour l'implémentation de l'addition, et 4.4s si on passe par l'interpréteur.

- Les listes de Casio séparent les parties imaginaires et réelles. Par exemple, pour la liste {3, 1+2i, -4i, 6}, Casio la stockera en {3, 1, 0, 6, ?, 2, -4, ?} avec '?' 12 octets de padding. B2C ne fait pas cette séparation et stocke la partie imaginaire à côté de la partie réelle, ce qui fait qu'une fonction peut appeler directement "list_1" au lieu de passer par une fonction intermédiaire qui recolle les 2 parties.
L'inconvénient est que les listes ne possédant pas de complexes sont 2 fois plus grandes. (en fait, si le programme possède des nombres complexes, la taille du BCDvar est de 24 octets, et sinon 12)

- Pour les matrices : même chose qu'avec les listes.

- Les strings de Casio implémentent des caractères, qui peuvent être sur 1 ou 2 octets. Cette différence fait qu'on ne peut pas avoir un accès en O(1) car on ne peut pas savoir directement la position du i-ème caractère du string en calculant. Si on veut accéder à str_1[255], l'interpréteur casio doit itérer sur tout le string.
B2C permet un accès beaucoup plus rapide en stockant chaque caractère, multi-byte ou non, sur 2 octets. Ainsi, les fonctions des strings qui travaillent sur les caractères casio (toutes sauf StrCmp) sont plus rapides. StrCmp est possiblement plus lent que si B2C implémentait les strings comme le fait casio, mais la différence est négligeable.

Pour résumer : B2C bouffe un peu plus de RAM, mais il est beaucoup plus rapide.



1, 2, 3, 4, 5, 6 Suivante
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 02/07/2016 11:55 | #


On en a parlé vite fait sur le chat mais ce principe est horrible. Écrivez un compilateur qui génère de l'assembleur, plutôt. Générer du code pour des langages de haut niveau c'est crade par nature.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Dark storm Hors ligne Labélisateur Points: 11641 Défis: 176 Message

Citer : Posté le 02/07/2016 12:10 | #


Non, ce qui est beaucoup plus propre, c'est faire un installateur de jeu Basic. Éventuellement lui donner le nom de CalcCenter et ainsi poser les bases du concept que j'avais évoqué il y a bien longtemps.

Par exemple, tu lis dans la mémoire de stockage les fichiers en .g*m, tu les affiches de manière user-frienly, et tu fais un bouton « Installer » et un autre « Sauvegarder ». Selon le choix, tu écrase le g1m existant, éventuellement avec une alerte si le nom du jeu dans la mémoire de stockage est différent de celui dans la mémoire principale, pour éviter d'écrire Arkenstone sur CloneLab par exemple ; ou tu copie le g1m dans la mémoire principale. Éventuellement ajouter une entrée par défaut appelée « Cours » pour y sauvegarder ce qui est utile pour les cours.
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Hackcell Hors ligne Maître du Puzzle Points: 1531 Défis: 11 Message

Citer : Posté le 02/07/2016 14:08 | #


Juste une question pour lephé, comment fait-on un compilateur? Je suis curieux.
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 02/07/2016 17:17 | #


Hackcell a écrit :
Juste une question pour lephé, comment fait-on un compilateur? Je suis curieux.

En général on analyse le code à compiler (vois les AST) et on en génère une représentation dite intermédiaire. C'est en travaillant sur cette représentation qu'on fait les optimisations et les retouches (vois LLVM). Ensuite on la réécrit généralement en Assembleur et on l'assemble, ce qui donne le code objet.

Edit : C'est plus subtil que s/Locate A, B, Str/locate(A, B); Print((unsigned char *)Str)/ quoi.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 02/07/2016 20:11 | #


Comme j'ai dit en fait le truc le plus dur sera d'interpréter la commande. Si on prend la commande du topic, il faut implémenter un ordre d'opérations. Dans ce cas l'opération => aura priorité sur les autres (sauf si j'en trouve une qui a une plus grande priorité). On aurait par exemple :


String parse(String str) {
    if (str.contains("=>")) {
        return "if (" + parse(str.substring(0, indexOf("=>"))) + ") {" + parse(str.substring(indexOf("=>"))) + "}";
    }
}


Il faut aussi gérer les parenthèses, les opérations qui ne sont pas forcément au début (par exemple : 1+2! ou (1+2)! ou 1+(2!) etc), bref ça va être un vrai défi. Ah et il faut aussi gérer les strings (dans l'exemple ci-dessus, si le => est dans un string, il produirait des instructions invalides).

Donc pour l'instant je vais générer en C parce que je n'y connais absolument rien à l'assembleur, mais quand j'aurai fini remplacer le C par de l'assembleur sera (je pense) très simple. Si on prend l'exemple ci dessus il suffirait de remplacer les if(condition){instruction} par l'équivalent en assembleur.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Nemhardy Hors ligne Grand maître des Traits d'Esprit Points: 1243 Défis: 54 Message

Citer : Posté le 02/07/2016 20:13 | #


Ben transformer le C en assembleur c'est ce que fait gcc par exemple, et c'est loin d'être simple en fait. ^^'
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 02/07/2016 20:24 | #


En fait c'est pour ça qu'il faudrait générer du C et non pas de l'assembleur, parce que GCC compilerait bien mieux qu'on pourrait générer de l'assembleur
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 02/07/2016 20:45 | #


Zezombye a écrit :
quand j'aurai fini remplacer le C par de l'assembleur sera (je pense) très simple

Ben génère de l'Assembleur. Pourquoi t'obstiner à faire un truc crade ?

Et non l'analyse syntaxique des expressions est loin d'être si difficile. Les parenthèses ne sont qu'un opérateur dont la priorité est maximale. La syntaxe est en fait très générique si l'on parvient à exprimer les opérateurs avec suffisamment de souplesse.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Dark storm Hors ligne Labélisateur Points: 11641 Défis: 176 Message

Citer : Posté le 02/07/2016 20:49 | #


Il n'empèche que je le redit, faire un compilateur de Basic est très crade. Enfin, vu que je sais que tu n'y arrivera pas – soyons réalistes, comment tu va gérer toutes les astuces inhérentes à l'interpréteur de Casio ? – vas-y, mais je pense que tu ferai mieux d'investir ton temps ailleurs…
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 02/07/2016 20:56 | #


Pour l'instant je ne vois rien que je ne puisse gérer, tu penses à quoi ?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 02/07/2016 22:05 | #


Dark storm a écrit :
Il n'empèche que je le redit, faire un compilateur de Basic est très crade.

Je ne vois pas en quoi. Un compilateur est rarement un outil crade... décider de compiler un langage qui était jusqu'alors interprété me semble même une amélioration pertinente.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Hackcell Hors ligne Maître du Puzzle Points: 1531 Défis: 11 Message

Citer : Posté le 02/07/2016 22:46 | #


Je pense plus que lephé a raison, mais reste que certaine astuce du basic vont être galère à géré( omission des symboles : ) ] et } ) ou encore le drawstat et les exploitation de bugs
Et puis reste à pouvoir lire les fichier g*m qui ne sont pas codé en ASCII
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 02/07/2016 22:48 | #


Pour les fichiers g1m on a la table de correspondance. Après pour les astuces du Basic, il « suffit » de coder l'analyseur syntaxique pile comme l'interpréteur. Ça nécessite un peu de réflexion mais honnêtement c'est pas du tout infaisable.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 03/07/2016 20:14 | #


J'ai fini mon prototype, pour l'instant il ne fonctionne que sur les Locate (et en théorie sur les If, While, For et d'autres trucs mais j'ai pas testé). Il convertit avec succès Locate X,Y,"Test" en locate(X,Y); Print((unsigned char*)"Test");. Ca semble ne pas être beaucoup mais j'ai aussi mis les bases pour les autres fonctions.

Si je vous dit ça c'est pour que vous voyiez un peu mon code, selon vous : quelles fonctions doivent être enlevées, lesquelles doivent être refactorisées, etc, bref la structure du code. http://git.planet-casio.com/Zezombye/B2C/blob/master/B2C.java

Ca paraît être moins difficile que prévu (surtout qu'avec le C je n'ai pas vraiment besoin de gérer les parenthèses, l'ordre des opérations, etc parce que le C s'en occupe déjà) donc je prévois une beta dans 1 semaine.

Ah et aussi, ce qui pourrait vraiment m'aider c'est des exemples de code valide mais bizarre (qu'on peut trouver dans les jeux). Par exemple Locate 1,Mat M[A, B], "Test" est valide mais mon parseur bloquera dessus (parce qu'il y a 3 virgules, et il assume qu'il y en a 2).
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Eltoredo Hors ligne Modérateur Points: 4301 Défis: 35 Message

Citer : Posté le 03/07/2016 20:18 | #


J'ai une petite remarque. Nous savons tous ici que le Basic est de loin très inférieur en puissance au C, bien qu'il peut exister de magnifiques programmes tout de même dans ce langage, là n'est pas la question. Du coup, en codant en Basic, le programme sera de base pas très adapté à la puissance du C vu qu'une fois converti, il sera peut-être écrit en C mais il n'en sera pas moins aussi puissant qu'en Basic voire un peu plus avec les commandes du C. Du coup, peut-être qu'y ajouter des améliorations, un peu comme le propose le C-Engine, ne serait pas de trop pour booster les capacités du Basic
La procrastination est une vertu. (voir ma description pour comprendre mon raisonnement)
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 03/07/2016 20:29 | #


Tu penses à PGRM2 Elto, qui lui ajoute d'autres fonctions en basic

Mais une fois converti en C le programme sera beaucoup plus rapide qu'en basic, la lenteur du basic venant du fait que c'est interprété et non pas compilé. Ecrire le programme en basic n'influera pas beaucoup sur la vitesse (il influera mais c'est dû au fait que du code généré sera toujours plus lent que du code écrit à la main).

Par exemple le programme en basic
For 1->I To 10000
Locate 1, 1, I
Next

sera beaucoup plus lent que son équivalent en C.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 03/07/2016 21:24 | #


J'ai regardé un peu le code. Je n'y connais rien en Java mais ça se comprend bien.

Ton parser n'est pas assez puissant. Je n'ai pas tout lu mais d'après tes commentaires tu n'analyses pas récursivement les arguments des fonctions. Tu ne peux pas juste compter les virgules, il faut compter les parenthèses pour éliminer les appels de fonctions internes -- ou plutôt, pour les calculer en C puis utiliser les résultats. Ce n'est pas très compliqué à faire, il suffit, en passant d'une virgule à la suivante, de compter (grosso modo) le nombre de parenthèses ouvertes (il augmente de 1 quand tu croises '(' et il diminue de 1 quand tu croises ')') et d'ignorer les virgules tant que ce nombre n'est pas retombé à 0.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Dark storm Hors ligne Labélisateur Points: 11641 Défis: 176 Message

Citer : Posté le 03/07/2016 23:08 | #


Lephenixnoir a écrit :
Dark storm a écrit :
Il n'empèche que je le redit, faire un compilateur de Basic est très crade.

Je ne vois pas en quoi. Un compilateur est rarement un outil crade... décider de compiler un langage qui était jusqu'alors interprété me semble même une amélioration pertinente.

Compiler le Basic n'est pas crade en soit. Ce qui est dégueux, c'est de vouloir compiler des jeux déja existant. Et si j'ai bien compris, c'est tout l'intérêt du projet, non ?

Dans la liste des trucs pour lesquels je me demande comment tu va faire :
– Sauvegarde (listes et matrices, variables, etc.)
– Astuces d'optimisation
– [Super] DrawStat
– ViewWindows
– Vitesse d'exécution (propre, pas à coup de sleep…)

Ajouté le 03/07/2016 à 23:11 :
Je viens de jeter un œil au parser : en gros tu commence par convertir les opcode en texte. Je suis pas sûr que ce soit une excellente idée. Ça fait une étape de plus sur laquelle tu peux avoir des bugs assez rigolos à debugguer x)
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Zezombye Hors ligne Rédacteur Points: 1756 Défis: 13 Message

Citer : Posté le 03/07/2016 23:56 | #


Ha nan, je convertis pas du tout les opcodes en texte, je les convertis directement dans leur équivalent C oO
Pour les sauvegardes c'est vrai que je n'y ai pas pensé, je ferai peut être une sauvegarde des variable dans un fichier .sav à la fermeture du programme.
Les astuces d'optimisation ça dépend lesquelles
Le drawstat et multi drawstat sont des fonctions, il suffira de parser leur arguments et de les remplacer par une fonction customisée B2C_GraphXY.
Pareil pour les viewwindows mais faut que je me renseigne sur leur utilisation vu que je les utilise pas beaucoup.
La vitesse d'exécution je peux détecter les for vides et les remplacer par des sleep mais de toute façon la vitesse d'exécution du basic n'est pas fixée, je pense qu'un for 1->I to 100 tourne plus vite sur une graph 95 que sur une 35+. Après c'est sur que pour des jeux en temps réel (genre spacerun) la vitesse d'exécution ne peut pas être fidèle au basic (déjà qu'il faut convertir les bugs, si en plus faut convertir la lenteur on a pas fini)
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
Lephenixnoir Hors ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 04/07/2016 07:51 | #


Zezombye a écrit :
Pareil pour les viewwindows mais faut que je me renseigne sur leur utilisation vu que je les utilise pas beaucoup.

Si tu utilises fxlib et non ML pour le dessin, sache que c'est déjà implémenté (si mes souvenirs ne me trompent pas).

Dark storm a écrit :
Compiler le Basic n'est pas crade en soit. Ce qui est dégueux, c'est de vouloir compiler des jeux déja existant. Et si j'ai bien compris, c'est tout l'intérêt du projet, non ?

Je ne pense pas qu'il soit possible de compiler en brut les jeux existants. Il faudrait au moins les porter : remplacer les Getkey non-bloquants par des structure bloquantes, remplacer les For vides par des Sleep, spécifier des détails sur les variables, etc.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
1, 2, 3, 4, 5, 6 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 62 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd