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- 2025 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 c-return 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="(argn==" + 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  lfwrap << " local arg = {...}" << std::endl; // Lua >= 5.1.x, omitt for earlier versions
496  lfwrap << " local argn = #arg" << std::endl; // Lua >= 5.1.x, use "local argn=arg['n']" for earlier versions
497  for(unsigned int i=0; i< lftest1.size(); i++) {
498  lfwrap << " if (" << lftest1.at(i) << ") then " << std::endl;
499  lfwrap << " if (" << lftest2.at(i) << ") then " << std::endl;
500  lfwrap << " return faudes." << lfcall.at(i) << std::endl;
501  lfwrap << " end" << std::endl;
502  lfwrap << " end" << std::endl;
503  }
504  lfwrap << " faudes.Error([[" << lfname << ": parameter mismatch: expected signature(s): " << std::endl;
505  for(unsigned int i=0; i< lfsig.size(); i++) {
506  lfwrap << lfsig.at(i) << std::endl;
507  }
508  lfwrap << "]])" << std::endl;
509  lfwrap << "end" << std::endl;
510 
511 
512  // debugging report
513  FD_DLB("LuaFunctionDefinition:Install(): code:" << std::endl << lfwrap.str());
514  FD_DLB("LuaFunctionDefinition:Install(): code: done");
515 
516  // finally install (aka run) the wrapper
517  int errexec=luaL_dostring(pLL,lfwrap.str().c_str());
518  if(errexec!=0) {
519  std::string lerr= std::string(lua_tostring(pLL, -1));
520  int c1 = lerr.find_first_of(':');
521  if(c1<0) c1=0;
522  int c2 = lerr.find_first_of(':',c1+1);
523  if(c2<0) c2=1;
524  std::string line = lerr.substr(c1+1,c2-c1-1);
525  if(c2>1) {
526  lerr="error in Lua script: line " + line + ": " + lerr.substr(c2+2);
527  }
528  throw Exception("LuaFunctionDefinition::Install(): " + Name(), lerr, 49);
529  }
530 }
531 
532 // token io
533 void LuaFunctionDefinition::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
534  FD_DLB("LuaFunctionDefinition::DoRead()");
535  // ignore
536  (void) pContext;
537  // label
538  std::string label=rLabel;
539  if(label=="") label="LuaFunctionDefinition";
540  // base can handle this
541  FunctionDefinition::DoRead(rTr,label,pContext);
542  // report
543  FD_DLB("LuaFunctionDefinition::DoRead(): done " << mPlugIn << "::" << mName);
544 }
545 
546 
547 // register all definitions froma file with the function registry
548 void LuaFunctionDefinition::Register(const std::string& rFilename) {
549  FD_DLB("LuaFunctionDefinition::Register(): file " << rFilename);
550  TokenReader tr(rFilename);
551  Token token;
552  while(tr.Peek(token)) {
553  if(!token.IsBegin("LuaFunctionDefinition")) {
554  tr.Get(token);
555  continue;
556  }
558  plfd->Read(tr);
559  FD_DLB("LuaFunctionDefinition::Register(): found " << plfd->Name());
560  if(FunctionRegistry::G()->Exists(plfd->Name())) {
561  FD_DLB("LuaFunctionDefinition::Register(): skipping doublet " << plfd->Name());
562  delete plfd;
563  continue;
564  }
565  // Registry takes ownership
566  FunctionRegistry::G()->Insert(plfd);
567  }
568 }
569 
570 
571 // token io
572 void LuaFunctionDefinition::DoReadCore(TokenReader& rTr) {
573  FD_DLB("LuaFunctionDefinition::DoReadCore()");
574  // call base
576  // read my members
577  Token token;
578  rTr.Peek(token);
579  // case a: embedded lua code
580  if(token.IsBegin())
581  if(token.StringValue()=="LuaCode") {
582  mLuaFile="";
583  rTr.ReadVerbatim("LuaCode",mLuaCode);
584  }
585  // case b: lua file
586  if(token.IsBegin())
587  if(token.StringValue()=="LuaFile") {
588  rTr.ReadBegin("LuaFile");
589  std::string mLuaFile=rTr.ReadString();
590  // todo: read that file
591  rTr.ReadEnd("LuaFile");
592  }
593 }
594 
595 
596 // token io
597 void LuaFunctionDefinition::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
598  // label
599  std::string label=rLabel;
600  if(label=="") label="LuaFunctionDefinition";
601  // base can handle
602  Documentation::DoWrite(rTw,label,pContext);
603 }
604 
605 // token io
606 void LuaFunctionDefinition::DoWriteCore(TokenWriter& rTw) const {
607  FD_DLB("LuaFunctionDefinition::DoWriteCore(): file " << rTw.FileName());
608  // call base core
610  // case a: embedded code
611  if(mLuaFile=="") {
612  rTw.WriteVerbatim("LuaCode",mLuaCode);
613  }
614  // case a: embedded code
615  if(mLuaFile!="") {
616  rTw.WriteBegin("LuaFile");
617  rTw.WriteString(mLuaFile);
618  rTw.WriteEnd("LuaFile");
619  // todo: write that file
620  }
621 }
622 
623 /*
624 ********************************************************************
625 ********************************************************************
626 ********************************************************************
627 
628 Implementation of class LuaFunction
629 
630 ********************************************************************
631 ********************************************************************
632 ********************************************************************
633 */
634 
635 // Constructor
636 LuaFunction::LuaFunction(const LuaFunctionDefinition* fdef) :
637  Function(fdef),
638  pLuaFuncDef(fdef),
639  pL(0),
640  pLL(0)
641 {
642  FD_DLB("LuaFunction::LuaFunction(): fdef " << pFuncDef);
643 }
644 
645 // new on heap
646 LuaFunction* LuaFunction::New(void) const {
647  return new LuaFunction(pLuaFuncDef);
648 }
649 
650 // set function definition
651 void LuaFunction::Definition(const FunctionDefinition* fdef) {
652  // cast and pass to base
653  pLuaFuncDef = dynamic_cast<const LuaFunctionDefinition*>(fdef);
655 }
656 
657 // get function definition
658 const LuaFunctionDefinition* LuaFunction::Definition(void) const {
659  return pLuaFuncDef;
660 }
661 
662 // set variant signature (accept -1)
663 void LuaFunction::DoVariant(int n) {
664  // std case by base
665  if(n!=-1) {
667  return;
668  }
669  // special case -1
670  mVariantIndex=-1;
671  mParameterValues.clear();
672 }
673 
674 
675 // implement typecheck
676 bool LuaFunction::DoTypeCheck(int n) {
677  FD_DLB("LuaFunction::DoTypeCheck("<< n << "): for " << Variant()->At(n).Type());
678  const Type* proto = TypeRegistry::G()->Prototype(Variant()->At(n).Type());
679  if(!proto) {
680  FD_DLB("LuaFunction::DoTypeCheck("<< n << "): unknown type");
681  return false;
682  }
683  if(!proto->Cast(ParamValue(n))) {
684  FD_DLB("LuaFunction::DoTypeCheck("<< n << "): could not cast param value");
685  return false;
686  }
687  return true;
688 }
689 
690 
691 // get/set lua state
692 LuaState* LuaFunction::L(void) {
693  if(!pL) pL=Definition()->DefaultL();
694  return pL;
695 }
696 
697 // get/set default lua state
698 void LuaFunction::L(LuaState* l) {
699  pL=l;
700 }
701 
702 
703 // implement execute: run stages
704 void LuaFunction::DoExecute(void) {
705  FD_DLB("LuaFunction::DoExecute()");
706  /*
707  for(int i=0; i< Variant()->Size(); i++) {
708  FD_DLB("LuaFunction::DoExecute(): value at #" << i);
709  ParamValue(i)->Write();
710  }
711  */
712  // use the global state
713  if(!pL) pL=L();
714  pLL=pL->LL();
715  mEntryStack=lua_gettop(pLL);
716  // run stages
717  DoExecuteA();
718  DoExecuteB();
719  DoExecuteC();
720  DoExecuteD();
721  DoExecuteE();
722  // done
723  lua_settop(pLL,mEntryStack);
724  FD_DLB("LuaFunction::DoExecute(): done");
725 }
726 
727 // implement execute: syntaxcheck
728 void LuaFunction::SyntaxCheck(void) {
729  FD_DLB("LuaFunction::SyntaxCheck()");
730  if(!Variant()) {
731  std::stringstream errstr;
732  errstr << "no valid variant";
733  throw Exception("LuaFunction::Syntaxcheck()", errstr.str(), 47);
734  }
735  // use the global state
736  if(!pL) pL=L();
737  pLL=pL->LL();
738  mEntryStack=lua_gettop(pLL);
739  // run stages
740  DoExecuteA();
741  DoExecuteB();
742  // done
743  lua_settop(pLL,mEntryStack);
744  FD_DLB("LuaFunction::SyntaxCheck(): done");
745 }
746 
747 // implement execute: plain evaluation
748 void LuaFunction::Evaluate(void) {
749  FD_DLB("LuaFunction::SyntaxCheck()");
750  // use the global state
751  if(!pL) pL=L();
752  pLL=pL->LL();
753  mEntryStack=lua_gettop(pLL);
754  // run stages
755  DoExecuteA();
756  // done
757  lua_settop(pLL,mEntryStack);
758  FD_DLB("LuaFunction::SyntaxCheck(): done");
759 }
760 
761 // implement execute: run lua code i.e. define lua functions
762 void LuaFunction::DoExecuteA(void) {
763  FD_DLB("LuaFunction::DoExecuteA()");
764  // Lua stack: empty
765  // load my script
766  const char* script = pLuaFuncDef->LuaCode().c_str();
767  int script_len = pLuaFuncDef->LuaCode().size();
768  int errload=luaL_loadbuffer(pLL, script, script_len, "luafaudes");
769  if(errload!=0) {
770  std::string lerr= std::string(lua_tostring(pLL, -1));
771  int c1 = lerr.find_first_of(':');
772  if(c1<0) c1=0;
773  int c2 = lerr.find_first_of(':',c1+1);
774  if(c2<0) c2=1;
775  std::string line = lerr.substr(c1+1,c2-c1-1);
776  if(c2>1) {
777  lerr="error in Lua script: line " + line + ": " + lerr.substr(c2+2);
778  }
779  lua_settop(pLL,mEntryStack);
780  throw Exception("LuaFunction::DoExecuteA()", lerr, 49);
781  }
782  // Lua stack: script
783  // install all functions aka run the script
784  int errrun=lua_pcall(pLL, 0, 0, 0);
785  if(errrun!=0) {
786  std::stringstream errstr;
787  errstr << "failed to run script: ";
788  errstr << std::string(lua_tostring(pLL, -1));
789  lua_settop(pLL,mEntryStack);
790  throw Exception("LuaFunction::DoExecuteA()", errstr.str(), 49);
791  }
792  // stack: []
793 }
794 
795 // implement execute: find the function of this variant
796 void LuaFunction::DoExecuteB(void) {
797  FD_DLB("LuaFunction::DoExecuteB()");
798  // Lua stack: empty
799  // get the swig generated table of faudes functions
800  lua_getglobal(pLL,"faudes");
801  mFtable=lua_gettop(pLL);
802  if(!lua_istable(pLL,-1)) {
803  lua_settop(pLL,mEntryStack);
804  throw Exception("LuaFunction::DoExecuteB()", "failed to load faudes table", 49);
805  }
806  // stack: [faudes]
807  // find my function: look up in faudes name space ...
808  std::string fname = MangleString(Variant()->Name());
809  lua_pushstring(pLL,fname.c_str());
810  lua_gettable(pLL,mFtable);
811  if(!lua_isfunction(pLL,-1)) {
812  lua_pop(pLL, 1); // pop nil.
813  lua_getglobal(pLL,fname.c_str()); // ... or as global (compatibility with pre 2.19)
814  if(!lua_isfunction(pLL,-1)) {
815  std::stringstream errstr;
816  errstr << "missing function \"" << fname << "\"";
817  lua_settop(pLL,mEntryStack);
818  throw Exception("LuaFunction::DoExecuteB()", errstr.str(), 49);
819  }
820  }
821  // stack: [faudes, luafnct]
822  // construct a plain Type usrdata
823  lua_pushstring(pLL,"Type");
824  lua_gettable(pLL,mFtable);
825  if(!lua_isfunction(pLL,-1))
826  if(!lua_istable(pLL,-1)) { /* tmoor 201407 for swig 3.02 */
827  lua_settop(pLL,mEntryStack);
828  throw Exception("LuaFunction::DoExecuteB():", "failed to construct plain Type (1)", 49);
829  }
830  // stack: [faudes, luafnct, Type constructor]
831  if(lua_pcall(pLL, 0, 1, 0) != 0) {
832  lua_settop(pLL,mEntryStack);
833  throw Exception("LuaFunction::DoExecuteB():", "failed to construct plain Type (2)", 49);
834  }
835  // stack: [faudes, luafnct, Type variable]
836  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
837  if(!susr) {
838  lua_settop(pLL,mEntryStack);
839  throw Exception("LuaFunction::DoExecuteB():", "failed to construct plain Type (3)", 49);
840  }
841  FD_DLB("LuaFunction::DoExecuteB(): plain type is " << susr->type->name);
842  // record swig type of faudes plain Type
843  mFType=susr->type;
844  lua_pop(pLL, 1);
845  // stack: [faudes, luafnct]
846 }
847 
848 
849 
850 // implement execute: prepare parameters
851 void LuaFunction::DoExecuteC(void) {
852  FD_DLB("LuaFunction::DoExecuteC()");
853  // stack: [faudes, luafnct]
854  // interpret signature
855  mLReturn.resize(Variant()->Size());
856  mLParameter.resize(Variant()->Size());
857  mLReturnCount=0;
859  for(int i=0; i< Variant()->Size(); i++) {
860  const std::string& ftype= Variant()->At(i).Type();
861  // default: parameter except for explicit creturn && out
862  mLParameter.at(i)= !(Variant()->At(i).CReturn() && (Variant()->At(i).Attribute()==Parameter::Out));
863  // default: explicitly declared creturn
864  mLReturn.at(i)= Variant()->At(i).CReturn();
865  // autofix elementary parameters
866  if((ftype=="Integer") || (ftype=="Boolean") || (ftype=="String")) {
867  // ... out becomes return value only
868  if(Variant()->At(i).Attribute()==Parameter::Out) {
869  mLReturn.at(i)=true;
870  mLParameter.at(i)=false;
871  }
872  // ... inout becomes return value and parameter
873  if(Variant()->At(i).Attribute()==Parameter::InOut) {
874  mLReturn.at(i)=true;
875  mLParameter.at(i)=true;
876  }
877  // ... in becomes parameter only
878  if(Variant()->At(i).Attribute()==Parameter::In) {
879  mLReturn.at(i)=false;
880  mLParameter.at(i)=true;
881  }
882  }
883  // keep counts
884  if(mLReturn.at(i)) mLReturnCount++;
885  if(mLParameter.at(i)) mLParameterCount++;
886  }
887 
888  FD_DLB("LuaFunction::DoExecuteC(): found " << mLReturnCount << " return values and "
889  << mLParameterCount << " parameters");
890  // stack: [faudes, luafnct]
891  // construct my parameters in Lua
892  for(int i=0; i< Variant()->Size(); i++) {
893  const std::string& ftype= Variant()->At(i).Type();
894  // skip non-parameter
895  if(!mLParameter.at(i)) {
896  FD_DLB("LuaFunction::DoExecuteC(): skip nonparameter value pos " << i);
897  continue;
898  }
899  // special case: int as lua number
900  if(ftype=="Integer") {
901  lua_pushnumber(pLL,((Integer*)ParamValue(i))->CValue());
902  FD_DLB("LuaFunction::DoExecuteC(): created ftype " << ftype);
903  continue;
904  }
905  // special case: bool as lua bool
906  if(ftype=="Boolean") {
907  lua_pushboolean(pLL,((Boolean*)ParamValue(i))->CValue());
908  FD_DLB("LuaFunction::DoExecuteC(): created ftype " << ftype);
909  continue;
910  }
911  // special case: str as lua string
912  if(ftype=="String") {
913  lua_pushstring(pLL,((String*)ParamValue(i))->CValue().c_str());
914  FD_DLB("LuaFunction::DoExecuteC(): created ftype " << ftype);
915  continue;
916  }
917  // std case: faudes type: construct 1
918  lua_pushstring(pLL,ftype.c_str());
919  lua_gettable(pLL,mFtable);
920  if(!lua_isfunction(pLL,-1))
921  if(!lua_istable(pLL,-1)) { /* tmoor 201407 for swig 3.02 */
922  std::stringstream errstr;
923  errstr << "failed to load constructor for \"" << ftype << "\"";
924  lua_settop(pLL,mEntryStack);
925  throw Exception("LuaFunction::DoExecuteC()", errstr.str(), 49);
926  }
927  // std case: faudes type: construct 2
928  if(lua_pcall(pLL, 0, 1, 0) != 0) {
929  std::stringstream errstr;
930  errstr << "failed to construct for \"" << ftype << "\" (1)";
931  lua_settop(pLL,mEntryStack);
932  throw Exception("LuaFunction::DoExecuteC()", errstr.str(), 49);
933  }
934  // std case: test user data pointer
935  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
936  if(!susr) {
937  std::stringstream errstr;
938  errstr << "failed to construct for\"" << ftype << "\" (2)";
939  lua_settop(pLL,mEntryStack);
940  throw Exception("LuaFunction::DoExecuteB()", errstr.str(), 49);
941  }
942  // inspect stack
943  FD_DLB("LuaFunction::DoExecuteC(): created stype " << susr->type->name << " for ftype " << ftype);
944  FD_DLB("LuaFunction::DoExecuteC(): faudes parameter at " << ParamValue(i));
945  FD_DLB("LuaFunction::DoExecuteC(): swig usrdata ptr " << susr->ptr);
946  FD_DLB("LuaFunction::DoExecuteC(): swig usrdata own flag " << susr->own);
947  /*
948  // variant a: copy parameter value
949  void* fptr=SwigCastPtr(susr->ptr,susr->type,(swig_type_info*)mFType);
950  FD_DLB("LuaFunction::DoExecuteB(): faudes::Type converted ptr " << fptr);
951  if(Variant()->At(i).Attribute()!=Parameter::Out) {
952  FD_DLB("LuaFunction::DoExecuteB(): copy parameter value");
953  ((Type*)fptr)->Assign(*ParamValue(i));
954  }
955  */
956  // variant b: use references
957  if(susr->own) free(susr->ptr);
958  susr->own=0;
959  susr->ptr = dynamic_cast<void*>(ParamValue(i)); // dynamic-up-cast: needed for multiple inheritance (!!)
960  }
961  // stack: [faudes, luafnct, rp_1 ... rp_n]
962  FD_DLB("LuaFunction::DoExecuteC(): done");
963 }
964 
965 // implement execute: execute the function
966 void LuaFunction::DoExecuteD(void) {
967  FD_DLB("LuaFunction::DoExecuteD()");
968  // stack: [faudes, luafnct, rp_1 ... rp_n]
969  // duplicate all my parameters (incl. the actual function for convenience)
970  // note: needed only for variant a to retrieve values of faudes typed parameters
971  // note: duplication is cheap since these are references
972  int t1=lua_gettop(pLL)-mLParameterCount;
973  int t2=lua_gettop(pLL);
974  for(int i= t1; i<=t2; i++) {
975  lua_pushvalue(pLL,i);
976 #ifdef FAUDES_DEBUG_LUABINDINGS
977  // report user data
978  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
979  if(!susr) continue;
980  // inspect user data stack
981  FD_DLB("LuaFunction::DoExecuteD(): inspect stype " << susr->type->name);
982  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata ptr " << susr->ptr);
983  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata own flag " << susr->own);
984  void* fptr=SwigCastPtr(susr->ptr,susr->type,(swig_type_info*)mFType);
985  FD_DLB("LuaFunction::DoExecuteD(): faudes::Type converted ptr " << fptr);
986 #endif
987  }
988  // stack: [faudes, luafnct, rp_1 ... rp_n, luafnct, rp_1 ... rp_n]
989  // run my function
990  if(lua_pcall(pLL, mLParameterCount, mLReturnCount, 0) != 0) {
991  FD_DLB("LuaFunction::DoExecuteD(): detect error");
992  std::string lerr= std::string(lua_tostring(pLL, -1));
993  // user request via loopback exception
994  if(lerr.find("break on application request")!=std::string::npos) {
995  lerr="break on application request";
996  }
997  // user request via explicit exception
998  else if(lerr.find("luafaudes script:")!=std::string::npos) {
999  std::size_t c1=lerr.find("luafaudes script:");
1000  lerr=lerr.substr(c1);
1001  }
1002  // have line number ?
1003  else if(lerr.size()>=2) {
1004  std::size_t c1 = lerr.find_first_of(':');
1005  if(c1==std::string::npos) c1=0;
1006  if(c1+1>=lerr.size()) c1=0;
1007  std::size_t c2 = lerr.find_first_of(':',c1+1);
1008  if(c2==std::string::npos) c2=c1+1;
1009  if(c2>c1+1) {
1010  std::string line = lerr.substr(c1+1,c2-c1-1);
1011  lerr="error in Lua script: line " + line + ": " + lerr.substr(c2+2);
1012  }
1013  }
1014  // anyway: fix stack
1015  lua_settop(pLL,mEntryStack);
1016  throw Exception("LuaFunction::DoExecuteD()", lerr, 49);
1017  }
1018  FD_DLB("LuaFunction::DoExecuteD():done ");
1019  // stack: [faudes, luafnct, rp_1 ... rp_n, lp1 ... lpm]
1020 }
1021 
1022 // implement execute: retrieve results
1023 void LuaFunction::DoExecuteE(void) {
1024  FD_DLB("LuaFunction::DoExecuteE()");
1025  // stack: [faudes, luafnct, rp_1 ... rp_n, lp1 ... lpm]
1026  // retrieve results from stack: return values
1027  for(int i=Variant()->Size()-1; i>=0; i--) {
1028  // skip non-return values
1029  if(!mLReturn.at(i)) continue;
1030  // switch on ftype
1031  const std::string& ftype= Variant()->At(i).Type();
1032  // int as lua number
1033  if(ftype=="Integer" && lua_isnumber(pLL,-1)) {
1034  FD_DLB("LuaFunction::DoExecuteE(): retrieve type " << ftype);
1035  ((Integer*)ParamValue(i))->CValue(lua_tonumber(pLL,-1));
1036  lua_pop(pLL, 1);
1037  continue;
1038  }
1039  // bool as lua bool
1040  if(ftype=="Boolean" && lua_isboolean(pLL,-1)) {
1041  ((Boolean*)ParamValue(i))->CValue(lua_toboolean(pLL,-1));
1042  FD_DLB("LuaFunction::DoExecuteE(): retrieved type " << ftype);
1043  lua_pop(pLL, 1);
1044  continue;
1045  }
1046  // str as lua string
1047  if(ftype=="String" && lua_isstring(pLL,-1)) {
1048  ((String*)ParamValue(i))->CValue(lua_tostring(pLL,-1));
1049  FD_DLB("LuaFunction::DoExecuteE(): retrieved type " << ftype);
1050  lua_pop(pLL, 1);
1051  continue;
1052  }
1053  // report error
1054  std::stringstream errstr;
1055  errstr << "invalid return values in \"" << Variant()->Name() << "\"";
1056  lua_settop(pLL,mEntryStack);
1057  throw Exception("LuaFunction::DoExecuteE()", errstr.str(), 49);
1058  }
1059 
1060  // stack: [faudes, luafnct, rp_1 ... rp_n]
1061 
1062  /*
1063  // variant a: need to copy results
1064 
1065  // retrieve results from stack: duplicate references to parameters
1066  for(int i=Variant()->Size()-1; i>=0; i--) {
1067  // skip return values
1068  if(mLReturn.at(i)) continue;
1069  // switch on type type
1070  const std::string& ftype= Variant()->At(i).Type();
1071  // discrad/ignore duplicate parameters with access In
1072  if(Variant()->At(i).Attribute()==Parameter::In) {
1073  FD_DLB("LuaFunction::DoExecuteD(): ignore in-paremeter of type " << ftype);
1074  lua_pop(pLL, 1);
1075  continue;
1076  }
1077  // discrad/ignore elementary types (lua call by value)
1078  if((ftype=="Integer") || (ftype=="Boolean") || (ftype=="String")) {
1079  FD_DLB("LuaFunction::DoExecuteD(): ignore elementary type parameter " << ftype);
1080  lua_pop(pLL, 1);
1081  continue;
1082  }
1083  // std case: get updated value
1084  if(lua_isuserdata(pLL,-1)) {
1085  FD_DLB("LuaFunction::DoExecuteD(): try to retrieve type " << ftype);
1086  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata(pLL, -1);
1087  if(susr) {
1088  FD_DLB("LuaFunction::DoExecuteD(): found swig type " << susr->type->name << " at " << susr->ptr);
1089  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata ptr " << susr->ptr);
1090  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata own flag " << susr->own);
1091  void* fptr=SwigCastPtr(susr->ptr,susr->type,(swig_type_info*)mFType);
1092  FD_DLB("LuaFunction::DoExecuteD(): swig usrdata ptr faudes::Type converted " << fptr);
1093  FD_DLB("LuaFunction::DoExecuteD(): parameter value " << ParamValue(i));
1094  FD_DLB("LuaFunction::DoExecuteD(): copy parameter value");
1095  ParamValue(i)->Assign(*((Type*)fptr));
1096  // pop
1097  lua_pop(pLL, 1);
1098  continue;
1099  }
1100  }
1101 
1102  */
1103 
1104  // variant b: discard duplicate parameters (did not need them for variant b anyway)
1105  for(int i=Variant()->Size()-1; i>=0; i--) {
1106  if(mLReturn.at(i)) continue;
1107  lua_pop(pLL, 1);
1108  }
1109 
1110 }
1111 
1112 
1113 
1114 /*
1115 ********************************************************************
1116 ********************************************************************
1117 ********************************************************************
1118 
1119 LuaState implementation
1120 
1121 ********************************************************************
1122 ********************************************************************
1123 ********************************************************************
1124 */
1125 
1126 // include Mike Pall's completer
1127 #include "lbp_completion.cpp"
1128 
1129 
1130 // construct/destruct
1131 LuaState::LuaState(void) : mpLL(0) { Open(); }
1132 LuaState::~LuaState(void) { Close(); }
1133 
1134 //access
1135 lua_State* LuaState::LL(void) { return mpLL; }
1136 
1137 // re-init
1138 void LuaState::Reset(void) {
1139  // have a new state
1140  Close();
1141  Open();
1142  // install from function registry
1144  for(;fit!=FunctionRegistry::G()->End(); fit++) {
1145  const LuaFunctionDefinition* lfd=dynamic_cast<const LuaFunctionDefinition*>(fit->second);
1146  if(!lfd) continue;
1147  lfd->Install(mpLL);
1148  }
1149 }
1150 
1151 // install extension
1152 void LuaState::Install(const std::string& rFilename) {
1153  Install(mpLL, rFilename);
1154 }
1155 
1156 // static state (convenience)
1157 LuaState* LuaState::G(void) {
1158  static LuaState* sls=NULL;
1159  if(!sls) sls=new LuaState();
1160  return sls;
1161 }
1162 
1163 // open/close lua state
1164 void LuaState::Open(void) {
1165  Close();
1166  FD_DLB("LuaState::Open()");
1167  mpLL=luaL_newstate();
1168  Initialize(mpLL);
1169  faudes_print_register(mpLL); // todo: configure this
1170  faudes_hook_register(mpLL); // todo: configure this
1171  FD_DLB("LuaState::Done()");
1172 }
1173 
1174 // open/close lua state
1175 void LuaState::Close(void) {
1176  if(!mpLL) return;
1177  FD_DLB("LuaState::Close()");
1178  lua_close(mpLL);
1179  mpLL=NULL;
1180 }
1181 
1182 // lua style interface to initialize lua state
1183 void LuaState::Initialize(lua_State* pLL) {
1184  lua_gc(pLL, LUA_GCSTOP, 0); /* stop collector during initialization */
1185  luaL_openlibs(pLL); /* open libraries */
1186  luaopen_faudes_allplugins(pLL); /* install my namespace */
1187  lua_gc(pLL, LUA_GCRESTART, 0); /* restart collector */
1188 }
1189 
1190 
1191 
1192 // convenience function: load all luafunctions defined in a file
1193 void LuaState::Install(lua_State* pLL, const std::string& rFilename) {
1194  FD_DLB("LuaState::Insatll(): file " << rFilename);
1195  TokenReader tr(rFilename);
1196  Token token;
1197  while(tr.Peek(token)) {
1198  // todo: figure title and ... faudes_dict_insert_topic(const std::string& topic, const std::string& text);
1199  if(!token.IsBegin("LuaFunctionDefinition")) {
1200  tr.Get(token);
1201  continue;
1202  }
1203  LuaFunctionDefinition lfd;
1204  lfd.Read(tr);
1205  FD_DLB("LuaState::Install(): found " << lfd.Name());
1206  lfd.Install(pLL);
1207  }
1208 }
1209 
1210 // push a faudes typed object on the stack
1211 void LuaState::Push(const Type* fdata) {
1212  Push(mpLL,fdata);
1213 }
1214 
1215 // push a faudes typed object on the stack
1216 void LuaState::Push(lua_State* pLL, const Type* fdata) {
1217  FD_DLB("LuaFunction::Push()");
1218  int savetop=lua_gettop(pLL);
1219  // stack: []
1220  // get the swig generated table of faudes functions
1221  lua_getglobal(pLL,"faudes");
1222  int ftable=lua_gettop(pLL);
1223  if(!lua_istable(pLL,-1)) {
1224  lua_settop(pLL,savetop);
1225  throw Exception("LuaState::Push()", "failed to load faudes table", 49);
1226  }
1227  // stack: [faudes]
1228  lua_pushstring(pLL,"Type");
1229  lua_gettable(pLL,ftable);
1230  if(!lua_isfunction(pLL,-1))
1231  if(!lua_istable(pLL,-1)) { /* tmoor 201607 for swig 3.02 */
1232  lua_settop(pLL,savetop);
1233  throw Exception("LuaState::Push()", "failed to construct plain Type (1)", 49);
1234  }
1235  // stack: [faudes, Type constructor]
1236  if(lua_pcall(pLL, 0, 1, 0) != 0) {
1237  lua_settop(pLL,savetop);
1238  throw Exception("LuaState::Push()", "failed to construct plain Type (2)", 49);
1239  }
1240  // stack: [faudes, Type variable]
1241  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
1242  if(!susr) {
1243  lua_settop(pLL,savetop);
1244  throw Exception("LuaState::Push()", "failed to construct plain Type (3)", 49);
1245  }
1246  FD_DLB("LuaState::Push(): plain type is " << susr->type->name);
1247  // record swig type of faudes plain Type
1248  swig_type_info* stype =susr->type;
1249  lua_pop(pLL, 1);
1250  // stack: [faudes]
1251  // construct my data in Lua
1252  const std::string& ftype= FaudesTypeName(*fdata);
1253  // special case: int as lua number
1254  if(ftype=="Integer") {
1255  lua_pushnumber(pLL,((const Integer&)*fdata));
1256  FD_DLB("LuaState::Push(): created ftype " << ftype);
1257  }
1258  // special case: bool as lua bool
1259  else if(ftype=="Boolean") {
1260  lua_pushboolean(pLL,((const Boolean&)*fdata));
1261  FD_DLB("LuaState::Push(): created ftype " << ftype);
1262  }
1263  // special case: str as lua string
1264  else if(ftype=="String") {
1265  lua_pushstring(pLL,((const String&)*fdata).CValue().c_str());
1266  FD_DLB("LuaState::Push(): created ftype " << ftype);
1267  }
1268  // std case: faudes type
1269  else {
1270  // construct 1
1271  lua_pushstring(pLL,ftype.c_str());
1272  lua_gettable(pLL,ftable);
1273  if(!lua_isfunction(pLL,-1))
1274  if(!lua_istable(pLL,-1)) { /* tmoor 201607 for swig 3.02 */
1275  std::stringstream errstr;
1276  errstr << "failed to load constructor for \"" << ftype << "\"";
1277  lua_settop(pLL,savetop);
1278  throw Exception("LuaState::Push()", errstr.str(), 49);
1279  }
1280  // construct 2
1281  if(lua_pcall(pLL, 0, 1, 0) != 0) {
1282  std::stringstream errstr;
1283  errstr << "failed to construct for \"" << ftype << "\" (1)";
1284  lua_settop(pLL,savetop);
1285  throw Exception("LuaState::Push()", errstr.str(), 49);
1286  }
1287  // test user data pointer
1288  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
1289  if(!susr) {
1290  std::stringstream errstr;
1291  errstr << "failed to construct for\"" << ftype << "\" (2)";
1292  lua_settop(pLL,savetop);
1293  throw Exception("LuaState::Push()", errstr.str(), 49);
1294  }
1295  // inspect stack
1296  FD_DLB("LuaState::Push(): created stype " << susr->type->name << " for ftype " << ftype);
1297  FD_DLB("LuaState::Push(): faudes parameter at " << fdata);
1298  FD_DLB("LuaState::Push(): swig usrdata ptr " << susr->ptr);
1299  FD_DLB("LuaState::Push(): swig usrdata own flag " << susr->own);
1300  // cast to plain Type
1301  void* fptr=SwigCastPtr(susr->ptr,susr->type,stype);
1302  FD_DLB("LuaState::Push(): faudes plain Type converted ptr " << fptr);
1303  if(!fptr) {
1304  std::stringstream errstr;
1305  errstr << "failed cast from " << ftype;
1306  lua_settop(pLL,savetop);
1307  throw Exception("LuaState::Push()", errstr.str(), 49);
1308  }
1309  ((Type*)fptr)->Assign(*fdata);
1310  }
1311  // stack: [faudes, fdata]
1312  lua_replace(pLL,-2);
1313  FD_DLB("LuaFunction::DoExecuteB(): done");
1314 }
1315 
1316 // pop a faudes typed object from the stack
1317 Type* LuaState::Pop(void) {
1318  return Pop(mpLL);
1319 }
1320 
1321 // pop a faudes typed object from the stack
1322 Type* LuaState::Pop(lua_State* pLL) {
1323  FD_DLB("LuaFunction::Pop()");
1324  int savetop=lua_gettop(pLL);
1325  Type* res=NULL;
1326  // stack: [fobject]
1327  // special cases: integer
1328  if(lua_isnumber(pLL,-1)) {
1329  res= new Integer(lua_tointeger(pLL,-1));
1330  lua_pop(pLL,1);
1331  return res;
1332  }
1333  // special cases: string
1334  if(lua_isstring(pLL,-1)) {
1335  res= new String(lua_tostring(pLL,-1));
1336  lua_pop(pLL,1);
1337  return res;
1338  }
1339  // special cases: string
1340  if(lua_isboolean(pLL,-1)) {
1341  res= new Boolean(lua_toboolean(pLL,-1));
1342  lua_pop(pLL,1);
1343  return res;
1344  }
1345  // stack: [fobject]
1346  // get the swig generated table of faudes functions
1347  lua_getglobal(pLL,"faudes");
1348  int ftable=lua_gettop(pLL);
1349  if(!lua_istable(pLL,-1)) {
1350  lua_settop(pLL,savetop);
1351  throw Exception("LuaState::Pop()", "failed to load faudes table", 49);
1352  }
1353  // stack: [fobject, faudes]
1354  // construct a plain Type usrdata
1355  lua_pushstring(pLL,"Type");
1356  lua_gettable(pLL,ftable);
1357  if(!lua_isfunction(pLL,-1))
1358  if(!lua_istable(pLL,-1)) { /* tmoor 201607 for swig 3.02 */
1359  lua_settop(pLL,savetop);
1360  throw Exception("LuaState::Pop()", "failed to construct plain Type (1)", 49);
1361  }
1362  // stack: [fobject, faudes, Type constructor]
1363  if(lua_pcall(pLL, 0, 1, 0) != 0) {
1364  lua_settop(pLL,savetop);
1365  throw Exception("LuaState::Pop()", "failed to construct plain Type (2)", 49);
1366  }
1367  // stack: [fobject, faudes, Type variable]
1368  swig_lua_userdata* susr = (swig_lua_userdata*) lua_touserdata (pLL, -1);
1369  if(!susr) {
1370  lua_settop(pLL,savetop);
1371  throw Exception("LuaState::Pop()", "failed to construct plain Type (3)", 49);
1372  }
1373  FD_DLB("LuaState::Pop(): plain type is " << susr->type->name);
1374  // record swig type of faudes plain Type
1375  swig_type_info* stype =susr->type;
1376  lua_pop(pLL, 2);
1377  // stack: [fobject]
1378  // test user data pointer 1 (this could be any user data, so we use SwigUserData to test)
1379  susr = SwigUserData(pLL, -1);
1380  if(!susr) {
1381  std::stringstream errstr;
1382  errstr << "unknown data type";
1383  lua_settop(pLL,savetop);
1384  throw Exception("LuaState::Pop()", errstr.str(), 49);
1385  }
1386  // cast to faudes Type
1387  void* fptr=SwigCastPtr(susr->ptr,susr->type,stype);
1388  FD_DLB("LuaState::Pop(): swig usrdata ptr " << susr->ptr);
1389  FD_DLB("LuaState::Pop(): swig stype " << susr->type->name);
1390  FD_DLB("LuaState::Pop(): faudes::Type converted ptr " << fptr);
1391  if(!fptr) {
1392  std::stringstream errstr;
1393  errstr << "faild to cast stype \"" << susr->type->name << "\" to plain Type";
1394  lua_settop(pLL,savetop);
1395  throw Exception("LuaState::Pop()", errstr.str(), 49);
1396  }
1397  // copy data
1398  res=((Type*)fptr)->Copy();
1399  // stack: [fobject]
1400  lua_pop(pLL,1);
1401  FD_DLB("LuaFunction::Pop(): done");
1402  return res;
1403 }
1404 
1405 // access global variables
1406 Type* LuaState::Global(const std::string& gname, const Type* fdata) {
1407  return Global(mpLL,gname,fdata);
1408 }
1409 
1410 // access global variables
1411 Type* LuaState::Global(lua_State* pLL, const std::string& gname, const Type* fdata) {
1412  // get
1413  if(fdata==NULL) {
1414  lua_getglobal(pLL,gname.c_str());
1415  return Pop(pLL);
1416  }
1417  // set
1418  else {
1419  Push(pLL,fdata);
1420  lua_setglobal(pLL,gname.c_str());
1421  return 0;
1422  }
1423 }
1424 
1425 
1426 // evaluate a Lua expression
1427 void LuaState::Evaluate(const std::string& expr) {
1428  Evaluate(mpLL,expr);
1429 }
1430 
1431 // evaluate a Lua expression
1432 void LuaState::Evaluate(lua_State* pLL, const std::string& expr) {
1433  FD_DLB("LuaFunction::Evaluate()");
1434 
1435  // record top of stack
1436  int top = lua_gettop(pLL);
1437 
1438  // load
1439  std::string cerr;
1440  if(cerr=="")
1441  if(luaL_loadbuffer(pLL, expr.c_str(), expr.size(), "string")) {
1442  cerr=std::string(lua_tostring(pLL, -1));
1443  lua_pop(pLL, 1);
1444  }
1445 
1446  // evaluate
1447  if(cerr=="")
1448  if(lua_pcall(pLL, 0, LUA_MULTRET, 0)){
1449  cerr=std::string(lua_tostring(pLL, -1));
1450  lua_pop(pLL, 1);
1451  }
1452 
1453  // fix stack (ignore results etc)
1454  lua_settop(pLL,top);
1455  lua_gc(pLL, LUA_GCCOLLECT, 0);
1456 
1457  // throw on error
1458  if(cerr!="") {
1459  lua_settop(pLL,top);
1460  throw Exception("LuaState::Evaluate()", cerr, 49);
1461  }
1462 
1463  return;
1464 }
1465 
1466 
1467 // completion
1468 std::list< std::string > LuaState::Complete(const std::string& word) {
1469  return Complete(mpLL,word);
1470 }
1471 
1472 // evaluate a Lua expression
1473 std::list< std::string > LuaState::Complete(lua_State* pLL, const std::string& word) {
1474  FD_DLB("LuaFunction::Complete(" << word <<")");
1475  return faudes_rl_complete(pLL,word);
1476 }
1477 
1478 
1479 
1480 } // namespace
1481 
#define FD_WARN(message)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition: cfl_types.h:958
const std::string & Name(void) const
Definition: cfl_types.cpp:565
std::string KeywordAt(int pos) const
Definition: cfl_types.cpp:621
const std::string & PlugIn(void) const
Definition: cfl_types.cpp:566
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Definition: cfl_types.cpp:811
const std::string & TextDoc(void) const
Definition: cfl_types.cpp:568
const std::string & CType(void) const
Definition: cfl_types.cpp:567
std::string mPlugIn
Definition: cfl_types.h:1556
virtual const char * What() const
const Signature & Variant(const std::string &rName) const
void DoAssign(const FunctionDefinition &rSrc)
const Function * Prototype(void) const
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
virtual void DoReadCore(TokenReader &rTr)
bool DoEqual(const FunctionDefinition &rOther) const
virtual void DoWriteCore(TokenWriter &rTw) const
virtual void Clear(void)
Iterator End(void) const
static FunctionRegistry * G()
std::map< std::string, FunctionDefinition * >::const_iterator Iterator
Definition: cfl_registry.h:541
void Insert(FunctionDefinition *pFunctionDef)
Iterator Begin(void) const
virtual void Definition(const FunctionDefinition *fdef)
void Variant(int n)
const Signature * Variant(void) const
const FunctionDefinition * Definition(void) const
void FreeValues(void)
void AllocateValues(void)
virtual void DoVariant(int n)
std::vector< Type * > mParameterValues
void ParamValue(int n, Type *param)
int VariantsSize(void) const
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
virtual void DoWriteCore(TokenWriter &rTw) const
void Install(LuaState *pL=NULL) const
virtual void DoReadCore(TokenReader &rTr)
LuaState * DefaultL(void) const
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
std::string Evaluate(LuaState *pL=NULL)
LuaFunctionDefinition(const std::string &name="")
static void Register(const std::string &rFilename)
const std::string & LuaCode(void) const
virtual bool DoEqual(const LuaFunctionDefinition &rOther) const
virtual void DoAssign(const LuaFunctionDefinition &rSrc)
LuaState * L(void)
virtual void DoExecuteC()
std::vector< bool > mLParameter
Definition: lbp_function.h:877
void SyntaxCheck(void)
virtual void DoExecuteB()
void L(LuaState *l)
virtual void DoExecuteD()
virtual void DoExecute()
LuaFunction(const LuaFunctionDefinition *fdef)
virtual void DoExecuteE()
virtual bool DoTypeCheck(int n)
virtual LuaFunction * New() const
const LuaFunctionDefinition * pLuaFuncDef
Definition: lbp_function.h:868
std::vector< bool > mLReturn
Definition: lbp_function.h:876
virtual void DoVariant(int n)
const LuaFunctionDefinition * Definition(void) const
virtual void DoExecuteA()
lua_State * mpLL
Definition: lbp_function.h:656
static void Initialize(lua_State *pLL)
Type * Global(const std::string &gname, const Type *fdata=0)
Type * Pop(void)
static LuaState * G(void)
void Install(const std::string &rFilename)
void Close(void)
void Evaluate(const std::string &expr)
void Open(void)
void Reset(void)
lua_State * LL(void)
std::list< std::string > Complete(const std::string &word)
void Push(const Type *fdata)
std::string Str(void) const
bool CReturn(void) const
const std::string & Type(void) const
const ParamAttr & Attribute(void) const
int Size(void) const
const std::string & Name(void) const
const Parameter & At(int n) const
const Type * Prototype(const std::string &rTypeName) const
static TypeRegistry * G()
virtual const std::string & Name(void) const
Definition: cfl_types.cpp:128
const std::string & FaudesTypeName(const Type &rObject)
static std::list< std::string > faudes_rl_complete(lua_State *L, const std::string &word)
#define FD_DLB(message)
Definition: lbp_include.h:265
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:122
struct faudes::swig_cast_info swig_cast_info
swig_lua_userdata * SwigUserData(lua_State *L, int index)
void faudes_dict_insert_entry(const std::string &topic, const std::string &key, const std::string &entry)
Definition: swg_utils.cpp:62
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43
void faudes_print_register(lua_State *L)
Definition: lbp_addons.cpp:97
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.33l --- 2025.09.16 --- c++ api documentaion by doxygen