void CheckMissusedPrimitiveType(IBoundTypeRef tref) { if (tref.IsPrimitiveType) { // error: use of primitive type {0} is misused // primitive type does not make any sense in this context _diagnostics.Add(_routine, tref.PhpSyntax, ErrorCode.ERR_PrimitiveTypeNameMisused, tref); } }
public SourceCustomAttribute(PhpCompilation compilation, SourceTypeSymbol containingType, IBoundTypeRef tref, ImmutableArray <BoundArgument> arguments) { _compilation = compilation; _tref = tref; _arguments = arguments; TypeCtx = new FlowAnalysis.TypeRefContext(compilation, containingType); }
private TypeRefMask GetPrimitiveTypeRefMask(IBoundTypeRef /*!*/ typeref) { Debug.Assert(typeref.IsPrimitiveType); // primitive type cannot include subclasses var index = AddToContext(typeref); return(TypeRefMask.CreateFromTypeIndex(index)); }
/// <summary> /// Does not lookup existing types whether there is typeref already. /// </summary> private TypeRefMask GetPrimitiveTypeRefMaskNoCheck(IBoundTypeRef /*!*/ typeref) { Debug.Assert(typeref.IsPrimitiveType); if (this.Types.Count < TypeRefMask.IndicesCount) { var index = AddToContextNoCheck(typeref); return(TypeRefMask.CreateFromTypeIndex(index)); } else { return(TypeRefMask.AnyType); } }
/// <summary>Template: new LateStaticTypeParam(PhpTypeInfo)</summary> public TypeSymbol EmitLateStaticTypeParam(IBoundTypeRef tref) { if (tref != null && (tref.IsSelf() || tref.IsParent()) && _cg.Routine != null && _cg.Routine.IsStatic && _cg.Routine.HasLateStaticBoundParam()) { // pass current <static> to the callsite: return(EmitWrapParam(_cg.CoreTypes.Dynamic_LateStaticTypeParam, _cg.EmitLoadStaticPhpTypeInfo())); } // not needed return(null); }
private int AddToContextNoCheck(IBoundTypeRef /*!*/ typeRef) { Contract.ThrowIfNull(typeRef); Debug.Assert(_typeRefs.IndexOf(typeRef) == -1); int index = _typeRefs.Count; this.UpdateMasks(typeRef, index); _typeRefs.Add(typeRef); // return(index); }
/// <summary> /// Updates internal masks for newly added type. /// </summary> /// <param name="typeRef">Type.</param> /// <param name="index">Type index.</param> private void UpdateMasks(IBoundTypeRef /*!*/ typeRef, int index) { Debug.Assert(index >= 0 && index < TypeRefMask.IndicesCount); ulong mask = (ulong)1 << index; if (typeRef.IsObject) { _isObjectMask |= mask; } if (typeRef.IsArray) { _isArrayMask |= mask; } if (typeRef.IsLambda) { _isLambdaMask |= mask; } if (typeRef is BoundPrimitiveTypeRef pt) { switch (pt.TypeCode) { case PhpTypeCode.Boolean: _isBoolMask = mask; break; case PhpTypeCode.Long: _isLongMask = mask; break; case PhpTypeCode.Double: _isDoubleMask = mask; break; case PhpTypeCode.String: _isStringMask = mask; break; case PhpTypeCode.Null: _isNullMask = mask; break; case PhpTypeCode.WritableString: _isWritableStringMask = mask; break; } } }
/// <summary> /// Ensures given type is in the context. /// </summary> /// <param name="typeRef">Type reference to be in the context.</param> /// <returns>Index of the type within the context. Can return <c>-1</c> if there is too many types in the context already.</returns> public int AddToContext(IBoundTypeRef /*!*/ typeRef) { Contract.ThrowIfNull(typeRef); var types = _typeRefs; var index = this.GetTypeIndex(typeRef); if (index < 0 && this.Types.Count < TypeRefMask.IndicesCount) { index = this.AddToContextNoCheck(typeRef); } // return(index); }
/// <summary> /// Helper method that builds <see cref="TypeRefMask"/> for given type in this context. /// </summary> public TypeRefMask GetTypeMask(IBoundTypeRef /*!*/ typeref, bool includesSubclasses) { var index = AddToContext(typeref); var mask = TypeRefMask.CreateFromTypeIndex(index); if (includesSubclasses && typeref.IsObject) { mask.SetIncludesSubclasses(); } if (typeref.IsNullable) { mask |= GetNullTypeMask(); } return(mask); }
/// <summary> /// Returns whether the given type can be used as an array key. /// </summary> public static bool IsValidKeyType(IBoundTypeRef type) { if (type is BoundPrimitiveTypeRef pt) { switch (pt.TypeCode) { case PhpTypeCode.Boolean: case PhpTypeCode.Long: case PhpTypeCode.Double: case PhpTypeCode.String: case PhpTypeCode.WritableString: case PhpTypeCode.Null: return(true); } } return(false); }
public static void EmitClassName(this IBoundTypeRef tref, CodeGenerator cg) { if (tref is BoundIndirectTypeRef it) { it.EmitClassName(cg); } else if (tref is BoundClassTypeRef ct) { cg.Builder.EmitStringConstant(ct.ClassName.ToString()); } else { // Template: {LOAD PhpTypeInfo}.Name tref.EmitLoadTypeInfo(cg, true); cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.GetName_PhpTypeInfo.Getter) .Expect(SpecialType.System_String); } }
public override bool Equals(IBoundTypeRef other) { if (ReferenceEquals(this, other)) { return(true); } if (other is BoundGenericClassTypeRef gt && gt._targetType.Equals(_targetType) && gt._typeArguments.Length == _typeArguments.Length) { for (int i = 0; i < _typeArguments.Length; i++) { if (!other.TypeArguments[i].Equals(this.TypeArguments[i])) { return(false); } } return(true); } return(false); }
/// <summary> /// Gets <see cref="TypeSymbol"/> suitable to be used for the runtime operations. /// Does not return <c>null</c> nor <see cref="ErrorTypeSymbol"/>. /// </summary> public static TypeSymbol ResolveRuntimeType(this IBoundTypeRef tref, PhpCompilation compilation) { var boundType = (BoundTypeRef)tref; var t = boundType.ResolvedType ?? (TypeSymbol)boundType.ResolveTypeSymbol(compilation); if (t.IsErrorTypeOrNull()) // error type => class could not be found { if (t is AmbiguousErrorTypeSymbol ambiguous) { // ambiguity -> try to find a common base var common = compilation.FindCommonBase(ambiguous._candidates); if (common.IsValidType()) { return(common); } } t = compilation.CoreTypes.Object.Symbol; } return(t); }
/// <summary> /// Gets string representation of types contained in given type mask. /// </summary> public string ToString(TypeRefMask mask) { if (!mask.IsVoid) { if (mask.IsAnyType) { return(TypeRefMask.MixedTypeName); } // var types = new List <string>(1); // handle arrays separately var arrmask = mask & _isArrayMask; if (arrmask != 0) { mask &= ~_isArrayMask; IBoundTypeRef elementtype = null; var elementmask = GetElementType(arrmask); if (elementmask.IsSingleType) { elementtype = GetTypes(elementmask).FirstOrDefault(); } if (elementtype != null) { types.Add(elementtype.ToString() + "[]"); } else { types.Add(QualifiedName.Array.ToString()); } } //// int|double => number //var isNumber = (_isIntMask != 0 && _isDoubleMask != 0 && (mask & IsNumberMask) == IsNumberMask); //if (isNumber) // mask &= ~IsNumberMask; //if (IsNull(mask)) //{ // mask &= ~_isNullMask; // types.Add(QualifiedName.Null.ToString()); //} // types.AddRange(GetTypes(mask).Select(t => t.ToString())); //if (isNumber) // types.Add("number"); // if (types.Count != 0) { types.Sort(); return(string.Join(PHPDocBlock.TypeVarDescTag.TypeNamesSeparator.ToString(), types.Distinct())); } } return(TypeRefMask.VoidTypeName); }
public BoundGenericClassTypeRef(IBoundTypeRef targetType, ImmutableArray <BoundTypeRef> typeArguments) { _targetType = targetType ?? throw ExceptionUtilities.ArgumentNull(nameof(targetType)); _typeArguments = typeArguments; }
public override bool Equals(IBoundTypeRef other) => base.Equals(other) || (other is BoundClassTypeRef ct && ct.ClassName == this.ClassName && ct.TypeArguments.IsDefaultOrEmpty);
public override bool Equals(IBoundTypeRef other) => base.Equals(other) || (other is BoundLambdaTypeRef lt && lt._returnType == this._returnType);
public override bool Equals(IBoundTypeRef other) => base.Equals(other) || (other is BoundArrayTypeRef at && at.ElementType == this.ElementType);
public override bool Equals(IBoundTypeRef other) => base.Equals(other) || (other is BoundPrimitiveTypeRef pt && pt._type == this._type);
private CatchBlock(IBoundTypeRef typeRef, BoundVariableRef variable, List <BoundStatement> statements) : base(statements) { _typeRef = typeRef; _variable = variable; }
public CatchBlock(IBoundTypeRef typeRef, BoundVariableRef variable) : this(typeRef, variable, new List <BoundStatement>()) { }
/// <summary> /// Determines if given <see cref="IBoundTypeRef"/> represents a number (integral or real). /// </summary> public static bool IsNumber(this IBoundTypeRef tref) => tref is BoundPrimitiveTypeRef pt && pt.IsNumber;
/// <summary>Template: new TargetTypeParam(PhpTypeInfo)</summary> public TypeSymbol EmitTargetTypeParam(IBoundTypeRef tref) => tref != null?EmitWrapParam(_cg.CoreTypes.Dynamic_TargetTypeParam, tref.EmitLoadTypeInfo(_cg, true)) : null;
public override bool Equals(IBoundTypeRef other) => base.Equals(other) || (other is BoundIndirectTypeRef it && it._typeExpression == _typeExpression);
/// <summary> /// Gets value indicating the <paramref name="tref"/> represents <c>self</c> keyword. /// </summary> public static bool IsSelf(this IBoundTypeRef tref) => tref is BoundReservedTypeRef reserved && reserved.ReservedType == Devsense.PHP.Syntax.Ast.ReservedTypeRef.ReservedType.self;
public static ITypeSymbol EmitLoadTypeInfo(this IBoundTypeRef tref, CodeGenerator cg, bool throwOnError = false) => ((BoundTypeRef)tref).EmitLoadTypeInfo(cg, throwOnError);
public override bool Equals(IBoundTypeRef other) => base.Equals(other) || (other is BoundTypeRefFromPlace pt && pt._place == _place);
void CannotInstantiate(IPhpOperation op, string kind, IBoundTypeRef t) { _diagnostics.Add(_routine, op.PhpSyntax, ErrorCode.ERR_CannotInstantiateType, kind, t.Type); }
public virtual bool Equals(IBoundTypeRef other) => ReferenceEquals(this, other);
/// <summary> /// Gets index of the given type within the context. Returns <c>-1</c> if such type is not present. /// </summary> int GetTypeIndex(IBoundTypeRef /*!*/ typeref) { return(_typeRefs.IndexOf(typeref)); }