main.pony 4.0 KB

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