/// <summary>
        /// Gets additional flags of the caller routine.
        /// </summary>
        public static RoutineFlags InvocationFlags(this IPhpRoutineSymbol routine)
        {
            RoutineFlags f = RoutineFlags.None;

            var ps = routine.Parameters;

            foreach (var p in ps)
            {
                if (p.IsImplicitlyDeclared)
                {
                    if (SpecialParameterSymbol.IsLocalsParameter(p))
                    {
                        f |= RoutineFlags.UsesLocals;
                    }
                    else if (SpecialParameterSymbol.IsCallerArgsParameter(p))
                    {
                        f |= RoutineFlags.UsesArgs;
                    }
                    else if (SpecialParameterSymbol.IsCallerStaticClassParameter(p))
                    {
                        f |= RoutineFlags.UsesLateStatic;
                    }
                }
                else
                {
                    break;
                }
            }

            return(f);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets additional flags of the caller routine.
        /// </summary>
        public static RoutineFlags InvocationFlags(this IPhpRoutineSymbol routine)
        {
            RoutineFlags f = RoutineFlags.None;

            var ps = routine.Parameters;

            foreach (var p in ps)
            {
                if (p.IsImplicitlyDeclared)
                {
                    if (SpecialParameterSymbol.IsQueryValueParameter(p, out var ctor, out var container))
                    {
                        switch (container)
                        {
                        case SpecialParameterSymbol.QueryValueTypes.CallerArgs:
                            f |= RoutineFlags.UsesArgs;
                            break;

                        case SpecialParameterSymbol.QueryValueTypes.LocalVariables:
                            f |= RoutineFlags.UsesLocals;
                            break;
                        }
                    }
                    else if (SpecialParameterSymbol.IsCallerStaticClassParameter(p))
                    {
                        f |= RoutineFlags.UsesLateStatic;
                    }
                }
        /// <summary>
        /// Gets mask with 1-bits corresponding to an argument that must be passed by reference.
        /// </summary>
        internal static PhpSignatureMask GetByRefArguments(this IPhpRoutineSymbol routine)
        {
            Contract.ThrowIfNull(routine);

            var mask = new PhpSignatureMask();
            var ps   = routine.Parameters;

            int index = 0;

            foreach (ParameterSymbol p in ps)
            {
                if (index == 0 && p.IsImplicitlyDeclared && !p.IsParams)
                {
                    continue;
                }

                if (p.IsParams)
                {
                    if (((ArrayTypeSymbol)p.Type).ElementType.Is_PhpAlias())    // PHP: ... &$p
                    {
                        mask.SetFrom(index++);
                    }
                }
                else
                {
                    mask[index++] =
                        p.RefKind != RefKind.None ||  // C#: ref|out p
                        p.Type.Is_PhpAlias();         // PHP: &$p
                }
            }

            return(mask);
        }
        /// <summary>
        /// Gets additional flags of the caller routine.
        /// </summary>
        public static RoutineFlags InvocationFlags(this IPhpRoutineSymbol routine)
        {
            var f = RoutineFlags.None;

            var ps = /*routine is SourceRoutineSymbol sr ? sr.ImplicitParameters :*/ routine.Parameters;

            foreach (var p in ps)
            {
                if (p.IsImplicitlyDeclared)
                {
                    switch (((ParameterSymbol)p).ImportValueAttributeData.Value)
                    {
                    case ImportValueAttributeData.ValueSpec.CallerArgs:
                        f |= RoutineFlags.UsesArgs;
                        break;

                    case ImportValueAttributeData.ValueSpec.Locals:
                        f |= RoutineFlags.UsesLocals;
                        break;

                    case ImportValueAttributeData.ValueSpec.CallerStaticClass:
                        f |= RoutineFlags.UsesLateStatic;
                        break;
                    }
                }
                else
                {
                    // implicit parameters are at begining only
                    break;
                }
            }

            return(f);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Determines if given global function symbol is unconditionally declared (always declared).
        /// </summary>
        static bool IsUnconditionalDeclaration(IPhpRoutineSymbol symbol)
        {
            // method declaration in a referenced assembly,
            // not within a compiled source script:
            if (symbol is PEMethodSymbol method)
            {
                var container = method.ContainingType;
                return(container != null && !container.IsPhpSourceFile());   // only functions declared in libraries, not in PHP source file
            }

            // Ambiguity,
            // only if all possible symbols are unconditionally declared.
            if (symbol is AmbiguousMethodSymbol ambiguous)
            {
                foreach (var a in ambiguous.Ambiguities)
                {
                    if (!IsUnconditionalDeclaration(a))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            //
            return(false);
        }
        /// <summary>
        /// Resolves list of input arguments.
        /// Implicit parameters passed by compiler are ignored.
        /// </summary>
        /// <param name="routine">Routine.</param>
        /// <param name="ctx">Type context to transfer type masks into.</param>
        /// <returns>List of input PHP arguments.</returns>
        public static IList <PhpParam> GetExpectedArguments(this IPhpRoutineSymbol routine, TypeRefContext ctx)
        {
            Contract.ThrowIfNull(routine);
            Contract.ThrowIfNull(ctx);

            List <PhpParam> result = null;

            int index = 0;

            var ps = routine.Parameters;

            foreach (ParameterSymbol p in ps)
            {
                if (result == null && p.IsImplicitlyDeclared && !p.IsParams)
                {
                    continue;
                }

                //
                var phpparam = p.IsParams
                    ? new PhpParam(p, index++, TypeRefMask.AnyType.WithIsRef(((ArrayTypeSymbol)p.Type).ElementType.Is_PhpAlias()))
                    : new PhpParam(p, index++, TypeRefFactory.CreateMask(ctx, p.Type, notNull: p.HasNotNull));

                result ??= new List <PhpParam>(ps.Length);
                result.Add(phpparam);
            }

            //
            return(result ?? (IList <PhpParam>)Array.Empty <PhpParam>());
        }
Exemplo n.º 7
0
        public bool EnqueueRoutine(IPhpRoutineSymbol routine, T caller)
        {
            Contract.ThrowIfNull(routine);

            if (routine.ControlFlowGraph == null)
            {
                var routine2 = routine is SynthesizedMethodSymbol sr
                    ? sr.ForwardedCall
                    : routine.OriginalDefinition as IPhpRoutineSymbol;

                if (routine2 != null && !ReferenceEquals(routine, routine2))
                {
                    return(EnqueueRoutine(routine2, caller));
                }

                // library (sourceless) function
                return(false);
            }

            // ensure caller is subscribed to routine's ExitBlock
            ((ExitBlock)routine.ControlFlowGraph.Exit).Subscribe(caller);

            // TODO: check if routine has to be reanalyzed => enqueue routine's StartBlock

            //
            return(false);
        }
Exemplo n.º 8
0
        public bool EnqueueRoutine(IPhpRoutineSymbol routine, T caller, BoundRoutineCall callExpression)
        {
            Contract.ThrowIfNull(routine);

            if (routine.ControlFlowGraph == null)
            {
                var routine2 = routine is SynthesizedMethodSymbol sr
                    ? sr.ForwardedCall
                    : routine.OriginalDefinition as IPhpRoutineSymbol;

                if (routine2 != null && !ReferenceEquals(routine, routine2))
                {
                    return(EnqueueRoutine(routine2, caller, callExpression));
                }

                // library (sourceless) function
                return(false);
            }

            var sourceRoutine = (SourceRoutineSymbol)routine;

            _callGraph.AddEdge(caller.FlowState.Routine, sourceRoutine, new CallSite(caller, callExpression));

            // ensure caller is subscribed to routine's ExitBlock
            ((ExitBlock)routine.ControlFlowGraph.Exit).Subscribe(caller);

            // TODO: check if routine has to be reanalyzed => enqueue routine's StartBlock

            // Return whether the routine exit block will certainly be analysed in the future
            return(!sourceRoutine.IsReturnAnalysed);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Resolves list of input arguments.
        /// Implicit parameters passed by compiler are ignored.
        /// </summary>
        /// <param name="routine">Routine.</param>
        /// <param name="ctx">TYpe context to transmer type masks into.</param>
        /// <returns>List of input PHP arguments.</returns>
        public static PhpParam[] GetExpectedArguments(this IPhpRoutineSymbol routine, TypeRefContext ctx)
        {
            Contract.ThrowIfNull(routine);

            var ps     = routine.Parameters;
            var table  = (routine as SourceRoutineSymbol)?.LocalsTable;
            var result = new List <PhpParam>(ps.Length);

            foreach (ParameterSymbol p in ps)
            {
                if (result.Count == 0 && p.IsImplicitlyDeclared)
                {
                    continue;
                }

                // default value (bound expression)
                ConstantValue cvalue;
                var           psrc        = p as SourceParameterSymbol;
                var           defaultexpr = psrc != null
                    ? psrc.Initializer
                    : ((cvalue = p.ExplicitDefaultConstantValue) != null ? new BoundLiteral(cvalue.Value) : null);

                //
                var phpparam = new PhpParam(
                    TypeRefFactory.CreateMask(ctx, p.Type),
                    p.RefKind != RefKind.None,
                    p.IsParams,
                    defaultexpr);

                result.Add(phpparam);
            }

            //
            return(result.ToArray());
        }
Exemplo n.º 10
0
        public static SymbolStat SearchParameters(IPhpRoutineSymbol routine, int position)
        {
            var parameter = routine.Parameters.FirstOrDefault(p => p.GetSpan().Contains(position));

            if (parameter != null)
            {
                TypeRefContext typeCtx = routine.ControlFlowGraph?.FlowContext?.TypeRefContext;
                return(new SymbolStat(typeCtx, parameter.GetSpan(), null, parameter));
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 11
0
        public static IEnumerable <SymbolStat> Select(IPhpRoutineSymbol routine)
        {
            TypeRefContext typeCtx = routine.ControlFlowGraph?.FlowContext?.TypeRefContext;

            foreach (var p in routine.Parameters)
            {
                if (p.IsImplicitlyDeclared || p.Locations.Length == 0)
                {
                    continue;                                                       // ignore compiler generated parameters
                }
                var textSpan = p.Locations[0].SourceSpan;
                yield return(new SymbolStat(typeCtx, textSpan.ToSpan(), null, p));
            }

            yield break;
        }
Exemplo n.º 12
0
        /// <summary>
        /// Gets additional flags of the caller routine.
        /// </summary>
        /// <param name="routine">The routine.</param>
        /// <param name="localaccess">Gets local variables that will be accessed by the routine. <c>NULL</c> if none (a common case).</param>
        public static RoutineFlags InvocationFlags(this IPhpRoutineSymbol routine, out IList <VariableName> localaccess)
        {
            localaccess = null;

            var f = RoutineFlags.None;

            var ps = /*routine is SourceRoutineSymbol sr ? sr.ImplicitParameters :*/ routine.Parameters;

            foreach (var p in ps)
            {
                if (p.IsImplicitlyDeclared)
                {
                    switch (((ParameterSymbol)p).ImportValueAttributeData.Value)
                    {
                    case ImportValueAttributeData.ValueSpec.CallerArgs:
                        f |= RoutineFlags.UsesArgs;
                        break;

                    case ImportValueAttributeData.ValueSpec.Locals:
                        f |= RoutineFlags.UsesLocals;
                        break;

                    case ImportValueAttributeData.ValueSpec.CallerStaticClass:
                        f |= RoutineFlags.UsesLateStatic;
                        break;

                    case ImportValueAttributeData.ValueSpec.LocalVariable:
                        if (p.Type.Is_PhpAlias())
                        {
                            if (localaccess == null)
                            {
                                localaccess = new List <VariableName>(1);
                            }
                            localaccess.Add(new VariableName(p.Name));
                        }
                        break;
                    }
                }
                else
                {
                    // implicit parameters are at begining only
                    break;
                }
            }

            return(f);
        }
Exemplo n.º 13
0
        public bool EnqueueRoutine(IPhpRoutineSymbol routine, T caller, ImmutableArray <BoundExpression> args)
        {
            Contract.ThrowIfNull(routine);

            if (routine.ControlFlowGraph == null)
            {
                // library (sourceless) function
                return(false);
            }

            // ensure caller is subscribed to routine's ExitBlock
            ((ExitBlock)routine.ControlFlowGraph.Exit).Subscribe(caller);

            // TODO: check if routine has to be reanalyzed => enqueue routine's StartBlock

            //
            return(false);
        }
        /// <summary>
        /// Resolves list of input arguments.
        /// Implicit parameters passed by compiler are ignored.
        /// </summary>
        /// <param name="routine">Routine.</param>
        /// <param name="ctx">Type context to transfer type masks into.</param>
        /// <returns>List of input PHP arguments.</returns>
        public static IList <PhpParam> GetExpectedArguments(this IPhpRoutineSymbol routine, TypeRefContext ctx)
        {
            Contract.ThrowIfNull(routine);
            Contract.ThrowIfNull(ctx);

            List <PhpParam> result = null;

            int index = 0;

            var ps = routine.Parameters;

            foreach (ParameterSymbol p in ps)
            {
                if (result == null && p.IsImplicitlyDeclared && !p.IsParams)
                {
                    continue;
                }

                //
                var phpparam = new PhpParam(
                    index++,
                    TypeRefFactory.CreateMask(ctx, p.Type, notNull: p.HasNotNullAttribute()),
                    p.RefKind != RefKind.None,
                    p.IsParams,
                    isPhpRw: p.GetPhpRwAttribute() != null,
                    defaultValue: p.Initializer);

                if (result == null)
                {
                    result = new List <PhpParam>(ps.Length);
                }

                result.Add(phpparam);
            }

            //
            return(result ?? (IList <PhpParam>)Array.Empty <PhpParam>());
        }
        /// <summary>
        /// Gets additional flags of the caller routine.
        /// </summary>
        public static RoutineFlags InvocationFlags(this IPhpRoutineSymbol routine)
        {
            var f = RoutineFlags.None;

            var ps = routine.Parameters;

            foreach (var p in ps)
            {
                if (p.IsImplicitlyDeclared)
                {
                    if (SpecialParameterSymbol.IsImportValueParameter(p, out var spec))
                    {
                        switch (spec)
                        {
                        case SpecialParameterSymbol.ValueSpec.CallerArgs:
                            f |= RoutineFlags.UsesArgs;
                            break;

                        case SpecialParameterSymbol.ValueSpec.Locals:
                            f |= RoutineFlags.UsesLocals;
                            break;

                        case SpecialParameterSymbol.ValueSpec.CallerStaticClass:
                            f |= RoutineFlags.UsesLateStatic;
                            break;
                        }
                    }
                }
                else
                {
                    // implicit parameters are at begining only
                    break;
                }
            }

            return(f);
        }
Exemplo n.º 16
0
 public static Span GetSpan(this IPhpRoutineSymbol routine)
 {
     return(routine.Locations.FirstOrDefault(l => l.IsInSource)?.SourceSpan.ToSpan() ?? Span.Invalid);
 }