Bug - Fixed EmptyStackException when using call

Paragon

Member
The code below is just about as trival an example as I could come up with, but it seems that perhaps some variables are not getting scoped correctly when using the call command?
Code:
int funcB(int[String] l)
{
    print("Start B");
    int[String] m;
    m["funcC"]=1;
    int[int] r;
    int i=0;
    foreach v in l
    {
        i+=1;
        r[i]=call int v(m);
    }
    print("End B");
    return 1;
}


int funcC(int[String] l)
{
    print("Start C "+l.Count());
    foreach v in l
    {
        print(v);
    }
    print("End C");
    return 5;
    
}


void main()
{
    int[String] list;
    list["funcB"]=1;
    Print("Start");
    funcB(list);
    print("Done");
}

Shows Output:
Start
Start B
Start B
Start C 1
funcC
End C
End B
Unexpected error, debug log printed.
Script execution aborted

Stack Trace attached. EmptyStackException
 

Attachments

  • DEBUG_20130202.txt
    2.9 KB · Views: 50

Catch-22

Active member
There's a lot of noise in the example, can be condensed to:
Code:
void funcB(string myFunc) {
    call void myFunc("funcC");
}

void funcC(string i) {}

void main() {
    funcB("funcB");
}
 

Paragon

Member
Is there any hope for this one getting fixed? I downloaded the latest code via SVN, and installed eclipse to try to take a look at it myself, but I am a C# Dev, not really a java guy... maybe someone can give me some advice of what I am looking for? I got to the point where I was able to write to the console all the trace output for the function calls... but I couldn't find where the Call logic was.
 

Catch-22

Active member
From memory, I think the call logic is in FunctionCall.java? Most ASH functions tend to have their own class in parsetree. I remember looking at this briefly and I don't think the problem is in FunctionCall.java but it might be. I might look at it later but I have a lot on my plate atm.
 

Paragon

Member
Ok... so the empty stack exception was coming from restoreBindings in UserDefinedFunction.java

So I made 2 changes to the func
Code:
ArrayList values=(ArrayList) this.callStack.pop();
.
.
if(!current.isStatic())
{
 current.forceValue((Value) values.get(i++));
}
became
Code:
ArrayList values = null;
if (!this.callStack.isEmpty())
{
   values = (ArrayList) this.callStack.pop();
}
.
.
.
if (!current.isStatic() && !(values ==null))
{
  current.forceValue((Value)values.get(i++));
}

I was worried that there might be some side effect, such as a Return value getting ignored, but changing your test script to:
Code:
int funcB(string myFunc){
  int c= call void myFunc("funcC");
  return c+1;
}

int funcC(string i){return 1;}

void main(){
   print(funcB("funcB"));
}

has the desired output of 3.

Note: I don't know if this is the "Correct" fix, of if it is just a hammer it until it fits fix.
 
Last edited:

Catch-22

Active member
I don't think the callstack should be empty in the first place, so you're kinda patching the symptoms instead of the cause. Perhaps I am mistaken, though.

If your changes to the test script worked than that would be a bug in itself, particularly this line int c= call void myFunc("funcC"); as void funcB and void funcC don't exist.
 

Paragon

Member
Double checked, you are correct... I typo'ed the change and it does in fact have to call int myFunc rather then call void myFunc.

Here is trace... Note the line that I marked... perhaps that is a clue as to what is happening.
Code:
Executing main function
      Param #1: funcB()
         Param #1: "funcB"
         [NORMAL] <- "funcB"
         Entering function funcB
               Eval: call int myFunc()
                  Invoke: call int myFunc()
                  Function name: myFunc
                  [NORMAL] <- funcB
                     Param #1: "funcC"
                     [NORMAL] <- "funcC"
                     Entering function funcB
                           Eval: call int myFunc()
                              Invoke: call int myFunc()
                              Function name: myFunc
                              [NORMAL] <- funcC
                                 Param #1: "funcC"
                                 [NORMAL] <- "funcC"
                                 Entering function funcC
                                       Eval: 1
                                       Returning: 1
                                    [RETURN] <- 1
                                 Function funcC returned: 1
                           Set: 1
                        [NORMAL] <- 1
                           Eval: ( c + 1 )
                              Operator: +
                                 Operand 1: c
                                 [NORMAL] <- 1
                                 Operand 2: 1
                                 [NORMAL] <- 1
                              <- 2
                           Returning: 2
                        [RETURN] <- 2
                     Function funcC returned: 2     <--- ODD Shouldn't this say funcB returned 2?  (This is also the line where execution is aborted in current version
               Set: 2
            [NORMAL] <- 2
               Eval: ( c + 1 )
                  Operator: +
                     Operand 1: c
                     [NORMAL] <- 2
                     Operand 2: 1
                     [NORMAL] <- 1
                  <- 3
               Returning: 3
            [RETURN] <- 3
         Function funcB returned: 3
      [NORMAL] <- 3
      Entering function print
      Function print returned: void
   [NORMAL] <- void

Sorry if I am stepping on toes, It's just a feature that a script that I am creating requires and I'm trying to help solve it, but I am a real fish out of water in java and this is some pretty confusing sections of code.
 
Last edited:

heeheehee

Developer
Staff member
Probably fixed at some point, since the example in the first post runs to completion without generating any errors.
 
Top