Ejemplo n.º 1
0
        public void VargsOnly()
        {
            var co = new CodeObject(new byte[0]);

            co.ArgCount = 0;
            co.Defaults = new List <object>();
            co.VarNames.Add("args");
            co.Flags |= CodeObject.CO_FLAGS_VARGS;

            var inputs = new object[][]
            {
                new object[] { 1 },
                new object[] { },
            };
            var keywordsIn = new Dictionary <string, object>[]
            {
                null,
                null,
            };
            var outputs = new object[][]
            {
                new object[] { PyTuple.Create(new object[] { 1 }) },
                new object[] { PyTuple.Create(new object[0]) }
            };

            InOutTest(co, inputs, keywordsIn, outputs);
        }
Ejemplo n.º 2
0
        public void VargsKeywordDefaults()
        {
            var co = new CodeObject(new byte[0]);

            co.ArgCount = 0;
            co.Defaults = new List <object>();
            co.VarNames.Add("args");
            co.VarNames.Add("a");
            co.VarNames.Add("b");
            co.Defaults   = new List <object>();
            co.KWDefaults = new List <object>();
            co.KWDefaults.Add(3);
            co.KWDefaults.Add(4);
            co.KWOnlyArgCount = 2;
            co.Flags         |= CodeObject.CO_FLAGS_VARGS;

            var inputs = new object[][]
            {
                new object[] { 1, 2 },
                new object[] { 1, 2 },
                new object[] { 1, 2 },
                new object[] { 1, 2 },
                new object[] { },
                new object[] { },
            };
            var keywordsIn = new Dictionary <string, object>[]
            {
                new Dictionary <string, object> {
                },
                new Dictionary <string, object> {
                    { "a", 200 }, { "b", 100 }
                },
                new Dictionary <string, object> {
                    { "a", 200 },
                },
                new Dictionary <string, object> {
                    { "b", 100 },
                },
                new Dictionary <string, object> {
                    { "a", 200 },
                },
                new Dictionary <string, object> {
                },
            };
            var outputs = new object[][]
            {
                new object[] { PyTuple.Create(new object[] { 1, 2 }), 3, 4 },
                new object[] { PyTuple.Create(new object[] { 1, 2 }), 200, 100 },
                new object[] { PyTuple.Create(new object[] { 1, 2 }), 200, 4 },
                new object[] { PyTuple.Create(new object[] { 1, 2 }), 3, 100 },
                new object[] { PyTuple.Create(new object[0]), 200, 4 },
                new object[] { PyTuple.Create(new object[0]), 3, 4 },
            };

            InOutTest(co, inputs, keywordsIn, outputs);
        }
Ejemplo n.º 3
0
        public void ArgsDefaultsVargs()
        {
            var co = new CodeObject(new byte[0]);

            co.ArgCount = 4;
            co.Defaults = new List <object>();
            co.VarNames.Add("a");
            co.VarNames.Add("b");
            co.VarNames.Add("c");
            co.VarNames.Add("d");
            co.VarNames.Add("e");
            co.Defaults = new List <object>();
            co.Defaults.Add(-1);
            co.Defaults.Add(-2);
            co.Flags |= CodeObject.CO_FLAGS_VARGS;

            // The 5th case is commented out because it's actually illegal Python. I stubbed my toe on it when I created the arg param
            // matcher state machine. It choked there and I verified in Python that it wouldn't have worked.
            var inputs = new object[][]
            {
                new object[] { 1, 2, 3, 4, 5 },
                new object[] { 6, 7, 8, 9 },
                new object[] { 10, 11, 12 },
                new object[] { 13, 14 },
                //new object[] { },
                new object[] { },
            };
            var keywordsIn = new Dictionary <string, object>[]
            {
                null,
                null,
                null,
                null,
                //new Dictionary<string, object> { { "a", 15 }, { "b", 16 }, { "c", 17 }, { "d", 18 }, { "e", PyTuple.Create(new object[] { 19 }) } },
                new Dictionary <string, object> {
                    { "a", 15 }, { "b", 16 }, { "c", 17 }, { "d", 18 }
                },
            };
            var outputs = new object[][]
            {
                new object[] { 1, 2, 3, 4, PyTuple.Create(new object[] { 5 }) },
                new object[] { 6, 7, 8, 9, PyTuple.Create(new object[0]) },
                new object[] { 10, 11, 12, -2, PyTuple.Create(new object[0]) },
                new object[] { 13, 14, -1, -2, PyTuple.Create(new object[0]) },
                //new object[] { 15, 16, 17, 18, PyTuple.Create(new object[] { 19 }) },
                new object[] { 15, 16, 17, 18, PyTuple.Create(new object[0]) },
            };

            InOutTest(co, inputs, keywordsIn, outputs);
        }
