/// 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.
 public static new TruExpr Parse(string code)
 {
     return(TruId.Parse(ExprTree.Parse(code)));
 }