Parcourir la source

Initial commit

Jean Fromentin il y a 8 ans
Parent
commit
fa7b341018
18 fichiers modifiés avec 4348 ajouts et 0 suppressions
  1. 22 0
      Makefile
  2. 325 0
      array.hpp
  3. 223 0
      dictionnary.hpp
  4. 14 0
      ext/base/Makefile
  5. 5 0
      ext/base/array.cpp
  6. 3 0
      ext/base/array.hpp
  7. 72 0
      ext/base/init.cpp
  8. 29 0
      ext/base/module.cpp
  9. 7 0
      ext/base/module.hpp
  10. 6 0
      ext/base/string.cpp
  11. 3 0
      ext/base/string.hpp
  12. 1500 0
      interpreter.cpp
  13. 694 0
      interpreter.hpp
  14. 387 0
      kernel.cpp
  15. 318 0
      kernel.hpp
  16. 79 0
      main.cpp
  17. 217 0
      module.cpp
  18. 444 0
      module.hpp

+ 22 - 0
Makefile

@@ -0,0 +1,22 @@
+CPP 	= g++ -fmax-errors=10
+INCDIR  =  -I/usr/local/opt/readline/include -I/usr/local/include/
+LIBDIR  =  -L/usr/local/opt/readline/lib -L/usr/local/lib/
+CPPFLAG = -g --std=c++11 -O3 $(INCDIR)
+LDFLAG	= -rdynamic -lgmpxx -lgmp -lflint -lreadline -ldl $(LIBDIR)
+EXE 	= gomu
+
+
+all: $(EXE)
+
+doc: array.hpp dictionnary.hpp interpreter.hpp kernel.hpp module.hpp
+	doxygen doc/Doxyfile
+
+%.o:%.cpp %.hpp
+	$(CPP) $(CPPFLAG) -o $@ -c $<
+
+$(EXE) : module.o kernel.o interpreter.o  main.cpp
+	$(CPP) $(CPPFLAG) $(LDFLAG) $^ -o $(EXE)
+
+clean:
+	-$(RM) *.o
+	-$(RM) $(EXE)

+ 325 - 0
array.hpp

@@ -0,0 +1,325 @@
+#ifndef Braids_array
+#define Braids_array
+
+#include <iostream>
+#include <list>
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#include <set>
+#include <stack>
+#include <initializer_list>
+#include <string.h>
+#include <cassert>
+
+using namespace std;
+
+//! Class for array
+template <class T>
+class Array{
+ protected:
+
+  //! Size of the array
+  size_t s;
+  //! Internal data of the array
+  T* array;
+  //! Construct an array from a c++ array a of size s and own it
+  Array(T* a,size_t s);
+
+public:
+
+  //! Contruct an array of size s
+  //! \param s size of the array
+  Array(size_t s=0);
+  
+  //! Construct an array from an initialization list
+   Array(const initializer_list<T>& list);
+    
+  //! The copy contructor
+  Array(const Array<T>&);
+    
+  //! The move constructor
+  Array(Array<T>&&);
+    
+  //! Construct an array from a stack
+  Array(stack<T>& stack);
+
+  //! Construct an array from a list 
+  Array(const list<T>& list);
+    
+  //! Construct an array from a set 
+  Array(const set<T>& set);
+    
+  //! Destructor
+  ~Array();
+    
+  //! Assignemnet operator with copy
+  //! \param array Array to copy
+  Array& operator=(const Array& array);
+
+  
+  //! Assignement operator with move
+  //! \param array Array to move
+  Array& operator=(Array&& array);
+
+  
+  //! Test is the array is empty
+  //! \return true if empty flase otherwise 
+  bool is_empty() const;
+    
+  //! Return the size of the array$
+    size_t size() const;
+    
+  //! Return a pointer to the begin of the array
+  const T* begin() const;
+    
+  //!* Return a pointer a pointer just after the end of the array
+  const T* end() const;
+    
+  //! Write the a value at a given index
+  //! \param i index where write
+  //! \param v value to write
+  void write(size_t i,const T& v);
+	
+  //! Return the value at a given index
+  //! \param i index where read
+  //! \param return a reference to the value at index i
+  T& read(size_t i) const;
+  
+  //! Return the value at a given index
+  //! \param i index where read
+  //! \param return a reference to the value at index i
+  const T& at(size_t i) const;
+
+  //! Return the value at a given index
+  //! \param i index where read
+  //! \param return a reference to the value at index i
+  const T& operator[](size_t i) const;
+    
+  //! Provide access to the the value at index i
+  //! \param i index where look
+  //! \param return a reference to the value at index i
+  T& at(size_t i);
+
+  //! Provide access to the the value at index i
+  //! \param i index where look
+  //! \param return a reference to the value at index i
+  T& operator[](size_t i);
+
+  
+  //! Comparison function
+  bool operator<(const Array& array) const;
+   
+  //! Display function
+  template<class U> friend std::ostream& operator<<(std::ostream& os,const Array<U>&);
+
+};
+
+//*************************
+//* Function declarations *
+//*************************
+
+template<class T> inline
+Array<T>::Array(size_t _s):s(_s),array(new T[_s]){}
+
+template<class T> inline
+Array<T>::Array(T* a,size_t _s):s(_s),array(a){}
+
+template<class T> 
+Array<T>::Array(const initializer_list<T> &list):s((int)list.size()),array(new T[s]){
+  T* ptr=array;
+  for(auto it=list.begin();it!=list.end();++it){
+    *ptr=*it;
+    ++ptr;
+  }
+}
+
+template<class T> inline
+Array<T>::Array(const Array<T>& a):s(a.s),array(new T[s]){
+  memcpy(array,a.array,s*sizeof(T));
+}
+
+template<class T> inline
+Array<T>::Array(Array<T>&& a):s(a.s),array(a.array){
+  a.s=0;
+  a.array=nullptr;
+}
+
+template<class T> 
+Array<T>::Array(const list<T>& l):s((int)l.size()),array(new T[s]){
+  T* ptr=array;
+  for(typename list<T>::const_iterator it=l.begin();it!=l.end();++it){
+    *ptr=*it;
+    ++ptr;
+  }
+}
+
+template<class T> 
+Array<T>::Array(stack<T>& stack):s(stack.size()),array(new T[s]){
+  T* ptr=array;
+  while(not stack.empty()){
+    *ptr=stack.top();
+    stack.pop();
+    ++ptr;
+  }
+}
+
+template<class T> 
+Array<T>::Array(const set<T>& l):s(l.size()),array(new T[s]){
+  T* ptr=array;
+  for(typename set<T>::const_iterator it=l.begin();it!=l.end();++it){
+    *ptr=*it;
+    ++ptr;
+  }
+}
+
+template<class T> inline
+Array<T>::~Array(){
+  if(array!=nullptr) delete[] array;
+}
+
+template<class T> Array<T>&
+Array<T>::operator=(const Array<T>& a){
+  if(this!=&a){
+    if(s!=a.s){
+      if(array!=nullptr) delete[] array;
+      array=new T[a.s];
+    }
+    s=a.s;
+    memcpy(array,a.array,s*sizeof(T));
+  }
+  return *this;
+}
+
+template<class T>  Array<T>&
+Array<T>::operator=(Array<T>&& a){
+  if(this!=&a){
+    if(array!=nullptr) delete[] array;
+    s=a.s;
+    a.s=0;
+    array=a.array;
+    a.array=nullptr;
+  }
+  return *this;
+}
+
+template<class T> inline bool
+Array<T>::is_empty() const{
+  return s==0;
+}
+
+template<class T> inline size_t
+Array<T>::size() const{
+  return s;
+}
+
+template<class T> inline const T*
+Array<T>::begin() const{
+  return array;
+}
+
+template<class T> inline const T*
+Array<T>::end() const{
+  return array+s;
+}
+
+template<class T> inline void
+Array<T>::write(size_t i,const T& v){
+  assert(i<s);
+  array[i]=v;
+}
+
+template<class T> inline T&
+Array<T>::read(size_t i) const{
+  assert(i<s);
+  return array[i];
+}
+
+template<class T> inline const T&
+Array<T>::at(size_t i) const{
+  assert(i<s);
+  return array[i];
+}
+
+template<class T> inline T&
+Array<T>::at(size_t i){
+  assert(i<s);
+  return array[i];
+}
+
+template<class T> inline const T&
+Array<T>::operator[](size_t i) const{
+  assert(i<s);
+  return array[i];
+}
+
+template<class T> inline T&
+Array<T>::operator[](size_t i){
+  assert(i<s);
+  return array[i];
+}
+
+template<class T> bool
+Array<T>::operator<(const Array<T>& arr) const{
+  if(s==arr.s){
+    for(size_t i=0;i<s;++i){
+      if(array[i]!=arr.array[i]) return array[i]<arr.array[i];
+    }
+    return false;
+  }
+  return s<arr.s;
+}
+
+inline ostream& 
+operator<<(ostream& os,const Array<uint8_t>& a){
+  os<<'[';
+  if(not a.is_empty()){
+    const uint8_t* ptr=a.begin();
+    os<<(int)*ptr;
+    for(++ptr;ptr!=a.end();++ptr) os<<','<<(int)*ptr;
+  }
+  return os<<']'; 
+}
+
+inline ostream& 
+operator<<(ostream& os,const Array<int8_t>& a){
+  os<<'[';
+  if(not a.is_empty()){
+    const int8_t* ptr=a.begin();
+    os<<(int)*ptr;
+    for(++ptr;ptr!=a.end();++ptr) os<<','<<(int)*ptr;
+  }
+  return os<<']'; 
+}
+
+template<class T> ostream& 
+operator<<(ostream& os,const Array<T>& a){
+  os<<'[';
+  if(not a.is_empty()){
+    const T* ptr=a.begin();
+    os<<*ptr;
+    for(++ptr;ptr!=a.end();++ptr) os<<','<<*ptr;
+  }
+  return os<<']'; 
+}
+
+
+
+
+#endif

+ 223 - 0
dictionnary.hpp

@@ -0,0 +1,223 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#ifndef DICTIONNARY_HPP
+#define DICTIONNARY_HPP
+
+#include <iostream>
+#include <string>
+#include <deque>
+
+using namespace std;
+
+//**********************
+//* Class declarations *
+//**********************
+
+//! Class representing a dictionnary node
+template<class T> class DictionnaryNode{
+public:
+
+  //!Info attached to a DictionnaryNode
+  T* info;
+
+  //!Sons of the dictionnary node
+  deque<DictionnaryNode<T>*> sons;
+
+  //! Letter of the node
+  char letter;
+
+  //! The empty constructor
+  DictionnaryNode();
+
+  //! Destructor
+  ~DictionnaryNode();
+
+  //! Add a word to the dictionnary at this node
+  //! \param op the word to addd
+  //! \param info information attached to the word
+  void add(string op,T* info);
+
+  //! Display word obatained from this node preceded by a prefix
+  //! \param preffix the preffix of the node (ie the path from the root to the current node)
+  void disp(const string& preffix) const;
+};
+
+//! A class representing a dictionnary
+template<class T> class Dictionnary{
+private:
+  //! Root node
+  DictionnaryNode<T>* root;
+public:
+  //! Empty constructor
+  Dictionnary();
+
+  //! Destructor
+  ~Dictionnary();
+
+  //! Add a word to the distionnary
+  //! \param op the word to add
+  //! \param indo information attached to the word
+  //! \retrun Return true if the word has bee added, false otherwise
+  bool add(string op,T* info);
+
+  //! Display the dictionnary
+  void disp() const;
+
+  //! Find a maximal preffix of a suffix of a word in the dictionnary
+  //! \param pos position of the first letter of the suffix
+  //! \param str the full word
+  //! \return Information attached to a maximal preffix or nullptr otherwise
+  T* find_at(size_t& pos,const string& str);
+};
+
+//*************************
+//* Function declarations *
+//*************************
+
+//------------------------------------
+// DictionnaryNode::DictionnaryNode()
+//------------------------------------
+
+template<class T> inline
+DictionnaryNode<T>::DictionnaryNode(){
+  info=nullptr;
+}
+
+//------------------------------------
+// DictionnaryNode::~DictionnaryNode()
+//------------------------------------
+
+template<class T>
+DictionnaryNode<T>::~DictionnaryNode(){
+  if(info!=nullptr) delete info;
+  for(auto it=sons.begin();it!=sons.end();++it) delete *it;
+}
+
+//--------------------------------------
+// DictionnaryNode::disp(const string&)
+//--------------------------------------
+
+template<class T> void
+DictionnaryNode<T>::disp(const string& preffix) const{
+  string npreffix=preffix+letter;
+  if(info!=nullptr) cout<<npreffix<<" : "<<info->func<<endl;
+  for(auto it=sons.begin();it!=sons.end();++it) (*it)->disp(npreffix);
+}
+
+//----------------------------
+// Dictionnary::Dictionnary()
+//----------------------------
+
+template<class T> inline
+Dictionnary<T>::Dictionnary(){
+  root=new DictionnaryNode<T>();
+}
+
+//----------------------------
+// Dictionnary::~Dictionnary()
+//----------------------------
+
+template<class T> inline
+Dictionnary<T>::~Dictionnary(){
+  if(root!=nullptr) delete root;
+}
+
+//---------------------
+// Dictionnary::disp()
+//---------------------
+
+template<class T> inline void
+Dictionnary<T>::disp() const{
+  for(auto it=root->sons.begin();it!=root->sons.end();++it) (*it)->disp("");
+}
+
+//-----------------------------
+// Dictionnary::add(string,T*)
+//-----------------------------
+
+template<class T> bool
+Dictionnary<T>::add(string op,T* info){
+  DictionnaryNode<T>* cur=root;
+  size_t pos=0;
+  size_t end=op.length();
+  //Search maximal prefix
+  while(pos<end){
+    char l=op[pos];
+    auto it=cur->sons.begin();
+      for(;it!=cur->sons.end();++it){
+      if((*it)->letter==l) break;
+    }
+    if(it==cur->sons.end()) break;//the letter not occur
+    cur=*it;
+    ++pos;
+  }
+  //If the prefix is the whole word
+  if(pos==end){
+    if(cur->info!=nullptr){
+      cout<<"Warning : entry "<<op<<" already exists"<<endl;
+      return false;
+    }
+    else{
+      cur->info=info;
+    }
+  }
+  //Adding suffix to dictionnary
+  while(pos<end){
+    DictionnaryNode<T>* ncur=new DictionnaryNode<T>();
+    ncur->letter=op[pos];
+    cur->sons.push_back(ncur);
+    cur=ncur;
+    ++pos;
+  }
+  cur->info=info;
+  return true;
+}
+
+//---------------------------------------------
+// Dictionnary::find_at(size_t&,const string&)
+//---------------------------------------------
+
+template<class T> T*
+Dictionnary<T>::find_at(size_t& pos,const string& str){
+  size_t end=str.length();
+  size_t npos=pos;
+  string path="";
+  T* res=nullptr;
+  DictionnaryNode<T>* cur=root;
+  while(pos<end){
+    char l=str[npos];
+    auto it=cur->sons.begin();
+    for(;it!=cur->sons.end();++it){
+      if((*it)->letter==l) break;
+    }
+    if(it==cur->sons.end()) break;//the letter not occur
+    cur=*it;
+    path+=l;
+    if(cur->info!=nullptr){
+      res=cur->info;
+      pos=npos+1;
+    }
+    ++npos;
+  }
+  return res;
+}
+
+#endif
+

