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