// stack implementation with little error handling. using System; using ResultMonad; public interface Stack { void push(T x); T pop(); T peek(); int size(); } public class ArrayStack : Stack { T[] A; // underlying array int tos; // top of stack (first value at A[tos-1]), also keeps track of size public ArrayStack(int capacity) { if (capacity < 1) capacity = 16; // 16 is default capacity A = new T[capacity]; tos = 0; }//constructor public int size() { return tos; } public int capacity() { return A.Length; } public void push(T x) { if (tos>=A.Length) throw new Exception("Stack overflow!"); A[tos++] = x; }//push public T pop() { if (tos<1) throw new Exception("Stack underflow!"); return A[--tos]; }//pop public T peek() { if (tos<1) throw new Exception("Stack underflow!"); else return A[tos-1]; } }//ArrayStack public interface SafeStack { Result push(T x); // int is dummy type Result pop(); Result peek(); int size(); } public class ArrStack : SafeStack { // for convenience static Result Ok(R x) => Result.Ok(x); static Result Err(String s) => Result.Err(s); T[] A; // underlying array int tos; // top of stack (first value at A[tos-1]), also keeps track of size public ArrStack(int capacity) { if (capacity < 1) capacity = 16; // 16 is default capacity A = new T[capacity]; tos = 0; }//constructor public int size() { return tos; } public int capacity() { return A.Length; } public Result push(T x) { if (tos>=A.Length) return Err("Stack overflow"); A[tos++] = x; return Ok(tos); }//push public Result pop() { if (tos<1) return Err("Stack underflow"); else return Ok(A[tos-1]); }//pop public Result peek() { if (tos<1) return Err("Stack underflow"); else return Ok(A[tos-1]); } }//ArrayStack