/// <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.Parameters.OfType <SourceParameterSymbol>().ToImmutableArray(); foreach (var p in parameters) { state.SetVar(p.Name, p.GetResultType(typeCtx)); if (p.Syntax.PassedByRef) { state.SetVarRef(p.Name); } } // $this if (routine.HasThis) { InitThisVar(flowCtx, state); } // return(state); }
/// <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); }
/// <summary> /// Merge constructor. /// </summary> public FlowState(FlowState state1, FlowState state2) { Debug.Assert(state1 != null); Debug.Assert(state2 != null); Debug.Assert(state1.FlowContext == state2.FlowContext); // _varsType = EnumeratorExtension.MixArrays(state1._varsType, state2._varsType, TypeRefMask.Or); _flowCtx = state1._flowCtx; _initializedMask = state1._initializedMask & state2._initializedMask; // intersection of other variable flags if (state1._lessThanLongMax != null && state2._lessThanLongMax != null) { _lessThanLongMax = new HashSet <VariableHandle>(state1._lessThanLongMax); _lessThanLongMax.Intersect(state2._lessThanLongMax); } //// merge variables kind, //// conflicting kinds are not allowed currently! //if (state1._varKindMap != null || state1._varKindMap != null) //{ // _varKindMap = new Dictionary<VariableName, VariableKind>(); // if (state1._varKindMap != null) state1._varKindMap.Foreach(k => SetVarKind(k.Key, k.Value)); // if (state2._varKindMap != null) state2._varKindMap.Foreach(k => SetVarKind(k.Key, k.Value)); //} }
/// <summary> /// Merge constructor. /// </summary> public FlowState(FlowState state1, FlowState state2) { Debug.Assert(state1 != null); Debug.Assert(state2 != null); Debug.Assert(state1.FlowContext == state2.FlowContext); Debug.Assert(state1.Version == state2.Version); // _flowCtx = state1._flowCtx; _varsType = EnumeratorExtension.MergeArrays(state1._varsType, state2._varsType, MergeType); _initializedMask = state1._initializedMask | state2._initializedMask; // intersection of other variable flags if (state1._notes != null && state2._notes != null) { _notes = new HashSet <NoteData>(state1._notes); _notes.Intersect(state2._notes); } _version = state1.Version; //// merge variables kind, //// conflicting kinds are not allowed currently! //if (state1._varKindMap != null || state1._varKindMap != null) //{ // _varKindMap = new Dictionary<VariableName, VariableKind>(); // if (state1._varKindMap != null) state1._varKindMap.Foreach(k => SetVarKind(k.Key, k.Value)); // if (state2._varKindMap != null) state2._varKindMap.Foreach(k => SetVarKind(k.Key, k.Value)); //} }
/// <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.Parameters.OfType<SourceParameterSymbol>().ToImmutableArray(); foreach (var p in parameters) { state.SetVar(p.Name, p.GetResultType(typeCtx)); if (p.Syntax.PassedByRef) { state.SetVarRef(p.Name); } } // $this if (routine.HasThis) { InitThisVar(flowCtx, state); } // return state; }
/// <summary> /// Copy constructor. /// </summary> private FlowState(FlowContext /*!*/ flowCtx, TypeRefMask[] /*!*/ varsType) { Contract.ThrowIfNull(flowCtx); Contract.ThrowIfNull(varsType); _flowCtx = flowCtx; _varsType = (TypeRefMask[])varsType.Clone(); }
/// <summary> /// Initial locals state for the Start block. /// </summary> internal FlowState(FlowContext /*!*/ flowcontext, CommonState /*!*/ common) { Contract.ThrowIfNull(flowcontext); _common = common; _initializedMask = (ulong)0; var count = flowcontext.Locals.Length; _varsType = new TypeRefMask[count]; }
/// <summary> /// Sets the initial routine return type. /// </summary> /// <param name="ctx"></param> /// <param name="initialState"></param> /// <param name="phpdoc"></param> static void InitReturn(FlowContext /*!*/ ctx, FlowState /*!*/ initialState, PHPDocBlock phpdoc) { Debug.Assert(ctx.ReturnVarIndex >= 0); if (phpdoc != null) { var returnTag = phpdoc.Returns; if (returnTag != null && returnTag.TypeNamesArray.Length != 0) { initialState.SetVar(ctx.ReturnVarIndex, PHPDoc.GetTypeMask(ctx.TypeRefContext, returnTag.TypeNamesArray)); } } }
/// <summary> /// Initializes <c>$this</c> variable, its type and initialized state. /// </summary> private static void InitThisVar(FlowContext /*!*/ ctx, FlowState /*!*/ initialState, int varIndex) { var thisVarType = ctx.TypeRefContext.GetThisTypeMask(); if (thisVarType.IsUninitialized) { thisVarType = TypeRefMask.AnyType; } // initialState.SetVarUsed(varIndex); initialState.SetVar(varIndex, thisVarType); }
/// <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 thisIdx = ctx.GetVarIndex(VariableName.ThisVariableName); initialState.SetVarUsed(thisIdx); initialState.SetVar(thisIdx, thisVarType); }
/// <summary> /// Initial locals state for the Start block. /// </summary> internal FlowState(FlowContext /*!*/ flowCtx) { Contract.ThrowIfNull(flowCtx); _flowCtx = flowCtx; _initializedMask = (ulong)0; // initial size of the array var countHint = (flowCtx.Routine != null) ? flowCtx.Routine.LocalsTable.Count : 0; _varsType = new TypeRefMask[countHint]; }
/// <summary> /// Sets all variables as initialized at this state and with a <c>mixed</c> type. /// </summary> public void SetAllUnknown(bool maybeRef) { var tmask = maybeRef ? TypeRefMask.AnyType.WithRefFlag : TypeRefMask.AnyType; foreach (var v in FlowContext.EnumerateVariables()) { SetLocalType(v, tmask); } // all initialized _initializedMask = ~0u; }
/// <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); }
/// <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 thisIdx = ctx.GetVarIndex(VariableName.ThisVariableName); initialState.SetVarUsed(thisIdx); initialState.SetVar(thisIdx, thisVarType); }
/// <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 }
/// <summary> /// Initial locals state for the Start block. /// </summary> internal FlowState(FlowContext /*!*/ flowCtx) { Contract.ThrowIfNull(flowCtx); FlowContext = flowCtx; _initializedMask = 0ul; // initial size of the array var countHint = (flowCtx.Routine != null) ? flowCtx.VarsType.Length : 0; _varsType = countHint != 0 ? new TypeRefMask[countHint] : Array.Empty <TypeRefMask>(); Version = flowCtx.Version; }
/// <summary> /// Initial locals state for the Start block. /// </summary> internal FlowState(FlowContext /*!*/ flowCtx) { Contract.ThrowIfNull(flowCtx); FlowContext = flowCtx; _initializedMask = (ulong)0; // initial size of the array var countHint = (flowCtx.Routine != null) ? flowCtx.VarsType.Length : 0; _varsType = new TypeRefMask[countHint]; Version = flowCtx.Version; }
public CommonState(FlowContext /*!*/ flowcontext, Symbols.SourceRoutineSymbol /*!*/ routine) { Debug.Assert(flowcontext != null); Debug.Assert(routine != null); _flowcontext = flowcontext; _routine = routine; var locals = flowcontext.Locals; var dict = new Dictionary <string, int>(locals.Length, StringComparer.OrdinalIgnoreCase); for (int i = 0; i < locals.Length; i++) { dict[locals[i].Name] = i; } _varsIndex = dict; }
/// <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); }
/// <summary> /// Creates new type context, flow context and flow state for the routine. /// </summary> public static FlowState CreateInitialState(SourceRoutineSymbol routine) { Contract.ThrowIfNull(routine); var containingType = routine.ContainingType as SourceNamedTypeSymbol; // collect locals var locals = LocalsBinder.BindLocals(routine); var returnIdx = locals.IndexOf(x => x.VariableKind == VariableKind.ReturnVariable); // create typeCtx var typeCtx = routine.TypeRefContext; // create FlowContext var flowCtx = new FlowContext(typeCtx, locals, returnIdx); // create FlowState var state = new FlowState(flowCtx, routine); // handle parameters passed by reference var parameters = routine.Parameters.OfType <SourceParameterSymbol>().ToImmutableArray(); foreach (var p in parameters) { if (p.Syntax.PassedByRef) { state.SetVarRef(p.Name); } } // mark $this as initialized // mark global variables as ByRef, used // mark function parameters as used, initialized, typed // construct initial state for variables int paramIdx = 0; for (int i = 0; i < locals.Length; i++) { switch (locals[i].VariableKind) { case VariableKind.GlobalVariable: state.SetVarRef(i); // => used, byref, initialized break; case VariableKind.Parameter: //state.SetVarUsed(i); var paramtag = PHPDoc.GetParamTag(routine.PHPDocBlock, paramIdx, locals[i].Name); state.SetVar(i, GetParamType(typeCtx, paramtag, parameters[paramIdx].Syntax, default(CallInfo), paramIdx)); paramIdx++; break; //case VariableKind.UseParameter: // state.SetVar(i, TypeRefMask.AnyType); // break; case VariableKind.ThisParameter: InitThisVar(flowCtx, state, i); break; case VariableKind.StaticVariable: state.SetVarInitialized(i); break; case VariableKind.ReturnVariable: InitReturn(flowCtx, state, routine.PHPDocBlock); break; } } // return(state); }
/// <summary> /// Initial locals state for the Start block. /// </summary> public FlowState(FlowContext /*!*/ context, Symbols.SourceRoutineSymbol /*!*/ routine) : this(context, new CommonState(context, routine)) { }
/// <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); }
/// <summary> /// Gets variable handle use for other variable operations. /// </summary> public VariableHandle /*!*/ GetLocalHandle(VariableName varname) { return(FlowContext.GetVarIndex(varname)); }
/// <summary> /// Handles use of a local variable. /// </summary> public void VisitLocal(VariableHandle handle) { handle.ThrowIfInvalid(); FlowContext.SetUsed(handle); }