Bug - Fixed exit does not exit

apologue

New member
The wiki says that exit will exit the script:

exit
Exits the script. Using return when in main() achieves the same effect. Note that while this will end the current script, it will not stop automation.

However, when running the following script on r19401:

Code:
int method3() {
	print("method3");
	exit;
}

int method2() {
	print("method2");
	method3();
	return 1;
}

void method1() {
	int a = 0;
	while (a < 10) {
		print("method1 " + a);
		a += method2();
	}
}

void main() {
	method1();
	print("done");
}

The following output is repeated until Esc is pressed:
method1 0
method2
method3
 

heeheehee

Developer
Staff member
It seems like it's breaking out of method3 / method2, then (hunch) since the return value of method2 is being used, it continues the loop in method1.
 

heeheehee

Developer
Staff member
Yeah. From adding the following block to Interpreter.setState:
Code:
		if (this.currentState.equals(STATE_EXIT)) {
			System.out.println("Transitioning from exit to " + state);
			this.printStackTrace();
			new Exception().printStackTrace();
			System.exit(1);
		}

we see

Code:
method1 0
method2
method3
Stack trace:
  at method2 (test_loop.ash:8)
  at method1 (test_loop.ash:16)
  at main (test_loop.ash:21)
Transitioning from exit to NORMAL
java.lang.Exception
	at net.sourceforge.kolmafia.textui.Interpreter.setState(Interpreter.java:228)
	at net.sourceforge.kolmafia.textui.Interpreter.captureValue(Interpreter.java:689)
	at net.sourceforge.kolmafia.textui.parsetree.Assignment.execute(Assignment.java:104)
	at net.sourceforge.kolmafia.textui.parsetree.BasicScope.execute(BasicScope.java:417)
	at net.sourceforge.kolmafia.textui.parsetree.Loop.execute(Loop.java:59)
	at net.sourceforge.kolmafia.textui.parsetree.WhileLoop.execute(WhileLoop.java:100)
	at net.sourceforge.kolmafia.textui.parsetree.BasicScope.execute(BasicScope.java:417)
	at net.sourceforge.kolmafia.textui.parsetree.UserDefinedFunction.execute(UserDefinedFunction.java:142)
	at net.sourceforge.kolmafia.textui.parsetree.FunctionCall.execute(FunctionCall.java:154)
	at net.sourceforge.kolmafia.textui.parsetree.BasicScope.execute(BasicScope.java:417)
	at net.sourceforge.kolmafia.textui.parsetree.UserDefinedFunction.execute(UserDefinedFunction.java:142)
	at net.sourceforge.kolmafia.textui.Interpreter.executeScope(Interpreter.java:425)
	at net.sourceforge.kolmafia.textui.Interpreter.execute(Interpreter.java:347)
	at net.sourceforge.kolmafia.textui.Interpreter.execute(Interpreter.java:340)
	at net.sourceforge.kolmafia.textui.command.CallScriptCommand.call(CallScriptCommand.java:256)
	at net.sourceforge.kolmafia.textui.command.CallScriptCommand.run(CallScriptCommand.java:75)
	at net.sourceforge.kolmafia.KoLmafiaCLI.doExecuteCommand(KoLmafiaCLI.java:596)
	at net.sourceforge.kolmafia.KoLmafiaCLI.executeCommand(KoLmafiaCLI.java:549)
	at net.sourceforge.kolmafia.KoLmafiaCLI.executeLine(KoLmafiaCLI.java:450)
	at net.sourceforge.kolmafia.KoLmafiaCLI.executeLine(KoLmafiaCLI.java:318)
	at net.sourceforge.kolmafia.KoLmafia.main(KoLmafia.java:406)

It seems the problem is that Mafia doesn't disambiguate between `exit` and any other source of abort.
 

Veracity

Developer
Staff member
That does seem like the issue. captureValue says this:

Code:
		// Even if an error occurred, since we captured the result,
		// permit further execution.
except "exit" is not an error.

The "exit" command simply sets you into STATE_EXIT. I looked at every place where Interpreter.setState is called to transition into something other than STATE_EXIT. In every case, it was guarded by an (if state != STATE_EXIT) or (if state == something which is not STATE_EXIT) - except for captureValue.

Perhaps the "exit" command can continue go into STATE_EXIT (since the huge bulk of the interpreter does the right thing for that) but also set something that captureValue will recognize as different than an "error".
 

Veracity

Developer
Staff member
Yeah, that works. Since interpreters get reused, have to reset that flag each time it starts. :)
Revision 19437.

Code:
[color=green]> exit-test[/color]

method1 0
method2
method3

[color=green]> exit-test[/color]

method1 0
method2
method3
 

Veracity

Developer
Staff member
Hmm. How does the abort() function work?

Code:
int method3() {
	print("method3");
	abort( "time to go!" );
	return 1;
}

int method2() {
	print("method2");
	method3();
	return 1;

}

void method1() {
	int a = 0;
	while (a < 10) {
		print("method1 " + a);
		a += method2();
	}
}

void main() {
	method1();
	print("done");
}
does this:

Code:
[color=green]> abort-test[/color]

method1 0
method2
method3
[color=red]time to go![/color]
This works because KoLmafia itself is in an ABORT state when captureValue is called.
 
Top