+ 14 - 0
ext/base/Makefile

@@ -0,0 +1,14 @@
+CPP 	= g++ -g --std=c++11 -march=corei7 -Wno-return-local-addr -fPIC -rdynamic -fmax-errors=1 -I/usr/local/include
+LDFLAGS = #-L/usr/local/lib -lgmpxx -lgmp -lflint
+MOD 	= ../base.so
+
+all: $(MOD)
+
+%.o:%.cpp %.hpp
+	$(CPP) -c $< -o $@
+
+$(MOD): init.cpp array.o string.o module.o
+	$(CPP) -shared  $(LDFLAGS) $^ -o $@
+
+clean:
+	-$(RM) $(MOD) *.o

+ 5 - 0
ext/base/array.cpp

@@ -0,0 +1,5 @@
+#include "array.hpp"
+
+void* array_len(void* v){
+  return Gomu::to_integer(((Gomu::ArrayValue*)v)->size);
+}

+ 3 - 0
ext/base/array.hpp

@@ -0,0 +1,3 @@
+#include "../../module.hpp"
+
+void* array_len(void*);

+ 72 - 0
ext/base/init.cpp

@@ -0,0 +1,72 @@
+#include "../../interpreter.hpp"
+#include "array.hpp"
+#include "string.hpp"
+#include "module.hpp"
+
+using namespace std;
+
+Value type(Context&,Value& v){
+  if(v.type==type_symbol) return Value(type_type,((Value*)v.ptr)->type); 
+  else return Value(type_type,v.type);
+}
+
+Value del(Context&,Value& v){
+  ((Value*)v.ptr)->del();  
+  ((Value*)v.ptr)->type=type_void;
+  return Value(type_void,nullptr);
+}
+
+
+
+ Value assignment(Context& context,Value& lhs,Value& rhs){
+    Value* rhse=rhs.eval();
+    if(lhs.ptr!=nullptr){
+      //Prevent auto assignement
+      if(((Value*)lhs.ptr)->ptr==rhse->ptr) return rhs;
+      Symbol* symbol=(Symbol*)lhs.ptr;
+      if(symbol->locked) ContextError("The symbol is locked");
+      ((Value*)lhs.ptr)->del();
+    }
+    if(rhs.type==type_symbol){
+      copyValue((Value*)lhs.ptr,rhse);
+    }
+    else{
+      ((Value*)lhs.ptr)->type=rhs.type;
+      ((Value*)lhs.ptr)->ptr=rhs.ptr;
+      rhs.type=type_void;
+      rhs.ptr=nullptr;
+    }
+    return lhs;
+  }
+
+extern "C"{
+  
+  Gomu::Type types[]={
+    TYPE_SENTINEL
+  };
+
+ 
+  //--- Functions ---//
+  Gomu::Module::Function functions[]={
+    {"Integer","len",{"String"},(void*)string_len},
+    //{"Integer","len",{"Array"},(void*)array_len},
+    FUNC_SENTINEL
+  };
+  
+  //--- Member functions ---//
+  Gomu::Module::Function member_functions[]={
+    {"Integer","len",{"String"},(void*)string_len},
+    {"Array","types",{"Module"},(void*)module_types},
+    FUNC_SENTINEL
+  };
+  
+  //--- Meta functions ---//
+  Gomu::Module::Function contextual_functions[]={
+    {"Type","type",{"Generic"},(void*)type},
+    {"Generic","operator=",{"Symbol","Generic"},(void*)assignment},
+    {"Void","delete",{"Symbol"},(void*)del},
+    {"Array","symbols",{"Type"},(void*)symbols},
+    FUNC_SENTINEL
+  };
+}
+

+ 29 - 0
ext/base/module.cpp

@@ -0,0 +1,29 @@
+#include "module.hpp"
+#include "../../interpreter.hpp"
+
+void* module_types(void* v){
+  Gomu::Module* module=(Gomu::Module*)v;
+  Gomu::ArrayValue *res=new Gomu::ArrayValue(module->ntype);
+  res->type=Gomu::type_string;
+  for(size_t i=0;i<module->ntype;++i){
+    res->tab[i]=new string(module->types[i]);
+  }
+  return res;
+}
+
+Value symbols(Context& context,Value& v){
+  Type* type=(Type*)v.ptr;
+  string str=type->name+'.';
+  deque<string> stack;
+  auto it=context.symbols.lower_bound(str);
+  while(it->first.substr(0,str.size())==str){
+    stack.push_back(it->first);
+    ++it;
+  }
+  ArrayValue* res=new ArrayValue(stack.size());
+  res->type=type_string;
+  for(size_t i=0;i<stack.size();++i){
+    res->tab[i]=new string(stack[i]);
+  }
+  return Value(type_array,res);
+}

+ 7 - 0
ext/base/module.hpp

@@ -0,0 +1,7 @@
+#include <deque>
+#include "../../module.hpp"
+
+using namespace Gomu;
+
+void* module_types(void*);
+Value symbols(Context& context,Value& v);

+ 6 - 0
ext/base/string.cpp

@@ -0,0 +1,6 @@
+#include "string.hpp"
+
+void* string_len(void* v){
+  return Gomu::to_integer(((string*)v)->size());
+}
+

+ 3 - 0
ext/base/string.hpp

@@ -0,0 +1,3 @@
+#include "../../module.hpp"
+
+void* string_len(void*);

+ 1500 - 0
interpreter.cpp

