tester si une fonction existe dans giac

Librairie C++ de calcul formel/ C++ symbolic computation library

Modérateur : xcasadmin

cdeval
Messages : 192
Inscription : mer. juin 03, 2009 4:28 pm

tester si une fonction existe dans giac

Message par cdeval » ven. juin 10, 2011 8:17 pm

Bonjour Bernard,

dans mon extension pour OOo-Writer, je me suis fabriqué une fonction qui teste si la fonction tapée dans le traitement de texte est une fonction giac pour éventuellement l'évaluer.
Ce que j'ai fait n'est pas très joli :
j'envoie à giac l'instruction "?ma_fonction" et je teste si le retour contient "no help"
Ca fonctionne bien mais je viens de me rendre compte que j'ai un soucis avec, par exemple, la fonction forme_canonique.
Dans mon extension OOo, cette fonction n'existe pas alors que j'utilise la version 0.8.6 de libgiac.
Or mon xcas sur le même ubuntu est aussi en version 0.8.6 et connaît forme_canonique. Bizarre...

Dans le fichier usr share giac aide_cas effectivement, pas de trace de forme_canonique
Où va chercher Xcas ?
Je m'y perds un peu...

Autrement, vois-tu un moyen plus élégant de tester si une fonction existe ou non dans Giac ?
A bientôt.

parisse
Messages : 5743
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: tester si une fonction existe dans giac

Message par parisse » sam. juin 11, 2011 8:30 am

Salut!

Toutes les fonctions de xcas ne sont pas forcément commentées dans l'aide, et en plus il faut tenir compte des traductions de commandes (dans le fichier keywords de $SHARE/doc/fr). Je pense qu'il serait plus judicieux de parser le nom de commande entre quotes et de voir si c'est un gen de type _FUNC, un truc du genre
gen g("'"+nom_de_commande+"'",contextptr);
if (g.type==_FUNC){ ... }
Sinon, tu peux aussi te baser (à la compilation) sur le fichier static_lexer.h.

cdeval
Messages : 192
Inscription : mer. juin 03, 2009 4:28 pm

Re: tester si une fonction existe dans giac

Message par cdeval » sam. juin 11, 2011 12:54 pm

salut,

effectivement, je n'avais pas pensé à utiliser la fonction type(). ça marche parfaitement : J'envoie à partir de OOo-basic l'instruction giac "type(ma_fonction)" et je récupère l'entier correspondant.
C'est parfait car ça marche aussi pour les fonctions définies par l'utilisateur, je vais pouvoir simplifier mon code.

En ce qui concerne les traductions, je comprends maintenant pourquoi ma librairie giac ne reconnaît pas "forme_canonique" dans OOo : je n'ai pas tenu compte du fichier keywords.
Pour les aides, j'appelle giac::readhelp en lui fournissant le fichier aide_cas.
Existe-t-il l'équivalent de giac::readhelp pour les traductions ?

merci et bon week end

parisse
Messages : 5743
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: tester si une fonction existe dans giac

Message par parisse » sam. juin 11, 2011 2:47 pm

La fonction set_language permet de changer de langue (1 pour le français). Tu peux regarder dans global.cc comment elle fonctionne, en particulier pour l'aide on peut ajouter des aides localisées pour les commandes (et il rajoute des synonymes aux noms de commande existant).

cdeval
Messages : 192
Inscription : mer. juin 03, 2009 4:28 pm

Re: tester si une fonction existe dans giac

Message par cdeval » sam. juin 11, 2011 7:16 pm

ok, j'ai trouvé le code qui m'intéresse. Mais il va falloir que je le modifie car le fichier keywords doit être situé dans mon extension, donc pas à l'endroit habituel pour giac.
J'avais déjà fait le boulot pour les aides, uniquement en fr pour l'instant il est vrai mais je saurais localiser facilement à partir de mon code en basic puisque je fournis le chemin de aide_cas en argument à ma fonction c++, ce qui me permet de le mettre ou je veux dans mon extension :

Code : Tout sélectionner

	// fonctionnement interne à OOoBasic : permet d'initialiser l'aide "?command"
	// dans la boite de dialogue CAS.
	if (!helpitems){
		OUString chemin;
		aValList[0] >>= chemin;		
		std::string helpfile=string(OUStringToOString(chemin,RTL_TEXTENCODING_UTF8));
		(*giac::vector_aide_ptr)=giac::readhelp(helpfile.c_str(),(int&) helpitems);
	}
