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