@@ -0,0 +1,1500 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#include "interpreter.hpp"
+
+namespace Gomu{
+
+  //************************************************************
+  //* Definition of fundamental types  declared in modules.hpp *
+  //************************************************************
+  
+  Type *type_array=new Type("Array",array_disp,array_del,array_copy,array_comp);
+  Type *type_boolean=new Type("Boolean",boolean_disp,boolean_del,boolean_copy,boolean_comp);
+  Type *type_context=new Type("Context",context_disp,context_del,context_copy,context_comp);
+  Type *type_generic=new Type("Generic",nullptr,nullptr,nullptr,nullptr);
+  Type *type_integer=new Type("Integer",integer_disp,integer_del,integer_copy,integer_comp);
+  Type *type_function=new Type("Function",function_disp,function_del,function_copy,function_comp);
+  Type *type_contextual_function=new Type("ContextualFunction",contextual_function_disp,contextual_function_del,contextual_function_copy,contextual_function_comp);
+  Type *type_meta_function=new Type("MetaFunction",meta_function_disp,meta_function_del,meta_function_copy,meta_function_comp);
+  Type *type_module=new Type("Module",module_disp,module_del,module_copy,module_comp);
+  Type *type_set=new Type("Set",set_disp,set_del,set_copy,set_comp);
+  Type *type_string=new Type("String",string_disp,string_del,string_copy,string_comp);
+  Type *type_symbol=new Type("Symbol",nullptr,nullptr,nullptr,nullptr);
+  Type *type_tuple=new Type("Tuple",tuple_disp,tuple_del,tuple_copy,tuple_comp);
+  Type *type_type=new Type("Type",type_disp,type_del,type_copy,type_comp);
+  Type *type_void=new Type("Void",void_disp,void_del,void_copy,void_comp);
+  
+  //***********************
+  //* Context definitions *
+  //***********************
+
+  //--------------------
+  // Context::Context()
+  //--------------------
+  
+  Context::Context(){
+    add_symbol("context",type_context,this)->hide=true;
+    add_symbol("Array",type_type,type_array);
+    add_symbol("Boolean",type_type,type_boolean)->hide=true;
+    add_symbol("Context",type_type,type_context)->hide=true;
+    add_symbol("Generic",type_type,type_generic)->hide=true;
+    add_symbol("Integer",type_type,type_integer)->hide=true;
+    add_symbol("Function",type_type,type_function)->hide=true;
+    add_symbol("ContextualFunction",type_type,type_contextual_function)->hide=true;
+    add_symbol("Module",type_type,type_module);
+    add_symbol("Set",type_type,type_set);
+    add_symbol("String",type_type,type_string);
+    add_symbol("Symbol",type_type,type_symbol)->hide=true;
+    add_symbol("Tuple",type_type,type_tuple);
+    add_symbol("Type",type_type,type_type)->hide=true;
+    add_symbol("Void",type_type,type_void)->hide=true;
+  }
+
+  //--------------------------------------------------------
+  // Context::add_function(string,string,string_list,void*)
+  //--------------------------------------------------------
+
+  void
+  Context::add_function(string ret,string name,string_list args,void* ptr){
+    Type* tr=get_type(ret);
+    Signature signature=get_signature(args);  
+    Symbol* symbol=get_symbol(name);
+    if(symbol==nullptr or (symbol!=nullptr and
+			   not symbol->locked and
+			   symbol->type!=type_meta_function and
+			   symbol->type!=type_function)){
+      Function* function=new Function(tr,signature,ptr);
+      add_symbol(name,type_function,function,true);
+      return;
+    }
+    string fullname=function_fullname(name,args);
+    if(symbol->type==type_meta_function){
+      if(not can_add(fullname))
+	ContextError("A locked symbol named "+fullname+" already exists");
+      MetaFunction* meta_function=(MetaFunction*)symbol->ptr;
+      meta_function->functions.insert(fullname);
+      Function* function=new Function(tr,signature,ptr);
+      add_symbol(fullname,type_function,function,true);
+      return;      
+    }
+    if(symbol->type==type_function){
+      Function* function=new Function(tr,signature,ptr);
+      add_symbol(fullname,type_function,function,true);
+      MetaFunction* meta_function=new MetaFunction;
+      meta_function->functions.insert(fullname);
+      function=(Function*)symbol->ptr;
+      fullname=function_fullname(name,function->signature);
+      add_symbol(fullname,type_function,function,true);
+      meta_function->functions.insert(fullname);
+      symbol->type=type_meta_function;
+      symbol->ptr=(void*)meta_function;
+      return;
+    }
+    ContextError("A locked symbol named "+name+" already exist");
+  }
+
+  //-------------------------------------------------------------
+  // Context::add_member_function(string,string,string_list,ptr)
+  //-------------------------------------------------------------
+
+  void
+  Context::add_member_function(string ret,string name,string_list args,void* ptr){
+    if(args.size()==0) ContextError("Member function must have at least one argument");
+    string cname=*args.begin();
+    Type* ctype=get_type(cname);
+    if(ctype==nullptr) ContextError("The class type "+cname+" does not exist.");
+    add_function(ret,cname+"."+name,args,ptr);
+  }
+
+  //--------------------------------------------
+  // Context::add_symbol(name,Type*,void*,bool)
+  //--------------------------------------------
+  
+  Symbol*
+  Context::add_symbol(string name,Type* type,void* ptr,bool lock){
+    Symbol& s=symbols[name];
+    if(s.locked) ContextError("A locked symbol named "+name+" already exist");
+    s.del();s.type=type;
+    s.ptr=ptr;s.locked=lock;
+    s.name=name;
+    s.hide=false;
+    return &s;
+  }
+
+  //-----------------------------------------------
+  // Context::can_add_function(string,string_list)
+  //-----------------------------------------------
+  
+  bool
+  Context::can_add_function(string name,string_list targs){
+    if(can_add(name)) return true;
+    if(not can_add(function_fullname(name,targs))) return false;
+    Symbol* symbol=get_symbol(name);
+    return symbol->type==type_meta_function or symbol->type==type_function;
+  }
+
+  //-----------------------------------------------
+  // Context::can_add_member_function(string,string_list)
+  //-----------------------------------------------
+  
+  bool
+  Context::can_add_member_function(string name,string_list targs){
+    if(targs.size()==0) ContextError("A member function must have at least one argument");
+    string cname=*(targs.begin());
+    Type* ctype=get_type(cname);
+    if(ctype==nullptr) ContextError("The class type "+cname+" does not exist");
+    return can_add(cname+"."+name);
+  }
+
+ 
+  //-----------------------------------------
+  // Context::eval_array(size_t,Node&,Node*)
+  //-----------------------------------------
+  
+  void 
+  Context::eval_array(size_t size,Node& current, Node* nodes){
+    ArrayValue* array;
+    if(size==0) array=new ArrayValue(0);
+    else{
+      size_t j=current.son;
+      int k=0;
+      Type* type=nodes[j].value.eval()->type;
+      if(type==nullptr or type==type_void)
+	ContextError("Non empty Array of undefinded type is forbidden");
+      array=new ArrayValue(size);
+      array->type=type;
+      while(j!=-1){
+	Node* node=&nodes[j];
+	Value* val=node->value.eval();
+	//Test if the type is correct
+	if(val->type!=type){
+	  //No -> delete array
+	  for(int i=0;i<k;++i) type->del(array->tab[i]);
+	  delete[] array->tab;
+	  delete array;
+	  current.value.ptr=nullptr;
+	  current.value.type=type_void;
+	  ContextError("Elements of an Array must have same type");
+	}
+	//We cannot stole pointer of value for a symbol
+	if(node->value.type==type_symbol){
+	  array->tab[k++]=type->copy(val->ptr);
+	}
+	else{
+	  array->tab[k++]=val->ptr;
+	  val->type=type_void;
+	  val->ptr=nullptr;
+	}
+	j=node->bro;
+      }
+    }
+    current.value.ptr=array;
+    current.value.type=type_array; 
+  }
+
+  //-----------------------------------------------------------------------
+  // Context::eval_contextual_function(ContextualFunction*,Value**,size_t)
+  //-----------------------------------------------------------------------
+  
+  Value
+  Context::eval_contextual_function(ContextualFunction* func,Value** args,size_t nargs){
+    const Signature& signature=func->signature;
+    if(nargs!=func->signature.size())
+      ContextError("The number of arguments is incorect ("+to_string(nargs)+" instead of "+to_string(func->signature.size())+").");
+    for(size_t i=0;i<nargs;++i){
+      if(args[i]->type==type_symbol and signature[i]!=type_symbol){
+	args[i]=(Value*)args[i]->ptr;
+      }
+      if(signature[i]!=type_generic and signature[i]!=args[i]->type)
+	ContextError("Argument "+to_string(i+1)+" type is incorrect ("+type_disp(args[i]->type)+" instead of "+type_disp(signature[i])+").");
+    }
+    return func->eval(args,nargs,*this);
+  }
+
+  //--------------------------------------------------
+  // Context::eval_function(Function*,Value**,size_t)
+  //--------------------------------------------------
+  
+  Value
+  Context::eval_function(Function* function,Value** args,size_t nargs){
+    if(nargs!=function->signature.size())
+      ContextError("Number of argument is "+to_string(nargs)+" instead of "+to_string(function->signature.size()));
+    Type* targ;
+    for(size_t i=0;i<nargs;++i){
+      if(args[i]->type==type_symbol){
+	targ=((Value*)(args[i]->ptr))->type;
+      }
+      else{
+	targ=args[i]->type;
+      }
+      if(targ!=function->signature[i])
+	ContextError("Argument "+to_string(i)+" is of type "+type_disp(targ)+" instead of "+type_disp(function->signature[i]));
+    }
+    return function->eval(args,nargs);
+  }
+
+  //-------------------------------------
+  // Context::eval_function(Node&,Node*)
+  //-------------------------------------
+  
+  void
+  Context::eval_function(Node& current,Node* nodes){
+    string name=current.str;
+    Symbol* symbol=get_symbol(name);
+    if(symbol==nullptr)
+      ContextError("There is no symbol named "+name);
+    Value* args[max_arguments_number];
+    size_t nargs=set_arguments(current,nodes,args);
+    eval_function(symbol,args,nargs);
+  }
+
+  //------------------------------------------------
+  // Context::eval_function(Symbol*,Value**,size_t)
+  //------------------------------------------------
+  
+  Value
+  Context::eval_function(Symbol* symbol,Value** args,size_t nargs){
+    if(symbol->type==type_contextual_function){
+      return eval_contextual_function((ContextualFunction*)symbol->ptr,args,nargs);
+    }
+    else if(symbol->type==type_function){
+      return eval_function((Function*)symbol->ptr,args,nargs);
+    }
+    else if(symbol->type==type_meta_function){
+      string fullname=function_fullname(symbol->name,args,nargs);
+      Value *val=get_symbol(fullname);
+      if(val==nullptr) ContextError("There is no function "+fullname);
+      if(val->type!=type_function) Bug("This case shall be impossible!");
+      return eval_function((Function*)val->ptr,args,nargs);
+    }
+    else{
+      Bug("The symbol named "+symbol->name+" is not callable");
+    }
+  }
+
+  //--------------------------------------------
+  // Context::eval_member_function(Node&,Node*)
+  //--------------------------------------------
+  
+  void
+  Context::eval_member_function(Node& current,Node* nodes){
+    Value* args[max_arguments_number];
+    size_t nargs=set_arguments(current,nodes,args);
+    Value* first=args[0]->eval();
+    Type* type=first->type;
+    Value* val=get_symbol(type,current.str);
+    if(val==nullptr){
+      if(type==type_type){
+	type=(Type*)first->ptr;
+	val=get_symbol(type,current.str);
+	//current.son=nodes[current.son].bro;
+	if(val==nullptr)
+	  ContextError("No member function "+current.str+" for tyipe "+type->name);
+	current.value=eval_function((Function*)val->ptr,&args[1],nargs-1);
+	return;
+      }
+      else{
+	ContextError("No member function "+current.str+" for type "+type->name);
+      }
+    }
+    if(val->type!=type_function)
+      ContextError("The symbol named "+current.str+" is not callable");
+    current.value=eval_function((Function*)val->ptr,args,nargs);
+  }
+
+  //---------------------------------------
+  // Context::eval_set(size_t,Node&,Node*)
+  //---------------------------------------
+  
+  void 
+  Context::eval_set(size_t size,Node& current, Node* nodes){
+    SetValue* set;
+    if(size==0) set=new SetValue(type_generic);
+    else{
+      size_t j=current.son;
+      int k=0;
+      Type* type=nodes[j].value.eval()->type;
+      if(type==nullptr or type==type_void)
+	ContextError("Non empty Set of undefinded type is forbidden");
+      set=new SetValue(type);
+      while(j!=-1){
+	Node* node=&nodes[j];
+	Value* val=node->value.eval();
+	//Test if the type is correct
+	if(val->type!=type){
+	  //No -> delete set
+	  for(auto it=set->data.begin();it!=set->data.end();++it) type->del(*it);
+	  delete set;
+	  current.value.ptr=nullptr;
+	  current.value.type=type_void;
+	  ContextError("Elements of a Set must have same type");
+	}
+	//Check if the value is not in the set otherwise do nothing
+	if(set->data.find(val->ptr)==set->data.end()){
+	  if(node->value.type==type_symbol){
+	    //We cannot stole pointer of value for a symbol
+	    set->data.insert(type->copy(val->ptr));
+	  }
+	  else{
+	    set->data.insert(val->ptr);
+	    val->type=type_void;
+	    val->ptr=nullptr;
+	  }
+	}
+	j=node->bro;
+      }
+    }
+    current.value.ptr=set;
+    current.value.type=type_set;
+  }
+
+  //-----------------------------------------
+  // Context::eval_tuple(size_t,Node&,Node*)
+  //-----------------------------------------
+
+  void 
+  Context::eval_tuple(size_t size,Node& current, Node* nodes){
+    TupleValue* tuple;
+    if(size==0) tuple=new TupleValue(0);
+    else{
+      size_t j=current.son;
+      int k=0;
+      tuple=new TupleValue(size);
+      while(j!=-1){
+	Node* node=&nodes[j];
+	Value* val=node->value.eval();
+	//We cannot stole pointer of value for a symbol
+	if(node->value.type==type_symbol){
+	  tuple->tab[k++]=val->copy();
+	}
+	else{
+	  tuple->tab[k++]=*val;
+	  val->type=type_void;
+	  val->ptr=nullptr;
+	}
+	j=node->bro;
+      }
+    }
+    current.value.ptr=tuple;
+    current.value.type=type_tuple;
+  }
+
+  //-------------------------------------
+  // Context::get_signature(string_list)
+  //-------------------------------------
+  
+  Signature
+  Context::get_signature(string_list targs){
+    Signature s(targs.size());
+    size_t i=0;
+    for(auto its=targs.begin();its!=targs.end();++its) s[i++]=get_type(*its);
+    return s;
+  }
+
+  //---------------------------
+  // Context::get_symbol(name)
+  //---------------------------
+  
+  Symbol*
+  Context::get_symbol(string name){
+    auto it=symbols.find(name);
+    if(it==symbols.end()) return nullptr;
+    return &it->second;
+  }
+
+  //-------------------------
+  // Context::get_type(name)
+  //-------------------------
+  
+  Type*
+  Context::get_type(string name){
+    Value* v=get_symbol(name);
+    if(v==nullptr) ContextError("Type "+name+" does not exist");
+    if(v->type!=type_type) ContextError(name+" does not design a type");
+    return (Type*)v->ptr;
+  }
+
+  //----------------------------
+  // Context::load_module(name)
+  //----------------------------
+  
+  void
+  Context::load_module(string name){
+    string filename="ext/"+name+".so";
+    Symbol* symbol=get_symbol(name);
+    if(symbol!=nullptr and symbol->locked==true) ContextError("A locked symbol "+name+" already exist");
+    void* handle=dlopen(filename.c_str(),RTLD_NOW);
+    if(not handle) RuntimeError("In loading module "+name+" : "+dlerror());
+    Module* module=new Module;
+    symbol=add_symbol(name,type_module,module);
+    module->handle=handle;
+    module->name=name;
+    //Loading types
+    Type* types=(Type*)dlsym(handle,"types");
+    module->functions=(Module::Function*)dlsym(handle,"functions");
+    module->member_functions=(Module::Function*)dlsym(handle,"member_functions");
+    module->contextual_functions=(Module::Function*)dlsym(handle,"contextual_functions");
+    module->init(types);
+    //Test if we can load all types
+    for(size_t i=0;i<module->ntype;++i){
+      if(not can_add(types[i].name)){
+	dlclose(handle);
+	delete(module);
+	ContextError("The type "+name+" cannot be added because a locked symbol has the same name");
+      }
+    }
+    module->types=new string[module->ntype];
+    for(size_t i=0;i<module->ntype;++i){
+      Type* type=new Type(types[i]);
+      module->types[i]=type->name;
+      add_symbol(type->name,type_type,type);
+    }
+    load_module_functions(module,0);
+    load_module_functions(module,1);
+    load_module_functions(module,2);
+  }
+
+  //---------------------------------------------
+  // Context::load_module_functions(Module*,int)
+  //---------------------------------------------
+  
+  void Context::load_module_functions(Module* module,int src){
+    bool (Context::*can_add_func)(string,string_list);
+    void (Context::*add_func)(string,string,string_list,void*);
+    Module::Function* module_func_ptr;
+    size_t n;
+    switch(src){
+    case 0:
+      can_add_func=&Context::can_add_function;
+      add_func=&Context::add_function;
+      module_func_ptr=module->functions;
+      n=module->nfunc;
+      break;
+    case 1:
+      can_add_func=&Context::can_add_member_function;
+      add_func=&Context::add_member_function;
+      module_func_ptr=module->member_functions;
+      n=module->nmfunc;
+      break;
+    case 2:
+      can_add_func=&Context::can_add_contextual_function;
+      add_func=&Context::add_contextual_function;
+      module_func_ptr=module->contextual_functions;
+      n=module->ncfunc;
+      break;
+    default:
+      Bug("Not yet implemented");
+    }
+    for(size_t i=0;i<n;++i){
+      Module::Function& function=module_func_ptr[i];
+      try{
+	function.loaded=(this->*can_add_func)(function.name,function.targs);
+      }
+      catch(Error& err){
+	err.disp(cout,"");
+	function.loaded=false;
+      }
+      if(function.loaded){
+	(this->*add_func)(function.tr,function.name,function.targs,function.ptr);
+      }
+      else{
+	cout<<"Warning : ";
+	if(src==0) cout<<"Function";
+	else if(src==1) cout<<"Member function";
+	else cout<<"Contextual function";
+	cout<<" "<<function.name<<" not loaded"<<endl;
+      }
+    }
+  }
+
+  //----------------------------------------------
+  // Context::unload_function(string,string_list)
+  //----------------------------------------------
+
+  void
+  Context::unload_function(string name,string_list args){
+    string fullname=function_fullname(name,args);
+    unload_symbol(fullname);
+    Symbol* symbol=get_symbol(name);
+    if(symbol==nullptr) Bug("The meta function "+name+" does not exist");
+    if(symbol->type==type_function){
+      unload_symbol(name);
+      return;
+    }
+    if(symbol->type!=type_meta_function) Bug("The symbol "+name+" is not of type Function or MetaFunction");
+    MetaFunction* meta=(MetaFunction*)(symbol->ptr);
+    meta->functions.erase(fullname);
+    if(meta->functions.empty()) //There is no more function called name
+      unload_symbol(name);
+  }
+
+  //---------------------------------
+  // Context::unload_module(Module*)
+  //---------------------------------
+  
+  void
+  Context::unload_module(Module* module){
+    unload_module_functions(module);
+    for(size_t i=0;i<module->ntype;++i){
+      unload_type(get_type(module->types[i]));
+    }
+    dlclose(module->handle);
+    unload_symbol(module->name);
+  }
+
+  //-------------------------------------------
+  // Context::unload_module_functions(Module*)
+  //-------------------------------------------
+  
+  void
+  Context::unload_module_functions(Module* module){
+    for(size_t i=0;i<module->nfunc;++i){
+      if(module->functions[i].loaded)
+	unload_function(module->functions[i].name,module->functions[i].targs);
+    }
+    for(size_t i=0;i<module->nmfunc;++i){
+      Module::Function& func=module->member_functions[i];
+      if(func.loaded)
+	unload_function(*func.targs.begin()+"."+func.name,func.targs);
+    }
+    for(size_t i=0;i<module->ncfunc;++i){
+      if(module->contextual_functions[i].loaded)
+	unload_symbol(module->contextual_functions[i].name);
+    }
+  }
+
+  //-----------------------------
+  // Context::unload_type(Type*)
+  //-----------------------------
+  
+  void
+  Context::unload_type(Type* type){
+    for(auto it=symbols.begin();it!=symbols.end();++it){
+      if(it->second.type==type)
+	unload_symbol(it->first);
+    }
+    unload_symbol(type->name);
+  }
+
+  //--------------------------
+  // Context::reload(Module*)
+  //--------------------------
+  
+  void
+  Context::reload_module(Module* module){
+    //** Unload some module member
+    unload_module_functions(module); //unload functions
+    if(module->handle!=nullptr){
+      dlclose(module->handle); //close previous module handle
+      module->handle=nullptr;
+    }
+    //we postpone the unload of module->types
+    
+    //** Load the new version of the library
+    string filename="modules/"+module->name+".so";
+    void* handle=dlopen(filename.c_str(),RTLD_NOW);
+    if(not handle){
+      handle=nullptr;
+      RuntimeError("In loading module "+module->name+" : "+dlerror());
+    }
+    Module nmod; //A temporary module for the newly loaded data
+    
+    Type* types=(Type*)dlsym(handle,"types"); 
+    nmod.functions=(Module::Function*)dlsym(handle,"functions");
+    nmod.member_functions=(Module::Function*)dlsym(handle,"member_functions");
+    nmod.contextual_functions=(Module::Function*)dlsym(handle,"contextual_functions");
+    nmod.init(types);//init the module, ie, compute size of arrays
+    
+    //Test if we can load the new types
+    int link[nmod.ntype];
+    for(size_t i=0;i<nmod.ntype;++i){
+      string name=types[i].name;
+      link[i]=-1;
+      if(not can_add(name)){
+	for(size_t j=0;j<module->ntype;++j){
+	  if(module->types[j]==name){
+	    link[i]=j;
+	    break;
+	  }
+	}
+	if(link[i]==-1){//We can't load a type
+	  //close the library
+	  dlclose(handle);
+	  ContextError("The type "+name+" cannot be added because a locked symbol has the same name");
+	}
+      }
+    }
+
+    //Look for old types to unload, ie, types in the old version of the library
+    //that are not present in the new version
+    bool to_unload[module->ntype];
+    for(size_t i=0;i<module->ntype;++i){
+      to_unload[i]=true;
+      for(size_t j=0;j<nmod.ntype;++j){
+	if(link[j]==i){
+	  to_unload[i]=false;
+	  break;
+	}
+      }
+    }
+    
+    //Unload marked types
+    for(size_t i=0;i<module->ntype;++i){
+      if(to_unload[i]) unload_type(get_type(module->types[i]));
+    }
+    
+    //Update or load the types in the new version of the library
+    delete[] module->types; //unload types array
+    module->types=new string[nmod.ntype];
+    for(size_t i=0;i<nmod.ntype;++i){
+      Type& nmod_type=types[i];
+      module->types[i]=nmod_type.name;
+      if(link[i]==-1){
+	Type *type=new Type(nmod_type);
+	add_symbol(type->name,type_type,type);
+      }
+      else{
+	Type* type=get_type(nmod_type.name);
+	type->disp=nmod_type.disp;
+	type->del=nmod_type.del;
+	type->copy=nmod_type.copy;
+	type->comp=nmod_type.comp;
+      }
+    }
+    module->ntype=nmod.ntype;
+    module->functions=nmod.functions;
+    module->nfunc=nmod.nfunc;
+    module->member_functions=nmod.member_functions;
+    module->nmfunc=nmod.nmfunc;
+    module->contextual_functions=nmod.contextual_functions;
+    module->ncfunc=nmod.ncfunc;
+    module->handle=handle;
+    load_module_functions(module,0);
+    load_module_functions(module,1);
+    load_module_functions(module,2);
+  }
+
+  //---------------------------------------------
+  // Context::set_arguments(Node&,Node*,Value**)
+  //---------------------------------------------
+  
+  size_t
+  Context::set_arguments(Node& current,Node* nodes,Value** args){
+    size_t j=current.son;
+    size_t nargs=0;
+    while(j!=-1){
+      args[nargs++]=&nodes[j].value;
+      j=nodes[j].bro;
+    }
+    return nargs;
+  }
+
+  //**********************
+  //* ContextualFunction *
+  //**********************
+
+  //---------------------------------------------------
+  // ContextualFunction::eval(Value**,size_t,Context&)
+  //---------------------------------------------------
+  
+  Value ContextualFunction::eval(Value* args[8],size_t nargs,Context& context){
+    switch(nargs){
+    case 0:
+      return (*((CFunc0)ptr))(context);
+    case 1:
+      return (*((CFunc1)ptr))(context,*args[0]);
+    case 2:
+      return (*((CFunc2)ptr))(context,*args[0],*args[1]);
+    default:
+      Bug("Not yet implemented");
+      break;
+    }
+  }
+
+  //************
+  //* Function *
+  //************
+
+  //--------------------------------
+  // Function::eval(Value**,size_t)
+  //--------------------------------
+  
+  Value Function::eval(Value* args[8],size_t nargs){
+    Value res;
+    res.type=tr;
+    switch(nargs){
+    case 1:
+      res.ptr=(*((Func1)ptr))(args[0]->eval()->ptr);
+      break;
+    default:
+      Bug("Not yet implemented");
+    }
+    return res;
+  }
+
+  //***************
+  //* Interpreter *
+  //***************
+
+  //-------------------------------------------------------------------------
+  // Interperter::add_operator(const string&,const string&,OperatorType,int)
+  //-------------------------------------------------------------------------
+  
+  void
+  Interpreter::add_operator(const string& op,const string& name,OperatorType type,int priority){
+    OperatorInfo* opInfo=new OperatorInfo(name,type,priority);
+    operator_tree.add(op,opInfo);
+  }
+
+  //------------------------------------------------------------------------
+  // Interpreter::complete(const string&,const string&,size_t,int,Context&)
+  //------------------------------------------------------------------------
+  
+  string
+  Interpreter::complete(const string& cmd,const string& word,size_t pos,int state,Context& context){
+    if(state==0){
+      split_to_tokens(cmd);
+      size_t i;
+      for(i=0;i<nodes_number;++i){
+	if(nodes[i].pos>pos) break;
+      }
+      if(i!=0) --i;
+      if(i>0 and nodes[i-1].tokenType==tDot) --i;
+      if(nodes[i].tokenType==tDot){
+	//*.word
+	if(i>0 and nodes[i-1].tokenType==tName){
+	  Symbol* symbol=context.get_symbol(nodes[i-1].str);
+	  if(symbol==nullptr) return "";
+	  if(symbol->type==type_type){
+	    completion.type=context.get_type(nodes[i-1].str);
+	  }
+	  else{
+	    completion.type=symbol->type;
+	  }
+	  completion.prefix=completion.type->name+".";
+	  completion.word=completion.prefix+word;
+	  completion.it=context.symbols.lower_bound(completion.word);
+	}
+	else return "";
+      }
+      else{
+	//word
+	completion.prefix="";
+	completion.word=word;
+	completion.it=context.symbols.lower_bound(completion.word);
+	completion.type=nullptr;
+      }
+    } 
+    //Omit function fullname, hidden symbol and member symbols if no member call
+    while((completion.it!=context.symbols.end()) and
+	  ((completion.it->second.hide) or
+	   (completion.it->first.find('(')!=string::npos) or
+	   (completion.type==nullptr and completion.it->first.find('.')!=string::npos)
+	   )
+	  )
+      ++completion.it;
+    if(completion.it==context.symbols.end()) return "";
+    
+    if(completion.it->first.compare(0,completion.word.size(),completion.word)==0){
+      string res=completion.it->first;
+      ++completion.it;
+      return res.substr(completion.prefix.size());
+    }
+    return "";
+  }
+
+  //-------------------------------------------------
+  // Interpreter::construct_sequence(size_t&,size_t)
+  //-------------------------------------------------
+  
+  size_t
+  Interpreter::construct_sequence(size_t& pos,size_t last){
+    Node& node=nodes[pos];
+    BracketType bt=node.bracketType;
+    node.expressionType=get_delimiter_expression_type(bt);
+    int depth=1;
+    size_t begin=pos;
+    slong* next=&node.son;
+    size_t i=++pos;
+    for(;pos<=last and depth!=0;++pos){
+      switch(nodes[pos].tokenType){
+      case tOpenBracket:
+	++depth;
+	break;
+      case tCloseBracket:
+	--depth;
+	break;
+      case tComma:
+	if(depth==1){
+	  if(i>pos-1)//Empty
+	    SyntaxError("An Expression is needed",nodes[i-1].pos,nodes[pos].pos);
+	  (*next)=construct_tree(i,pos-1,max_precedence_level);
+	  next=&(nodes[*next].bro);
+	  i=pos+1;
+	}     
+	break;
+      default:
+	break;
+      }
+    }
+    //Close bracket not found
+    if(depth!=0){
+      switch(bt){
+      case bRound:
+	SyntaxError("Tuple or list has not ending",nodes[begin].pos,nodes[last].pos);
+      case bSquare:
+	SyntaxError("Array has not ending",nodes[begin].pos,nodes[last].pos);
+      case bCurly:
+	SyntaxError("Set has not ending",nodes[begin].pos,nodes[last].pos);
+      default:
+	Bug("Bracket type unkown");
+	break;
+      }
+    }
+    size_t end=pos-1;
+    //Close bracket mismatch
+    if(nodes[end].bracketType!=bt)
+      SyntaxError("Close bracket mismatch the opening one",nodes[begin].pos,nodes[end].pos);
+
+    //The sequence is empty
+    if(end==begin+1) return begin;
+    //Add the last element
+    if(i>=end)//Empty 
+      SyntaxError("An expression is needed",nodes[i-1].pos,nodes[end].pos);
+    (*next)=construct_tree(i,end-1,max_precedence_level);
+    return begin;
+  }
+
+  //-------------------------------------------------
+  // Interpreter::construct_tree(size_t&,size_t,int)
+  //-------------------------------------------------
+  
+  size_t
+  Interpreter::construct_tree(size_t& first,size_t last,int precedence_level){
+    Node& node=nodes[first];
+    size_t root=first;
+    switch(node.tokenType){
+    case tInteger:
+    case tString:
+      node.expressionType=expLeaf;
+      ++first;
+      break;
+    case tName:
+      ++first;
+      if(first<=last and nodes[first].tokenType==tOpenBracket){
+	if(nodes[first].bracketType==bRound){
+	  //Function call
+	  node.son=nodes[construct_sequence(first,last)].son;
+	  node.expressionType=expFunction;
+	  break;
+	}
+	else if(nodes[first].bracketType==bSquare){
+	  //Get or set call
+	  node.bro=nodes[construct_sequence(first,last)].son;
+	  Node& nnode=nodes[first];
+	  nnode.son=root;
+	  nnode.str="get";
+	  root=first;
+	  nnode.expressionType=expArrayGet; 
+	  node.expressionType=expLeaf;
+	  break;
+	}
+	else{
+	  Bug("Not yet implemented");
+	}
+      }
+      else if(first<=last and (nodes[first].tokenType==tDot)){
+	//Member function call
+	++first;
+	if(first>last or nodes[first].tokenType!=tName){
+	  if(nodes[first-1].tokenType==tDot) SyntaxError("Name missing after dot",nodes[first-1].pos,nodes[first-1].pos);
+	  SyntaxError("Name missing after ::",nodes[first-1].pos,nodes[first-1].pos+1);
+	}
+	string name=nodes[first].str;
+	++first;
+	if(first<=last and nodes[first].tokenType==tOpenBracket and nodes[first].bracketType==bRound){
+	  Node& nnode=nodes[first-2];
+	  nnode.son=root;
+	  nnode.str=name;
+	  nnode.expressionType=expMemberFunction;
+	  root=first-2;
+	  node.bro=nodes[construct_sequence(first,last)].son;
+	  node.expressionType=expLeaf;
+	  break;
+	}
+	else{
+	  Node& nnode=nodes[first-1];
+	  nnode.son=root;
+	  nnode.expressionType=expMemberFunction;
+	  nnode.str=name;
+	  node.expressionType=expLeaf;
+	  root=first-1;
+	  break;
+	}
+      }
+      else{
+	node.expressionType=expLeaf;
+      }
+      break;
+    case tOpenBracket:
+      root=construct_sequence(first,last);
+      //(Expr) -> Expr
+      if(node.bracketType==bRound and node.son!=-1 and nodes[node.son].bro==-1){
+	root=node.son;
+      }
+      break;
+    case tOperator:
+      if(node.operatorInfo->type!=opPreUnitary and node.str!="-")
+	SyntaxError("Operator not allowed here",node.pos,node.pos+node.str.length()-1);
+      node.expressionType=expFunction;
+      if(node.str=="-"){
+	node.str="negate";
+	node.son=construct_tree(++first,last,1);
+      }
+      else{
+	node.str=node.operatorInfo->func;
+	node.son=construct_tree(++first,last,node.operatorInfo->precedence);
+      }
+      break;
+    case tCloseBracket:
+      SyntaxError("Missing openning bracket",node.pos,node.pos);
+    case tComma:
+      SyntaxError("Unexecepted comma outside a sequence",node.pos,node.pos);
+    case tUnkown:
+      SyntaxError("Get unkown token",node.pos,node.pos);
+    case tEnd:
+      //Ignore this token 
+      break;
+    default:
+      Bug("not yet implemented");
+      break;
+    }
+    size_t lhs;
+    //We already read an expression
+    while(first<=last){//There is something on the right
+      //At this time inly operator are allowed
+      lhs=root;
+      root=first;
+      Node& node=nodes[root];
+      if(node.tokenType==tOperator){
+	if(node.operatorInfo->type==opPreUnitary){
+	  SyntaxError("A prefixed unitary operator is not allowed here",node.pos,node.pos+node.str.length()-1);
+	}
+	if(node.operatorInfo->precedence>precedence_level) return lhs;
+	if(node.operatorInfo->type==opPostUnitary){
+	  node.expressionType=expFunction;
+	  node.son=lhs;
+	  ++first;
+	}
+	else if(node.operatorInfo->type==opBinary){
+	  if(first==last) SyntaxError("An expression is needed after binary operator",node.pos,node.pos+node.str.length()-1);
+	  size_t rhs=construct_tree(++first,last,node.operatorInfo->precedence);
+	  node.str=node.operatorInfo->func;
+	  node.expressionType=expFunction;
+	  node.son=lhs;
+	  nodes[lhs].bro=rhs;
+	}
+      }
+      else SyntaxError("Only operator are allowed after such expression",node.pos,node.pos+node.str.length()-1);
+    }
+    return root;
+  }
+
+  //-------------------------------------------------------
+  // Interpreter::display_expression_tree(ostream&,size_t)
+  //-------------------------------------------------------
+  
+  void
+  Interpreter::display_expression_tree(ostream& os,size_t i) const{
+    const Node& node=nodes[i];
+    switch(node.expressionType){
+    case expLeaf:
+      os<<'[';
+      display_token(os,i);
+      os<<']';
+      return;
+    case expTuple:
+      os<<"[tuple";
+      break;
+    case expArray:
+      os<<"[array";
+      break;
+    case expSet:
+      os<<"[set";
+      break;
+    case expFunction:
+      os<<"[function '"<<node.str<<"'";
+      break;
+    case expMemberFunction:
+      os<<"[member function '"<<node.str<<"'";
+      break;
+    default:
+      Bug("ExpressionNode type unkown");
+    }
+    slong j=node.son;
+    if(j>=0){//There is at least a son
+      do{
+	os<<',';
+	display_expression_tree(os,j);
+	j=nodes[j].bro;
+      }while(j>=0);
+    }
+    os<<']';
+  }
+
+  //---------------------------------------------
+  // Interpreter::display_token(ostream&,size_t)
+  //---------------------------------------------
+
+  void
+  Interpreter::display_token(ostream& os,size_t i) const{
+    const Node& node=nodes[i];
+    switch(node.tokenType){
+    case tInteger:
+      os<<"(integer,"<<integer_disp(node.value.ptr)<<')';
+      return;
+    case tString:
+      os<<"(string,"<<node.str<<')';
+      return;
+    case tName:
+      os<<"(name,"<<node.str<<')';
+      return;
+    case tEnd:
+      os<<"(end)";
+      return;
+    case tComma:
+      os<<"(comma)";
+      return;
+    case tOpenBracket:
+      os<<"(open "<<node.bracketType<<" bracket)";
+      return;
+    case tCloseBracket:
+      os<<"(close "<<node.bracketType<<" bracket)";
+      return;
+    case tOperator:
+      os<<"(operator, "<<*node.operatorInfo<<")";
+      return;
+    case tUnkown:
+      os<<"(?,"<<node.str<<')';
+      return;
+    default:
+      Bug("Token type unkown");
+      return;
+    }
+  }
+
+  //---------------------------------------
+  // Interpreter::display_tokens(ostream&)
+  //---------------------------------------
+  
+  void
+  Interpreter::display_tokens(ostream& os) const{
+    for(size_t i=0;i<nodes_number;++i){
+      display_token(os,i);
+      os<<endl;
+    }
+  }
+
+  //---------------------------
+  // Interpreter::eval(string)
+  //---------------------------
+  
+  void Interpreter::eval(string cmd,Context& context){
+    size_t root;
+    Node* node;
+    bool error=false;
+    try{
+      split_to_tokens(cmd);
+      size_t first=0;
+      root=construct_tree(first,nodes_number-1,max_precedence_level);
+      eval_expression(root,context);
+      node=&nodes[root];
+      Value* value=node->value.eval();
+      if(value->type!=nullptr and value->type!=type_void){
+	cout<<value->disp()<<endl;
+      }
+    }
+    catch(Error err){
+      err.disp(cout,cmd);
+      cout<<endl;
+      error=true;
+    }
+    //Delete the return value
+    if(not error){
+      if(node->erase){
+      node->value.del();
+      node->erase=false;
+      }
+    }
+  }
+
+  //-----------------------------------------------
+  // Interpreter::eval_expression(size_t,Context&)
+  //-----------------------------------------------
+  
+  void Interpreter::eval_expression(size_t pos,Context& context){
+    Node &node=nodes[pos];
+    if(node.expressionType==expLeaf){
+      if(node.tokenType==tName){
+	node.value.type=type_symbol;
+	Symbol* symbol=context.get_symbol(node.str);
+	if(symbol!=nullptr){
+	  node.value.ptr=symbol;
+	}
+	else{
+	  node.value.ptr=context.add_symbol(node.str,type_void,nullptr,false);
+	}
+	return;
+      }
+      return;
+    }
+    size_t size=0;
+    slong j=node.son;
+    while(j!=-1){
+      ++size;
+      eval_expression(j,context);
+      j=nodes[j].bro;
+    }
+    switch(node.expressionType){
+    case expFunction:
+      context.eval_function(node,nodes);
+      break;
+    case expMemberFunction:
+      context.eval_member_function(node,nodes);
+      break;
+    case expArray:
+      context.eval_array(size,node,nodes);
+      break;
+    case expSet:
+      context.eval_set(size,node,nodes);
+      break;
+    case expTuple:
+      context.eval_tuple(size,node,nodes);
+      break;
+    case expArrayGet:
+      Bug("Exp array get not yet implemented");
+      break;
+    default:
+      Bug("Not yet implemented");
+    }
+    j=node.son;
+    while(j!=-1){
+      if(nodes[j].erase){
+	nodes[j].value.del();
+	nodes[j].erase=false;
+      }
+      j=nodes[j].bro;
+    }
+  }
+
+  //-------------------------------------------------
+  // Interpreter::get_integer(size_t&,const string&)
+  //-------------------------------------------------
+  
+  fmpz*
+  Interpreter::get_integer(size_t& pos,const string& cmd){
+    size_t oldPos=pos;
+    size_t end=cmd.length();
+    char l;
+    do{
+      l=cmd[++pos];
+    }while(pos<end and '0'<=l and l<='9');
+    string sint=cmd.substr(oldPos,pos-oldPos);
+    fmpz* res=new fmpz;
+    fmpz_init(res);
+    fmpz_set_str(res,sint.c_str(),10);
+    return res;
+  }
+
+  //----------------------------------------------
+  // Interpreter::get_name(size_t&,const string&)
+  //----------------------------------------------
+
+  string
+  Interpreter::get_name(size_t& pos,const string& cmd){
+    size_t end=cmd.length();
+    size_t npos=pos;
+    char l=cmd[npos];
+    do{
+      ++npos;
+      l=cmd[npos];
+    }while(npos<end and (('a'<=l and l<='z') or 
+			 ('A'<=l and l<='Z') or
+			 ('0'<=l and l<='9') or
+			 l=='_'));
+    string str=cmd.substr(pos,npos-pos);
+    pos=npos;
+    return str;
+  }
+
+  //------------------------------------------------
+  // Interpreter::get_string(size_t&,const string&)
+  //------------------------------------------------
+  
+  string
+  Interpreter::get_string(size_t& pos,const string& cmd){
+    size_t npos=cmd.find('"',pos+1);
+    if(npos==string::npos){
+      SyntaxError("the string does not end by \"",pos,string::npos);
+    }
+    string str=cmd.substr(pos+1,npos-pos-1);
+    pos=npos+1;
+    return str;
+  }
+
+  //-----------------------------------------------------
+  // Interpreter::set_token(Node&,size_t&,const string&)
+  //-----------------------------------------------------
+  
+  void
+  Interpreter::set_token(Node& node,size_t& pos,const string& cmd){
+    node.value.type=nullptr;
+    node.erase=false;
+    size_t oldPos;
+    node.pos=pos;
+    node.son=-1;
+    node.bro=-1;
+    size_t end=cmd.length();
+    if(pos>=end){
+      node.tokenType=tEnd;
+      return;
+    }
+    char l=cmd[pos];
+    if('0'<=l and l<='9'){
+      node.tokenType=tInteger;
+      oldPos=pos;
+      node.value.type=type_integer;
+      node.value.ptr=(void*)(get_integer(pos,cmd));
+      node.erase=true;
+      node.str=cmd.substr(oldPos,pos-oldPos+1);
+      return;
+    }
+    if(l=='"'){
+      node.tokenType=tString;
+      node.str=get_string(pos,cmd);
+      node.value.type=type_string;
+      string* pstr=new string;
+      *pstr=node.str;
+      node.value.ptr=(void*)pstr;
+      node.erase=true;
+      return;
+    }
+    if(('a'<=l and l<='z') or ('A'<=l and l<='Z') or l=='_'){
+      node.tokenType=tName;
+      node.str=get_name(pos,cmd);
+      return;
+    }
+    switch(l){
+    case ',':
+      node.str=',';
+      node.tokenType=tComma;
+      ++pos;
+      return;
+    case '.':
+      node.str='.';
+      node.tokenType=tDot;
+      ++pos;
+      return;
+    case '(':
+      node.tokenType=tOpenBracket;
+      node.bracketType=bRound;
+      node.str=l;++pos;
+      return;
+    case ')':
+      node.tokenType=tCloseBracket;
+      node.bracketType=bRound;
+      node.str=l;++pos;
+      return;
+    case '[':
+      node.tokenType=tOpenBracket;
+      node.bracketType=bSquare;
+      node.str=l;++pos;
+      return;
+    case ']':
+      node.tokenType=tCloseBracket;
+      node.bracketType=bSquare;
+      node.str=l;++pos;
+      return;
+    case '{':
+      node.tokenType=tOpenBracket;
+      node.bracketType=bCurly;
+      node.str=l;++pos;
+      return;
+    case '}':
+      node.tokenType=tCloseBracket;
+      node.bracketType=bCurly;
+      node.str=l;++pos;
+      return;
+    }
+    //Try to find operator
+    oldPos=pos;
+    OperatorInfo* operatorInfo=get_operator(pos,cmd);
+    if(operatorInfo!=nullptr){//Operator found
+      node.tokenType=tOperator;
+      node.operatorInfo=operatorInfo;
+      node.str=cmd.substr(oldPos,pos-oldPos);
+      return;
+    }
+    //Operator not found
+    SyntaxError("Token unkown",oldPos,oldPos);
+    return;
+  }
+
+  //---------------------------------------------
+  // Interpreter::split_to_tokens(const string&)
+  //---------------------------------------------
+  
+  void Interpreter::split_to_tokens(const string& cmd){
+    nodes_number=0;
+    size_t pos=0;
+    while(true){
+      if(nodes_number>=max_nodes_number) Bug("The command is too huge");
+      Node& node=nodes[nodes_number++];
+      set_token(node,pos,cmd);
+      if(node.tokenType==tEnd) break;
+    }
+    //Remove node of token type tEnd
+    --nodes_number;
+  }
+  
+  //***********************
+  //* Auxiliary functions *
+  //***********************
+
+  //--------------------------------------------
+  // get_delimiter_expression_type(BracketType)
+  //--------------------------------------------
+  
+  ExpressionType
+  get_delimiter_expression_type(BracketType type){
+    switch(type){
+    case bRound:
+      return expTuple;
+    case bSquare:
+      return expArray;
+    case bCurly:
+      return expSet;
+    default:
+      cout<<"BUG from getDelimiterExpressionType"<<endl;
+      return expTuple;
+    }
+  }
+
+  //---------------------------------
+  // close_bracket_char(BracketType)
+  //---------------------------------
+  
+  char
+  close_bracket_char(BracketType type){
+    switch(type){
+    case bRound:
+      return ')';
+    case bSquare:
+      return ']';
+    case bCurly:
+      return '}';
+    default:
+      cout<<"BUG from closeBracketChar"<<endl;
+      return ')';
+    }
+  }
+
+  //---------------------------------------
+  // function_fullname(string,string_list)
+  //---------------------------------------
+  
+  string
+  function_fullname(string name,string_list args){
+    string res=name+"(";
+    if(args.size()==0) return res+")";
+    auto it=args.begin();
+    res+=*it;
+    for(++it;it!=args.end();++it){
+      res+=",";
+      res+=*it;
+    }
+    return res+")";
+  }
+
+  //------------------------------------------
+  // function_fullname(string,Vlaue**,size_t)
+  //------------------------------------------
+  
+  string
+  function_fullname(string name,Value** args,size_t nargs){
+    string res=name+"(";
+    if(nargs==0) return res+")";
+    res+=args[0]->type->name;
+    for(size_t i=1;i<nargs;++i){
+      res+=",";
+      res+=args[i]->type->name;
+    }
+    return res+")";
+  }
+
+  //--------------------------------------------
+  // function_fullname(string,const Signature&)
+  //--------------------------------------------
+  
+  string
+  function_fullname(string name,const Signature& signature){
+    string res=name+"(";
+    if(signature.is_empty()) return res+")";
+    res+=signature[0]->name;
+    for(size_t i=1;i<signature.size();++i){
+      res+=",";
+      res+=signature[i]->name;
+    }
+    return res+")";
+  }
+    
+
+  ostream&
+  operator<<(ostream& os,const BracketType& bt){
+    switch(bt){
+    case bRound:
+      return os<<"round";
+      break;
+    case bSquare:
+      return os<<"square";
+      break;
+    case bCurly:
+      return os<<"curly";
+      break;
+    default:
+      return os<<"?";
+      break;
+    }
+  }
+
+  ostream&
+  operator<<(ostream& os,const OperatorInfo& info){
+    switch(info.type){
+    case opPreUnitary:
+      return os<<"_ "<<info.func;
+    case opPostUnitary:
+      return os<<info.func<<" _";
+    case opBinary:
+      return os<<"_ "<<info.func<<" _";
+    default:
+      return os<<"Operator type unkown";
+    }
+  }
+}

