Search code examples
javalogicbooleanstack-overflowsimulator

Boolean Logic Simulator - StackOverflowError


I'm creating a Boolean logic simulator. I've posted a question regarding the organization and general setup of the application and it's located here: Organizing Simple Boolean Logic Simulator - Java. I figured this doesn't apply directly to the other question so it would be OK posting this separately. Please excuse my code, I'm very new to Java.

The organization of the code is actually quite simple, but I've run into a problem when I try to assign a variable to itself in an assign statement.

For example, we'll commonly use statements like this:

assign input1 * input2 + test3 * input2 to test3;

When input1 and input2 are high, test3 will become high. At that point, input1 could drop out and test3 would still be high because it refers to itself in the statement. (Note: * => AND, + => OR) As you can see below, I'm having problems when a variable refers to itself in its assign statement like above. That's because when I attempt to get the value of the statement above I'm getting:

input1 * input2 + (input1 * input2 + (input1 * input2 + test3 * input2) * input2) * input2

Etc. It just attempts to evaluate its statement over and over again.

public interface Argument {
    public boolean evaluate();
}

Here is the "Bit" class that stores information about each bit. The bit can either be a "hard-wired" true or false, or it can have a statement assigned to it.

public class Bit implements Argument {

    private String name;
    private boolean value;
    private Argument assign;
    private boolean assigned;

    Bit( String name, boolean value ) {
        this.name = name;
        this.value = value;
    }

    @Override
    public boolean evaluate() {
        if ( assigned == true ) {
            return assign.evaluate();
        } else {
            return value;
        }
    }

    public void setValue( boolean value ) {
        this.value = value;
    }

    public void setAssign( Argument assign ) {
        this.assign = assign;
        this.assigned = true;
    }

}

This is an example of the Operation class; the others are very similar.

public class OrOperation implements Argument {

    private Argument argument1, argument2;

    public OrOperation( Argument arg1, Argument arg2 ) {
        this.argument1 = arg1;
        this.argument2 = arg2;
    }

    @Override
    public boolean evaluate() {
        return argument1.evaluate() || argument2.evaluate();
    }

}

Parser class: I've only included part of this, since the actually parsing isn't all that relevant. Note that when I assign a variable to itself the error is produced. In the second test below, I assigned test3 to test3. I can infer that this is because test3 attempts to determine the value of itself, calling that second statement over and over again.

public class Parser {

    public HashMap<String, Bit> bits = new HashMap<String, Bit>();

    Parser(String file) {

        bits.put( "test1", new Bit( "test1", true ) );
        bits.put( "test2", new Bit( "test2", true ) );
        bits.put( "test3", new Bit( "test3", false ) );
        bits.put( "test4", new Bit( "test4", true ) );

        // Works great
        bits.get("test3").setAssign( parseStatement("test1 * ~test2 + test4 * test2") );
        System.out.println( bits.get("test3").evaluate() );

        // Produces error
        bits.get("test3").setAssign( parseStatement("test1 * test2 + test3 * test2") );
        System.out.println( bits.get("test3").evaluate() );

    }
}

The parser basically creates the statements like so: (taken from previous question)

Operand op = new AndOperand( register1, new OrOperand( register2, register3 );
boolean output = op.evaluate(); // this is register1 && (register2 || register3 )

Hopefully this was clear enough. Let me know if there's any question as to what the problem is or what I'm trying to do. Thanks in advance.


Solution

  • Assuming that this is a simulator / evaluator (and not an equation solver), then you need to model the system as states that change over time. Thus, the statement:

    assign test1 * input1 to test1;
    

    means that the state of test1t+1 is test1t * input1t.

    What your code is doing is not distinguishing between test1t and test1t+1 ... and as a result is causing infinite recursion.

    One solution is to represent the state (the values of the variables) separately from the equations, and furthermore to use different data structures to represent the state at time t and the state at time t + 1.