Ben si je fait un jar + tuto, le tuto parlerai de comment écrire la syntaxe et les visiteur d'un langage en utilisant mon parseur (JASI pour les intimes).
Découvrez Algoid le langage pour apprendre à programmer.
Enfin ! J'ai mis la coloration syntaxique !
Bon, ça ne concerne que les commentaires et les chaines. Pour l'instant. Mais je pensais ne pas y arriver...
D'ailleurs, merci à toi, metalm : Les sources de Linotte m'ont été utiles.
Sinon, j'ai ajouté les mots-clés vrai et faux, des méthodes dans les types Entier et Flottant, et une petite fenêtre A propos. Version 0.1.0 ici
- Edité par antoine1023 13 juin 2013 à 17:20:47
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
Je pense que les langages modernes peuvent se passer de ce détail, sauf pour raison de performance (hmmm, en java ...) ou sinon, pour des raisons purement mathématiques.
C'est une question de choix fait à la conception du langage. Certains langages tronqueront, d'autres provoqueront une erreur, et certains autres langages sont typés (statiquement) et la situation est simplement impossible (le code ne peut jamais atteindre cet état-piège).
De nouveau. Pourquoi encombrer les débutants avec ce genre de considération ????
Utilise des listes dynamiques.
Exemple en AL :
set a = array {1, 2, 3, 4};
a.add(5);
metalm : concernant les performances :
Il faut savoir que ce qu'il coûte de toutes façon extrèmenent cher, lorsque l'on interprête un langage, c'est le fait de traversé l'AST (donc une structure arborescente) et de changer de contexte (porté du langage hote) à chaque fois. Surtout de façon imbriqué (parcours en profondeur).
En java et selon mes propres résultats obtenus avec des benchmarks réalisés sur mon langage, c'est au allentours de 100 fois plus lents.
C'est ennorme, mais c'est le prix de l'interprétation. Python ne fait guerre mieux, il est pourtant écrit en c++.
Donc l'utilisation de float à la place des int (comme indice de boucle par exemple), ça à une incidence quand on programme un moteur 3d, car c'est 3x plus lent. Dans notre cas, c'est 3x / 100x.... soit 0.03x plus lent.... autent dire un rapport négligeable.
Maintenant les solutions qui existent pour palier à cela :
- Developper un analyseur semantique qui va intelligement limiter le parcour en profondeur de l'AST, car il va supprimer des noeuds innutiles.
- Générer du byte-code à la volés (ce que fait Rhino, mais sans grand succès). Et bien oui, une macine virtuelle execute séquentiellement les instruction, plus de saut de scope imbriqués.... c'est très malin....
- Compiler en asm.... on retombe sur un langage compilé.
- Faire du fromage de chèvre dans les alpages, c'est bien ça évite ce genre de questions....
- Edité par CyaNn 14 juin 2013 à 13:16:19
Découvrez Algoid le langage pour apprendre à programmer.
Ha, et je viens de jeter un oeil à ton architecture.... tu n'utilise pas de visiteur ? Du coup le code de ton interpréteur est un peu partout dans ton code.... pas très simple à maintenir.
Découvrez Algoid le langage pour apprendre à programmer.
Alors, en fait, en plus des paramètres, les différences entre un bloc de parenthèses et une définition de fonction (un bloc d'accolades) sont :
Le code dans une fonction n'est pas évalué dès l'évaluation de sa définition, il faut mettre les paramètres entre deux parenthèses après elle (une variable la référençant ou une définition) ;
Sauf s'il s'agit de paramètres d'un appel de fonction, le code dans un bloc de parenthèses est évalué immédiatement.
Ces trois exemples sont équivalents, ils retournent tous 5,2 :
{5,2}() // On crée une fonction que l'on appelle immédiatement,
// équivalent fonction anonyme en JavaScript.
(5,2) // Le bloc est évalué et retourne 5,2
a = {5,2}
a() // Même chose qu'au début, mais la fonction a un nom.
Voilà pour les différences autres que les paramètres. En fait, ce qui faut bien comprendre, c'est que les accolades sont l'équivalent des crochets de SmallTalk. Ca fonctionne pareil en fait. CyaNn a écrit:
De plus, pourquoi définir quelque chose d'aussi éloigné de tous les autres langages ?
C'est pas de ma faute si SmallTalk est particulier :-)
Bien sûr, c'est très différent des définitions de fonctions du C, du VisualBasic, de Java ou de plein d'autres langages. Mais c'est assez proche du Javascript en fait. Donc je ne trouve pas ça très spécial, ni compliqué.
Quand aux histoires entre les entiers et les flottants, je pense que je vais rajouter un type Nombre, avec une précision exacte (un BigDecimal en fait). Ca serait plus simple pour les débutants : le nom serait plus explicite, pas à comprendre les différences entre Entier et Flottant...
Parce que comme le type Entier est représenté avec une variable Java long, donc sur 64 bits, et que 2^64 = 1.8446744e+19 ; c'est beaucoup trop petit pour faire tenir dedans rien que la factorielle de 25, soit : 1,551 121 004 333 098 598 4e+25 :-p
EDIT: Au fait, j'ai ajouté le mot clé var. Maintenant, toutes les variables (sauf les paramètres de fonction) doivent être déclarées avec lui. J'ajouterai aussi un retour pour quitter les fonctions parce que là c'est pas terrible...
- Edité par antoine1023 14 juin 2013 à 14:08:20
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
Ha, et je viens de jeter un oeil à ton architecture.... tu n'utilise pas de visiteur ?
Du coup le code de ton interpréteur est un peu partout dans ton code.... pas très simple à maintenir.
Non, pas de visiteur. Je connais pas bien le pattern... Mais je verrais CyaNn a écrit:
EDIT: J'ai essayé, il a bien signalé l'erreur. J'ai du déjà corriger le problème...
AUTRE EDIT: Faudra vraiment que je regarde les visiteurs, je sais pas si ça limite les appels de fonctions, parce que quand j'essaye d'appeler récursivement une fonction 10 000 fois j'ai une stack overflow...
- Edité par antoine1023 14 juin 2013 à 14:48:44
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
De nouveau. Pourquoi encombrer les débutants avec ce genre de considération ????
Parce qu'un débutant aura forcément besoin d'utiliser et d'indicer un tableau !!!!
Il faut savoir que ce qu'il coûte de toutes façon extrèmenent cher, lorsque l'on interprête un langage, c'est le fait de traversé l'AST (donc une structure arborescente) et de changer de contexte (porté du langage hote) à chaque fois. Surtout de façon imbriqué (parcours en profondeur).
Personne ne fait ça en 2013. Python (par exemple) est compilé en bytecode. Ce qui coûte cher à exécuter, c'est davantage son modèle objet dynamique qu'autre chose AMHA.
Donc l'utilisation de float à la place des int (comme indice de boucle par exemple), ça à une incidence quand on programme un moteur 3d, car c'est 3x plus lent. Dans notre cas, c'est 3x / 100x.... soit 0.03x plus lent.... autent dire un rapport négligeable.
La différence entre entiers et flottants n'est pas seulement une affaire de coûte à l'exécution, c'est une question de sémantique.
- Compiler en asm.... on retombe sur un langage compilé.
Il n'y a pas de différence conceptuelle entre langage interprété et compilé. Il n'y a que des implémentations différentes.
En fait une fonction, ce sont deux scopes imbriqués.
Il est très vraisemblable que toute définition "minimaliste" de la portée (scope) confonde les deux. D'ailleurs je ne vois pas ce qu'on gagne à les distinguer.
antoine1023> Il n'est pas idiot d'utiliser un type entier de taille arbitraire par défaut. C'est ce que font Erlang, Python ou Haskell, par exemple (ce dernier permettant de se rabattre facilement, si nécessaire, vers un type entier natif). De même pour les décimaux.
Mais flottants et entiers sont vraiment différents, pas seulement parce qu'ils sont implémentés différemment, mais surtout parce qu'ils ne s'utilisent pas de la même façon. Tu peux remplacer des flottants par des décimaux, mais tu ne peux pas tout le temps les confondre avec des entiers, ça n'a pas de sens (à cause des indices de tableaux par exemple).
De nouveau. Pourquoi encombrer les débutants avec ce genre de considération ????
Parce qu'un débutant aura forcément besoin d'utiliser et d'indicer un tableau !!!!
Mouep.... c'est un partis pris. En AL j'ignore ce genre de truc étrange. J'écrirai par la suite un analyseur qui permettra de placer des warning dans l'IDE. C'est une approche plus "soft" de la detection d'erreur. Un langage très permissif et des analyseurs gardes fous.
poiujlkljio a écrit:
CyaNn a écrit:
Il faut savoir que ce qu'il coûte de toutes façon extrèmenent cher, lorsque l'on interprête un langage, c'est le fait de traversé l'AST (donc une structure arborescente) et de changer de contexte (porté du langage hote) à chaque fois. Surtout de façon imbriqué (parcours en profondeur).
Personne ne fait ça en 2013. Python (par exemple) est compilé en bytecode. Ce qui coûte cher à exécuter, c'est davantage son modèle objet dynamique qu'autre chose AMHA.
Ca effectivement je l'ignorai. Dans nos cas (de langages amateurs) une VM est un coût de developpement non négligeable. D'autant que la portabilité est déjà résolu grâce à la JVM.... On passe donc pas une VM mais indirectement. Cela dit en 2013 des tas de langages n'utilisent pas de VM. Mais il sont moins connus.
poiujlkljio a écrit:
CyaNn a écrit:
En fait une fonction, ce sont deux scopes imbriqués.
Il est très vraisemblable que toute définition "minimaliste" de la portée (scope) confonde les deux. D'ailleurs je ne vois pas ce qu'on gagne à les distinguer.
Terrence Parr répond à cette question dans son livre sur les patterns de compilos. C'est justement ce que j'expliquait : Faire une chaine de responsabilité au travers l'empilement des scopes. Dans le cas d'un scope de type parameter : ignorer l'assignation.... Mais ça peu très bien être codé salement avec de joli if/then/else.... d'ailleurs tout peu l'être !!!! C'est coté maintenance que ça coincera.
- Edité par CyaNn 15 juin 2013 à 8:14:16
Découvrez Algoid le langage pour apprendre à programmer.
Mouep.... c'est un partis pris. En AL j'ignore ce genre de truc étrange. J'écrirai par la suite un analyseur qui permettra de placer des warning dans l'IDE. C'est une approche plus "soft" de la detection d'erreur. Un langage très permissif et des analyseurs gardes fous.
C'est le parti pris de Dart (et, dans une moindre mesure, d'Objective-C). Ça n'est pas tout à fait une mauvaise idée, parce que plus les langages deviennent compliqués, plus leur système de types l'est (notamment dès qu'on a de la généricité et du sous-typage, il y a des choix à faire). Il faut être conscient que ça reste une approche limitée.
Cela dit en 2013 des tas de langages n'utilisent pas de VM.
Je suis surpris et je veux bien des noms, s'il te plaît.
Terrence Parr répond à cette question dans son livre sur les patterns de compilos.
Je suppose qu'il faudrait que j'y jette un œil alors.
Cela dit, j'ai trouvé dans un autre doc, que les AST permettaient une plus simple approche du debugger. Ca tombe bien !!!! c'était le priorité dans mon langage... et avec des perfs très acceptables sur android et PC ;-)
- MsDOS fait toujours de l'interpretation directe de la syntaxe (sans AST)
MS-DOS ? L'OS de Microsoft ? CyaNn a écrit:
- LISP, scheme, prolog
Euh pour Prolog, là je pense que tu va chercher un peu loin quand même :-)
Bref, je pense qu'il est temps de clore cette discussion, aussi passionnante soit-elle. Revenons à nos moutons :-)
Donc, pour l'instant, je met la priorité sur :
L'ajout de mots-clés et d'instructions au langage (null, return, for each, ...)
L'ajout de fonctions aux types
L’amélioration de l'éditeur
L'amélioration de la gestion des erreurs
La documentation
On verra pour les performances plus tard...
Je vous informe que ça y est, l'interpréteur tourne sous le JRE 6. En fait, j'était passé sous le JRE 7 parce que je n'avait pas bien compris comment configurer ça sur Eclipse... bref.
EDIT: J'ai oublié une autre grosse priorité... L'amélioration de la console. Avec le multithreading et tout, c'est pas si évident.
- Edité par antoine1023 15 juin 2013 à 17:00:11
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
EDIT: J'ai posté trop vite !
Avec l'ajout de l'instruction retour, le script de calcul de factorielle livré dans le JAR ne marche pas. Utilisez celui-ci à la place :
/* Factorielle
Exemple de fonction récursive pour smallFrench.
*/
var a = 5
var factorielle = { x :
si (x infegal 1) (
retour(1)
) sinon (
retour(x * factorielle(x - 1))
)
}
Console.ecrireLigne("Factorielle de " + a + " : " +
factorielle(a))
- Edité par antoine1023 18 juin 2013 à 18:00:21
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
{x :
retour ({y : Console.ecrireLigne ("x = " + x + " and y = " + y) })
} (10)(20)
Il me dit ça Ce n'est pas un(e) Fonction, mais un(e) : class smallfrench.lang.parser.noeuds.NAppel)
Ca non plus :
var f = {x :
retour ({y : Console.ecrireLigne ("x = " + x + " and y = " + y) })
}
var g = f (10)
g (20)
Il me dit Variable indéfinie : x
Il y a un problème avec le scope des tes fonctions
Ca ça marche et c'est joli :
var deco = {f :
retour ({
Console.ecrireLigne ("before")
f ()
Console.ecrireLigne ("after")
})
}
var f = {
Console.ecrireLigne ("during")
}
var g = deco (f)
g()
J't'embauche... quels sont tes disponibilités.... ???? lol.
Découvrez Algoid le langage pour apprendre à programmer.
Mes disponibilités ? En ce moment pas trop : épreuves anticipées du bac de français et d'histoire géo... :-)
Les décorateurs, je n'en ai jamais utilisé. Mais oui, c'est bien que ça marche :-) Et merci pour les deux problèmes, je regarde tout de suite. Ca doit pas être trop grave...
EDIT :
Pour le 2nd problème, c'est bien une histoire de portée. Je crois qu'il va falloir que je reprenne tout ça :-(
EDIT 2 :
Je sais pas si tu l'a remarqué, mais ton troisième exemple marche à moitié en fait, à cause de ces histoires de portée. En fait, il fonctionne comme ça :
var deco = {
retour ({
Console.ecrireLigne("avant")
f ()
Console.ecrireLigne("après")
})
}
var f = {
Console.ecrireLigne("pendant")
}
var g = deco()
g()
</pre>
... amusant, non ? :-)
La portée est dynamique. Et d'après ce que j'ai compris, ça empêche les closures. Non ?
- Edité par antoine1023 19 juin 2013 à 20:33:38
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
OK donc tu confirme bien ce que je pensais : il faut que je m'occupe en priorité de cette portée, parce que là c'est pas terrible...
J'ai lu 3-4 trucs là dessus hier, et je commence à en avoir marre :-)
Donc d'après ce que j'ai compris, pour une portée statique, je dois mettre une sauvegarde de tout le scope dans chaque définition de fonction, pour pouvoir les retrouver pendant l'appel ?
Arius, vraiment le plus puissant de l'ancienne Ligue des Super Zéros !
Très bon travail mais je me pose une question ne faut-il pas initier à la programmation avec de l'anglais. Je trouve ça plus sensé à vrai dire. Parce que l'utilisateur qui a tout appris ne comprendra pas forcement bien le Java quand il voudra apprendre. Après c'est comme même minime.
Donc d'après ce que j'ai compris, pour une portée statique, je dois mettre une sauvegarde de tout le scope dans chaque définition de fonction, pour pouvoir les retrouver pendant l'appel ?
Oui tout à fait.
Sur Algoid, j'ai fait comme suit :
J'ai définit une classe abstraite scope et une classe concrète functionScope.
Dans ton cas, scope sera constitué d'une map<String, RObject> et de méthodes pour acceder / définir des variables.
j'ai mis : define, resolve, delete et clear
Ensuite tu doit savoir, à partir d'une portée, quel est la porté parent. Chaque doit que tu en crée une, tu référence la portée courance comme parente de la nouvelle. J'ai mis ça dans le constructor.
RootScope extends Scope : constructeur sans paramètre
FunctionScope extends Scope : constructeur avec Scope : parent (et attribut final Scope parent)
Tes objets RObject doivent contenir une référence au FunctionScope.... c'est ce qui fait ta closure.
héhé.... bienvenu dans le monde de la programmation de langage. Après on verra pour optimiser..... Qui consiste en gros à peter tout ce que tu avait faire de propre auparavant.
Découvrez Algoid le langage pour apprendre à programmer.
Très bon travail mais je me pose une question ne faut-il pas initier à la programmation avec de l'anglais. Je trouve ça plus sensé à vrai dire. Parce que l'utilisateur qui a tout appris ne comprendra pas forcement bien le Java quand il voudra apprendre. Après c'est comme même minime.
Je me suis fait la même reflexion, c'est pour cette raison qu'AL est en anglais.
Je pense que la difficulté qu'ont les enfant réside plus dans les idiomes que dans la syntaxe.
Mais mon fils à l'aire de me dire le contraire.... je vous redirait quant on en aura parlé.
Découvrez Algoid le langage pour apprendre à programmer.
Merci !
Ca y est, je crois que j'ai réussi : Maintenant, portée statique !
Bon je vais quand même faire 2-3 tests pour voir si ça marche bien
EDIT:
Je confirme, c'est OK pour les closures !
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.