+ 694 - 0
interpreter.hpp

@@ -0,0 +1,694 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#ifndef INTERPRETER_HPP
+#define INTERPRETER_HPP
+
+#include <iostream>
+#include <deque>
+#include <map>
+#include <list>
+#include <vector>
+#include <dlfcn.h>
+#include <initializer_list>
+#include <cstdint>
+#include "dictionnary.hpp"
+#include "kernel.hpp"
+
+using namespace std;
+
+namespace Gomu{
+
+  //*************
+  //* Constants *
+  //*************
+
+  static const int assignement_precedence_level=98;
+  static const int max_precedence_level=99;
+  static const size_t max_nodes_number=1024;
+  static const size_t max_arguments_number=8;
+
+  //**********************
+  //* Early declarations *
+  //**********************
+  
+  class Completion;
+  class Context;
+  class ContextualFunction;
+  class Function;
+  class Node;
+  class Interpreter;
+  class OperatorInfo; 
+  class Symbol;
+  
+  //************
+  //* Typedefs *
+  //************
+  
+  typedef Value (*CFunc0)(Context&);
+  typedef Value (*CFunc1)(Context&,Value&);
+  typedef Value (*CFunc2)(Context&,Value&,Value&);
+
+  typedef void* (*Func1)(void*);
+
+  typedef const initializer_list<string>& string_list;
+  
+
+  //*********************
+  //* Enumeration types *
+  //*********************
+  
+  //! Enumeration of bracket types
+  typedef enum{
+    bCurly,
+    bRound,
+    bSquare
+  } BracketType;
+
+  //! Enumeration of expression types
+  typedef enum{
+    expArray,
+    expArrayGet,
+    expArraySet,
+    expFunction,
+    expMemberFunction,
+    expLeaf,
+    expTuple,
+    expSet
+  } ExpressionType;
+
+  //! Enumeration of token types
+  typedef enum{
+    tCloseBracket,
+    tComma,
+    tDot,
+    tEnd,
+    tInteger,
+    tName,
+    tOpenBracket,
+    tOperator,
+    tString,
+    tUnkown
+  } TokenType;
+
+  //! Enumeration of operator types
+  typedef enum{
+    opBinary,
+    opPreUnitary,
+    opPostUnitary
+  } OperatorType;
+
+  
+  //**********************
+  //* Class declarations *
+  //**********************
+
+  //------------
+  // Completion 
+  //------------
+  
+  //! A class for completion information
+  class Completion{
+    
+  public:
+    
+    //! Prefix to add to the word for looking symbol, used in case of a member call
+    //! By example if s is ot type string then a.<tab> has prefix 'String.'
+    string prefix;
+    //! The word to complete
+    string word;
+    //! Type of the class for a member call, nullptr otherwise
+    Type* type;
+    //! An iterator for the context's symbols
+    map<string,Symbol>::iterator it;
+  };
+
+  //---------
+  // Context
+  //---------
+  
+  //! A class for the interpretation context
+  class Context{
+  public:
+    //! Map for association name <-> symbol
+    map<string,Symbol> symbols;
+    
+    //! The unique constructor
+    Context();
+
+    //! Add a symbol for a contextual function
+    //! \param name name of the symbol
+    //! \param args list of the argument type strings
+    //! \param ptr the contextual function pointer
+    void add_contextual_function(string ret,string name,string_list args,void* ptr);
+    
+   //! Add a symbol for a function 
+    //! \param ret return type string
+    //! \param name name of the symbol
+    //! \param args list of the argument type strings
+    //! \param ptr the standard function pointer
+    void add_function(string ret,string name,string_list args,void* ptr);
+    
+    //! Add a member function to the class given by the first argument
+    //! \param ret return type string
+    //! \param name name of the symbol
+    //! \param args list of the argument type strings
+    //! \param ptr the standard function pointer
+    void add_member_function(string ret,string name,string_list args,void* ptr);
+
+    //! Add a symbol named name
+    //! \param name name of the symbol
+    //! \param type type of the symbol
+    //! \param ptr pointer to the data
+    //! \param lock specify if the symbol is locked or not
+    //! \return Return the new added symbol
+    Symbol* add_symbol(string name,Type* type,void* ptr,bool lock=true);
+    
+    //! Test if we can add a symbol named name
+    //! \param name the symbol name
+    //! \return true if we can add the symbol false otherwise
+    bool can_add(string name);
+    
+    //! Test if we can add a contextual function called name
+    //! \param name function name
+    //! \param targs type of function arguments
+    //! \return true if we can add the symbol false otherwise
+    bool can_add_contextual_function(string name,string_list targs);
+    
+    //! Test if we can add a function called name
+    //! \param name function name
+    //! \param targs type of function arguments
+    //! \return true if we can add the symbol false otherwise
+    bool can_add_function(string name,string_list targs);
+
+    //! Test if we can add a member function called name
+    //! \param name function name
+    //! \param targs type of function arguments
+    //! \return true if we can add the symbol false otherwise
+    bool can_add_member_function(string name,string_list targs);
+
+    //! Evaluate an array node
+    //! \param size size of the array
+    //! \param current the node of the array
+    //! \param nodes array of all nodes
+    void eval_array(size_t size,Node& current,Node* nodes);
+
+    //! Evaluate a contextual function
+    //! \param contextual pointer to a contextual function
+    //! \param args arguments of the function call
+    //! \param nargs number of argument for the function call
+    //! \return value returned by the contextual function
+    Value eval_contextual_function(ContextualFunction* contextual,Value** args,size_t nargs);
+
+     //! Evaluate a function
+    //! \param function pointer to a function
+    //! \param args arguments of the function call
+    //! \param nargs number of argument for the function call
+    //! \return value returned by the function
+    Value eval_function(Function* function,Value** args,size_t nargs);
+
+    //! Evaluate a function node (contextual or not)
+    //! \param current the node of the function to evaluate
+    //! \param nodes array of all nodes
+    //! \param size size of the array
+    void eval_function(Node& current,Node* nodes);
+    
+    //! Evaluate a function given by a symbol (contextual or not)
+    //! \param symbol symbol for the function
+    //! \param args arguments of the function call
+    //! \param nargs number of argument for the function call
+    //! \return value returned by the function
+    Value eval_function(Symbol* symbol,Value** args,size_t nargs);
+    
+    //! Evaluate a member function node (contextual or not)
+    //! \param current the node of the function to evaluate
+    //! \param nodes array of all nodes
+    //! \param size size of the array
+    void eval_member_function(Node& current,Node* nodes);
+        
+    //! Evaluate a set node
+    //! \param size size of the set
+    //! \param current the node of the set
+    //! \param nodes array of all nodes
+    void eval_set(size_t size,Node& current,Node* nodes);
+ 
+    //! Evaluate a tuple node
+    //! \param size size of the tuple
+    //! \param current the node of the tuple
+    //! \param nodes array of all nodes
+    void eval_tuple(size_t size,Node& current,Node* nodes);
+
+    //! Return the signature of a string list of arguments
+    //! \param args the string list
+    //! \return The corresponding signature
+    Signature get_signature(string_list args);
+
+    //! Return the symbol named name
+    //! \param name name to find
+    //! \return Symbol corresponding to name if it exists, nullptr otherwise
+    Symbol* get_symbol(string name);
+    
+    //! Return the symbol named name in class type
+    //! \param ctype type to lookup
+    //! \param name name to find
+    //! \return Symbol corresponding to name if it exists, nullptr otherwise
+    Symbol* get_symbol(Type* ctype,string name);
+    
+    //! Return the type named name
+    //! \param name name to find
+    //! \return Type corresponding to name if it exists, nullptr otherwise
+    Type* get_type(string name);
+
+    //! Load the module name
+    //! \param name of the module to load
+    void load_module(string name);
+
+    //! Load functions of a module
+    //! \param the module to load
+    //! \param src specify the src to load 0:functions 1:member_functions 2:contextual_functions 
+    void load_module_functions(Module* module,int src);
+
+    //! Unload a function
+    //! \param name the name of the function to delete
+    //! \param args the string list of the function arguments
+    void unload_function(string name,string_list args);
+
+    //! Unload a module
+    //! \param module the module to unload
+    void unload_module(Module* module);
+
+    //! Unload module functions
+    //! \param module the module containint functions to unload
+    void unload_module_functions(Module* module);
+
+    //! Unload a symbol
+    //! \param name of the symbol to delete
+    void unload_symbol(string name);
+    
+    //! Unload a type
+    //! \param type the type tu unload
+    void unload_type(Type* type);
+
+    //! Reload a module
+    //! \param module the module to reload
+    void reload_module(Module* module);
+
+    //! Set arguments of a function node
+    //! \param current node of the function to consider
+    //! \param nodes an array of all nodes
+    //! \args an array of Value* to store the arguments of the function
+    //! \return number of arguments of the function call
+    size_t set_arguments(Node& current,Node* nodes,Value** args);
+  };
+
+  //--------------------
+  // ContextualFunction
+  //--------------------
+
+  //! A class for contextual function
+  class ContextualFunction{
+      
+  public:
+      
+    //! Return type of the contextual function
+    Type* tr;
+    //! Pointer to the contextual function
+    void* ptr;
+    //! Signature of the contextual function
+    Signature signature;
+
+    //! The unique constructor
+    ContextualFunction(Type* tr,const Signature& signature,void* ptr);
+    
+    //! Eval the contextual function
+    //! \param args function call arguments
+    //! \papam number of arguments of the function call
+    //! \param context the context of the contextual function evaluation
+    //! \return The returned value
+    Value eval(Value* args[8],size_t nargs,Context& context);
+  };
+
+  //----------
+  // Function
+  //----------
+
+  //! A class for function
+  
+  class Function{
+    
+  public:
+    
+    //! Return type of the function
+    Type* tr;
+    //! Signature of the function
+    Signature signature;
+    //! Pointer to the function
+    void* ptr;
+
+    //! The unique constructor
+    Function(Type* tr,const Signature& signature,void* ptr);
+
+    //! Evaluate the function
+    //! \param args function call arguments
+    //! \papam number of arguments of the function call
+    //! \return The returned value
+    Value eval(Value* args[8],size_t nargs);
+  };
+
+  //------
+  // Node
+  //------
+
+  //! Class for expression node
+  class Node{
+    
+  public:
+    
+    //! Token type of the node
+    TokenType tokenType;
+    //! Expression type of the node
+    ExpressionType expressionType;
+    //! Position in the command of the fisrt letter of the substring representing the node
+    size_t pos;
+    //! Substring of the command representing the node
+    string str;
+    union{
+      //! Bracket type of the node (if any)
+      BracketType bracketType;
+      //! Operator information of the node (if any)
+      OperatorInfo* operatorInfo;
+    };
+    //! Value of the node after evaluation
+    Value value;
+    //! Index of the node son
+    slong son;
+    //! Index of the node brother
+    slong bro;
+    //! Specify if the node can be erased or not
+    bool erase;
+  };
+  
+  //-------------
+  // Interpreter
+  //-------------
+
+  //! A class for the interpreter
+  class Interpreter{
+    
+  protected:
+    
+    //! Information about completion
+    Completion completion;
+    //! Number of nodes in the expression
+    size_t nodes_number;
+    //! An array of nodes describing the expression obtained from the command string
+    Node nodes[max_nodes_number];
+    //! The dictionnary of all defined operator
+    Dictionnary<OperatorInfo> operator_tree;
+    
+  public:
+    
+    //! The unique constructor
+    Interpreter();
+    
+    //! Add an operator to the operator's dictionnary
+    //! \param op operator identification (=,!=,...)
+    //! \param name name of the operator function to call
+    //! \param type operator type (binary,preunitary,postunitary)
+    //! \pram p operator precedence
+    void add_operator(const string& op,const string& name,OperatorType type,int p);
+
+    //! Function called during completion. It return a non empty string for each
+    //! possible coompleted word and an empty one if there is non more possibiliy.
+    //! \param cmd command containing the word to complete
+    //! \param word the word to complete
+    //! \param pos position of the cursor when completion has been called
+    //! \param state state of the completion process 0 for the first call and >0 for the others
+    //! \param context context of the future command evaluation
+    //! \return a possible completion or ""
+    string complete(const string& cmd,const string& word,size_t pos,int state,Context& context);
+
+    //! Construct a sequence from an expression
+    //! \param first position of the first node of the sequence
+    //! \param last position of the last node of the sequence
+    //! \return size of the sequence
+    size_t construct_sequence(size_t& first,size_t last);
+
+    //! Construct the expression tree of the command from an array of tokens
+    //! \param first position of the first token of the experssion
+    //! \param last position of the last token of the expession
+    //! \param precedence_level current precedence level
+    //! \return position of the root of the constructed tree
+    size_t construct_tree(size_t& first,size_t last,int precedence_level);
+
+    //! Display an expression tree
+    //! \param os the output stream for display
+    //! \param i position of the tree root
+    void display_expression_tree(ostream& os,size_t i) const;
+
+    //! Display a token
+    //! \param os the output stream for display
+    //! \parap i index of the token to diplay
+    void display_token(ostream& os,size_t i) const;
+
+    //! Display the token array
+    //! \param os the output stream for display
+    void display_tokens(ostream& os) const;
+    
+    //! Evaluate a command
+    //! \param cmd command to evaluate
+    //! \param context context of the evaluation
+    void eval(string cmd,Context& context);
+
+    //! Evaluate an expression
+    //! \param pos indice of the expression to evaluate
+    //! \param context context of the evaluation
+    void eval_expression(size_t pos,Context& context);
+
+    //! Get an integer from a substring of a command
+    //! \param pos indice of the substring of the command representing the integer
+    //! \param cmd command
+    //! \return pointer to the corresponding integer
+    fmpz* get_integer(size_t& pos,const string& cmd);
+
+    //! Get a name from a substring of a command
+    //! \param pos indice of the substring of the command representing the name
+    //! \param cmd command
+    //! \return name
+    string get_name(size_t& pos,const string& cmd);
+
+    //! Try to get an operator from a substring of a command
+    //! \param pos indice of the substring of the command representing the operator
+    //! \param cmd command
+    //! \return A pointer to the new created operator information, nullptr otherwise 
+    OperatorInfo* get_operator(size_t& pos,const string& cmd);
+
+    //! Get a string from a substring of a command
+    //! \param pos indice of the substring of the command representing the string
+    //! \param cmd command
+    //! \return string
+    string get_string(size_t& pos,const string& cmd);
+    
+    //! Set node to be the token of command at position pos
+    //! \param node destination node of the token
+    //! \param pos position of the substring representing the token in comman
+    //! \param command command to evaluate
+    void set_token(Node& node,size_t& pos,const string& cmd);
+
+    //! Create an array of tokens from a command
+    //! \param command command to evaluate
+    void split_to_tokens(const string& cmd);
+  };
+
+  //--------------
+  // MetaFunction
+  //--------------
+
+  //! Class for meta function (used in case of overloaded functions)
+  class MetaFunction{
+  public:
+    //! Fullname of overloaded functions
+    set<string> functions;
+  };
+   
+  //--------------
+  // OperatorInfo
+  //--------------
+
+  //! Class for operator informtation
+  class OperatorInfo{
+    
+  public:
+
+    //! Name of the operator function to call
+    string func;
+    //! Type of the operator (unary,...)
+    OperatorType type;
+    //! Precedence of the operator
+    int precedence;
+    //! The unique constructor
+    OperatorInfo(string func,OperatorType t,int p);
+  };
+  
+  //--------
+  // Symbol
+  //--------
+  
+  //! Class for context symbol
+  class Symbol:public Value{
+  public:
+    //! Specify if the symbol is hidden in completion
+    bool hide;
+    //! Specify if the symbol is locked (roughlt created by C++ call)
+    bool locked;
+    //! Name of the symbol
+    string name;
+    //! The unique constructor
+    Symbol();
+  };
+
+  //***********************
+  //* Auxiliary functions *
+  //***********************
+
+  //! Copy the value src to the value dst
+  //! \param dst pointer to the destination value
+  //! \param src pointer to the source value
+  void copy_value(Value* dst,Value* src);
+
+  //! Get the fullname of a function
+  //! \param name short name of the function
+  //! \param args string array of argument type
+  //! \return fullname of the function
+  string function_fullname(string name,string_list args);
+
+  //! Get the fullname of a function call
+  //! \param name short name of the function
+  //! \param args arguments of function call
+  //! \param nargs number of arguments of the function call
+  //! \return fullname of the function
+  string function_fullname(string name,Value** args,size_t nargs);
+
+  //! Get the fullname of a function
+  //! \param name short name of the function
+  //! \param signature signature of the function
+  //! \return fullname of the function
+  string function_fullname(string name,const Signature& signature);
+
+  //! Get the expression type of hthe sequence corresponding to the bracket type t
+  //! \param t a bracket type
+  //! \return Expression type cooresponding to t
+  ExpressionType get_delimiter_expression_type(BracketType t);
+
+  //! Set a signature for a list of argument type string
+  //! \param signature signature to fullfill
+  //! \param args list of argument type string
+  void set_signature(Signature& signature,string_list args);
+  
+  ostream& operator<<(ostream& os,const BracketType& bt);
+  ostream& operator<<(ostream& os,const OperatorInfo& oi);
+  
+  //**********************
+  //* Inline definitions *
+  //**********************
+ 
+  //---------
+  // Context
+  //---------
+  
+  inline void
+  Context::add_contextual_function(string ret,string name,string_list args,void* ptr){
+    Signature signature=get_signature(args);
+    Type* tr=get_type(ret);
+    add_symbol(name,type_contextual_function,(void*)(new ContextualFunction(tr,signature,ptr))); 
+  }
+
+  inline  bool
+  Context::can_add(string name){
+    Symbol* symbol=get_symbol(name);
+    return (symbol==nullptr or not symbol->locked); 
+  }
+  
+  inline bool
+  Context::can_add_contextual_function(string name,string_list targs){
+    return can_add(name);
+  }
+
+  inline Symbol*
+  Context::get_symbol(Type* ctype,string name){
+    return get_symbol(ctype->name+"."+name);
+  }
+
+  inline void
+  Context::unload_symbol(string name){
+    symbols.erase(name);
+  }
+  
+  //--------------------
+  // ContextualFunction
+  //--------------------
+  
+  inline
+  ContextualFunction::ContextualFunction(Type* t,const Signature& s,void* p):tr(t),signature(s),ptr(p){
+  }
+
+  //----------
+  // Function
+  //----------
+  
+  inline
+  Function::Function(Type* t,const Signature& s,void* p):tr(t),signature(s),ptr(p){
+  }
+
+   //-------------
+  // Interpreter
+  //-------------
+  
+  inline
+  Interpreter::Interpreter(){}
+
+  inline OperatorInfo*
+  Interpreter::get_operator(size_t& pos,const string& cmd){return operator_tree.find_at(pos,cmd);}
+
+  //--------
+  // Symbol
+  //--------
+  
+  inline
+  Symbol::Symbol():Value(),locked(false){
+  }
+
+  //--------------
+  // OperatorInfo
+  //--------------
+  
+  inline
+  OperatorInfo::OperatorInfo(string str,OperatorType t,int p):func(str),type(t),precedence(p){}
+
+  //---------------------
+  // Auxiliray functions
+  //---------------------
+  
+  inline void copyValue(Value* dst,Value* src){
+    dst->type=src->type;
+    dst->ptr=src->type->copy(src->ptr);
+  }
+}
+
+#endif

