Bind() public method

Bind a name to this scope, including destructuring assignment.
public Bind ( Analyzer analyzer, Exp target, DataType rvalue, BindingKind kind ) : void
analyzer Analyzer
target Exp
rvalue DataType
kind BindingKind
return void
Exemplo n.º 1
0
        public DataType VisitClass(ClassDef c)
        {
            var             path      = scope.extendPath(analyzer, c.name.Name);
            ClassType       classType = new ClassType(c.name.Name, scope, path);
            List <DataType> baseTypes = new List <DataType>();

            foreach (var @base in c.args)
            {
                DataType baseType = @base.Accept(this);
                switch (baseType)
                {
                case ClassType _:
                    classType.addSuper(baseType);
                    break;

                case UnionType ut:
                    foreach (DataType parent in ut.types)
                    {
                        classType.addSuper(parent);
                    }
                    break;

                default:
                    analyzer.putProblem(@base, @base + " is not a class");
                    break;
                }
                baseTypes.Add(baseType);
            }

            // XXX: Not sure if we should add "bases", "name" and "dict" here. They
            // must be added _somewhere_ but I'm just not sure if it should be HERE.
            addSpecialAttribute(classType.Table, "__bases__", analyzer.TypeFactory.CreateTuple(baseTypes.ToArray()));
            addSpecialAttribute(classType.Table, "__name__", DataType.Str);
            addSpecialAttribute(classType.Table, "__dict__",
                                analyzer.TypeFactory.CreateDict(DataType.Str, DataType.Unknown));
            addSpecialAttribute(classType.Table, "__module__", DataType.Str);
            addSpecialAttribute(classType.Table, "__doc__", DataType.Str);

            // Bind ClassType to name here before resolving the body because the
            // methods need this type as self.
            scope.Bind(analyzer, c.name, classType, BindingKind.CLASS);
            if (c.body != null)
            {
                var sOld = this.scope;
                this.scope = classType.Table;
                c.body.Accept(this);
                this.scope = sOld;
            }
            return(DataType.Cont);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Binds the parameters of a call to the called function.
        /// </summary>
        /// <param name="analyzer"></param>
        /// <param name="call"></param>
        /// <param name="func"></param>
        /// <param name="funcTable"></param>
        /// <param name="parameters"></param>
        /// <param name="rest"></param>
        /// <param name="restKw"></param>
        /// <param name="pTypes"></param>
        /// <param name="dTypes"></param>
        /// <param name="hash"></param>
        /// <param name="kw"></param>
        /// <param name="star"></param>
        /// <returns></returns>
        private static DataType BindParameters(
            Analyzer analyzer,
            Node call,
            FunctionDef func,
            State funcTable,
            List <Parameter> parameters,
            Identifier rest,
            Identifier restKw,
            List <DataType> pTypes,
            List <DataType> dTypes,
            IDictionary <string, DataType> hash,
            DataType kw,
            DataType star)
        {
            TupleType fromType = analyzer.TypeFactory.CreateTuple();
            int       pSize    = parameters == null ? 0 : parameters.Count;
            int       aSize    = pTypes == null ? 0 : pTypes.Count;
            int       dSize    = dTypes == null ? 0 : dTypes.Count;
            int       nPos     = pSize - dSize;

            if (star != null && star is ListType list)
            {
                star = list.toTupleType();
            }

            for (int i = 0, j = 0; i < pSize; i++)
            {
                Parameter param = parameters[i];
                DataType  aType;
                if (i < aSize)
                {
                    aType = pTypes[i];
                }
                else if (i - nPos >= 0 && i - nPos < dSize)
                {
                    aType = dTypes[i - nPos];
                }
                else
                {
                    if (hash != null && hash.ContainsKey(parameters[i].Id.Name))
                    {
                        aType = hash[parameters[i].Id.Name];
                        hash.Remove(parameters[i].Id.Name);
                    }
                    else
                    {
                        if (star != null && star is TupleType &&
                            j < ((TupleType)star).eltTypes.Count)
                        {
                            aType = ((TupleType)star).get(j++);
                        }
                        else
                        {
                            aType = DataType.Unknown;
                            if (call != null)
                            {
                                analyzer.putProblem(parameters[i].Id, //$REVIEW: should be using identifiers
                                                    "unable to bind argument:" + parameters[i]);
                            }
                        }
                    }
                }
                funcTable.Bind(analyzer, param.Id, aType, BindingKind.PARAMETER);
                fromType.add(aType);
            }

            if (restKw != null)
            {
                DataType dt;
                if (hash != null && hash.Count > 0)
                {
                    DataType hashType = UnionType.newUnion(hash.Values);
                    dt = analyzer.TypeFactory.CreateDict(DataType.Str, hashType);
                }
                else
                {
                    dt = DataType.Unknown;
                }
                funcTable.Bind(
                    analyzer,
                    restKw,
                    dt,
                    BindingKind.PARAMETER);
            }

            if (rest != null)
            {
                if (pTypes.Count > pSize)
                {
                    DataType restType = analyzer.TypeFactory.CreateTuple(pTypes.subList(pSize, pTypes.Count).ToArray());
                    funcTable.Bind(analyzer, rest, restType, BindingKind.PARAMETER);
                }
                else
                {
                    funcTable.Bind(
                        analyzer,
                        rest,
                        DataType.Unknown,
                        BindingKind.PARAMETER);
                }
            }
            return(fromType);
        }