public void EvaluateClass()
        {
            // Open class scope chain
            using (Eval.OpenScope(Module, _classDef, out var outerScope)) {
                var instance = Eval.GetInScope(_classDef.Name, outerScope);
                if (!(instance?.GetPythonType() is PythonClassType classInfo))
                {
                    if (instance != null)
                    {
                        // TODO: warning that variable is already declared of a different type.
                    }
                    return;
                }

                // Evaluate inner classes, if any
                EvaluateInnerClasses(_classDef);
                _class = classInfo;

                var bases = ProcessBases();
                _class.SetBases(bases, Eval.CurrentScope);
                _class.DecideGeneric();
                // Declare __class__ variable in the scope.
                Eval.DeclareVariable("__class__", _class, VariableSource.Declaration);
                ProcessClassBody();
            }
        }
        public async Task Mro()
        {
            using (var s = await CreateServicesAsync(null, null, null)) {
                var interpreter = s.GetService <IPythonInterpreter>();
                var o           = interpreter.GetBuiltinType(BuiltinTypeId.Object);
                var m           = new SentinelModule("test", s);

                var location = new Location(m);
                var O        = new PythonClassType("O", location);
                var A        = new PythonClassType("A", location);
                var B        = new PythonClassType("B", location);
                var C        = new PythonClassType("C", location);
                var D        = new PythonClassType("D", location);
                var E        = new PythonClassType("E", location);
                var F        = new PythonClassType("F", location);

                O.SetBases(new[] { o });
                F.SetBases(new[] { O });
                E.SetBases(new[] { O });
                D.SetBases(new[] { O });
                C.SetBases(new[] { D, F });
                B.SetBases(new[] { D, E });
                A.SetBases(new[] { B, C });

                var mroA = PythonClassType.CalculateMro(A).Select(p => p.Name);
                mroA.Should().Equal("A", "B", "C", "D", "E", "F", "O", "object");

                var mroB = PythonClassType.CalculateMro(B).Select(p => p.Name);
                mroB.Should().Equal("B", "D", "E", "O", "object");

                var mroC = PythonClassType.CalculateMro(C).Select(p => p.Name);
                mroC.Should().Equal("C", "D", "F", "O", "object");
            }
        }
예제 #3
0
 public PythonLazyClassType(ClassModel model, ModuleFactory mf, IGlobalScope gs, IPythonType declaringType)
     : base(model, mf, gs, declaringType)
 {
     _cls = new PythonClassType(model.Name, new Location(mf.Module, model.IndexSpan.ToSpan()));
     _cls.SetDocumentation(model.Documentation);
     SetInnerType(_cls);
 }
예제 #4
0
        public override IMember Create(ModuleFactory mf, IPythonType declaringType, IGlobalScope gs)
        {
            if (_cls != null)
            {
                return(_cls);
            }
            _cls = new PythonClassType(Name, new Location(mf.Module, IndexSpan.ToSpan()));
            var bases = CreateBases(mf, gs);

            _cls.SetBases(bases);
            _cls.SetDocumentation(Documentation);

            if (GenericParameterValues.Length > 0)
            {
                _cls.StoreGenericParameters(
                    _cls,
                    _cls.GenericParameters.Keys.ToArray(),
                    GenericParameterValues.ToDictionary(
                        k => _cls.GenericParameters.Keys.First(x => x == k.Name),
                        v => mf.ConstructType(v.Type)
                        )
                    );
            }

            var all = Classes.Concat <MemberModel>(Properties).Concat(Methods).Concat(Fields);

            foreach (var m in all)
            {
                _cls.AddMember(m.Name, m.Create(mf, _cls, gs), false);
            }
            return(_cls);
        }
        private PythonClassType CreateClass(ClassDefinition cd)
        {
            var cls = new PythonClassType(cd, _eval.GetLocationOfName(cd),
                                          _eval.SuppressBuiltinLookup ? BuiltinTypeId.Unknown : BuiltinTypeId.Type);

            _typeMap[cd] = cls;
            return(cls);
        }
예제 #6
0
        private PythonClassType CreateClass(ClassDefinition node)
        {
            var cls = new PythonClassType(node, _eval.Module, GetLoc(node),
                                          _eval.SuppressBuiltinLookup ? BuiltinTypeId.Unknown : BuiltinTypeId.Type);

            _typeMap[node] = cls;
            return(cls);
        }
예제 #7
0
        /// <summary>
        /// Given generic class type and the passed constructor arguments
        /// creates specific type and instance of the type. Attempts to match
        /// supplied arguments to either __init__ signature or to the
        /// list of generic definitions in Generic[T1, T2, ...].
        /// </summary>
        private IMember CreateClassInstance(PythonClassType cls, IReadOnlyList <IMember> constructorArguments, CallExpression callExpr)
        {
            // Look at the constructor arguments and create argument set
            // based on the __init__ definition.
            var initFunc     = cls.GetMember(@"__init__") as IPythonFunctionType;
            var initOverload = initFunc?.DeclaringType == cls?initFunc.Overloads.FirstOrDefault() : null;

            var argSet = initOverload != null
                    ? new ArgumentSet(initFunc, 0, null, callExpr, this)
                    : new ArgumentSet(constructorArguments, callExpr, this);

            argSet.Evaluate();
            var specificType = cls.CreateSpecificType(argSet);

            return(new PythonInstance(specificType));
        }
        private PythonClassType CreateClass(ClassDefinition cd)
        {
            PythonType declaringType = null;

            if (!(cd.Parent is PythonAst))
            {
                Debug.Assert(_typeMap.ContainsKey(cd.Parent));
                _typeMap.TryGetValue(cd.Parent, out declaringType);
            }
            var cls = new PythonClassType(cd, declaringType, _eval.GetLocationOfName(cd),
                                          _eval.SuppressBuiltinLookup ? BuiltinTypeId.Unknown : BuiltinTypeId.Type);

            _typeMap[cd] = cls;

            declaringType?.AddMember(cls.Name, cls, overwrite: true);
            return(cls);
        }
        public async Task EvaluateClassAsync(CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Open class scope chain
            using (Eval.OpenScope(_classDef, out var outerScope)) {
                var instance = Eval.GetInScope(_classDef.Name, outerScope);
                if (!(instance?.GetPythonType() is PythonClassType classInfo))
                {
                    if (instance != null)
                    {
                        // TODO: warning that variable is already declared of a different type.
                    }
                    // May be odd case like class inside a class.
                    return;
                }

                // Evaluate inner classes, if any
                await EvaluateInnerClassesAsync(_classDef, cancellationToken);

                _class = classInfo;
                // Set bases to the class.
                var bases = new List <IPythonType>();
                foreach (var a in _classDef.Bases.Where(a => string.IsNullOrEmpty(a.Name)))
                {
                    // We cheat slightly and treat base classes as annotations.
                    var b = await Eval.GetTypeFromAnnotationAsync(a.Expression, cancellationToken);

                    if (b != null)
                    {
                        bases.Add(b.GetPythonType());
                    }
                }
                _class.SetBases(Interpreter, bases);

                // Declare __class__ variable in the scope.
                Eval.DeclareVariable("__class__", _class, _classDef);

                await ProcessClassBody(cancellationToken);
            }
        }
        public void EvaluateClass()
        {
            // Open class scope chain
            using (Eval.OpenScope(Module, _classDef, out var outerScope)) {
                var instance = Eval.GetInScope(_classDef.Name, outerScope);
                if (!(instance?.GetPythonType() is PythonClassType classInfo))
                {
                    if (instance != null)
                    {
                        // TODO: warning that variable is already declared of a different type.
                    }
                    return;
                }

                // Evaluate inner classes, if any
                EvaluateInnerClasses(_classDef);

                _class = classInfo;
                // Set bases to the class.
                var bases = new List <IPythonType>();
                foreach (var a in _classDef.Bases.Where(a => string.IsNullOrEmpty(a.Name)))
                {
                    // We cheat slightly and treat base classes as annotations.
                    var b = Eval.GetTypeFromAnnotation(a.Expression);
                    if (b != null)
                    {
                        var t = b.GetPythonType();
                        bases.Add(t);
                        t.AddReference(Eval.GetLocationOfName(a.Expression));
                    }
                }
                _class.SetBases(bases);

                // Declare __class__ variable in the scope.
                Eval.DeclareVariable("__class__", _class, VariableSource.Declaration);

                ProcessClassBody();
            }
        }
        private PythonClassType CreateClass(ClassDefinition cd)
        {
            PythonType declaringType = null;

            if (!(cd.Parent is PythonAst))
            {
                if (!_typeMap.TryGetValue(cd.Parent, out declaringType))
                {
                    // we can get into this situation if parent is defined twice and we preserve
                    // only one of them.
                    // for example, code has function definition with exact same signature
                    // and class is defined under one of that function
                    return(null);
                }
            }
            var cls = new PythonClassType(cd, declaringType, _eval.GetLocationOfName(cd),
                                          _eval.SuppressBuiltinLookup ? BuiltinTypeId.Unknown : BuiltinTypeId.Type);

            _typeMap[cd] = cls;

            declaringType?.AddMember(cls.Name, cls, overwrite: true);
            return(cls);
        }