+ 387 - 0
kernel.cpp

@@ -0,0 +1,387 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#include "kernel.hpp"
+#include "interpreter.hpp"
+
+namespace Gomu{
+
+  //*********
+  //* Array *
+  //*********
+
+  string
+  array_disp(void* v){
+    string str;
+    ArrayValue* arr=(ArrayValue*)v;
+    if(arr->size==0)
+      return "[]";
+    str="[";
+    str+=arr->type->disp(arr->tab[0]);
+    for(size_t i=1;i<arr->size;++i){
+      str+=", ";
+      str+=arr->type->disp(arr->tab[i]);
+    }
+    str+=']';
+    return str;
+  }
+
+  void
+  array_del(void* v){
+    ArrayValue* arr=(ArrayValue*)v;
+   Type* type=arr->type;
+    for(size_t i=0;i<arr->size;++i){
+      type->del(arr->tab[i]);
+    }
+    delete[] arr->tab;
+    delete arr;
+  }
+
+  void*
+  array_copy(void* v){
+    ArrayValue* arr=(ArrayValue*)v;
+    size_t size=arr->size;
+    ArrayValue* res=new ArrayValue(size);
+    Type* type=res->type=arr->type;
+    res->tab=new void*[size];
+    for(size_t i=0;i<size;++i){
+      res->tab[i]=type->copy(arr->tab[i]);
+    }
+    return (void*)res;
+  }
+
+  int
+  array_comp(void* v1,void* v2){
+    ArrayValue* arr1=(ArrayValue*)v1;
+    ArrayValue* arr2=(ArrayValue*)v2;
+    size_t size1=arr1->size;
+    size_t size2=arr2->size;
+    if(size1!=0 and size2!=0){
+      if(arr1->type!=arr2->type) RuntimeError("Types of array mismatch for comparison");
+    }
+    if(size1==size2){
+      Type* type=arr1->type;
+      for(size_t i=0;i<size1;++i){
+	int c=type->comp(arr1->tab[i],arr2->tab[i]);
+	if(c!=0) return c;
+      }
+      return 0;
+    }
+    if(size1<size2) return -1;
+    return 1;
+  }
+
+  
+  //***********
+  //* Boolean *
+  //***********
+
+  string
+  boolean_disp(void* v){
+    if((*(char*)v)==1)
+      return "\033[35mtrue\033[0m";
+    else
+      return "\033[35mtrue\033[0m";
+   }
+
+  int
+  boolean_comp(void* u,void* v){
+    char a=*(char*)u;
+    char b=*(char*)v;
+    if(a==b) return 0;
+    if(a<b) return 1;
+    return -1;
+  }
+
+  //**********************
+  //* ContextualFunction *
+  //**********************
+
+  string
+  contextual_function_disp(void* v){
+    ContextualFunction* f=(ContextualFunction*)v;
+    return disp_signature(f->signature)+" -> "+type_disp(f->tr);
+  }
+  
+  //************
+  //* Function *
+  //************
+
+  string
+  function_disp(void* val){
+    Function* function=(Function*)(val);
+    return disp_signature(function->signature)+" -> "+type_disp(function->tr);
+  }
+  
+  //***********
+  //* Integer *
+  //***********
+
+  string
+  integer_disp(void* v){
+    char* disp=fmpz_get_str(NULL,10,(fmpz*)v);  
+    string res="\033[34m";
+    res+=disp;
+    res+="\033[0m";
+    free(disp);
+    return res;
+  }
+
+  void*
+  integer_copy(void* v){
+    fmpz* res=new fmpz;
+    fmpz_init_set(res,(fmpz*)v);
+    return res;
+  }
+
+  //****************
+  //* MetaFunction *
+  //****************
+  
+   string
+   meta_function_disp(void* v){
+    MetaFunction* meta=(MetaFunction*)v;
+    auto it=meta->functions.begin();
+    string str=*it;
+    for(++it;it!=meta->functions.end();++it){
+      str+='\n';
+      str+=*it;
+    }
+    return str;
+  }
+
+  //*******
+  //* Set *
+  //*******
+
+  string
+  set_disp(void* v){
+    string str;
+    SetValue* setval=(SetValue*)v;
+    Type* type=setval->data.key_comp().type;
+    if(setval->data.empty()) return "{}";
+    str="{";
+    auto it=setval->data.begin();
+    str+=type->disp(*it);
+    for(++it;it!=setval->data.end();++it){
+      str+=',';
+      str+=type->disp(*it);
+    }
+    str+='}';
+    return str;
+  }
+
+  void
+  set_del(void* v){
+    SetValue* setval=(SetValue*)v;
+    Type* type=setval->data.key_comp().type;
+    for(auto it=setval->data.begin();it!=setval->data.end();++it){
+      type->del(*it);
+    }
+    delete setval;
+  }
+
+  void*
+  set_copy(void* v){
+    SetValue* setval=(SetValue*)v;
+    Type* type=setval->data.key_comp().type;
+    SetValue* setres=new SetValue(type);
+    for(auto it=setval->data.begin();it!=setval->data.end();++it){
+      setres->data.insert(type->copy(*it));
+    }
+    return setres;
+  }
+
+  int
+  set_comp(void* v1,void* v2){
+    SetValue* set1=(SetValue*)v1;
+    SetValue* set2=(SetValue*)v2;
+    Type* type=set1->data.key_comp().type;
+    if(type!=set2->data.key_comp().type) RuntimeError("Recurssive Types mismatch in set");
+    if(set1->data.size()==set2->data.size()){
+      auto it1=set1->data.begin();
+      auto it2=set2->data.begin();
+      for(;it1!=set1->data.end();++it1){
+	int c=type->comp(*it1,*it2);
+	if(c!=0) return c;
+      }
+      return 0;
+    }
+    else{
+      if(set1->data.size()<set2->data.size()) return -1;
+      return 1;
+    }
+  }
+
+  //**********
+  //* String *
+  //**********
+
+  int
+  string_comp(void* u,void* v){
+    string& a=*(string*)u;
+    string& b=*(string*)v;
+    if(a==b) return 0;
+    if(a<b) return -1;
+    return 1;
+  }
+
+  //*********
+  //* Tuple *
+  //*********
+
+  string
+  tuple_disp(void* v){
+    TupleValue* t=(TupleValue*)v;
+    if(t->size==0) return "()";
+    string str="(";
+    str+=t->tab[0].disp();
+    for(size_t i=1;i<t->size;++i){
+      str+=',';
+      str+=t->tab[i].disp();
+    }
+    return str+')';
+  }
+
+  void
+  tuple_del(void* v){
+    TupleValue* t=(TupleValue*)v;
+    for(size_t i=0;i<t->size;++i){
+      t->tab[i].del();
+    }
+  }
+  
+  void*
+  tuple_copy(void* v){
+    TupleValue* t=(TupleValue*)v;
+    TupleValue* res=new TupleValue(t->size);
+    for(size_t i=0;i<t->size;++i){
+      res->tab[i]=t->tab[i].copy();
+    }
+    return res;
+  }
+
+  int
+  tuple_comp(void* v1,void *v2){
+    TupleValue* t1=(TupleValue*)v1;
+    TupleValue* t2=(TupleValue*)v2;
+    if(t1->size==t2->size){
+      for(size_t i=0;i<t1->size;++i){
+	if(t1->tab[i].type==t2->tab[i].type){
+	  Type* type=t1->tab[i].type;
+	  int c=type->comp(t1->tab[i].ptr,t2->tab[i].ptr);
+	  if(c!=0) return c;
+	}
+	else{
+	  if(t1->tab[i].type->name<t2->tab[i].type->name) return -1;
+	  return 1;
+	}
+      }
+    }
+    else{
+      if(t1->size<t2->size) return -1;
+      return 1;
+    }
+  }
+
+  //********
+  //* Type *
+  //********
+ 
+  int
+  type_comp(void* T1,void* T2){
+    string s1=((Type*)T1)->name;
+    string s2=((Type*)T2)->name;
+    return string_comp(&s1,&s2);
+  }
+  
+  //***********************
+  //* Auxialiry functions *
+  //***********************
+
+    //----------------------------------
+  // disp_signature(const Signature&)
+  //----------------------------------
+  
+  string
+  disp_signature(const Signature& s){
+    if(s.size()==0) return "()";
+    string str="(";
+    str+=type_disp(s[0]);
+    for(uint32_t i=1;i<s.size();++i){
+      str+=','+type_disp(s[i]);
+    }
+    return str+')';
+  }
+    
+  //------------------------------------
+  // init_kernel(Context&,Interpreter&)
+  //------------------------------------
+  
+  void init_kernel(Context& context,Interpreter& interpreter){
+    //Operators
+    interpreter.add_operator("=","operator=",opBinary,15);
+    interpreter.add_operator("<","operator<",opBinary,8);
+    interpreter.add_operator(">","operator>",opBinary,8);
+    interpreter.add_operator("<=","operator<=",opBinary,8);
+    interpreter.add_operator(">=","operator>=",opBinary,8);
+    interpreter.add_operator("==","operator==",opBinary,8);
+    interpreter.add_operator("!=","operator!=",opBinary,8);
+    interpreter.add_operator("+","operator+",opBinary,4);
+    interpreter.add_operator("-","operator-",opBinary,4);
+    interpreter.add_operator("*","operator*",opBinary,3);
+    interpreter.add_operator("::","operator::",opBinary,1);
+    interpreter.add_operator("!","factorial",opPostUnitary,2);
+    context.add_contextual_function("Void","load_module",{"String"},(void*)load_module);
+    context.add_contextual_function("Void","unload",{"Module"},(void*)unload);
+    context.add_contextual_function("Void","reload",{"Module"},(void*)reload);
+  }
+  
+  //-----------------------
+  // load(Context&,Value&)
+  //-----------------------
+  
+  Value
+  load_module(Context& context,Value& v){
+    context.load_module(*((string*)(v.eval()->ptr)));
+    return Value(type_void,nullptr); 
+  }
+
+  //-------------------------
+  // unload(Context&,Value&)
+  //-------------------------
+  
+  Value
+  unload(Context& context,Value& v){
+    context.unload_module((Module*)(v.ptr));
+    return Value(type_void,nullptr);
+  }
+
+  //-------------------------
+  // reload(Context&,Value&)
+  //-------------------------
+  
+  Value
+  reload(Context& context,Value& v){
+    context.reload_module((Module*)(v.ptr));
+    return Value(type_void,nullptr);
+  }
+}
+
+

