Exemple #1
0
        /// <summary>
        /// Creates new type context, flow context and flow state for the routine.
        /// </summary>
        public static FlowState CreateInitialState(SourceRoutineSymbol /*!*/ routine, FlowContext flowCtx = null)
        {
            Contract.ThrowIfNull(routine);

            // get or create typeCtx
            var typeCtx = routine.TypeRefContext;

            if (flowCtx == null)
            {
                // create FlowContext
                flowCtx = new FlowContext(typeCtx, routine);
            }

            // create FlowState
            var state = new FlowState(flowCtx);

            // handle input parameters type
            foreach (var p in routine.SourceParameters)
            {
                var local = state.GetLocalHandle(new VariableName(p.Name));
                var ptype = p.GetResultType(typeCtx);
                state.SetLocalType(local, ptype);
            }

            // $this
            if (routine.GetPhpThisVariablePlace() != null)
            {
                InitThisVar(flowCtx, state);
            }

            //
            return(state);
        }
Exemple #2
0
        /// <summary>
        /// Creates new type context, flow context and flow state for the routine.
        /// </summary>
        public static FlowState CreateInitialState(SourceRoutineSymbol /*!*/ routine, FlowContext flowCtx = null)
        {
            Contract.ThrowIfNull(routine);

            // get or create typeCtx
            var typeCtx = routine.TypeRefContext;

            if (flowCtx == null)
            {
                // create FlowContext
                flowCtx = new FlowContext(typeCtx, routine);
            }

            // create FlowState
            var state = new FlowState(flowCtx);

            // handle input parameters type
            foreach (var p in routine.SourceParameters)
            {
                var local = state.GetLocalHandle(new VariableName(p.Name));
                var ptype = p.GetResultType(typeCtx);
                if (p.IsNotNull)
                {
                    // remove 'null' type from the mask,
                    // it cannot be null
                    ptype = typeCtx.WithoutNull(ptype);
                }
                else if (p.Type.IsReferenceType)    // a reference type that can be null
                {
                    ptype |= typeCtx.GetNullTypeMask();
                }

                state.SetLocalType(local, ptype);

                if (p.Syntax.PassedByRef && !p.Syntax.IsVariadic)
                {
                    state.MarkLocalByRef(local);
                }
            }

            // $this
            if (routine.GetPhpThisVariablePlace() != null)
            {
                InitThisVar(flowCtx, state);
            }

            //
            return(state);
        }
Exemple #3
0
        /// <summary>
        /// Initializes <c>$this</c> variable, its type and initialized state.
        /// </summary>
        private static void InitThisVar(FlowContext /*!*/ ctx, FlowState /*!*/ initialState)
        {
            var thisVarType = ctx.TypeRefContext.GetThisTypeMask();

            if (thisVarType.IsUninitialized)
            {
                thisVarType = TypeRefMask.AnyType;
            }

            //
            var thisHandle = ctx.GetVarIndex(VariableName.ThisVariableName);

            initialState.SetLocalType(thisHandle, thisVarType); // set $this type
            initialState.VisitLocal(thisHandle);                // mark as visited (used) to not report as unused
        }
Exemple #4
0
        /// <summary>
        /// Creates new type context, flow context and flow state for the routine.
        /// </summary>
        public static FlowState CreateInitialState(SourceRoutineSymbol /*!*/ routine, FlowContext flowCtx = null)
        {
            Contract.ThrowIfNull(routine);

            // get or create typeCtx
            var typeCtx = routine.TypeRefContext;

            // create or reuse FlowContext
            flowCtx ??= new FlowContext(typeCtx, routine);

            // pre-allocate locals map // https://github.com/peachpiecompiler/peachpie/issues/1002
            foreach (var variable in routine.LocalsTable.Variables)
            {
                if (variable is Semantics.LocalVariableReference local && local.VariableKind == VariableKind.LocalVariable)
                {
                    flowCtx.GetVarIndex(variable.BoundName.NameValue);
                }
            }

            // create FlowState
            var state = new FlowState(flowCtx);

            // populate input parameters type
            foreach (var p in routine.SourceParameters)
            {
                var local = state.GetLocalHandle(new VariableName(p.Name));
                var ptype = p.GetResultType(typeCtx);
                state.SetLocalType(local, ptype);
            }

            // $this
            if (routine.GetPhpThisVariablePlace() != null)
            {
                InitThisVar(flowCtx, state);
            }

            //
            return(state);
        }
Exemple #5
0
        /// <summary>
        /// Creates new type context, flow context and flow state for the routine.
        /// </summary>
        public static FlowState CreateInitialState(SourceRoutineSymbol /*!*/ routine)
        {
            Contract.ThrowIfNull(routine);

            // create typeCtx
            var typeCtx = routine.TypeRefContext;

            // create FlowContext
            var flowCtx = new FlowContext(typeCtx, routine);

            // create FlowState
            var state = new FlowState(flowCtx);

            // handle input parameters type
            var parameters = routine.SourceParameters;

            foreach (var p in parameters)
            {
                var local = state.GetLocalHandle(new VariableName(p.Name));
                state.SetLocalType(local, p.GetResultType(typeCtx));

                if (p.Syntax.PassedByRef && !p.Syntax.IsVariadic)
                {
                    state.MarkLocalByRef(local);
                }
            }

            // $this
            if (routine.GetPhpThisVariablePlace() != null)
            {
                InitThisVar(flowCtx, state);
            }

            //
            return(state);
        }
Exemple #6
0
        private static bool HandleTypeChecking(
            TypeRefMask currentType,
            TypeRefMask targetType,
            ConditionBranch branch,
            FlowState flowState,
            VariableHandle handle,
            bool skipTrueIfAnyType)
        {
            // Information whether this path can ever be taken
            bool isFeasible = true;

            if (branch == ConditionBranch.ToTrue)
            {
                // In the true branch the IsAnyType case can be optionally skipped
                if (skipTrueIfAnyType && currentType.IsAnyType)
                {
                    return(isFeasible);
                }

                // Intersect the possible types with those checked by the function, always keeping the IsRef flag.
                // IncludesSubclasses is kept only if it is specified in targetType.
                TypeRefMask resultType = (currentType & (targetType | TypeRefMask.IsRefMask));

                if (resultType.IsVoid)
                {
                    // Clearing the type out in this branch means the variable will never be of that type.
                    // In order to prevent errors in analysis and code generation, set the type to the one specified.
                    resultType = targetType | (currentType & TypeRefMask.IsRefMask);

                    isFeasible = false;
                }

                flowState.SetLocalType(handle, resultType);
            }
            else
            {
                Debug.Assert(branch == ConditionBranch.ToFalse);

                // In the false branch we cannot handle the IsAnyType case
                if (currentType.IsAnyType)
                {
                    return(isFeasible);
                }

                // Remove the types and flags excluded by the fact that the function returned false
                TypeRefMask resultType = currentType & (~targetType);

                if (resultType.IsVoid)
                {
                    // Clearing the type out in this branch means the variable will always be of that type
                    // In order to prevent errors in analysis and code generation, do not alter the type in this case.

                    isFeasible = false;
                }
                else
                {
                    flowState.SetLocalType(handle, resultType);
                }
            }

            return(isFeasible);
        }