| 
					
				 | 
			
			
				@@ -85,6 +85,21 @@ type Opcode is I64 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // a Mode is true if immediate, false if positional 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type Modes is (Bool, Bool, Bool) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class val OutputRequest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let _o: I64 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  new val create(_o': I64) => _o = _o' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun output(): I64 => _o 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun string(): String => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "OutputRequest(" + _o.string() + ")" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+primitive InputRequest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun string(): String => "InputRequest" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+primitive Halted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun string(): String => "Halted" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type ProgramResult is (OutputRequest | InputRequest | Halted) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   All the logic we need for running programs 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -94,26 +109,23 @@ class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   var storage: Array[I64] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // the current instruction we're running 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   var pc: USize = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  var input: Array[I64] = Array[I64]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // a list of errors that may or may not have happened. (right now, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // we'll only ever have one, but it's worth planning ahead, eh?) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   var errors: Array[Error val] = Array[Error val]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // the queue of input values from the user 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  var input: Array[I64] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // the queue of lines we intend to output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  var output: Array[I64] = Array[I64]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // a queue of debug messages 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   var debug: Array[String] = Array[String]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  new create(s: Array[I64], i: Array[I64] = Array[I64]()) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  new create(s: Array[I64]) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Create a Program from a verbatim storage and input array 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     storage = s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    input = i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  new from_file(file: File, i: Array[I64] = Array[I64]()) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  new from_file(file: File) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Create a Program by walking input from a file. This just skips any 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     errors if they happen (e.g. if there are non-numbers), which 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -127,8 +139,9 @@ class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    input = i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref send_input(i: I64) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    input.push(i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   fun print(env: Env) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -224,13 +237,15 @@ class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (opcode, (mode1 == 1, mode2 == 1, mode3 == 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun ref do_binop(modes: Modes, op: {(I64, I64): I64}) ? => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref do_binop(modes: Modes, op: {(I64, I64): I64}, op_name: String) ? => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Get the values of the first two operands by the provided modes, run 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     the function `op` on them, and store the result of that at the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     provided location 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let data = get_op_data(modes)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    dbg("    writing " + data.val1().string() + op_name + data.val2().string() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      + " = " + op(data.val1(), data.val2()).string() + " to *" + data.tgt().string()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     write_storage(data.tgt(), op(data.val1(), data.val2()))? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pc = pc + 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -258,19 +273,45 @@ class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       errors.push(NotEnoughInput(pc)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    write_storage(read_storage(pc+1)?.usize(), i)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let addr = read_storage(pc+1)?.usize() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    dbg("    writing " + i.string() + " to *" + addr.string()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    write_storage(addr.usize(), i)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pc = pc + 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun ref do_output(modes: Modes) ? => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref do_output(modes: Modes): OutputRequest ? => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Write the value indicated according to the mode to the output queue. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (let m, _, _) = modes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    output.push(get_value(pc+1, m)?.value()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let r = get_value(pc+1, m)?.value() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pc = pc + 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    OutputRequest(r) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref at_pc(): USize => pc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref fmt_op(opcode: I64, modes: Modes): String => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (let a, let b, let c) = modes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let op1 = try read_storage(pc+1)? else -99 end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let op2 = try read_storage(pc+2)? else -99 end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let op3 = try read_storage(pc+3)? else -99 end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let arg1 = if not a then "*" else "" end + op1.string() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let arg2 = if not b then "*" else "" end + op2.string() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let arg3 = if not c then "*" else "" end + op3.string() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    match opcode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 1 => "add " + arg1 + " " + arg2 + " -> " + arg3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 2 => "sub " + arg1 + " " + arg2 + " -> " + arg3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 3 => "input " + arg1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 4 => "output " + arg1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 5 => "jnz " + arg1 + " to " + arg2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 6 => "jez " + arg1 + " to " + arg2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 7 => "lt " + arg1 + " " + arg2 + " -> " + arg3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 8 => "eq " + arg1 + " " + arg2 + " -> " + arg3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      | 99 => "halt" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      "unknown op(" + opcode.string() + ")" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun ref run_loop() ? => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref run_loop(): ProgramResult ? => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     This continues running the VM until it encounters a halt instruction 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     or it encounters some other error 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -278,33 +319,43 @@ class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while true do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (let opcode, let modes) = parse_op(read_storage(pc)?) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      dbg("running op " + Format.int[I64](opcode)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      dbg("  " + pc.string() + " -> " + fmt_op(opcode, modes)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       match opcode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 1 => do_binop(modes, {(x, y) => x + y})? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 2 => do_binop(modes, {(x, y) => x * y})? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 3 => do_input(modes)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 4 => do_output(modes)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 1 => do_binop(modes, {(x, y) => x + y}, "+")? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 2 => do_binop(modes, {(x, y) => x * y}, "*")? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 3 => try do_input(modes)? else return InputRequest end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 4 => return do_output(modes)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         | 5 => do_jump(modes, {(x) => x != 0})? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         | 6 => do_jump(modes, {(x) => x == 0})? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 7 => do_binop(modes, {(x, y) => if x < y then 1 else 0 end})? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 8 => do_binop(modes, {(x, y) => if x == y then 1 else 0 end})? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        | 99 => return None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 7 => do_binop(modes, {(x, y) => if x < y then 1 else 0 end}, "<")? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 8 => do_binop(modes, {(x, y) => if x == y then 1 else 0 end}, "==")? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        | 99 => return Halted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         | let x: I64 => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           errors.push(UnknownOperand(x)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Halted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun ref run(env: Env): Array[I64] => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref run_with(env: Env, i: Array[I64]): Array[I64] => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     This runs the VM and prints output: if an error occurs, it prints 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     the error message(s) and any debug messages that happened during 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     program execution, and then it prints everything printed via an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     output instruction. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    input.append(i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var output = Array[I64]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var is_done = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     try 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      run_loop()? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      repeat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        match run_loop()? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          | Halted => is_done = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          | InputRequest => env.err.print("Not enough input for program"); is_done = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          | let o: OutputRequest => output.push(o.output()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      until is_done end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       for err in errors.values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         env.out.print(err.message()) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -318,12 +369,24 @@ class Program 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun ref clone(): Program => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Program(storage, input) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref run_step(env: Env): ProgramResult => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      env.out.print("restarting from " + pc.string()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let r = run_loop()? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for msg in debug.values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        env.out.print(msg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      debug.clear() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      r 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for err in errors.values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        env.out.print(err.message()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      Halted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun ref set_input(i: Array[I64]): Program => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    input = i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun ref clone(): Program => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Program(storage.clone()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 actor Main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   new create(env: Env) => 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -334,12 +397,12 @@ actor Main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       with 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         file = OpenFile(FilePath(env.root as AmbientAuth, target_file, caps)?) as File 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let program = Program.from_file(file, [0;1]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let program = Program.from_file(file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         var max: (I64 | None) = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         var choice = Array[I64]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for p in permutations([0;1;2;3;4]).values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          env.out.print("\ntesting") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          let res = test_phases(env, program, p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for p in permutations([5;6;7;8;9]).values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          env.out.print(".") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          let res = test_phases_pt2(env, program, p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if try (res as I64) > (max as I64) else true end then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             max = res 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             choice = p 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -358,10 +421,10 @@ actor Main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       env.exitcode(99) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fun test_phases(env: Env, program: Program, phases: Array[I64]): (I64 | None) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun test_phases_pt1(env: Env, program: Program, phases: Array[I64]): (I64 | None) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     var input: I64 = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for i in phases.values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      let output = program.clone().set_input([i; input]).run(env) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let output = program.clone().run_with(env, [i;input]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       input = try output(0)? else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         env.out.print("Not enough output returned") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return None 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -370,6 +433,48 @@ actor Main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     input 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fun test_phases_pt2(env: Env, program: Program, phases: Array[I64]): (I64 | None) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var input: (I64 | None) = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var programs = Array[(I64, Program)]() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var n: I64 = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for i in phases.values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let p = program.clone() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      env.out.print("first step on " + n.string() + " produces " + p.run_step(env).string()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      env.out.print("  (pc = " + p.at_pc().string() + ")") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      env.out.print("sending input " + i.string()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      p.send_input(i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      env.out.print("second step on " + n.string() + " produces " + p.run_step(env).string()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      env.out.print("  (pc = " + p.at_pc().string() + ")") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      programs.push((n, p)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      n = n + 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var programs_left = phases.size() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while programs_left > 0 do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (n', p) in programs.values() do 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        env.out.print("running program " + n'.string() + " at " + p.at_pc().string() + " with " + input.string() + ": ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          p.send_input((input = None) as I64) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          env.out.print("used input more than once!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var running = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        repeat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          let r = p.run_step(env) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          match r 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            | Halted => programs_left = programs_left - 1; running = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            | InputRequest => running = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            | let o: OutputRequest => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            input = o.output() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            env.out.print("produced " + input.string() + ", ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        until not running end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        env.out.print("") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    input 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   fun permutations(array: Array[I64]): Array[Array[I64]] => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if array.size() == 0 then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       [[]] 
			 |