123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500 |
- /**
- * 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);
- current.value=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="ext/"+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";
- }
- }
- }
|