2010-09-15 19 views
2

J'écris un langage en utilisant les arbres Antlr et Expression.Découverte d'op_Addition OU implémentation du procédé pour Expression.Add

J'ai défini une méthode d'usine standard pour utiliser mon Tree Parser lors de la génération de l'addition, et cela fonctionne très bien pour les types intégrés intégrés, maintenant je passe à des types plus généraux.

Au moment où il est incroyablement naïf, il ne suffit ceci (en cours code TDD semble souvent bien naïve !?):

protected Expression GenerateAdd(Expression left, Expression right) 
{ 
    if (left.Type.Equals(right.Type)) 
    return Expression.Add(left, right); 
    if (left.Type.IsValueType && right.Type.IsValueType) 
    Promote7_2_6_2(ref left, ref right); 
    return Expression.Add(left, right); 
} 

Promote7_2_6_2 génère Convertir des expressions qui suivent les règles de promotion intégrale comme prévu out par la spécification C# 7.2.6.2 (La langue sera similaire à C#, mais elle se recoupera avec JScript et aura d'autres mots-clés flambant neufs).

Naturellement, je suis passé à plus de chaîne de tests - à savoir "a" + "b"; et je reçois l'erreur:

System.InvalidOperationException: The binary operator Add is not defined for the types 'System.String' and 'System.String'.

assez juste - je pense System.String et bien sûr que l'opérateur est en effet pas défini. Génération d'un arbre d'expression dans une méthode d'essai comme celui-ci:

Expression<Func<string, string, string>> e = (s1, s2) => s1 + s2; 

montre qu'un BinaryExpression Ajouter est en effet créé, mais avec la méthode d'exécution prévue à l'une des méthodes string.Concat. Je savais que j'allais devoir faire quelque chose comme ça dans certains cas, mais combien d'autres types définissent l'addition de cette façon? Est-ce seulement string?

Est-ce une règle intégrée au compilateur C# - ou existe-t-il des métadonnées que je peux utiliser pour découvrir ces méthodes sur d'autres types?

Merci d'avance!

Répondre

1

Il me semble que je fais une grande ligne en répondant à mes propres questions! Mes excuses, cette réponse pourrait être mieux formatée, mais je suis sur mon désir HTC et son clavier ne supporte pas tous les symboles!

Il semble qu'il n'y ait aucun moyen de «découvrir» ces règles lors de l'exécution, il est de la responsabilité du langage hôte de décider comment implémenter des éléments tels que l'ajout de chaîne. C# s'adapte au nombre de termes consécutifs dans un ajout, en appelant la méthode .Concat qui correspond le mieux à cela. Donc, si je souhaite que ma langue supporte l'ajout d'instances de classe où un opérateur n'est pas défini, par exemple, je peux simplement écrire ou trouver une méthode statique pour le faire (de la bonne signature bien sûr!) et ensuite câbler la langue pour l'utiliser dans ce cas. Un exemple classique ici est de savoir si soutenir array1 + array2 à travers les méthodes de tableau statique. Pour ce qui est de la découverte des opérateurs, la méthode Expression.Add s'en occupe, mais elle n'effectue pas automatiquement de conversions. Ainsi, comme dans le cas de la méthode de promotion intégrale/à virgule flottante que j'ai mentionnée dans la question, jusqu'aux règles du langage pour déterminer si d'autres conversions sont nécessaires avant de tenter de générer l'expression.En tant que tel, il est probablement préférable de réfléchir d'abord l'opérateur, pour voir si l'on est défini pour les deux types, avant d'envisager une conversion s'il en existe une.