public void TestPolymorphicReorder()
        {
            interpreter = reorderInterpreter;
            var factory   = ReorderWrapper.GetFactory(StrictInstruction.factory);
            var addInt    = factory.Binary((int a, int b) => a + b);
            var addFloat  = factory.Binary((float a, float b) => a + b);
            var addString = factory.Binary((string a, string b) => a + b);

            var addPoly
                = new PolymorphicInstruction(new [] { addInt, addFloat, addString })
                {
                tryBestFit = true
                };

            interpreter.AddInstruction("+", addPoly);
            Assert.Equal("[[] 1.1 5]", Run("[[3 1.1 2 +]]"));
            Assert.Equal("[[] 1.1 2]", Run("[[1.1 2 +]]"));
            Assert.Equal(@"[[] 2 1.1 ""hi there""]", Run(@"[[""hi "" 1.1 2 ""there"" +]]"));
            Assert.Equal(@"[[] sym 2 1.1 ""hi there""]", Run(@"[[""hi "" 1.1 2 ""there"" sym +]]"));
        }
        public void TestPolymorphicInstruction()
        {
            interpreter = cleanInterpreter;
            var addInt    = StrictInstruction.factory.Binary((int a, int b) => a + b);
            var addFloat  = StrictInstruction.factory.Binary((float a, float b) => a + b);
            var addString = StrictInstruction.factory.Binary((string a, string b) => a + b);

            var addPoly = new PolymorphicInstruction(new [] { addInt, addFloat, addString });

            interpreter.AddInstruction("+", addPoly);
            Assert.Equal("[[] 3]", Run("[[1 2 +]]"));
            Assert.Equal("[[] 3.5]", Run("[[1f 2.5f +]]"));
            Assert.Equal(@"[[] ""helloworld""]", Run(@"[[""hello"" ""world"" +]]"));
            // Assert.Equal(@"[[] helloworld]", Run(@"[[""hello"" ""world"" +]]"));
            lastRun.Pop();
            Assert.Equal("helloworld", lastRun.Pop());

            Assert.Throws <Exception>(() => Run("[[1 2.5f +]]"));
            Assert.Throws <Exception>(() => Run("[[1 +]]"));
        }
        public void TestPolymorphicInstructionTryBestFit()
        {
            interpreter = cleanInterpreter;
            var addInt    = StrictInstruction.factory.Binary((int a, int b) => a + b);
            var addFloat  = StrictInstruction.factory.Binary((float a, float b) => a + b);
            var addString = StrictInstruction.factory.Binary((string a, string b) => a + b);

            var addPoly = new PolymorphicInstruction(new [] { addInt, addFloat, addString })
            {
                tryBestFit = true
            };

            interpreter.AddInstruction("+", addPoly);
            Assert.Equal("[[] 3]", Run("[[1 2 +]]"));
            Assert.Equal("[[] 3.5]", Run("[[1f 2.5f +]]"));
            Assert.Equal(@"[[] ""helloworld""]", Run(@"[[""hello"" ""world"" +]]"));
            // Assert.Equal(@"[[] helloworld]", Run(@"[[""hello"" ""world"" +]]"));
            lastRun.Pop();
            Assert.Equal("helloworld", lastRun.Pop());

            var e = EvalStream("[[2.5 1 +]]").GetEnumerator();

            Assert.True(e.MoveNext());
            Assert.Equal("[[1 +] 2.5]", e.Current); Assert.True(e.MoveNext());
            Assert.Equal("[[+] 1 2.5]", e.Current); Assert.True(e.MoveNext());
            Assert.Equal("[[+ 2.5] 1]", e.Current); Assert.True(e.MoveNext());
            Assert.Equal("[[2.5] 1]", e.Current); Assert.True(e.MoveNext());
            Assert.Equal("[[] 2.5 1]", e.Current); Assert.False(e.MoveNext());

            Assert.Equal("[[] 2.5 1]", Run("[[2.5f 1 +]]"));

            Assert.Equal("[[] 2.5 1]", Run("[[1 2.5f]]"));
            Assert.Equal("[[] 2.5 1]", Run("[[2.5f 1 +]]"));
            Assert.Equal("[[] 1 2.5]", Run("[[1 2.5f +]]"));
            Assert.Equal("[[] 1]", Run("[[1 +]]"));
        }