/// <summary> /// Sets type of local variable in current state. /// </summary> protected virtual TypeRefMask SetVar(string name, TypeRefMask typemask) { AssertState(); _state.SetVar(name, typemask); return(typemask); }
/// <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> /// 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> /// 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); }