using static System.Console; using Env = System.Collections.Generic.Dictionary; interface Value { string to_string(); bool as_bool() => throw new Exception("bool expected"); int as_int() => throw new Exception("int expected"); } record Bool(bool b) : Value { public bool as_bool() => b; public string to_string() => b.ToString(); } record Int(int i) : Value { public int as_int() => i; public string to_string() => i.ToString(); } interface Expr { Value eval(Env env); } record Const(Value v) : Expr { public Value eval(Env env) => v; } record Var(string s) : Expr { public Value eval(Env env) => env[s]; } record BinOp(Expr e, string op, Expr f) : Expr { public Value eval(Env env) { Value x = e.eval(env), y = f.eval(env); return op switch { "+" => new Int(x.as_int() + y.as_int()), "-" => new Int(x.as_int() - y.as_int()), "*" => new Int(x.as_int() * y.as_int()), "/" => new Int(x.as_int() / y.as_int()), "%" => new Int(x.as_int() % y.as_int()), "==" => new Bool(x.Equals(y)), "!=" => new Bool(!x.Equals(y)), "<" => new Bool(x.as_int() < y.as_int()), "<=" => new Bool(x.as_int() <= y.as_int()), ">" => new Bool(x.as_int() > y.as_int()), ">=" => new Bool(x.as_int() >= y.as_int()), _ => throw new Exception("bad operation") }; } } interface Stmt { void run(Env env); } record Block(List stmts) : Stmt { public void run(Env env) { foreach (Stmt stmt in stmts) stmt.run(env); } } record Print(Expr e) : Stmt { public void run(Env env) { WriteLine(e.eval(env).to_string()); } } record Assign(string id, Expr e) : Stmt { public void run(Env env) { env[id] = e.eval(env); } } class Top { static void Main(string[] args) { if (args.Length < 1) { WriteLine("usage: p2 "); return; } Parser p = new(File.ReadAllText(args[0])); p.parse_program().run([]); } }