il me reste à faire le même travail pour les synonymes.
Si je ne fais pas d'erreur, ça se situe dans le code ci-dessous, au paragraphe "add synonyms" :

Code : Tout sélectionner

  void add_language(int i){
    if (!equalposcomp(lexer_localization_vector,i)){
      lexer_localization_vector.push_back(i);
      update_lexer_localization(lexer_localization_vector,lexer_localization_map(),back_lexer_localization_map);
      if (vector_aide_ptr){
	// add locale command description
	int count;
	string filename=giac_aide_dir()+find_doc_prefix(i)+"aide_cas";
	readhelp(*vector_aide_ptr,filename.c_str(),count,true);
	// add synonyms
	multimap<string,localized_string>::iterator it,backend=back_lexer_localization_map.end(),itend;
	vector<aide>::iterator jt = vector_aide_ptr->begin(),jtend=vector_aide_ptr->end();
	for (;jt!=jtend;++jt){
	  it=back_lexer_localization_map.find(jt->cmd_name);
	  itend=back_lexer_localization_map.upper_bound(jt->cmd_name);
	  if (it!=backend){
	    for (;it!=itend;++it){
	      if (it->second.language==i)
		jt->synonymes.push_back(it->second);
	    }
	  }
	}
	int s = vector_aide_ptr->size();
	for (int j=0;j<s;++j){
	  aide a=(*vector_aide_ptr)[j];
	  it=back_lexer_localization_map.find(a.cmd_name);
	  itend=back_lexer_localization_map.upper_bound(a.cmd_name);
	  if (it!=backend){
	    for (;it!=itend;++it){
	      if (it->second.language==i){
		a.cmd_name=it->second.chaine;
		a.language=it->second.language;
		vector_aide_ptr->push_back(a);
	      }
	    }
	  }
	}
	cerr << "Added " << vector_aide_ptr->size()-s << " synonyms" << endl;
	sort(vector_aide_ptr->begin(),vector_aide_ptr->end(),alpha_order);
	update_completions();
      }
    }
  }
mais ça ne semble pas aussi simple que le readhelp. Il va falloir que je trie en espérant que ça se compile bien dans mon extension. Je vais tenter le coup dès que j'ai un peu de temps libre. J'y tiens parce que, pour le moment, je ne peux pas appeler de fonctions telles que "forme_canonique", "cercle", "droite"... dans le traitement de texte.
Je te tiens au courant. A+

cdeval
Messages : 192
Inscription : mer. juin 03, 2009 4:28 pm

Re: tester si une fonction existe dans giac

Message par cdeval » dim. juin 19, 2011 10:58 am

ça y est j'ai réussi à définir les synonymes dans mon extension :
screenshot_333.png
screenshot_333.png (23.92 Kio) Consulté 7429 fois
pour info, ça peut servir à d'autres :
j'ai ajouté un :

Code : Tout sélectionner

#include <giac/input_lexer.h>
puis repris le code de global.cc/void add_language
j'ai simplement court-circuité la fonction update_lexer_localization pour une autre que j'ai créée et insérée dans mon code afin de tenir compte du chemin d'accès au fichier keywords dans mon extension.
Je n'ai pas complètement fini la localisation du code, mais avant je voulais régler mon problème de la localisation des aides. Je l'ai depuis toujours, avant l'ajout des synonymes mais je ne m'en étais pas occupé. Tu peux voir sur la copie d'écran que les aides sont toujours en anglais. Là je sèche.
Voilà mon code :

Code : Tout sélectionner

