public void EvaluateUsingDefaultValuesForArguments()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", 1, false), new Parameter("b", 2, false) };
            ICommand body = new ReturnCommand(new BinaryOperatorExpression(new NameExpression("a"), new NameExpression("b"), BinaryOperator.Add));

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            Assert.AreEqual(3, func.Apply(new BindingEnvironment(), null, null));
        }
        public void CreateSimpleDefinedFunction()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", null, false), new Parameter("b", null, false) };
            ICommand body = new SetCommand("c", new NameExpression("a"));
            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            Assert.AreEqual(parameters, func.Parameters);
            Assert.AreEqual(body, func.Body);
        }
        public void EvaluateUsingEmptyListArgument()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", null, false), new Parameter("b", null, true) };
            ICommand body = new ReturnCommand(new NameExpression("b"));

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            var result = func.Apply(new BindingEnvironment(), new object[] { 1 }, null);

            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(IList<object>));

            var list = (IList<object>)result;

            Assert.AreEqual(0, list.Count);
        }
        public void RaiseWhenOneParameterExpectedAndNoneIsProvided()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", null, false) };
            CompositeCommand body = new CompositeCommand();

            Machine machine = new Machine();

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            try
            {
                func.Apply(machine.Environment, null, null);
                Assert.Fail("Exception expected");
            }
            catch (Exception ex)
            {
                Assert.IsInstanceOfType(ex, typeof(TypeError));
                Assert.AreEqual("foo() takes exactly 1 positional argument (0 given)", ex.Message);
            }
        }
        public void RaiseWhenMultipleValuesForKeywordArgument()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", 1, false), new Parameter("b", 2, false) };
            ICommand body = new ReturnCommand(new BinaryOperatorExpression(new NameExpression("a"), new NameExpression("b"), BinaryOperator.Add));

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            try
            {
                func.Apply(new BindingEnvironment(), new object[] { 1 }, new Dictionary<string, object> { { "a", 2 } });
                Assert.Fail("Exception expected");
            }
            catch (Exception ex)
            {
                Assert.IsInstanceOfType(ex, typeof(TypeError));
                Assert.AreEqual("foo() got multiple values for keyword argument 'a'", ex.Message);
            }
        }
        public void RaiseWhenFewParametersProvided()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", null, false), new Parameter("b", null, false) };
            CompositeCommand body = new CompositeCommand();

            Machine machine = new Machine();
            StringWriter writer = new StringWriter();
            machine.Output = writer;

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            try
            {
                func.Apply(machine.Environment, new object[] { 1 }, null);
                Assert.Fail("Exception expected");
            }
            catch (Exception ex)
            {
                Assert.IsInstanceOfType(ex, typeof(TypeError));
                Assert.AreEqual("foo() takes exactly 2 positional arguments (1 given)", ex.Message);
            }
        }
        public void ExecuteFunctionWithReturn()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", null, false), new Parameter("b", null, false) };
            CompositeCommand body = new CompositeCommand();
            body.AddCommand(new ReturnCommand(new BinaryOperatorExpression(new NameExpression("a"), new NameExpression("b"), BinaryOperator.Add)));

            Machine machine = new Machine();
            StringWriter writer = new StringWriter();
            machine.Output = writer;

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            var result = func.Apply(machine.Environment, new object[] { 1, 2 }, null);

            Assert.IsNotNull(result);
            Assert.AreEqual(3, result);
        }
        public void ExecuteFunctionWithPrint()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", null, false), new Parameter("b", null, false) };
            CompositeCommand body = new CompositeCommand();
            body.AddCommand(new ExpressionCommand(new CallExpression(new NameExpression("print"), new IExpression[] { new NameExpression("a") })));
            body.AddCommand(new ExpressionCommand(new CallExpression(new NameExpression("print"), new IExpression[] { new NameExpression("b") })));

            Machine machine = new Machine();
            StringWriter writer = new StringWriter();
            machine.Output = writer;

            DefinedFunction func = new DefinedFunction("foo", parameters, body, machine.Environment);

            func.Apply(machine.Environment, new object[] { 1, 2 }, null);
            Assert.AreEqual("1\r\n2\r\n", writer.ToString());
        }
        public void EvaluateUsingTwoNamedArguments()
        {
            IList<Parameter> parameters = new Parameter[] { new Parameter("a", 1, false), new Parameter("b", 2, false) };
            ICommand body = new ReturnCommand(new BinaryOperatorExpression(new NameExpression("a"), new NameExpression("b"), BinaryOperator.Add));

            DefinedFunction func = new DefinedFunction("foo", parameters, body, null);

            var result = func.Apply(new BindingEnvironment(), null, new Dictionary<string, object> { { "a", 2 }, { "b", 3 } });

            Assert.IsNotNull(result);
            Assert.AreEqual(5, result);
        }