/// Parses an ExprTree into Tru abstract syntax that can be Executed. public static TruStatement Parse(ExprTree expr) { if (expr is ExprList exprList && exprList.list.Length > 0) // cast expr into exprList { if (ExprTree.Match("{define LITERAL ANY}", exprList)) { return(new TruDef(TruId.Parse(exprList.list[1]).name, TruExpr.Parse(exprList.list[2]))); } else if (ExprTree.Match("{define {LITERAL LITERAL ...} ANY}", exprList)) { ExprTree[] signature = ((ExprList)exprList.list[1]).list; string[] paramaters = new string[signature.Length - 1]; // put all but first element into parameters as strings for (int i = 0; i < paramaters.Length; i++) { paramaters[i] = TruId.Parse(signature[i + 1]).name; } return(new TruDef(TruId.Parse(signature[0]).name, new TruLambda(paramaters, TruExpr.Parse(exprList.list[2])) )); } } // If not a define statement, its an expression. return(TruExpr.Parse(expr)); }
/// Parses an ExprTree into Tru abstract syntax. public static new TruExpr Parse(ExprTree expr) { if (expr is ExprLiteral exprLit) { if (ExprTree.Match("true", exprLit)) { return(new TruBool(true)); } else if (ExprTree.Match("false", exprLit)) { return(new TruBool(false)); } else { return(TruId.Parse(exprLit)); } } else if (expr is ExprList exprList && exprList.list.Length > 0) // cast expr into exprList { if (ExprTree.Match("{lambda {LITERAL ...} ANY}", exprList)) { ExprTree[] parameters = ((ExprList)exprList.list[1]).list; return(new TruLambda( Helpers.ArrayMap(parameters, (p) => TruId.Parse(p).name), // Will throw error if contains an invalid id. TruExpr.Parse(exprList.list[2]) )); } else if (ExprTree.Match("{let {[LITERAL ANY] ...} ANY}", exprList)) { ExprList[] localExpr = Helpers.ArrayMap(((ExprList)exprList.list[1]).list, (x) => (ExprList)x); (string, TruExpr)[] locals = Helpers.ArrayMap(localExpr, // Convert into name, expr tuples.
/// Interprets expr, checks its type, and returns it. Throws an error if the type doesn't match. private static T Check <T>(TruExpr expr, Environment env) where T : TruVal { TruVal val = expr.Interpret(env); if (val is T t) { return(t); } else { throw new TruRuntimeException($"Incorrect types, given {val.GetType().Name} expected {typeof(T).Name}."); } }
/// Parses a string into Tru abstract syntax that can be interpreted. public static new TruExpr Parse(string code) { return(TruExpr.Parse(ExprTree.Parse(code))); }