示例#1
0
 public BoundGlobalVariableStatement Update(BoundVariableRef variable)
 {
     if (variable == Variable)
     {
         return(this);
     }
     else
     {
         return(new BoundGlobalVariableStatement(variable));
     }
 }
示例#2
0
 public BoundGlobalVariableStatement(BoundVariableRef variable)
 {
     Variable = variable;
 }
示例#3
0
 public virtual void VisitVariableRef(BoundVariableRef x)
 {
 }
 public virtual TResult VisitVariableRef(BoundVariableRef x) => DefaultVisitOperation(x);
示例#5
0
        public virtual void VisitVariableRef(BoundVariableRef x)
        {

        }
示例#6
0
        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;
            }
        }