How to store a Lua function into C++ with SLB ( Simple Lua Binder )? - lua

I need to store a Lua function using the library "Simple Lua Binder"
typedef ? TLuaFunction;
class Foo
{
public:
void SetCallback( TLuaFunction f )
{
mCallback = f;
}
void ExecuteCallback()
{
f(); // Calls Lua function
}
private:
TLuaFunction mCallback;
};
// Manager initialization
SLB::Manager scriptManager;
// SetCallback registration into lua
SLB::Class<Foo>( "Foo", &scriptManager )
.constructor()
.set( "SetCallback", &Foo::SetCallback )
.set( "ExecuteCallback", &Foo::ExecuteCallback )
;
char* luaCode =
"SLB.using( SLB )\n"
"o = Foo()\n"
"o:SetCallback( function() \n"
" print( 'Callback executed' ) \n"
" end \n"
") \n"
"o:ExecuteCallback() \n";
SLB::Script script( &scriptManager );
script.doString( luaCode );
// The result is
> "Callback executed"
I don't know if there is a type in SLB library that I can put instead of ? ( see the first line of code ).
Or if I have to do the things different.

Related

Populate a list with Modules and display it in a Dialogbox in DOORS

I need a DXL script that fill a DialogBox with returned Module names'. I have several modules within a project.
Below is my current progress. My idea is to put all Module names in a List and then display the list in a DialogBox.
Can you help me write ´´´fillModulelist()´´´
// This DXL script iterates through all formal modules of the folder
DB dbMain = null
DBE dbeModuleList = null
DBE dbeExport = null
DBE dbeExportPath = null
Folder currFolder = null
string startFolder="/Project/Folder";
int moduleCount=0;
void forAllModulesInFolder(Folder f)
{
Item itemRef;
string shType;
string sItemNameFull;
string sItemName;
Module moduleReference;
for itemRef in f do
{
shType = type(itemRef);
print shType "\t";
sItemNameFull = fullName(itemRef);
print sItemNameFull "\t";
sItemName = name(itemRef);
print sItemName "\n";
if(shType=="Folder")
{
string selectedFolder = sItemNameFull;
Folder f = folder selectedFolder;
forAllModulesInFolder(f);
}
if(shType=="Formal")
{
moduleReference = read(sItemNameFull,false,true);
filtering off;
// do s.th. with the moduleReference
close(moduleReference);
moduleCount++;
}
}}
void fillModuleList()
{
//........... HELP NEEDED........
}
// Main-Method
void main(void)
{
string selectedFolder = startFolder;
Folder f = folder selectedFolder;
forAllModulesInFolder(f);
print "Affected Modules: " moduleCount "\n";
}
main();
Any help provided I would be very thankful.
As the list of modules is for displaying it to the user (and perhaps let them select from that list), it is best to display the full name of the modules, thus I would not store the module reference. You can open the module later, when the user has selected/double clicked the module (supposing that this is what you want). Thus, I fill a Skip list with sItemNameFull, sItemNameFull, but if it suits your script better, you can also fill it with moduleReference, sItemNameFull (use create instead of createString in this case). The changes to your script are marked with //->> and //<<-
// This DXL script iterates through all formal modules of the folder
DB dbMain = null
DBE dbeModuleList = null
DBE dbeExport = null
DBE dbeExportPath = null
Folder currFolder = null
string startFolder="/testtrunk";
int moduleCount=0;
//->>
Skip skModules = createString()
//<<-
void forAllModulesInFolder(Folder f)
{
Item itemRef;
string shType;
string sItemNameFull;
string sItemName;
Module moduleReference;
for itemRef in f do
{
shType = type(itemRef);
print shType "\t";
sItemNameFull = fullName(itemRef);
print sItemNameFull "\t";
sItemName = name(itemRef);
print sItemName "\n";
if(shType=="Folder")
{
string selectedFolder = sItemNameFull;
Folder f = folder selectedFolder;
forAllModulesInFolder(f);
}
if(shType=="Formal")
{
//->>
put (skModules, sItemNameFull, sItemNameFull)
//moduleReference = read(sItemNameFull,false,true);
//filtering off;
// do s.th. with the moduleReference
//close(moduleReference);
//<<-
moduleCount++;
}
}}
//->>
void fillModuleList(Skip skContent, DBE dbeList)
{
empty dbeList
int cnt=0
string sLine
for sLine in skContent do {
insert (dbeList, cnt, sLine)
cnt++
}
}
//<<-
//->>
void DoSomethingWithDoubleClickedModule (DBE x) {
string sModName = get(x)
print "doing something with " sModName "<---\n"
}
void canvasDummyCB( DBE dummy ) { }
void doNothing(DBE x) {}
void prepareGui()
{
const string sArEmpty[] = {}
dbMain = create ("mytitle", styleCentered)
DBE spaceLeft = canvas(dbMain, 0, 0, canvasDummyCB)
spaceLeft->"top"->"form"; spaceLeft->"left"->"form"
spaceLeft->"right"->"unattached"; spaceLeft->"bottom"->"unattached"
DBE spaceRight = canvas(dbMain, 0, 0, canvasDummyCB)
spaceRight->"top"->"form"; spaceRight->"right"->"form"
spaceRight->"left"->"unattached"; spaceRight->"bottom"->"unattached"
DBE dInfoTextLabel = label(dbMain, "choose a module")
dInfoTextLabel->"top"->"form"
dInfoTextLabel->"left"->"flush"->spaceLeft
dInfoTextLabel->"right"->"flush"->spaceRight
dbeModuleList = list( dbMain, "Modules", 200, 15, sArEmpty)
dbeModuleList->"top"->"flush"->dInfoTextLabel
dbeModuleList->"left"->"flush"->spaceLeft
dbeModuleList->"right"->"flush"->spaceRight
realize dbMain
set( dbeModuleList, doNothing, DoSomethingWithDoubleClickedModule)
}
//<<-
// Main-Method
void main(void)
{
//->>
prepareGui()
//<<-
string selectedFolder = startFolder;
Folder f = folder selectedFolder;
setempty(skModules)
forAllModulesInFolder(f);
//->>
fillModuleList (skModules, dbeModuleList)
//<<-
print "Affected Modules: " moduleCount "\n";
}
main();

Basic parsing Flow with Babel not working

I cannot seem to be able to parse Flow using Babel, its not recognising types or "declare" and is coming up with errors on them :-
const fs = require("fs");
const babel = require("#babel/core");
const parser = require('#babel/parser');
const generate = require('#babel/generator').default;
if (process.argv.length == 3) {
const filename = process.argv[2];
const sourceCode = fs.readFileSync(filename).toString();
console.log("sourceCode = ", sourceCode);
var options = {
"sourceType": "module", // parse in strict mode and allow module declarations
"presets": ["#babel/preset-flow"]
};
const parsedAst = parser.parse(sourceCode, options);
console.log("parsedAst = ", parsedAst)
const { codeOutput, map, ast } = babel.transformFromAstSync(parsedAst, sourceCode, { ast: true } );
console.log("ast = ", JSON.stringify(ast, 2, 2))
const output = generate(ast, { /* options */ }, sourceCode);
console.log("codeOutput = ", codeOutput);
console.log("output = ", output);
};
given the following code :-
// #flow strict
const MAX_SUGGESTIONS = 5;
/**
* Given [ A, B, C ] return ' Did you mean A, B, or C?'.
*/
declare function didYouMean(suggestions: $ReadOnlyArray<string>): string;
// eslint-disable-next-line no-redeclare
declare function didYouMean(
subMessage: string,
suggestions: $ReadOnlyArray<string>,
): string;
// eslint-disable-next-line no-redeclare
export default function didYouMean(firstArg, secondArg?) { ... }
I am getting errors on declare also on types :-
C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:730
throw err;
^
SyntaxError: Unexpected token, expected ";" (8:8)
at Parser._raise (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:723:17)
at Parser.raiseWithData (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:716:17)
at Parser.raise (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:710:17)
at Parser.unexpected (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:8610:16)
at Parser.semicolon (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:8592:40)
at Parser.parseExpressionStatement (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11449:10)
at Parser.parseStatementContent (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11050:19)
at Parser.parseStatement (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:10916:17)
at Parser.parseBlockOrModuleBlockBody (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11490:25)
at Parser.parseBlockBody (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11477:10) {
loc: Position { line: 8, column: 8 },
pos: 118
}
Github :-
https://github.com/AaronNGray/babel-flow-parser-test
Tag v0 is without package-lock.json
Need to add some extra details which I cannot think of ???
The following works :-
const fs = require('fs');
const babel = require('#babel/core');
if (process.argv.length == 3) {
const filename = process.argv[2];
const source = fs.readFileSync(filename).toString();
const ast = babel.parseSync(source, {
babelrc: false,
configFile: false,
ast: true,
parserOpts: {
plugins: ['flow', 'jsx'],
},
filename,
});
console.log("ast = ", JSON.stringify(ast, null, 2))
}
I would still like to know if the original will work with modification as its the near enough what is specified in the Babel documentation.

How to get function definition/signature as a string in Clang?

How can I get a function's signature (or at least the entire definition?) as a string using Clang/Libclang, assuming I have its CXCursor or so?
I think that the definition may be somehow obtainable by using the cursor's extents, but I don't really know how (what function to use).
You can use this simple code to get prototype of a function ( name, return type, count of arguments and arguments[name,data type]).
string Convert(const CXString& s)
{
string result = clang_getCString(s);
clang_disposeString(s);
return result;
}
void print_function_prototype(CXCursor cursor)
{
// TODO : Print data!
auto type = clang_getCursorType(cursor);
auto function_name = Convert(clang_getCursorSpelling(cursor));
auto return_type = Convert(clang_getTypeSpelling(clang_getResultType(type)));
int num_args = clang_Cursor_getNumArguments(cursor);
for (int i = 0; i < num_args; ++i)
{
auto arg_cursor = clang_Cursor_getArgument(cursor, i);
auto arg_name = Convert(clang_getCursorSpelling(arg_cursor));
if (arg_name.empty())
{
arg_name = "no name!";
}
auto arg_data_type = Convert(clang_getTypeSpelling(clang_getArgType(type, i)));
}
}
CXChildVisitResult functionVisitor(CXCursor cursor, CXCursor /* parent */, CXClientData /* clientData */)
{
if (clang_Location_isFromMainFile(clang_getCursorLocation(cursor)) == 0)
return CXChildVisit_Continue;
CXCursorKind kind = clang_getCursorKind(cursor);
if ((kind == CXCursorKind::CXCursor_FunctionDecl || kind == CXCursorKind::CXCursor_CXXMethod || kind == CXCursorKind::CXCursor_FunctionTemplate || \
kind == CXCursorKind::CXCursor_Constructor))
{
print_function_prototype(cursor);
}
return CXChildVisit_Continue;
}
You could try using clang_Cursor_getMangling() and demangle the result in order to get the complete definition.
I'm using the following for a project I am working on and it works great for the definition. TL&DR clang_getCursorPrettyPrinted with the policy TerseOutput set to true.
std::string getStdString(const CXString &s)
{
std::string rv = clang_getCString(s);
clang_disposeString(s);
return rv;
}
bool isFunctionImplementation(CXCursor &cursor,std::string &decl,std::string &filename,unsigned &lineno)
{
std::string cs = getStdString(clang_getCursorPrettyPrinted(cursor,nullptr));
if (cs.find('{') == std::string::npos) // Just a declaration, not the "meat" of the function, so we dont care
return false;
clang::LangOptions lo;
struct clang::PrintingPolicy pol(lo);
pol.adjustForCPlusPlus();
pol.TerseOutput = true;
pol.FullyQualifiedName = true;
decl = getStdString(clang_getCursorPrettyPrinted(cursor,&pol));
CXSourceLocation location = clang_getCursorLocation( cursor );
CXFile f;
lineno = 0;
filename = "(None)";
clang_getSpellingLocation(location,&f,&lineno,nullptr,nullptr);
if (lineno)
{
filename = getStdString(clang_File_tryGetRealPathName(f));
}
return isAllowedDirectory(filename);
}
This one checks if the function call is "meat" or just a definition. Obviously you can adjust as needed, including writing your own isAllowedDirectory function. Just pass the cursor, two strings and an unsigned into this as you walk your AST when you hit a declaration type.
I use the following, shorter way with clang 10 (though its using a matcher, not a cursor):
The 2 helper functions are general helpers to get the code snippet as a string.
// helper function 1: find position of end of token
SourceLocation
end_of_the_end(SourceLocation const & start_of_end, SourceManager & sm)
{
using namespace clang;
LangOptions lopt;
return Lexer::getLocForEndOfToken(start_of_end, 0, sm, lopt);
}
// helper function 2:
std::string getSymbolString(clang::SourceManager & sm,
const clang::SourceRange & range)
{
return std::string(sm.getCharacterData(range.getBegin()),
sm.getCharacterData(end_of_the_end(range.getEnd(), sm)));
}
The actual code snippet to get the function declaration string is:
// ... in run() of a matcher:
virtual void run(corct::result_t const & result) override
{
using namespace clang;
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>(fd_bd_name_));
if(f_decl) {
SourceManager & sm(result.Context->getSourceManager());
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>(fd_bd_name_));
auto full_decl_string =
getSymbolString(sm, f_decl->DeclaratorDecl::getSourceRange());
}
}
This will output inline bool test2(std::string const & str, std::vector<std::string> & sss) for the following function:
inline bool test2(std::string const & str, std::vector<std::string> & sss)
{
return true;
}

