/// <summary> /// Gets type mask of the literal within given type context. /// </summary> internal TypeRefMask ResolveTypeMask(TypeRefContext typeCtx) { Debug.Assert(this.ConstantValue.HasValue); var value = this.ConstantValue.Value; if (value == null) { return typeCtx.GetNullTypeMask(); } else { if (value is long || value is int) { return typeCtx.GetLongTypeMask(); } else if (value is string) { return typeCtx.GetStringTypeMask(); } else if (value is bool) { return typeCtx.GetBooleanTypeMask(); } else if (value is double) { return typeCtx.GetDoubleTypeMask(); } else { throw new NotImplementedException(); } } }
/// <summary> /// Gets expected return type mask of given symbol (field, function, method or property). /// </summary> /// <remarks>Returned type mask corresponds to types that can be returned by invoking given symbol.</remarks> public static TypeRefMask GetResultType(this IPhpValue symbol, TypeRefContext ctx) { Contract.ThrowIfNull(symbol); Contract.ThrowIfNull(ctx); TypeSymbol t; if (symbol is FieldSymbol) { t = ((FieldSymbol)symbol).Type; } else if (symbol is MethodSymbol) { var m = (MethodSymbol)symbol; var r = symbol as SourceRoutineSymbol; if (r != null && r.IsStatic) { // In case of a static function, we can return expected return type mask exactly. // Such function cannot be overriden and we know exactly what the return type will be even the CLR type covers more possibilities. return ctx.AddToContext(r.TypeRefContext, r.ResultTypeMask); } t = m.ReturnType; } else if (symbol is PropertySymbol) { t = ((PropertySymbol)symbol).Type; } else if (symbol is ParameterSymbol) { t = ((ParameterSymbol)symbol).Type; } else { throw Roslyn.Utilities.ExceptionUtilities.UnexpectedValue(symbol); } // create the type mask from the CLR type symbol var mask = TypeRefFactory.CreateMask(ctx, t); // [CastToFalse] if (symbol is IPhpRoutineSymbol && ((IPhpRoutineSymbol)symbol).CastToFalse) { mask |= ctx.GetBooleanTypeMask(); // the function may return FALSE } // return mask; }
public static TypeRefMask CreateMask(TypeRefContext ctx, TypeSymbol t) { Contract.ThrowIfNull(t); switch (t.SpecialType) { case SpecialType.System_Void: return 0; case SpecialType.System_Int64: return ctx.GetLongTypeMask(); case SpecialType.System_String: return ctx.GetStringTypeMask(); case SpecialType.System_Double: return ctx.GetDoubleTypeMask(); case SpecialType.System_Boolean: return ctx.GetBooleanTypeMask(); case SpecialType.None: var containing = t.ContainingAssembly; if (containing != null && containing.IsPchpCorLibrary) { if (t.Name == "PhpValue") return TypeRefMask.AnyType; if (t.Name == "PhpAlias") return TypeRefMask.AnyType.WithRefFlag; if (t.Name == "PhpNumber") return ctx.GetNumberTypeMask(); if (t.Name == "PhpString") return ctx.GetWritableStringTypeMask(); if (t.Name == "PhpArray") return ctx.GetArrayTypeMask(); if (t.Name == "IPhpCallable") return ctx.GetCallableTypeMask(); } break; } return CreateMask(ctx, CreateTypeRef(ctx, t)); }