import JSim.util.*;
import JSim.mml.*;
import JSim.plan.*;

public class MyPlanWriter extends PlanWriter {
	protected MathSys math;
	private MyContext ctxt;

	// constructor
	public MyPlanWriter(PlanIF p) {
	    super(p, MyLang.lang);
	    math = plan.math();
	    ctxt = new MyContext(this);
	}
	
	// write plan
	public void write() throws Xcept {
	    indent=0;
	    for (int i=0; i<math.nVar(); i++) {
	    	Var v = math.var(i);
		println("double " + v.toString(ctxt) + ";");
	    }
	    write(plan.mainProc());
	    for (int i=0; i<plan.procs().size(); i++) {
                Proc p = plan.procs().proc(i);
  		if (p instanceof TopProc)
		    write((TopProc) p);
                else if (p instanceof ODEProc)
		    write((ODEProc) p);
		else
		    println("// unsupported class " + p.getClass());
               println("");
            }
	}

	// write TopProc
	public void write(TopProc p) throws Xcept {
	    println("void mainline() {");
	    indent++;
	    writeCalc(p.mcalc);
	    indent--;
	    println("}");
	}

	// write FzeroProc
	public void write(FzeroProc p) throws Xcept {
	    println("// write(FzeroProc) not implemented");
	}

	// write ODEProc
	public void write(ODEProc p) throws Xcept {
	    println("void function_" + p.hashCode() + "() {");
	    indent++;
	    write((MultiCalc) p.calc);
	    indent--;
	    println("}");
	}

	// write PDEProc
	public void write(PDEProc p) throws Xcept {
	    println("// write(PDEProc) not implemented");
	}

	// write ExprCalc
	public void write(ExprCalc calc) throws Xcept {
	    println(calc.v.toString(ctxt) + "=" + 
	    	calc.expr.toString(ctxt) + ";");
	}

	// write DomainCalc
	public void write(DomainCalc calc) throws Xcept {
	    println("// write(DomainCalc) not implemented");
	}

	// write FuncCalc
	public void write(FuncCalc calc) throws Xcept {
	    println("// write(FuncCalc) not implemented");
	}

	// write LoopCalc
	public void write(LoopCalc calc) throws Xcept {
	    String x = calc.x.toString(ctxt);
	    println("for (" + x + "=min; " +
	    	x + "<=max; " + x + "+=delta) {");
	    indent++;
	    write((MultiCalc) calc.loop);
	    indent--;
	    println("}");
	}

	// write IfCalc
	public void write(IfCalc calc) throws Xcept {
	    println("// write(IfCalc) not implemented");
	}

	// write SetCalc
	public void write(SetCalc calc) throws Xcept {
	    println("// write(SetCalc) not implemented");
	}

	// write MultiCalc
	public void write(MultiCalc calc) throws Xcept {
	    for (int i=0; i<calc.calc.size(); i++) {
		Calc c = (Calc) calc.calc.get(i);
		writeCalc(c);
	    }
	}

	// write ProcCalc
	public void write(ProcCalc calc) throws Xcept {
	    println("CALL_SOLVER(function_" + 
	    	calc.proc.hashCode() + ");");
	}

	// write RelationCalc
	public void write(RelationCalc calc) throws Xcept {
	    println("// write(RelationCalc) not implemented");
	}

}
