public Bind ( Analyzer analyzer, Exp target, DataType rvalue, BindingKind kind ) : void | ||
analyzer | Analyzer | |
target | Exp | |
rvalue | DataType | |
kind | BindingKind | |
return | void |
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); }
/// <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); }