commit
a926b96a5a
1 changed files with 73 additions and 0 deletions
@ -0,0 +1,73 @@ |
|||
use "itertools" |
|||
|
|||
class RPN |
|||
fun operate(a : I64, b : I64, op : String) : I64 => |
|||
match op |
|||
| "+" => return a + b |
|||
| "*" => return a * b |
|||
| "/" => return a / b |
|||
| "-" => return a - b |
|||
else |
|||
0 |
|||
end |
|||
|
|||
fun calculate(exp : String, env : Env)? => |
|||
let tokens = this.tokenize(exp) |
|||
let stack : Array[I64] = [] |
|||
|
|||
for token in tokens do |
|||
match token |
|||
| let op : String => |
|||
try |
|||
stack.push(this.operate(stack.pop()?, stack.pop()?, op)) |
|||
else |
|||
env.out.print("Error: stack underflow, exiting") |
|||
return |
|||
end |
|||
|
|||
| let n : I64 => |
|||
stack.push(n) |
|||
end |
|||
end |
|||
|
|||
env.out.print(stack.apply(0)?.string()) |
|||
|
|||
None |
|||
|
|||
fun tokenize(exp : String) : Iter[(I64 | String)] => |
|||
// We use a union type since read_int returns (I64, USize), and we want I64 | String |
|||
Iter[String](exp.split(" ").values()) |
|||
.filter({ |
|||
(c) => (c != "") and (c != "\t") and (c != "\n") |
|||
}) |
|||
.map[(I64 | String)]({ |
|||
(n) => |
|||
try |
|||
// ? indicates it could return an exception |
|||
match n.read_int[I64]() ? |
|||
// returns the character if no int was found |
|||
| (0, 0) => n |
|||
| (let n' : I64, let s : USize) => n' |
|||
end |
|||
else |
|||
n |
|||
end |
|||
}) |
|||
|
|||
new val create() => |
|||
// Make the RPN class a val |
|||
// This means the instance is immutable |
|||
// It can be safely aliased |
|||
""" |
|||
""" |
|||
|
|||
actor Main |
|||
new create(env : Env) => |
|||
let calc = RPN.create() |
|||
let input : String = " ".join(Iter[String](env.args.values()).skip(1)) |
|||
|
|||
try |
|||
calc.calculate(input, env)? |
|||
else |
|||
None |
|||
end |
Loading…
Reference in new issue