+ 318 - 0
kernel.hpp

@@ -0,0 +1,318 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#ifndef KERNEL_HPP
+#define KERNEL_HPP
+
+#include "module.hpp"
+#include <set>
+
+namespace Gomu{
+
+  //************
+  //* Typedefs *
+  //************
+  
+  typedef Array<Type*> Signature;
+
+  //***********************
+  //* Auxiliary functions *
+  //***********************
+  
+  //-------
+  // Array
+  //-------
+  
+  string array_disp(void*);
+  void array_del(void*);
+  void* array_copy(void*);
+  int array_comp(void*,void*);
+  
+  //---------
+  // Boolean
+  //---------
+  
+  string boolean_disp(void*);
+  void boolean_del(void*);
+  void* boolean_copy(void*);
+  int boolean_comp(void*,void*);
+  
+  //---------
+  // Context
+  //---------
+
+  string context_disp(void*);
+  void context_del(void*);
+  void* context_copy(void*);
+  int context_comp(void*,void*);
+  
+  //--------------------
+  // ContextualFunction
+  //--------------------
+
+  string contextual_function_disp(void*);
+  void contextual_function_del(void*);
+  void* contextual_function_copy(void*);
+  int contextual_function_comp(void*,void*);
+  
+  //----------
+  // Function
+  //----------
+  
+  string function_disp(void*);
+  void function_del(void*);
+  void* function_copy(void*);
+  int function_comp(void*,void*);
+  
+  //---------
+  // Integer
+  //---------
+  
+  string integer_disp(void*);
+  void integer_del(void*);
+  void* integer_copy(void*);
+  int integer_comp(void*,void*);
+  
+  //--------------
+  // MetaFunction
+  //--------------
+  
+  string meta_function_disp(void*);
+  void meta_function_del(void*);
+  void* meta_function_copy(void*);
+  int meta_function_comp(void*,void*);
+  
+  //--------
+  // Module
+  //--------
+  
+  string module_disp(void*);
+  void module_del(void*);
+  void* module_copy(void*);
+  int module_comp(void*,void*);
+
+  //-----
+  // Set
+  //-----
+  
+  string set_disp(void*);
+  void set_del(void*);
+  void* set_copy(void*);
+  int set_comp(void*,void*);
+  
+  //--------
+  // String
+  //--------
+  
+  string string_disp(void*);
+  void string_del(void*);
+  void* string_copy(void*);
+  int string_comp(void*,void*);
+  
+  //-------
+  // Tuple
+  //-------
+  
+  string tuple_disp(void*);
+  void tuple_del(void*);
+  void* tuple_copy(void*);
+  int tuple_comp(void*,void*);
+  
+  //------
+  // Type
+  //------
+  
+  string type_disp(void*);
+  void type_del(void*);
+  void* type_copy(void*);
+  int type_comp(void*,void*);
+  //  Value* getType(Value*,Context*);
+
+  //------
+  // Void
+  //------
+  
+  string void_disp(void*);
+  void void_del(void*);
+  void* void_copy(void*);
+  int void_comp(void*,void*);
+  
+  //***********************
+  //* Auxiliary functions *
+  //***********************
+
+  //! Init the kernel
+  //! \param context evaluation context
+  //! \param interpreter the interpreter used for evaluation
+  void init_kernel(Context& context,Interpreter& interpreter);
+
+  //! Display Signature signature
+  string disp_signature(const Signature& signaure);
+
+  //! Load a module
+  Value load_module(Context& context,Value& v);
+
+  //! Unload a module
+  Value unload(Context& context,Value& v);
+
+  //! Reload a module
+  Value reload(Context& context,Value& v);
+  
+  //***********************
+  //* Inline declarations *
+  //***********************
+
+  //---------
+  // Boolean
+  //----------
+  inline void
+  boolean_del(void* v){delete (char*)v;}
+  
+  inline void*
+  boolean_copy(void* v){return new char(*(char*)v);}
+
+  //---------
+  // Context
+  //---------
+    
+  inline string
+  context_disp(void*){return "Context";}
+
+  inline void
+  context_del(void*){}
+
+  inline void*
+  context_copy(void*){Bug("Not yet implemented");}
+
+  inline int
+  context_comp(void*,void*){Bug("Not yet implemented");}
+
+  //--------------------
+  // ContextualFunction
+  //--------------------
+  
+  inline void
+  contextual_function_del(void*){Bug("Not yet implemented");}
+  
+  inline void*
+  contextual_function_copy(void*){Bug("Not yet implemented");}
+  
+  inline int
+  contextual_function_comp(void*,void*){Bug("Not yet implemented");}
+
+  //----------
+  // Function
+  //----------
+  
+  inline void
+  function_del(void*){Bug("Not yet implemented");}
+
+  inline void*
+  function_copy(void*){Bug("Not yet implemented");}
+
+  inline int
+  function_comp(void*,void*){Bug("Not yet implemented");}
+  
+  //---------
+  // Integer
+  //---------
+ 
+  inline void
+  integer_del(void* v){fmpz_clear((fmpz*)v);}
+
+  inline int
+  integer_comp(void* v1,void* v2){return fmpz_cmp((fmpz*)v1,(fmpz*)v2);}
+  
+  //--------------
+  // MetaFunction
+  //--------------
+
+  inline void
+  meta_function_del(void*){}
+
+  inline void*
+  meta_function_copy(void*){Bug("Not yet implemented");}
+  
+  inline int
+  meta_function_comp(void*,void*){Bug("Not yet implemented");}
+
+  //--------
+  // Module
+  //--------
+  
+  inline void 
+  module_del(void* v){delete (Module*)(v);}
+
+  inline void*
+  module_copy(void*){Bug("Not yet implemented");}
+
+  inline string
+  module_disp(void*){return "module";}
+
+  inline int
+  module_comp(void*,void*){Bug("Not yet implemented");}
+
+  //--------
+  // String
+  //--------
+
+  inline string
+  string_disp(void* v){
+    return "\033[32m"+*(string*)v+"\033[0m";
+  }
+
+  inline void
+  string_del(void* v){delete (string*)v;}
+
+  inline void*
+  string_copy(void* v){return new string(*(string*)v);}
+
+  //------
+  // Type
+  //------
+
+  
+  inline string
+  type_disp(void* T){
+    return "\033[1;32m"+((Type*)T)->name+"\033[0m";
+  }
+  inline void
+  type_del(void*){}
+
+  inline void*
+  type_copy(void*){Bug("Not yet implemented");}
+
+  //------
+  // Void
+  //------
+
+  inline string
+  void_disp(void*){return "";}
+
+  inline void
+  void_del(void*){}
+
+  inline int
+  void_comp(void*,void*){return 0;}
+
+  inline void*
+  void_copy(void*){return nullptr;}
+
+}
+#endif

