Advertisement
Guest User

Untitled

a guest
Jan 27th, 2020
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.72 KB | None | 0 0
  1. use std::collections::HashMap;
  2.  
  3. #[derive(Debug)]
  4. enum Instruction {
  5. Move(isize),
  6. Increment(u8),
  7. Decrement(u8),
  8. Loop(Procedure),
  9. Output,
  10. Input,
  11. EOF,
  12. }
  13.  
  14. type Procedure = Vec<Instruction>;
  15.  
  16. fn compile_program(program: &str) -> Procedure {
  17. let mut procedure = compile(program);
  18. procedure.push(Instruction::EOF);
  19. procedure
  20. }
  21.  
  22. fn compile(program: &str) -> Procedure {
  23. let mut procedure: Procedure = vec![];
  24. let pairs = build_pairs(program);
  25.  
  26. let mut i = 0;
  27. let mut trailing = ' ';
  28. let mut trailing_val = 0;
  29.  
  30. while i < program.len() {
  31. // Get the current instruction in the feed
  32. let instr = program.chars().nth(i).expect("No instructions in program");
  33.  
  34. // If the trailing character is not already set to the incoming instruction (it's the start
  35. // of a new possible trail), take whatever was previously trailing, and push it to our
  36. // procedure
  37. if trailing != instr {
  38. match trailing {
  39. '>' | '<' => procedure.push(Instruction::Move(trailing_val)),
  40. '+' => procedure.push(Instruction::Increment(trailing_val as u8)),
  41. '-' => procedure.push(Instruction::Decrement(trailing_val as u8)),
  42. _ => (),
  43. }
  44. trailing = instr;
  45. trailing_val = 0;
  46. }
  47.  
  48. match instr {
  49. '>' | '<' | '+' | '-' => match instr {
  50. '>' | '+' | '-' => trailing_val += 1,
  51. '<' => trailing_val -= 1,
  52. _ => (),
  53. },
  54. '[' => {
  55. procedure.push(Instruction::Loop(compile(
  56. &program[i + 1..pairs[&i]].chars().collect::<String>(),
  57. )));
  58. i = pairs[&i];
  59. }
  60. '.' => {
  61. procedure.push(Instruction::Output);
  62. }
  63. ',' => {
  64. procedure.push(Instruction::Input);
  65. }
  66. _ => (),
  67. }
  68. i += 1;
  69. }
  70.  
  71. match trailing {
  72. '>' | '<' => procedure.push(Instruction::Move(trailing_val)),
  73. '+' => procedure.push(Instruction::Increment(trailing_val as u8)),
  74. '-' => procedure.push(Instruction::Decrement(trailing_val as u8)),
  75. _ => (),
  76. }
  77.  
  78. procedure
  79. }
  80.  
  81. struct Computer {
  82. memory: Vec<u8>,
  83. pointer: isize,
  84. }
  85.  
  86. impl Computer {
  87. fn new() -> Self {
  88. Computer {
  89. memory: vec![0; 30000],
  90. pointer: 0,
  91. }
  92. }
  93.  
  94. fn run(&mut self, procedure: &Procedure) {
  95. self.run_procedure(procedure);
  96. }
  97.  
  98. fn run_procedure(&mut self, procedure: &Procedure) {
  99. for instruction in procedure {
  100. match instruction {
  101. Instruction::Move(n) => {
  102. self.pointer += n;
  103. }
  104. Instruction::Increment(n) => {
  105. self.memory[self.pointer as usize] =
  106. self.memory[self.pointer as usize].wrapping_add(*n);
  107. }
  108. Instruction::Decrement(n) => {
  109. self.memory[self.pointer as usize] =
  110. self.memory[self.pointer as usize].wrapping_sub(*n);
  111. }
  112. Instruction::Output => {
  113. print!("{}", self.memory[self.pointer as usize] as char);
  114. }
  115. Instruction::Loop(proc) => {
  116. if self.memory[self.pointer as usize] > 0 {
  117. self.run_procedure(&proc);
  118. }
  119. }
  120. Instruction::EOF => {
  121. return;
  122. }
  123. _ => (),
  124. }
  125. }
  126.  
  127. if self.memory[self.pointer as usize] != 0 {
  128. self.run_procedure(procedure);
  129. }
  130. }
  131. }
  132.  
  133. fn build_pairs(program: &str) -> HashMap<usize, usize> {
  134. let mut stack_depth = 0;
  135. let mut stack: Vec<usize> = vec![];
  136. let mut stack_map: HashMap<usize, usize> = HashMap::new();
  137. let mut i = 0;
  138.  
  139. while i < program.len() {
  140. let instruction = program.chars().nth(i).expect("No instructions in program");
  141. match instruction {
  142. '[' => {
  143. stack_depth += 1;
  144. stack.push(i);
  145. }
  146. ']' => {
  147. let opening_brace = stack.pop().expect("No opening brace");
  148. stack_map.insert(opening_brace, i);
  149. }
  150. _ => (),
  151. }
  152. i += 1;
  153. }
  154.  
  155. stack_map
  156. }
  157.  
  158. fn main() {
  159. let program = std::fs::read_to_string("adv.b").unwrap();
  160. let procedure = compile_program(&program);
  161. let mut pc: Computer = Computer::new();
  162. pc.run(&procedure);
  163. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement