commit a926b96a5a222ad8482dcec65385bda4b831b011 Author: Wesley Kerfoot Date: Wed May 1 15:59:41 2019 -0400 Initial commit of RPN program diff --git a/rpn/main.pony b/rpn/main.pony new file mode 100644 index 0000000..aac7700 --- /dev/null +++ b/rpn/main.pony @@ -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