+ 79 - 0
main.cpp

@@ -0,0 +1,79 @@
+#include <iostream>
+#include <cstring>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <pthread.h>
+#include "interpreter.hpp"
+//#include "modules/base.hpp"
+//#include "modules/permutations.hpp"
+//#include "modules/matrix.hpp"
+//#include "modules/combinatorics.hpp"
+//#include "maths/polynomial.hpp"
+ 
+ 
+using namespace std;
+using namespace Gomu;
+ 
+static Context* completionContext;
+static size_t completionPos;
+static string completionString;
+static Interpreter* completionInterpreter;
+static char** completion(const char* str,int start,int end);
+static char* completionGenerator(const char* str,int state); 
+ 
+int main(){
+  Context context;
+  Interpreter interpreter;
+  completionContext=&context;
+  completionInterpreter=&interpreter;
+  //  lexer.setContext(context);*/
+  try{
+    init_kernel(context,interpreter);
+  }
+  catch(Error err){
+    err.disp(cout,"");
+  }
+  rl_basic_word_break_characters=(char*)" .,;:()[]{}=+-*<>/#@%$!?";
+    // rl_completion_suppress_append=1;
+     
+    rl_completion_entry_function=completionGenerator;
+    rl_filename_completion_desired=0;
+    rl_attempted_completion_function = completion;
+    string cmd;
+    char* c_cmd;
+    while((c_cmd = readline("> "))!=NULL){
+        //enable autocomplete
+        rl_bind_key('\t',rl_complete);
+        cmd=c_cmd;
+        free(c_cmd);
+        if(cmd.compare("quit")==0)
+            break;
+	interpreter.eval(cmd,context);
+        add_history(cmd.c_str());
+    }
+  return 0;
+}
+ 
+static char** completion(const char* str,int beg,int pos){
+    completionPos=pos;
+    //prevent adding extra character
+    rl_completion_suppress_append=1;
+    return rl_completion_matches(str,completionGenerator);
+}
+ 
+static char* completionGenerator(const char* str,int state){
+    char* res=new char[1024];
+    string comp;
+    try{
+      comp=completionInterpreter->complete(string(rl_line_buffer),string(str),completionPos,state,*completionContext);
+    }
+    catch(Error& err){
+      return nullptr;
+    }
+    if(comp.empty()){
+        rl_filename_completion_desired=0;
+        //rl_bind_key('\t',rl_abort);
+        return nullptr;
+    }
+    return strcpy(res,comp.c_str());
+}

