public BoundGlobalVariableStatement Update(BoundVariableRef variable) { if (variable == Variable) { return(this); } else { return(new BoundGlobalVariableStatement(variable)); } }
public BoundGlobalVariableStatement(BoundVariableRef variable) { Variable = variable; }
public virtual void VisitVariableRef(BoundVariableRef x) { }
public virtual TResult VisitVariableRef(BoundVariableRef x) => DefaultVisitOperation(x);
public override void VisitVariableRef(BoundVariableRef x) { if (x.Name.IsDirect) { // direct variable access: var name = x.Name.NameValue.Value; // bind variable place x.Variable = Routine.LocalsTable.BindVariable(x.Name.NameValue, State.GetVarKind(x.Name.NameValue)); // update state if (x.Access.IsRead) { State.SetVarUsed(name); var vartype = State.GetVarType(name); if (vartype.IsVoid || x.Variable.VariableKind == VariableKind.GlobalVariable) { // in global code or in case of undefined variable, // assume the type is mixed (unspecified). // In global code, the type of variable cannot be determined by type analysis, it can change between every two operations (this may be improved by better flow analysis). vartype = TypeRefMask.AnyType; } if (x.Access.IsEnsure) { if (x.Access.IsReadRef) { State.SetVarRef(name); vartype.IsRef = true; } if (x.Access.EnsureObject && !IsClassOnly(vartype)) { vartype |= TypeCtx.GetSystemObjectTypeMask(); } if (x.Access.EnsureArray && !IsArrayOnly(vartype)) { vartype |= TypeCtx.GetArrayTypeMask(); } State.SetVarInitialized(name); State.SetVar(name, vartype); } x.TypeRefMask = vartype; } if (x.Access.IsWrite) { // State.SetVarInitialized(name); State.SetVar(name, x.Access.WriteMask); State.LTInt64Max(name, false); x.TypeRefMask = x.Access.WriteMask; if (x.Access.IsWriteRef) { State.SetVarRef(name); x.TypeRefMask = x.TypeRefMask.WithRefFlag; } // if (x.Variable.VariableKind == VariableKind.StaticVariable) { // analysis has to be started over // TODO: start from the block which declares the static local variable var startBlock = Routine.ControlFlowGraph.Start; var startState = startBlock.FlowState; var oldVar = startState.GetVarType(name); if (oldVar != x.TypeRefMask) { startState.SetVar(name, x.TypeRefMask); this.Worklist.Enqueue(startBlock); } } } if (x.Access.IsUnset) { State.SetVar(name, 0); State.LTInt64Max(name, false); x.TypeRefMask = 0; } } else { // indirect variable access: Routine.Flags |= RoutineFlags.HasIndirectVar; Accept(x.Name.NameExpression); // bind variable place if (x.Variable == null) { x.Variable = new BoundIndirectLocal(x.Name.NameExpression); } // update state if (x.Access.IsRead) { State.FlowContext.SetAllUsed(); } if (x.Access.IsWrite) { State.SetAllInitialized(); } if (x.Access.IsUnset) { } return; } }