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

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen