YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

Evaluate expressions within a debug hook
pockpock
#1 Posted : Monday, September 26, 2016 7:05:26 PM(UTC)
Rank: Member

Groups: Registered
Joined: 9/13/2013(UTC)
Posts: 17

Thanks: 3 times
Was thanked: 0 time(s) in 0 post(s)
Hi,

I'm currently working on a debugger and seem stuck on expression evaluation.
The problem is it works with simple expressions that does not contain variables (e.g. "3+4")
But as soon as I add variables it does not work ("a+b" in the below example).
The error message thrown suggests a and b are not defined.
Squirrel-script:
Code:

local a = 3;
local b = 4;
print(a+b); // <-- halted here


C++ part (within my native debug hook):
Code:

string expression = "return "+expression_->stdString();
int topPre = sq_gettop(sqvm);

sq_enabledebuginfo(sqvm, false);
sq_compilebuffer(sqvm,expression.c_str(),expression.length() ,"debugger_expr",false);

sq_pushroottable(sqvm);
SQInteger res = sq_call(sqvm, 1, true, false);
sq_enabledebuginfo(sqvm, true);

if( SQ_SUCCEEDED(res) ){
    HSQOBJECT hobj;
    sq_getstackobj(sqvm,-1,&hobj);
    std::cout << Util.HObjToString(hobj) << std::endl;
} else {
    std::cout << "<<evaluation error>>" << std::endl;
}
sq_settop(sqvm,topPre);


My guess the problem is that I evaluate the function in root-table context
"sq_pushroottable(sqvm)" (I also tried "sq_push(sqvm, -2)", no success).

Is there a reliable way to achive evaluation within the context?

best regards
fagiano
#2 Posted : Saturday, October 1, 2016 10:05:40 PM(UTC)
Rank: Advanced Member

Groups: Registered, Administrators
Joined: 6/11/2005(UTC)
Posts: 1,056

Thanks: 0 times
Was thanked: 78 time(s) in 60 post(s)
Yes, take a look at sqdbg "watches", it generates a closure on the fly to emulate local evaluation. look at the script "serialize_stat.nut" is much easier than explaining it here.

http://wiki.squirrel-lan...dbg_3.x_07_May_2011.zip

here is the interesting code:
Code:

function evaluate_watch(locals,id,expression)
{
    local func_src="return function ("
    local params=[];
    
    params.append(locals["this"])
    local first=1;
    foreach(i,v in locals){
        if(i!="this" && i[0] != '@'){ //foreach iterators start with @
            if(!first){
                func_src=func_src+","
                
            }
            first=null
            params.append(v)
            func_src=func_src+i
        }
    }
    func_src=func_src+"){\n"
    func_src=func_src+"return ("+expression+")\n}"
    
    try {
        local func=::compilestring(func_src);
        return {status="ok" , val=func().acall(params)};
    }
    catch(e)
    {
        
        return {status="error"}
    }
}


ciao
Alberto
Follow me on Twitter @squirrellang
1 user thanked fagiano for this useful post.
pockpock on 10/2/2016(UTC)
pockpock
#3 Posted : Sunday, October 2, 2016 7:20:56 PM(UTC)
Rank: Member

Groups: Registered
Joined: 9/13/2013(UTC)
Posts: 17

Thanks: 3 times
Was thanked: 0 time(s) in 0 post(s)
Great, that's a nice idea!

If anyone is interested the expression becomes:
Code:


std::map<string, HSQOBJECT> locals = getLocals();
string expression = "return function(";
bool first = true;
for(std::map<string,HSQOBJECT>::iterator it = locals.begin(); it != locals.end(); it++) {
    if(it->first == "this"){
        continue;
    }
    if(first){
        first = false;
    }else{
        expression += ",";
    }
    expression += (it->first);
}

getLocals there is a helper method that returns a map between local and outer variable names (based on sq_getlocal) and
the according HSQOBJECT.

And the call:
Code:

sq_compilebuffer(sqvm,expression.c_str(),expression.length() ,"debugger_expr",false);
sq_push(sqvm, -2);
int res = sq_call(sqvm, 1, true, false);

if(SQ_SUCCEEDED(res)){
    sq_push(sqvm, -2);
    int num=0;
    for(std::map<string,HSQOBJECT>::iterator it = locals.begin(); it != locals.end(); it++) {
        if(it->first == "this"){
            continue;
        }
        num++;
        sq_pushobject(sqvm,it->second);
    }
    res = sq_call(sqvm, num+1, true, false);
}

fagiano
#4 Posted : Sunday, October 2, 2016 8:16:37 PM(UTC)
Rank: Advanced Member

Groups: Registered, Administrators
Joined: 6/11/2005(UTC)
Posts: 1,056

Thanks: 0 times
Was thanked: 78 time(s) in 60 post(s)
you want to skip local variables that start with '@', squirrel uses them as hidden iterators for 'foreach'. But maybe your getLocals already does that.

Alberto
Follow me on Twitter @squirrellang
pockpock
#5 Posted : Tuesday, October 4, 2016 7:31:58 PM(UTC)
Rank: Member

Groups: Registered
Joined: 9/13/2013(UTC)
Posts: 17

Thanks: 3 times
Was thanked: 0 time(s) in 0 post(s)
Yes, getLocals filters those, I should have pointed that out
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.081 seconds.