main.pony 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. use "collections"
  2. use "files"
  3. use "format"
  4. interface Value
  5. fun value(): I64
  6. class Position
  7. let _addr: I64
  8. let _value: I64
  9. new create(__addr: I64, __value: I64) =>
  10. _addr = __addr
  11. _value = __value
  12. fun addr(): I64 => _addr
  13. fun value(): I64 => _value
  14. class Immediate
  15. let _value: I64
  16. new create(__value: I64) =>
  17. _value = __value
  18. fun value(): I64 => _value
  19. class Operands
  20. let _lhs: Value
  21. let _rhs: Value
  22. let _tgt: I64
  23. new create(__lhs: Value, __rhs: Value, __tgt: I64) =>
  24. _lhs = __lhs
  25. _rhs = __rhs
  26. _tgt = __tgt
  27. fun val1(): I64 => _lhs.value()
  28. fun val2(): I64 => _rhs.value()
  29. fun tgt(): USize => _tgt.usize()
  30. trait Error
  31. fun message(): String
  32. class val OutOfBounds is Error
  33. let _loc: USize
  34. new val create(loc: USize) => _loc = loc
  35. fun message(): String =>
  36. "Memory access out of bounds: " + Format.int[USize](_loc)
  37. class val UnknownOperand is Error
  38. let _op: I64
  39. new val create(op: I64) => _op = op
  40. fun message(): String =>
  41. "Unknown operand: " + Format.int[I64](_op)
  42. primitive Handler
  43. fun run(env: Env, result: (None | Error)) =>
  44. match result
  45. | None => None
  46. | let e: Error => env.err.print(e.message())
  47. end
  48. class Program
  49. var storage: Array[I64]
  50. var pc: USize = 0
  51. var errors: Array[Error val]
  52. new create(s: Array[I64]) =>
  53. storage = s
  54. errors = Array[Error val]()
  55. new from_file(file: File) =>
  56. storage = Array[I64](0)
  57. for line in file.lines() do
  58. for chunk in line.split(",").values() do
  59. try
  60. storage.push(chunk.i64()?)
  61. end
  62. end
  63. end
  64. errors = Array[Error val]()
  65. fun print(env: Env) =>
  66. env.out.write("[")
  67. for x in storage.values() do
  68. env.out.write(Format.int[I64](x))
  69. env.out.write(" ")
  70. end
  71. env.out.print("]")
  72. fun ref read_storage(addr: USize): I64 ? =>
  73. try
  74. storage(addr)?
  75. else
  76. errors.push(OutOfBounds(addr))
  77. error
  78. end
  79. fun ref write_storage(addr: USize, value: I64) ? =>
  80. try
  81. storage(addr)? = value
  82. else
  83. errors.push(OutOfBounds(addr))
  84. error
  85. end
  86. fun ref get_immediate(addr_loc: USize): Immediate ? =>
  87. let value = read_storage(addr_loc)?
  88. Immediate(value)
  89. fun ref get_position(addr_loc: USize): Position ? =>
  90. let addr = read_storage(addr_loc)?
  91. let value = read_storage(addr.usize())?
  92. Position(addr, value)
  93. fun ref get_op_data(): Operands ? =>
  94. let lhs = get_position(pc+1)?
  95. let rhs = get_position(pc+2)?
  96. let tgt = read_storage(pc+3)?
  97. Operands(lhs, rhs, tgt)
  98. fun ref do_add() ? =>
  99. let data = get_op_data()?
  100. write_storage(data.tgt(), data.val1() + data.val2())?
  101. pc = pc + 4
  102. None
  103. fun ref do_mul() ? =>
  104. let data = get_op_data()?
  105. write_storage(data.tgt(), data.val1() * data.val2())?
  106. pc = pc + 4
  107. None
  108. fun ref run() ? =>
  109. match read_storage(pc)?
  110. | 1 => do_add()?
  111. | 2 => do_mul()?
  112. | 99 => return None
  113. | let x: I64 =>
  114. errors.push(UnknownOperand(x))
  115. error
  116. end
  117. run()?
  118. fun make_trial(a: I64, b: I64): Program ? =>
  119. var arr = storage.clone()
  120. arr(1)? = a
  121. arr(2)? = b
  122. Program(arr)
  123. fun ref run_trial(env: Env): Bool =>
  124. try
  125. run()?
  126. else
  127. for err in errors.values() do
  128. env.out.print(err.message())
  129. end
  130. end
  131. try
  132. storage(0)? == 19690720
  133. else
  134. false
  135. end
  136. actor Main
  137. new create(env: Env) =>
  138. let caps = recover val FileCaps.>set(FileRead).>set(FileStat) end
  139. try
  140. with
  141. file = OpenFile(FilePath(env.root as AmbientAuth, "input.txt", caps)?) as File
  142. do
  143. let program = Program.from_file(file)
  144. program.print(env)
  145. for a in Range[I64](0, 100) do
  146. for b in Range[I64](0, 100) do
  147. let trial = program.make_trial(a, b)?
  148. if trial.run_trial(env) then
  149. env.out.print("noun=" + Format.int[I64](a) + ", verb=" + Format.int[I64](b))
  150. env.out.print("result=" + Format.int[I64]((a * 100) + b))
  151. end
  152. end
  153. end
  154. end
  155. else
  156. // if something failed, then print an error message of some kind and exit
  157. env.err.print("Couldn't read expected file `input.txt'")
  158. env.exitcode(99)
  159. end