lbp_function.cpp
Go to the documentation of this file.
1 /** @file lbp_function.cpp luafaudes class to run scripts as rti functions */
2 
3 /*
4 FAU Discrete Event Systems Library (libfaudes)
5 
6 Copyright (C) 2010 Thomas Moor
7 
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12 
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 
23 */
24 
25 
26 // my header
27 #include "lbp_function.h"
28 
29 // all lua headers, incl Lua nd lbp_addons.h
30 #include "lbp_include.h"
31 
32 
33 
34 namespace faudes{
35 
36 /*
37 ********************************************************************
38 ********************************************************************
39 ********************************************************************
40 
41 Borrow from SWIG type system
42 
43 ********************************************************************
44 ********************************************************************
45 ********************************************************************
46 */
47 
48 
49 /*
50 SWIGS representation of user data (lua runtime version 4, swig 1.3.36)
51 Note: the below interface has also been verified to meet SWIG 1.3.40
52 and 2.0.1. Other versions of SWIG may or may not have compatible interfaces
53 and, hence, should be carefully verified befor use.
54 */
55 typedef void *(*swig_converter_func)(void *, int *);
56 typedef struct swig_type_info *(*swig_dycast_func)(void **);
57 typedef struct swig_cast_info {
58  swig_type_info *type; /* pointer to type that is equivalent to this type */
59  swig_converter_func converter; /* function to cast the void pointers */
60  struct swig_cast_info *next; /* pointer to next cast in linked list */
61  struct swig_cast_info *prev; /* pointer to the previous cast */
63 typedef struct swig_type_info {
64  const char *name; /* mangled name of this type */
65  const char *str; /* human readable name of this type */
66  swig_dycast_func dcast; /* dynamic cast function down a hierarchy */
67  struct swig_cast_info *cast; /* linked list of types that can cast into this type */
68  void *clientdata; /* language specific type data */
69  int owndata; /* flag if the structure owns the clientdata */
71 typedef struct {
73  int own; /* 1 <> owned by swig (garbadge collector wont destroy) */
74  void *ptr;
76 
77 
78 
79 /*
80 Swig runtime sytem: dynamic cast of swig userdata pointers.
81 We need this to cast swig's userdata to the faudes base type
82 faudes::Type. In contrast to the original SWIG runtime function
83 SWIG_ConvertPtr, the below variant is are more picky on types
84 that do mot cast to faufes::Type. For such types, we return NULL
85 */
86 void* SwigCastPtr(void* ptr, swig_type_info *from, swig_type_info *ty) {
87  void* res=ptr;
88  if(!ptr) return 0;
89  if(!from) return 0;
90  if(!ty) return 0;
91  swig_cast_info *iter = ty->cast;
92  while(iter) {
93  if(iter->type == from) {
94  if(iter == ty->cast) break;
95  iter->prev->next = iter->next;
96  if(iter->next)
97  iter->next->prev = iter->prev;
98  iter->next = ty->cast;
99  iter->prev = 0;
100  if(ty->cast) ty->cast->prev = iter;
101  ty->cast = iter;
102  break;
103  }
104  iter = iter->next;
105  }
106  if(!iter) return 0;
107  if(!iter->converter) return 0;
108  int nm;
109  res= (*iter->converter)(ptr,&nm);
110  return res;
111 }
112 
113 /*
114 Test whether userdata is SWIG generated, i.e., can be examined by
115 the SWIG type system
116 */
117 swig_lua_userdata* SwigUserData(lua_State* L, int index) {
118  if(!lua_isuserdata(L,index)) return NULL;
119  // get the metatable
120  if(!lua_getmetatable(L,index)) return NULL;
121  // get the ".type" entry
122  lua_pushstring(L,".type");
123  lua_rawget(L,-2);
124  if(!lua_isstring(L,-1)) { lua_pop(L,2); return NULL;};
125  const char* ftype = lua_tostring(L,-1);
126  if(!ftype) {lua_pop(L,2); return NULL;};
127  // todo: test whether this is a faudes type?
128  // todo: test whether the metatable is a registered by swig
129  lua_pop(L,2);
130  return (swig_lua_userdata*) lua_touserdata(L,index);
131 }
132 
133 
134 /*
135 ********************************************************************
136 ********************************************************************
137 ********************************************************************
138 
139 local helper, may go to cfl_helper.*
140 
141 ********************************************************************
142 ********************************************************************
143 ********************************************************************
144 */
145 
146 std::string MangleString(const std::string& str) {
147  std::string res=str;
148  std::size_t src=0;
149  std::size_t dst=0;
150  while(src<res.length()) {
151  if(isalnum(res.at(src))) {res[dst++]=res[src++]; continue;}
152  res[dst++]='_';
153  for(;src<res.length();src++)
154  if(isalnum(res.at(src))) break;
155  }
156  if(dst>2)
157  if(res[dst-1]=='_')
158  dst--;
159  res.resize(dst);
160  return res;
161 }
162 
163 
164 /*
165 ********************************************************************
166 ********************************************************************
167 ********************************************************************
168 
169 Implementation of class LuaFunctionDefinition
170 
171 ********************************************************************
172 ********************************************************************
173 ********************************************************************
174 */
175 
176 // faudes type
177 FAUDES_TYPE_IMPLEMENTATION(LuaFunctionDefinition,LuaFunctionDefinition,FunctionDefinition)
178 
179 // construct
180 LuaFunctionDefinition::LuaFunctionDefinition(const std::string& name) :
181  FunctionDefinition(name),
182  pDefaultL(0)
183 {
184  Prototype(new LuaFunction(0));
185  FD_DLB("LuaFunctionDefinition::LuaFunctionDefinition("<<this<<"): name " << name);
186  FD_DLB("LuaFunctionDefinition::LuaFunctionDefinition("<<this<<"): proto " << mpFunction);
187  FD_DLB("LuaFunctionDefinition::LuaFunctionDefinition("<<this<<"): has def " << mpFunction->Definition());
188 }
189 
190 // copy construct
192  FunctionDefinition(rSrc.Name()),
193  pDefaultL(0)
194 {
195  FD_DLB("LuaFunctionDefinition::LuaFunctionDefinition(copy)");
196  DoAssign(rSrc);
197 }
198 
199 // std faudes type
201  FD_DLB("LuaFunctionDefinition::DoAssign()");
202  // assign base members
204  // assign my members
205  mLuaCode=rSrc.mLuaCode;
206  mLuaFile=rSrc.mLuaFile;
207  // special member
208  pLuaFunction=dynamic_cast<LuaFunction*>(mpFunction);
209  // report
210  FD_DLB("LuaFunctionDefinition::DoAssign("<<this<<"): name " << mName);
211  FD_DLB("LuaFunctionDefinition::DoAssign("<<this<<"): proto " << mpFunction);
212  FD_DLB("LuaFunctionDefinition::DoAssign("<<this<<"): has def " << mpFunction->Definition())
213 }
214 
215 // std faudes type
217  // test base members
218  if(!FunctionDefinition::DoEqual(rOther)) return false;
219  // test my members
220  if(mLuaCode!=rOther.mLuaCode) return false;
221  if(mLuaFile!=rOther.mLuaFile) return false;
222  return true;
223 }
224 
225 // clear (all but prototype)
227  FD_DLB("LuaFunctionDefinition::Clear(): " << Name());
228  // call base
230  // clear my data
231  mLuaCode.clear();
232 }
233 
234 
235 // set prototype object
238  // set typed version
239  pLuaFunction=dynamic_cast<LuaFunction*>(pFunc);
240 }
241 
242 
243 // get lua code
244 const std::string& LuaFunctionDefinition::LuaCode(void) const {
245  return mLuaCode;
246 }
247 
248 // set lua code
249 void LuaFunctionDefinition::LuaCode(const std::string& rCode) {
250  mLuaCode=rCode;
251 }
252 
253 // get/set default lua state
255  if(!pDefaultL) return const_cast<LuaFunctionDefinition*>(this)->pDefaultL=LuaState::G();
256  return pDefaultL;
257 }
258 
259 // get/set default lua state
261  pDefaultL=pL;
262 }
263 
264 // test all variants
266  // trivial case ... use evaluate
267  if(VariantsSize()==0) {
268  FD_DLB("LuaFunctionDefinition::SyntaxCheck(): no variants defined, evaluate");
269  return Evaluate();
270  }
271  // allocate function
273  // iterate variants
274  std::string err = "";
275  for(int i=0; i<lfnct->VariantsSize(); i++) {
276  // select
277  lfnct->Variant(i);
278  FD_DLB("LuaFunctionDefinition::SyntaxCheck(): variant " <<
279  lfnct->Variant()->Name());
280  // allocate args (exception on unknown type, will lead to mem leak)
281  try {
282  lfnct->AllocateValues();
283  // let luafunction have a go
284  if(err=="") try {
285  lfnct->SyntaxCheck();
286  } catch(const faudes::Exception& ex) {
287  err = ex.What();
288  }
289  // free args
290  lfnct->FreeValues();
291  // alloc err
292  } catch(const faudes::Exception& ex) {
293  err = "cannot allocate parameters for variant " + lfnct->Variant()->Name();
294  }
295  } // iterate variants
296  delete lfnct;
297  // done
298  return err;
299 }
300 
301 
302 // test all variants
304  // allocate function and set state
306  lfnct->L(pL);
307  // evaluate
308  std::string err = "";
309  try {
310  lfnct->Evaluate();
311  } catch(const faudes::Exception& ex) {
312  err = ex.What();
313  }
314  // done
315  delete lfnct;
316  return err;
317 }
318 
319 // install myself to a lua state
321  if(!pL) pL=DefaultL();
322  Install(pL->LL());
323 }
324 
325 // install myself to a lua state
326 void LuaFunctionDefinition::Install(lua_State* pLL) const {
327  FD_DLB("LuaFunctionDefinition::Install(): " << Name());
328 
329  // bail out if no signature (it's a DESTool plain script)
330  if(VariantsSize()==0) {
331  FD_DLB("LuaFunctionDefinition::Install(): no signatures for fnct " << Name());
332  return;
333  }
334 
335  // function name (ctype overwrites name)
336  std::string lfname = Name();
337  if(CType()!="") {
338  size_t pos=CType().find("faudes::");
339  if(pos!=std::string::npos)
340  lfname=CType().substr(std::string("faudes::").length());
341  }
342 
343  // parse signatures, test consistence
344  std::vector< std::string > lffnct; //fnct names
345  std::vector< int > lfparcnt; // # actual parameters
346  std::vector< std::vector<std::string> > lfparams; // par names
347  std::vector< std::vector<Parameter::ParamAttr> > lfattrib; // par access
348  std::vector< std::vector<bool> > lfretval; // actual return value
349  std::vector< std::vector<bool> > lfparval; // actual parameter
350  lffnct.resize(VariantsSize());
351  lfparcnt.resize(VariantsSize());
352  lfparams.resize(VariantsSize());
353  lfattrib.resize(VariantsSize());
354  lfretval.resize(VariantsSize());
355  lfparval.resize(VariantsSize());
356  for(int i=0; i<VariantsSize(); i++) {
357  const Signature& sigi=Variant(i);
358  int parcnt=0;
359  for(int j=0; j<sigi.Size(); j++) {
360  // retrieve faudes type and attrib
361  std::string ftype=sigi.At(j).Type();
362  Parameter::ParamAttr fattr=sigi.At(j).Attribute();
363  // autodefault creturn flag
364  bool fcret=false;
365  if(fattr==Parameter::Out) fcret=true;
366  if(fattr==Parameter::InOut) fcret=true;
367  // get creturn from signature for non-elementary
368  if(ftype!="Boolean")
369  if(ftype!="Integer")
370  if(ftype!="String")
371  fcret=sigi.At(j).CReturn();
372  // bail out on non-out ret value
373  if(fcret)
374  if((fattr!=Parameter::Out) && (fattr!=Parameter::InOut))
375  break;
376  // bail out on unknown faudestype
377  if(ftype!="Boolean")
378  if(ftype!="Integer")
379  if(ftype!="String")
380  if(!TypeRegistry::G()->Exists(ftype))
381  break;
382  // figure and count actual parameters
383  bool fcpar=true;
384  if(fcret && fattr==Parameter::Out) fcpar=false;
385  if(fcpar) parcnt++;
386  // bail out on undef attribute
387  if(fattr==Parameter::UnDef) break;
388  // param ok
389  lfparams.at(i).push_back(ftype);
390  lfattrib.at(i).push_back(fattr);
391  lfretval.at(i).push_back(fcret);
392  lfparval.at(i).push_back(fcpar);
393  }
394  // test for signature error
395  if((int) lfparams.at(i).size()!=sigi.Size()) {
396  FD_WARN("LuaFunctionDefinition::Install(): cannot interpret signature \"" << sigi.Name() << "\"");
397  lffnct.resize(i);
398  break;
399  }
400  // record function name
401  lffnct.at(i)=MangleString(sigi.Name());
402  lfparcnt.at(i)=parcnt;
403  }
404  FD_DLB("LuaFunctionDefinition::Install(): #" << lffnct.size() << " valid signatures");
405 
406  // todo: filter out doublets as in rti2code
407  // prepare lua code for signature dispatch
408  std::vector< std::string > lftest1;
409  std::vector< std::string > lftest2;
410  std::vector< std::string > lfcall;
411  std::vector< std::string > lfsig;
412  for(unsigned int i=0; i<lffnct.size(); i++) {
413  // create type conditional, part1: lua types
414  std::string test1="(arg['n']==" + ToStringInteger(lfparcnt.at(i)) + ")" ;
415  unsigned int pj=0;
416  for(unsigned int j=0; j<lfparams.at(i).size(); j++) {
417  if(!lfparval.at(i).at(j)) continue;
418  pj++;
419  test1=test1+" and ";
420  std::string ltype="userdata";
421  if(lfparams.at(i).at(j) == "Integer") ltype="number";
422  if(lfparams.at(i).at(j) == "Boolean") ltype="bool";
423  if(lfparams.at(i).at(j) == "String") ltype="string";
424  test1=test1 + "(type(arg[" + ToStringInteger(pj) + "])=='" + ltype + "')";
425  }
426  lftest1.push_back(test1);
427  // create type conditional, part2: faudes types
428  std::string test2="";
429  pj=0;
430  for(unsigned int j=0; j<lfparams.at(i).size(); j++) {
431  if(!lfparval.at(i).at(j)) continue;
432  pj++;
433  if(lfparams.at(i).at(j) == "Integer") continue;
434  if(lfparams.at(i).at(j) == "Boolean") continue;
435  if(lfparams.at(i).at(j) == "String") continue;
436  if(test2.size()>0) test2=test2+" and ";
437  test2=test2 + "faudes.TypeTest(\"" + lfparams.at(i).at(j) + "\", arg[" + ToStringInteger(pj) + "])";
438  }
439  lftest2.push_back(test2);
440  // create function call
441  std::string call= lffnct.at(i) + "(";
442  pj=0;
443  for(unsigned int j=0; j<lfparams.at(i).size(); j++) {
444  if(!lfparval.at(i).at(j)) continue;
445  pj++;
446  if(pj>1) call = call + ", ";
447  call = call + "arg[" + ToStringInteger(pj) + "]";
448  }
449  call = call + ")";
450  lfcall.push_back(call);
451  // create nice signature. note: this should match the respective code in rti2code.cpp
452  std::string nsig = " " + lfname + "(";
453  bool leftcomma = false;
454  bool rightcomma = false;
455  for(unsigned int j=0; j<lfparams.at(i).size(); j++) {
456  // return value
457  if(lfretval.at(i).at(j)) {
458  if(leftcomma) nsig = "," + nsig;
459  nsig=lfparams.at(i).at(j) + nsig;
460  leftcomma=true;
461  }
462  // parameter value
463  if(lfparval.at(i).at(j)) {
464  if(rightcomma) nsig += ", ";
465  const Signature& sigi=Variant(i);
466  nsig += sigi.At(j).Str();
467  rightcomma=true;
468  }
469  }
470  nsig+=")";
471  lfsig.push_back(nsig);
472  }
473 
474  // add to help system
475  if(TextDoc()!="") {
476  for(unsigned int i=0; i< lfsig.size(); i++) {
477  std::string topic= PlugIn();
478  std::string key1= KeywordAt(1);
479  if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
480  if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
481  faudes_dict_insert_entry(topic,key1,lfsig.at(i));
482  }
483  }
484 
485 
486  // set up wrapper frunction
487  std::stringstream lfwrap;
488  //lfwrap << "-- LuaFunctionDefinition.Install() " << Name() << std::endl;
489  //lfwrap << std::endl;
490  lfwrap << LuaCode();
491  //lfwrap << std::endl;
492  lfwrap << std::endl;
493  //lfwrap << "-- LuaFunctionDefinition.Install(): dispatch / typecheck" << std::endl;
494  lfwrap << "function faudes." << lfname << "(...)" << std::endl;
495  for(unsigned int i=0; i< lftest1.size(); i++) {
496  lfwrap << " if (" << lftest1.at(i) << ") then " << std::endl;
497  lfwrap << " if (" << lftest2.at(i) << ") then " << std::endl;
498  lfwrap << " return faudes." << lfcall.at(i) << std::endl;
499  lfwrap << " end" << std::endl;
500  lfwrap << " end" << std::endl;
501  }
502  lfwrap << " faudes.Error([[" << lfname << ": parameter mismatch: expected signature(s): " << std::endl;
503  for(unsigned int i=0; i< lfsig.size(); i++) {
504  lfwrap << lfsig.at(i) << std::endl;
505  }
506  lfwrap << "]])" << std::endl;
507  lfwrap << "end" << std::endl;
508 
509 
510  // debugging report
511  //FD_WARN("LuaFunctionDefinition:Install(): code:" << std::endl << lfwrap.str());
512  FD_DLB("LuaFunctionDefinition:Install(): code: done");
513 
514  // finally install (aka run) the wrapper
515  int errexec=luaL_dostring(pLL,lfwrap.str().c_str());
516  if(errexec!=0) {
517  std::string lerr= std::string(lua_tostring(pLL, -1));
518  int c1 = lerr.find_first_of(':');
519  if(c1<0) c1=0;
520  int c2 = lerr.find_first_of(':',c1+1);
521  if(c2<0) c2=1;
522  std::string line = lerr.substr(c1+1,c2-c1-1);
523  if(c2>1) {
524  lerr="error in Lua script: line " + line + ": " + lerr.substr(c2+2);
525  }
526  throw Exception("LuaFunctionDefinition::Install(): " + Name(), lerr, 49);
527  }
528 }
529 
530 // token io
531 void LuaFunctionDefinition::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
532  FD_DLB("LuaFunctionDefinition::DoRead()");
533  // ignore
534  (void) pContext;
535  // label
536  std::string label=rLabel;
537  if(label=="") label="LuaFunctionDefinition";
538  // base can handle this
539  FunctionDefinition::DoRead(rTr,label,pContext);
540  // report
541  FD_DLB("LuaFunctionDefinition::DoRead(): done " << mPlugIn << "::" << mName);
542 }
543 
544 
545 // register all definitions froma file with the function registry
546 void LuaFunctionDefinition::Register(const std::string& rFilename) {
547  FD_DLB("LuaFunctionDefinition::Register(): file " << rFilename);
548  TokenReader tr(rFilename);
549  Token token;
550  while(tr.Peek(token)) {
551  if(!token.IsBegin("LuaFunctionDefinition")) {
552  tr.Get(token);
553  continue;
554  }
556  plfd->Read(tr);
557  FD_DLB("LuaFunctionDefinition::Register(): found " << plfd->Name());
558  if(FunctionRegistry::G()->Exists(plfd->Name())) {
559  FD_DLB("LuaFunctionDefinition::Register(): skipping doublet " << plfd->Name());
560  delete plfd;
561  continue;
562  }
563  // Registry takes ownership
564  FunctionRegistry::G()->Insert(plfd);
565  }
566 }
567 
568 
569 // token io
570 void LuaFunctionDefinition::DoReadCore(TokenReader& rTr) {
571  FD_DLB("LuaFunctionDefinition::DoReadCore()");
572  // call base
574  // read my members
575  Token token;
576  rTr.Peek(token);
577  // case a: embedded lua code
578  if(token.IsBegin())
579  if(token.StringValue()=="LuaCode") {
580  mLuaFile="";
581  rTr.ReadVerbatim("LuaCode",mLuaCode);
582  }
583  // case b: lua file
584  if(token.IsBegin())
585  if(token.StringValue()=="LuaFile") {
586  rTr.ReadBegin("LuaFile");
587  std::string mLuaFile=rTr.ReadString();
588  // todo: read that file
589  rTr.ReadEnd("LuaFile");
590  }
591 }
592 
593 
594 // token io
595 void LuaFunctionDefinition::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
596  // label
597  std::string label=rLabel;
598  if(label=="") label="LuaFunctionDefinition";
599  // base can handle
600  Documentation::DoWrite(rTw,label,pContext);
601 }
602 
603 // token io
604 void LuaFunctionDefinition::DoWriteCore(TokenWriter& rTw) const {
605  FD_DLB("LuaFunctionDefinition::DoWriteCore(): file " << rTw.FileName());
606  // call base core
608  // case a: embedded code
609  if(mLuaFile=="") {
610  rTw.WriteVerbatim("LuaCode",mLuaCode);
611  }
612  // case a: embedded code
613  if(mLuaFile!="") {
614  rTw.WriteBegin("LuaFile");
615  rTw.WriteString(mLuaFile);
616  rTw.WriteEnd("LuaFile");
617  // todo: write that file
618  }
619 }
620 
621 /*
622 ********************************************************************
623 ********************************************************************
624 ********************************************************************
625 
626 Implementation of class LuaFunction
627 
628 ********************************************************************
629 ********************************************************************
630 ********************************************************************
631 */
632 
633 // Constructor
634 LuaFunction::LuaFunction(const LuaFunctionDefinition* fdef) :
635  Function(fdef),
636  pLuaFuncDef(fdef),
637  pL(0),
638  pLL(0)
639 {
640  FD_DLB("LuaFunction::LuaFunction(): fdef " << pFuncDef);
641 }
642 
643 // new on heap
644 LuaFunction* LuaFunction::New(void) const {
645  return new LuaFunction(pLuaFuncDef);
646 }
647 
648 // set function definition
649 void LuaFunction::Definition(const FunctionDefinition* fdef) {
650  // cast and pass to base
651  pLuaFuncDef = dynamic_cast<const LuaFunctionDefinition*>(fdef);
653 }
654 
655 // get function definition
656 const LuaFunctionDefinition* LuaFunction::Definition(void) const {
657  return pLuaFuncDef;
658 }
659 
660 // set variant signature (accept -1)
661 void LuaFunction::DoVariant(int n) {
662  // std case by base
663  if(n!=-1) {
665  return;
666  }
667  // special case -1
668  mVariantIndex=-1;
669  mParameterValues.clear();
670 }
671 
672 
673 // implement typecheck
674 bool LuaFunction::DoTypeCheck(int n) {
675  FD_DLB("LuaFunction::DoTypeCheck("<< n << "): for " << Variant()->At(n).Type());
676  const Type* proto = TypeRegistry::G()->Prototype(Variant()->At(n).Type());
677  if(!proto) {
678  FD_DLB("LuaFunction::DoTypeCheck("<< n << "): unknown type");
679  return false;
680  }
681  if(!proto->Cast(ParamValue(n))) {
682  FD_DLB("LuaFunction::DoTypeCheck("<< n << "): could not cast param value");
683  return false;
684  }
685  return true;
686 }
687 
688 
689 // get/set lua state
690 LuaState* LuaFunction::L(void) {
691  if(!pL) pL=Definition()->DefaultL();
692  return pL;
693 }
694 
695 // get/set default lua state
696 void LuaFunction::L(LuaState* l) {
697  pL=l;
698 }
699 
700 
701 // implement execute: run stages
702 void LuaFunction::DoExecute(void) {
703  FD_DLB("LuaFunction::DoExecute()");
704  /*
705  for(int i=0; i< Variant()->Size(); i++) {
706  FD_DLB("LuaFunction::DoExecute(): value at #" << i);
707  ParamValue(i)->Write();
708  }
709  */
710  // use the global state
711  if(!pL) pL=L();
712  pLL=pL->LL();
713  mEntryStack=lua_gettop(pLL);
714  // run stages
715  DoExecuteA();
716  DoExecuteB();
717  DoExecuteC();
718  DoExecuteD();
719  DoExecuteE();
720  // done
721  lua_settop(pLL,mEntryStack);
722  FD_DLB("LuaFunction::DoExecute(): done");
723 }
724 
725 // implement execute: syntaxcheck
726 void LuaFunction::SyntaxCheck(void) {
727  FD_DLB("LuaFunction::SyntaxCheck()");
728  if(!Variant()) {
729  std::stringstream errstr;
730  errstr << "no valid variant";
731  throw Exception("LuaFunction::Syntaxcheck()", errstr.str(), 47);
732  }
733  // use the global state
734  if(!pL) pL=L();
735  pLL=pL->LL();
736  mEntryStack=lua_gettop(pLL);
737  // run stages
738  DoExecuteA();
739  DoExecuteB();
740  // done
741  lua_settop(pLL,mEntryStack);
742  FD_DLB("LuaFunction::SyntaxCheck(): done");
743 }
744 
745 // implement execute: plain evaluation
746 void LuaFunction::Evaluate(void) {
747  FD_DLB("LuaFunction::SyntaxCheck()");
748  // use the global state
749  if(!pL) pL=L();
750  pLL=pL->LL();
751  mEntryStack=lua_gettop(pLL);
752  // run stages
753  DoExecuteA();
754  // done
755  lua_settop(pLL,mEntryStack);
756  FD_DLB("LuaFunction::SyntaxCheck(): done");
757 }
758 
759 // implement execute: run lua code i.e. define lua functions
760 void LuaFunction::DoExecuteA(void) {
761  FD_DLB("LuaFunction::DoExecuteA()");
762  // Lua stack: empty
763  // load my script
764  const char* script = pLuaFuncDef->LuaCode().c_str();
765  int script_len = pLuaFuncDef->LuaCode().size();
766  int errload=luaL_loadbuffer(pLL, script, script_len, "luafaudes");
767  if(errload!=0) {
768  std::string lerr= std::string(lua_tostring(pLL, -1));
769  int c1 = lerr.find_first_of(':');
770  if(c1<0) c1=0;
771  int c2 = lerr.find_first_of(':',c1+1);
772  if(c2<0) c2=1;
773  std::string line = lerr.substr(c1+1,c2-c1-1);
774  if(c2>1) {
775  lerr="error in Lua script: line " + line + ": " + lerr.substr(c2+2);
776  }
777  lua_settop(pLL,mEntryStack);
778  throw Exception("LuaFunction::DoExecuteA()", lerr, 49);
779  }
780  // Lua stack: script
781  // install all functions aka run the script
782  int errrun=lua_pcall(pLL, 0, 0, 0);
783  if(errrun!=0) {
784  std::stringstream errstr;
785  errstr << "failed to run script: ";
786  errstr << std::string(lua_tostring(pLL, -1));
787  lua_settop(pLL,mEntryStack);
788  throw Exception("LuaFunction::DoExecuteA()", errstr.str(), 49);
789  }
790  // stack: []
791 }
792 
793 // implement execute: find the function of this variant
794 void LuaFunction::DoExecuteB(void) {
795  FD_DLB("LuaFunction::DoExecuteB()");
796  // Lua stack: empty
797  // get the swig generated table of faudes functions
798  lua_getglobal(pLL,"faudes");
799  mFtable=lua_gettop(pLL);
800  if(!lua_istable(pLL,-1)) {
801  lua_settop(pLL,mEntryStack);
802  throw Exception("LuaFunction::DoExecuteB()", "failed to load faudes table", 49);
803  }
804  // stack: [faudes]
805  // find my function: look up in faudes name space ...
806  std::string fname = MangleString(Variant()->Name());
807  lua_pushstring(pLL,fname.c_str());
808  lua_gettable(pLL,mFtable);
809  if(!lua_isfunction(pLL,-1)) {
810  lua_pop(pLL, 1); // pop nil.
811  lua_getglobal(pLL,fname.c_str()); // ... or as global (compatibility with pre 2.19)
812  if(!lua_isfunction(pLL,-1)) {
813  std::stringstream errstr;
814  errstr << "missing function \"" << fname << "\"";
815  lua_settop(pLL,mEntryStack);
816  throw Exception("LuaFunction::DoExecuteB()", errstr.str(), 49);
817  }
818  }
819  // stack: [faudes, luafnct]
820  // construct a plain Type usrdata
821  lua_pushstring(pLL,"Type");
822  lua_gettable(pLL,mFtable);
823  if(!lua_isfunction(pLL,-1))
824  if(!lua_istable(pLL,-1)) { /* tmoor 201407 for swig 3.02 */
825  lua_settop(pLL,mEntryStack);
826  throw Exception("LuaFunction::DoExecuteB():", "failed to construct plain Type (1)", 49);
827  }
828  // stack: [faudes, luafnct, Type constructor]
829  if(lua_pcall(pLL, 0, 1, 0) != 0) {
830  lua_settop(pLL,mEntryStack);
831  throw Exception("LuaFunction::DoExecuteB():", "failed to construct plain Type (2)", 49);
832  }
833  // stack: [faudes, luafnct, Type variable]
834  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
835  if(!susr) {
836  lua_settop(pLL,mEntryStack);
837  throw Exception("LuaFunction::DoExecuteB():", "failed to construct plain Type (3)", 49);
838  }
839  FD_DLB("LuaFunction::DoExecuteB(): plain type is " << susr->type->name);
840  // record swig type of faudes plain Type
841  mFType=susr->type;
842  lua_pop(pLL, 1);
843  // stack: [faudes, luafnct]
844 }
845 
846 
847 
848 // implement execute: prepare parameters
849 void LuaFunction::DoExecuteC(void) {
850  FD_DLB("LuaFunction::DoExecuteC()");
851  // stack: [faudes, luafnct]
852  // interpret signature
853  mLReturn.resize(Variant()->Size());
854  mLParameter.resize(Variant()->Size());
855  mLReturnCount=0;
857  for(int i=0; i< Variant()->Size(); i++) {
858  const std::string& ftype= Variant()->At(i).Type();
859  // default: parameter except for explicit creturn && out
860  mLParameter.at(i)= !(Variant()->At(i).CReturn() && (Variant()->At(i).Attribute()==Parameter::Out));
861  // default: explicitly declared creturn
862  mLReturn.at(i)= Variant()->At(i).CReturn();
863  // autofix elementary parameters
864  if((ftype=="Integer") || (ftype=="Boolean") || (ftype=="String")) {
865  // ... out becomes return value only
866  if(Variant()->At(i).Attribute()==Parameter::Out) {
867  mLReturn.at(i)=true;
868  mLParameter.at(i)=false;
869  }
870  // ... inout becomes return value and parameter
871  if(Variant()->At(i).Attribute()==Parameter::InOut) {
872  mLReturn.at(i)=true;
873  mLParameter.at(i)=true;
874  }
875  // ... in becomes parameter only
876  if(Variant()->At(i).Attribute()==Parameter::In) {
877  mLReturn.at(i)=false;
878  mLParameter.at(i)=true;
879  }
880  }
881  // keep counts
882  if(mLReturn.at(i)) mLReturnCount++;
883  if(mLParameter.at(i)) mLParameterCount++;
884  }
885 
886  FD_DLB("LuaFunction::DoExecuteC(): found " << mLReturnCount << " return values and "
887  << mLParameterCount << " parameters");
888  // stack: [faudes, luafnct]
889  // construct my parameters in Lua
890  for(int i=0; i< Variant()->Size(); i++) {
891  const std::string& ftype= Variant()->At(i).Type();
892  // skip non-parameter
893  if(!mLParameter.at(i)) {
894  FD_DLB("LuaFunction::DoExecuteC(): skip nonparameter value pos " << i);
895  continue;
896  }
897  // special case: int as lua number
898  if(ftype=="Integer") {
899  lua_pushnumber(pLL,((Integer*)ParamValue(i))->CValue());
900  FD_DLB("LuaFunction::DoExecuteC(): created ftype " << ftype);
901  continue;
902  }
903  // special case: bool as lua bool
904  if(ftype=="Boolean") {
905  lua_pushboolean(pLL,((Boolean*)ParamValue(i))->CValue());
906  FD_DLB("LuaFunction::DoExecuteC(): created ftype " << ftype);
907  continue;
908  }
909  // special case: str as lua string
910  if(ftype=="String") {
911  lua_pushstring(pLL,((String*)ParamValue(i))->CValue().c_str());
912  FD_DLB("LuaFunction::DoExecuteC(): created ftype " << ftype);
913  continue;
914  }
915  // std case: faudes type: construct 1
916  lua_pushstring(pLL,ftype.c_str());
917  lua_gettable(pLL,mFtable);
918  if(!lua_isfunction(pLL,-1))
919  if(!lua_istable(pLL,-1)) { /* tmoor 201407 for swig 3.02 */
920  std::stringstream errstr;
921  errstr << "failed to load constructor for \"" << ftype << "\"";
922  lua_settop(pLL,mEntryStack);
923  throw Exception("LuaFunction::DoExecuteC()", errstr.str(), 49);
924  }
925  // std case: faudes type: construct 2
926  if(lua_pcall(pLL, 0, 1, 0) != 0) {
927  std::stringstream errstr;
928  errstr << "failed to construct for \"" << ftype << "\" (1)";
929  lua_settop(pLL,mEntryStack);
930  throw Exception("LuaFunction::DoExecuteC()", errstr.str(), 49);
931  }
932  // std case: test user data pointer
933  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
934  if(!susr) {
935  std::stringstream errstr;
936  errstr << "failed to construct for\"" << ftype << "\" (2)";
937  lua_settop(pLL,mEntryStack);
938  throw Exception("LuaFunction::DoExecuteB()", errstr.str(), 49);
939  }
940  // inspect stack
941  FD_DLB("LuaFunction::DoExecuteC(): created stype " << susr->type->name << " for ftype " << ftype);
942  FD_DLB("LuaFunction::DoExecuteC(): faudes parameter at " << ParamValue(i));
943  FD_DLB("LuaFunction::DoExecuteC(): swig usrdata ptr " << susr->ptr);
944  FD_DLB("LuaFunction::DoExecuteC(): swig usrdata own flag " << susr->own);
945  /*
946  // variant a: copy parameter value
947  void* fptr=SwigCastPtr(susr->ptr,susr->type,(swig_type_info*)mFType);
948  FD_DLB("LuaFunction::DoExecuteB(): faudes::Type converted ptr " << fptr);
949  if(Variant()->At(i).Attribute()!=Parameter::Out) {
950  FD_DLB("LuaFunction::DoExecuteB(): copy parameter value");
951  ((Type*)fptr)->Assign(*ParamValue(i));
952  }
953  */
954  // variant b: use references
955  if(susr->own) free(susr->ptr);
956  susr->own=0;
957  susr->ptr = dynamic_cast<void*>(ParamValue(i)); // dynamic-up-cast: needed for multiple inheritance (!!)
958  }
959  // stack: [faudes, luafnct, rp_1 ... rp_n]
960  FD_DLB("LuaFunction::DoExecuteC(): done");
961 }
962 
963 // implement execute: execute the function
964 void LuaFunction::DoExecuteD(void) {
965  FD_DLB("LuaFunction::DoExecuteD()");
966  // stack: [faudes, luafnct, rp_1 ... rp_n]
967  // duplicate all my parameters (incl. the actual function for convenience)
968  // note: needed only for variant a to retrieve values of faudes typed parameters
969  // note: duplication is cheap since these are references
970  int t1=lua_gettop(pLL)-mLParameterCount;
971  int t2=lua_gettop(pLL);
972  for(int i= t1; i<=t2; i++) {
973  lua_pushvalue(pLL,i);
974 #ifdef FAUDES_DEBUG_LUABINDINGS
975  // report user data
976  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
977  if(!susr) continue;
978  // inspect user data stack
979  FD_DLB("LuaFunction::DoExecuteD(): inspect stype " << susr->type->name);
980  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata ptr " << susr->ptr);
981  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata own flag " << susr->own);
982  void* fptr=SwigCastPtr(susr->ptr,susr->type,(swig_type_info*)mFType);
983  FD_DLB("LuaFunction::DoExecuteD(): faudes::Type converted ptr " << fptr);
984 #endif
985  }
986  // stack: [faudes, luafnct, rp_1 ... rp_n, luafnct, rp_1 ... rp_n]
987  // run my function
988  if(lua_pcall(pLL, mLParameterCount, mLReturnCount, 0) != 0) {
989  FD_DLB("LuaFunction::DoExecuteD(): detect error");
990  std::string lerr= std::string(lua_tostring(pLL, -1));
991  // user request via loopback exception
992  if(lerr.find("break on application request")!=std::string::npos) {
993  lerr="break on application request";
994  }
995  // user request via explicit exception
996  else if(lerr.find("luafaudes script:")!=std::string::npos) {
997  std::size_t c1=lerr.find("luafaudes script:");
998  lerr=lerr.substr(c1);
999  }
1000  // have line number ?
1001  else if(lerr.size()>=2) {
1002  std::size_t c1 = lerr.find_first_of(':');
1003  if(c1==std::string::npos) c1=0;
1004  if(c1+1>=lerr.size()) c1=0;
1005  std::size_t c2 = lerr.find_first_of(':',c1+1);
1006  if(c2==std::string::npos) c2=c1+1;
1007  if(c2>c1+1) {
1008  std::string line = lerr.substr(c1+1,c2-c1-1);
1009  lerr="error in Lua script: line " + line + ": " + lerr.substr(c2+2);
1010  }
1011  }
1012  // anyway: fix stack
1013  lua_settop(pLL,mEntryStack);
1014  throw Exception("LuaFunction::DoExecuteD()", lerr, 49);
1015  }
1016  FD_DLB("LuaFunction::DoExecuteD():done ");
1017  // stack: [faudes, luafnct, rp_1 ... rp_n, lp1 ... lpm]
1018 }
1019 
1020 // implement execute: retrieve results
1021 void LuaFunction::DoExecuteE(void) {
1022  FD_DLB("LuaFunction::DoExecuteE()");
1023  // stack: [faudes, luafnct, rp_1 ... rp_n, lp1 ... lpm]
1024  // retrieve results from stack: return values
1025  for(int i=Variant()->Size()-1; i>=0; i--) {
1026  // skip non-return values
1027  if(!mLReturn.at(i)) continue;
1028  // switch on ftype
1029  const std::string& ftype= Variant()->At(i).Type();
1030  // int as lua number
1031  if(ftype=="Integer" && lua_isnumber(pLL,-1)) {
1032  FD_DLB("LuaFunction::DoExecuteE(): retrieve type " << ftype);
1033  ((Integer*)ParamValue(i))->CValue(lua_tonumber(pLL,-1));
1034  lua_pop(pLL, 1);
1035  continue;
1036  }
1037  // bool as lua bool
1038  if(ftype=="Boolean" && lua_isboolean(pLL,-1)) {
1039  ((Boolean*)ParamValue(i))->CValue(lua_toboolean(pLL,-1));
1040  FD_DLB("LuaFunction::DoExecuteE(): retrieved type " << ftype);
1041  lua_pop(pLL, 1);
1042  continue;
1043  }
1044  // str as lua string
1045  if(ftype=="String" && lua_isstring(pLL,-1)) {
1046  ((String*)ParamValue(i))->CValue(lua_tostring(pLL,-1));
1047  FD_DLB("LuaFunction::DoExecuteE(): retrieved type " << ftype);
1048  lua_pop(pLL, 1);
1049  continue;
1050  }
1051  // report error
1052  std::stringstream errstr;
1053  errstr << "invalid return values in \"" << Variant()->Name() << "\"";
1054  lua_settop(pLL,mEntryStack);
1055  throw Exception("LuaFunction::DoExecuteE()", errstr.str(), 49);
1056  }
1057 
1058  // stack: [faudes, luafnct, rp_1 ... rp_n]
1059 
1060  /*
1061  // variant a: need to copy results
1062 
1063  // retrieve results from stack: duplicate references to parameters
1064  for(int i=Variant()->Size()-1; i>=0; i--) {
1065  // skip return values
1066  if(mLReturn.at(i)) continue;
1067  // switch on type type
1068  const std::string& ftype= Variant()->At(i).Type();
1069  // discrad/ignore duplicate parameters with access In
1070  if(Variant()->At(i).Attribute()==Parameter::In) {
1071  FD_DLB("LuaFunction::DoExecuteD(): ignore in-paremeter of type " << ftype);
1072  lua_pop(pLL, 1);
1073  continue;
1074  }
1075  // discrad/ignore elementary types (lua call by value)
1076  if((ftype=="Integer") || (ftype=="Boolean") || (ftype=="String")) {
1077  FD_DLB("LuaFunction::DoExecuteD(): ignore elementary type parameter " << ftype);
1078  lua_pop(pLL, 1);
1079  continue;
1080  }
1081  // std case: get updated value
1082  if(lua_isuserdata(pLL,-1)) {
1083  FD_DLB("LuaFunction::DoExecuteD(): try to retrieve type " << ftype);
1084  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata(pLL, -1);
1085  if(susr) {
1086  FD_DLB("LuaFunction::DoExecuteD(): found swig type " << susr->type->name << " at " << susr->ptr);
1087  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata ptr " << susr->ptr);
1088  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata own flag " << susr->own);
1089  void* fptr=SwigCastPtr(susr->ptr,susr->type,(swig_type_info*)mFType);
1090  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata ptr faudes::Type converted " << fptr);
1091  FD_DLB("LuaFunction::DoExecuteD(): parameter value " << ParamValue(i));
1092  FD_DLB("LuaFunction::DoExecuteD(): copy parameter value");
1093  ParamValue(i)->Assign(*((Type*)fptr));
1094  // pop
1095  lua_pop(pLL, 1);
1096  continue;
1097  }
1098  }
1099 
1100  */
1101 
1102  // variant b: discard duplicate parameters (did not need them for variant b anyway)
1103  for(int i=Variant()->Size()-1; i>=0; i--) {
1104  if(mLReturn.at(i)) continue;
1105  lua_pop(pLL, 1);
1106  }
1107 
1108 }
1109 
1110 
1111 
1112 /*
1113 ********************************************************************
1114 ********************************************************************
1115 ********************************************************************
1116 
1117 LuaState implementation
1118 
1119 ********************************************************************
1120 ********************************************************************
1121 ********************************************************************
1122 */
1123 
1124 // include Mike Pall's completer
1125 #include "lbp_completion.cpp"
1126 
1127 
1128 // construct/destruct
1129 LuaState::LuaState(void) : mpLL(0) { Open(); }
1130 LuaState::~LuaState(void) { Close(); }
1131 
1132 //access
1133 lua_State* LuaState::LL(void) { return mpLL; }
1134 
1135 // re-init
1136 void LuaState::Reset(void) {
1137  // have a new state
1138  Close();
1139  Open();
1140  // install from function registry
1142  for(;fit!=FunctionRegistry::G()->End(); fit++) {
1143  const LuaFunctionDefinition* lfd=dynamic_cast<const LuaFunctionDefinition*>(fit->second);
1144  if(!lfd) continue;
1145  lfd->Install(mpLL);
1146  }
1147 }
1148 
1149 // install extension
1150 void LuaState::Install(const std::string& rFilename) {
1151  Install(mpLL, rFilename);
1152 }
1153 
1154 // static state (convenience)
1155 LuaState* LuaState::G(void) {
1156  static LuaState* sls=NULL;
1157  if(!sls) sls=new LuaState();
1158  return sls;
1159 }
1160 
1161 // open/close lua state
1162 void LuaState::Open(void) {
1163  Close();
1164  FD_DLB("LuaState::Open()");
1165  mpLL=lua_open();
1166  Initialize(mpLL);
1167  faudes_print_register(mpLL); // todo: configure this
1168  faudes_hook_register(mpLL); // todo: configure this
1169  FD_DLB("LuaState::Done()");
1170 }
1171 
1172 // open/close lua state
1173 void LuaState::Close(void) {
1174  if(!mpLL) return;
1175  FD_DLB("LuaState::Close()");
1176  lua_close(mpLL);
1177  mpLL=NULL;
1178 }
1179 
1180 // lua style interface to initialize lua state
1181 void LuaState::Initialize(lua_State* pLL) {
1182  lua_gc(pLL, LUA_GCSTOP, 0); /* stop collector during initialization */
1183  luaL_openlibs(pLL); /* open libraries */
1184  luaopen_faudes_allplugins(pLL); /* install my namespace */
1185  lua_gc(pLL, LUA_GCRESTART, 0); /* restart collector */
1186 }
1187 
1188 
1189 
1190 // convenience function: load all luafunctions defined in a file
1191 void LuaState::Install(lua_State* pLL, const std::string& rFilename) {
1192  FD_DLB("LuaState::Insatll(): file " << rFilename);
1193  TokenReader tr(rFilename);
1194  Token token;
1195  while(tr.Peek(token)) {
1196  // todo: figure title and ... faudes_dict_insert_topic(const std::string& topic, const std::string& text);
1197  if(!token.IsBegin("LuaFunctionDefinition")) {
1198  tr.Get(token);
1199  continue;
1200  }
1201  LuaFunctionDefinition lfd;
1202  lfd.Read(tr);
1203  FD_DLB("LuaState::Install(): found " << lfd.Name());
1204  lfd.Install(pLL);
1205  }
1206 }
1207 
1208 // push a faudes typed object on the stack
1209 void LuaState::Push(const Type* fdata) {
1210  Push(mpLL,fdata);
1211 }
1212 
1213 // push a faudes typed object on the stack
1214 void LuaState::Push(lua_State* pLL, const Type* fdata) {
1215  FD_DLB("LuaFunction::Push()");
1216  int savetop=lua_gettop(pLL);
1217  // stack: []
1218  // get the swig generated table of faudes functions
1219  lua_getglobal(pLL,"faudes");
1220  int ftable=lua_gettop(pLL);
1221  if(!lua_istable(pLL,-1)) {
1222  lua_settop(pLL,savetop);
1223  throw Exception("LuaState::Push()", "failed to load faudes table", 49);
1224  }
1225  // stack: [faudes]
1226  lua_pushstring(pLL,"Type");
1227  lua_gettable(pLL,ftable);
1228  if(!lua_isfunction(pLL,-1))
1229  if(!lua_istable(pLL,-1)) { /* tmoor 201607 for swig 3.02 */
1230  lua_settop(pLL,savetop);
1231  throw Exception("LuaState::Push()", "failed to construct plain Type (1)", 49);
1232  }
1233  // stack: [faudes, Type constructor]
1234  if(lua_pcall(pLL, 0, 1, 0) != 0) {
1235  lua_settop(pLL,savetop);
1236  throw Exception("LuaState::Push()", "failed to construct plain Type (2)", 49);
1237  }
1238  // stack: [faudes, Type variable]
1239  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
1240  if(!susr) {
1241  lua_settop(pLL,savetop);
1242  throw Exception("LuaState::Push()", "failed to construct plain Type (3)", 49);
1243  }
1244  FD_DLB("LuaState::Push(): plain type is " << susr->type->name);
1245  // record swig type of faudes plain Type
1246  swig_type_info* stype =susr->type;
1247  lua_pop(pLL, 1);
1248  // stack: [faudes]
1249  // construct my data in Lua
1250  const std::string& ftype= FaudesTypeName(*fdata);
1251  // special case: int as lua number
1252  if(ftype=="Integer") {
1253  lua_pushnumber(pLL,((const Integer&)*fdata));
1254  FD_DLB("LuaState::Push(): created ftype " << ftype);
1255  }
1256  // special case: bool as lua bool
1257  else if(ftype=="Boolean") {
1258  lua_pushboolean(pLL,((const Boolean&)*fdata));
1259  FD_DLB("LuaState::Push(): created ftype " << ftype);
1260  }
1261  // special case: str as lua string
1262  else if(ftype=="String") {
1263  lua_pushstring(pLL,((const String&)*fdata).CValue().c_str());
1264  FD_DLB("LuaState::Push(): created ftype " << ftype);
1265  }
1266  // std case: faudes type
1267  else {
1268  // construct 1
1269  lua_pushstring(pLL,ftype.c_str());
1270  lua_gettable(pLL,ftable);
1271  if(!lua_isfunction(pLL,-1))
1272  if(!lua_istable(pLL,-1)) { /* tmoor 201607 for swig 3.02 */
1273  std::stringstream errstr;
1274  errstr << "failed to load constructor for \"" << ftype << "\"";
1275  lua_settop(pLL,savetop);
1276  throw Exception("LuaState::Push()", errstr.str(), 49);
1277  }
1278  // construct 2
1279  if(lua_pcall(pLL, 0, 1, 0) != 0) {
1280  std::stringstream errstr;
1281  errstr << "failed to construct for \"" << ftype << "\" (1)";
1282  lua_settop(pLL,savetop);
1283  throw Exception("LuaState::Push()", errstr.str(), 49);
1284  }
1285  // test user data pointer
1286  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
1287  if(!susr) {
1288  std::stringstream errstr;
1289  errstr << "failed to construct for\"" << ftype << "\" (2)";
1290  lua_settop(pLL,savetop);
1291  throw Exception("LuaState::Push()", errstr.str(), 49);
1292  }
1293  // inspect stack
1294  FD_DLB("LuaState::Push(): created stype " << susr->type->name << " for ftype " << ftype);
1295  FD_DLB("LuaState::Push(): faudes parameter at " << fdata);
1296  FD_DLB("LuaState::Push(): swig usrdata ptr " << susr->ptr);
1297  FD_DLB("LuaState::Push(): swig usrdata own flag " << susr->own);
1298  // cast to plain Type
1299  void* fptr=SwigCastPtr(susr->ptr,susr->type,stype);
1300  FD_DLB("LuaState::Push(): faudes plain Type converted ptr " << fptr);
1301  if(!fptr) {
1302  std::stringstream errstr;
1303  errstr << "failed cast from " << ftype;
1304  lua_settop(pLL,savetop);
1305  throw Exception("LuaState::Push()", errstr.str(), 49);
1306  }
1307  ((Type*)fptr)->Assign(*fdata);
1308  }
1309  // stack: [faudes, fdata]
1310  lua_replace(pLL,-2);
1311  FD_DLB("LuaFunction::DoExecuteB(): done");
1312 }
1313 
1314 // pop a faudes typed object from the stack
1315 Type* LuaState::Pop(void) {
1316  return Pop(mpLL);
1317 }
1318 
1319 // pop a faudes typed object from the stack
1320 Type* LuaState::Pop(lua_State* pLL) {
1321  FD_DLB("LuaFunction::Pop()");
1322  int savetop=lua_gettop(pLL);
1323  Type* res=NULL;
1324  // stack: [fobject]
1325  // special cases: integer
1326  if(lua_isnumber(pLL,-1)) {
1327  res= new Integer(lua_tointeger(pLL,-1));
1328  lua_pop(pLL,1);
1329  return res;
1330  }
1331  // special cases: string
1332  if(lua_isstring(pLL,-1)) {
1333  res= new String(lua_tostring(pLL,-1));
1334  lua_pop(pLL,1);
1335  return res;
1336  }
1337  // special cases: string
1338  if(lua_isboolean(pLL,-1)) {
1339  res= new Boolean(lua_toboolean(pLL,-1));
1340  lua_pop(pLL,1);
1341  return res;
1342  }
1343  // stack: [fobject]
1344  // get the swig generated table of faudes functions
1345  lua_getglobal(pLL,"faudes");
1346  int ftable=lua_gettop(pLL);
1347  if(!lua_istable(pLL,-1)) {
1348  lua_settop(pLL,savetop);
1349  throw Exception("LuaState::Pop()", "failed to load faudes table", 49);
1350  }
1351  // stack: [fobject, faudes]
1352  // construct a plain Type usrdata
1353  lua_pushstring(pLL,"Type");
1354  lua_gettable(pLL,ftable);
1355  if(!lua_isfunction(pLL,-1))
1356  if(!lua_istable(pLL,-1)) { /* tmoor 201607 for swig 3.02 */
1357  lua_settop(pLL,savetop);
1358  throw Exception("LuaState::Pop()", "failed to construct plain Type (1)", 49);
1359  }
1360  // stack: [fobject, faudes, Type constructor]
1361  if(lua_pcall(pLL, 0, 1, 0) != 0) {
1362  lua_settop(pLL,savetop);
1363  throw Exception("LuaState::Pop()", "failed to construct plain Type (2)", 49);
1364  }
1365  // stack: [fobject, faudes, Type variable]
1366  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
1367  if(!susr) {
1368  lua_settop(pLL,savetop);
1369  throw Exception("LuaState::Pop()", "failed to construct plain Type (3)", 49);
1370  }
1371  FD_DLB("LuaState::Pop(): plain type is " << susr->type->name);
1372  // record swig type of faudes plain Type
1373  swig_type_info* stype =susr->type;
1374  lua_pop(pLL, 2);
1375  // stack: [fobject]
1376  // test user data pointer 1 (this could be any user data, so we use SwigUserData to test)
1377  susr = SwigUserData(pLL, -1);
1378  if(!susr) {
1379  std::stringstream errstr;
1380  errstr << "unknown data type";
1381  lua_settop(pLL,savetop);
1382  throw Exception("LuaState::Pop()", errstr.str(), 49);
1383  }
1384  // cast to faudes Type
1385  void* fptr=SwigCastPtr(susr->ptr,susr->type,stype);
1386  FD_DLB("LuaState::Pop(): swig usrdata ptr " << susr->ptr);
1387  FD_DLB("LuaState::Pop(): swig stype " << susr->type->name);
1388  FD_DLB("LuaState::Pop(): faudes::Type converted ptr " << fptr);
1389  if(!fptr) {
1390  std::stringstream errstr;
1391  errstr << "faild to cast stype \"" << susr->type->name << "\" to plain Type";
1392  lua_settop(pLL,savetop);
1393  throw Exception("LuaState::Pop()", errstr.str(), 49);
1394  }
1395  // copy data
1396  res=((Type*)fptr)->Copy();
1397  // stack: [fobject]
1398  lua_pop(pLL,1);
1399  FD_DLB("LuaFunction::Pop(): done");
1400  return res;
1401 }
1402 
1403 // access global variables
1404 Type* LuaState::Global(const std::string& gname, const Type* fdata) {
1405  return Global(mpLL,gname,fdata);
1406 }
1407 
1408 // access global variables
1409 Type* LuaState::Global(lua_State* pLL, const std::string& gname, const Type* fdata) {
1410  // get
1411  if(fdata==NULL) {
1412  lua_getfield(pLL, LUA_GLOBALSINDEX, gname.c_str());
1413  return Pop(pLL);
1414  }
1415  // set
1416  else {
1417  Push(pLL,fdata);
1418  lua_setfield(pLL, LUA_GLOBALSINDEX, gname.c_str());
1419  return 0;
1420  }
1421 }
1422 
1423 
1424 // evaluate a Lua expression
1425 void LuaState::Evaluate(const std::string& expr) {
1426  Evaluate(mpLL,expr);
1427 }
1428 
1429 // evaluate a Lua expression
1430 void LuaState::Evaluate(lua_State* pLL, const std::string& expr) {
1431  FD_DLB("LuaFunction::Evaluate()");
1432 
1433  // record top of stack
1434  int top = lua_gettop(pLL);
1435 
1436  // load
1437  std::string cerr;
1438  if(cerr=="")
1439  if(luaL_loadbuffer(pLL, expr.c_str(), expr.size(), "string")) {
1440  cerr=std::string(lua_tostring(pLL, -1));
1441  lua_pop(pLL, 1);
1442  }
1443 
1444  // evaluate
1445  if(cerr=="")
1446  if(lua_pcall(pLL, 0, LUA_MULTRET, 0)){
1447  cerr=std::string(lua_tostring(pLL, -1));
1448  lua_pop(pLL, 1);
1449  }
1450 
1451  // fix stack (ignore results etc)
1452  lua_settop(pLL,top);
1453  lua_gc(pLL, LUA_GCCOLLECT, 0);
1454 
1455  // throw on error
1456  if(cerr!="") {
1457  lua_settop(pLL,top);
1458  throw Exception("LuaState::Evaluate()", cerr, 49);
1459  }
1460 
1461  return;
1462 }
1463 
1464 
1465 // completion
1466 std::list< std::string > LuaState::Complete(const std::string& word) {
1467  return Complete(mpLL,word);
1468 }
1469 
1470 // evaluate a Lua expression
1471 std::list< std::string > LuaState::Complete(lua_State* pLL, const std::string& word) {
1472  FD_DLB("LuaFunction::Complete(" << word <<")");
1473  return faudes_rl_complete(pLL,word);
1474 }
1475 
1476 
1477 
1478 } // namespace
1479 
#define FD_WARN(message)
Debug: always report warnings.
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
faudes type implementation macros, overall
Definition: cfl_types.h:946
const std::string & Name(void) const
Get name of the entety to document (aka faudes-type or faudes-function).
Definition: cfl_types.cpp:396
std::string KeywordAt(int pos) const
Definition: cfl_types.cpp:452
const std::string & PlugIn(void) const
Get name of plugin.
Definition: cfl_types.cpp:397
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Write configuration data of this object to TokenWriter.
Definition: cfl_types.cpp:642
const std::string & TextDoc(void) const
Definition: cfl_types.cpp:399
const std::string & CType(void) const
Get corresponding C++ type.
Definition: cfl_types.cpp:398
std::string mName
Faudes name.
Definition: cfl_types.h:1415
std::string mPlugIn
Faudes plugin.
Definition: cfl_types.h:1418
Faudes exception class.
virtual const char * What() const
Returns error description.
A FunctionDefinition defines the interface to a faudes-function.
const Signature & Variant(const std::string &rName) const
Return reference to Signature by name.
void DoAssign(const FunctionDefinition &rSrc)
Std faudes type interface: assignment.
int VariantsSize(void) const
Return number of supported Signature instances.
const Function * Prototype(void) const
Return pointer to function object prototype.
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Read configuration data of this object from TokenReader.
virtual void DoReadCore(TokenReader &rTr)
Read configuration data of this object from TokenReader.
bool DoEqual(const FunctionDefinition &rOther) const
Std faudes type interface: test equality.
virtual void DoWriteCore(TokenWriter &rTw) const
Write configuration data of this object to TokenWriter.
Function * mpFunction
Prototype instance.
virtual void Clear(void)
Clear documentation-data and signature (keep prototype)
Iterator End(void) const
STL interator to the internal function-name map.
static FunctionRegistry * G()
Method to access the single global instance of the registry.
std::map< std::string, FunctionDefinition * >::const_iterator Iterator
Convenience typedef to access registry entries.
Definition: cfl_registry.h:501
void Insert(FunctionDefinition *pFunctionDef)
Add another function definition to the registry.
Iterator Begin(void) const
STL interator to the internal function-name map.
A faudes-function hosts parameter values of some faudes type and provides a method to perform an oper...
virtual void Definition(const FunctionDefinition *fdef)
Set function definition.
void Variant(int n)
Set signature from function definition.
const Signature * Variant(void) const
Return pointer to assigned faudes::Signature.
const FunctionDefinition * Definition(void) const
Get function definition.
void FreeValues(void)
Destruct parameter values.
void AllocateValues(void)
Construct parameter values.
virtual void DoVariant(int n)
std::vector< Type * > mParameterValues
Vector of arguments.
void ParamValue(int n, Type *param)
Set parameter at certain position.
int mVariantIndex
current variant aka signature as index w.r.t.
int VariantsSize(void) const
Return number of variants.
A LuaFunctionDefinition is derived from FunctionDefinition to define a faudes-function by a Lua scrip...
Definition: lbp_function.h:140
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Read configuration data of this object from TokenReader.
virtual void DoWriteCore(TokenWriter &rTw) const
Write configuration data of this object to TokenWriter.
void Install(LuaState *pL=NULL) const
Install this function to a Lua state.
LuaState * pDefaultL
Default lua state.
Definition: lbp_function.h:396
std::string SyntaxCheck(void)
Syntax check lua code.
virtual void DoReadCore(TokenReader &rTr)
Read configuration data of this object from TokenReader.
std::string mLuaFile
Lua file.
Definition: lbp_function.h:393
LuaState * DefaultL(void) const
Get default lua state.
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Write configuration data of this object to TokenWriter.
LuaFunction * pLuaFunction
Typed prototype instance.
Definition: lbp_function.h:387
std::string Evaluate(LuaState *pL=NULL)
Evaluate lua code.
void DefaultL(LuaState *pL)
Set default lua state.
LuaFunctionDefinition(const std::string &name="")
Constructor.
std::string mLuaCode
Lua code.
Definition: lbp_function.h:390
void Clear(void)
Clear documentation-data, signature and script (keep prototype)
static void Register(const std::string &rFilename)
const std::string & LuaCode(void) const
Get Lua code.
virtual bool DoEqual(const LuaFunctionDefinition &rOther) const
Std faudes type interface: test equality.
virtual void DoAssign(const LuaFunctionDefinition &rSrc)
Std faudes type interface: assignment.
A LuaFunction is a faudes-function that executes a luafaudes script.
Definition: lbp_function.h:677
LuaState * L(void)
Get default lua state.
virtual void DoExecuteC()
Execute stages.
std::vector< bool > mLParameter
Definition: lbp_function.h:878
void SyntaxCheck(void)
Syntax check lua code.
virtual void DoExecuteB()
Execute stages.
void L(LuaState *l)
Set lua state.
virtual void DoExecuteD()
Execute stages.
LuaState * pL
State of Lua interpreter.
Definition: lbp_function.h:872
virtual void DoExecute()
Executes code as supplied by FunctionDefinition.
LuaFunction(const LuaFunctionDefinition *fdef)
Constructor.
virtual void DoExecuteE()
Execute stages.
void Evaluate(void)
Evaluate lua code.
virtual bool DoTypeCheck(int n)
Method to test the type of an assigned parameter with the specified faudes::Signature (i....
virtual LuaFunction * New() const
Construct on heap.
const LuaFunctionDefinition * pLuaFuncDef
Typed reference to definition.
Definition: lbp_function.h:869
std::vector< bool > mLReturn
Definition: lbp_function.h:877
virtual void DoVariant(int n)
const LuaFunctionDefinition * Definition(void) const
Get function definition.
virtual void DoExecuteA()
Execute stages.
Wrapper class to maintain a Lua state.
Definition: lbp_function.h:413
lua_State * mpLL
Definition: lbp_function.h:657
static void Initialize(lua_State *pLL)
Initialze.
Type * Global(const std::string &gname, const Type *fdata=0)
Get/set global data.
Type * Pop(void)
Pop faudes typed object from Lua stack.
static LuaState * G(void)
Convenience global Lua state.
void Install(const std::string &rFilename)
Install LuaExtension to Lua state.
void Close(void)
void Evaluate(const std::string &expr)
Evaluate Lua expression.
void Open(void)
void Reset(void)
Reinitialize Lua state.
lua_State * LL(void)
Access Lua state.
std::list< std::string > Complete(const std::string &word)
Complete Lua identifier.
void Push(const Type *fdata)
Push faudes typed object on the Lua stack.
LuaState(void)
Constructor.
~LuaState(void)
Destructor.
std::string Str(void) const
Convenience method to produce a textual representation of a parameter.
bool CReturn(void) const
Get C-Return flag.
ParamAttr
A function parameter has has one out of four so called io-attrributes;.
Definition: cfl_functions.h:52
const std::string & Type(void) const
Get type.
const ParamAttr & Attribute(void) const
Get Attribute.
Signature of a Function.
int Size(void) const
Return number of parameters.
const std::string & Name(void) const
Return signature name.
const Parameter & At(int n) const
Get parameter type by position.
A TokenReader reads sequential tokens from a file or string.
const Type * Prototype(const std::string &rTypeName) const
Look up the prototype object by faudes-type name.
static TypeRegistry * G()
Method to access the single global instance of the registry.
Base class of all libFAUDES objects that participate in the run-time interface.
Definition: cfl_types.h:239
virtual const std::string & Name(void) const
Get objects's name.
Definition: cfl_types.cpp:122
Type(void)
Constructor.
Definition: cfl_types.cpp:45
const std::string & FaudesTypeName(const Type &rObject)
Query type name.
static std::list< std::string > faudes_rl_complete(lua_State *L, const std::string &word)
luafaudes class to run scripts as rti functions
Includes all luabindings plug-in headers.
#define FD_DLB(message)
Definition: lbp_include.h:231
libFAUDES resides within the namespace faudes.
struct faudes::swig_type_info swig_type_info
struct swig_type_info *(* swig_dycast_func)(void **)
void * SwigCastPtr(void *ptr, swig_type_info *from, swig_type_info *ty)
void faudes_hook_register(lua_State *L)
Definition: lbp_addons.cpp:109
struct faudes::swig_cast_info swig_cast_info
swig_lua_userdata * SwigUserData(lua_State *L, int index)
FAUDES_API void faudes_dict_insert_entry(const std::string &topic, const std::string &key, const std::string &entry)
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.cpp:43
void faudes_print_register(lua_State *L)
Definition: lbp_addons.cpp:86
void *(* swig_converter_func)(void *, int *)
std::string MangleString(const std::string &str)
swig_type_info * type
swig_converter_func converter
struct swig_cast_info * prev
struct swig_cast_info * next
struct swig_cast_info * cast
swig_dycast_func dcast

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen