/*
Java version of sum-trampolined.ss

Note: java on linus seems to be broken, so try this example somewhere else.

% javac RegisterSum.java
% java RegisterSum 50000
answer is: 1250025000
java RegisterSum 60000
answer is: 1800030000
% java RegisterSum 1000000
answer is: 500000500000

*/

public class RegisterSum {

    // registers
    private static long n_reg;
    private static long value_reg;
    private static continuation k_reg;
    private static String action_reg;

    public static void main(String[] args) {

	// set up n_reg, k_reg, and action_reg
	if (args.length > 0) {
	    try {
		n_reg = Long.parseLong(args[0]);
	    } catch (NumberFormatException nfe) {
		System.err.println(nfe);
		System.exit(-1);
	    }
	}
	k_reg = new continuation_cont0();
	action_reg = "sum_cps";

	// the run loop
	try {
	    while (true) {
		if (action_reg.equals("sum_cps")) {
		    sum_cps();
		} else if (action_reg.equals("apply_cont")) {
		    apply_cont();
		} else {
		    break;
		}
	    }
	} catch (StackOverflowError e) {
	    System.err.println(e);
	    System.exit(-1);
	}
	System.out.println("answer is: " + value_reg);
    }

    // uses n_reg and k_reg
    public static void sum_cps() {
	if (n_reg == 0) {
	    value_reg = 0;
	    action_reg = "apply_cont";
	} else {
	    k_reg = new continuation_cont1(k_reg, n_reg);
	    n_reg = n_reg - 1;
	    action_reg = "sum_cps";
	}
    }

    // uses k_reg and value_reg
    public static void apply_cont() {
	if (k_reg.tag.equals("continuation_cont0_tag")) {
	    action_reg = "false";
	} else if (k_reg.tag.equals("continuation_cont1_tag")) {
	    continuation k = ((continuation_cont1) k_reg).k;
	    long n = ((continuation_cont1) k_reg).n;
	    k_reg = k;
	    value_reg = n + value_reg;
	    action_reg = "apply_cont";
	} else {
	    System.err.println("bad continuation: " + k_reg);
	    System.exit(-1);
	}
    }
}

//-----------------------------------------------------------------------
// continuation record constructors

class continuation {
    public String tag;

    public continuation(String t) {
	this.tag = t;
    }
}

class continuation_cont0 extends continuation {

    public continuation_cont0() {
	super("continuation_cont0_tag");
    }
}

class continuation_cont1 extends continuation {
    public continuation k;
    public long n;

    public continuation_cont1(continuation k, long n) {
	super("continuation_cont1_tag");
	this.k = k;
	this.n = n;
    }
}
