Contexte
L'annotation @tailrec est actuellement reconnue et stockée par le compilateur (commit 0e0bb42) mais ne valide pas encore que la fonction est effectivement récursive terminale.
Comportement attendu
// @strict
@tailrec
function sum(n, acc) {
if (n == 0) return acc;
return sum(n - 1, acc + n); // ✓ tail call
}
@tailrec
function bad(n) {
if (n == 0) return 0;
return bad(n - 1) + 1; // ✗ erreur: appel récursif non terminal
}
bad() doit produire une erreur de compilation ANNOTATION_TAILREC_NOT_TAIL.
Implémentation
Fichiers à modifier
Error.java : ajouter ANNOTATION_TAILREC_NOT_TAIL (code 159)
FunctionBlock.java : dans analyze(), après super.analyze(), si hasAnnotation(TAILREC) → déclencher la vérification
LeekReturnInstruction.java : ajouter getExpression() getter
src/lang/fr|en|it/leekscript.json : traduction de l'erreur 159
Algorithme
Après l'analyse du corps de la fonction, traverser récursivement les instructions :
Pour chaque instruction I dans le bloc :
Si I est un return :
Si son expression est directement LeekFunctionCall(this) → tail call ✓
Si son expression contient LeekFunctionCall(this) en position non-terminale → erreur ✗
Si I est un bloc (if/for/while) → récurser
Pour toute autre instruction : si elle contient LeekFunctionCall(this) → erreur ✗
Un appel foo(n-1) est en position terminale si et seulement si c'est l'expression directe du return (nature FUNCTION), pas imbriquée dans une LeekExpression (opérateur binaire/unaire).
Points clés
LeekFunctionCall.getResolvedFunction() permet d'identifier si l'appel cible la fonction courante
compiler.getCurrentFunction() dans FunctionBlock.analyze() = this
- Traversée des expressions via
LeekExpression.getExpression1/2(), LeekFunctionCall params
- Approche conservatrice : si on ne sait pas analyser une expression, la marquer comme non-tail
Références
- Commit d'implémentation des annotations :
0e0bb42
- Exploration faite en session — voir memory
project_annotations_tailrec.md
Contexte
L'annotation
@tailrecest actuellement reconnue et stockée par le compilateur (commit 0e0bb42) mais ne valide pas encore que la fonction est effectivement récursive terminale.Comportement attendu
bad()doit produire une erreur de compilationANNOTATION_TAILREC_NOT_TAIL.Implémentation
Fichiers à modifier
Error.java: ajouterANNOTATION_TAILREC_NOT_TAIL(code 159)FunctionBlock.java: dansanalyze(), aprèssuper.analyze(), sihasAnnotation(TAILREC)→ déclencher la vérificationLeekReturnInstruction.java: ajoutergetExpression()gettersrc/lang/fr|en|it/leekscript.json: traduction de l'erreur 159Algorithme
Après l'analyse du corps de la fonction, traverser récursivement les instructions :
Un appel
foo(n-1)est en position terminale si et seulement si c'est l'expression directe dureturn(natureFUNCTION), pas imbriquée dans uneLeekExpression(opérateur binaire/unaire).Points clés
LeekFunctionCall.getResolvedFunction()permet d'identifier si l'appel cible la fonction courantecompiler.getCurrentFunction()dansFunctionBlock.analyze()=thisLeekExpression.getExpression1/2(),LeekFunctionCallparamsRéférences
0e0bb42project_annotations_tailrec.md