/* CodeGen.java - generator kodu jazyka PL/0
 *
 * Michal Beran, berny@students.zcu.cz
 * 4.1.2001
 */
package pl0prog;

import java.io.*;
import java.text.*;


/** Trida CodeGen ma funkci tabulky generovaneho kodu (tabulky instrukci). 
  */
public class CodeGen {
	/** Maximalni pocet instukci v programu. */
	final int MAX_INSTRUCTION = 1000;		
	/** Jmena instrukci */
	final String[] MNEMONIC =						
		{"LIT  ","OPR  ","LOD  ","STO  ","CAL  ","RET  ","INT  ","JMP  ","JMC  "};
	/** Vlastni tabulka instrukci */
	private GenInstruction[] GenCode =	
		new GenInstruction[MAX_INSTRUCTION];
	/** Citac adres */
	private int AddressCounter = 0;			

	/* Nastaveni adresy/operandu 
	 * @param where poradovy index instukce,
	 * @param what nova hodnota adresy/operandu.
	 */
	public void setAddressAt(int where, int what) {
		GenCode[where].operand = what;
	}

	/* Ziskani adresy/operandu 
	 * @param where poradovy index instukce,
	 * @return pozadovana adresa/operand
	 */
	public int getAdress(int where) {
		if (GenCode[where] != null) 
		{
			return GenCode[where].operand;
		}
		else
			return 0;
	}
	public int getAddressCounter() {return AddressCounter;};

	/**Generovani instrukci do pole generovanych kodu
	  * @param x kod funkce,
	  * @param y uroven instrukce,
	  * @param z adresni cast v instrukci.
	  */
	public void gen(int x,int y,int z) {
		if (AddressCounter>=MAX_INSTRUCTION) {
	    	System.out.println("Program je prilis dlouhy");
	   		System.exit(1);
	 	}
		GenCode[AddressCounter++] = new GenInstruction(x,y,z); 
	}

	/**Pomocna fce pro vypis generovaneho kodu. Metoda generuje vyjimku IOException.
	  *@param path jmeno(cesta) souboru, kam se ma vysledny kod ulozit.
	  */
	public void list(String path) { 	
		int i;
		FileWriter file;										
		BufferedWriter out;

		
		try {
			file = new FileWriter(path);
			out = new BufferedWriter(file);

			out.write("\ngenerovany kod:\n");
			out.write("**************\n");

			for (i=0;i<=(AddressCounter-1);i++) {
				Object[] arguments= {new Integer(i),MNEMONIC[GenCode[i].functionCode],
					 new Integer(GenCode[i].level), new Integer(GenCode[i].operand)};
								// objekty pro formatovani vystupniho retezce

				String text = MessageFormat.format("{0, number, integer} {1} " +
							"{2, number, integer}, {3, number, integer}", arguments);
				out.write(text);
				out.newLine();
			}
			out.close();
		}
		catch (IOException E) {
			System.out.println("Chyba pri zapisovani do souboru" + path);
		}
	}

	/** Vypis specifickych casti generovanych kodu prelozeneho bloku.
	  * @param from pocatecni index,
	  * @param to konecny index.
 	  */
	void listcode(int from, int to) {
		int i;

		for (i=from;i<=(AddressCounter-1);i++) {
			Object[] arguments= {new Integer(i),MNEMONIC[GenCode[i].functionCode],
							 new Integer(GenCode[i].level), new Integer(GenCode[i].operand)};
								// objekty pro formatovani vystupniho retezce

			String text = MessageFormat.format("{0, number, integer} {1} " +
						"{2, number, integer}, {3, number, integer}", arguments);
			System.out.println(text);

		}
	}

	/** Ziskani instrukce z tabulky instukci.
	  * @param i index instrukce,
	  * @return pozadovana instrukce.
	  */
	public GenInstruction getInstruction(int i) {
		return GenCode[i];
	}
}

