001package components.program; 002 003import components.queue.Queue; 004import components.sequence.Sequence; 005import components.simplereader.SimpleReader; 006import components.simplewriter.SimpleWriter; 007 008/** 009 * {@code ProgramKernel} enhanced with secondary methods. 010 */ 011public interface Program extends ProgramKernel { 012 013 /** 014 * A constant, with value 4, holding the number of spaces added for each 015 * indentation level when pretty printing a {@code Program} object. 016 */ 017 int INDENT_SIZE = 4; 018 019 /** 020 * BugsWorld virtual machine instructions and "byte codes". 021 */ 022 enum Instruction { 023 /** 024 * Byte code = 0. 025 */ 026 MOVE(0), 027 028 /** 029 * Byte code = 1. 030 */ 031 TURNLEFT(1), 032 033 /** 034 * Byte code = 2. 035 */ 036 TURNRIGHT(2), 037 038 /** 039 * Byte code = 3. 040 */ 041 INFECT(3), 042 043 /** 044 * Byte code = 4. 045 */ 046 SKIP(4), 047 048 /** 049 * Byte code = 5. 050 */ 051 HALT(5), 052 053 /** 054 * Byte code = 6. 055 */ 056 JUMP(6), 057 058 /** 059 * Byte code = 7. 060 */ 061 JUMP_IF_NOT_NEXT_IS_EMPTY(7), 062 063 /** 064 * Byte code = 8. 065 */ 066 JUMP_IF_NOT_NEXT_IS_NOT_EMPTY(8), 067 068 /** 069 * Byte code = 9. 070 */ 071 JUMP_IF_NOT_NEXT_IS_WALL(9), 072 073 /** 074 * Byte code = 10. 075 */ 076 JUMP_IF_NOT_NEXT_IS_NOT_WALL(10), 077 078 /** 079 * Byte code = 11. 080 */ 081 JUMP_IF_NOT_NEXT_IS_FRIEND(11), 082 083 /** 084 * Byte code = 12. 085 */ 086 JUMP_IF_NOT_NEXT_IS_NOT_FRIEND(12), 087 088 /** 089 * Byte code = 13. 090 */ 091 JUMP_IF_NOT_NEXT_IS_ENEMY(13), 092 093 /** 094 * Byte code = 14. 095 */ 096 JUMP_IF_NOT_NEXT_IS_NOT_ENEMY(14), 097 098 /** 099 * Byte code = 15. 100 */ 101 JUMP_IF_NOT_RANDOM(15), 102 103 /** 104 * Byte code = 16. 105 */ 106 JUMP_IF_NOT_TRUE(16); 107 108 /** 109 * Instruction byte code. 110 */ 111 private final int blByteCode; 112 113 /** 114 * Constructor. 115 * 116 * @param code 117 * the instruction byte code 118 */ 119 Instruction(int code) { 120 this.blByteCode = code; 121 } 122 123 /** 124 * Returns the instruction byte code. 125 * 126 * @return the instruction byte code 127 */ 128 public int byteCode() { 129 return this.blByteCode; 130 } 131 132 } 133 134 /** 135 * Pretty prints {@code this} to the given stream {@code out} using 136 * {@link #INDENT_SIZE INDENT_SIZE} spaces for each indentation level. 137 * 138 * @param out 139 * the output stream 140 * @updates out.content 141 * @requires out.is_open 142 * @ensures <pre> 143 * out.content = 144 * #out.content * [this pretty printed using INDENT_SIZE spaces for indentation] 145 * </pre> 146 */ 147 void prettyPrint(SimpleWriter out); 148 149 /** 150 * Parses a BL program from {@code in} into {@code this}. 151 * 152 * @param in 153 * the input stream 154 * @replaces this 155 * @updates in.content 156 * @requires in.is_open 157 * @ensures {@code 158 * if #in.content = [a program string] and 159 * [the last token of #in.content equals the name of the program supplied 160 * near the beginning] and 161 * [the beginning name of each new instruction equals its ending name] and 162 * [none of the names of the new instructions equals the name of a primitive 163 * instruction in the BL language or the name of any other new 164 * instruction] then 165 * this = [Program corresponding to program string #in.content] and 166 * in.content = <> 167 * else 168 * [reports an appropriate error message to the console and terminates client] 169 * } 170 */ 171 void parse(SimpleReader in); 172 173 /** 174 * Parses a BL program from {@code tokens} into {@code this}. 175 * 176 * @param tokens 177 * the input tokens 178 * @replaces this 179 * @updates tokens 180 * @requires {@code [<Tokenizer.END_OF_INPUT> is a suffix of tokens]} 181 * @ensures {@code 182 * if #tokens = [a program string] * <Tokenizer.END_OF_INPUT> and 183 * [the penultimate token of #tokens equals the name of the program supplied 184 * near the beginning] and 185 * [the beginning name of each new instruction equals its ending name] and 186 * [none of the names of the new instructions equals the name of a primitive 187 * instruction in the BL language or the name of any other new 188 * instruction] then 189 * this = [Program corresponding to program string at start of #tokens] and 190 * tokens = <Tokenizer.END_OF_INPUT> 191 * else 192 * [reports an appropriate error message to the console and terminates client] 193 * } 194 */ 195 void parse(Queue<String> tokens); 196 197 /** 198 * Generates and returns the sequence of virtual machine instructions ( 199 * "byte codes") corresponding to {@code this}. 200 * 201 * @return the compiled program 202 * @ensures <pre> 203 * if [all instructions called in this are either primitive or 204 * defined in this.context] and 205 * [this does not include any calling cycles, i.e., recursion] then 206 * generatedCode = 207 * [the sequence of virtual machine "byte codes" corresponding to this] 208 * else 209 * [reports an appropriate error message to the console and terminates client] 210 * </pre> 211 */ 212 Sequence<Integer> generatedCode(); 213 214}