Friend ostream operator << wont acces private fields

It just wont acces private fields
.hpp:
private:
std::string model;
public:
Piekarnik &operator << (const Ciasto &ciasto);
friend std::ostream &operator<<(std::ostream &os, const Ciasto &ciasto);
.cpp:
Piekarnik &Piekarnik::operator<<(const Ciasto &ciasto)
{
append(ciasto);
return *this;
}
ostream &operator<<(ostream &os, const Piekarnik &piekarnik) // dwuargumentowy;
{
os<<"Piekarnik (model: "<<piekarnik.model<<", temperatura: " << piekarnik.obecnyProgram.temperatura <<", pieczenie: " << EnumToString(piekarnik.obecnyProgram.pieczenie) << ", wlozone ciasto: " << EnumToString(piekarnik.wlozoneCiasto.rodzaj);
return os<<")";
}
error: 'std::string Piekarnik::model' is private
Change your friend declaration to
friend std::ostream &operator<<(std::ostream &os, const Piekarnik&);

Is it right way to make text-protocol interpretation program?

I'm trying to make a program for parsing text protocol.
(I selected text protocol cause I heard that binary packet parsing is more difficult).
Currently, there are really few command and parameters.
each packet can be splited by delimiter(';')
[packet1];[packet2];
Let's break packet1 down.
[Action],[Param1],[Param2],...;
Action : [SET]
Params : [DELAY]
if you send "SET,DELAY,300;" to server,
server will change 'delay' parameter and send "SET,DELAY,300;" to client.
Action : [GET]
Params : [DELAY] [MODE]
if you send "GET,DELAY,MODE;" to server,
server will send "GET,DELAY,300,MODE,2;" to client.
Any way I suceed to make it.
(The code is here. because it is long, I couldn't add it here)
But even if there are only few params and actions, the code is very long and complicated.
I used 'boost::algorithm::split' to split packets.
And I only used 'if','else if','else' to invoke right task corresponding 'action' and 'parameter'.
But I will add more actions and parameters.
But at this rate, I cannot debug or modify code because the comlexity of the code will be more severe.
Is it wrong way to make protocol translation program?
If you know better way, please share with me.
Yes. The better way is to make a grammar, write a parser for it and parse into an AST (abstract syntax tree, or simply strong typed representation of the packets).
A Spirit grammar for this looks like:
I always start out with the AST types:
namespace ast {
struct nil {
friend std::ostream& operator<<(std::ostream& os, nil) { return os << "<nil>"; }
};
using value = boost::variant<nil, double, std::string>;
struct parameter {
std::string _key;
value _val;
};
enum class action {
get,
set,
};
using parameters = std::vector<parameter>;
struct packet {
action _action;
parameters _params;
};
using packets = std::vector<packet>;
}
For simplicity I've
assumed parameters (mode/delay) will have numeric or string values.
used the same packet definition for GET and SET requests (GET requests will just us nil values for the parameters listed)
Next we define a grammar using Boost Spirit Qi:
template <typename It, typename Skipper=qi::space_type>
struct grammar : qi::grammar<It, ast::packets(), Skipper> {
grammar():grammar::base_type(start) {
using qi::raw;
using qi::no_case;
param_key_.add
("delay")
("mode");
start = *(packet_ >> ';');
packet_ =
(no_case["get"] >> qi::attr(ast::action::get) >> *(',' >> get_param_))
| (no_case["set"] >> qi::attr(ast::action::set) >> *(',' >> set_param_))
;
get_param_ = raw[no_case[param_key_]] >> qi::attr(ast::nil());
set_param_ = raw[no_case[param_key_]] >> "," >> value_;
value_ = qi::double_ | string_;
string_ = '"' >> *~qi::char_('"') >> '"';
BOOST_SPIRIT_DEBUG_NODES((start)(packet_)(get_param_)(set_param_)(value_)(string_))
}
// ... field declarations
};
There's a little bit of a learning curve here, but the key point to observe is that it it's possible to create maintainable code that is also debuggable (see here for BOOST_SPIRIT_DEBUG enabled output).
Finally, because the AST is simple we can make a fake request processor that uses a request context (in this case a map to contain the current values of the parameters) to actually process the requests:
struct request_context {
std::map<std::string, ast::value> properties;
request_context()
: properties { { "MODE", 2 }, { "DELAY", 300 } } // defaults
{
}
boost::optional<ast::packet> process_request(ast::packet packet) {
switch (packet._action) {
case ast::action::get:
for(auto& param : packet._params) {
param._val = properties[param._key];
}
return packet;
case ast::action::set:
for(auto& param : packet._params) {
std::cout << "DEBUG: setting property '" << param._key << "' to value '" << param._val << "'\n";
properties[param._key] = param._val;
}
return boost::none;
default:
throw std::runtime_error("bad packet"); // TODO proper exception type
};
}
};
Imagine who much messier this was if you had it mixed with the parsing code, or everything stringly typed
Live On Coliru
//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <map>
namespace qi = boost::spirit::qi;
namespace ast {
struct nil {
friend std::ostream& operator<<(std::ostream& os, nil) { return os << "<nil>"; }
};
using value = boost::variant<nil, double, std::string>;
struct parameter {
std::string _key;
value _val;
};
enum class action {
get,
set,
};
using parameters = std::vector<parameter>;
struct packet {
action _action;
parameters _params;
};
using packets = std::vector<packet>;
static std::ostream& operator<<(std::ostream& os, action a) {
switch(a) {
case action::get: return os << "GET";
case action::set: return os << "SET";
}
return os << "(other)";
}
}
BOOST_FUSION_ADAPT_STRUCT(ast::parameter,(std::string,_key)(ast::value,_val))
BOOST_FUSION_ADAPT_STRUCT(ast::packet,(ast::action,_action)(ast::parameters,_params))
template <typename It, typename Skipper=qi::space_type>
struct grammar : qi::grammar<It, ast::packets(), Skipper> {
grammar():grammar::base_type(start) {
using qi::raw;
using qi::no_case;
param_key_.add
("delay")
("mode");
start = *(packet_ >> ';');
packet_ =
(no_case["get"] >> qi::attr(ast::action::get) >> *(',' >> get_param_))
| (no_case["set"] >> qi::attr(ast::action::set) >> *(',' >> set_param_))
;
get_param_ = raw[no_case[param_key_]] >> qi::attr(ast::nil());
set_param_ = raw[no_case[param_key_]] >> "," >> value_;
value_ = qi::double_ | string_;
string_ = '"' >> *~qi::char_('"') >> '"';
BOOST_SPIRIT_DEBUG_NODES((start)(packet_)(get_param_)(set_param_)(value_)(string_))
}
private:
qi::symbols<char, std::string> param_key_;
qi::rule<It, ast::parameter(), Skipper> set_param_, get_param_;
qi::rule<It, ast::packets(), Skipper> start;
qi::rule<It, ast::packet(), Skipper> packet_;
qi::rule<It, ast::value(), Skipper> value_;
qi::rule<It, std::string()> string_;
};
struct request_context {
std::map<std::string, ast::value> properties;
request_context()
: properties { { "MODE", 2 }, { "DELAY", 300 } } // defaults
{
}
boost::optional<ast::packet> process_request(ast::packet packet) {
switch (packet._action) {
case ast::action::get:
for(auto& param : packet._params) {
param._val = properties[param._key];
}
return packet;
case ast::action::set:
for(auto& param : packet._params) {
std::cout << "DEBUG: setting property '" << param._key << "' to value '" << param._val << "'\n";
properties[param._key] = param._val;
}
return boost::none;
default:
throw std::runtime_error("bad packet"); // TODO proper exception type
};
}
};
int main()
{
std::string const input =
"GET,DELAY,MODE;"
"SET,DELAY,0,MODE,\"we can have string values too\";GET,MODE;SET,MODE,42;GET,MODE,DELAY;";
using It = std::string::const_iterator;
It f(input.begin()), l(input.end());
grammar<It> p;
ast::packets parsed;
bool ok = qi::phrase_parse(f,l,p,qi::space,parsed);
if (ok) {
std::cout << parsed.size() << " packets successfully parsed\n";
request_context ctx;
for(auto& packet : parsed)
{
auto response = ctx.process_request(packet);
if (response) {
std::cout << "response: " << response->_action;
for(auto& kv : packet._params) {
std::cout << "," << kv._key << "," << kv._val;
}
std::cout << ";\n";
}
}
} else {
std::cout << "Parse error\n";
}
if (f!=l)
std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
Prints:
5 packets successfully parsed
response: GET,DELAY,300,MODE,2;
DEBUG: setting property 'DELAY' to value '0'
DEBUG: setting property 'MODE' to value 'we can have string values too'
response: GET,MODE,we can have string values too;
DEBUG: setting property 'MODE' to value '42'
response: GET,MODE,42,DELAY,0;

Resources