public object Evaluate(Environment environment, object expression) => Evaluation(environment, Syntax.Parse((string)(expression as object[])[0]), true);
        protected virtual object Evaluation(Environment environment, object expression, bool topLevel)
        {
            var list   = expression as object[];
            var symbol = Syntax.Symbol(expression);

            if (environment == null)
            {
                return(Validate().Evaluation(new Environment(this, Semantics), expression));
            }
            else if (list != null)
            {
                Keyword keyword;
                if ((list.Length > 1) && ((symbol = Syntax.Symbol(list[1])) != null) && ((keyword = Keyword(symbol.Id)) != null))
                {
                    if (keyword.IsInfix)
                    {
                        var head = Syntax.Symbol(list[0]);
                        var lead = head != null?Keyword(head.Id) : null;

                        if ((lead == null) || !IsReserved(lead))
                        {
                            return(keyword.Semantic(environment, new[] { list[0] }.Concat(list.Skip(2)).ToArray()));
                        }
                        throw Error("infix keyword {0} not allowed after reserved keyword {1}", keyword, lead);
                    }
                    throw Error("not an infix keyword at position 2: {0}", keyword);
                }
                if ((list.Length > 0) && ((symbol = Syntax.Symbol(list[0])) != null) && ((keyword = Keyword(symbol.Id)) != null))
                {
                    return(keyword.Semantic(environment, list.Skip(1).ToArray()));
                }
                else
                {
                    int length;
                    list = list.Select(item => Evaluation(environment, item)).ToArray();
                    if (((length = list.Length) > 0) && ((symbol = Syntax.Symbol(list[0])) != null) && (symbol is Callable))
                    {
                        var callable  = (Callable)symbol;
                        var variadic  = callable.Variadic;
                        var arguments = new object[variadic ? length - 1 : length];
                        if (length > 1)
                        {
                            Array.Copy(list, 1, arguments, variadic ? 0 : 1, length - 1);
                        }
                        if (variadic)
                        {
                            return(callable.Invoke(environment, arguments));
                        }
                        else
                        {
                            arguments[0] = environment;
                            return(callable.Invoke(arguments));
                        }
                    }
                    else
                    {
                        return(list);
                    }
                }
            }
            else if (symbol != null)
            {
                return((Delegator != null ? Delegator(environment, symbol) : null) ?? environment.Get(symbol.Id));
            }
            else
            {
                return((Delegator != null ? Delegator(environment, expression) : null) ?? expression);
            }
        }
 public Language(Syntax syntax)
 {
     Syntax    = syntax ?? new Syntax();
     Semantics = new Dictionary <string, object>(GetReflectedSemantics());
     Reserved  = new HashSet <Semantic>(new Semantic[] { Evaluation, Application, Quoting, Construction, Letting, Abstraction, Testing });
 }
 public override string ToString()
 {
     var pair = (object[])Definition; return(string.Concat(Syntax.ToString(pair[0]), " => ", Syntax.ToString(pair[1])));
 }