Sequence< Sequence< Any > > CASImpl::cas1(const Sequence< Any > &aValList)
	throw (RuntimeException)
{ 	
	// fonctionnement interne à OOoBasic : permet d'initialiser l'aide "?command"
	// dans la boite de dialogue CAS.
	if (!nbAides){
		OUString chemin;
		aValList[0] >>= chemin;
		OUString language;			
		aValList[1] >>= language;
		OUString cheminAides;
		OUString cheminSynonymes;
		cheminAides=chemin+OUString::createFromAscii("aide_cas");
		cheminSynonymes=chemin+language+OUString::createFromAscii("/keywords");
		std::string helpFile=string(OUStringToOString(cheminAides,RTL_TEXTENCODING_UTF8));
		std::string synonymsFile=string(OUStringToOString(cheminSynonymes,RTL_TEXTENCODING_UTF8));
		// ajoute les synonymes, code de giac/global.cc/add_language modifié ligne 2190
		// pour les lexer, reprise du code de giac/input_lexer.cc ligne 7848
     		lexer_localization_vector.push_back(1); // 1 pour fr, todo : tenir compte de "language"
		// fonction suivante modifiée pour tenir compte du chemin d'accès de keywords dans l'extension OOo
		cmath_update_lexer_localization(lexer_localization_vector,lexer_localization_map(),back_lexer_localization_map, synonymsFile);
		// ajoute les aides
		giac::readhelp(*vector_aide_ptr,helpFile.c_str(),(int&) nbAides,true);
		// (*giac::vector_aide_ptr)=giac::readhelp(helpFile.c_str(),(int&) nbAides);
		if (vector_aide_ptr){
			// add locale command description
			// int count;
			// string filename=giac_aide_dir()+find_doc_prefix(i)+"aide_cas";
			// readhelp(*vector_aide_ptr,filename.c_str(),count,true);
			// add synonyms
			multimap<string,localized_string>::iterator it,backend=back_lexer_localization_map.end(),itend;
			vector<aide>::iterator jt = vector_aide_ptr->begin(),jtend=vector_aide_ptr->end();
			for (;jt!=jtend;++jt){
			  it=back_lexer_localization_map.find(jt->cmd_name);
			  itend=back_lexer_localization_map.upper_bound(jt->cmd_name);
			  if (it!=backend){
			    for (;it!=itend;++it){
			      if (it->second.language==1)
				jt->synonymes.push_back(it->second);
			    }
			  }
			}
			sal_Int32 s = vector_aide_ptr->size();
			for (sal_Int32 j=0;j<s;++j){
			  aide a=(*vector_aide_ptr)[j];
			  it=back_lexer_localization_map.find(a.cmd_name);
			  itend=back_lexer_localization_map.upper_bound(a.cmd_name);
			  if (it!=backend){
			    for (;it!=itend;++it){
			      if (it->second.language==1){
				a.cmd_name=it->second.chaine;
				a.language=it->second.language;
				vector_aide_ptr->push_back(a);
			      }
			    }
			  }
			}
			nbSynonymes=vector_aide_ptr->size()-s;
			//	cerr << "Added " << vector_aide_ptr->size()-s << " synonyms" << endl;
			//	sort(vector_aide_ptr->begin(),vector_aide_ptr->end(),alpha_order);
			//	update_completions();
		}
	}
	OUString sNbAides;
	OUString sNbSynonymes;
	sNbAides=OUString::valueOf(nbAides);
	sNbSynonymes=OUString::valueOf(nbSynonymes);
	Sequence< Any >	solList1D(2);
	Sequence< Sequence< Any > > solList2D(1);
	solList1D[0]=makeAny(sNbAides);
	solList1D[1]=makeAny(sNbSynonymes);
	solList2D[0]=solList1D;
	return solList2D;
}
A+

parisse
Messages : 5743
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: tester si une fonction existe dans giac

Message par parisse » dim. juin 19, 2011 12:17 pm

Pour l'affichage de l'aide, tu peux appeler writehelp(helpon(...)), ou regarder comment fonctionne _findhelp dans prog.cc (voire directement appeler _findhelp(string2gen("nom_de_commande",false)),contextptr)),

cdeval
Messages : 192
Inscription : mer. juin 03, 2009 4:28 pm

Re: tester si une fonction existe dans giac

Message par cdeval » lun. juin 20, 2011 9:54 am

c'est bon, j'avais juste oublié de définir la variable globale "language" avec :

Code : Tout sélectionner

giac::language(1,contextptr);
il ne me restait plus que le problème de l'encodage :
screenshot_335.png
screenshot_335.png (16.5 Kio) Consulté 7425 fois
je me suis rendu compte que je ne convertissais pas en utf8 les sorties de giac qui venait de e.print(contextptr).c_str(). Une fonction fournie par OOo fait ça très bien. Maintenant c'est bon, l'aide est correcte dans OOo.
merci encore.

Répondre