WIP Code Gen
This commit is contained in:
		
							parent
							
								
									b50325d3a5
								
							
						
					
					
						commit
						7fd97ed0b3
					
				
							
								
								
									
										494
									
								
								src/pins25/common/PDM.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								src/pins25/common/PDM.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,494 @@
 | 
			
		||||
package pins25.common;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Ukazi skladovnega stroja.
 | 
			
		||||
 * 
 | 
			
		||||
 * Vse spremenljivke (in parametri, ki so samo posebna vrsta spremenljivke),
 | 
			
		||||
 * katerih ime se zacne z {@code debug}, so lahko nastavljene na {@code null}.
 | 
			
		||||
 * Uporabljajo se samo za izpis sledenja delovanja skladovnega stroja.
 | 
			
		||||
 */
 | 
			
		||||
public class PDM {
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings({ "doclint:missing" })
 | 
			
		||||
	public PDM() {
 | 
			
		||||
		throw new Report.InternalError();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Vrsta ukazov skladovnega stroja.
 | 
			
		||||
	 */
 | 
			
		||||
	public static interface Instruction {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Vrne dolzino ukaza.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @return Dolzina ukaza.
 | 
			
		||||
		 */
 | 
			
		||||
		Integer size();
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/** Ukazi skladovnega stroja za opis podatkov. */
 | 
			
		||||
	public static interface DataInstr extends Instruction {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/** Ukazi skladovnega stroja za opis kode programa. */
 | 
			
		||||
	public static interface CodeInstr extends Instruction {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Ukaz skladovnega stroja.
 | 
			
		||||
	 */
 | 
			
		||||
	public static abstract class INSTR implements Instruction {
 | 
			
		||||
 | 
			
		||||
		/** Lokacija dela izvorne kode, ki se prevede v ta ukaz. */
 | 
			
		||||
		public final Report.Location debugLocation;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nov ukaz skladovnega stroja.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public INSTR(final Report.Locatable debugLocation) {
 | 
			
		||||
			this.debugLocation = debugLocation == null ? null : debugLocation.location();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Integer size() {
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Oznaka.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class LABEL extends INSTR implements DataInstr, CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Ime oznake. */
 | 
			
		||||
		public final String name;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nov ukaz {@link LABEL}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param name          Ime oznake.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public LABEL(final String name, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.name = name;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Integer size() {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "LABEL " + name;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Dodeljevanje prostora v staticnem pomnilniku.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class SIZE extends INSTR implements DataInstr {
 | 
			
		||||
 | 
			
		||||
		/** Velikost prostora v pomnilniku. */
 | 
			
		||||
		public final Integer size;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nov ukaz {@link SIZE}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param size          Velikost prostora v pomnilniku.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public SIZE(final Integer size, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.size = size;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Integer size() {
 | 
			
		||||
			return size;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "SIZE " + size;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Konstanta v v staticnem pomnilniku.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class DATA extends INSTR implements DataInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Vrednost konstante.
 | 
			
		||||
		 */
 | 
			
		||||
		public final Integer intc;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nov ukaz {@link SIZE}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param intc          Vrednost konstante.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public DATA(final Integer intc, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.intc = intc;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Integer size() {
 | 
			
		||||
			return 4;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "DATA " + intc;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Inicializacija spremenljivke.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class INIT extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link INIT}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public INIT(final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "INIT";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Prenos vrednosti iz pomnilnika na sklad.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class LOAD extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link LOAD}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public LOAD(final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "LOAD";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Prenos vrednosti s sklada v pomnilnik.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class SAVE extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link SAVE}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public SAVE(final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "SAVE";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Spreminjanje lokacija vrha sklada.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class POPN extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link POPN}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public POPN(final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "POPN";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Prenos konstante na sklad.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class PUSH extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Konstanta. */
 | 
			
		||||
		public final Integer intc;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link PUSH}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param intc          Konstanta.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public PUSH(final Integer intc, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.intc = intc;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Integer size() {
 | 
			
		||||
			return super.size() + 4;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "PUSH " + intc;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Prenos imena oznake na sklad.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class NAME extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Ime oznake. */
 | 
			
		||||
		public final String name;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link NAME}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param name          Ime oznake.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public NAME(final String name, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.name = name;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Integer size() {
 | 
			
		||||
			return super.size() + 4;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "NAME " + name;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Prenos vrednosti registra na sklad.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class REGN extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Imena registrov. */
 | 
			
		||||
		public enum Reg {
 | 
			
		||||
			/** Programski stevec. */
 | 
			
		||||
			PC,
 | 
			
		||||
			/** Klicni kazalec. */
 | 
			
		||||
			FP,
 | 
			
		||||
			/** Skladovni zapis. */
 | 
			
		||||
			SP,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** Ime registra. */
 | 
			
		||||
		public final Reg regn;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link REGN}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param regn          Ime registra.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public REGN(Reg regn, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.regn = regn;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "REGN." + regn;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Izvedba racunske operacije.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class OPER extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Vrste racunskih operacij. */
 | 
			
		||||
		public enum Oper {
 | 
			
		||||
			/** Negacija. */
 | 
			
		||||
			NOT,
 | 
			
		||||
			/** Sprememba predznaka. */
 | 
			
		||||
			NEG,
 | 
			
		||||
			/** Disjunkcija. */
 | 
			
		||||
			OR,
 | 
			
		||||
			/** Konjunkcija. */
 | 
			
		||||
			AND,
 | 
			
		||||
			/** Enakonst. */
 | 
			
		||||
			EQU,
 | 
			
		||||
			/** Neenakost. */
 | 
			
		||||
			NEQ,
 | 
			
		||||
			/** Vecji kot. */
 | 
			
		||||
			GTH,
 | 
			
		||||
			/** Manjsi kot. */
 | 
			
		||||
			LTH,
 | 
			
		||||
			/** Vecji ali enak. */
 | 
			
		||||
			GEQ,
 | 
			
		||||
			/** Manjsi ali enak. */
 | 
			
		||||
			LEQ,
 | 
			
		||||
			/** Sestevanje. */
 | 
			
		||||
			ADD,
 | 
			
		||||
			/** Odstevanje. */
 | 
			
		||||
			SUB,
 | 
			
		||||
			/** Mnozenje. */
 | 
			
		||||
			MUL,
 | 
			
		||||
			/** Deljenje. */
 | 
			
		||||
			DIV,
 | 
			
		||||
			/** Modulo. */
 | 
			
		||||
			MOD,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** Racunska operacija. */
 | 
			
		||||
		public final Oper oper;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link OPER}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param oper          Racunska operacija.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public OPER(final Oper oper, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.oper = oper;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "OPER." + oper;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Brezpogojni skok.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class UJMP extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link UJMP}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public UJMP(final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "UJMP";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Pogojni skok.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class CJMP extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link CJMP}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public CJMP(final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "CJMP";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Klic podprograma.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class CALL extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Klicni zapis klicanega podprograma. */
 | 
			
		||||
		public final Mem.Frame debugFrame;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link CALL}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugFrame    Klicni zapis klicanega podprograma.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public CALL(final Mem.Frame debugFrame, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.debugFrame = debugFrame;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "CALL";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Vrnitev iz podprograma.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class RETN extends INSTR implements CodeInstr {
 | 
			
		||||
 | 
			
		||||
		/** Klicni zapis vracajocega se podprograma. */
 | 
			
		||||
		public final Mem.Frame debugFrame;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nok ukaz {@link RETN}.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param debugFrame    Klicni zapis vracajocega se programa.
 | 
			
		||||
		 * @param debugLocation Lokacija dela izvorne kode, ki se prevede v ta ukaz.
 | 
			
		||||
		 */
 | 
			
		||||
		public RETN(final Mem.Frame debugFrame, final Report.Locatable debugLocation) {
 | 
			
		||||
			super(debugLocation);
 | 
			
		||||
			this.debugFrame = debugFrame;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "RETN";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										566
									
								
								src/pins25/phase/CodeGen.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								src/pins25/phase/CodeGen.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,566 @@
 | 
			
		||||
package pins25.phase;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import pins25.common.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generiranje kode.
 | 
			
		||||
 */
 | 
			
		||||
public class CodeGen {
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings({"doclint:missing"})
 | 
			
		||||
    public CodeGen() {
 | 
			
		||||
        throw new Report.InternalError();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abstraktno sintaksno drevo z dodanimi atributi izracuna pomnilniske
 | 
			
		||||
     * predstavitve.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Atributi:
 | 
			
		||||
     * <ol>
 | 
			
		||||
     * <li>({@link Abstr}) lokacija kode, ki pripada posameznemu vozliscu;</li>
 | 
			
		||||
     * <li>({@link SemAn}) definicija uporabljenega imena;</li>
 | 
			
		||||
     * <li>({@link SemAn}) ali je dani izraz levi izraz;</li>
 | 
			
		||||
     * <li>({@link Memory}) klicni zapis funkcije;</li>
 | 
			
		||||
     * <li>({@link Memory}) dostop do parametra;</li>
 | 
			
		||||
     * <li>({@link Memory}) dostop do spremenljivke;</li>
 | 
			
		||||
     * <li>({@link CodeGen}) seznam ukazov, ki predstavljajo kodo programa;</li>
 | 
			
		||||
     * <li>({@link CodeGen}) seznam ukazov, ki predstavljajo podatke programa.</li>
 | 
			
		||||
     * </ol>
 | 
			
		||||
     */
 | 
			
		||||
    public static class AttrAST extends Memory.AttrAST {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Atribut: seznam ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
         */
 | 
			
		||||
        public final Map<AST.Node, List<PDM.CodeInstr>> attrCode;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Atribut: seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         */
 | 
			
		||||
        public final Map<AST.Node, List<PDM.DataInstr>> attrData;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Ustvari novo abstraktno sintaksno drevo z dodanimi atributi generiranja kode.
 | 
			
		||||
         *
 | 
			
		||||
         * @param attrAST  Abstraktno sintaksno drevo z dodanimi atributi pomnilniske
 | 
			
		||||
         *                 predstavitve.
 | 
			
		||||
         * @param attrCode Attribut: seznam ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
         * @param attrData Attribut: seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         */
 | 
			
		||||
        public AttrAST(final Memory.AttrAST attrAST, final Map<AST.Node, List<PDM.CodeInstr>> attrCode,
 | 
			
		||||
                       final Map<AST.Node, List<PDM.DataInstr>> attrData) {
 | 
			
		||||
            super(attrAST);
 | 
			
		||||
            this.attrCode = attrCode;
 | 
			
		||||
            this.attrData = attrData;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Ustvari novo abstraktno sintaksno drevo z dodanimi atributi generiranja kode.
 | 
			
		||||
         *
 | 
			
		||||
         * @param attrAST Abstraktno sintaksno drevo z dodanimi atributi generiranja
 | 
			
		||||
         *                kode.
 | 
			
		||||
         */
 | 
			
		||||
        public AttrAST(final AttrAST attrAST) {
 | 
			
		||||
            super(attrAST);
 | 
			
		||||
            this.attrCode = attrAST.attrCode;
 | 
			
		||||
            this.attrData = attrAST.attrData;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public String head(final AST.Node node, final boolean highlighted) {
 | 
			
		||||
            final StringBuffer head = new StringBuffer();
 | 
			
		||||
            head.append(super.head(node, false));
 | 
			
		||||
            return head.toString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void desc(final int indent, final AST.Node node, final boolean highlighted) {
 | 
			
		||||
            super.desc(indent, node, false);
 | 
			
		||||
            System.out.print(highlighted ? "\033[31m" : "");
 | 
			
		||||
            if (attrCode.get(node) != null) {
 | 
			
		||||
                List<PDM.CodeInstr> instrs = attrCode.get(node);
 | 
			
		||||
                if (instrs != null) {
 | 
			
		||||
                    if (indent > 0)
 | 
			
		||||
                        System.out.printf("%" + indent + "c", ' ');
 | 
			
		||||
                    System.out.printf("--- Code: ---\n");
 | 
			
		||||
                    for (final PDM.CodeInstr instr : instrs) {
 | 
			
		||||
                        if (indent > 0)
 | 
			
		||||
                            System.out.printf("%" + indent + "c", ' ');
 | 
			
		||||
                        System.out.println((instr instanceof PDM.LABEL ? "" : "  ") + instr.toString());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (attrData.get(node) != null) {
 | 
			
		||||
                List<PDM.DataInstr> instrs = attrData.get(node);
 | 
			
		||||
                if (instrs != null) {
 | 
			
		||||
                    if (indent > 0)
 | 
			
		||||
                        System.out.printf("%" + indent + "c", ' ');
 | 
			
		||||
                    System.out.printf("--- Data: ---\n");
 | 
			
		||||
                    for (final PDM.DataInstr instr : instrs) {
 | 
			
		||||
                        if (indent > 0)
 | 
			
		||||
                            System.out.printf("%" + indent + "c", ' ');
 | 
			
		||||
                        System.out.println((instr instanceof PDM.LABEL ? "" : "  ") + instr.toString());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            System.out.print(highlighted ? "\033[30m" : "");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Izracuna kodo programa
 | 
			
		||||
     *
 | 
			
		||||
     * @param memoryAttrAST Abstraktno sintaksno drevo z dodanimi atributi izracuna
 | 
			
		||||
     *                      pomnilniske predstavitve.
 | 
			
		||||
     * @return Abstraktno sintaksno drevo z dodanimi atributi izracuna pomnilniske
 | 
			
		||||
     * predstavitve.
 | 
			
		||||
     */
 | 
			
		||||
    public static AttrAST generate(final Memory.AttrAST memoryAttrAST) {
 | 
			
		||||
        AttrAST attrAST = new AttrAST(memoryAttrAST, new HashMap<AST.Node, List<PDM.CodeInstr>>(),
 | 
			
		||||
                new HashMap<AST.Node, List<PDM.DataInstr>>());
 | 
			
		||||
        (new CodeGenerator(attrAST)).generate();
 | 
			
		||||
        return attrAST;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generiranje kode v abstraktnem sintaksnem drevesu.
 | 
			
		||||
     */
 | 
			
		||||
    private static class CodeGenerator {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Abstraktno sintaksno drevo z dodanimi atributi izracuna pomnilniske
 | 
			
		||||
         * predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        private final AttrAST attrAST;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Stevec anonimnih label.
 | 
			
		||||
         */
 | 
			
		||||
        private int labelCounter = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Ustvari nov generator kode v abstraktnem sintaksnem drevesu.
 | 
			
		||||
         *
 | 
			
		||||
         * @param attrAST Abstraktno sintaksno drevo z dodanimi atributi izracuna
 | 
			
		||||
         *                pomnilniske predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        public CodeGenerator(final AttrAST attrAST) {
 | 
			
		||||
            this.attrAST = attrAST;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Sprozi generiranje kode v abstraktnem sintaksnem drevesu.
 | 
			
		||||
         *
 | 
			
		||||
         * @return Abstraktno sintaksno drevo z dodanimi atributi izracuna pomnilniske
 | 
			
		||||
         * predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        public AttrAST generate() {
 | 
			
		||||
            attrAST.ast.accept(new Generator(), null);
 | 
			
		||||
            return new AttrAST(attrAST, Collections.unmodifiableMap(attrAST.attrCode),
 | 
			
		||||
                    Collections.unmodifiableMap(attrAST.attrData));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Obiskovalec, ki generira kodo v abstraktnem sintaksnem drevesu.
 | 
			
		||||
         */
 | 
			
		||||
        private class Generator implements AST.FullVisitor<List<PDM.CodeInstr>, Mem.Frame> {
 | 
			
		||||
 | 
			
		||||
            @SuppressWarnings({"doclint:missing"})
 | 
			
		||||
            public Generator() {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.FunDef funDef, Mem.Frame frame) {
 | 
			
		||||
                Report.Locatable loc = attrAST.attrLoc.get(funDef);
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
                code.add(new PDM.LABEL(funDef.name, loc));
 | 
			
		||||
 | 
			
		||||
                code.addAll(funDef.stmts.accept(this, frame));
 | 
			
		||||
 | 
			
		||||
                code.add(new PDM.PUSH(attrAST.attrFrame.get(funDef).parsSize, loc));
 | 
			
		||||
                code.add(new PDM.RETN(attrAST.attrFrame.get(funDef), loc));
 | 
			
		||||
 | 
			
		||||
                attrAST.attrCode.put(funDef, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.AtomExpr atomExpr, Mem.Frame frame) {
 | 
			
		||||
                Report.Locatable loc = attrAST.attrLoc.get(atomExpr);
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>();
 | 
			
		||||
                switch (atomExpr.type) {
 | 
			
		||||
                    case INTCONST:
 | 
			
		||||
                        code.add(new PDM.PUSH(Memory.decodeIntConst(atomExpr, loc), loc));
 | 
			
		||||
                        break;
 | 
			
		||||
                    case CHRCONST:
 | 
			
		||||
                        code.add(new PDM.PUSH(Memory.decodeChrConst(atomExpr, loc), loc));
 | 
			
		||||
                        break;
 | 
			
		||||
                    case STRCONST:
 | 
			
		||||
                        List<PDM.DataInstr> data = new ArrayList<>();
 | 
			
		||||
                        String label = String.valueOf(labelCounter++);
 | 
			
		||||
                        data.add(new PDM.LABEL(label, loc));
 | 
			
		||||
                        for (Integer value : Memory.decodeStrConst(atomExpr, loc)) {
 | 
			
		||||
                            data.add(new PDM.DATA(value, loc));
 | 
			
		||||
                        }
 | 
			
		||||
                        attrAST.attrData.put(atomExpr, data);
 | 
			
		||||
                        code.add(new PDM.NAME(label, loc));
 | 
			
		||||
                        code.add(new PDM.LOAD(loc));
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                attrAST.attrCode.put(atomExpr, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.BinExpr binExpr, Mem.Frame frame) {
 | 
			
		||||
                Report.Locatable loc = attrAST.attrLoc.get(binExpr);
 | 
			
		||||
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
                // TODO: invert
 | 
			
		||||
                code.addAll(binExpr.fstExpr.accept(this, frame));
 | 
			
		||||
                code.addAll(binExpr.sndExpr.accept(this, frame));
 | 
			
		||||
 | 
			
		||||
                PDM.OPER.Oper oper = switch (binExpr.oper) {
 | 
			
		||||
                    case OR -> PDM.OPER.Oper.OR;
 | 
			
		||||
                    case AND -> PDM.OPER.Oper.AND;
 | 
			
		||||
                    case EQU -> PDM.OPER.Oper.EQU;
 | 
			
		||||
                    case NEQ -> PDM.OPER.Oper.NEQ;
 | 
			
		||||
                    case GTH -> PDM.OPER.Oper.GTH;
 | 
			
		||||
                    case LTH -> PDM.OPER.Oper.LTH;
 | 
			
		||||
                    case GEQ -> PDM.OPER.Oper.GEQ;
 | 
			
		||||
                    case LEQ -> PDM.OPER.Oper.LEQ;
 | 
			
		||||
                    case ADD -> PDM.OPER.Oper.ADD;
 | 
			
		||||
                    case SUB -> PDM.OPER.Oper.SUB;
 | 
			
		||||
                    case MUL -> PDM.OPER.Oper.MUL;
 | 
			
		||||
                    case DIV -> PDM.OPER.Oper.DIV;
 | 
			
		||||
                    case MOD -> PDM.OPER.Oper.MOD;
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                code.add(new PDM.OPER(oper, loc));
 | 
			
		||||
 | 
			
		||||
                attrAST.attrCode.put(binExpr, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.Nodes<? extends AST.Node> nodes, Mem.Frame frame) {
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>();
 | 
			
		||||
                for (AST.Node node : nodes) {
 | 
			
		||||
                    code.addAll(node.accept(this, frame));
 | 
			
		||||
                }
 | 
			
		||||
                attrAST.attrCode.put(nodes, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.ExprStmt exprStmt, Mem.Frame frame) {
 | 
			
		||||
                return exprStmt.expr.accept(this, frame);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.VarExpr varExpr, Mem.Frame frame) {
 | 
			
		||||
                Report.Locatable loc = attrAST.attrLoc.get(varExpr);
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
                AST.VarDef def = (AST.VarDef) attrAST.attrDef.get(varExpr);
 | 
			
		||||
                Mem.Access access = attrAST.attrVarAccess.get(def);
 | 
			
		||||
 | 
			
		||||
                switch (access) {
 | 
			
		||||
                    case Mem.AbsAccess absAccess:
 | 
			
		||||
                        code.add(new PDM.NAME(absAccess.name, loc));
 | 
			
		||||
                        code.add(new PDM.LOAD(loc));
 | 
			
		||||
                        break;
 | 
			
		||||
                    case Mem.RelAccess relAccess:
 | 
			
		||||
                        code.add(new PDM.REGN(PDM.REGN.Reg.FP, loc));
 | 
			
		||||
                        code.add(new PDM.PUSH(relAccess.offset, loc));
 | 
			
		||||
                        code.add(new PDM.OPER(PDM.OPER.Oper.ADD, loc));
 | 
			
		||||
                        code.add(new PDM.LOAD(loc));
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                attrAST.attrCode.put(varExpr, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.UnExpr unExpr, Mem.Frame frame) {
 | 
			
		||||
                Report.Locatable loc = attrAST.attrLoc.get(unExpr);
 | 
			
		||||
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>(unExpr.expr.accept(this, frame));
 | 
			
		||||
 | 
			
		||||
                code.add(switch (unExpr.oper) {
 | 
			
		||||
                    case NOT -> new PDM.OPER(PDM.OPER.Oper.NOT, loc);
 | 
			
		||||
                    case ADD -> new PDM.OPER(PDM.OPER.Oper.ADD, loc); // TODO
 | 
			
		||||
                    case SUB -> new PDM.OPER(PDM.OPER.Oper.NEG, loc);
 | 
			
		||||
                    case MEMADDR -> new PDM.REGN(PDM.REGN.Reg.SP, loc);
 | 
			
		||||
                    case VALUEAT -> new PDM.LOAD(loc);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                attrAST.attrCode.put(unExpr, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<PDM.CodeInstr> visit(AST.CallExpr callExpr, Mem.Frame frame) {
 | 
			
		||||
                Report.Locatable loc = attrAST.attrLoc.get(callExpr);
 | 
			
		||||
                List<PDM.CodeInstr> code = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
                for (int i = 0; i < callExpr.args.size(); i++) {
 | 
			
		||||
                    AST.Expr expr = (AST.Expr) callExpr.args.get(i);
 | 
			
		||||
                    code.addAll(expr.accept(this, frame));
 | 
			
		||||
                    code.add(new PDM.REGN(PDM.REGN.Reg.SP, loc));
 | 
			
		||||
 | 
			
		||||
                    code.add(new PDM.PUSH(0, loc));
 | 
			
		||||
                    code.add(new PDM.OPER(PDM.OPER.Oper.ADD, loc));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                code.add(new PDM.REGN(PDM.REGN.Reg.FP, loc)); // SL
 | 
			
		||||
 | 
			
		||||
                code.add(new PDM.NAME(callExpr.name, loc));
 | 
			
		||||
                code.add(new PDM.LOAD(loc));
 | 
			
		||||
                code.add(new PDM.CALL(frame, loc));
 | 
			
		||||
 | 
			
		||||
                attrAST.attrCode.put(callExpr, code);
 | 
			
		||||
                return code;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generator seznama ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
     */
 | 
			
		||||
    public static class CodeSegmentGenerator {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Abstraktno sintaksno drevo z dodanimi atributi izracuna pomnilniske
 | 
			
		||||
         * predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        private final AttrAST attrAST;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Seznam ukazov za inicializacijo staticnih spremenljivk.
 | 
			
		||||
         */
 | 
			
		||||
        private final Vector<PDM.CodeInstr> codeInitSegment = new Vector<PDM.CodeInstr>();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Seznam ukazov funkcij.
 | 
			
		||||
         */
 | 
			
		||||
        private final Vector<PDM.CodeInstr> codeFunsSegment = new Vector<PDM.CodeInstr>();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Klicni zapis funkcije {@code main}.
 | 
			
		||||
         */
 | 
			
		||||
        private Mem.Frame main = null;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Ustvari nov generator seznama ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
         *
 | 
			
		||||
         * @param attrAST Abstraktno sintaksno drevo z dodanimi atributi izracuna
 | 
			
		||||
         *                pomnilniske predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        public CodeSegmentGenerator(final AttrAST attrAST) {
 | 
			
		||||
            this.attrAST = attrAST;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Izracuna seznam ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
         *
 | 
			
		||||
         * @return Seznam ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
         */
 | 
			
		||||
        public List<PDM.CodeInstr> codeSegment() {
 | 
			
		||||
            attrAST.ast.accept(new Generator(), null);
 | 
			
		||||
            codeInitSegment.addLast(new PDM.PUSH(0, null));
 | 
			
		||||
            codeInitSegment.addLast(new PDM.NAME("main", null));
 | 
			
		||||
            codeInitSegment.addLast(new PDM.CALL(main, null));
 | 
			
		||||
            codeInitSegment.addLast(new PDM.PUSH(0, null));
 | 
			
		||||
            codeInitSegment.addLast(new PDM.NAME("exit", null));
 | 
			
		||||
            codeInitSegment.addLast(new PDM.CALL(null, null));
 | 
			
		||||
            final Vector<PDM.CodeInstr> codeSegment = new Vector<PDM.CodeInstr>();
 | 
			
		||||
            codeSegment.addAll(codeInitSegment);
 | 
			
		||||
            codeSegment.addAll(codeFunsSegment);
 | 
			
		||||
            return Collections.unmodifiableList(codeSegment);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Obiskovalec, ki izracuna seznam ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
         */
 | 
			
		||||
        private class Generator implements AST.FullVisitor<Object, Object> {
 | 
			
		||||
 | 
			
		||||
            @SuppressWarnings({"doclint:missing"})
 | 
			
		||||
            public Generator() {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public Object visit(final AST.FunDef funDef, final Object arg) {
 | 
			
		||||
                if (funDef.stmts.size() == 0)
 | 
			
		||||
                    return null;
 | 
			
		||||
                List<PDM.CodeInstr> code = attrAST.attrCode.get(funDef);
 | 
			
		||||
                codeFunsSegment.addAll(code);
 | 
			
		||||
                funDef.pars.accept(this, arg);
 | 
			
		||||
                funDef.stmts.accept(this, arg);
 | 
			
		||||
                switch (funDef.name) {
 | 
			
		||||
                    case "main" -> main = attrAST.attrFrame.get(funDef);
 | 
			
		||||
                }
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public Object visit(final AST.VarDef varDef, final Object arg) {
 | 
			
		||||
                switch (attrAST.attrVarAccess.get(varDef)) {
 | 
			
		||||
                    case Mem.AbsAccess __: {
 | 
			
		||||
                        List<PDM.CodeInstr> code = attrAST.attrCode.get(varDef);
 | 
			
		||||
                        codeInitSegment.addAll(code);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    case Mem.RelAccess __: {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    default:
 | 
			
		||||
                        throw new Report.InternalError();
 | 
			
		||||
                }
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generator seznama ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
     */
 | 
			
		||||
    public static class DataSegmentGenerator {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Abstraktno sintaksno drevo z dodanimi atributi izracuna pomnilniske
 | 
			
		||||
         * predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        private final AttrAST attrAST;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         */
 | 
			
		||||
        private final Vector<PDM.DataInstr> dataSegment = new Vector<PDM.DataInstr>();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Ustvari nov generator seznama ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         *
 | 
			
		||||
         * @param attrAST Abstraktno sintaksno drevo z dodanimi atributi izracuna
 | 
			
		||||
         *                pomnilniske predstavitve.
 | 
			
		||||
         */
 | 
			
		||||
        public DataSegmentGenerator(final AttrAST attrAST) {
 | 
			
		||||
            this.attrAST = attrAST;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Izracuna seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         *
 | 
			
		||||
         * @return Seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         */
 | 
			
		||||
        public List<PDM.DataInstr> dataSegment() {
 | 
			
		||||
            attrAST.ast.accept(new Generator(), null);
 | 
			
		||||
            return Collections.unmodifiableList(dataSegment);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Obiskovalec, ki izracuna seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
         */
 | 
			
		||||
        private class Generator implements AST.FullVisitor<Object, Object> {
 | 
			
		||||
 | 
			
		||||
            @SuppressWarnings({"doclint:missing"})
 | 
			
		||||
            public Generator() {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public Object visit(final AST.VarDef varDef, final Object arg) {
 | 
			
		||||
                List<PDM.DataInstr> data = attrAST.attrData.get(varDef);
 | 
			
		||||
                if (data != null)
 | 
			
		||||
                    dataSegment.addAll(data);
 | 
			
		||||
                varDef.inits.accept(this, arg);
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public Object visit(final AST.AtomExpr atomExpr, final Object arg) {
 | 
			
		||||
                List<PDM.DataInstr> data = attrAST.attrData.get(atomExpr);
 | 
			
		||||
                if (data != null)
 | 
			
		||||
                    dataSegment.addAll(data);
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // --- ZAGON ---
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Zagon izracuna pomnilniske predstavitve kot samostojnega programa.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cmdLineArgs Argumenti v ukazni vrstici.
 | 
			
		||||
     */
 | 
			
		||||
    public static void main(final String[] cmdLineArgs) {
 | 
			
		||||
        System.out.println("This is PINS'25 compiler (code generation):");
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            if (cmdLineArgs.length == 0)
 | 
			
		||||
                throw new Report.Error("No source file specified in the command line.");
 | 
			
		||||
            if (cmdLineArgs.length > 1)
 | 
			
		||||
                Report.warning("Unused arguments in the command line.");
 | 
			
		||||
 | 
			
		||||
            try (SynAn synAn = new SynAn(cmdLineArgs[0])) {
 | 
			
		||||
                // abstraktna sintaksa:
 | 
			
		||||
                final Abstr.AttrAST abstrAttrAST = Abstr.constructAST(synAn);
 | 
			
		||||
                // semanticna analiza:
 | 
			
		||||
                final SemAn.AttrAST semanAttrAST = SemAn.analyze(abstrAttrAST);
 | 
			
		||||
                // pomnilniska predstavitev:
 | 
			
		||||
                final Memory.AttrAST memoryAttrAST = Memory.organize(semanAttrAST);
 | 
			
		||||
                // generiranje kode:
 | 
			
		||||
                final AttrAST codegenAttrAST = CodeGen.generate(memoryAttrAST);
 | 
			
		||||
 | 
			
		||||
                (new AST.Logger(codegenAttrAST)).log();
 | 
			
		||||
                {
 | 
			
		||||
                    int addr = 0;
 | 
			
		||||
                    final List<PDM.CodeInstr> codeSegment = (new CodeSegmentGenerator(codegenAttrAST)).codeSegment();
 | 
			
		||||
                    {
 | 
			
		||||
                        System.out.println("\n\033[1mCODE SEGMENT:\033[0m");
 | 
			
		||||
                        for (final PDM.CodeInstr instr : codeSegment) {
 | 
			
		||||
                            System.out.printf("%8d [%s] %s\n", addr, instr.size(),
 | 
			
		||||
                                    (instr instanceof PDM.LABEL ? "" : "  ") + instr.toString());
 | 
			
		||||
                            addr += instr.size();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    final List<PDM.DataInstr> dataSegment = (new DataSegmentGenerator(codegenAttrAST)).dataSegment();
 | 
			
		||||
                    {
 | 
			
		||||
                        System.out.println("\n\033[1mDATA SEGMENT:\033[0m");
 | 
			
		||||
                        for (final PDM.DataInstr instr : dataSegment) {
 | 
			
		||||
                            System.out.printf("%8d [%s] %s\n", addr, (instr instanceof PDM.SIZE) ? " " : instr.size(),
 | 
			
		||||
                                    (instr instanceof PDM.LABEL ? "" : "  ") + instr.toString());
 | 
			
		||||
                            addr += instr.size();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    System.out.println();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Upajmo, da kdaj pridemo to te tocke.
 | 
			
		||||
            // A zavedajmo se sledecega:
 | 
			
		||||
            // 1. Prevod je zaradi napak v programu lahko napacen :-o
 | 
			
		||||
            // 2. Izvorni program se zdalec ni tisto, kar je programer hotel, da bi bil ;-)
 | 
			
		||||
            Report.info("Done.");
 | 
			
		||||
        } catch (Report.Error error) {
 | 
			
		||||
            // Izpis opisa napake.
 | 
			
		||||
            System.err.println(error.getMessage());
 | 
			
		||||
            System.exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										624
									
								
								src/pins25/phase/Machine.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										624
									
								
								src/pins25/phase/Machine.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,624 @@
 | 
			
		||||
package pins25.phase;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import pins25.common.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Skladovni stroj.
 | 
			
		||||
 * 
 | 
			
		||||
 * Naslovi 'sistemskih' funkcij:
 | 
			
		||||
 * <ol>
 | 
			
		||||
 * <li>{@code -1}: {@code fun exit(exitcode)}</li>
 | 
			
		||||
 * <li>{@code -2}: {@code fun getint()}</li>
 | 
			
		||||
 * <li>{@code -3}: {@code fun putint(intvalue)}</li>
 | 
			
		||||
 * <li>{@code -4}: {@code fun getstr(straddr)}</li>
 | 
			
		||||
 * <li>{@code -5}: {@code fun putstr(straddr)}</li>
 | 
			
		||||
 * <li>{@code -6}: {@code fun new(size)}</li>
 | 
			
		||||
 * <li>{@code -7}: {@code fun del(addr)}</li>
 | 
			
		||||
 * </ol>
 | 
			
		||||
 */
 | 
			
		||||
public class Machine {
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings({ "doclint:missing" })
 | 
			
		||||
	public Machine() {
 | 
			
		||||
		throw new Report.InternalError();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/** Ali se opravi testni izpis ukazov. */
 | 
			
		||||
	public static boolean debugInstrsList = false;
 | 
			
		||||
 | 
			
		||||
	/** Ali se opravi testni izpis vrednost oznak. */
 | 
			
		||||
	public static boolean debugLabelsList = false;
 | 
			
		||||
 | 
			
		||||
	/** Ali se opravi testni izpis dogajanja na skladu. */
 | 
			
		||||
	public static boolean debugStack = false;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Izvajanje skladovnega stroja.
 | 
			
		||||
	 */
 | 
			
		||||
	public static class Executor {
 | 
			
		||||
 | 
			
		||||
		/** Seznam ukazov kode programa. */
 | 
			
		||||
		private final HashMap<Integer, PDM.CodeInstr> program = new HashMap<Integer, PDM.CodeInstr>();
 | 
			
		||||
 | 
			
		||||
		/** Pomnilnik (brez predstavitve ukazov. */
 | 
			
		||||
		private final HashMap<Integer, Byte> memory = new HashMap<Integer, Byte>();
 | 
			
		||||
 | 
			
		||||
		/** Preslikava imen oznak v fizicne naslove. */
 | 
			
		||||
		private final HashMap<String, Integer> labelToAddr = new HashMap<String, Integer>();
 | 
			
		||||
 | 
			
		||||
		/** Preslikava fizicnih naslovov v imena oznak. */
 | 
			
		||||
		private final HashMap<Integer, String> addrToLabel = new HashMap<Integer, String>();
 | 
			
		||||
 | 
			
		||||
		/** Velikost segmenta z ukazi kode programa. */
 | 
			
		||||
		private final int codeSegmentSize;
 | 
			
		||||
 | 
			
		||||
		/** Velikost segmenta s staticnimi spremenljivkami. */
 | 
			
		||||
		private final int dataSegmentSize;
 | 
			
		||||
 | 
			
		||||
		/** Preslikava naslova v lokacijo kode, ki je izvor vrednosti na naslovu. */
 | 
			
		||||
		final HashMap<Integer, String> debugLocs = new HashMap<Integer, String>();
 | 
			
		||||
 | 
			
		||||
		/** Preslikava naslova v pomen podatka, ki je shranjen na naslovu. */
 | 
			
		||||
		final HashMap<Integer, String> debugDscs = new HashMap<Integer, String>();
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			labelToAddr.put("exit", -1);
 | 
			
		||||
			addrToLabel.put(-1, "exit");
 | 
			
		||||
			labelToAddr.put("getint", -2);
 | 
			
		||||
			addrToLabel.put(-2, "getint");
 | 
			
		||||
			labelToAddr.put("putint", -3);
 | 
			
		||||
			addrToLabel.put(-3, "putint");
 | 
			
		||||
			labelToAddr.put("getstr", -4);
 | 
			
		||||
			addrToLabel.put(-4, "getstr");
 | 
			
		||||
			labelToAddr.put("putstr", -5);
 | 
			
		||||
			addrToLabel.put(-5, "putstr");
 | 
			
		||||
			labelToAddr.put("new", -6);
 | 
			
		||||
			addrToLabel.put(-6, "new");
 | 
			
		||||
			labelToAddr.put("del", -7);
 | 
			
		||||
			addrToLabel.put(-7, "del");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** Programski stevec. */
 | 
			
		||||
		private int PC;
 | 
			
		||||
 | 
			
		||||
		/** Klicni kazalec. */
 | 
			
		||||
		private int FP;
 | 
			
		||||
 | 
			
		||||
		/** Skladovni kazalec. */
 | 
			
		||||
		private int SP;
 | 
			
		||||
 | 
			
		||||
		/** Kazalec na prvi prosti naslov na kopici. */
 | 
			
		||||
		private int HP;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Shrani vrednost v pomnilnik.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param addr       Pomnilniski naslov.
 | 
			
		||||
		 * @param value      Vrednost.
 | 
			
		||||
		 * @param debugInstr Lokacija dela izvorne kode, ki zahteva shranjevanje.
 | 
			
		||||
		 */
 | 
			
		||||
		private void memSAVE(int addr, int value, final PDM.INSTR debugInstr) {
 | 
			
		||||
			if (addr < codeSegmentSize)
 | 
			
		||||
				throw new Report.InternalError();
 | 
			
		||||
			if (debugStack && (debugInstr != null) && (debugInstr.debugLocation != null))
 | 
			
		||||
				debugLocs.put(addr, debugInstr.debugLocation.toString());
 | 
			
		||||
			for (int b = 0; b < 4; b++) {
 | 
			
		||||
				int val = ((value >> (b * 8)) & 0xFF);
 | 
			
		||||
				memory.put(addr, (byte) val);
 | 
			
		||||
				addr += 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Prebere vrednost iz pomnilnika.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param addr Pomnilniski naslov.
 | 
			
		||||
		 * @return Vrednost.
 | 
			
		||||
		 */
 | 
			
		||||
		private int memLOAD(int addr) {
 | 
			
		||||
			if (addr < codeSegmentSize)
 | 
			
		||||
				throw new Report.InternalError();
 | 
			
		||||
			int value = 0;
 | 
			
		||||
			for (int b = 0; b < 4; b++) {
 | 
			
		||||
				Byte val = memory.get(addr);
 | 
			
		||||
				addr += 1;
 | 
			
		||||
				if (val == null)
 | 
			
		||||
					val = 0;
 | 
			
		||||
				value = value | (((val < 0) ? ((int) val) + 256 : ((int) val)) << (b * 8));
 | 
			
		||||
			}
 | 
			
		||||
			return value;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Prenos nove vrednosti na sklad.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param value      Vrednost.
 | 
			
		||||
		 * @param debugInstr Lokacija dela izvorne kode, ki prenos nove vrednosti na
 | 
			
		||||
		 *                   sklad.
 | 
			
		||||
		 */
 | 
			
		||||
		private void push(final int value, final PDM.INSTR debugInstr) {
 | 
			
		||||
			SP -= 4;
 | 
			
		||||
			memSAVE(SP, value, debugInstr);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Prevzem vrednost z vrha sklada.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @return Vrednost.
 | 
			
		||||
		 */
 | 
			
		||||
		private int pop() {
 | 
			
		||||
			if (debugStack)
 | 
			
		||||
				debugLocs.put(SP, null);
 | 
			
		||||
			final int value = memLOAD(SP);
 | 
			
		||||
			SP += 4;
 | 
			
		||||
			return value;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari nov skladovni stroj za podan program in ta program izvede.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param codeSegment Seznam ukazov, ki predstavljajo kodo programa.
 | 
			
		||||
		 * @param dataSegment Seznam ukazov, ki predstavljajo podatke programa.
 | 
			
		||||
		 */
 | 
			
		||||
		public Executor(final List<PDM.CodeInstr> codeSegment, final List<PDM.DataInstr> dataSegment) {
 | 
			
		||||
 | 
			
		||||
			Scanner scanner = new Scanner(System.in);
 | 
			
		||||
 | 
			
		||||
			int memPtr = 0;
 | 
			
		||||
 | 
			
		||||
			if (debugLabelsList)
 | 
			
		||||
				System.out.println("\n\033[1mCODE LABELS:\033[0m");
 | 
			
		||||
			for (final PDM.CodeInstr instr : codeSegment) {
 | 
			
		||||
				switch (instr) {
 | 
			
		||||
				case PDM.LABEL i -> {
 | 
			
		||||
					labelToAddr.put(i.name, memPtr);
 | 
			
		||||
					addrToLabel.put(memPtr, i.name);
 | 
			
		||||
					if (debugLabelsList)
 | 
			
		||||
						System.out.printf("LABEL %s = %d\n", i.name, memPtr);
 | 
			
		||||
					memPtr -= 1;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.INIT i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.LOAD i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.SAVE i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.POPN i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.PUSH i -> {
 | 
			
		||||
					program.put(memPtr, i);
 | 
			
		||||
					memPtr += 4;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.NAME i -> {
 | 
			
		||||
					program.put(memPtr, i);
 | 
			
		||||
					memPtr += 4;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.REGN i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.OPER i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.UJMP i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.CJMP i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.CALL i -> program.put(memPtr, i);
 | 
			
		||||
				case PDM.RETN i -> program.put(memPtr, i);
 | 
			
		||||
				default -> throw new Report.InternalError();
 | 
			
		||||
				}
 | 
			
		||||
				memPtr += 1;
 | 
			
		||||
			}
 | 
			
		||||
			codeSegmentSize = memPtr;
 | 
			
		||||
 | 
			
		||||
			if (debugLabelsList)
 | 
			
		||||
				System.out.println("\n\033[1mDATA LABELS:\033[0m");
 | 
			
		||||
			for (final PDM.DataInstr instr : dataSegment) {
 | 
			
		||||
				switch (instr) {
 | 
			
		||||
				case PDM.LABEL i -> {
 | 
			
		||||
					labelToAddr.put(i.name, memPtr);
 | 
			
		||||
					addrToLabel.put(memPtr, i.name);
 | 
			
		||||
					if (debugLabelsList)
 | 
			
		||||
						System.out.printf("LABEL %s = %d\n", i.name, memPtr);
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.SIZE i -> {
 | 
			
		||||
					memPtr += i.size;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.DATA i -> {
 | 
			
		||||
					memSAVE(memPtr, i.intc, i);
 | 
			
		||||
					memPtr += 4;
 | 
			
		||||
				}
 | 
			
		||||
				default -> throw new Report.InternalError();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			dataSegmentSize = memPtr - codeSegmentSize;
 | 
			
		||||
 | 
			
		||||
			PC = 0;
 | 
			
		||||
			FP = 0x10000;
 | 
			
		||||
			SP = 0x10000;
 | 
			
		||||
			HP = codeSegmentSize + dataSegmentSize;
 | 
			
		||||
 | 
			
		||||
			push(-1, null);
 | 
			
		||||
			FP = SP + 0;
 | 
			
		||||
			push(-1, null);
 | 
			
		||||
			SP = SP + 0;
 | 
			
		||||
 | 
			
		||||
			System.out.printf("\n");
 | 
			
		||||
			loop: while (true) {
 | 
			
		||||
 | 
			
		||||
				if (debugStack) {
 | 
			
		||||
					for (int stackAddr = 0x10000 - 4; stackAddr >= SP; stackAddr -= 4) {
 | 
			
		||||
						final String debugLoc = debugLocs.get(stackAddr);
 | 
			
		||||
						System.out.printf("%15s ", debugLoc == null ? "" : debugLoc);
 | 
			
		||||
						if (stackAddr == FP)
 | 
			
		||||
							System.out.printf("FP => ");
 | 
			
		||||
						else if (stackAddr == SP)
 | 
			
		||||
							System.out.printf("SP => ");
 | 
			
		||||
						else
 | 
			
		||||
							System.out.printf("      ");
 | 
			
		||||
						System.out.printf("%6d: %12d", stackAddr, memLOAD(stackAddr));
 | 
			
		||||
						final String debugDsc = debugDscs.get(stackAddr);
 | 
			
		||||
						System.out.printf(" %s", debugDsc == null ? "" : debugDsc);
 | 
			
		||||
						System.out.printf("\n");
 | 
			
		||||
					}
 | 
			
		||||
					System.out.printf("\n");
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				final PDM.CodeInstr instr = program.get(PC);
 | 
			
		||||
				if (debugStack) {
 | 
			
		||||
					System.out.printf("\033[1m%15s %5d: %s\033[0m\n\n",
 | 
			
		||||
							((PDM.INSTR) instr).debugLocation == null ? "" : ((PDM.INSTR) instr).debugLocation, PC,
 | 
			
		||||
							instr.toString());
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				switch (instr) {
 | 
			
		||||
				case PDM.INIT i: {
 | 
			
		||||
					int initAddr = pop();
 | 
			
		||||
					int dstAddr = pop();
 | 
			
		||||
					final int numInits = memLOAD(initAddr);
 | 
			
		||||
					initAddr += 4;
 | 
			
		||||
					for (int nInit = 0; nInit < numInits; nInit++) {
 | 
			
		||||
						int num = memLOAD(initAddr);
 | 
			
		||||
						initAddr += 4;
 | 
			
		||||
						int len = memLOAD(initAddr);
 | 
			
		||||
						initAddr += 4;
 | 
			
		||||
						for (int n = 0; n < num; n++) {
 | 
			
		||||
							for (int l = 0; l < len; l++) {
 | 
			
		||||
								memSAVE(dstAddr, memLOAD(initAddr + 4 * l), i);
 | 
			
		||||
								dstAddr += 4;
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						initAddr += 4 * len;
 | 
			
		||||
					}
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.LOAD i: {
 | 
			
		||||
					int addr = pop();
 | 
			
		||||
					int value = memLOAD(addr);
 | 
			
		||||
					push(value, i);
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.SAVE i: {
 | 
			
		||||
					final int addr = pop();
 | 
			
		||||
					final int value = pop();
 | 
			
		||||
					memSAVE(addr, value, i);
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.POPN i: {
 | 
			
		||||
					int n = pop();
 | 
			
		||||
					if (n < 0) {
 | 
			
		||||
						while (n < 0) {
 | 
			
		||||
							push(0, i);
 | 
			
		||||
							n += 4;
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						while (n > 0) {
 | 
			
		||||
							pop();
 | 
			
		||||
							n -= 4;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.PUSH i: {
 | 
			
		||||
					push(i.intc, i);
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.NAME i: {
 | 
			
		||||
					push(labelToAddr.get(i.name), i);
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.REGN i: {
 | 
			
		||||
					final int value = switch (i.regn) {
 | 
			
		||||
					case PC -> PC;
 | 
			
		||||
					case FP -> FP;
 | 
			
		||||
					case SP -> SP;
 | 
			
		||||
					default -> throw new Report.InternalError();
 | 
			
		||||
					};
 | 
			
		||||
					push(value, i);
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.OPER i: {
 | 
			
		||||
					switch (i.oper) {
 | 
			
		||||
					case NOT:
 | 
			
		||||
					case NEG: {
 | 
			
		||||
						final int expr = pop();
 | 
			
		||||
						final int result = switch (i.oper) {
 | 
			
		||||
						case NOT -> (expr == 0) ? 1 : 0;
 | 
			
		||||
						case NEG -> -expr;
 | 
			
		||||
						default -> throw new Report.InternalError();
 | 
			
		||||
						};
 | 
			
		||||
						push(result, i);
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					case OR:
 | 
			
		||||
					case AND:
 | 
			
		||||
					case EQU:
 | 
			
		||||
					case NEQ:
 | 
			
		||||
					case GTH:
 | 
			
		||||
					case LTH:
 | 
			
		||||
					case GEQ:
 | 
			
		||||
					case LEQ:
 | 
			
		||||
					case ADD:
 | 
			
		||||
					case SUB:
 | 
			
		||||
					case MUL:
 | 
			
		||||
					case DIV:
 | 
			
		||||
					case MOD: {
 | 
			
		||||
						final int snd = pop();
 | 
			
		||||
						final int fst = pop();
 | 
			
		||||
						int result = switch (i.oper) {
 | 
			
		||||
						case OR -> (fst != 0) || (snd != 0) ? 1 : 0;
 | 
			
		||||
						case AND -> (fst != 0) && (snd != 0) ? 1 : 0;
 | 
			
		||||
						case EQU -> fst == snd ? 1 : 0;
 | 
			
		||||
						case NEQ -> fst != snd ? 1 : 0;
 | 
			
		||||
						case GTH -> fst > snd ? 1 : 0;
 | 
			
		||||
						case LTH -> fst < snd ? 1 : 0;
 | 
			
		||||
						case GEQ -> fst >= snd ? 1 : 0;
 | 
			
		||||
						case LEQ -> fst <= snd ? 1 : 0;
 | 
			
		||||
						case ADD -> fst + snd;
 | 
			
		||||
						case SUB -> fst - snd;
 | 
			
		||||
						case MUL -> fst * snd;
 | 
			
		||||
						case DIV -> fst / snd;
 | 
			
		||||
						case MOD -> fst % snd;
 | 
			
		||||
						default -> throw new Report.InternalError();
 | 
			
		||||
						};
 | 
			
		||||
						push(result, i);
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					default:
 | 
			
		||||
						throw new Report.InternalError();
 | 
			
		||||
					}
 | 
			
		||||
					PC += i.size();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.UJMP i: {
 | 
			
		||||
					PC = pop();
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.CJMP i: {
 | 
			
		||||
					final int elsePC = pop();
 | 
			
		||||
					final int thenPC = pop();
 | 
			
		||||
					final int cond = pop();
 | 
			
		||||
					PC = (cond != 0) ? thenPC : elsePC;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.CALL i: {
 | 
			
		||||
					final int newPC = pop();
 | 
			
		||||
					if (newPC < 0) {
 | 
			
		||||
						switch (newPC) {
 | 
			
		||||
						case -1: { // exit(exitcode)
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							final int exitCode = pop();
 | 
			
		||||
							pop();
 | 
			
		||||
							pop();
 | 
			
		||||
							System.out.printf("EXIT CODE (SP=%d): %d\n", SP, exitCode);
 | 
			
		||||
							break loop;
 | 
			
		||||
						}
 | 
			
		||||
						case -2: { // getint()
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							final int intValue = scanner.nextInt();
 | 
			
		||||
							push(intValue, null); // result
 | 
			
		||||
							PC += i.size();
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						case -3: { // putint(intvalue)
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							final int intValue = pop();
 | 
			
		||||
							System.out.printf("%d", intValue);
 | 
			
		||||
							push(1, null); // result
 | 
			
		||||
							PC += i.size();
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						case -4: { // getstr(straddr)
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							int strAddr = pop();
 | 
			
		||||
							final String strValue = scanner.nextLine();
 | 
			
		||||
							for (int c = 0; c < strValue.length(); c++) {
 | 
			
		||||
								memSAVE(strAddr, strValue.charAt(c), null);
 | 
			
		||||
								strAddr += 4;
 | 
			
		||||
							}
 | 
			
		||||
							memSAVE(strAddr, 0, null);
 | 
			
		||||
							push(1, null); // result
 | 
			
		||||
							PC += i.size();
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						case -5: { // putstr(straddr)
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							int strAddr = pop();
 | 
			
		||||
							while (true) {
 | 
			
		||||
								int c = memLOAD(strAddr);
 | 
			
		||||
								if (c == 0)
 | 
			
		||||
									break;
 | 
			
		||||
								System.out.printf("%c", c);
 | 
			
		||||
								strAddr += 4;
 | 
			
		||||
							}
 | 
			
		||||
							push(1, null); // result
 | 
			
		||||
							PC += i.size();
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						case -6: { // new(size)
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							final int size = pop();
 | 
			
		||||
							final int addr = HP;
 | 
			
		||||
							for (int a = addr; a < addr + size; a++)
 | 
			
		||||
								memory.put(a, (byte) 0);
 | 
			
		||||
							HP += size;
 | 
			
		||||
							push(addr, null); // result
 | 
			
		||||
							PC += i.size();
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						case -7: { // del(addr)
 | 
			
		||||
							pop(); // SL
 | 
			
		||||
							pop(); // addr
 | 
			
		||||
							push(1, null); // result
 | 
			
		||||
							PC += i.size();
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						default:
 | 
			
		||||
							throw new Report.InternalError();
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						if (debugStack) {
 | 
			
		||||
							debugDscs.put(SP, "... SL");
 | 
			
		||||
							debugDscs.put(SP - 4,
 | 
			
		||||
									"... FP *** " + (i.debugFrame == null ? "" : i.debugFrame.name) + " ***");
 | 
			
		||||
							debugDscs.put(SP - 8, "... RA ");
 | 
			
		||||
							if (i.debugFrame != null) {
 | 
			
		||||
								if (i.debugFrame.debugPars != null)
 | 
			
		||||
									for (final Mem.RelAccess relAccess : i.debugFrame.debugPars)
 | 
			
		||||
										if (relAccess.debugName != null)
 | 
			
		||||
											debugDscs.put(SP + relAccess.offset, "... par: " + relAccess.debugName);
 | 
			
		||||
								if (i.debugFrame.debugVars != null)
 | 
			
		||||
									for (final Mem.RelAccess relAccess : i.debugFrame.debugVars)
 | 
			
		||||
										if (relAccess.debugName != null) {
 | 
			
		||||
											if (relAccess.size == 4)
 | 
			
		||||
												debugDscs.put(SP + relAccess.offset, "... var: " + relAccess.debugName);
 | 
			
		||||
											else {
 | 
			
		||||
												for (int s = 0; s < relAccess.size; s += 4)
 | 
			
		||||
													debugDscs.put(SP + relAccess.offset + s,
 | 
			
		||||
															"... var: " + relAccess.debugName + "[" + (s / 4) + "]");
 | 
			
		||||
											}
 | 
			
		||||
										}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						push(FP, i);
 | 
			
		||||
						push(PC + i.size(), i);
 | 
			
		||||
						FP = SP + 8;
 | 
			
		||||
						PC = newPC;
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				case PDM.RETN i: {
 | 
			
		||||
					if (debugStack) {
 | 
			
		||||
						debugDscs.put(FP, null);
 | 
			
		||||
						debugDscs.put(FP - 4, null);
 | 
			
		||||
						debugDscs.put(FP - 8, null);
 | 
			
		||||
						if (i.debugFrame != null) {
 | 
			
		||||
							if (i.debugFrame.debugPars != null)
 | 
			
		||||
								for (final Mem.RelAccess relAccess : i.debugFrame.debugPars)
 | 
			
		||||
									if (relAccess.debugName != null)
 | 
			
		||||
										debugDscs.put(FP + relAccess.offset, null);
 | 
			
		||||
							if (i.debugFrame.debugVars != null)
 | 
			
		||||
								for (final Mem.RelAccess relAccess : i.debugFrame.debugVars)
 | 
			
		||||
									if (relAccess.debugName != null) {
 | 
			
		||||
										if (relAccess.size == 4)
 | 
			
		||||
											debugDscs.put(FP + relAccess.offset, null);
 | 
			
		||||
										else {
 | 
			
		||||
											for (int s = 0; s < relAccess.size; s += 4)
 | 
			
		||||
												debugDscs.put(FP + relAccess.offset + s, null);
 | 
			
		||||
										}
 | 
			
		||||
									}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					int parsSize = pop();
 | 
			
		||||
					final int result = pop();
 | 
			
		||||
					PC = memLOAD(FP - 8);
 | 
			
		||||
					while (SP != FP) {
 | 
			
		||||
						pop();
 | 
			
		||||
					}
 | 
			
		||||
					// SP = FP;
 | 
			
		||||
					FP = memLOAD(FP - 4);
 | 
			
		||||
					parsSize += 4;
 | 
			
		||||
					while (parsSize > 0) {
 | 
			
		||||
						pop();
 | 
			
		||||
						parsSize -= 4;
 | 
			
		||||
					}
 | 
			
		||||
					push(result, i);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				default:
 | 
			
		||||
					throw new Report.InternalError();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			scanner.close();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// --- ZAGON ---
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Zagon izracuna pomnilniske predstavitve kot samostojnega programa.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param cmdLineArgs Argumenti v ukazni vrstici.
 | 
			
		||||
	 */
 | 
			
		||||
	public static void main(final String[] cmdLineArgs) {
 | 
			
		||||
		System.out.println("This is PINS'25 compiler (pushdown machine):");
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			if (cmdLineArgs.length == 0)
 | 
			
		||||
				throw new Report.Error("No source file specified in the command line.");
 | 
			
		||||
			if (cmdLineArgs.length > 1)
 | 
			
		||||
				Report.warning("Unused arguments in the command line.");
 | 
			
		||||
 | 
			
		||||
			try (SynAn synAn = new SynAn(cmdLineArgs[0])) {
 | 
			
		||||
				// abstraktna sintaksa:
 | 
			
		||||
				final Abstr.AttrAST abstrAttrAST = Abstr.constructAST(synAn);
 | 
			
		||||
				// semanticna analiza:
 | 
			
		||||
				final SemAn.AttrAST semanAttrAST = SemAn.analyze(abstrAttrAST);
 | 
			
		||||
				// pomnilniska predstavitev:
 | 
			
		||||
				final Memory.AttrAST memoryAttrAST = Memory.organize(semanAttrAST);
 | 
			
		||||
				// generiranje kode:
 | 
			
		||||
				final CodeGen.AttrAST codegenAttrAST = CodeGen.generate(memoryAttrAST);
 | 
			
		||||
 | 
			
		||||
				final List<PDM.CodeInstr> codeSegment = (new CodeGen.CodeSegmentGenerator(codegenAttrAST))
 | 
			
		||||
						.codeSegment();
 | 
			
		||||
				final List<PDM.DataInstr> dataSegment = (new CodeGen.DataSegmentGenerator(codegenAttrAST))
 | 
			
		||||
						.dataSegment();
 | 
			
		||||
 | 
			
		||||
				if (debugInstrsList) {
 | 
			
		||||
					int addr = 0;
 | 
			
		||||
					{
 | 
			
		||||
						System.out.println("\n\033[1mCODE SEGMENT:\033[0m");
 | 
			
		||||
						for (final PDM.CodeInstr instr : codeSegment) {
 | 
			
		||||
							System.out.printf("%8d [%s] %s\n", addr, instr.size(),
 | 
			
		||||
									(instr instanceof PDM.LABEL ? "" : "  ") + instr.toString());
 | 
			
		||||
							addr += instr.size();
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					{
 | 
			
		||||
						System.out.println("\n\033[1mDATA SEGMENT:\033[0m");
 | 
			
		||||
						for (final PDM.DataInstr instr : dataSegment) {
 | 
			
		||||
							System.out.printf("%8d [%s] %s\n", addr, (instr instanceof PDM.SIZE) ? " " : instr.size(),
 | 
			
		||||
									(instr instanceof PDM.LABEL ? "" : "  ") + instr.toString());
 | 
			
		||||
							addr += instr.size();
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// ustvari nov stroj in izvede program:
 | 
			
		||||
				new Executor(codeSegment, dataSegment);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Upajmo, da kdaj pridemo to te tocke.
 | 
			
		||||
			// A zavedajmo se sledecega:
 | 
			
		||||
			// 1. Prevod je zaradi napak v programu lahko napacen :-o
 | 
			
		||||
			// 2. Izvorni program se zdalec ni tisto, kar je programer hotel, da bi bil ;-)
 | 
			
		||||
			Report.info("Done.");
 | 
			
		||||
		} catch (Report.Error error) {
 | 
			
		||||
			// Izpis opisa napake.
 | 
			
		||||
			System.err.println(error.getMessage());
 | 
			
		||||
			System.exit(1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user