using System; namespace AST { public interface ISemantReturn { T Value { get; } ABT.Env Env { get; } } public class SemantReturn : ISemantReturn { protected SemantReturn(ABT.Env env, T value) { this.Value = value; this.Env = env; } public static ISemantReturn Create(ABT.Env env, T value) => new SemantReturn(env, value); public T Value { get; } public ABT.Env Env { get; } } public class SemantReturn { public static ISemantReturn Create(ABT.Env env, T value) => SemantReturn.Create(env, value); } public static class SemanticAnalysis { public class SemantMethod : System.Attribute { } public static R Semant(Func> semantFunc, ref ABT.Env env) { var semantReturn = semantFunc(env); env = semantReturn.Env; return semantReturn.Value; } public static R Semant(Func> semantFunc, I arg, ref ABT.Env env) { var semantReturn = semantFunc(env, arg); env = semantReturn.Env; return semantReturn.Value; } public static ABT.Expr SemantExpr(Func semantFunc, ILineInfo info, ref ABT.Env env) { var semantReturn = semantFunc(env, info); env = semantReturn.Env; return semantReturn; } public static ABT.Expr SemantExpr(Expr expr, ref ABT.Env env) => SemantExpr(expr.GetExpr, expr, ref env); public static ABT.Stmt SemantStmt(Func> semantFunc, ref ABT.Env env) { var semantReturn = semantFunc(env); env = semantReturn.Item1; return semantReturn.Item2; } } }