Ejemplo n.º 4
0
        public async Task LenFunction()
        {
            var dictin = PyDict.Create();

            dictin.InternalDict[PyString.Create("1")] = PyInteger.Create(1);
            dictin.InternalDict[PyString.Create("2")] = PyInteger.Create(2);

            await runBasicTest(
                "listout = len(listin)\n" +
                "dictout = len(dictin)\n" +
                "tupleout = len(tuplein)\n" +
                "strout = len(strin)\n" +
                "rangeout = len(rangein)\n" +
                "arrayout = len(arrayin)\n" +
                "enumerableout = len(enumerablein)\n" +
                "dotnetstrout = len(dotnetstrin)\n",     // I think this should be IEnumerable but I'm not taking chances
                new Dictionary <string, object>()
            {
                { "listin", PyList.Create(new List <object>()
                    {
                        PyInteger.Create(1)
                    }) },
                { "dictin", dictin },
                { "tuplein", PyTuple.Create(new object[] { 1, 2, 3 }) },
                { "strin", PyString.Create("1234") },
                { "rangein", PyRange.Create(5, 0, 1) },
                { "arrayin", new int[] { 1, 2, 3, 4, 5, 6 } },
                { "enumerablein", new List <int>()
                  {
                      1, 2, 3, 4, 5, 6, 7
                  } },
                { "dotnetstrin", "12345678" },
            }, new VariableMultimap(new TupleList <string, object>
            {
                { "listout", PyInteger.Create(1) },
                { "dictout", PyInteger.Create(2) },
                { "tupleout", PyInteger.Create(3) },
                { "strout", PyInteger.Create(4) },
                { "rangeout", PyInteger.Create(5) },
                { "arrayout", PyInteger.Create(6) },
                { "enumerableout", PyInteger.Create(7) },
                { "dotnetstrout", PyInteger.Create(8) },
            }), 1);
        }
Ejemplo n.º 5
0
        // TODO [KEYWORD-POSITIONAL-ONLY] Implement positional-only (/) and keyword-only (*) arguments
        // TODO [ARGPARAMMATCHER ERRORS] Generate errors when input arguments don't match requirements of code object.
        // TODO [**kwargs] Support kwargs
        public static object[] Resolve(CodeObject co, object[] inArgs, Dictionary <string, object> keywords = null)
        {
            // This state machine model is definitely more verbose but it's much easier to maintain because:
            // 1. We will loiter in only one section at a time so we can mentally compartmentalize what's happening.
            // 2. We can be very explicit about what happens next.
            var state     = ArgParamState.Initial;
            int inArg_i   = 0;
            int outArg_i  = 0;
            int default_i = 0;

            object[] outArgs       = new object[co.ArgCount + co.KWOnlyArgCount + (co.HasVargs ? 1 : 0)];
            bool     hasDefaults   = co.Defaults.Count > 0;
            bool     hasKwOnlyArgs = co.KWOnlyArgCount > 0;
            bool     hasKeywords   = keywords is null ? false : true;

            // Determine our true first state. Initial is just symbolic.
            if (co.ArgCount > 0)
            {
                state = ArgParamState.Positional;
                if (inArgs.Length == 0)
                {
                    if (hasDefaults || hasKeywords)
                    {
                        state = ArgParamState.KeywordOverride;
                    }
                    else if (co.HasVargs)
                    {
                        state = ArgParamState.Variable;
                    }
                    else if (hasKwOnlyArgs)
                    {
                        state = ArgParamState.KeywordOnly;
                    }
                    else
                    {
                        state = ArgParamState.Finished;
                    }
                }
            }
            else
            {
                if (co.HasVargs)
                {
                    state = ArgParamState.Variable;
                }
                else if (hasKwOnlyArgs)
                {
                    state = ArgParamState.KeywordOnly;
                }
                else
                {
                    state = ArgParamState.Finished;
                }
            }

            if (state == ArgParamState.Initial)
            {
                throw new InvalidOperationException("Arg param state was still in initial state after checking entire environment.");
            }

            while (state != ArgParamState.Finished)
            {
                switch (state)
                {
                case ArgParamState.Positional:
                    while (inArg_i < inArgs.Length && inArg_i < co.ArgCount)
                    {
                        outArgs[outArg_i] = inArgs[inArg_i];
                        outArg_i         += 1;
                        inArg_i          += 1;
                    }

                    if (inArg_i < co.ArgCount)
                    {
                        if (hasKeywords || hasDefaults)
                        {
                            state = ArgParamState.KeywordOverride;
                        }
                        else if (co.HasVargs)
                        {
                            state = ArgParamState.Variable;
                        }
                        else
                        {
                            // TODO: [PARAM MATCHER ERRORS] Cast to actual TypeError
                            throw new Exception("TypeError: " + co.Name + " takes " + co.ArgCount + " position arguments but " + inArgs.Length + " were given");
                        }
                    }
                    else if (co.HasVargs)
                    {
                        state = ArgParamState.Variable;
                    }
                    else if (hasKwOnlyArgs)
                    {
                        state = ArgParamState.KeywordOnly;
                    }
                    else
                    {
                        state = ArgParamState.Finished;
                    }
                    break;

                case ArgParamState.KeywordOverride:
                {
                    List <string> missingOverrides = null;
                    while (inArg_i < co.ArgCount - co.Defaults.Count)
                    {
                        if (hasKeywords && keywords.ContainsKey(co.VarNames[outArg_i]))
                        {
                            outArgs[outArg_i] = keywords[co.VarNames[outArg_i]];
                        }
                        else
                        {
                            if (missingOverrides == null)
                            {
                                missingOverrides = new List <string>();
                            }
                            missingOverrides.Add(co.VarNames[outArg_i]);
                        }
                        ++inArg_i;
                        ++outArg_i;
                    }

                    if (missingOverrides != null && missingOverrides.Count > 0)
                    {
                        // TODO: [PARAM MATCHER ERRORS] Cast to actual TypeError
                        var errorBuilder = new StringBuilder("TypeError: " + co.Name + " missing " + co.ArgCount + " positional argument");
                        if (missingOverrides.Count == 1)
                        {
                            errorBuilder.Append(": ");
                            errorBuilder.Append(missingOverrides[0]);
                        }
                        else
                        {
                            errorBuilder.Append("s: ");
                            for (int i = 0; i < missingOverrides.Count - 2; ++i)
                            {
                                errorBuilder.Append(missingOverrides[i]);
                                errorBuilder.Append(", ");
                            }
                            errorBuilder.Append(missingOverrides[missingOverrides.Count - 2]);
                            errorBuilder.Append(" and ");
                            errorBuilder.Append(missingOverrides[missingOverrides.Count - 1]);
                        }

                        throw new Exception(errorBuilder.ToString());
                    }
                    else if (co.Defaults.Count > 0)
                    {
                        state = ArgParamState.KeywordOrDefault;
                    }
                    else if (co.HasVargs)
                    {
                        state = ArgParamState.Variable;
                    }
                    else if (co.HasKwargs)
                    {
                        state = ArgParamState.KeywordOnly;
                    }
                    else
                    {
                        state = ArgParamState.Finished;
                    }
                }
                break;

                case ArgParamState.KeywordOrDefault:
                    // We might not start at the first default; some positionals might have had a keyword override.
                    default_i = outArg_i - (co.ArgCount - co.Defaults.Count);
                    while (default_i < co.Defaults.Count || outArg_i < co.ArgCount)
                    {
                        if (hasKeywords && keywords.ContainsKey(co.VarNames[outArg_i]))
                        {
                            outArgs[outArg_i] = keywords[co.VarNames[outArg_i]];
                        }
                        else if (default_i < co.Defaults.Count)
                        {
                            outArgs[outArg_i] = co.Defaults[default_i];
                        }
                        else
                        {
                            // TODO: [PARAM MATCHER ERRORS] Cast to actual TypeError
                            throw new Exception("TypeError: " + co.Name + " takes " + co.ArgCount + " position arguments but " + inArgs.Length + " were given");
                        }
                        default_i += 1;
                        outArg_i  += 1;
                    }

                    if (default_i >= co.Defaults.Count)
                    {
                        if (co.HasVargs)
                        {
                            state = ArgParamState.Variable;
                        }
                        else if (hasKwOnlyArgs)
                        {
                            state = ArgParamState.KeywordOnly;
                        }
                        else
                        {
                            state = ArgParamState.Finished;
                        }
                    }
                    break;

                case ArgParamState.Variable:
                {
                    var vargLength = inArgs.Length - inArg_i;
                    vargLength = vargLength < 0 ? 0 : vargLength;
                    object[] vargs  = new object[vargLength];
                    int      varg_i = 0;
                    // Variable arguments (*args)
                    while (inArg_i < inArgs.Length)
                    {
                        vargs[varg_i] = inArgs[inArg_i];
                        ++inArg_i;
                        ++varg_i;
                    }
                    outArgs[outArg_i] = PyTuple.Create(vargs);
                    outArg_i         += 1;

                    if (hasKwOnlyArgs)
                    {
                        state = ArgParamState.KeywordOnly;
                    }
                    else
                    {
                        state = ArgParamState.Finished;
                    }
                }
                break;

                case ArgParamState.KeywordOnly:
                {
                    int kwonly_i = 0;
                    while (kwonly_i < co.KWDefaults.Count)
                    {
                        if (hasKeywords && keywords.ContainsKey(co.VarNames[outArg_i]))
                        {
                            outArgs[outArg_i] = keywords[co.VarNames[outArg_i]];
                        }
                        else
                        {
                            outArgs[outArg_i] = co.KWDefaults[kwonly_i];
                        }

                        ++kwonly_i;
                        ++outArg_i;
                    }
                }
                    state = ArgParamState.Finished;
                    break;
                }
            }

            return(outArgs);
        }