+ 217 - 0
module.cpp

@@ -0,0 +1,217 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#include "module.hpp"
+
+namespace Gomu{
+
+  //**************
+  //* ArrayValue *
+  //**************
+  
+   ArrayValue::ArrayValue(size_t s){
+    size=s;
+    type=nullptr;
+    if(s==0) tab=nullptr;
+    else tab=new void*[size];
+  }
+
+  //*********
+  //* Error *
+  //*********
+   
+  void
+  Error::disp(ostream& os,const string& cmd) const{
+    switch(type){
+      case errBug:
+      os<<"\033[31mBug\033[0m : "<<msg;
+      os<<" (\033[34m"<<file<<"\033[0m:\033[32m"<<line<<"\033[0m)";
+      return;
+    case errContext:
+      os<<"\033[31mContext error\033[0m : "<<msg;
+      os<<" (\033[34m"<<file<<"\033[0m:\033[32m"<<line<<"\033[0m)";
+      return;
+    case errRuntime:
+      os<<"\033[31mRuntime error\033[0m : "<<msg;
+      return;
+    case errSyntax:
+      os<<"\033[31mSyntax error\033[0m : "<<msg;
+      os<<"(\033[34m"<<file<<"\033[0m:\033[32m"<<line<<"\033[0m)";
+      break;
+    default:
+      os<<"\033[31mError\033[0m : ";
+      break;
+    }
+    os<<endl<<"@ ";
+    if(first>0) os<<cmd.substr(0,first);
+    os<<"\033[32m"<<cmd.substr(first,last-first+1)<<"\033[0m";
+    if(last+1<cmd.length()) os<<cmd.substr(last+1,string::npos);
+    return;
+  }
+  
+  //**********
+  //* Module *
+  //**********
+
+  //------------------
+  // Module::Module()
+  //------------------
+  
+  Module::Module(){
+    types=nullptr;
+    functions=nullptr;
+    member_functions=nullptr;
+    contextual_functions=nullptr;
+  }
+  
+  //---------------------
+  // Module::init(Type*)
+  //---------------------
+  
+  void Module::init(Type* types){
+    size_t i=0;
+    if(types==nullptr) ntype=0;
+    else{
+      while(types[i].disp!=nullptr) ++i;
+      ntype=i;
+      i=0;
+    }
+    if(functions==nullptr) nfunc=0;
+    else{
+      while(functions[i].ptr!=nullptr) ++i;
+      nfunc=i;
+      i=0;
+    }
+    if(member_functions==nullptr) nmfunc=0;
+    else{
+      while(member_functions[i].ptr!=nullptr) ++i;
+      nmfunc=i;
+      i=0;
+    }
+    if(contextual_functions==nullptr) ncfunc=0;
+    else{
+      while(contextual_functions[i].ptr!=nullptr) ++i;
+      ncfunc=i;
+    }
+  }
+  //********
+  //* Type *
+  //********
+  
+  //-------------------------------------------------------
+  // Type::Type(string,DispFunc,DelFunc,CopyFunc,CompFunc)
+  //-------------------------------------------------------
+  
+  Type::Type(string _name,DispFunc _disp,DelFunc _del,CopyFunc _copy,CompFunc _comp){
+    name=_name;
+    disp=_disp;
+    del=_del;
+    copy=_copy;
+    comp=_comp;
+  }
+
+  //-------------------------
+  // Type::Type(const Type&)
+  //-------------------------
+  
+  Type::Type(const Type& t){
+    name=t.name;
+    disp=t.disp;
+    del=t.del;
+    copy=t.copy;
+    comp=t.comp;
+  }
+
+
+  //**************
+  //* TupleValue *
+  //**************
+  
+  TupleValue::TupleValue(size_t s){
+    size=s;
+    tab=(s==0)?nullptr:new Value[s];
+  }
+   
+
+  //*********
+  //* Value *
+  //*********
+
+  //---------------
+  // Value::copy()
+  //---------------
+  
+  Value
+  Value::copy(){
+    Value res;
+    res.type=type;
+    res.ptr=type->copy(ptr);
+    return res;
+  }
+
+  //---------------
+  // Value::disp()
+  //---------------
+  
+  string
+  Value::disp(){
+    if(type==type_symbol) return ((Value*)ptr)->disp();
+    if(ptr!=nullptr and type!=nullptr) return type->disp(ptr);
+    else return "";
+  }
+
+  //***********************
+  //* Auxiliary functions *
+  //***********************
+
+  //------------------
+  // get_slong(void*)
+  //------------------
+  
+  uint64
+  get_slong(void* v){
+    fmpz* z=(fmpz*)v;
+    if(fmpz_fits_si(z)) return fmpz_get_si(z);
+    else  RuntimeError("Integer too huge to fit slong");
+  }
+
+  //------------------
+  // to_boolean(bool)
+  //------------------
+  
+  void*
+  to_boolean(bool b){
+    char* res=new char;
+    *res=(b?1:0);
+    return res;
+  }
+
+  //-------------------
+  // to_integer(slong)
+  //-------------------
+  
+  void*
+  to_integer(slong n){
+    fmpz* z=new fmpz;
+    fmpz_init(z);
+    fmpz_set_si(z,n);
+    return z;
+  }
+
+}

+ 444 - 0
module.hpp

@@ -0,0 +1,444 @@
+/**
+ * This file is part of Gomu.
+ *
+ *  Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
+ *
+ * Gomu is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gomu is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gomu. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#ifndef MODULES_HPP
+#define MODULES_HPP
+
+#include <iostream>
+#include <cstdint>
+#include <map>
+#include <set>
+#include "array.hpp"
+#include "flint/fmpz.h"
+
+using namespace std;
+
+//*****************
+//* Integer types *
+//*****************
+
+typedef uint64_t uint64;
+typedef int64_t int64;
+
+//**********
+//* Macros *
+//**********
+  
+#define FUNC(f) (void*)(f)
+#define CONT_FUNC_SENTINEL {"",{""},nullptr}
+#define FUNC_SENTINEL {"","",{""},nullptr}
+#define TYPE_SENTINEL {"",nullptr,nullptr,nullptr,nullptr}
+
+
+#define SyntaxError(msg,first,last) throw Error(errSyntax,(msg),(first),(last),__FILE__,__LINE__,__PRETTY_FUNCTION__);
+#define Bug(msg) throw Gomu::Error(Gomu::errBug,(msg),0,0,__FILE__,__LINE__,__PRETTY_FUNCTION__);
+#define ContextError(msg) throw Error(errContext,(msg),0,0,__FILE__,__LINE__,__PRETTY_FUNCTION__);
+#define RuntimeError(msg) throw Gomu::Error(Gomu::errRuntime,(msg),0,0,__FILE__,__LINE__,__PRETTY_FUNCTION__);
+namespace Gomu{
+  
+  //*********************
+  //* Early declaration *
+  //*********************
+
+  class ArrayValue;
+  class Context;
+  class Interpreter;
+  class Node;
+  class SetValue;
+  class SetValueComp;
+  class Type;
+  class Value;
+
+  //************
+  //* Typedefs *
+  //************
+
+  typedef string (*DispFunc)(void*);
+  typedef void (*DelFunc)(void*);
+  typedef void* (*CopyFunc)(void*);
+  typedef int (*CompFunc)(void*,void*);
+
+  
+  //*********************
+  //* Enumeration types *
+  //*********************
+
+  //! Enumeration of error type
+  typedef enum{
+    errBug,
+    errSyntax,
+    errContext,
+    errRuntime,
+    errUnkown
+  } ErrorType;
+
+  //******************
+  //* Global objects *
+  //******************
+  
+  extern Type *type_array;
+  extern Type *type_boolean;
+  extern Type *type_context;
+  extern Type *type_generic;
+  extern Type *type_integer;
+  extern Type *type_function;
+  extern Type *type_contextual_function;
+  extern Type *type_meta_function;
+  extern Type *type_module;
+  extern Type *type_set;
+  extern Type *type_string;
+  extern Type *type_symbol;
+  extern Type *type_tuple;
+  extern Type *type_type;
+  extern Type *type_void;
+
+  //**********************
+  //* Class declarations *
+  //**********************
+
+  //------------
+  // ArrayValue
+  //------------
+
+  //! Class for array of value of same type
+  class  ArrayValue{
+  public:
+
+    //! size of the array
+    size_t size;
+    //! type of stored values
+    Type* type;
+    //! array of C++ pointer of value
+    void** tab;
+    //! Contrust an ArrayValue of a given size
+    //! \param desired size
+    ArrayValue(size_t s);
+  };
+
+  //! Class for interpreter error
+  class Error{
+  public:
+    //! Type of the error
+    ErrorType type;
+    //! Error message
+    string msg;
+    //! Filename of the source file that have launched the error
+    string file;
+    //! Name of the function that have launched the error
+    string function;
+    //! First character of the corresponding token
+    size_t first;
+    //! Last  character of the corresponding token
+    size_t last;
+    //! Number of the line that have launched the error
+    size_t line;
+
+    //! The empty constructor
+    Error();
+
+    //! The full constructor
+    Error(ErrorType type,string msg,size_t first,size_t last,string file,int line,string function);
+
+    //! Display the error
+    //! \param os output streamm for display
+    //! \param cmd command where error was found
+    void disp(ostream& os,const string& cmd) const;
+  };
+  
+  //--------
+  // Module
+  //--------
+  
+  //! Class for module
+  class Module{
+  public:
+    
+    class Function;
+
+    //! Name of the module
+    string name;
+    
+    //! Number of defined types
+    size_t ntype;
+
+    //! Number of defined functions
+    size_t nfunc;
+
+    //! Number of defined member functions
+    size_t nmfunc;
+
+    //! Number of defined contextual functions
+    size_t ncfunc;
+
+    //! Handle to the dinamic library object associated to the module
+    void* handle;
+
+    //! Name of defined types
+    string* types;
+
+    //! Defined functions
+    Function *functions;
+
+    //! Defined member functions
+    Function *member_functions;
+
+    //! Defined contextual function
+    Function* contextual_functions;
+    
+    //! Destructor
+    ~Module();
+
+    //! Unique constructor
+    Module();
+
+    //! Init module from types
+    //! \param types types defined in the library
+    void init(Type* types);
+  };
+
+  //------------------
+  // Module::Function
+  //------------------
+
+  //! Class for the module function declarations
+  class Module::Function{
+  public:
+    
+    //! Returned type
+    string tr;
+
+    //! Name of the function
+    string name;
+
+    //! Arguments type of the fnction 
+    initializer_list<string> targs;
+
+    //! Pointer to the C++ function
+    void* ptr;
+
+    //! Specify if the function is loaded or not
+    bool loaded;
+  };
+  
+  //--------------
+  // SetValueComp
+  //--------------
+  
+  //! Class for comparison of SetValue objects
+  class SetValueComp{
+  public:
+
+    //! Type of values in SetValue
+    Type* type;
+
+    //! The unsique constructor
+    SetValueComp(Type* type);
+
+    //! Function called for the comparison
+    //! \param lhs pointer to a SetValue of type type
+    //! \param rhs pointer to a SetValue of type type
+    //! \return true if lhs<rhs and false otherwise
+    bool operator()(void* lhs,void* rhs) const;
+  };
+
+  //----------
+  // SetValue
+  //----------
+  
+  //! Class for set of value of same type
+  class SetValue{
+  public:
+
+    //! Set of value
+    set<void*,SetValueComp> data;
+
+    //! Construct a set of value of specified type
+    //! \param type desired type
+    SetValue(Type* type);
+  };
+
+  //------------
+  // TupleValue
+  //------------
+  
+  //! Class for tuple of Values
+  class TupleValue{
+  public:
+
+    //! Tuple size
+    size_t size;
+
+    //! An array of Value
+    Value* tab;
+
+    //! Construt a TupleValue of size s
+    //! \param s the desired size
+    TupleValue(size_t s);
+  };
+
+  //------
+  // Type
+  //------
+  
+  //! Class for type
+  class Type{
+  public:
+    
+    //! Name of the type
+    string name;
+    //! Display function of the type
+    DispFunc disp;
+    //! Delete function of the type
+    DelFunc del;
+    //! Copy function of the type
+    CopyFunc copy;
+    //! Compeare function of the type
+    CompFunc comp;
+    //! Empty constructor
+    Type();
+    //! Full constructor
+    Type(string,DispFunc disp,DelFunc del,CopyFunc copy,CompFunc comp);
+    //! Recopy constructor
+    Type(const Type&);
+  };
+
+  //-------
+  // Value
+  //-------
+
+  //! Class for value of the intepreter
+  class Value{
+  public:
+
+    //! Type of the value
+    Type* type;
+
+    //! Pointer to theCc++ value
+    void* ptr;
+
+    //! Empty constructor
+    Value();
+
+    //! Constructor
+    //! \param type type of the value
+    //! \param ptr pointer to C++ value
+    Value(Type* type,void* ptr);
+    
+    //! Delete the current value
+    void del();
+    
+    //! Display the current value
+    //! \return a string of the diplay
+    string disp();
+
+    //! Evaluate the current value (use for Symbolic value)
+    //! \return pointed value if the current one is symbolic or the the current ont otherwise
+    Value* eval();
+
+    //! Return a copy of the current value
+    Value copy();
+  };
+  
+  //***********************
+  //* Auxiliary functions *
+  //***********************
+
+  //! Return an slong from a value ptr
+  uint64 get_slong(void* v);
+
+  //! Return a value ptr for a bool 
+  void* to_boolean(bool n);
+
+  //! Return a value ptr from a slong integer
+  void* to_integer(slong s);
+
+
+  //**********************
+  //* Inline definitions *
+  //**********************
+
+  //-------
+  // Error
+  //-------
+  
+  inline
+  Error::Error(){}
+  
+  inline
+  Error::Error(ErrorType _type,string _msg,size_t _first,size_t _last,string _file,int _line,string _function):type(_type),msg(_msg),first(_first),last(_last),file(_file),line(_line),function(_function){}
+  //------
+  // Type
+  //------
+  
+  inline
+  Type::Type(){}
+  
+  //--------
+  // Module
+  //--------
+ 
+  inline
+  Module::~Module(){}
+
+  //--------------
+  // SetValueComp
+  //--------------
+
+  inline
+  SetValueComp::SetValueComp(Type* t){
+    type=t;
+  }
+
+  inline bool
+  SetValueComp::operator()(void* lhs,void* rhs) const{return type->comp(lhs,rhs)==-1;}
+
+  //----------
+  // SetValue
+  //----------
+
+  inline
+  SetValue::SetValue(Type* typeinfo):data(SetValueComp(typeinfo)){}
+  
+  //-------
+  // Value
+  //-------
+  
+  inline
+  Value::Value():type(nullptr),ptr(nullptr){}
+
+  inline
+  Value::Value(Type* t,void* p):type(t),ptr(p){}
+
+  inline void
+  Value::del(){
+    if(ptr!=nullptr and type!=nullptr){
+      type->del(ptr);
+    }
+  }
+
+  inline Value*
+  Value::eval(){
+    if(type!=type_symbol) return this;
+    return (Value*)ptr;
+  }
+   
+}
+
+
+#endif