using System; using System.Collections.Generic; namespace Amogulator.Suslang; public class Compiler { private List operations = new(); public List result() => this.operations; public string compileExpr(Expr expr) => expr switch { IntExpr => compileIntExpr((IntExpr) expr), FloatExpr => compileFloatExpr((FloatExpr) expr), StringExpr => compileStringExpr((StringExpr) expr), BoolExpr => compileBoolExpr((BoolExpr) expr), UnaryExpr => compileUnaryExpr((UnaryExpr) expr), BinaryExpr => compileBinaryExpr((BinaryExpr) expr), _ => throw new NotImplementedException(), }; public string compileIntExpr(IntExpr expr) { this.operations.Add(new PushIntOperation() { value = expr.value }); return "int"; } public string compileFloatExpr(FloatExpr expr) { this.operations.Add(new PushFloatOperation() { value = expr.value }); return "float"; } public string compileStringExpr(StringExpr expr) { this.operations.Add(new PushStringOperation() { value = expr.value }); return "string"; } public string compileBoolExpr(BoolExpr expr) { this.operations.Add(new PushBoolOperation() { value = expr.value }); return "bool"; } public string compileUnaryExpr(UnaryExpr expr) { throw new NotImplementedException(); } public string compileBinaryExpr(BinaryExpr expr) { var leftType = compileExpr(expr.left); var rightType = compileExpr(expr.right); if ((leftType, rightType) == ("int", "int")) { this.operations.Add(expr.type switch { BinaryType.Add => new AddIntOperation(), BinaryType.Subtract => new SubtractIntOperation(), BinaryType.Multiply => new MultiplyIntOperation(), BinaryType.Divide => new DivideIntOperation(), BinaryType.Modulo => new ModuloIntOperation(), }); return "int"; } else if ((leftType, rightType) == ("float", "float")) { this.operations.Add(expr.type switch { BinaryType.Add => new AddFloatOperation(), BinaryType.Subtract => new SubtractFloatOperation(), BinaryType.Multiply => new MultiplyFloatOperation(), BinaryType.Divide => new DivideFloatOperation(), BinaryType.Modulo => new ModuloFloatOperation(), }); return "float"; } else { throw new Exception("type mismatch"); } } }